1
+ use std:: default;
2
+
1
3
use crate :: conway;
4
+ use crate :: RunModes ;
5
+ use crate :: UserInterface ;
2
6
use conway:: conway_map;
3
7
use eframe:: egui;
4
8
use egui:: Id ;
5
9
use egui:: LayerId ;
6
10
/// We derive Deserialize/Serialize so we can persist app state on shutdown.
7
11
#[ derive( serde:: Deserialize , serde:: Serialize ) ]
8
12
#[ serde( default ) ] // if we add new fields, give them default values when deserializing old state
9
- pub struct App {
13
+ pub struct ConwaySim {
14
+ // TODO: Move conway_map::Map to its own file, keeping the original implementation of map underneath conway_map, but also create an interface for more generalized behavior
10
15
map : conway:: conway_map:: Map ,
11
16
running : bool ,
12
17
filename : String ,
@@ -20,31 +25,34 @@ pub struct App {
20
25
value : f32 ,
21
26
view_stats : bool ,
22
27
first_run : bool ,
28
+ mode : RunModes ,
23
29
}
24
30
// TODO: implement feature so that the user can click and drag on the main view window to move
25
31
// their view around instead of using sliders, cause sliders are janky as fuck
26
32
27
- impl Default for App {
33
+ //generate documentation
34
+ impl Default for ConwaySim {
28
35
fn default ( ) -> Self {
29
36
let mut map = conway_map:: Map :: new ( ) ;
30
37
map. gen_random ( ) ;
31
38
Self {
32
39
// Example stuff:
33
40
map,
34
41
running : false ,
35
- label : "Hello World! " . to_owned ( ) ,
42
+ label : "Cellular Automata " . to_owned ( ) ,
36
43
filename : "" . to_owned ( ) ,
37
44
rect : None ,
38
45
fps : 0.0 ,
39
46
value : 2.7 ,
40
47
view_stats : false ,
41
48
reset : false ,
42
49
first_run : true ,
50
+ mode : RunModes :: default ( ) ,
43
51
}
44
52
}
45
53
}
46
54
47
- impl App {
55
+ impl ConwaySim {
48
56
/// Called once before the first frame.
49
57
pub fn new ( cc : & eframe:: CreationContext < ' _ > ) -> Self {
50
58
// This is also where you can customize the look and feel of egui using
@@ -58,7 +66,56 @@ impl App {
58
66
Default :: default ( )
59
67
}
60
68
61
- #[ inline]
69
+ fn update_simulation ( & mut self , ctx : & egui:: Context ) {
70
+ egui:: CentralPanel :: default ( ) . show ( ctx, |ui| {
71
+ let gridline_layer: egui:: LayerId =
72
+ LayerId :: new ( egui:: Order :: Foreground , Id :: from ( "gridlines" ) ) ;
73
+ let painter = egui:: Painter :: new (
74
+ ui. ctx ( ) . clone ( ) ,
75
+ ui. layer_id ( ) ,
76
+ ui. available_rect_before_wrap ( ) ,
77
+ ) ;
78
+ let line_painter = egui:: Painter :: new (
79
+ ui. ctx ( ) . clone ( ) ,
80
+ gridline_layer,
81
+ ui. available_rect_before_wrap ( ) ,
82
+ ) ;
83
+ ui. expand_to_include_rect ( painter. clip_rect ( ) ) ;
84
+ ui. expand_to_include_rect ( line_painter. clip_rect ( ) ) ;
85
+ self . rect = Some ( painter. clip_rect ( ) ) ;
86
+ let mut shapes: Vec < egui:: Shape > = if self . map . light_mode {
87
+ vec ! [ egui:: Shape :: rect_filled(
88
+ self . rect. unwrap( ) ,
89
+ egui:: Rounding :: ZERO ,
90
+ egui:: Color32 :: WHITE ,
91
+ ) ]
92
+ } else {
93
+ vec ! [ egui:: Shape :: rect_filled(
94
+ self . rect. unwrap( ) ,
95
+ egui:: Rounding :: ZERO ,
96
+ egui:: Color32 :: BLACK ,
97
+ ) ]
98
+ } ;
99
+ self . map . generate_cells ( & mut shapes, self . rect . unwrap ( ) ) ;
100
+ painter. extend ( shapes) ;
101
+ if self . running {
102
+ self . map . update ( ) ;
103
+ }
104
+ if self . map . lines {
105
+ let mut lines = vec ! [ egui:: Shape :: Noop ] ;
106
+ self . map . draw_lines ( self . rect . unwrap ( ) , & mut lines) ;
107
+ line_painter. extend ( lines) ;
108
+ }
109
+ } ) ;
110
+
111
+ if self . view_stats {
112
+ egui:: Window :: new ( "Stats" ) . show ( ctx, |ui| {
113
+ ui. label ( "TODO :(" ) ;
114
+ } ) ;
115
+ }
116
+ }
117
+ }
118
+ impl UserInterface for ConwaySim {
62
119
fn update_side_panel ( & mut self , ctx : & egui:: Context ) {
63
120
egui:: SidePanel :: left ( "Menu" ) . show ( ctx, |ui| {
64
121
ui. add (
@@ -81,21 +138,21 @@ impl App {
81
138
. text ( "FPS" ) ,
82
139
) ;
83
140
self . map . update_speed ( ) ;
84
- // BUG: below sliders are bugged, if one of the viewports is updated, say, the x axis, the vertical
85
- // lines will not move along with the horizontal ones, leading to a realy weird effect, and vice
86
- // versa for the y axis, with the other lines not moving, while the vertical ones will move
87
- // ui.add(
88
- // egui::Slider::new(&mut self.map.x_axis, -1000..=1000)
89
- // .step_by(1.0)
90
- // .orientation(egui::SliderOrientation::Horizontal)
91
- // .text("X Axis"),
92
- // );
93
- // ui.add(
94
- // egui::Slider::new(&mut self.map.y_axis, -1000..=1000)
95
- // .step_by(1.0)
96
- // .orientation(egui::SliderOrientation::Horizontal)
97
- // .text("Y Axis"),
98
- // );
141
+ // BUG: below sliders are bugged, if one of the viewports is updated, say, the x axis, the vertical
142
+ // lines will not move along with the horizontal ones, leading to a realy weird effect, and vice
143
+ // versa for the y axis, with the other lines not moving, while the vertical ones will move
144
+ // ui.add(
145
+ // egui::Slider::new(&mut self.map.x_axis, -1000..=1000)
146
+ // .step_by(1.0)
147
+ // .orientation(egui::SliderOrientation::Horizontal)
148
+ // .text("X Axis"),
149
+ // );
150
+ // ui.add(
151
+ // egui::Slider::new(&mut self.map.y_axis, -1000..=1000)
152
+ // .step_by(1.0)
153
+ // .orientation(egui::SliderOrientation::Horizontal)
154
+ // .text("Y Axis"),
155
+ // );
99
156
ui. add (
100
157
egui:: Slider :: new ( & mut self . map . map_size , 10 ..=500 )
101
158
. step_by ( 1.0 )
@@ -143,7 +200,11 @@ impl App {
143
200
self . map . clear ( ) ;
144
201
self . running = false ;
145
202
}
146
- if ui. add ( egui:: Button :: new ( "Revert" ) ) . on_hover_text ( "Revert to the saved state" ) . clicked ( ) {
203
+ if ui
204
+ . add ( egui:: Button :: new ( "Revert" ) )
205
+ . on_hover_text ( "Revert to the saved state" )
206
+ . clicked ( )
207
+ {
147
208
self . map . restore_initial_state ( ) ;
148
209
self . running = false ;
149
210
}
@@ -156,88 +217,39 @@ impl App {
156
217
{
157
218
self . map . lines = !self . map . lines ;
158
219
}
159
- if ui. add ( egui:: Button :: new ( "ReCenter" ) ) . on_hover_text ( "Recenter the Grid" ) . clicked ( ) {
220
+ if ui
221
+ . add ( egui:: Button :: new ( "ReCenter" ) )
222
+ . on_hover_text ( "Recenter the Grid" )
223
+ . clicked ( )
224
+ {
160
225
self . map . center_cells ( self . rect . unwrap ( ) ) ;
161
-
162
226
}
163
227
} ) ;
164
228
} ) ;
165
229
}
166
230
167
- #[ inline]
168
- fn update_menu_bar ( & self , ctx : & egui:: Context ) {
169
- egui:: TopBottomPanel :: top ( "top_panel" ) . show ( ctx, |ui| {
170
- // The top panel is often a good place for a menu bar:
171
-
172
- egui:: menu:: bar ( ui, |ui| {
173
- // NOTE: no File->Quit on web pages!
174
- let is_web = cfg ! ( target_arch = "wasm32" ) ;
175
- if !is_web {
176
- ui. menu_button ( "File" , |ui| {
177
- if ui. button ( "Quit" ) . clicked ( ) {
178
- ctx. send_viewport_cmd ( egui:: ViewportCommand :: Close ) ;
179
- }
180
- } ) ;
181
- ui. add_space ( 16.0 ) ;
182
- }
183
- egui:: widgets:: global_dark_light_mode_buttons ( ui) ;
184
- } ) ;
185
- } ) ;
186
- }
187
-
188
- #[ inline]
189
- fn update_simulation ( & mut self , ctx : & egui:: Context ) {
190
- egui:: CentralPanel :: default ( ) . show ( ctx, |ui| {
191
- let gridline_layer: egui:: LayerId =
192
- LayerId :: new ( egui:: Order :: Foreground , Id :: from ( "gridlines" ) ) ;
193
- let painter = egui:: Painter :: new (
194
- ui. ctx ( ) . clone ( ) ,
195
- ui. layer_id ( ) ,
196
- ui. available_rect_before_wrap ( ) ,
197
- ) ;
198
- let line_painter = egui:: Painter :: new (
199
- ui. ctx ( ) . clone ( ) ,
200
- gridline_layer,
201
- ui. available_rect_before_wrap ( ) ,
202
- ) ;
203
- ui. expand_to_include_rect ( painter. clip_rect ( ) ) ;
204
- ui. expand_to_include_rect ( line_painter. clip_rect ( ) ) ;
205
- self . rect = Some ( painter. clip_rect ( ) ) ;
206
- let mut shapes: Vec < egui:: Shape > =
207
- if self . map . light_mode {
208
- vec ! [ egui:: Shape :: rect_filled(
209
- self . rect. unwrap( ) ,
210
- egui:: Rounding :: ZERO ,
211
- egui:: Color32 :: WHITE ,
212
- ) ]
213
- } else {
214
- vec ! [ egui:: Shape :: rect_filled(
215
- self . rect. unwrap( ) ,
216
- egui:: Rounding :: ZERO ,
217
- egui:: Color32 :: BLACK ,
218
- ) ]
219
- } ;
220
- self . map . generate_cells ( & mut shapes, self . rect . unwrap ( ) ) ;
221
- painter. extend ( shapes) ;
222
- if self . running {
223
- self . map . update ( ) ;
224
- }
225
- if self . map . lines {
226
- let mut lines = vec ! [ egui:: Shape :: Noop ] ;
227
- self . map . draw_lines ( self . rect . unwrap ( ) , & mut lines) ;
228
- line_painter. extend ( lines) ;
229
- }
230
- } ) ;
231
+ fn update_menu_bar ( & self , ctx : & egui:: Context ) {
232
+ egui:: TopBottomPanel :: top ( "top_panel" ) . show ( ctx, |ui| {
233
+ // The top panel is often a good place for a menu bar:
231
234
232
- if self . view_stats {
233
- egui:: Window :: new ( "Stats" ) . show ( ctx, |ui| {
234
- ui. label ( "TODO :(" ) ;
235
- } ) ;
236
- }
237
- }
235
+ egui:: menu:: bar ( ui, |ui| {
236
+ // NOTE: no File->Quit on web pages!
237
+ let is_web = cfg ! ( target_arch = "wasm32" ) ;
238
+ if !is_web {
239
+ ui. menu_button ( "File" , |ui| {
240
+ if ui. button ( "Quit" ) . clicked ( ) {
241
+ ctx. send_viewport_cmd ( egui:: ViewportCommand :: Close ) ;
242
+ }
243
+ } ) ;
244
+ ui. add_space ( 16.0 ) ;
245
+ }
246
+ egui:: widgets:: global_dark_light_mode_buttons ( ui) ;
247
+ } ) ;
248
+ } ) ;
249
+ }
238
250
}
239
251
240
- impl eframe:: App for App {
252
+ impl eframe:: App for ConwaySim {
241
253
/// Called by the frame work to save state before shutdown.
242
254
fn save ( & mut self , storage : & mut dyn eframe:: Storage ) {
243
255
eframe:: set_value ( storage, eframe:: APP_KEY , self ) ;
0 commit comments