Skip to content

Commit b49156b

Browse files
committed
Add permission panel for Android camera access
- Show permission panel when camera permission is not granted - Use correct permission string (android.permission.CAMERA) - Wait for permission result using on_request_permissions_result signal
1 parent ee8893d commit b49156b

File tree

2 files changed

+111
-30
lines changed

2 files changed

+111
-30
lines changed

misc/camera_feed/camerafeed.gd

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ enum ColorRange { FULL = 0, VIDEO = 1 }
1818
@onready var mirror_list := $DrawerContainer/Drawer/DrawerContent/VBoxContainer/MirrorList
1919
@onready var start_or_stop_button := $DrawerContainer/Drawer/DrawerContent/VBoxContainer/ButtonContainer/StartOrStopButton
2020
@onready var reload_button := $DrawerContainer/Drawer/DrawerContent/VBoxContainer/ButtonContainer/ReloadButton
21+
@onready var permission_panel := $PermissionPanel
2122

2223
var camera_feed: CameraFeed
2324
var _initialized := false
@@ -30,6 +31,14 @@ func _ready() -> void:
3031
_is_mobile = _check_is_mobile()
3132
_adjust_ui()
3233
_setup_mirror_list()
34+
35+
# Check camera permission on Android
36+
if OS.get_name() == "Android":
37+
var granted := await _request_camera_permission()
38+
if not granted:
39+
permission_panel.visible = true
40+
return
41+
3342
_reload_camera_list()
3443
_initialized = true
3544

@@ -83,13 +92,6 @@ func _reload_camera_list() -> void:
8392
camera_list.clear()
8493
format_list.clear()
8594

86-
# Request camera permission on Android
87-
if OS.get_name() == "Android":
88-
if not "CAMERA" in OS.get_granted_permissions():
89-
if not OS.request_permission("CAMERA"):
90-
print("CAMERA permission not granted")
91-
return
92-
9395
if CameraServer.is_monitoring_feeds:
9496
CameraServer.monitoring_feeds = false
9597
await get_tree().process_frame
@@ -412,6 +414,32 @@ func _on_mirror_list_item_selected(_index: int) -> void:
412414
_update_scene_transform()
413415

414416

417+
func _request_camera_permission() -> bool:
418+
const CAMERA_PERMISSION := "android.permission.CAMERA"
419+
420+
if CAMERA_PERMISSION in OS.get_granted_permissions():
421+
return true
422+
423+
var already_granted := OS.request_permission("CAMERA")
424+
if already_granted:
425+
return true
426+
427+
while true:
428+
var result = await get_tree().on_request_permissions_result
429+
# result = [permission_name: String, granted: bool]
430+
if result[0] == CAMERA_PERMISSION:
431+
return result[1]
432+
433+
return false # Unreachable
434+
435+
436+
func _on_permission_button_pressed() -> void:
437+
if await _request_camera_permission():
438+
permission_panel.visible = false
439+
_reload_camera_list()
440+
_initialized = true
441+
442+
415443
func _notification(what: int) -> void:
416444
if not _initialized:
417445
return

misc/camera_feed/camerafeed.tscn

Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[gd_scene load_steps=11 format=3 uid="uid://oiv4p8ii3am4"]
1+
[gd_scene format=3 uid="uid://oiv4p8ii3am4"]
22

33
[ext_resource type="Script" uid="uid://dxaoavn781kxe" path="res://camerafeed.gd" id="1_fuswq"]
44
[ext_resource type="Shader" uid="uid://dhjh7s6i7jnlp" path="res://ycbcr_to_rgb.gdshader" id="2_0uyi5"]
@@ -42,7 +42,21 @@ corner_radius_top_right = 10
4242
corner_radius_bottom_right = 10
4343
corner_radius_bottom_left = 10
4444

45-
[node name="CameraApp" type="Control"]
45+
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_permission_normal"]
46+
bg_color = Color(0.2, 0.5, 0.8, 1)
47+
corner_radius_top_left = 15
48+
corner_radius_top_right = 15
49+
corner_radius_bottom_right = 15
50+
corner_radius_bottom_left = 15
51+
52+
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_permission_hover"]
53+
bg_color = Color(0.3, 0.6, 0.9, 1)
54+
corner_radius_top_left = 15
55+
corner_radius_top_right = 15
56+
corner_radius_bottom_right = 15
57+
corner_radius_bottom_left = 15
58+
59+
[node name="CameraApp" type="Control" unique_id=418879243]
4660
layout_mode = 3
4761
anchors_preset = 15
4862
anchor_right = 1.0
@@ -51,7 +65,7 @@ grow_horizontal = 2
5165
grow_vertical = 2
5266
script = ExtResource("1_fuswq")
5367

54-
[node name="Background" type="ColorRect" parent="."]
68+
[node name="Background" type="ColorRect" parent="." unique_id=800907370]
5569
layout_mode = 1
5670
anchors_preset = 15
5771
anchor_right = 1.0
@@ -60,14 +74,14 @@ grow_horizontal = 2
6074
grow_vertical = 2
6175
color = Color(0, 0, 0, 1)
6276

