@@ -74,6 +74,32 @@ impl ImageOperation for Load {
7474 }
7575}
7676
77+ /// Adjusts the contrast of the image.
78+ #[ derive( Debug , Clone , Reflect ) ]
79+ #[ reflect( ImageOperation ) ]
80+ struct AdjustContrast {
81+ amount : f32 ,
82+ }
83+
84+ impl ImageOperation for AdjustContrast {
85+ fn apply ( & self , ctx : & mut ImageOperationContext < ' _ > ) {
86+ ctx. current = ctx. current . adjust_contrast ( self . amount ) ;
87+ }
88+ }
89+
90+ /// Adjusts the brightness of the image.
91+ #[ derive( Debug , Clone , Reflect ) ]
92+ #[ reflect( ImageOperation ) ]
93+ struct Brighten {
94+ amount : i32 ,
95+ }
96+
97+ impl ImageOperation for Brighten {
98+ fn apply ( & self , ctx : & mut ImageOperationContext < ' _ > ) {
99+ ctx. current = ctx. current . brighten ( self . amount ) ;
100+ }
101+ }
102+
77103/// Inverts all pixels in the image.
78104#[ derive( Debug , Clone , Reflect ) ]
79105#[ reflect( ImageOperation ) ]
@@ -99,7 +125,74 @@ impl ImageOperation for Blur {
99125 }
100126}
101127
102- // Deserialization logic
128+ // All types that we want to be able to deserialize must be present in the type
129+ // registry.
130+ fn register_op_types ( app : & mut App ) {
131+ app. register_type :: < Load > ( )
132+ . register_type :: < AdjustContrast > ( )
133+ . register_type :: < Brighten > ( )
134+ . register_type :: < Invert > ( )
135+ . register_type :: < Blur > ( ) ;
136+ }
137+
138+ // Asset loader implementation
139+
140+ #[ derive( Debug ) ]
141+ struct ImagePipelineLoader {
142+ type_registry : TypeRegistryArc ,
143+ }
144+
145+ #[ derive( Debug , Error ) ]
146+ enum ImagePipelineLoaderError {
147+ #[ error( "failed to read bytes" ) ]
148+ ReadBytes ( #[ from] io:: Error ) ,
149+ #[ error( "failed to make RON deserializer" ) ]
150+ MakeRonDeserializer ( #[ from] ron:: error:: SpannedError ) ,
151+ #[ error( "failed to parse RON: {0:?}" ) ]
152+ ParseRon ( #[ from] ron:: Error ) ,
153+ }
154+
155+ impl FromWorld for ImagePipelineLoader {
156+ fn from_world ( world : & mut World ) -> Self {
157+ let type_registry = world. resource :: < AppTypeRegistry > ( ) ;
158+ Self {
159+ type_registry : type_registry. 0 . clone ( ) ,
160+ }
161+ }
162+ }
163+
164+ impl AssetLoader for ImagePipelineLoader {
165+ type Asset = ImagePipeline ;
166+ type Settings = ( ) ;
167+ type Error = ImagePipelineLoaderError ;
168+
169+ fn extensions ( & self ) -> & [ & str ] {
170+ & [ "imgpipeline.ron" ]
171+ }
172+
173+ async fn load (
174+ & self ,
175+ reader : & mut dyn Reader ,
176+ _settings : & Self :: Settings ,
177+ load_context : & mut LoadContext < ' _ > ,
178+ ) -> Result < Self :: Asset , Self :: Error > {
179+ let mut bytes = Vec :: new ( ) ;
180+ reader. read_to_end ( & mut bytes) . await ?;
181+
182+ let mut ron_deserializer = ron:: Deserializer :: from_bytes ( & bytes) ?;
183+ // Put this into its own block so that the `read()` lock isn't held for
184+ // the entire scope.
185+ let pipeline = {
186+ ImagePipelineDeserializer {
187+ type_registry : & self . type_registry . read ( ) ,
188+ load_context,
189+ }
190+ . deserialize ( & mut ron_deserializer)
191+ } ?;
192+
193+ Ok ( pipeline)
194+ }
195+ }
103196
104197/// Deserializes an [`ImagePipeline`].
105198struct ImagePipelineDeserializer < ' a , ' b > {
@@ -265,77 +358,18 @@ impl<'de> DeserializeSeed<'de> for ImagePipelineDeserializer<'_, '_> {
265358 }
266359}
267360
268- // Asset loader implementation
269-
270- #[ derive( Debug ) ]
271- struct ImagePipelineLoader {
272- type_registry : TypeRegistryArc ,
273- }
274-
275- #[ derive( Debug , Error ) ]
276- enum ImagePipelineLoaderError {
277- #[ error( "failed to read bytes" ) ]
278- ReadBytes ( #[ from] io:: Error ) ,
279- #[ error( "failed to make RON deserializer" ) ]
280- MakeRonDeserializer ( #[ from] ron:: error:: SpannedError ) ,
281- #[ error( "failed to parse RON: {0:?}" ) ]
282- ParseRon ( #[ from] ron:: Error ) ,
283- }
284-
285- impl FromWorld for ImagePipelineLoader {
286- fn from_world ( world : & mut World ) -> Self {
287- let type_registry = world. resource :: < AppTypeRegistry > ( ) ;
288- Self {
289- type_registry : type_registry. 0 . clone ( ) ,
290- }
291- }
292- }
293-
294- impl AssetLoader for ImagePipelineLoader {
295- type Asset = ImagePipeline ;
296- type Settings = ( ) ;
297- type Error = ImagePipelineLoaderError ;
298-
299- fn extensions ( & self ) -> & [ & str ] {
300- & [ "imgpipeline.ron" ]
301- }
302-
303- async fn load (
304- & self ,
305- reader : & mut dyn Reader ,
306- _settings : & Self :: Settings ,
307- load_context : & mut LoadContext < ' _ > ,
308- ) -> Result < Self :: Asset , Self :: Error > {
309- let mut bytes = Vec :: new ( ) ;
310- reader. read_to_end ( & mut bytes) . await ?;
311-
312- let mut ron_deserializer = ron:: Deserializer :: from_bytes ( & bytes) ?;
313- // Put this into its own block so that the `read()` lock isn't held for
314- // the entire scope.
315- let pipeline = {
316- ImagePipelineDeserializer {
317- type_registry : & self . type_registry . read ( ) ,
318- load_context,
319- }
320- . deserialize ( & mut ron_deserializer)
321- } ?;
322-
323- Ok ( pipeline)
324- }
325- }
326-
327361// App logic
328362
329363fn main ( ) -> AppExit {
330- App :: new ( )
331- . add_plugins ( DefaultPlugins )
364+ let mut app = App :: new ( ) ;
365+ app . add_plugins ( DefaultPlugins )
332366 . init_asset :: < ImagePipeline > ( )
333367 . init_asset_loader :: < ImagePipelineLoader > ( )
334- . init_resource :: < DemoImagePipeline > ( )
335- . register_type :: < Load > ( )
336- . register_type :: < Invert > ( )
337- . register_type :: < Blur > ( )
338- . add_systems ( Startup , setup)
368+ . init_resource :: < DemoImagePipeline > ( ) ;
369+
370+ register_op_types ( & mut app ) ;
371+
372+ app . add_systems ( Startup , setup)
339373 . add_systems ( Update , make_demo_image)
340374 . run ( )
341375}
0 commit comments