diff --git a/Content/Common/Data/Materials/Confetti.material b/Content/Common/Data/Materials/Confetti.material
new file mode 100644
index 0000000..a5d23f3
--- /dev/null
+++ b/Content/Common/Data/Materials/Confetti.material
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content/Common/Data/Models/Particles.mdl b/Content/Common/Data/Models/Particles.mdl
new file mode 100644
index 0000000..b0be6ee
Binary files /dev/null and b/Content/Common/Data/Models/Particles.mdl differ
diff --git a/Content/Common/Data/Objects/Confetti.prefab b/Content/Common/Data/Objects/Confetti.prefab
new file mode 100644
index 0000000..747dadf
--- /dev/null
+++ b/Content/Common/Data/Objects/Confetti.prefab
@@ -0,0 +1,100 @@
+{
+ "components": [
+ {
+ "_typeName": "Octree"
+ }
+ ],
+ "nodes": [
+ {
+ "components": [
+ {
+ "_typeName": "StaticModel",
+ "attributes": [
+ {
+ "name": "Model",
+ "type": "ResourceRef",
+ "value": "Model;Models/Particles.mdl"
+ },
+ {
+ "name": "Material",
+ "type": "ResourceRefList",
+ "value": "Material;Materials/Confetti.material"
+ },
+ {
+ "name": "Cast Shadows",
+ "type": "Bool",
+ "value": true
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "attributes": [
+ {
+ "name": "Name",
+ "type": "String",
+ "value": "Default Skybox"
+ }
+ ],
+ "components": [
+ {
+ "_typeName": "Skybox",
+ "attributes": [
+ {
+ "name": "Model",
+ "type": "ResourceRef",
+ "value": "Model;Models/Box.mdl"
+ },
+ {
+ "name": "Material",
+ "type": "ResourceRefList",
+ "value": "Material;Materials/DefaultSkybox.xml"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "attributes": [
+ {
+ "name": "Name",
+ "type": "String",
+ "value": "Default Zone"
+ }
+ ],
+ "components": [
+ {
+ "_typeName": "Zone",
+ "attributes": [
+ {
+ "name": "Bounding Box Min",
+ "type": "Vector3",
+ "value": "-1000 -1000 -1000"
+ },
+ {
+ "name": "Bounding Box Max",
+ "type": "Vector3",
+ "value": "1000 1000 1000"
+ },
+ {
+ "name": "Ambient Color",
+ "type": "Color",
+ "value": "0 0 0 1"
+ },
+ {
+ "name": "Background Brightness",
+ "type": "Float",
+ "value": 1.0
+ },
+ {
+ "name": "Zone Texture",
+ "type": "ResourceRef",
+ "value": "TextureCube;Textures/DefaultSkybox.xml"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Content/Common/Data/Scenes/Scene.scene b/Content/Common/Data/Scenes/Scene.scene
index 970c866..5edf346 100644
--- a/Content/Common/Data/Scenes/Scene.scene
+++ b/Content/Common/Data/Scenes/Scene.scene
@@ -1,8 +1,9 @@
-
-
+
+
+
@@ -56,7 +57,7 @@
-
+
@@ -105,6 +106,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content/Common/Data/Shaders/GLSL/v2/M_Confetti.glsl b/Content/Common/Data/Shaders/GLSL/v2/M_Confetti.glsl
new file mode 100644
index 0000000..d247110
--- /dev/null
+++ b/Content/Common/Data/Shaders/GLSL/v2/M_Confetti.glsl
@@ -0,0 +1,110 @@
+#define URHO3D_PIXEL_NEED_TEXCOORD
+
+#ifndef URHO3D_VERTEX_HAS_TEXCOORD0
+#define URHO3D_VERTEX_HAS_TEXCOORD0
+#endif
+
+#ifndef URHO3D_VERTEX_HAS_COLOR
+#define URHO3D_VERTEX_HAS_COLOR
+#endif
+
+
+#define URHO3D_MATERIAL_ALBEDO URHO3D_TEXTURE_ALBEDO
+#define URHO3D_MATERIAL_NORMAL URHO3D_TEXTURE_NORMAL
+#define URHO3D_MATERIAL_PROPERTIES URHO3D_TEXTURE_PROPERTIES
+#define URHO3D_MATERIAL_EMISSION URHO3D_TEXTURE_EMISSION
+#define URHO3D_CUSTOM_MATERIAL_UNIFORMS
+
+#include "_Config.glsl"
+#include "_Uniforms.glsl"
+#include "_DefaultSamplers.glsl"
+
+UNIFORM_BUFFER_BEGIN(4, Material)
+ DEFAULT_MATERIAL_UNIFORMS
+ UNIFORM(half cAnimationPhase)
+UNIFORM_BUFFER_END(4, Material)
+
+#include "_Material.glsl"
+
+#ifdef URHO3D_VERTEX_SHADER
+
+mat3 FromAngleAxis(float angle, vec3 normAxis)
+{
+ float sinAngle = sin(angle);
+ float cosAngle = cos(angle);
+ float _cosAngle = 1.0 - cosAngle;
+
+ return mat3(
+ cosAngle + normAxis.x * normAxis.x * _cosAngle,
+ normAxis.y * normAxis.x * _cosAngle + normAxis.z * sinAngle,
+ normAxis.z * normAxis.x * _cosAngle - normAxis.y * sinAngle,
+
+ normAxis.x * normAxis.y * _cosAngle - normAxis.z * sinAngle,
+ cosAngle + normAxis.y * normAxis.y * _cosAngle,
+ normAxis.z * normAxis.y * _cosAngle + normAxis.x * sinAngle,
+
+ normAxis.x * normAxis.z * _cosAngle + normAxis.y * sinAngle,
+ normAxis.y * normAxis.z * _cosAngle - normAxis.x * sinAngle,
+ cosAngle + normAxis.z * normAxis.z * _cosAngle);
+}
+
+void main()
+{
+ mat4 modelMatrix = GetModelMatrix();
+
+ float t = cAnimationPhase;
+ float _t = 1.0 - t;
+ vec3 bernsteinCoefficients = vec3(_t*_t, 2.0*t*_t, t*t);
+
+ vec3 offset = FromAngleAxis(iColor.w + t * 10.0, iNormal) * vec3(iTexCoord.x-0.5, 0.0, -iTexCoord.y+0.5);
+
+ float up = dot(bernsteinCoefficients, vec3(0.0, 0.0, -0.5));
+ float size = dot(bernsteinCoefficients, vec3(0.0, 0.1, 0.0));
+ float dist = dot(bernsteinCoefficients, vec3(0.0, 1.0, 1.0));
+
+ VertexTransform vertexTransform;
+ vertexTransform.position = vec4(iPos.xyz*dist + offset.xyz*size + vec3(0.0, up, 0.0), 1.0) * modelMatrix;
+
+ #ifdef URHO3D_VERTEX_NEED_NORMAL
+ mediump mat3 normalMatrix = GetNormalMatrix(modelMatrix);
+ vertexTransform.normal = normalize(iNormal * normalMatrix);
+
+ ApplyShadowNormalOffset(result.position, result.normal);
+
+ #ifdef URHO3D_VERTEX_NEED_TANGENT
+ vertexTransform.tangent = normalize(iTangent.xyz * normalMatrix);
+ vertexTransform.bitangent = cross(result.tangent, result.normal) * iTangent.w;
+ #endif
+ #endif
+
+ Vertex_SetAll(vertexTransform, cNormalScale, cUOffset, cVOffset, cLMOffset);
+}
+#endif
+
+#ifdef URHO3D_PIXEL_SHADER
+void main()
+{
+#ifdef URHO3D_DEPTH_ONLY_PASS
+ Pixel_DepthOnly(sAlbedo, vTexCoord);
+#else
+ SurfaceData surfaceData;
+
+ Surface_SetCommon(surfaceData);
+ Surface_SetAmbient(surfaceData, sEmission, vTexCoord2);
+ Surface_SetNormal(surfaceData, vNormal, sNormal, vTexCoord, vTangent, vBitangentXY);
+ Surface_SetPhysicalProperties(surfaceData, cRoughness, cMetallic, cDielectricReflectance, sProperties, vTexCoord);
+ Surface_SetLegacyProperties(surfaceData, cMatSpecColor.a, sEmission, vTexCoord);
+ Surface_SetCubeReflection(surfaceData, sReflection0, sReflection1, vReflectionVec, vWorldPos);
+ Surface_SetPlanarReflection(surfaceData, sReflection0, cReflectionPlaneX, cReflectionPlaneY);
+ Surface_SetBackground(surfaceData, sEmission, sDepthBuffer);
+ Surface_SetBaseAlbedo(surfaceData, cMatDiffColor, cAlphaCutoff, vColor, sAlbedo, vTexCoord, URHO3D_MATERIAL_ALBEDO);
+ Surface_SetBaseSpecular(surfaceData, cMatSpecColor, cMatEnvMapColor, sProperties, vTexCoord);
+ Surface_SetAlbedoSpecular(surfaceData);
+ Surface_SetEmission(surfaceData, cMatEmissiveColor, sEmission, vTexCoord, URHO3D_MATERIAL_EMISSION);
+ Surface_ApplySoftFadeOut(surfaceData, vWorldDepth, cFadeOffsetScale);
+
+ half3 surfaceColor = GetSurfaceColor(surfaceData);
+ gl_FragColor = GetFragmentColorAlpha(surfaceColor, surfaceData.albedo.a, surfaceData.fogFactor);
+#endif
+}
+#endif
diff --git a/Content/Common/Data/Techniques/Confetti.xml b/Content/Common/Data/Techniques/Confetti.xml
new file mode 100644
index 0000000..74f30fe
--- /dev/null
+++ b/Content/Common/Data/Techniques/Confetti.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Content/Common/Data/UI/GameScreen.rml b/Content/Common/Data/UI/GameScreen.rml
index 1de28fe..2c8dd42 100644
--- a/Content/Common/Data/UI/GameScreen.rml
+++ b/Content/Common/Data/UI/GameScreen.rml
@@ -25,12 +25,20 @@
}
/* Style of the root panel element */
dev.menu-panel {
- width: 50%;
+ width: 50%;
max-height: 90%;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
+
+ .levelblock {
+ display: inline-block;
+ border-width: 1px;
+ border-color: #fff;
+ margin: 2px;
+ padding: 2px;
}
@@ -42,10 +50,17 @@
-
+
{{Level}}
+
+
{{CurrentLevel > BaseLevel ? 'V' : BaseLevel}}
+
{{CurrentLevel > BaseLevel+1 ? 'V' : BaseLevel+1}}
+
{{CurrentLevel > BaseLevel+2 ? 'V' : BaseLevel+2}}
+
{{CurrentLevel > BaseLevel+3 ? 'V' : BaseLevel+3}}
+
{{CurrentLevel > BaseLevel+4 ? 'V' : BaseLevel+4}}
+
diff --git a/RbfxTemplate/GameState.cs b/RbfxTemplate/GameState.cs
index a4f3ea1..f0f0ae9 100644
--- a/RbfxTemplate/GameState.cs
+++ b/RbfxTemplate/GameState.cs
@@ -52,8 +52,9 @@ public sealed class GameState : RmlUIStateBase
private Vector2 _areaSize = new Vector2(1, 1);
private int _levelIndex;
- private int _hintsLeft = 1;
+ private int _hintsLeft = 2;
private bool _victory;
+ private readonly FiniteTimeAction _confettiAnimation;
public GameState(UrhoPluginApplication app) : base(app, "UI/GameScreen.rml")
{
@@ -86,6 +87,8 @@ public GameState(UrhoPluginApplication app) : base(app, "UI/GameScreen.rml")
_dragState = new DragState(this);
_victoryState = new VictoryState(this);
+ _confettiAnimation = new ActionBuilder(Context).Enable().ShaderParameterFromTo(1.0f, "AnimationPhase", 0.0f, 1.0f).Disable().Build();
+
NextLevel(null);
Deactivate();
@@ -108,6 +111,8 @@ public StateBase State
public override void OnDataModelInitialized(GameRmlUIComponent component)
{
component.BindDataModelProperty("Level", _ => _.Set("Level " + _levelIndex), _ => { });
+ component.BindDataModelProperty("BaseLevel", _ => _.Set(1+((_levelIndex-1)/5)*5), _ => { });
+ component.BindDataModelProperty("CurrentLevel", _ => _.Set(_levelIndex), _ => { });
component.BindDataModelProperty("Victory", _ => _.Set(_victory), _ => { });
component.BindDataModelEvent("Next", NextLevel);
component.BindDataModelEvent("Settings", Settings);
@@ -253,7 +258,8 @@ public void StartPicking()
if (tile.LinkedTile != tile.ValidLink)
{
isCorrect = false;
- hint = tile;
+ if (hint == null)
+ hint = tile;
}
}
@@ -304,6 +310,12 @@ protected override void Dispose(bool disposing)
private void Victory()
{
+ var nodeList = new NodeList();
+ _scene.Ptr.GetNodesWithTag(nodeList, "Confetti");
+ foreach (var node in nodeList)
+ {
+ ActionManager.AddAction(_confettiAnimation, node);
+ }
State = _victoryState;
_victory = true;
RmlUiComponent.UpdateProperties();