Working on UI improvement
This commit is contained in:
parent
0da1ae124c
commit
80af0e61ae
@ -1,5 +1,6 @@
|
|||||||
//precisionmediump float;
|
//precisionmediump float;
|
||||||
uniform sampler2D Texture;
|
uniform sampler2D Texture;
|
||||||
|
uniform float uAlpha;
|
||||||
varying vec2 texCoord;
|
varying vec2 texCoord;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
@ -7,6 +8,6 @@ void main()
|
|||||||
vec4 color = texture2D(Texture,texCoord).rgba;
|
vec4 color = texture2D(Texture,texCoord).rgba;
|
||||||
//gl_FragColor = vec4(color.rgb*0.1 + vec3(0.9, 0.9, 0.9), 1.0);
|
//gl_FragColor = vec4(color.rgb*0.1 + vec3(0.9, 0.9, 0.9), 1.0);
|
||||||
|
|
||||||
gl_FragColor = color;
|
gl_FragColor = vec4(color.rgb, color.a * uAlpha);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
precision mediump float;
|
precision mediump float;
|
||||||
uniform sampler2D Texture;
|
uniform sampler2D Texture;
|
||||||
|
uniform float uAlpha;
|
||||||
varying vec2 texCoord;
|
varying vec2 texCoord;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
@ -7,6 +8,6 @@ void main()
|
|||||||
vec4 color = texture2D(Texture,texCoord).rgba;
|
vec4 color = texture2D(Texture,texCoord).rgba;
|
||||||
//gl_FragColor = vec4(color.rgb*0.1 + vec3(0.9, 0.9, 0.9), 1.0);
|
//gl_FragColor = vec4(color.rgb*0.1 + vec3(0.9, 0.9, 0.9), 1.0);
|
||||||
|
|
||||||
gl_FragColor = color;
|
gl_FragColor = vec4(color.rgb, color.a * uAlpha);
|
||||||
|
|
||||||
}
|
}
|
||||||
43
resources/w/ui/hud_regular.json
Normal file
43
resources/w/ui/hud_regular.json
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "FrameLayout",
|
||||||
|
"name": "hud_root",
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": "match_parent",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "LinearLayout",
|
||||||
|
"orientation": "vertical",
|
||||||
|
"vertical_align": "center",
|
||||||
|
"horizontal_align": "center",
|
||||||
|
"spacing": 0,
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": 600,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "Button",
|
||||||
|
"name": "phoneButton",
|
||||||
|
"width": 229,
|
||||||
|
"height": 229,
|
||||||
|
"textures": {
|
||||||
|
"normal": "resources/w/ui/img/Phone001_State=Default.png",
|
||||||
|
"hover": "resources/w/ui/img/Phone001_State=Selected.png",
|
||||||
|
"pressed": "resources/w/ui/img/Phone001_State=Tap.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Button",
|
||||||
|
"name": "journalButton",
|
||||||
|
"width": 229,
|
||||||
|
"height": 229,
|
||||||
|
"textures": {
|
||||||
|
"normal": "resources/w/ui/img/Phone001_State=Default.png",
|
||||||
|
"hover": "resources/w/ui/img/Phone001_State=Selected.png",
|
||||||
|
"pressed": "resources/w/ui/img/Phone001_State=Tap.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,6 +13,7 @@
|
|||||||
"spacing": 0,
|
"spacing": 0,
|
||||||
"width": "match_parent",
|
"width": "match_parent",
|
||||||
"height": 600,
|
"height": 600,
|
||||||
|
"x" : 300,
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"type": "StaticImage",
|
"type": "StaticImage",
|
||||||
@ -20,7 +21,13 @@
|
|||||||
"width": 440,
|
"width": 440,
|
||||||
"height": 134,
|
"height": 134,
|
||||||
"horizontal_gravity": "center",
|
"horizontal_gravity": "center",
|
||||||
"texture": "resources/w/ui/img/Hint2.png"
|
"texture": "resources/w/ui/img/Hint1.png",
|
||||||
|
"pulse": {
|
||||||
|
"minScale": 0.92,
|
||||||
|
"maxScale": 1.08,
|
||||||
|
"periodMs": 1500
|
||||||
|
},
|
||||||
|
"fadeIn": { "durationMs": 600 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "StaticImage",
|
"type": "StaticImage",
|
||||||
|
|||||||
@ -5,42 +5,31 @@
|
|||||||
"width": "match_parent",
|
"width": "match_parent",
|
||||||
"height": "match_parent",
|
"height": "match_parent",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"type": "TextButton",
|
"type": "LinearLayout",
|
||||||
"name": "inventory_button",
|
"orientation": "vertical",
|
||||||
"x": 50.0,
|
"vertical_align": "center",
|
||||||
"y": 50.0,
|
"horizontal_align": "center",
|
||||||
"width": 150.0,
|
"spacing": 0,
|
||||||
"height": 60.0,
|
"width": "match_parent",
|
||||||
"text": "Inventory",
|
"height": 600,
|
||||||
"fontSize": 24,
|
"y" : 300,
|
||||||
"fontPath": "resources/fonts/DroidSans.ttf",
|
"children": [
|
||||||
"textCentered": true,
|
{
|
||||||
"color": [1.0, 1.0, 1.0, 1.0],
|
"type": "StaticImage",
|
||||||
"textures": {
|
"name": "hint2",
|
||||||
"normal": "resources/w/red.png",
|
"width": 440,
|
||||||
"hover": "resources/w/red.png",
|
"height": 134,
|
||||||
"pressed": "resources/w/red.png"
|
"horizontal_gravity": "center",
|
||||||
}
|
"texture": "resources/w/ui/img/Hint2.png",
|
||||||
},
|
"pulse": {
|
||||||
{
|
"minScale": 0.92,
|
||||||
"type": "TextButton",
|
"maxScale": 1.08,
|
||||||
"name": "quest_journal_button",
|
"periodMs": 1500
|
||||||
"x": 220.0,
|
},
|
||||||
"y": 50.0,
|
"fadeIn": { "durationMs": 600 }
|
||||||
"width": 170.0,
|
}
|
||||||
"height": 60.0,
|
]
|
||||||
"text": "Quests",
|
}]
|
||||||
"fontSize": 24,
|
|
||||||
"fontPath": "resources/fonts/DroidSans.ttf",
|
|
||||||
"textCentered": true,
|
|
||||||
"color": [1.0, 1.0, 1.0, 1.0],
|
|
||||||
"textures": {
|
|
||||||
"normal": "resources/w/red.png",
|
|
||||||
"hover": "resources/w/red.png",
|
|
||||||
"pressed": "resources/w/red.png"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
resources/w/ui/hud_step2.json
Normal file
35
resources/w/ui/hud_step2.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "FrameLayout",
|
||||||
|
"name": "hud_root",
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": "match_parent",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "LinearLayout",
|
||||||
|
"orientation": "vertical",
|
||||||
|
"vertical_align": "center",
|
||||||
|
"horizontal_align": "center",
|
||||||
|
"spacing": 0,
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": 600,
|
||||||
|
"y" : 300,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "StaticImage",
|
||||||
|
"name": "hint3",
|
||||||
|
"width": 440,
|
||||||
|
"height": 134,
|
||||||
|
"horizontal_gravity": "center",
|
||||||
|
"texture": "resources/w/ui/img/Hint3.png",
|
||||||
|
"pulse": {
|
||||||
|
"minScale": 0.92,
|
||||||
|
"maxScale": 1.08,
|
||||||
|
"periodMs": 1500
|
||||||
|
},
|
||||||
|
"fadeIn": { "durationMs": 600 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
35
resources/w/ui/hud_step3.json
Normal file
35
resources/w/ui/hud_step3.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "FrameLayout",
|
||||||
|
"name": "hud_root",
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": "match_parent",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "LinearLayout",
|
||||||
|
"orientation": "vertical",
|
||||||
|
"vertical_align": "center",
|
||||||
|
"horizontal_align": "center",
|
||||||
|
"spacing": 0,
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": 600,
|
||||||
|
"y" : 300,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "StaticImage",
|
||||||
|
"name": "hint4",
|
||||||
|
"width": 440,
|
||||||
|
"height": 134,
|
||||||
|
"horizontal_gravity": "center",
|
||||||
|
"texture": "resources/w/ui/img/Hint4.png",
|
||||||
|
"pulse": {
|
||||||
|
"minScale": 0.92,
|
||||||
|
"maxScale": 1.08,
|
||||||
|
"periodMs": 1500
|
||||||
|
},
|
||||||
|
"fadeIn": { "durationMs": 600 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
35
resources/w/ui/hud_step4.json
Normal file
35
resources/w/ui/hud_step4.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "FrameLayout",
|
||||||
|
"name": "hud_root",
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": "match_parent",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "LinearLayout",
|
||||||
|
"orientation": "vertical",
|
||||||
|
"vertical_align": "center",
|
||||||
|
"horizontal_align": "center",
|
||||||
|
"spacing": 0,
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": 600,
|
||||||
|
"y" : 300,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "StaticImage",
|
||||||
|
"name": "hint5",
|
||||||
|
"width": 440,
|
||||||
|
"height": 134,
|
||||||
|
"horizontal_gravity": "center",
|
||||||
|
"texture": "resources/w/ui/img/Hint5.png",
|
||||||
|
"pulse": {
|
||||||
|
"minScale": 0.92,
|
||||||
|
"maxScale": 1.08,
|
||||||
|
"periodMs": 1500
|
||||||
|
},
|
||||||
|
"fadeIn": { "durationMs": 600 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
57
resources/w/ui/hud_step5a.json
Normal file
57
resources/w/ui/hud_step5a.json
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "FrameLayout",
|
||||||
|
"name": "hud_root",
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": "match_parent",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "LinearLayout",
|
||||||
|
"orientation": "vertical",
|
||||||
|
"vertical_align": "center",
|
||||||
|
"horizontal_align": "center",
|
||||||
|
"spacing": 0,
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": 600,
|
||||||
|
"y" : -250,
|
||||||
|
"x" : 300,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "StaticImage",
|
||||||
|
"name": "hint6a",
|
||||||
|
"width": 440,
|
||||||
|
"height": 134,
|
||||||
|
"horizontal_gravity": "center",
|
||||||
|
"texture": "resources/w/ui/img/Hint6a.png",
|
||||||
|
"pulse": {
|
||||||
|
"minScale": 0.92,
|
||||||
|
"maxScale": 1.08,
|
||||||
|
"periodMs": 1500
|
||||||
|
},
|
||||||
|
"fadeIn": {
|
||||||
|
"durationMs": 600
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Button",
|
||||||
|
"name": "phoneButton",
|
||||||
|
"horizontal_gravity": "right",
|
||||||
|
"vertical_gravity": "top",
|
||||||
|
"x": -46,
|
||||||
|
"y" :-46,
|
||||||
|
"width": 229,
|
||||||
|
"height": 229,
|
||||||
|
"clickZoneWidth": 104,
|
||||||
|
"clickZoneHeight": 104,
|
||||||
|
"textures": {
|
||||||
|
"normal": "resources/w/ui/img/Phone001_State=Default.png",
|
||||||
|
"hover": "resources/w/ui/img/Phone001_State=Selected.png",
|
||||||
|
"pressed": "resources/w/ui/img/Phone001_State=Tap.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
31
resources/w/ui/hud_step5aa.json
Normal file
31
resources/w/ui/hud_step5aa.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "FrameLayout",
|
||||||
|
"name": "hud_root",
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": "match_parent",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "LinearLayout",
|
||||||
|
"orientation": "vertical",
|
||||||
|
"vertical_align": "center",
|
||||||
|
"horizontal_align": "center",
|
||||||
|
"spacing": 0,
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": 600,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "Button",
|
||||||
|
"name": "phoneButton",
|
||||||
|
"width": 229,
|
||||||
|
"height": 229,
|
||||||
|
"textures": {
|
||||||
|
"normal": "resources/w/ui/img/Phone001_State=Default.png",
|
||||||
|
"hover": "resources/w/ui/img/Phone001_State=Selected.png",
|
||||||
|
"pressed": "resources/w/ui/img/Phone001_State=Tap.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
82
resources/w/ui/hud_step5ab.json
Normal file
82
resources/w/ui/hud_step5ab.json
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "FrameLayout",
|
||||||
|
"name": "hud_root",
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": "match_parent",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "LinearLayout",
|
||||||
|
"orientation": "horizontal",
|
||||||
|
"vertical_align": "center",
|
||||||
|
"horizontal_align": "right",
|
||||||
|
"spacing": 16,
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": 600,
|
||||||
|
"y" : -200,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "StaticImage",
|
||||||
|
"name": "hint6a",
|
||||||
|
"width": 440,
|
||||||
|
"height": 134,
|
||||||
|
"horizontal_gravity": "center",
|
||||||
|
"texture": "resources/w/ui/img/Hint6a.png",
|
||||||
|
"pulse": {
|
||||||
|
"minScale": 0.92,
|
||||||
|
"maxScale": 1.08,
|
||||||
|
"periodMs": 1500
|
||||||
|
},
|
||||||
|
"fadeIn": { "durationMs": 600 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "StaticImage",
|
||||||
|
"name": "hint6b",
|
||||||
|
"width": 440,
|
||||||
|
"height": 134,
|
||||||
|
"horizontal_gravity": "center",
|
||||||
|
"texture": "resources/w/ui/img/Hint6b.png",
|
||||||
|
"pulse": {
|
||||||
|
"minScale": 0.92,
|
||||||
|
"maxScale": 1.08,
|
||||||
|
"periodMs": 1500
|
||||||
|
},
|
||||||
|
"fadeIn": { "durationMs": 600 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},{
|
||||||
|
"type": "Button",
|
||||||
|
"name": "phoneButton",
|
||||||
|
"width": 229,
|
||||||
|
"height": 229,
|
||||||
|
"x": 74,
|
||||||
|
"y" :-46,
|
||||||
|
"clickZoneWidth": 104,
|
||||||
|
"clickZoneHeight": 104,
|
||||||
|
"horizontal_gravity": "right",
|
||||||
|
"vertical_gravity": "top",
|
||||||
|
"textures": {
|
||||||
|
"normal": "resources/w/ui/img/Phone001_State=Default.png",
|
||||||
|
"hover": "resources/w/ui/img/Phone001_State=Selected.png",
|
||||||
|
"pressed": "resources/w/ui/img/Phone001_State=Tap.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Button",
|
||||||
|
"name": "journalButton",
|
||||||
|
"width": 163,
|
||||||
|
"height": 163,
|
||||||
|
"x": -13,
|
||||||
|
"y" :-13,
|
||||||
|
"clickZoneWidth": 89,
|
||||||
|
"clickZoneHeight": 89,
|
||||||
|
"horizontal_gravity": "right",
|
||||||
|
"vertical_gravity": "top",
|
||||||
|
"textures": {
|
||||||
|
"normal": "resources/w/ui/img/Journal001_State=Default.png",
|
||||||
|
"hover": "resources/w/ui/img/Journal001_State=Selected.png",
|
||||||
|
"pressed": "resources/w/ui/img/Journal001_State=Tap.png"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
54
resources/w/ui/hud_step5b.json
Normal file
54
resources/w/ui/hud_step5b.json
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "FrameLayout",
|
||||||
|
"name": "hud_root",
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": "match_parent",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "LinearLayout",
|
||||||
|
"orientation": "vertical",
|
||||||
|
"vertical_align": "center",
|
||||||
|
"horizontal_align": "center",
|
||||||
|
"spacing": 0,
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": 600,
|
||||||
|
"y" : -250,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "StaticImage",
|
||||||
|
"name": "hint6b",
|
||||||
|
"width": 440,
|
||||||
|
"height": 134,
|
||||||
|
"horizontal_gravity": "center",
|
||||||
|
"texture": "resources/w/ui/img/Hint6b.png",
|
||||||
|
"pulse": {
|
||||||
|
"minScale": 0.92,
|
||||||
|
"maxScale": 1.08,
|
||||||
|
"periodMs": 1500
|
||||||
|
},
|
||||||
|
"fadeIn": { "durationMs": 600 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Button",
|
||||||
|
"name": "journalButton",
|
||||||
|
"horizontal_gravity": "right",
|
||||||
|
"vertical_gravity": "top",
|
||||||
|
"x": -13,
|
||||||
|
"y" :-13,
|
||||||
|
"width": 163,
|
||||||
|
"height": 163,
|
||||||
|
"clickZoneWidth": 89,
|
||||||
|
"clickZoneHeight": 89,
|
||||||
|
"horizontal_gravity": "right",
|
||||||
|
"vertical_gravity": "top",
|
||||||
|
"textures": {
|
||||||
|
"normal": "resources/w/ui/img/Journal001_State=Default.png",
|
||||||
|
"hover": "resources/w/ui/img/Journal001_State=Selected.png",
|
||||||
|
"pressed": "resources/w/ui/img/Journal001_State=Tap.png"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
31
resources/w/ui/hud_step5bb.json
Normal file
31
resources/w/ui/hud_step5bb.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "FrameLayout",
|
||||||
|
"name": "hud_root",
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": "match_parent",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "LinearLayout",
|
||||||
|
"orientation": "vertical",
|
||||||
|
"vertical_align": "center",
|
||||||
|
"horizontal_align": "center",
|
||||||
|
"spacing": 0,
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": 600,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "Button",
|
||||||
|
"name": "journalButton",
|
||||||
|
"width": 229,
|
||||||
|
"height": 229,
|
||||||
|
"textures": {
|
||||||
|
"normal": "resources/w/ui/img/Phone001_State=Default.png",
|
||||||
|
"hover": "resources/w/ui/img/Phone001_State=Selected.png",
|
||||||
|
"pressed": "resources/w/ui/img/Phone001_State=Tap.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
resources/w/ui/img/Hint1.png
(Stored with Git LFS)
BIN
resources/w/ui/img/Hint1.png
(Stored with Git LFS)
Binary file not shown.
BIN
resources/w/ui/img/Hint2.png
(Stored with Git LFS)
BIN
resources/w/ui/img/Hint2.png
(Stored with Git LFS)
Binary file not shown.
BIN
resources/w/ui/img/Hint3.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/Hint3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/Hint4.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/Hint4.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/Hint5.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/Hint5.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/Hint6a.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/Hint6a.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/Hint6b.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/Hint6b.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/Journal001_State=Default.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/Journal001_State=Default.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/Journal001_State=Selected.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/Journal001_State=Selected.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/Journal001_State=Tap.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/Journal001_State=Tap.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/Phone001_State=Default.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/Phone001_State=Default.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/Phone001_State=Selected.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/Phone001_State=Selected.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/Phone001_State=Tap.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/Phone001_State=Tap.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/PhoneTest001.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/PhoneTest001.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/QuestJournal001.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/QuestJournal001.png
(Stored with Git LFS)
Normal file
Binary file not shown.
25
resources/w/ui/screen_journal.json
Normal file
25
resources/w/ui/screen_journal.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "FrameLayout",
|
||||||
|
"name": "hud_root",
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": "match_parent",
|
||||||
|
"vertical_align": "center",
|
||||||
|
"horizontal_align": "center",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "Button",
|
||||||
|
"name": "journalExitButton",
|
||||||
|
"horizontal_gravity": "center",
|
||||||
|
"vertical_gravity": "center",
|
||||||
|
"width": 1125,
|
||||||
|
"height": 520,
|
||||||
|
"textures": {
|
||||||
|
"normal": "resources/w/ui/img/QuestJournal001.png",
|
||||||
|
"hover": "resources/w/ui/img/QuestJournal001.png",
|
||||||
|
"pressed": "resources/w/ui/img/QuestJournal001.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
25
resources/w/ui/screen_phone.json
Normal file
25
resources/w/ui/screen_phone.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"type": "FrameLayout",
|
||||||
|
"name": "hud_root",
|
||||||
|
"width": "match_parent",
|
||||||
|
"height": "match_parent",
|
||||||
|
"vertical_align": "center",
|
||||||
|
"horizontal_align": "center",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "Button",
|
||||||
|
"name": "phoneExitButton",
|
||||||
|
"horizontal_gravity": "center",
|
||||||
|
"vertical_gravity": "center",
|
||||||
|
"width": 1232,
|
||||||
|
"height": 627,
|
||||||
|
"textures": {
|
||||||
|
"normal": "resources/w/ui/img/PhoneTest001.png",
|
||||||
|
"hover": "resources/w/ui/img/PhoneTest001.png",
|
||||||
|
"pressed": "resources/w/ui/img/PhoneTest001.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,7 +15,7 @@ namespace ZL {
|
|||||||
using std::max;
|
using std::max;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr float DEFAULT_ZOOM = 24.f;
|
constexpr float DEFAULT_ZOOM = 6.f;
|
||||||
|
|
||||||
class Environment {
|
class Environment {
|
||||||
public:
|
public:
|
||||||
|
|||||||
54
src/Game.cpp
54
src/Game.cpp
@ -369,6 +369,24 @@ namespace ZL
|
|||||||
locations["uni_interior"]->onTeleport = teleportCallback;
|
locations["uni_interior"]->onTeleport = teleportCallback;
|
||||||
locations["location_dorm"]->onTeleport = teleportCallback;
|
locations["location_dorm"]->onTeleport = teleportCallback;
|
||||||
|
|
||||||
|
// Wire tutorial advance callbacks for all locations.
|
||||||
|
// advanceTutorialStep() guards against double-advancing, so sharing is safe.
|
||||||
|
for (auto& [name, loc] : locations) {
|
||||||
|
loc->dialogueSystem.setOnDialogueAdvanced([this]() {
|
||||||
|
menuManager.advanceTutorialStep();
|
||||||
|
});
|
||||||
|
loc->onPlayerFloorWalk = [this]() {
|
||||||
|
if (menuManager.tutorialStep == TutorialStep::Step2) {
|
||||||
|
menuManager.advanceTutorialStep();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wire inventory item-pickup callback for tutorial step4/5 item tracking.
|
||||||
|
inventory.onItemAdded = [this](const std::string& itemId) {
|
||||||
|
menuManager.onItemPickedUp(itemId);
|
||||||
|
};
|
||||||
|
|
||||||
currentLocation = locations["location_dorm"];
|
currentLocation = locations["location_dorm"];
|
||||||
currentLocation->scriptEngine.callLocationEnterCallback();
|
currentLocation->scriptEngine.callLocationEnterCallback();
|
||||||
|
|
||||||
@ -552,6 +570,8 @@ namespace ZL
|
|||||||
|
|
||||||
updateDarklandsFlash(delta);
|
updateDarklandsFlash(delta);
|
||||||
|
|
||||||
|
menuManager.uiManager.update(static_cast<float>(delta));
|
||||||
|
|
||||||
if (currentLocation)
|
if (currentLocation)
|
||||||
{
|
{
|
||||||
currentLocation->update(delta);
|
currentLocation->update(delta);
|
||||||
@ -661,6 +681,10 @@ namespace ZL
|
|||||||
if (Environment::zoom < zoomstep) {
|
if (Environment::zoom < zoomstep) {
|
||||||
Environment::zoom = zoomstep;
|
Environment::zoom = zoomstep;
|
||||||
}
|
}
|
||||||
|
// Tutorial step3 → step4: any mouse-wheel scroll counts as "zoom gesture".
|
||||||
|
if (menuManager.tutorialStep == TutorialStep::Step3) {
|
||||||
|
menuManager.advanceTutorialStep();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.type == SDL_KEYDOWN && event.key.repeat == 0) {
|
if (event.type == SDL_KEYDOWN && event.key.repeat == 0) {
|
||||||
@ -722,8 +746,10 @@ namespace ZL
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_l:
|
case SDLK_l:
|
||||||
x = x - 1;
|
//x = x - 1;
|
||||||
std::cout << "current x: " << x << std::endl;
|
//std::cout << "current x: " << x << std::endl;
|
||||||
|
std::cout << "Azimuth: " << currentLocation->cameraAzimuth << std::endl;
|
||||||
|
std::cout << "Inclination: " << currentLocation->cameraInclination << std::endl;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_c:
|
case SDLK_c:
|
||||||
@ -826,6 +852,10 @@ namespace ZL
|
|||||||
// movement threshold was crossed.
|
// movement threshold was crossed.
|
||||||
currentLocation->lastMouseX = eventX;
|
currentLocation->lastMouseX = eventX;
|
||||||
currentLocation->lastMouseY = eventY;
|
currentLocation->lastMouseY = eventY;
|
||||||
|
|
||||||
|
// Snapshot current angles so we can measure how far the user rotates.
|
||||||
|
dragStartAzimuth = currentLocation->cameraAzimuth;
|
||||||
|
dragStartInclination = currentLocation->cameraInclination;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -881,6 +911,13 @@ namespace ZL
|
|||||||
static const float zoomMin = 2.0f;
|
static const float zoomMin = 2.0f;
|
||||||
if (newZoom < zoomMin) newZoom = zoomMin;
|
if (newZoom < zoomMin) newZoom = zoomMin;
|
||||||
Environment::zoom = newZoom;
|
Environment::zoom = newZoom;
|
||||||
|
|
||||||
|
// Tutorial step3 → step4: detect a significant pinch-zoom (≥ 2 zoom units).
|
||||||
|
if (menuManager.tutorialStep == TutorialStep::Step3) {
|
||||||
|
if (std::abs(Environment::zoom - pinchStartZoom) >= 2.0f) {
|
||||||
|
menuManager.advanceTutorialStep();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::endPinch()
|
void Game::endPinch()
|
||||||
@ -1004,6 +1041,19 @@ namespace ZL
|
|||||||
if (currentLocation) {
|
if (currentLocation) {
|
||||||
// Forwarded for dialogue hover and (when cameraDragging) camera rotation.
|
// Forwarded for dialogue hover and (when cameraDragging) camera rotation.
|
||||||
currentLocation->handleMotion(fingerId, eventX, eventY, mx, my);
|
currentLocation->handleMotion(fingerId, eventX, eventY, mx, my);
|
||||||
|
|
||||||
|
// Tutorial step1 → step2: detect a significant camera rotation on BOTH axes.
|
||||||
|
// ~0.15 rad (≈8.6°) per axis ensures the user intentionally panned in 2D,
|
||||||
|
// not just nudged a single axis by accident.
|
||||||
|
static constexpr float TUTORIAL_ROTATION_THRESHOLD = 0.15f;
|
||||||
|
if (cameraDragging
|
||||||
|
&& menuManager.tutorialStep == TutorialStep::Step1) {
|
||||||
|
float deltaAz = std::abs(currentLocation->cameraAzimuth - dragStartAzimuth);
|
||||||
|
float deltaInc = std::abs(currentLocation->cameraInclination - dragStartInclination);
|
||||||
|
if (deltaAz >= TUTORIAL_ROTATION_THRESHOLD && deltaInc >= TUTORIAL_ROTATION_THRESHOLD) {
|
||||||
|
menuManager.advanceTutorialStep();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -87,6 +87,11 @@ namespace ZL {
|
|||||||
float pinchStartDistance = 0.0f;
|
float pinchStartDistance = 0.0f;
|
||||||
float pinchStartZoom = 0.0f;
|
float pinchStartZoom = 0.0f;
|
||||||
|
|
||||||
|
// Tutorial: azimuth and inclination captured at the start of each camera drag,
|
||||||
|
// used to measure how far the user has rotated before advancing the tutorial step.
|
||||||
|
float dragStartAzimuth = 0.0f;
|
||||||
|
float dragStartInclination = 0.0f;
|
||||||
|
|
||||||
std::unique_ptr<AudioPlayerAsync> audioPlayer;
|
std::unique_ptr<AudioPlayerAsync> audioPlayer;
|
||||||
|
|
||||||
int64_t getSyncTimeMs();
|
int64_t getSyncTimeMs();
|
||||||
|
|||||||
@ -1519,6 +1519,7 @@ namespace ZL
|
|||||||
targetInteractNpc = nullptr;
|
targetInteractNpc = nullptr;
|
||||||
targetInteractNpcIndex = -1;
|
targetInteractNpcIndex = -1;
|
||||||
targetTeleportZone = nullptr;
|
targetTeleportZone = nullptr;
|
||||||
|
if (onPlayerFloorWalk) onPlayerFloorWalk();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@ -51,12 +51,11 @@ namespace ZL
|
|||||||
|
|
||||||
std::vector<InteractiveObject> interactiveObjects;
|
std::vector<InteractiveObject> interactiveObjects;
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<Character> player;
|
std::unique_ptr<Character> player;
|
||||||
std::vector<std::unique_ptr<Character>> npcs;
|
std::vector<std::unique_ptr<Character>> npcs;
|
||||||
|
|
||||||
float cameraAzimuth = 0.0f;
|
float cameraAzimuth = -2.35;
|
||||||
float cameraInclination = M_PI * 30.f / 180.f;
|
float cameraInclination = 1.1036;//M_PI * 30.f / 180.f;
|
||||||
|
|
||||||
std::vector<PathFinder> navigationMaps;
|
std::vector<PathFinder> navigationMaps;
|
||||||
PathFinder* navigation = nullptr;
|
PathFinder* navigation = nullptr;
|
||||||
@ -87,6 +86,10 @@ namespace ZL
|
|||||||
// Read by draw functions and raycast — do not write from Location code.
|
// Read by draw functions and raycast — do not write from Location code.
|
||||||
bool isDarklands = false;
|
bool isDarklands = false;
|
||||||
|
|
||||||
|
// Called when the player successfully taps the ground and a floor walk target is set.
|
||||||
|
// Used by the tutorial system to detect the "tap to walk" gesture.
|
||||||
|
std::function<void()> onPlayerFloorWalk;
|
||||||
|
|
||||||
// Set by Game after setup(). Lua and onDeathAnimComplete call this to
|
// Set by Game after setup(). Lua and onDeathAnimComplete call this to
|
||||||
// request the transition without coupling Location to Game directly.
|
// request the transition without coupling Location to Game directly.
|
||||||
std::function<bool()> requestDarklandsTransition;
|
std::function<bool()> requestDarklandsTransition;
|
||||||
|
|||||||
@ -34,7 +34,16 @@ namespace ZL {
|
|||||||
inventory = &inv;
|
inventory = &inv;
|
||||||
|
|
||||||
//hudRoot = loadUiFromFile("resources/config2/hud.json", renderer, zipFile);
|
//hudRoot = loadUiFromFile("resources/config2/hud.json", renderer, zipFile);
|
||||||
hudRoot = loadUiFromFile("resources/w/ui/hud_step0.json", renderer, zipFile);
|
hudRoot = loadUiFromFile("resources/w/ui/hud_step0.json", renderer, zipFile);
|
||||||
|
hudStep1Root = loadUiFromFile("resources/w/ui/hud_step1.json", renderer, zipFile);
|
||||||
|
hudStep2Root = loadUiFromFile("resources/w/ui/hud_step2.json", renderer, zipFile);
|
||||||
|
hudStep3Root = loadUiFromFile("resources/w/ui/hud_step3.json", renderer, zipFile);
|
||||||
|
hudStep4Root = loadUiFromFile("resources/w/ui/hud_step4.json", renderer, zipFile);
|
||||||
|
hudStep5aRoot = loadUiFromFile("resources/w/ui/hud_step5a.json", renderer, zipFile);
|
||||||
|
hudStep5bRoot = loadUiFromFile("resources/w/ui/hud_step5b.json", renderer, zipFile);
|
||||||
|
hudStep5abRoot = loadUiFromFile("resources/w/ui/hud_step5ab.json", renderer, zipFile);
|
||||||
|
phoneScreenRoot = loadUiFromFile("resources/w/ui/screen_phone.json", renderer, zipFile);
|
||||||
|
journalScreenRoot= loadUiFromFile("resources/w/ui/screen_journal.json", renderer, zipFile);
|
||||||
inventoryRoot = loadUiFromFile("resources/config2/ui_inventory.json", renderer, zipFile);
|
inventoryRoot = loadUiFromFile("resources/config2/ui_inventory.json", renderer, zipFile);
|
||||||
questJournalRoot = loadUiFromFile("resources/config2/ui_quest_journal.json", renderer, zipFile);
|
questJournalRoot = loadUiFromFile("resources/config2/ui_quest_journal.json", renderer, zipFile);
|
||||||
|
|
||||||
@ -124,6 +133,119 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MenuManager::openPhoneScreen() {
|
||||||
|
state = GameState::PhoneScreen;
|
||||||
|
tutorialPhoneScreenOpened = true;
|
||||||
|
// Hide the phone hint on the current HUD so it stays hidden when we return.
|
||||||
|
uiManager.setNodeVisible("hint6a", false);
|
||||||
|
uiManager.pushMenuFromSavedRoot(phoneScreenRoot);
|
||||||
|
uiManager.setButtonCallback("phoneExitButton", [this](const std::string&) {
|
||||||
|
closePhoneScreen();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::closePhoneScreen() {
|
||||||
|
state = GameState::Gameplay;
|
||||||
|
uiManager.popMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::openJournalScreen() {
|
||||||
|
state = GameState::JournalScreen;
|
||||||
|
tutorialJournalScreenOpened = true;
|
||||||
|
// Hide the journal hint on the current HUD so it stays hidden when we return.
|
||||||
|
uiManager.setNodeVisible("hint6b", false);
|
||||||
|
uiManager.pushMenuFromSavedRoot(journalScreenRoot);
|
||||||
|
uiManager.setButtonCallback("journalExitButton", [this](const std::string&) {
|
||||||
|
closeJournalScreen();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::closeJournalScreen() {
|
||||||
|
state = GameState::Gameplay;
|
||||||
|
uiManager.popMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registers phoneButton / journalButton callbacks on the current HUD root
|
||||||
|
// and hides any hints that have already been completed.
|
||||||
|
// Called after every replaceRoot during step 5.
|
||||||
|
void MenuManager::setupStep5Callbacks() {
|
||||||
|
if (uiManager.findButton("phoneButton")) {
|
||||||
|
uiManager.setButtonCallback("phoneButton", [this](const std::string&) {
|
||||||
|
openPhoneScreen();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (uiManager.findButton("journalButton")) {
|
||||||
|
uiManager.setButtonCallback("journalButton", [this](const std::string&) {
|
||||||
|
openJournalScreen();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (tutorialPhoneScreenOpened) uiManager.setNodeVisible("hint6a", false);
|
||||||
|
if (tutorialJournalScreenOpened) uiManager.setNodeVisible("hint6b", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::advanceTutorialStep() {
|
||||||
|
std::shared_ptr<UiNode> nextRoot;
|
||||||
|
|
||||||
|
switch (tutorialStep) {
|
||||||
|
case TutorialStep::Step0:
|
||||||
|
tutorialStep = TutorialStep::Step1;
|
||||||
|
nextRoot = hudStep1Root;
|
||||||
|
break;
|
||||||
|
case TutorialStep::Step1:
|
||||||
|
tutorialStep = TutorialStep::Step2;
|
||||||
|
nextRoot = hudStep2Root;
|
||||||
|
break;
|
||||||
|
case TutorialStep::Step2:
|
||||||
|
tutorialStep = TutorialStep::Step3;
|
||||||
|
nextRoot = hudStep3Root;
|
||||||
|
break;
|
||||||
|
case TutorialStep::Step3:
|
||||||
|
tutorialStep = TutorialStep::Step4;
|
||||||
|
nextRoot = hudStep4Root;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return; // Step4/Step5 transitions are driven by onItemPickedUp
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == GameState::Gameplay && nextRoot) {
|
||||||
|
uiManager.replaceRoot(nextRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::onItemPickedUp(const std::string& itemId) {
|
||||||
|
if (tutorialStep != TutorialStep::Step4 && tutorialStep != TutorialStep::Step5) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemId == "phone") tutorialPhonePickedUp = true;
|
||||||
|
if (itemId == "journal") tutorialJournalPickedUp = true;
|
||||||
|
|
||||||
|
if (tutorialStep == TutorialStep::Step4) {
|
||||||
|
tutorialStep = TutorialStep::Step5;
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshItemPickupHud();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::refreshItemPickupHud() {
|
||||||
|
if (state != GameState::Gameplay) return;
|
||||||
|
|
||||||
|
std::shared_ptr<UiNode> nextRoot;
|
||||||
|
if (tutorialPhonePickedUp && tutorialJournalPickedUp) {
|
||||||
|
nextRoot = hudStep5abRoot;
|
||||||
|
} else if (tutorialPhonePickedUp) {
|
||||||
|
nextRoot = hudStep5aRoot;
|
||||||
|
} else if (tutorialJournalPickedUp) {
|
||||||
|
nextRoot = hudStep5bRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextRoot) {
|
||||||
|
uiManager.replaceRoot(nextRoot);
|
||||||
|
// Register item-screen buttons and re-apply any already-completed hint visibility.
|
||||||
|
setupStep5Callbacks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MenuManager::refreshQuestJournalUi() {
|
void MenuManager::refreshQuestJournalUi() {
|
||||||
visibleQuestIds.clear();
|
visibleQuestIds.clear();
|
||||||
auto quests = questJournal.getVisibleQuests();
|
auto quests = questJournal.getVisibleQuests();
|
||||||
|
|||||||
@ -16,7 +16,18 @@ namespace ZL {
|
|||||||
enum class GameState {
|
enum class GameState {
|
||||||
Gameplay,
|
Gameplay,
|
||||||
Inventory,
|
Inventory,
|
||||||
QuestJournal
|
QuestJournal,
|
||||||
|
PhoneScreen,
|
||||||
|
JournalScreen
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class TutorialStep {
|
||||||
|
Step0, // Dialogue hint: "click to advance"
|
||||||
|
Step1, // Camera rotation hint
|
||||||
|
Step2, // Floor tap / walk hint
|
||||||
|
Step3, // Pinch-zoom hint
|
||||||
|
Step4, // Pick-up item hint
|
||||||
|
Step5, // Post-pickup reaction (sub-state: which items were collected)
|
||||||
};
|
};
|
||||||
|
|
||||||
class MenuManager {
|
class MenuManager {
|
||||||
@ -38,6 +49,16 @@ namespace ZL {
|
|||||||
bool isInventoryOpen() const { return state == GameState::Inventory; }
|
bool isInventoryOpen() const { return state == GameState::Inventory; }
|
||||||
bool isQuestJournalOpen() const { return state == GameState::QuestJournal; }
|
bool isQuestJournalOpen() const { return state == GameState::QuestJournal; }
|
||||||
|
|
||||||
|
void openPhoneScreen();
|
||||||
|
void closePhoneScreen();
|
||||||
|
void openJournalScreen();
|
||||||
|
void closeJournalScreen();
|
||||||
|
|
||||||
|
void advanceTutorialStep();
|
||||||
|
void onItemPickedUp(const std::string& itemId);
|
||||||
|
|
||||||
|
TutorialStep tutorialStep = TutorialStep::Step0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Renderer& renderer;
|
Renderer& renderer;
|
||||||
|
|
||||||
@ -45,11 +66,27 @@ namespace ZL {
|
|||||||
void enterGameplay();
|
void enterGameplay();
|
||||||
void refreshQuestJournalUi();
|
void refreshQuestJournalUi();
|
||||||
void selectQuestByIndex(int index);
|
void selectQuestByIndex(int index);
|
||||||
|
void refreshItemPickupHud();
|
||||||
|
void setupStep5Callbacks();
|
||||||
|
|
||||||
GameState state = GameState::Gameplay;
|
GameState state = GameState::Gameplay;
|
||||||
Inventory* inventory = nullptr;
|
Inventory* inventory = nullptr;
|
||||||
|
|
||||||
|
bool tutorialPhonePickedUp = false;
|
||||||
|
bool tutorialJournalPickedUp = false;
|
||||||
|
bool tutorialPhoneScreenOpened = false;
|
||||||
|
bool tutorialJournalScreenOpened = false;
|
||||||
|
|
||||||
std::shared_ptr<UiNode> hudRoot;
|
std::shared_ptr<UiNode> hudRoot;
|
||||||
|
std::shared_ptr<UiNode> hudStep1Root;
|
||||||
|
std::shared_ptr<UiNode> hudStep2Root;
|
||||||
|
std::shared_ptr<UiNode> hudStep3Root;
|
||||||
|
std::shared_ptr<UiNode> hudStep4Root;
|
||||||
|
std::shared_ptr<UiNode> hudStep5aRoot;
|
||||||
|
std::shared_ptr<UiNode> hudStep5bRoot;
|
||||||
|
std::shared_ptr<UiNode> hudStep5abRoot;
|
||||||
|
std::shared_ptr<UiNode> phoneScreenRoot;
|
||||||
|
std::shared_ptr<UiNode> journalScreenRoot;
|
||||||
std::shared_ptr<UiNode> inventoryRoot;
|
std::shared_ptr<UiNode> inventoryRoot;
|
||||||
std::shared_ptr<UiNode> questJournalRoot;
|
std::shared_ptr<UiNode> questJournalRoot;
|
||||||
|
|
||||||
|
|||||||
@ -373,9 +373,17 @@ namespace ZL {
|
|||||||
void UiStaticImage::draw(Renderer& renderer) const {
|
void UiStaticImage::draw(Renderer& renderer) const {
|
||||||
if (!texture) return;
|
if (!texture) return;
|
||||||
|
|
||||||
|
const float alpha = (fadeInEnabled && fadeInDurationMs > 0.0f)
|
||||||
|
? std::clamp(fadeInElapsedMs / fadeInDurationMs, 0.0f, 1.0f)
|
||||||
|
: 1.0f;
|
||||||
|
|
||||||
renderer.RenderUniform1i(textureUniformName, 0);
|
renderer.RenderUniform1i(textureUniformName, 0);
|
||||||
|
renderer.RenderUniform1f("uAlpha", alpha);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
|
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
|
||||||
renderer.DrawVertexRenderStruct(mesh);
|
renderer.DrawVertexRenderStruct(mesh);
|
||||||
|
if (alpha < 1.0f) {
|
||||||
|
renderer.RenderUniform1f("uAlpha", 1.0f); // restore for subsequent draws
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UiTextField::draw(Renderer& renderer) const {
|
void UiTextField::draw(Renderer& renderer) const {
|
||||||
@ -504,6 +512,8 @@ namespace ZL {
|
|||||||
btn->texDisabled = loadTex("disabled");
|
btn->texDisabled = loadTex("disabled");
|
||||||
|
|
||||||
btn->border = j.value("border", 0.0f);
|
btn->border = j.value("border", 0.0f);
|
||||||
|
if (j.contains("clickZoneWidth")) btn->clickZoneWidth = j["clickZoneWidth"].get<float>();
|
||||||
|
if (j.contains("clickZoneHeight")) btn->clickZoneHeight = j["clickZoneHeight"].get<float>();
|
||||||
|
|
||||||
node->button = btn;
|
node->button = btn;
|
||||||
}
|
}
|
||||||
@ -616,6 +626,8 @@ namespace ZL {
|
|||||||
if (j.contains("color") && j["color"].is_array() && j["color"].size() == 4) {
|
if (j.contains("color") && j["color"].is_array() && j["color"].size() == 4) {
|
||||||
for (int i = 0; i < 4; ++i) tb->color[i] = j["color"][i].get<float>();
|
for (int i = 0; i < 4; ++i) tb->color[i] = j["color"][i].get<float>();
|
||||||
}
|
}
|
||||||
|
if (j.contains("clickZoneWidth")) tb->clickZoneWidth = j["clickZoneWidth"].get<float>();
|
||||||
|
if (j.contains("clickZoneHeight")) tb->clickZoneHeight = j["clickZoneHeight"].get<float>();
|
||||||
|
|
||||||
tb->textRenderer = std::make_unique<TextRenderer>();
|
tb->textRenderer = std::make_unique<TextRenderer>();
|
||||||
if (!tb->textRenderer->init(renderer, tb->fontPath, tb->fontSize, zipFile)) {
|
if (!tb->textRenderer->init(renderer, tb->fontPath, tb->fontSize, zipFile)) {
|
||||||
@ -679,6 +691,23 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
node->staticImage = img;
|
node->staticImage = img;
|
||||||
|
|
||||||
|
// Optional fade-in on display
|
||||||
|
if (j.contains("fadeIn") && j["fadeIn"].is_object()) {
|
||||||
|
const auto& fi = j["fadeIn"];
|
||||||
|
img->fadeInEnabled = true;
|
||||||
|
img->fadeInDurationMs = fi.value("durationMs", 1000.0f);
|
||||||
|
img->fadeInElapsedMs = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional pulse-scale animation
|
||||||
|
if (j.contains("pulse") && j["pulse"].is_object()) {
|
||||||
|
const auto& p = j["pulse"];
|
||||||
|
node->pulseEnabled = true;
|
||||||
|
node->pulseMinScale = p.value("minScale", 0.9f);
|
||||||
|
node->pulseMaxScale = p.value("maxScale", 1.1f);
|
||||||
|
node->pulsePeriodMs = p.value("periodMs", 1000.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeStr == "TextView") {
|
if (typeStr == "TextView") {
|
||||||
@ -777,6 +806,7 @@ namespace ZL {
|
|||||||
textViews.clear();
|
textViews.clear();
|
||||||
textFields.clear();
|
textFields.clear();
|
||||||
staticImages.clear();
|
staticImages.clear();
|
||||||
|
pulsingNodes.clear();
|
||||||
collectButtonsAndSliders(root);
|
collectButtonsAndSliders(root);
|
||||||
|
|
||||||
nodeActiveAnims.clear();
|
nodeActiveAnims.clear();
|
||||||
@ -1020,6 +1050,12 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
if (node->staticImage) {
|
if (node->staticImage) {
|
||||||
staticImages.push_back(node->staticImage);
|
staticImages.push_back(node->staticImage);
|
||||||
|
if (node->staticImage->fadeInEnabled) {
|
||||||
|
node->staticImage->fadeInElapsedMs = 0.0f; // restart fade every time UI is shown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node->pulseEnabled && node->staticImage) {
|
||||||
|
pulsingNodes.push_back(node);
|
||||||
}
|
}
|
||||||
for (auto& c : node->children) collectButtonsAndSliders(c);
|
for (auto& c : node->children) collectButtonsAndSliders(c);
|
||||||
}
|
}
|
||||||
@ -1128,6 +1164,7 @@ namespace ZL {
|
|||||||
prev.textViews = textViews;
|
prev.textViews = textViews;
|
||||||
prev.textFields = textFields;
|
prev.textFields = textFields;
|
||||||
prev.staticImages = staticImages;
|
prev.staticImages = staticImages;
|
||||||
|
prev.pulsingNodes = pulsingNodes;
|
||||||
prev.pressedButtons = pressedButtons;
|
prev.pressedButtons = pressedButtons;
|
||||||
prev.pressedTextButtons = pressedTextButtons;
|
prev.pressedTextButtons = pressedTextButtons;
|
||||||
prev.pressedSliders = pressedSliders;
|
prev.pressedSliders = pressedSliders;
|
||||||
@ -1190,6 +1227,7 @@ namespace ZL {
|
|||||||
textViews = s.textViews;
|
textViews = s.textViews;
|
||||||
textFields = s.textFields;
|
textFields = s.textFields;
|
||||||
staticImages = s.staticImages;
|
staticImages = s.staticImages;
|
||||||
|
pulsingNodes = s.pulsingNodes;
|
||||||
pressedButtons = s.pressedButtons;
|
pressedButtons = s.pressedButtons;
|
||||||
pressedTextButtons = s.pressedTextButtons;
|
pressedTextButtons = s.pressedTextButtons;
|
||||||
pressedSliders = s.pressedSliders;
|
pressedSliders = s.pressedSliders;
|
||||||
@ -1233,6 +1271,7 @@ namespace ZL {
|
|||||||
renderer.PushProjectionMatrix(Environment::projectionWidth, Environment::projectionHeight, -1, 1);
|
renderer.PushProjectionMatrix(Environment::projectionWidth, Environment::projectionHeight, -1, 1);
|
||||||
renderer.PushMatrix();
|
renderer.PushMatrix();
|
||||||
renderer.LoadIdentity();
|
renderer.LoadIdentity();
|
||||||
|
renderer.RenderUniform1f("uAlpha", 1.0f); // ensure alpha is fully opaque unless a widget overrides it
|
||||||
|
|
||||||
std::function<void(const std::shared_ptr<UiNode>&)> drawNode =
|
std::function<void(const std::shared_ptr<UiNode>&)> drawNode =
|
||||||
[&](const std::shared_ptr<UiNode>& node) {
|
[&](const std::shared_ptr<UiNode>& node) {
|
||||||
@ -1301,6 +1340,29 @@ namespace ZL {
|
|||||||
void UiManager::update(float deltaMs) {
|
void UiManager::update(float deltaMs) {
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
|
|
||||||
|
// Fade-in animations (StaticImage elements with fadeInEnabled == true)
|
||||||
|
for (auto& img : staticImages) {
|
||||||
|
if (!img || !img->fadeInEnabled) continue;
|
||||||
|
if (img->fadeInElapsedMs < img->fadeInDurationMs) {
|
||||||
|
img->fadeInElapsedMs += deltaMs;
|
||||||
|
if (img->fadeInElapsedMs > img->fadeInDurationMs)
|
||||||
|
img->fadeInElapsedMs = img->fadeInDurationMs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pulse-scale animations (StaticImage nodes with pulseEnabled == true)
|
||||||
|
for (auto& node : pulsingNodes) {
|
||||||
|
if (!node) continue;
|
||||||
|
node->pulseElapsedMs += deltaMs;
|
||||||
|
if (node->pulseElapsedMs >= node->pulsePeriodMs)
|
||||||
|
node->pulseElapsedMs = std::fmod(node->pulseElapsedMs, node->pulsePeriodMs);
|
||||||
|
const float phase = node->pulseElapsedMs / node->pulsePeriodMs;
|
||||||
|
const float t = (std::sin(phase * 2.0f * static_cast<float>(M_PI)) + 1.0f) * 0.5f;
|
||||||
|
const float s = node->pulseMinScale + (node->pulseMaxScale - node->pulseMinScale) * t;
|
||||||
|
node->scaleX = s;
|
||||||
|
node->scaleY = s;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::pair<std::shared_ptr<UiNode>, size_t>> animationsToRemove;
|
std::vector<std::pair<std::shared_ptr<UiNode>, size_t>> animationsToRemove;
|
||||||
std::vector<std::function<void()>> pendingCallbacks;
|
std::vector<std::function<void()>> pendingCallbacks;
|
||||||
|
|
||||||
@ -1490,7 +1552,7 @@ namespace ZL {
|
|||||||
for (auto& b : buttons) {
|
for (auto& b : buttons) {
|
||||||
if (b->state != ButtonState::Disabled)
|
if (b->state != ButtonState::Disabled)
|
||||||
{
|
{
|
||||||
if (b->rect.containsConsideringBorder((float)x, (float)y, b->border)) {
|
if (b->getClickZoneRect().containsConsideringBorder((float)x, (float)y, b->border)) {
|
||||||
if (b->state != ButtonState::Pressed) b->state = ButtonState::Hover;
|
if (b->state != ButtonState::Pressed) b->state = ButtonState::Hover;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1501,7 +1563,7 @@ namespace ZL {
|
|||||||
for (auto& tb : textButtons) {
|
for (auto& tb : textButtons) {
|
||||||
if (tb->state != ButtonState::Disabled)
|
if (tb->state != ButtonState::Disabled)
|
||||||
{
|
{
|
||||||
if (tb->rect.containsConsideringBorder((float)x, (float)y, tb->border)) {
|
if (tb->getClickZoneRect().containsConsideringBorder((float)x, (float)y, tb->border)) {
|
||||||
if (tb->state != ButtonState::Pressed) tb->state = ButtonState::Hover;
|
if (tb->state != ButtonState::Pressed) tb->state = ButtonState::Hover;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1534,7 +1596,7 @@ namespace ZL {
|
|||||||
for (auto& b : buttons) {
|
for (auto& b : buttons) {
|
||||||
if (b->state != ButtonState::Disabled)
|
if (b->state != ButtonState::Disabled)
|
||||||
{
|
{
|
||||||
if (b->rect.containsConsideringBorder((float)x, (float)y, b->border)) {
|
if (b->getClickZoneRect().containsConsideringBorder((float)x, (float)y, b->border)) {
|
||||||
b->state = ButtonState::Pressed;
|
b->state = ButtonState::Pressed;
|
||||||
pressedButtons[fingerId] = b;
|
pressedButtons[fingerId] = b;
|
||||||
if (b->onPress) b->onPress(b->name);
|
if (b->onPress) b->onPress(b->name);
|
||||||
@ -1546,7 +1608,7 @@ namespace ZL {
|
|||||||
for (auto& tb : textButtons) {
|
for (auto& tb : textButtons) {
|
||||||
if (tb->state != ButtonState::Disabled)
|
if (tb->state != ButtonState::Disabled)
|
||||||
{
|
{
|
||||||
if (tb->rect.containsConsideringBorder((float)x, (float)y, tb->border)) {
|
if (tb->getClickZoneRect().containsConsideringBorder((float)x, (float)y, tb->border)) {
|
||||||
tb->state = ButtonState::Pressed;
|
tb->state = ButtonState::Pressed;
|
||||||
pressedTextButtons[fingerId] = tb;
|
pressedTextButtons[fingerId] = tb;
|
||||||
if (tb->onPress) tb->onPress(tb->name);
|
if (tb->onPress) tb->onPress(tb->name);
|
||||||
@ -1593,7 +1655,7 @@ namespace ZL {
|
|||||||
if (btnIt != pressedButtons.end()) {
|
if (btnIt != pressedButtons.end()) {
|
||||||
auto b = btnIt->second;
|
auto b = btnIt->second;
|
||||||
if (b) {
|
if (b) {
|
||||||
bool contains = b->rect.contains((float)x, (float)y);
|
bool contains = b->getClickZoneRect().contains((float)x, (float)y);
|
||||||
if (b->state == ButtonState::Pressed) {
|
if (b->state == ButtonState::Pressed) {
|
||||||
if (contains) {
|
if (contains) {
|
||||||
clicked.push_back(b);
|
clicked.push_back(b);
|
||||||
@ -1609,7 +1671,7 @@ namespace ZL {
|
|||||||
if (tbIt != pressedTextButtons.end()) {
|
if (tbIt != pressedTextButtons.end()) {
|
||||||
auto tb = tbIt->second;
|
auto tb = tbIt->second;
|
||||||
if (tb) {
|
if (tb) {
|
||||||
bool contains = tb->rect.contains((float)x, (float)y);
|
bool contains = tb->getClickZoneRect().contains((float)x, (float)y);
|
||||||
if (tb->state == ButtonState::Pressed) {
|
if (tb->state == ButtonState::Pressed) {
|
||||||
if (contains) {
|
if (contains) {
|
||||||
clickedText.push_back(tb);
|
clickedText.push_back(tb);
|
||||||
|
|||||||
@ -93,6 +93,17 @@ namespace ZL {
|
|||||||
|
|
||||||
VertexRenderStruct mesh;
|
VertexRenderStruct mesh;
|
||||||
|
|
||||||
|
// Optional explicit hit-test zone, centred on rect.
|
||||||
|
// 0 means "use rect.w / rect.h" (default behaviour).
|
||||||
|
float clickZoneWidth = 0.0f;
|
||||||
|
float clickZoneHeight = 0.0f;
|
||||||
|
|
||||||
|
UiRect getClickZoneRect() const {
|
||||||
|
float cw = (clickZoneWidth > 0.0f) ? clickZoneWidth : rect.w;
|
||||||
|
float ch = (clickZoneHeight > 0.0f) ? clickZoneHeight : rect.h;
|
||||||
|
return { rect.x + (rect.w - cw) * 0.5f, rect.y + (rect.h - ch) * 0.5f, cw, ch };
|
||||||
|
}
|
||||||
|
|
||||||
std::function<void(const std::string&)> onClick;
|
std::function<void(const std::string&)> onClick;
|
||||||
std::function<void(const std::string&)> onPress; // fires on touch/mouse down
|
std::function<void(const std::string&)> onPress; // fires on touch/mouse down
|
||||||
|
|
||||||
@ -139,6 +150,17 @@ namespace ZL {
|
|||||||
ButtonState state = ButtonState::Normal;
|
ButtonState state = ButtonState::Normal;
|
||||||
VertexRenderStruct mesh;
|
VertexRenderStruct mesh;
|
||||||
|
|
||||||
|
// Optional explicit hit-test zone, centred on rect.
|
||||||
|
// 0 means "use rect.w / rect.h" (default behaviour).
|
||||||
|
float clickZoneWidth = 0.0f;
|
||||||
|
float clickZoneHeight = 0.0f;
|
||||||
|
|
||||||
|
UiRect getClickZoneRect() const {
|
||||||
|
float cw = (clickZoneWidth > 0.0f) ? clickZoneWidth : rect.w;
|
||||||
|
float ch = (clickZoneHeight > 0.0f) ? clickZoneHeight : rect.h;
|
||||||
|
return { rect.x + (rect.w - cw) * 0.5f, rect.y + (rect.h - ch) * 0.5f, cw, ch };
|
||||||
|
}
|
||||||
|
|
||||||
// Text drawn on top of the button
|
// Text drawn on top of the button
|
||||||
std::string text;
|
std::string text;
|
||||||
std::string fontPath = "resources/fonts/DroidSans.ttf";
|
std::string fontPath = "resources/fonts/DroidSans.ttf";
|
||||||
@ -209,6 +231,11 @@ namespace ZL {
|
|||||||
|
|
||||||
VertexRenderStruct mesh;
|
VertexRenderStruct mesh;
|
||||||
|
|
||||||
|
// Fade-in on first display (triggers each time the containing UI is shown)
|
||||||
|
bool fadeInEnabled = false;
|
||||||
|
float fadeInDurationMs = 1000.0f;
|
||||||
|
float fadeInElapsedMs = 0.0f; // runtime, reset by collectButtonsAndSliders
|
||||||
|
|
||||||
void buildMesh();
|
void buildMesh();
|
||||||
void draw(Renderer& renderer) const;
|
void draw(Renderer& renderer) const;
|
||||||
};
|
};
|
||||||
@ -236,6 +263,13 @@ namespace ZL {
|
|||||||
|
|
||||||
bool visible = true;
|
bool visible = true;
|
||||||
|
|
||||||
|
// Pulse-scale animation (StaticImage only; auto-starts when pulseEnabled == true)
|
||||||
|
bool pulseEnabled = false;
|
||||||
|
float pulseMinScale = 1.0f;
|
||||||
|
float pulseMaxScale = 1.1f;
|
||||||
|
float pulsePeriodMs = 1000.0f;
|
||||||
|
float pulseElapsedMs = 0.0f; // runtime, not persisted in JSON
|
||||||
|
|
||||||
// Иерархия
|
// Иерархия
|
||||||
std::vector<std::shared_ptr<UiNode>> children;
|
std::vector<std::shared_ptr<UiNode>> children;
|
||||||
|
|
||||||
@ -322,6 +356,13 @@ namespace ZL {
|
|||||||
tb->animScaleY = 1.0f;
|
tb->animScaleY = 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (auto& n : pulsingNodes) {
|
||||||
|
if (n) {
|
||||||
|
n->scaleX = 1.0f;
|
||||||
|
n->scaleY = 1.0f;
|
||||||
|
n->pulseElapsedMs = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<UiButton> findButton(const std::string& name);
|
std::shared_ptr<UiButton> findButton(const std::string& name);
|
||||||
@ -404,6 +445,7 @@ namespace ZL {
|
|||||||
std::vector<std::shared_ptr<UiTextView>> textViews;
|
std::vector<std::shared_ptr<UiTextView>> textViews;
|
||||||
std::vector<std::shared_ptr<UiTextField>> textFields;
|
std::vector<std::shared_ptr<UiTextField>> textFields;
|
||||||
std::vector<std::shared_ptr<UiStaticImage>> staticImages;
|
std::vector<std::shared_ptr<UiStaticImage>> staticImages;
|
||||||
|
std::vector<std::shared_ptr<UiNode>> pulsingNodes;
|
||||||
|
|
||||||
std::map<std::shared_ptr<UiNode>, std::vector<ActiveAnim>> nodeActiveAnims;
|
std::map<std::shared_ptr<UiNode>, std::vector<ActiveAnim>> nodeActiveAnims;
|
||||||
std::map<std::pair<std::string, std::string>, std::function<void()>> animCallbacks; // key: (nodeName, animName)
|
std::map<std::pair<std::string, std::string>, std::function<void()>> animCallbacks; // key: (nodeName, animName)
|
||||||
@ -422,6 +464,7 @@ namespace ZL {
|
|||||||
std::vector<std::shared_ptr<UiTextView>> textViews;
|
std::vector<std::shared_ptr<UiTextView>> textViews;
|
||||||
std::vector<std::shared_ptr<UiTextField>> textFields;
|
std::vector<std::shared_ptr<UiTextField>> textFields;
|
||||||
std::vector<std::shared_ptr<UiStaticImage>> staticImages;
|
std::vector<std::shared_ptr<UiStaticImage>> staticImages;
|
||||||
|
std::vector<std::shared_ptr<UiNode>> pulsingNodes;
|
||||||
std::map<int64_t, std::shared_ptr<UiButton>> pressedButtons;
|
std::map<int64_t, std::shared_ptr<UiButton>> pressedButtons;
|
||||||
std::map<int64_t, std::shared_ptr<UiTextButton>> pressedTextButtons;
|
std::map<int64_t, std::shared_ptr<UiTextButton>> pressedTextButtons;
|
||||||
std::map<int64_t, std::shared_ptr<UiSlider>> pressedSliders;
|
std::map<int64_t, std::shared_ptr<UiSlider>> pressedSliders;
|
||||||
|
|||||||
@ -104,6 +104,7 @@ bool DialogueSystem::handlePointerReleased(float x, float y) {
|
|||||||
|
|
||||||
if (advanceDialogue) {
|
if (advanceDialogue) {
|
||||||
runtime.confirmAdvance();
|
runtime.confirmAdvance();
|
||||||
|
if (onDialogueAdvancedCallback) onDialogueAdvancedCallback();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,4 +144,8 @@ void DialogueSystem::stopDialogue() {
|
|||||||
runtime.stop();
|
runtime.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogueSystem::setOnDialogueAdvanced(std::function<void()> cb) {
|
||||||
|
onDialogueAdvancedCallback = std::move(cb);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ZL::Dialogue
|
} // namespace ZL::Dialogue
|
||||||
@ -27,6 +27,7 @@ public:
|
|||||||
void setOnDialogueLineStarted(std::function<void(const std::string&)> cb);
|
void setOnDialogueLineStarted(std::function<void(const std::string&)> cb);
|
||||||
void setOnCutsceneLineStarted(std::function<void(const std::string&)> cb);
|
void setOnCutsceneLineStarted(std::function<void(const std::string&)> cb);
|
||||||
void setOnCutsceneFadeInComplete(std::function<void(const std::string&)> cb);
|
void setOnCutsceneFadeInComplete(std::function<void(const std::string&)> cb);
|
||||||
|
void setOnDialogueAdvanced(std::function<void()> cb);
|
||||||
void stopDialogue();
|
void stopDialogue();
|
||||||
|
|
||||||
bool isActive() const { return runtime.isActive(); }
|
bool isActive() const { return runtime.isActive(); }
|
||||||
@ -39,6 +40,7 @@ private:
|
|||||||
DialogueDatabase database;
|
DialogueDatabase database;
|
||||||
DialogueRuntime runtime;
|
DialogueRuntime runtime;
|
||||||
DialogueOverlay overlay;
|
DialogueOverlay overlay;
|
||||||
|
std::function<void()> onDialogueAdvancedCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZL::Dialogue
|
} // namespace ZL::Dialogue
|
||||||
|
|||||||
@ -7,6 +7,7 @@ namespace ZL {
|
|||||||
void Inventory::addItem(const Item& item) {
|
void Inventory::addItem(const Item& item) {
|
||||||
items.push_back(item);
|
items.push_back(item);
|
||||||
std::cout << "Item added to inventory: " << item.name << std::endl;
|
std::cout << "Item added to inventory: " << item.name << std::endl;
|
||||||
|
if (onItemAdded) onItemAdded(item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inventory::removeItem(const std::string& itemId) {
|
void Inventory::removeItem(const std::string& itemId) {
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace ZL {
|
namespace ZL {
|
||||||
|
|
||||||
@ -28,6 +29,9 @@ namespace ZL {
|
|||||||
bool hasItem(const std::string& itemId) const;
|
bool hasItem(const std::string& itemId) const;
|
||||||
void clear() { items.clear(); }
|
void clear() { items.clear(); }
|
||||||
size_t getCount() const { return items.size(); }
|
size_t getCount() const { return items.size(); }
|
||||||
|
|
||||||
|
// Called whenever an item is added; receives the item id.
|
||||||
|
std::function<void(const std::string&)> onItemAdded;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
Loading…
Reference in New Issue
Block a user