63-
[node name="CameraDisplay" type="Control" parent="."]
77+
[node name="CameraDisplay" type="Control" parent="." unique_id=1987229930]
6478
anchors_preset = 0
6579
offset_left = 20.0
6680
offset_top = 20.0
6781
offset_right = 700.0
6882
offset_bottom = 1260.0
6983

70-
[node name="MirrorContainer" type="Control" parent="CameraDisplay"]
84+
[node name="MirrorContainer" type="Control" parent="CameraDisplay" unique_id=1850494703]
7185
layout_mode = 1
7286
anchors_preset = 15
7387
anchor_right = 1.0
@@ -76,7 +90,7 @@ grow_horizontal = 2
7690
grow_vertical = 2
7791
mouse_filter = 2
7892

79-
[node name="RotationContainer" type="Control" parent="CameraDisplay/MirrorContainer"]
93+
[node name="RotationContainer" type="Control" parent="CameraDisplay/MirrorContainer" unique_id=551260684]
8094
layout_mode = 1
8195
anchors_preset = 15
8296
anchor_right = 1.0
@@ -85,7 +99,7 @@ grow_horizontal = 2
8599
grow_vertical = 2
86100
mouse_filter = 2
87101

88-
[node name="AspectContainer" type="AspectRatioContainer" parent="CameraDisplay/MirrorContainer/RotationContainer"]
102+
[node name="AspectContainer" type="AspectRatioContainer" parent="CameraDisplay/MirrorContainer/RotationContainer" unique_id=1911510357]
89103
layout_mode = 1
90104
anchors_preset = 15
91105
anchor_right = 1.0
@@ -94,12 +108,12 @@ grow_horizontal = 2
94108
grow_vertical = 2
95109
stretch_mode = 3
96110

97-
[node name="CameraPreview" type="TextureRect" parent="CameraDisplay/MirrorContainer/RotationContainer/AspectContainer"]
111+
[node name="CameraPreview" type="TextureRect" parent="CameraDisplay/MirrorContainer/RotationContainer/AspectContainer" unique_id=231281310]
98112
material = SubResource("ShaderMaterial_lgiw1")
99113
layout_mode = 2
100114
expand_mode = 1
101115

102-
[node name="DrawerContainer" type="Control" parent="."]
116+
[node name="DrawerContainer" type="Control" parent="." unique_id=2120195199]
103117
modulate = Color(1, 1, 1, 0.5019608)
104118
layout_mode = 1
105119
anchors_preset = 10
@@ -108,7 +122,7 @@ offset_top = 160.0
108122
offset_bottom = 160.0
109123
grow_horizontal = 2
110124

111-
[node name="Drawer" type="PanelContainer" parent="DrawerContainer"]
125+
[node name="Drawer" type="PanelContainer" parent="DrawerContainer" unique_id=617236126]
112126
layout_mode = 1
113127
anchors_preset = 15
114128
anchor_right = 1.0
@@ -117,22 +131,22 @@ grow_horizontal = 2
117131
grow_vertical = 2
118132
theme_override_styles/panel = SubResource("StyleBoxFlat_1")
119133

120-
[node name="DrawerContent" type="MarginContainer" parent="DrawerContainer/Drawer"]
134+
[node name="DrawerContent" type="MarginContainer" parent="DrawerContainer/Drawer" unique_id=93200021]
121135
layout_mode = 2
122136
theme_override_constants/margin_left = 20
123137
theme_override_constants/margin_top = 20
124138
theme_override_constants/margin_right = 20
125139
theme_override_constants/margin_bottom = 20
126140

127-
[node name="VBoxContainer" type="VBoxContainer" parent="DrawerContainer/Drawer/DrawerContent"]
141+
[node name="VBoxContainer" type="VBoxContainer" parent="DrawerContainer/Drawer/DrawerContent" unique_id=687341086]
128142
layout_mode = 2
129143
theme_override_constants/separation = 15
130144

