1
1
use std:: io:: ErrorKind ;
2
+ use std:: path:: Path ;
2
3
3
4
use bevy:: { prelude:: * , ui:: RelativeCursorPosition } ;
4
5
use bevy_editor:: project:: { run_project, set_project_list, templates:: Templates , ProjectInfo } ;
@@ -13,6 +14,66 @@ use crate::ProjectInfoList;
13
14
#[ require( Node ) ]
14
15
pub struct ProjectList ;
15
16
17
+ /// Component for notification popup
18
+ #[ derive( Component ) ]
19
+ pub struct NotificationPopup {
20
+ pub timer : Timer ,
21
+ }
22
+
23
+ /// System to handle notification popups
24
+ pub fn handle_notification_popups (
25
+ mut commands : Commands ,
26
+ time : Res < Time > ,
27
+ mut query : Query < ( Entity , & mut NotificationPopup ) > ,
28
+ ) {
29
+ for ( entity, mut popup) in query. iter_mut ( ) {
30
+ popup. timer . tick ( time. delta ( ) ) ;
31
+ if popup. timer . finished ( ) {
32
+ commands. entity ( entity) . despawn ( ) ;
33
+ }
34
+ }
35
+ }
36
+
37
+ /// Spawn a notification popup with a message
38
+ pub fn spawn_notification_popup ( commands : & mut Commands , theme : & Theme , message : & str ) -> Entity {
39
+ commands
40
+ . spawn ( (
41
+ Node {
42
+ position_type : PositionType :: Absolute ,
43
+ left : Val :: Px ( 0.0 ) ,
44
+ right : Val :: Px ( 0.0 ) ,
45
+ top : Val :: Px ( 50.0 ) ,
46
+ margin : UiRect :: horizontal ( Val :: Auto ) ,
47
+ padding : UiRect :: all ( Val :: Px ( 12.0 ) ) ,
48
+ width : Val :: Auto ,
49
+ height : Val :: Auto ,
50
+ align_items : AlignItems :: Center ,
51
+ justify_content : JustifyContent :: Center ,
52
+ ..default ( )
53
+ } ,
54
+ BackgroundColor ( Color :: srgba ( 0.1 , 0.1 , 0.1 , 0.9 ) ) ,
55
+ BorderRadius :: all ( Val :: Px ( 8.0 ) ) ,
56
+ NotificationPopup {
57
+ timer : Timer :: from_seconds ( 3.0 , TimerMode :: Once ) ,
58
+ } ,
59
+ ) )
60
+ . with_child ( (
61
+ Text :: new ( message. to_string ( ) ) ,
62
+ TextFont {
63
+ font : theme. text . font . clone ( ) ,
64
+ font_size : 18.0 ,
65
+ ..default ( )
66
+ } ,
67
+ TextColor ( Color :: WHITE ) ,
68
+ Outline {
69
+ width : Val :: Px ( 0.5 ) ,
70
+ color : Color :: BLACK ,
71
+ ..default ( )
72
+ } ,
73
+ ) )
74
+ . id ( )
75
+ }
76
+
16
77
pub fn setup (
17
78
mut commands : Commands ,
18
79
theme : Res < Theme > ,
@@ -140,7 +201,8 @@ pub(crate) fn spawn_project_node<'a>(
140
201
query_children : Query < & Children > ,
141
202
query_text : Query < & Text > ,
142
203
mut exit : EventWriter < AppExit > ,
143
- mut project_list : ResMut < ProjectInfoList > | {
204
+ mut project_list : ResMut < ProjectInfoList > ,
205
+ theme : Res < Theme > | {
144
206
let project = {
145
207
let text = {
146
208
let project_entity = trigger. target ( ) ;
@@ -165,6 +227,25 @@ pub(crate) fn spawn_project_node<'a>(
165
227
. clone ( )
166
228
} ;
167
229
230
+ // Check if project directory exists before trying to run it
231
+ if !Path :: new ( & project. path ) . exists ( ) {
232
+ // Show notification popup
233
+ let project_name = project. name ( ) . unwrap_or_else ( || "Unknown" . to_string ( ) ) ;
234
+ spawn_notification_popup (
235
+ & mut commands,
236
+ & theme,
237
+ & format ! ( "Project not found: '{project_name}'" ) ,
238
+ ) ;
239
+ // Remove project from list
240
+ project_list. 0 . retain ( |p| p. path != project. path ) ;
241
+ set_project_list ( project_list. 0 . clone ( ) ) ;
242
+ // Remove project node from UI
243
+ let project_entity = trigger. target ( ) ;
244
+ commands. entity ( project_entity) . despawn ( ) ;
245
+ return ;
246
+ }
247
+
248
+ // Project exists, try to run it
168
249
match run_project ( & project) {
169
250
Ok ( _) => {
170
251
exit. send ( AppExit :: Success ) ;
@@ -173,14 +254,28 @@ pub(crate) fn spawn_project_node<'a>(
173
254
error ! ( "Failed to run project: {:?}" , error) ;
174
255
match error. kind ( ) {
175
256
ErrorKind :: NotFound | ErrorKind :: InvalidData => {
257
+ // Show notification popup
258
+ let project_name = project. name ( ) . unwrap_or_else ( || "Unknown" . to_string ( ) ) ;
259
+ spawn_notification_popup (
260
+ & mut commands,
261
+ & theme,
262
+ & format ! ( "Failed to run project: '{project_name}'" ) ,
263
+ ) ;
176
264
// Remove project from list
177
265
project_list. 0 . retain ( |p| p. path != project. path ) ;
178
266
set_project_list ( project_list. 0 . clone ( ) ) ;
179
267
// Remove project node from UI
180
268
let project_entity = trigger. target ( ) ;
181
269
commands. entity ( project_entity) . despawn ( ) ;
182
270
}
183
- _ => { }
271
+ _ => {
272
+ // Show generic error notification
273
+ spawn_notification_popup (
274
+ & mut commands,
275
+ & theme,
276
+ & format ! ( "Error running project: '{error}'" ) ,
277
+ ) ;
278
+ }
184
279
}
185
280
}
186
281
}
0 commit comments