131-
[node name="HandleBar" type="Control" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer"]
145+
[node name="HandleBar" type="Control" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer" unique_id=1706428189]
132146
custom_minimum_size = Vector2(0, 20)
133147
layout_mode = 2
134148

135-
[node name="Bar" type="ColorRect" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer/HandleBar"]
149+
[node name="Bar" type="ColorRect" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer/HandleBar" unique_id=663312817]
136150
layout_mode = 1
137151
anchors_preset = 8
138152
anchor_left = 0.5
@@ -147,11 +161,11 @@ grow_horizontal = 2
147161
grow_vertical = 2
148162
color = Color(0.5, 0.5, 0.5, 1)
149163

150-
[node name="ButtonContainer" type="HBoxContainer" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer"]
164+
[node name="ButtonContainer" type="HBoxContainer" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer" unique_id=422251785]
151165
layout_mode = 2
152166
theme_override_constants/separation = 10
153167

154-
[node name="StartOrStopButton" type="Button" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer/ButtonContainer"]
168+
[node name="StartOrStopButton" type="Button" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer/ButtonContainer" unique_id=167818591]
155169
custom_minimum_size = Vector2(0, 50)
156170
layout_mode = 2
157171
size_flags_horizontal = 3
@@ -160,7 +174,7 @@ theme_override_styles/pressed = SubResource("StyleBoxFlat_2")
160174
theme_override_styles/hover = SubResource("StyleBoxFlat_3")
161175
text = "Stop"
162176

163-
[node name="ReloadButton" type="Button" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer/ButtonContainer"]
177+
[node name="ReloadButton" type="Button" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer/ButtonContainer" unique_id=1289133198]
164178
custom_minimum_size = Vector2(0, 50)
165179
layout_mode = 2
166180
size_flags_horizontal = 3
@@ -169,32 +183,71 @@ theme_override_styles/pressed = SubResource("StyleBoxFlat_2")
169183
theme_override_styles/hover = SubResource("StyleBoxFlat_3")
170184
text = "Reload"
171185

172-
[node name="CameraLabel" type="Label" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer"]
186+
[node name="CameraLabel" type="Label" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer" unique_id=1215480226]
173187
layout_mode = 2
174188
text = "Camera"
175189

176-
[node name="CameraList" type="OptionButton" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer"]
190+
[node name="CameraList" type="OptionButton" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer" unique_id=1914948274]
177191
custom_minimum_size = Vector2(0, 40)
178192
layout_mode = 2
179193

180-
[node name="FormatLabel" type="Label" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer"]
194+
[node name="FormatLabel" type="Label" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer" unique_id=1679243280]
181195
layout_mode = 2
182196
text = "Format"
183197

184-
[node name="FormatList" type="OptionButton" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer"]
198+
[node name="FormatList" type="OptionButton" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer" unique_id=7868013]
185199
custom_minimum_size = Vector2(0, 40)
186200
layout_mode = 2
187201

188-
[node name="MirrorLabel" type="Label" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer"]
202+
[node name="MirrorLabel" type="Label" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer" unique_id=1556455286]
189203
layout_mode = 2
190204
text = "Mirror"
191205

192-
[node name="MirrorList" type="OptionButton" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer"]
206+
[node name="MirrorList" type="OptionButton" parent="DrawerContainer/Drawer/DrawerContent/VBoxContainer" unique_id=1476419984]
193207
custom_minimum_size = Vector2(0, 40)
194208
layout_mode = 2
195209

210+
[node name="PermissionPanel" type="ColorRect" parent="."]
211+
visible = false
212+
layout_mode = 1
213+
anchors_preset = 15
214+
anchor_right = 1.0
215+
anchor_bottom = 1.0
216+
grow_horizontal = 2
217+
grow_vertical = 2
218+
color = Color(0, 0, 0, 0.85)
219+
220+
[node name="CenterContainer" type="CenterContainer" parent="PermissionPanel"]
221+
layout_mode = 1
222+
anchors_preset = 15
223+
anchor_right = 1.0
224+
anchor_bottom = 1.0
225+
grow_horizontal = 2
226+
grow_vertical = 2
227+
mouse_filter = 2
228+
229+
[node name="VBoxContainer" type="VBoxContainer" parent="PermissionPanel/CenterContainer"]
230+
layout_mode = 2
231+
theme_override_constants/separation = 30
232+
mouse_filter = 2
233+
234+
[node name="Label" type="Label" parent="PermissionPanel/CenterContainer/VBoxContainer"]
235+
layout_mode = 2
236+
text = "Camera permission is required"
237+
horizontal_alignment = 1
238+
239+
[node name="PermissionButton" type="Button" parent="PermissionPanel/CenterContainer/VBoxContainer"]
240+
custom_minimum_size = Vector2(200, 60)
241+
layout_mode = 2
242+
size_flags_horizontal = 4
243+
theme_override_styles/normal = SubResource("StyleBoxFlat_permission_normal")
244+
theme_override_styles/pressed = SubResource("StyleBoxFlat_permission_normal")
245+
theme_override_styles/hover = SubResource("StyleBoxFlat_permission_hover")
246+
text = "Grant Permission"
247+
196248
[connection signal="pressed" from="DrawerContainer/Drawer/DrawerContent/VBoxContainer/ButtonContainer/StartOrStopButton" to="." method="_on_start_or_stop_button_pressed"]
197249
[connection signal="pressed" from="DrawerContainer/Drawer/DrawerContent/VBoxContainer/ButtonContainer/ReloadButton" to="." method="_on_reload_button_pressed"]
198250
[connection signal="item_selected" from="DrawerContainer/Drawer/DrawerContent/VBoxContainer/CameraList" to="." method="_on_camera_list_item_selected"]
199251
[connection signal="item_selected" from="DrawerContainer/Drawer/DrawerContent/VBoxContainer/FormatList" to="." method="_on_format_list_item_selected"]
200252
[connection signal="item_selected" from="DrawerContainer/Drawer/DrawerContent/VBoxContainer/MirrorList" to="." method="_on_mirror_list_item_selected"]
253+
[connection signal="pressed" from="PermissionPanel/CenterContainer/VBoxContainer/PermissionButton" to="." method="_on_permission_button_pressed"]

0 commit comments

Comments
 (0)