Skip to main content

elicit_bevy/
render_plugin.rs

1//! `BevyRenderPlugin` — core render/material descriptor codegen tools.
2//!
3//! This first render slice focuses on the high-value Bevy 0.18 render building
4//! blocks that agents commonly need to assemble scenes and apps:
5//!
6//! - `StandardMaterial`
7//! - ambient/directional/point/spot lights
8//! - `RenderTarget`
9//! - camera spawn tuples for 2D and 3D
10//! - `Tonemapping` and `AlphaMode` selectors
11
12use elicitation::emit_code::{CrateDep, EmitCode, ToCodeLiteral};
13use elicitation::{
14    BevyAtmosphere, BevyColor, BevyFalloff, BevyPhaseFunction, BevyScatteringTerm, ElicitPlugin,
15    elicit_tool,
16};
17use proc_macro2::TokenStream;
18use quote::quote;
19use rmcp::ErrorData;
20use rmcp::model::{CallToolResult, Content};
21use schemars::JsonSchema;
22use serde::{Deserialize, Deserializer, Serialize};
23use tracing::instrument;
24
25/// Supported render-target output kinds.
26#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
27#[serde(rename_all = "snake_case")]
28pub enum BevyRenderTargetKind {
29    /// Emit `RenderTarget::Window(WindowRef::Primary)`.
30    PrimaryWindow,
31    /// Emit `RenderTarget::Window(WindowRef::Entity(expr))`.
32    WindowEntity,
33    /// Emit `RenderTarget::Image(expr.into())`.
34    Image,
35    /// Emit `RenderTarget::TextureView(expr)`.
36    TextureView,
37}
38
39/// Supported tonemapping algorithms.
40#[derive(
41    Debug,
42    Clone,
43    Copy,
44    Serialize,
45    Deserialize,
46    JsonSchema,
47    PartialEq,
48    Eq,
49    elicitation::ToCodeLiteral,
50)]
51#[serde(rename_all = "snake_case")]
52#[to_code_literal(path = "::bevy::core_pipeline::tonemapping::Tonemapping")]
53pub enum BevyTonemappingVariant {
54    /// `Tonemapping::None`
55    None,
56    /// `Tonemapping::Reinhard`
57    Reinhard,
58    /// `Tonemapping::ReinhardLuminance`
59    ReinhardLuminance,
60    /// `Tonemapping::AcesFitted`
61    AcesFitted,
62    /// `Tonemapping::AgX`
63    AgX,
64    /// `Tonemapping::SomewhatBoringDisplayTransform`
65    SomewhatBoringDisplayTransform,
66    /// `Tonemapping::TonyMcMapface`
67    TonyMcMapface,
68    /// `Tonemapping::BlenderFilmic`
69    BlenderFilmic,
70}
71
72/// Supported alpha-mode variants.
73#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
74#[serde(rename_all = "snake_case")]
75pub enum BevyRenderAlphaModeVariant {
76    /// `AlphaMode::Opaque`
77    Opaque,
78    /// `AlphaMode::Mask(threshold)`
79    Mask,
80    /// `AlphaMode::Blend`
81    Blend,
82    /// `AlphaMode::Premultiplied`
83    Premultiplied,
84    /// `AlphaMode::AlphaToCoverage`
85    AlphaToCoverage,
86    /// `AlphaMode::Add`
87    Add,
88    /// `AlphaMode::Multiply`
89    Multiply,
90}
91
92/// Parameters for `bevy_render__render_target`.
93#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
94struct BevyRenderTargetFields {
95    /// Which `RenderTarget` variant to emit.
96    pub kind: BevyRenderTargetKind,
97    /// Expression used by non-primary variants.
98    #[serde(default)]
99    pub target_expr: Option<String>,
100}
101
102/// Parameters for `bevy_render__render_target`.
103#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
104#[to_code_literal(transparent, path = "::bevy::camera::RenderTarget")]
105pub struct BevyRenderTargetParams {
106    /// Flattened render-target fields preserving the MCP JSON shape.
107    #[serde(flatten)]
108    #[to_code_literal(to_tokens = "render_target_tokens")]
109    fields: BevyRenderTargetFields,
110}
111
112/// Parameters for `bevy_render__tonemapping`.
113#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
114#[to_code_literal(transparent)]
115pub struct BevyTonemappingParams {
116    /// Tonemapping algorithm to emit.
117    pub variant: BevyTonemappingVariant,
118}
119
120/// Supported deband-dither variants.
121#[derive(
122    Debug,
123    Clone,
124    Copy,
125    Serialize,
126    Deserialize,
127    JsonSchema,
128    PartialEq,
129    Eq,
130    elicitation::ToCodeLiteral,
131)]
132#[serde(rename_all = "snake_case")]
133#[to_code_literal(path = "::bevy::core_pipeline::tonemapping::DebandDither")]
134pub enum BevyDebandDitherVariant {
135    /// Disable debanding dithering.
136    Disabled,
137    /// Enable debanding dithering.
138    Enabled,
139}
140
141/// Parameters for `bevy_render__deband_dither`.
142#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
143#[to_code_literal(transparent)]
144pub struct BevyDebandDitherParams {
145    /// Deband-dither mode to emit.
146    pub variant: BevyDebandDitherVariant,
147}
148
149/// Parameters for `bevy_render__order_independent_transparency_settings`.
150#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
151#[to_code_literal(
152    path = "::bevy::core_pipeline::oit::OrderIndependentTransparencySettings",
153    update = "::std::default::Default::default()",
154    default_expr = "::bevy::core_pipeline::oit::OrderIndependentTransparencySettings::default()"
155)]
156pub struct BevyOrderIndependentTransparencySettingsParams {
157    /// Optional number of transparency layers to keep.
158    #[serde(default)]
159    #[to_code_literal(optional)]
160    pub layer_count: Option<i32>,
161    /// Optional alpha threshold for placing fragments into OIT layers.
162    #[serde(default)]
163    #[to_code_literal(optional)]
164    pub alpha_threshold: Option<f32>,
165}
166
167/// Supported orthographic scaling modes.
168#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
169#[serde(rename_all = "snake_case")]
170pub enum BevyScalingModeVariant {
171    /// Match the viewport size.
172    WindowSize,
173    /// Use a fixed width and height in world units.
174    Fixed,
175    /// Constrain the minimum width and height.
176    AutoMin,
177    /// Constrain the maximum width and height.
178    AutoMax,
179    /// Keep a fixed viewport height.
180    FixedVertical,
181    /// Keep a fixed viewport width.
182    FixedHorizontal,
183}
184
185/// Parameters for `bevy_render__scaling_mode`.
186#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
187#[serde(tag = "variant", rename_all = "snake_case")]
188#[to_code_literal(path = "::bevy::camera::ScalingMode")]
189pub enum BevyScalingModeParams {
190    /// Match the viewport size.
191    WindowSize,
192    /// Use a fixed width and height in world units.
193    Fixed {
194        /// Fixed-mode width.
195        width: f32,
196        /// Fixed-mode height.
197        height: f32,
198    },
199    /// Constrain the minimum width and height.
200    AutoMin {
201        /// Auto-min minimum width.
202        min_width: f32,
203        /// Auto-min minimum height.
204        min_height: f32,
205    },
206    /// Constrain the maximum width and height.
207    AutoMax {
208        /// Auto-max maximum width.
209        max_width: f32,
210        /// Auto-max maximum height.
211        max_height: f32,
212    },
213    /// Keep a fixed viewport height.
214    FixedVertical {
215        /// Fixed-vertical viewport height.
216        viewport_height: f32,
217    },
218    /// Keep a fixed viewport width.
219    FixedHorizontal {
220        /// Fixed-horizontal viewport width.
221        viewport_width: f32,
222    },
223}
224
225/// Parameters for `bevy_render__perspective_projection`.
226#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
227#[to_code_literal(
228    path = "::bevy::camera::PerspectiveProjection",
229    update = "::bevy::camera::PerspectiveProjection::default()",
230    default_expr = "::bevy::camera::PerspectiveProjection::default()"
231)]
232pub struct BevyPerspectiveProjectionParams {
233    /// Optional vertical field of view in radians.
234    #[serde(default)]
235    #[to_code_literal(optional)]
236    pub fov: Option<f32>,
237    /// Optional aspect ratio.
238    #[serde(default)]
239    #[to_code_literal(optional)]
240    pub aspect_ratio: Option<f32>,
241    /// Optional near clip distance.
242    #[serde(default)]
243    #[to_code_literal(optional)]
244    pub near: Option<f32>,
245    /// Optional far clip distance.
246    #[serde(default)]
247    #[to_code_literal(optional)]
248    pub far: Option<f32>,
249    /// Optional clip-plane expression.
250    #[serde(default)]
251    #[to_code_literal(rename = "near_clip_plane", expr, optional)]
252    pub near_clip_plane_expr: Option<String>,
253}
254
255/// Parameters for `bevy_render__orthographic_projection`.
256#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
257pub(crate) struct BevyOrthographicProjectionFields {
258    /// Whether to start from Bevy's 2D defaults instead of 3D defaults.
259    #[serde(default)]
260    pub use_2d_defaults: Option<bool>,
261    /// Optional near clip distance.
262    #[serde(default)]
263    pub near: Option<f32>,
264    /// Optional far clip distance.
265    #[serde(default)]
266    pub far: Option<f32>,
267    /// Optional viewport-origin expression.
268    #[serde(default)]
269    pub viewport_origin_expr: Option<String>,
270    /// Optional scaling-mode expression.
271    #[serde(default)]
272    pub scaling_mode_expr: Option<String>,
273    /// Optional scale multiplier.
274    #[serde(default)]
275    pub scale: Option<f32>,
276    /// Optional orthographic area expression.
277    #[serde(default)]
278    pub area_expr: Option<String>,
279}
280
281/// Parameters for `bevy_render__orthographic_projection`.
282#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
283#[to_code_literal(transparent, path = "::bevy::camera::OrthographicProjection")]
284pub struct BevyOrthographicProjectionParams {
285    /// Flattened orthographic projection fields preserving the MCP JSON shape.
286    #[serde(flatten)]
287    #[to_code_literal(to_tokens = "orthographic_projection_tokens")]
288    pub(crate) fields: BevyOrthographicProjectionFields,
289}
290
291/// Supported clear-color configuration variants.
292#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
293#[serde(rename_all = "snake_case")]
294pub enum BevyClearColorConfigVariant {
295    /// Use the world's `ClearColor` resource.
296    Default,
297    /// Use a camera-specific clear color.
298    Custom,
299    /// Do not clear before rendering.
300    None,
301}
302
303/// Parameters for `bevy_render__clear_color_config`.
304#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
305#[serde(tag = "variant", content = "color_expr", rename_all = "snake_case")]
306#[to_code_literal(path = "::bevy::camera::ClearColorConfig")]
307pub enum BevyClearColorConfigParams {
308    /// Use the world's `ClearColor` resource.
309    Default,
310    /// Use a camera-specific clear color expression.
311    Custom(#[to_code_literal(expr)] String),
312    /// Do not clear before rendering.
313    None,
314}
315
316/// Supported MSAA writeback variants.
317#[derive(
318    Debug,
319    Clone,
320    Copy,
321    Serialize,
322    Deserialize,
323    JsonSchema,
324    PartialEq,
325    Eq,
326    elicitation::ToCodeLiteral,
327)]
328#[serde(rename_all = "snake_case")]
329#[to_code_literal(path = "::bevy::camera::MsaaWriteback")]
330pub enum BevyMsaaWritebackVariant {
331    /// Never write back MSAA contents.
332    Off,
333    /// Automatically write back when needed.
334    Auto,
335    /// Always perform writeback.
336    Always,
337}
338
339/// Parameters for `bevy_render__msaa_writeback`.
340#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
341#[to_code_literal(transparent)]
342pub struct BevyMsaaWritebackParams {
343    /// Which MSAA writeback mode to emit.
344    pub variant: BevyMsaaWritebackVariant,
345}
346
347/// Named Bevy exposure presets.
348#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
349#[serde(rename_all = "snake_case")]
350pub enum BevyExposurePreset {
351    /// Match bright outdoor sunlight.
352    Sunlight,
353    /// Match overcast outdoor lighting.
354    Overcast,
355    /// Match indoor lighting.
356    Indoor,
357    /// Match Blender's default exposure.
358    Blender,
359}
360
361#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
362struct BevyExposureFields {
363    /// Optional named exposure preset.
364    #[serde(default)]
365    preset: Option<BevyExposurePreset>,
366    /// Optional explicit EV100 value.
367    #[serde(default)]
368    ev100: Option<f32>,
369}
370
371/// Parameters for `bevy_render__exposure`.
372#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
373#[to_code_literal(path = "::bevy::camera::Exposure", transparent)]
374pub struct BevyExposureParams {
375    #[serde(flatten)]
376    #[to_code_literal(to_tokens = "exposure_tokens")]
377    fields: BevyExposureFields,
378}
379
380/// Parameters for `bevy_render__clear_color`.
381#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
382#[to_code_literal(path = "::bevy::camera::ClearColor", transparent)]
383pub struct BevyClearColorParams {
384    /// Optional color expression overriding Bevy's default clear color.
385    #[serde(default)]
386    #[to_code_literal(to_tokens = "clear_color_tokens")]
387    pub color_expr: Option<String>,
388}
389
390/// Supported camera depth-load operations.
391#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
392#[serde(rename_all = "snake_case")]
393pub enum BevyCamera3dDepthLoadOpVariant {
394    /// Clear the depth buffer, optionally with a custom depth.
395    #[default]
396    Clear,
397    /// Load the existing depth buffer contents.
398    Load,
399}
400
401/// Parameters for `bevy_render__camera_3d_depth_load_op`.
402#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
403#[serde(tag = "variant", rename_all = "snake_case")]
404#[to_code_literal(path = "::bevy::camera::Camera3dDepthLoadOp")]
405pub enum BevyCamera3dDepthLoadOpParams {
406    /// Clear the depth buffer, optionally with a custom depth.
407    #[to_code_literal(tuple)]
408    Clear {
409        /// Clear value when `variant = clear`.
410        #[serde(default = "default_camera_3d_depth_clear")]
411        depth: f32,
412    },
413    /// Load the existing depth buffer contents.
414    Load,
415}
416
417impl Default for BevyCamera3dDepthLoadOpParams {
418    fn default() -> Self {
419        Self::Clear {
420            depth: default_camera_3d_depth_clear(),
421        }
422    }
423}
424
425/// Supported screen-space transmission quality levels.
426#[derive(
427    Debug,
428    Clone,
429    Copy,
430    Serialize,
431    Deserialize,
432    JsonSchema,
433    PartialEq,
434    Eq,
435    Default,
436    elicitation::ToCodeLiteral,
437)]
438#[serde(rename_all = "snake_case")]
439#[to_code_literal(path = "::bevy::camera::ScreenSpaceTransmissionQuality")]
440pub enum BevyScreenSpaceTransmissionQualityVariant {
441    /// Lowest quality.
442    Low,
443    /// Medium quality.
444    #[default]
445    Medium,
446    /// High quality.
447    High,
448    /// Ultra quality.
449    Ultra,
450}
451
452/// Parameters for `bevy_render__screen_space_transmission_quality`.
453#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
454#[to_code_literal(transparent)]
455pub struct BevyScreenSpaceTransmissionQualityParams {
456    /// Which transmission quality to emit.
457    pub variant: BevyScreenSpaceTransmissionQualityVariant,
458}
459
460#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
461struct BevyMainPassResolutionOverrideFields {
462    /// Override width in physical pixels.
463    width: u32,
464    /// Override height in physical pixels.
465    height: u32,
466}
467
468/// Parameters for `bevy_render__main_pass_resolution_override`.
469#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
470#[to_code_literal(path = "::bevy::camera::MainPassResolutionOverride", transparent)]
471pub struct BevyMainPassResolutionOverrideParams {
472    #[serde(flatten)]
473    #[to_code_literal(to_tokens = "main_pass_resolution_override_tokens")]
474    fields: BevyMainPassResolutionOverrideFields,
475}
476
477#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
478struct BevySubCameraViewFields {
479    /// Total logical width of the full multi-camera image.
480    full_width: u32,
481    /// Total logical height of the full multi-camera image.
482    full_height: u32,
483    /// Horizontal offset of this sub view.
484    offset_x: f32,
485    /// Vertical offset of this sub view.
486    offset_y: f32,
487    /// Width of the sub view.
488    width: u32,
489    /// Height of the sub view.
490    height: u32,
491}
492
493/// Parameters for `bevy_render__sub_camera_view`.
494#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
495#[to_code_literal(path = "::bevy::camera::SubCameraView", transparent)]
496pub struct BevySubCameraViewParams {
497    #[serde(flatten)]
498    #[to_code_literal(to_tokens = "sub_camera_view_tokens")]
499    fields: BevySubCameraViewFields,
500}
501
502/// Parameters for `bevy_render__no_cpu_culling`.
503#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
504#[to_code_literal(path = "::bevy::camera::visibility::NoCpuCulling")]
505pub struct BevyNoCpuCullingParams;
506
507/// Parameters for `bevy_render__no_frustum_culling`.
508#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
509#[to_code_literal(path = "::bevy::camera::visibility::NoFrustumCulling")]
510pub struct BevyNoFrustumCullingParams;
511
512#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
513struct BevyVisibilityRangeFields {
514    /// Start distance where the near fade begins.
515    start_margin_start: f32,
516    /// Distance where the near fade completes.
517    start_margin_end: f32,
518    /// Distance where the far fade begins.
519    end_margin_start: f32,
520    /// Distance where the far fade completes.
521    end_margin_end: f32,
522    /// Whether to use the mesh AABB center instead of the origin.
523    #[serde(default)]
524    use_aabb: Option<bool>,
525}
526
527/// Parameters for `bevy_render__visibility_range`.
528#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
529#[to_code_literal(path = "::bevy::camera::visibility::VisibilityRange", transparent)]
530pub struct BevyVisibilityRangeParams {
531    #[serde(flatten)]
532    #[to_code_literal(to_tokens = "visibility_range_tokens")]
533    fields: BevyVisibilityRangeFields,
534}
535
536/// Parameters for `bevy_render__color`.
537#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
538#[to_code_literal(transparent)]
539pub struct BevyColorParams {
540    /// Structured Bevy color-space payload.
541    pub color: BevyColor,
542}
543
544/// Parameters for `bevy_render__alpha_mode`.
545#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
546#[serde(tag = "variant", rename_all = "snake_case")]
547#[to_code_literal(path = "::bevy::render::alpha::AlphaMode")]
548pub enum BevyRenderAlphaModeParams {
549    /// `AlphaMode::Opaque`
550    Opaque,
551    /// `AlphaMode::Mask(threshold)`
552    #[to_code_literal(tuple)]
553    Mask {
554        /// Mask threshold used when `variant = mask`.
555        #[serde(default = "default_render_alpha_mode_threshold")]
556        threshold: f32,
557    },
558    /// `AlphaMode::Blend`
559    Blend,
560    /// `AlphaMode::Premultiplied`
561    Premultiplied,
562    /// `AlphaMode::AlphaToCoverage`
563    AlphaToCoverage,
564    /// `AlphaMode::Add`
565    Add,
566    /// `AlphaMode::Multiply`
567    Multiply,
568}
569
570/// Supported Bevy UV channels.
571#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
572#[serde(rename_all = "snake_case")]
573#[to_code_literal(path = "::bevy::pbr::UvChannel")]
574pub enum BevyUvChannelVariant {
575    /// Use the first UV set.
576    Uv0,
577    /// Use the second UV set.
578    Uv1,
579}
580
581/// Parameters for `bevy_render__uv_channel`.
582#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
583#[to_code_literal(transparent)]
584pub struct BevyUvChannelParams {
585    /// Which Bevy UV channel to emit.
586    pub variant: BevyUvChannelVariant,
587}
588
589/// Supported Bevy parallax mapping methods.
590#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
591#[serde(rename_all = "snake_case")]
592pub enum BevyParallaxMappingMethodVariant {
593    /// Use fast occlusion mapping.
594    Occlusion,
595    /// Use relief mapping with a configurable maximum step count.
596    Relief,
597}
598
599/// Parameters for `bevy_render__parallax_mapping_method`.
600#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
601#[serde(tag = "variant", rename_all = "snake_case")]
602#[to_code_literal(path = "::bevy::pbr::ParallaxMappingMethod")]
603pub enum BevyParallaxMappingMethodParams {
604    /// Use fast occlusion mapping.
605    Occlusion,
606    /// Use relief mapping with a configurable maximum step count.
607    Relief {
608        /// Maximum step count for the relief-mapping solver.
609        #[serde(default = "default_parallax_relief_max_steps")]
610        max_steps: u32,
611    },
612}
613
614/// Supported Bevy opaque renderer methods.
615#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
616#[serde(rename_all = "snake_case")]
617#[to_code_literal(path = "::bevy::pbr::OpaqueRendererMethod")]
618pub enum BevyOpaqueRendererMethodVariant {
619    /// Let Bevy pick based on the default resource.
620    Auto,
621    /// Force forward rendering.
622    Forward,
623    /// Force deferred rendering.
624    Deferred,
625}
626
627/// Parameters for `bevy_render__opaque_renderer_method`.
628#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
629#[to_code_literal(transparent)]
630pub struct BevyOpaqueRendererMethodParams {
631    /// Which opaque renderer method to emit.
632    pub variant: BevyOpaqueRendererMethodVariant,
633}
634
635/// Supported constructors for `DefaultOpaqueRendererMethod`.
636#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
637#[serde(rename_all = "snake_case")]
638pub enum BevyDefaultOpaqueRendererMethodVariant {
639    /// Use Bevy's default constructor.
640    Default,
641    /// Force forward rendering as the resource default.
642    Forward,
643    /// Force deferred rendering as the resource default.
644    Deferred,
645}
646
647/// Parameters for `bevy_render__default_opaque_renderer_method`.
648#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
649#[to_code_literal(path = "::bevy::pbr::DefaultOpaqueRendererMethod", transparent)]
650pub struct BevyDefaultOpaqueRendererMethodParams {
651    /// Which resource constructor to emit.
652    #[to_code_literal(to_tokens = "default_opaque_renderer_method_tokens")]
653    pub variant: BevyDefaultOpaqueRendererMethodVariant,
654}
655
656/// Supported alpha modes for 2D materials.
657#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
658#[serde(rename_all = "snake_case")]
659pub enum BevyAlphaMode2dVariant {
660    /// Force fully opaque output.
661    Opaque,
662    /// Use alpha cutoff masking.
663    Mask,
664    /// Use standard alpha blending.
665    Blend,
666}
667
668/// Parameters for `bevy_render__alpha_mode_2d`.
669#[derive(
670    Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, elicitation::ToCodeLiteral,
671)]
672#[serde(tag = "variant", content = "threshold", rename_all = "snake_case")]
673#[to_code_literal(path = "::bevy::sprite_render::AlphaMode2d")]
674pub enum BevyAlphaMode2dParams {
675    /// Force fully opaque output.
676    Opaque,
677    /// Use alpha cutoff masking.
678    Mask(f32),
679    /// Use standard alpha blending.
680    Blend,
681}
682
683/// Parameters for `bevy_render__standard_material`.
684#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
685#[to_code_literal(path = "::bevy::pbr::StandardMaterial", default_update)]
686pub struct BevyStandardMaterialParams {
687    /// Optional base-color expression.
688    #[serde(default)]
689    #[to_code_literal(optional, rename = "base_color", expr)]
690    pub base_color_expr: Option<String>,
691    /// Optional UV channel for the base-color texture.
692    #[serde(default)]
693    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
694    pub base_color_channel: Option<BevyUvChannelVariant>,
695    /// Optional base-color texture handle expression.
696    #[serde(default)]
697    #[to_code_literal(
698        optional,
699        rename = "base_color_texture",
700        to_tokens = "some_expr_tokens"
701    )]
702    pub base_color_texture_expr: Option<String>,
703    /// Optional emissive color expression.
704    #[serde(default)]
705    #[to_code_literal(optional, rename = "emissive", expr)]
706    pub emissive_expr: Option<String>,
707    /// Optional UV channel for the emissive texture.
708    #[serde(default)]
709    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
710    pub emissive_channel: Option<BevyUvChannelVariant>,
711    /// Optional emissive texture handle expression.
712    #[serde(default)]
713    #[to_code_literal(optional, rename = "emissive_texture", to_tokens = "some_expr_tokens")]
714    pub emissive_texture_expr: Option<String>,
715    /// Optional emissive exposure multiplier.
716    #[serde(default)]
717    #[to_code_literal(optional)]
718    pub emissive_exposure_weight: Option<f32>,
719    /// Optional metallic factor.
720    #[serde(default)]
721    #[to_code_literal(optional)]
722    pub metallic: Option<f32>,
723    /// Optional perceptual roughness factor.
724    #[serde(default)]
725    #[to_code_literal(optional)]
726    pub perceptual_roughness: Option<f32>,
727    /// Optional UV channel for the metallic/roughness texture.
728    #[serde(default)]
729    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
730    pub metallic_roughness_channel: Option<BevyUvChannelVariant>,
731    /// Optional metallic/roughness texture handle expression.
732    #[serde(default)]
733    #[to_code_literal(
734        optional,
735        rename = "metallic_roughness_texture",
736        to_tokens = "some_expr_tokens"
737    )]
738    pub metallic_roughness_texture_expr: Option<String>,
739    /// Optional reflectance factor.
740    #[serde(default)]
741    #[to_code_literal(optional)]
742    pub reflectance: Option<f32>,
743    /// Optional specular tint expression.
744    #[serde(default)]
745    #[to_code_literal(optional, rename = "specular_tint", expr)]
746    pub specular_tint_expr: Option<String>,
747    /// Optional diffuse transmission factor.
748    #[serde(default)]
749    #[to_code_literal(optional)]
750    pub diffuse_transmission: Option<f32>,
751    /// Optional UV channel for the diffuse transmission texture.
752    #[serde(default)]
753    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
754    pub diffuse_transmission_channel: Option<BevyUvChannelVariant>,
755    /// Optional diffuse transmission texture handle expression.
756    #[serde(default)]
757    #[to_code_literal(
758        optional,
759        rename = "diffuse_transmission_texture",
760        to_tokens = "some_expr_tokens"
761    )]
762    pub diffuse_transmission_texture_expr: Option<String>,
763    /// Optional specular transmission factor.
764    #[serde(default)]
765    #[to_code_literal(optional)]
766    pub specular_transmission: Option<f32>,
767    /// Optional UV channel for the specular transmission texture.
768    #[serde(default)]
769    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
770    pub specular_transmission_channel: Option<BevyUvChannelVariant>,
771    /// Optional specular transmission texture handle expression.
772    #[serde(default)]
773    #[to_code_literal(
774        optional,
775        rename = "specular_transmission_texture",
776        to_tokens = "some_expr_tokens"
777    )]
778    pub specular_transmission_texture_expr: Option<String>,
779    /// Optional volume thickness.
780    #[serde(default)]
781    #[to_code_literal(optional)]
782    pub thickness: Option<f32>,
783    /// Optional UV channel for the thickness texture.
784    #[serde(default)]
785    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
786    pub thickness_channel: Option<BevyUvChannelVariant>,
787    /// Optional thickness texture handle expression.
788    #[serde(default)]
789    #[to_code_literal(optional, rename = "thickness_texture", to_tokens = "some_expr_tokens")]
790    pub thickness_texture_expr: Option<String>,
791    /// Optional index of refraction.
792    #[serde(default)]
793    #[to_code_literal(optional)]
794    pub ior: Option<f32>,
795    /// Optional attenuation distance.
796    #[serde(default)]
797    #[to_code_literal(optional)]
798    pub attenuation_distance: Option<f32>,
799    /// Optional attenuation color expression.
800    #[serde(default)]
801    #[to_code_literal(optional, rename = "attenuation_color", expr)]
802    pub attenuation_color_expr: Option<String>,
803    /// Optional clearcoat strength.
804    #[serde(default)]
805    #[to_code_literal(optional)]
806    pub clearcoat: Option<f32>,
807    /// Optional UV channel for the clearcoat texture.
808    #[serde(default)]
809    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
810    pub clearcoat_channel: Option<BevyUvChannelVariant>,
811    /// Optional clearcoat texture handle expression.
812    #[serde(default)]
813    #[to_code_literal(optional, rename = "clearcoat_texture", to_tokens = "some_expr_tokens")]
814    pub clearcoat_texture_expr: Option<String>,
815    /// Optional clearcoat roughness.
816    #[serde(default)]
817    #[to_code_literal(optional)]
818    pub clearcoat_perceptual_roughness: Option<f32>,
819    /// Optional UV channel for the clearcoat roughness texture.
820    #[serde(default)]
821    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
822    pub clearcoat_roughness_channel: Option<BevyUvChannelVariant>,
823    /// Optional clearcoat roughness texture handle expression.
824    #[serde(default)]
825    #[to_code_literal(
826        optional,
827        rename = "clearcoat_roughness_texture",
828        to_tokens = "some_expr_tokens"
829    )]
830    pub clearcoat_roughness_texture_expr: Option<String>,
831    /// Optional UV channel for the clearcoat normal texture.
832    #[serde(default)]
833    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
834    pub clearcoat_normal_channel: Option<BevyUvChannelVariant>,
835    /// Optional clearcoat normal texture handle expression.
836    #[serde(default)]
837    #[to_code_literal(
838        optional,
839        rename = "clearcoat_normal_texture",
840        to_tokens = "some_expr_tokens"
841    )]
842    pub clearcoat_normal_texture_expr: Option<String>,
843    /// Optional anisotropy strength.
844    #[serde(default)]
845    #[to_code_literal(optional)]
846    pub anisotropy_strength: Option<f32>,
847    /// Optional anisotropy rotation in radians.
848    #[serde(default)]
849    #[to_code_literal(optional)]
850    pub anisotropy_rotation: Option<f32>,
851    /// Optional UV channel for the anisotropy texture.
852    #[serde(default)]
853    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
854    pub anisotropy_channel: Option<BevyUvChannelVariant>,
855    /// Optional anisotropy texture handle expression.
856    #[serde(default)]
857    #[to_code_literal(
858        optional,
859        rename = "anisotropy_texture",
860        to_tokens = "some_expr_tokens"
861    )]
862    pub anisotropy_texture_expr: Option<String>,
863    /// Optional UV channel for the normal map texture.
864    #[serde(default)]
865    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
866    pub normal_map_channel: Option<BevyUvChannelVariant>,
867    /// Optional normal-map texture handle expression.
868    #[serde(default)]
869    #[to_code_literal(
870        optional,
871        rename = "normal_map_texture",
872        to_tokens = "some_expr_tokens"
873    )]
874    pub normal_map_texture_expr: Option<String>,
875    /// Optional flag for DirectX-authored normal maps.
876    #[serde(default)]
877    #[to_code_literal(optional)]
878    pub flip_normal_map_y: Option<bool>,
879    /// Optional UV channel for the occlusion texture.
880    #[serde(default)]
881    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
882    pub occlusion_channel: Option<BevyUvChannelVariant>,
883    /// Optional occlusion texture handle expression.
884    #[serde(default)]
885    #[to_code_literal(optional, rename = "occlusion_texture", to_tokens = "some_expr_tokens")]
886    pub occlusion_texture_expr: Option<String>,
887    /// Optional UV channel for the specular texture.
888    #[serde(default)]
889    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
890    pub specular_channel: Option<BevyUvChannelVariant>,
891    /// Optional specular texture handle expression.
892    #[serde(default)]
893    #[to_code_literal(optional, rename = "specular_texture", to_tokens = "some_expr_tokens")]
894    pub specular_texture_expr: Option<String>,
895    /// Optional UV channel for the specular tint texture.
896    #[serde(default)]
897    #[to_code_literal(optional, to_tokens = "emit_uv_channel_variant_tokens")]
898    pub specular_tint_channel: Option<BevyUvChannelVariant>,
899    /// Optional specular tint texture handle expression.
900    #[serde(default)]
901    #[to_code_literal(
902        optional,
903        rename = "specular_tint_texture",
904        to_tokens = "some_expr_tokens"
905    )]
906    pub specular_tint_texture_expr: Option<String>,
907    /// Optional alpha-mode expression.
908    #[serde(default)]
909    #[to_code_literal(optional, rename = "alpha_mode", expr)]
910    pub alpha_mode_expr: Option<String>,
911    /// Whether the material is double-sided.
912    #[serde(default)]
913    #[to_code_literal(optional)]
914    pub double_sided: Option<bool>,
915    /// Whether the material is unlit.
916    #[serde(default)]
917    #[to_code_literal(optional)]
918    pub unlit: Option<bool>,
919    /// Whether the material participates in fog.
920    #[serde(default)]
921    #[to_code_literal(optional)]
922    pub fog_enabled: Option<bool>,
923    /// Optional cull mode expression.
924    #[serde(default)]
925    #[to_code_literal(optional, rename = "cull_mode", to_tokens = "some_expr_tokens")]
926    pub cull_mode_expr: Option<String>,
927    /// Optional constant depth bias.
928    #[serde(default)]
929    #[to_code_literal(optional)]
930    pub depth_bias: Option<f32>,
931    /// Optional depth-map texture handle expression.
932    #[serde(default)]
933    #[to_code_literal(optional, rename = "depth_map", to_tokens = "some_expr_tokens")]
934    pub depth_map_expr: Option<String>,
935    /// Optional parallax depth scale.
936    #[serde(default)]
937    #[to_code_literal(optional)]
938    pub parallax_depth_scale: Option<f32>,
939    /// Optional parallax mapping method expression.
940    #[serde(default)]
941    #[to_code_literal(optional, rename = "parallax_mapping_method", expr)]
942    pub parallax_mapping_method_expr: Option<String>,
943    /// Optional parallax layer count ceiling.
944    #[serde(default)]
945    #[to_code_literal(optional)]
946    pub max_parallax_layer_count: Option<f32>,
947    /// Optional lightmap exposure scale.
948    #[serde(default)]
949    #[to_code_literal(optional)]
950    pub lightmap_exposure: Option<f32>,
951    /// Optional opaque renderer method expression.
952    #[serde(default)]
953    #[to_code_literal(optional, rename = "opaque_render_method", expr)]
954    pub opaque_render_method_expr: Option<String>,
955    /// Optional deferred lighting pass identifier.
956    #[serde(default)]
957    #[to_code_literal(optional)]
958    pub deferred_lighting_pass_id: Option<u8>,
959    /// Optional UV transform expression.
960    #[serde(default)]
961    #[to_code_literal(optional, rename = "uv_transform", expr)]
962    pub uv_transform_expr: Option<String>,
963}
964
965/// Parameters for `bevy_render__lightmap`.
966#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
967#[to_code_literal(path = "::bevy::pbr::Lightmap", default_update)]
968pub struct BevyLightmapParams {
969    /// Expression that yields the `Handle<Image>` for the baked lightmap.
970    #[to_code_literal(rename = "image", expr)]
971    pub image_expr: String,
972    /// Optional `Rect` expression describing the atlas region.
973    #[serde(default)]
974    #[to_code_literal(rename = "uv_rect", expr, optional)]
975    pub uv_rect_expr: Option<String>,
976    /// Whether bicubic sampling should be enabled.
977    #[serde(default)]
978    #[to_code_literal(optional)]
979    pub bicubic_sampling: Option<bool>,
980}
981
982/// Parameters for `bevy_render__color_material`.
983#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
984#[to_code_literal(path = "::bevy::sprite_render::ColorMaterial", default_update)]
985pub struct BevyColorMaterialParams {
986    /// Optional tint color expression.
987    #[serde(default)]
988    #[to_code_literal(rename = "color", expr, optional)]
989    pub color_expr: Option<String>,
990    /// Optional `AlphaMode2d` expression.
991    #[serde(default)]
992    #[to_code_literal(rename = "alpha_mode", expr, optional)]
993    pub alpha_mode_expr: Option<String>,
994    /// Optional UV transform expression.
995    #[serde(default)]
996    #[to_code_literal(rename = "uv_transform", expr, optional)]
997    pub uv_transform_expr: Option<String>,
998    /// Optional texture handle expression.
999    #[serde(default)]
1000    #[to_code_literal(rename = "texture", optional, to_tokens = "some_expr_tokens")]
1001    pub texture_expr: Option<String>,
1002}
1003
1004/// Parameters for `bevy_render__skybox`.
1005#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1006#[to_code_literal(path = "::bevy::core_pipeline::Skybox", default_update)]
1007pub struct BevySkyboxParams {
1008    /// Cubemap image handle expression.
1009    #[to_code_literal(rename = "image", expr)]
1010    pub image_expr: String,
1011    /// Optional brightness multiplier.
1012    #[serde(default)]
1013    #[to_code_literal(optional)]
1014    pub brightness: Option<f32>,
1015    /// Optional rotation expression.
1016    #[serde(default)]
1017    #[to_code_literal(rename = "rotation", expr, optional)]
1018    pub rotation_expr: Option<String>,
1019}
1020
1021/// Parameters for `bevy_render__depth_prepass`.
1022#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1023#[to_code_literal(path = "::bevy::core_pipeline::prepass::DepthPrepass")]
1024pub struct BevyDepthPrepassParams;
1025
1026/// Parameters for `bevy_render__normal_prepass`.
1027#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1028#[to_code_literal(path = "::bevy::core_pipeline::prepass::NormalPrepass")]
1029pub struct BevyNormalPrepassParams;
1030
1031/// Parameters for `bevy_render__motion_vector_prepass`.
1032#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1033#[to_code_literal(path = "::bevy::core_pipeline::prepass::MotionVectorPrepass")]
1034pub struct BevyMotionVectorPrepassParams;
1035
1036/// Parameters for `bevy_render__deferred_prepass`.
1037#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1038#[to_code_literal(path = "::bevy::core_pipeline::prepass::DeferredPrepass")]
1039pub struct BevyDeferredPrepassParams;
1040
1041/// Parameters for `bevy_render__depth_prepass_double_buffer`.
1042#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1043#[to_code_literal(path = "::bevy::core_pipeline::prepass::DepthPrepassDoubleBuffer")]
1044pub struct BevyDepthPrepassDoubleBufferParams;
1045
1046/// Parameters for `bevy_render__deferred_prepass_double_buffer`.
1047#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1048#[to_code_literal(path = "::bevy::core_pipeline::prepass::DeferredPrepassDoubleBuffer")]
1049pub struct BevyDeferredPrepassDoubleBufferParams;
1050
1051/// Parameters for `bevy_render__ambient_light`.
1052#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1053#[to_code_literal(path = "::bevy::light::AmbientLight", default_update)]
1054pub struct BevyAmbientLightParams {
1055    /// Optional color expression.
1056    #[serde(default)]
1057    #[to_code_literal(rename = "color", expr, optional)]
1058    pub color_expr: Option<String>,
1059    /// Optional brightness multiplier.
1060    #[serde(default)]
1061    #[to_code_literal(optional)]
1062    pub brightness: Option<f32>,
1063    /// Optional flag controlling whether the ambient light affects meshes with lightmaps.
1064    #[serde(default)]
1065    #[to_code_literal(optional)]
1066    pub affects_lightmapped_meshes: Option<bool>,
1067}
1068
1069/// Parameters for `bevy_render__directional_light`.
1070#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1071#[to_code_literal(path = "::bevy::light::DirectionalLight", default_update)]
1072pub struct BevyDirectionalLightParams {
1073    /// Optional color expression.
1074    #[serde(default)]
1075    #[to_code_literal(rename = "color", expr, optional)]
1076    pub color_expr: Option<String>,
1077    /// Optional illuminance in lux.
1078    #[serde(default)]
1079    #[to_code_literal(optional)]
1080    pub illuminance: Option<f32>,
1081    /// Optional shadows-enabled flag.
1082    #[serde(default)]
1083    #[to_code_literal(optional)]
1084    pub shadows_enabled: Option<bool>,
1085}
1086
1087/// Parameters for `bevy_render__global_ambient_light`.
1088#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1089#[to_code_literal(path = "::bevy::light::GlobalAmbientLight", default_update)]
1090pub struct BevyGlobalAmbientLightParams {
1091    /// Optional color expression.
1092    #[serde(default)]
1093    #[to_code_literal(rename = "color", expr, optional)]
1094    pub color_expr: Option<String>,
1095    /// Optional brightness multiplier.
1096    #[serde(default)]
1097    #[to_code_literal(optional)]
1098    pub brightness: Option<f32>,
1099    /// Optional flag controlling whether the ambient light affects meshes with lightmaps.
1100    #[serde(default)]
1101    #[to_code_literal(optional)]
1102    pub affects_lightmapped_meshes: Option<bool>,
1103}
1104
1105/// Parameters for `bevy_render__point_light`.
1106#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1107#[to_code_literal(path = "::bevy::light::PointLight", default_update)]
1108pub struct BevyPointLightParams {
1109    /// Optional color expression.
1110    #[serde(default)]
1111    #[to_code_literal(rename = "color", expr, optional)]
1112    pub color_expr: Option<String>,
1113    /// Optional light intensity.
1114    #[serde(default)]
1115    #[to_code_literal(optional)]
1116    pub intensity: Option<f32>,
1117    /// Optional light range.
1118    #[serde(default)]
1119    #[to_code_literal(optional)]
1120    pub range: Option<f32>,
1121    /// Optional radius.
1122    #[serde(default)]
1123    #[to_code_literal(optional)]
1124    pub radius: Option<f32>,
1125    /// Optional shadows-enabled flag.
1126    #[serde(default)]
1127    #[to_code_literal(optional)]
1128    pub shadows_enabled: Option<bool>,
1129}
1130
1131/// Parameters for `bevy_render__spot_light`.
1132#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1133#[to_code_literal(path = "::bevy::light::SpotLight", default_update)]
1134pub struct BevySpotLightParams {
1135    /// Optional color expression.
1136    #[serde(default)]
1137    #[to_code_literal(rename = "color", expr, optional)]
1138    pub color_expr: Option<String>,
1139    /// Optional light intensity.
1140    #[serde(default)]
1141    #[to_code_literal(optional)]
1142    pub intensity: Option<f32>,
1143    /// Optional light range.
1144    #[serde(default)]
1145    #[to_code_literal(optional)]
1146    pub range: Option<f32>,
1147    /// Optional radius.
1148    #[serde(default)]
1149    #[to_code_literal(optional)]
1150    pub radius: Option<f32>,
1151    /// Optional inner-cone angle in radians.
1152    #[serde(default)]
1153    #[to_code_literal(optional)]
1154    pub inner_angle: Option<f32>,
1155    /// Optional outer-cone angle in radians.
1156    #[serde(default)]
1157    #[to_code_literal(optional)]
1158    pub outer_angle: Option<f32>,
1159    /// Optional shadows-enabled flag.
1160    #[serde(default)]
1161    #[to_code_literal(optional)]
1162    pub shadows_enabled: Option<bool>,
1163}
1164
1165/// Parameters for `bevy_render__directional_light_shadow_map`.
1166#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1167#[to_code_literal(
1168    path = "::bevy::light::DirectionalLightShadowMap",
1169    default_expr = "::bevy::light::DirectionalLightShadowMap::default()"
1170)]
1171pub struct BevyDirectionalLightShadowMapParams {
1172    /// Optional width/height for each directional-light cascade shadow map.
1173    #[serde(default)]
1174    #[to_code_literal(optional)]
1175    pub size: Option<usize>,
1176}
1177
1178/// Parameters for `bevy_render__point_light_shadow_map`.
1179#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1180#[to_code_literal(
1181    path = "::bevy::light::PointLightShadowMap",
1182    default_expr = "::bevy::light::PointLightShadowMap::default()"
1183)]
1184pub struct BevyPointLightShadowMapParams {
1185    /// Optional width/height for each point-light cubemap face shadow map.
1186    #[serde(default)]
1187    #[to_code_literal(optional)]
1188    pub size: Option<usize>,
1189}
1190
1191/// Parameters for `bevy_render__environment_map_light`.
1192#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1193#[to_code_literal(path = "::bevy::light::EnvironmentMapLight", default_update)]
1194pub struct BevyEnvironmentMapLightParams {
1195    /// Expression that yields the diffuse cubemap handle.
1196    #[to_code_literal(rename = "diffuse_map", expr)]
1197    pub diffuse_map_expr: String,
1198    /// Expression that yields the specular cubemap handle.
1199    #[to_code_literal(rename = "specular_map", expr)]
1200    pub specular_map_expr: String,
1201    /// Optional radiance scale factor.
1202    #[serde(default)]
1203    #[to_code_literal(optional)]
1204    pub intensity: Option<f32>,
1205    /// Optional world-space rotation expression.
1206    #[serde(default)]
1207    #[to_code_literal(rename = "rotation", expr, optional)]
1208    pub rotation_expr: Option<String>,
1209    /// Optional flag controlling diffuse contribution on lightmapped meshes.
1210    #[serde(default)]
1211    #[to_code_literal(optional)]
1212    pub affects_lightmapped_mesh_diffuse: Option<bool>,
1213}
1214
1215/// Parameters for `bevy_render__generated_environment_map_light`.
1216#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1217#[to_code_literal(path = "::bevy::light::GeneratedEnvironmentMapLight", default_update)]
1218pub struct BevyGeneratedEnvironmentMapLightParams {
1219    /// Expression that yields the source cubemap handle.
1220    #[to_code_literal(rename = "environment_map", expr)]
1221    pub environment_map_expr: String,
1222    /// Optional radiance scale factor.
1223    #[serde(default)]
1224    #[to_code_literal(optional)]
1225    pub intensity: Option<f32>,
1226    /// Optional world-space rotation expression.
1227    #[serde(default)]
1228    #[to_code_literal(rename = "rotation", expr, optional)]
1229    pub rotation_expr: Option<String>,
1230    /// Optional flag controlling diffuse contribution on lightmapped meshes.
1231    #[serde(default)]
1232    #[to_code_literal(optional)]
1233    pub affects_lightmapped_mesh_diffuse: Option<bool>,
1234}
1235
1236/// Parameters for `bevy_render__atmosphere_environment_map_light`.
1237#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1238#[to_code_literal(
1239    path = "::bevy::light::AtmosphereEnvironmentMapLight",
1240    default_update,
1241    default_expr = "::bevy::light::AtmosphereEnvironmentMapLight::default()"
1242)]
1243pub struct BevyAtmosphereEnvironmentMapLightParams {
1244    /// Optional brightness multiplier.
1245    #[serde(default)]
1246    #[to_code_literal(optional)]
1247    pub intensity: Option<f32>,
1248    /// Optional flag controlling diffuse contribution on lightmapped meshes.
1249    #[serde(default)]
1250    #[to_code_literal(optional)]
1251    pub affects_lightmapped_mesh_diffuse: Option<bool>,
1252    /// Optional cubemap resolution in pixels.
1253    #[serde(default)]
1254    #[to_code_literal(optional, to_tokens = "uvec2_array_tokens")]
1255    pub size: Option<[u32; 2]>,
1256}
1257
1258/// Parameters for `bevy_render__volumetric_light`.
1259#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1260#[to_code_literal(path = "::bevy::light::VolumetricLight")]
1261pub struct BevyVolumetricLightParams;
1262
1263/// Parameters for `bevy_render__volumetric_fog`.
1264#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1265#[to_code_literal(path = "::bevy::light::VolumetricFog", default_update)]
1266pub struct BevyVolumetricFogParams {
1267    /// Optional ambient-light color expression.
1268    #[serde(default)]
1269    #[to_code_literal(rename = "ambient_color", expr, optional)]
1270    pub ambient_color_expr: Option<String>,
1271    /// Optional ambient intensity.
1272    #[serde(default)]
1273    #[to_code_literal(optional)]
1274    pub ambient_intensity: Option<f32>,
1275    /// Optional ray-origin jitter distance in meters.
1276    #[serde(default)]
1277    #[to_code_literal(optional)]
1278    pub jitter: Option<f32>,
1279    /// Optional raymarch step count.
1280    #[serde(default)]
1281    #[to_code_literal(optional)]
1282    pub step_count: Option<u32>,
1283}
1284
1285/// Parameters for `bevy_render__fog_volume`.
1286#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1287#[to_code_literal(path = "::bevy::light::FogVolume", default_update)]
1288pub struct BevyFogVolumeParams {
1289    /// Optional fog color expression.
1290    #[serde(default)]
1291    #[to_code_literal(rename = "fog_color", expr, optional)]
1292    pub fog_color_expr: Option<String>,
1293    /// Optional density factor.
1294    #[serde(default)]
1295    #[to_code_literal(optional)]
1296    pub density_factor: Option<f32>,
1297    /// Optional density-texture handle expression.
1298    #[serde(default)]
1299    #[to_code_literal(rename = "density_texture", optional, to_tokens = "some_expr_tokens")]
1300    pub density_texture_expr: Option<String>,
1301    /// Optional density-texture offset expression.
1302    #[serde(default)]
1303    #[to_code_literal(rename = "density_texture_offset", expr, optional)]
1304    pub density_texture_offset_expr: Option<String>,
1305    /// Optional absorption coefficient.
1306    #[serde(default)]
1307    #[to_code_literal(optional)]
1308    pub absorption: Option<f32>,
1309    /// Optional scattering coefficient.
1310    #[serde(default)]
1311    #[to_code_literal(optional)]
1312    pub scattering: Option<f32>,
1313    /// Optional anisotropy factor.
1314    #[serde(default)]
1315    #[to_code_literal(optional)]
1316    pub scattering_asymmetry: Option<f32>,
1317    /// Optional nonphysical light tint expression.
1318    #[serde(default)]
1319    #[to_code_literal(rename = "light_tint", expr, optional)]
1320    pub light_tint_expr: Option<String>,
1321    /// Optional nonphysical light intensity scale.
1322    #[serde(default)]
1323    #[to_code_literal(optional)]
1324    pub light_intensity: Option<f32>,
1325}
1326
1327/// Parameters for `bevy_render__light_probe`.
1328#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1329#[to_code_literal(path = "::bevy::light::LightProbe")]
1330pub struct BevyLightProbeParams;
1331
1332/// Parameters for `bevy_render__irradiance_volume`.
1333#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1334#[to_code_literal(path = "::bevy::light::IrradianceVolume", default_update)]
1335pub struct BevyIrradianceVolumeParams {
1336    /// Expression that yields the irradiance voxel texture handle.
1337    #[to_code_literal(rename = "voxels", expr)]
1338    pub voxels_expr: String,
1339    /// Optional radiance scale factor.
1340    #[serde(default)]
1341    #[to_code_literal(optional)]
1342    pub intensity: Option<f32>,
1343    /// Optional flag controlling whether the probe affects lightmapped meshes.
1344    #[serde(default)]
1345    #[to_code_literal(optional)]
1346    pub affects_lightmapped_meshes: Option<bool>,
1347}
1348
1349/// Parameters for `bevy_render__sun_disk`.
1350#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1351#[to_code_literal(path = "::bevy::light::SunDisk", default_update)]
1352pub struct BevySunDiskParams {
1353    /// Optional angular size in radians.
1354    #[serde(default)]
1355    #[to_code_literal(optional)]
1356    pub angular_size: Option<f32>,
1357    /// Optional brightness multiplier.
1358    #[serde(default)]
1359    #[to_code_literal(optional)]
1360    pub intensity: Option<f32>,
1361}
1362
1363/// Parameters for `bevy_render__not_shadow_caster`.
1364#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1365#[to_code_literal(path = "::bevy::light::NotShadowCaster")]
1366pub struct BevyNotShadowCasterParams;
1367
1368/// Parameters for `bevy_render__not_shadow_receiver`.
1369#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1370#[to_code_literal(path = "::bevy::light::NotShadowReceiver")]
1371pub struct BevyNotShadowReceiverParams;
1372
1373/// Parameters for `bevy_render__transmitted_shadow_receiver`.
1374#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1375#[to_code_literal(path = "::bevy::light::TransmittedShadowReceiver")]
1376pub struct BevyTransmittedShadowReceiverParams;
1377
1378/// Supported `ShadowFilteringMethod` variants.
1379#[derive(
1380    Debug,
1381    Clone,
1382    Copy,
1383    Serialize,
1384    Deserialize,
1385    JsonSchema,
1386    PartialEq,
1387    Eq,
1388    elicitation::ToCodeLiteral,
1389)]
1390#[serde(rename_all = "snake_case")]
1391#[to_code_literal(path = "::bevy::light::ShadowFilteringMethod")]
1392pub enum BevyShadowFilteringMethodVariant {
1393    /// `ShadowFilteringMethod::Hardware2x2`
1394    Hardware2x2,
1395    /// `ShadowFilteringMethod::Gaussian`
1396    Gaussian,
1397    /// `ShadowFilteringMethod::Temporal`
1398    Temporal,
1399}
1400
1401/// Parameters for `bevy_render__shadow_filtering_method`.
1402#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1403#[to_code_literal(transparent)]
1404pub struct BevyShadowFilteringMethodParams {
1405    /// Filtering mode to emit.
1406    pub variant: BevyShadowFilteringMethodVariant,
1407}
1408
1409/// Supported `ClusterFarZMode` variants.
1410#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1411#[serde(rename_all = "snake_case")]
1412pub enum BevyClusterFarZModeKind {
1413    /// `ClusterFarZMode::MaxClusterableObjectRange`
1414    MaxClusterableObjectRange,
1415    /// `ClusterFarZMode::Constant(value)`
1416    Constant,
1417}
1418
1419/// Parameters for `bevy_render__cluster_far_z_mode`.
1420#[derive(
1421    Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, elicitation::ToCodeLiteral,
1422)]
1423#[serde(tag = "kind", content = "constant", rename_all = "snake_case")]
1424#[to_code_literal(path = "::bevy::light::ClusterFarZMode")]
1425pub enum BevyClusterFarZModeParams {
1426    /// Use Bevy's max-clusterable-object-range heuristic.
1427    MaxClusterableObjectRange,
1428    /// Use a fixed far-z value.
1429    Constant(f32),
1430}
1431
1432/// Parameters for `bevy_render__cluster_z_config`.
1433#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1434#[to_code_literal(
1435    path = "::bevy::light::ClusterZConfig",
1436    default_update,
1437    default_expr = "::std::default::Default::default()"
1438)]
1439pub struct BevyClusterZConfigParams {
1440    /// Optional far plane for the first slice.
1441    #[serde(default)]
1442    #[to_code_literal(optional)]
1443    pub first_slice_depth: Option<f32>,
1444    /// Optional far-z strategy override.
1445    #[serde(default)]
1446    #[to_code_literal(rename = "far_z_mode", optional, to_tokens = "emit_code_tokens")]
1447    pub far_z_mode: Option<BevyClusterFarZModeParams>,
1448}
1449
1450/// Parameters for `bevy_render__cluster_config`.
1451#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1452#[serde(tag = "kind", rename_all = "snake_case")]
1453#[to_code_literal(path = "::bevy::light::ClusterConfig")]
1454pub enum BevyClusterConfigParams {
1455    /// `ClusterConfig::None`
1456    None,
1457    /// `ClusterConfig::Single`
1458    Single,
1459    /// `ClusterConfig::XYZ { .. }`
1460    #[serde(rename = "xyz")]
1461    XYZ {
1462        /// Explicit cluster dimensions for the XYZ grid.
1463        #[to_code_literal(to_tokens = "uvec3_array_tokens")]
1464        dimensions: [u32; 3],
1465        /// Optional z-configuration override.
1466        #[serde(default)]
1467        z_config: BevyClusterZConfigParams,
1468        /// Whether the cluster grid may dynamically resize.
1469        #[serde(default = "default_true")]
1470        dynamic_resizing: bool,
1471    },
1472    /// `ClusterConfig::FixedZ { .. }`
1473    FixedZ {
1474        /// Maximum total clusters.
1475        total: u32,
1476        /// Number of z-slices.
1477        z_slices: u32,
1478        /// Optional z-configuration override.
1479        #[serde(default)]
1480        z_config: BevyClusterZConfigParams,
1481        /// Whether the cluster grid may dynamically resize.
1482        #[serde(default = "default_true")]
1483        dynamic_resizing: bool,
1484    },
1485}
1486
1487/// Parameters for `bevy_render__screen_space_reflections`.
1488#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1489#[to_code_literal(path = "::bevy::pbr::ScreenSpaceReflections", default_update)]
1490pub struct BevyScreenSpaceReflectionsParams {
1491    /// Optional roughness threshold.
1492    #[serde(default)]
1493    #[to_code_literal(optional)]
1494    pub perceptual_roughness_threshold: Option<f32>,
1495    /// Optional assumed surface thickness.
1496    #[serde(default)]
1497    #[to_code_literal(optional)]
1498    pub thickness: Option<f32>,
1499    /// Optional number of linear marching steps.
1500    #[serde(default)]
1501    #[to_code_literal(optional)]
1502    pub linear_steps: Option<u32>,
1503    /// Optional exponent for the linear march distribution.
1504    #[serde(default)]
1505    #[to_code_literal(optional)]
1506    pub linear_march_exponent: Option<f32>,
1507    /// Optional number of bisection steps.
1508    #[serde(default)]
1509    #[to_code_literal(optional)]
1510    pub bisection_steps: Option<u32>,
1511    /// Optional secant-method toggle.
1512    #[serde(default)]
1513    #[to_code_literal(optional)]
1514    pub use_secant: Option<bool>,
1515}
1516
1517/// Parameters for `bevy_render__clustered_decal`.
1518#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1519#[to_code_literal(path = "::bevy::light::ClusteredDecal", default_update)]
1520pub struct BevyClusteredDecalParams {
1521    /// Optional base-color decal texture handle expression.
1522    #[serde(default)]
1523    #[to_code_literal(
1524        rename = "base_color_texture",
1525        optional,
1526        to_tokens = "some_expr_tokens"
1527    )]
1528    pub base_color_texture_expr: Option<String>,
1529    /// Optional normal-map decal texture handle expression.
1530    #[serde(default)]
1531    #[to_code_literal(
1532        rename = "normal_map_texture",
1533        optional,
1534        to_tokens = "some_expr_tokens"
1535    )]
1536    pub normal_map_texture_expr: Option<String>,
1537    /// Optional metallic-roughness texture handle expression.
1538    #[serde(default)]
1539    #[to_code_literal(
1540        rename = "metallic_roughness_texture",
1541        optional,
1542        to_tokens = "some_expr_tokens"
1543    )]
1544    pub metallic_roughness_texture_expr: Option<String>,
1545    /// Optional emissive texture handle expression.
1546    #[serde(default)]
1547    #[to_code_literal(rename = "emissive_texture", optional, to_tokens = "some_expr_tokens")]
1548    pub emissive_texture_expr: Option<String>,
1549    /// Optional application-specific tag.
1550    #[serde(default)]
1551    #[to_code_literal(optional)]
1552    pub tag: Option<u32>,
1553}
1554
1555/// Parameters for `bevy_render__mesh_3d`.
1556#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1557#[to_code_literal(path = "::bevy::mesh::Mesh3d", tuple)]
1558pub struct BevyMesh3dParams {
1559    /// Expression that yields a `Handle<Mesh>`.
1560    #[to_code_literal(expr)]
1561    pub mesh_expr: String,
1562}
1563
1564/// Parameters for `bevy_render__mesh_2d`.
1565#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1566#[to_code_literal(path = "::bevy::mesh::Mesh2d", tuple)]
1567pub struct BevyMesh2dParams {
1568    /// Expression that yields a `Handle<Mesh>`.
1569    #[to_code_literal(expr)]
1570    pub mesh_expr: String,
1571}
1572
1573/// Parameters for `bevy_render__mesh_material_3d`.
1574#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1575#[to_code_literal(path = "::bevy::pbr::MeshMaterial3d", tuple)]
1576pub struct BevyMeshMaterial3dParams {
1577    /// Expression that yields a typed material handle.
1578    #[to_code_literal(expr)]
1579    pub material_expr: String,
1580}
1581
1582/// Parameters for `bevy_render__mesh_material_2d`.
1583#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1584#[to_code_literal(path = "::bevy::sprite_render::MeshMaterial2d", tuple)]
1585pub struct BevyMeshMaterial2dParams {
1586    /// Expression that yields a typed 2D material handle.
1587    #[to_code_literal(expr)]
1588    pub material_expr: String,
1589}
1590
1591/// Parameters for `bevy_render__wireframe`.
1592#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1593#[to_code_literal(path = "::bevy::pbr::Wireframe")]
1594pub struct BevyWireframeParams;
1595
1596/// Parameters for `bevy_render__wireframe_color`.
1597#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1598#[to_code_literal(path = "::bevy::pbr::WireframeColor")]
1599pub struct BevyWireframeColorParams {
1600    /// Expression that yields a `Color`.
1601    #[to_code_literal(rename = "color", expr)]
1602    pub color_expr: String,
1603}
1604
1605/// Parameters for `bevy_render__no_wireframe`.
1606#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1607#[to_code_literal(path = "::bevy::pbr::NoWireframe")]
1608pub struct BevyNoWireframeParams;
1609
1610/// Parameters for `bevy_render__wireframe_config`.
1611#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1612#[to_code_literal(
1613    path = "::bevy::pbr::WireframeConfig",
1614    default_update,
1615    default_expr = "::bevy::pbr::WireframeConfig::default()"
1616)]
1617pub struct BevyWireframeConfigParams {
1618    /// Whether all eligible meshes should render in wireframe by default.
1619    #[serde(default)]
1620    #[to_code_literal(optional)]
1621    pub global: Option<bool>,
1622    /// Override for the default wireframe color.
1623    #[serde(default)]
1624    #[to_code_literal(rename = "default_color", expr, optional)]
1625    pub default_color_expr: Option<String>,
1626}
1627
1628/// Parameters for `bevy_render__mesh_3d_wireframe`.
1629#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1630#[to_code_literal(path = "::bevy::pbr::Mesh3dWireframe", tuple)]
1631pub struct BevyMesh3dWireframeParams {
1632    /// Expression that yields a `Handle<WireframeMaterial>`.
1633    #[to_code_literal(expr)]
1634    pub material_expr: String,
1635}
1636
1637/// Parameters for `bevy_render__wireframe_2d`.
1638#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1639#[to_code_literal(path = "::bevy::sprite_render::Wireframe2d")]
1640pub struct BevyWireframe2dParams;
1641
1642/// Parameters for `bevy_render__wireframe_2d_color`.
1643#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1644#[to_code_literal(path = "::bevy::sprite_render::Wireframe2dColor")]
1645pub struct BevyWireframe2dColorParams {
1646    /// Expression that yields a `Color`.
1647    #[to_code_literal(rename = "color", expr)]
1648    pub color_expr: String,
1649}
1650
1651/// Parameters for `bevy_render__no_wireframe_2d`.
1652#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1653#[to_code_literal(path = "::bevy::sprite_render::NoWireframe2d")]
1654pub struct BevyNoWireframe2dParams;
1655
1656/// Parameters for `bevy_render__wireframe_2d_config`.
1657#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1658#[to_code_literal(
1659    path = "::bevy::sprite_render::Wireframe2dConfig",
1660    default_update,
1661    default_expr = "::bevy::sprite_render::Wireframe2dConfig::default()"
1662)]
1663pub struct BevyWireframe2dConfigParams {
1664    /// Whether all eligible 2D meshes should render in wireframe by default.
1665    #[serde(default)]
1666    #[to_code_literal(optional)]
1667    pub global: Option<bool>,
1668    /// Override for the default 2D wireframe color.
1669    #[serde(default)]
1670    #[to_code_literal(rename = "default_color", expr, optional)]
1671    pub default_color_expr: Option<String>,
1672}
1673
1674/// Parameters for `bevy_render__mesh_2d_wireframe`.
1675#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1676#[to_code_literal(path = "::bevy::sprite_render::Mesh2dWireframe", tuple)]
1677pub struct BevyMesh2dWireframeParams {
1678    /// Expression that yields a `Handle<Wireframe2dMaterial>`.
1679    #[to_code_literal(expr)]
1680    pub material_expr: String,
1681}
1682
1683/// Parameters for `bevy_render__camera_3d`.
1684#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
1685pub struct BevyCamera3dParams {
1686    /// Commands-like receiver expression.
1687    #[serde(default = "default_commands_var")]
1688    pub commands_var: String,
1689    /// Optional transform expression.
1690    #[serde(default)]
1691    pub transform_expr: Option<String>,
1692    /// Optional perspective FOV in radians.
1693    #[serde(default)]
1694    pub fov: Option<f32>,
1695    /// Optional near clip plane.
1696    #[serde(default)]
1697    pub near: Option<f32>,
1698    /// Optional far clip plane.
1699    #[serde(default)]
1700    pub far: Option<f32>,
1701    /// Optional explicit HDR override on `Camera`.
1702    #[serde(default)]
1703    pub hdr: Option<bool>,
1704    /// Optional render-target descriptor.
1705    #[serde(default)]
1706    pub render_target: Option<BevyRenderTargetParams>,
1707    /// Optional tonemapping expression.
1708    #[serde(default)]
1709    pub tonemapping_expr: Option<String>,
1710}
1711
1712/// Parameters for `bevy_render__camera_2d`.
1713#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
1714pub struct BevyCamera2dParams {
1715    /// Commands-like receiver expression.
1716    #[serde(default = "default_commands_var")]
1717    pub commands_var: String,
1718    /// Optional transform expression.
1719    #[serde(default)]
1720    pub transform_expr: Option<String>,
1721    /// Optional orthographic near clip plane.
1722    #[serde(default)]
1723    pub near: Option<f32>,
1724    /// Optional orthographic far clip plane.
1725    #[serde(default)]
1726    pub far: Option<f32>,
1727    /// Optional orthographic scale.
1728    #[serde(default)]
1729    pub scale: Option<f32>,
1730    /// Optional explicit HDR override on `Camera`.
1731    #[serde(default)]
1732    pub hdr: Option<bool>,
1733    /// Optional render-target descriptor.
1734    #[serde(default)]
1735    pub render_target: Option<BevyRenderTargetParams>,
1736    /// Optional tonemapping expression.
1737    #[serde(default)]
1738    pub tonemapping_expr: Option<String>,
1739}
1740
1741/// Parameters for `bevy_render__viewport`.
1742#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1743#[to_code_literal(path = "::bevy::camera::Viewport")]
1744pub struct BevyViewportParams {
1745    /// Physical top-left position in pixels.
1746    #[to_code_literal(to_tokens = "uvec2_array_tokens")]
1747    pub physical_position: [u32; 2],
1748    /// Physical size in pixels.
1749    #[to_code_literal(to_tokens = "uvec2_array_tokens")]
1750    pub physical_size: [u32; 2],
1751    /// Optional depth range `[min, max]`.
1752    #[serde(default)]
1753    #[to_code_literal(to_tokens = "viewport_depth_tokens")]
1754    pub depth: Option<[f32; 2]>,
1755}
1756
1757/// Parameters for `bevy_render__fog_settings`.
1758#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1759#[to_code_literal(path = "::bevy::pbr::DistanceFog", default_update)]
1760pub struct BevyFogSettingsParams {
1761    /// Optional fog color expression.
1762    #[serde(default)]
1763    #[to_code_literal(rename = "color", optional, to_tokens = "into_expr_tokens")]
1764    pub color_expr: Option<String>,
1765    /// Optional directional-light contribution color expression.
1766    #[serde(default)]
1767    #[to_code_literal(
1768        rename = "directional_light_color",
1769        optional,
1770        to_tokens = "into_expr_tokens"
1771    )]
1772    pub directional_light_color_expr: Option<String>,
1773    /// Optional directional-light exponent.
1774    #[serde(default)]
1775    #[to_code_literal(optional)]
1776    pub directional_light_exponent: Option<f32>,
1777    /// Optional `FogFalloff` expression.
1778    #[serde(default)]
1779    #[to_code_literal(rename = "falloff", expr, optional)]
1780    pub falloff_expr: Option<String>,
1781}
1782
1783/// Preset bloom configurations available in Bevy 0.18.
1784#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1785#[serde(rename_all = "snake_case")]
1786pub enum BevyBloomPreset {
1787    /// `Bloom::NATURAL`
1788    Natural,
1789    /// `Bloom::ANAMORPHIC`
1790    Anamorphic,
1791    /// `Bloom::OLD_SCHOOL`
1792    OldSchool,
1793    /// `Bloom::SCREEN_BLUR`
1794    ScreenBlur,
1795}
1796
1797/// Supported bloom composite modes.
1798#[derive(
1799    Debug,
1800    Clone,
1801    Copy,
1802    Serialize,
1803    Deserialize,
1804    JsonSchema,
1805    PartialEq,
1806    Eq,
1807    elicitation::ToCodeLiteral,
1808)]
1809#[serde(rename_all = "snake_case")]
1810#[to_code_literal(path = "::bevy::post_process::bloom::BloomCompositeMode")]
1811pub enum BevyBloomCompositeModeVariant {
1812    /// `BloomCompositeMode::EnergyConserving`
1813    EnergyConserving,
1814    /// `BloomCompositeMode::Additive`
1815    Additive,
1816}
1817
1818/// Parameters for `bevy_render__bloom_composite_mode`.
1819#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1820#[to_code_literal(transparent)]
1821pub struct BevyBloomCompositeModeParams {
1822    /// Bloom composite mode to emit.
1823    pub variant: BevyBloomCompositeModeVariant,
1824}
1825
1826/// Parameters for `bevy_render__bloom_settings`.
1827#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
1828pub struct BevyBloomSettingsParams {
1829    /// Optional starting preset.
1830    #[serde(default)]
1831    pub preset: Option<BevyBloomPreset>,
1832    /// Optional bloom intensity override.
1833    #[serde(default)]
1834    pub intensity: Option<f32>,
1835    /// Optional low-frequency boost override.
1836    #[serde(default)]
1837    pub low_frequency_boost: Option<f32>,
1838    /// Optional low-frequency boost curvature override.
1839    #[serde(default)]
1840    pub low_frequency_boost_curvature: Option<f32>,
1841    /// Optional high-pass frequency override.
1842    #[serde(default)]
1843    pub high_pass_frequency: Option<f32>,
1844    /// Optional bloom prefilter threshold override.
1845    #[serde(default)]
1846    pub prefilter_threshold: Option<f32>,
1847    /// Optional bloom prefilter threshold softness override.
1848    #[serde(default)]
1849    pub prefilter_threshold_softness: Option<f32>,
1850    /// Optional bloom composite mode override.
1851    #[serde(default)]
1852    pub composite_mode: Option<BevyBloomCompositeModeVariant>,
1853    /// Optional max-mip-dimension override.
1854    #[serde(default)]
1855    pub max_mip_dimension: Option<u32>,
1856    /// Optional `Vec2` scale expression.
1857    #[serde(default)]
1858    pub scale_expr: Option<String>,
1859}
1860
1861/// Parameters for `bevy_render__sprite`.
1862#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1863#[to_code_literal(
1864    path = "::bevy::sprite::Sprite",
1865    default_update,
1866    default_expr = "::bevy::sprite::Sprite { ..::std::default::Default::default() }"
1867)]
1868pub struct BevySpriteParams {
1869    /// Optional image handle expression.
1870    #[serde(default)]
1871    #[to_code_literal(rename = "image", expr, optional)]
1872    pub image_expr: Option<String>,
1873    /// Optional tint color expression.
1874    #[serde(default)]
1875    #[to_code_literal(rename = "color", optional, to_tokens = "into_expr_tokens")]
1876    pub color_expr: Option<String>,
1877    /// Whether the sprite should be flipped on X.
1878    #[serde(default)]
1879    #[to_code_literal(optional)]
1880    pub flip_x: Option<bool>,
1881    /// Whether the sprite should be flipped on Y.
1882    #[serde(default)]
1883    #[to_code_literal(optional)]
1884    pub flip_y: Option<bool>,
1885    /// Optional custom-size expression.
1886    #[serde(default)]
1887    #[to_code_literal(rename = "custom_size", optional, to_tokens = "some_expr_tokens")]
1888    pub custom_size_expr: Option<String>,
1889}
1890
1891#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1892#[to_code_literal(
1893    path = "::bevy::text::TextFont",
1894    default_update,
1895    default_expr = "::bevy::text::TextFont::default()"
1896)]
1897struct BevyTextFontParams {
1898    /// Optional font handle expression.
1899    #[serde(default)]
1900    #[to_code_literal(rename = "font", expr, optional)]
1901    font_handle_expr: Option<String>,
1902    /// Optional font size in logical pixels.
1903    #[serde(default)]
1904    #[to_code_literal(optional)]
1905    font_size: Option<f32>,
1906}
1907
1908#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1909#[to_code_literal(transparent)]
1910struct BevyTextColorParams {
1911    /// Optional text color expression.
1912    #[serde(default)]
1913    #[to_code_literal(to_tokens = "text_color_tokens")]
1914    color_expr: Option<String>,
1915}
1916
1917#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, elicitation::ToCodeLiteral)]
1918#[to_code_literal(
1919    path = "::bevy::text::TextLayout",
1920    default_update,
1921    default_expr = "::bevy::text::TextLayout::default()"
1922)]
1923struct BevyTextLayoutParams {
1924    /// Optional `Justify` expression.
1925    #[serde(default)]
1926    #[to_code_literal(rename = "justify", expr, optional)]
1927    justify_expr: Option<String>,
1928    /// Optional `LineBreak` expression.
1929    #[serde(default)]
1930    #[to_code_literal(rename = "linebreak", expr, optional)]
1931    linebreak_expr: Option<String>,
1932}
1933
1934/// Parameters for `bevy_render__text_style`.
1935#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1936#[to_code_literal(raw_tuple)]
1937pub struct BevyTextStyleParams {
1938    /// Font tuple fragment fields.
1939    #[serde(flatten)]
1940    font: BevyTextFontParams,
1941    /// Color tuple fragment fields.
1942    #[serde(flatten)]
1943    color: BevyTextColorParams,
1944    /// Layout tuple fragment fields.
1945    #[serde(flatten)]
1946    layout: BevyTextLayoutParams,
1947}
1948
1949/// SSAO quality variants in Bevy 0.18.
1950#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1951#[serde(rename_all = "snake_case")]
1952pub enum BevySsaoQualityVariant {
1953    /// `ScreenSpaceAmbientOcclusionQualityLevel::Low`
1954    Low,
1955    /// `ScreenSpaceAmbientOcclusionQualityLevel::Medium`
1956    Medium,
1957    /// `ScreenSpaceAmbientOcclusionQualityLevel::High`
1958    High,
1959    /// `ScreenSpaceAmbientOcclusionQualityLevel::Ultra`
1960    Ultra,
1961    /// `ScreenSpaceAmbientOcclusionQualityLevel::Custom { .. }`
1962    Custom,
1963}
1964
1965/// Parameters for `bevy_render__ssao_quality`.
1966#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1967#[serde(tag = "variant", rename_all = "snake_case")]
1968#[to_code_literal(path = "::bevy::pbr::ScreenSpaceAmbientOcclusionQualityLevel")]
1969pub enum BevySsaoQualityParams {
1970    /// `ScreenSpaceAmbientOcclusionQualityLevel::Low`
1971    Low,
1972    /// `ScreenSpaceAmbientOcclusionQualityLevel::Medium`
1973    Medium,
1974    /// `ScreenSpaceAmbientOcclusionQualityLevel::High`
1975    High,
1976    /// `ScreenSpaceAmbientOcclusionQualityLevel::Ultra`
1977    Ultra,
1978    /// `ScreenSpaceAmbientOcclusionQualityLevel::Custom { .. }`
1979    Custom {
1980        /// Custom slice count.
1981        slice_count: u32,
1982        /// Custom samples-per-slice-side.
1983        samples_per_slice_side: u32,
1984    },
1985}
1986
1987/// Parameters for `bevy_render__ssao`.
1988#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
1989#[to_code_literal(path = "::bevy::pbr::ScreenSpaceAmbientOcclusion", default_update)]
1990pub struct BevySsaoParams {
1991    /// Optional SSAO quality-level payload.
1992    #[serde(default)]
1993    #[to_code_literal(optional, to_tokens = "emit_code_tokens")]
1994    pub quality_level: Option<BevySsaoQualityParams>,
1995    /// Optional constant estimated object thickness.
1996    #[serde(default)]
1997    #[to_code_literal(optional)]
1998    pub constant_object_thickness: Option<f32>,
1999}
2000
2001/// Parameters for `bevy_render__temporal_anti_aliasing`.
2002#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
2003#[to_code_literal(path = "::bevy::anti_alias::taa::TemporalAntiAliasing", default_update)]
2004pub struct BevyTemporalAntiAliasingParams {
2005    /// Optional reset flag; defaults to Bevy's `TemporalAntiAliasing::default()`.
2006    #[serde(default)]
2007    #[to_code_literal(optional)]
2008    pub reset: Option<bool>,
2009}
2010
2011#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
2012#[to_code_literal(transparent)]
2013struct BevyCascadeShadowBoundsParams(
2014    #[to_code_literal(to_tokens = "cascade_bounds_tokens")] Vec<f32>,
2015);
2016
2017/// Parameters for `bevy_render__cascade_shadow_config`.
2018#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
2019#[to_code_literal(
2020    path = "::bevy::light::CascadeShadowConfig",
2021    default_update,
2022    default_expr = "::bevy::light::CascadeShadowConfig::default()"
2023)]
2024pub struct BevyCascadeShadowConfigParams {
2025    /// Optional explicit cascade far bounds.
2026    #[serde(
2027        default,
2028        deserialize_with = "deserialize_optional_cascade_bounds",
2029        skip_serializing_if = "Option::is_none"
2030    )]
2031    #[to_code_literal(optional)]
2032    bounds: Option<BevyCascadeShadowBoundsParams>,
2033    /// Optional overlap proportion between cascades.
2034    #[serde(default)]
2035    #[to_code_literal(optional)]
2036    pub overlap_proportion: Option<f32>,
2037    /// Optional near boundary of the first cascade.
2038    #[serde(default)]
2039    #[to_code_literal(optional)]
2040    pub minimum_distance: Option<f32>,
2041}
2042
2043/// Parameters for `bevy_render__cascade_shadow_config_builder`.
2044#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, elicitation::ToCodeLiteral)]
2045#[to_code_literal(path = "::bevy::light::CascadeShadowConfigBuilder", default_update)]
2046pub struct BevyCascadeShadowConfigBuilderParams {
2047    /// Optional number of cascades.
2048    #[serde(default)]
2049    #[to_code_literal(optional)]
2050    pub num_cascades: Option<usize>,
2051    /// Optional minimum shadow distance.
2052    #[serde(default)]
2053    #[to_code_literal(optional)]
2054    pub minimum_distance: Option<f32>,
2055    /// Optional maximum shadow distance.
2056    #[serde(default)]
2057    #[to_code_literal(optional)]
2058    pub maximum_distance: Option<f32>,
2059    /// Optional far bound of the first cascade.
2060    #[serde(default)]
2061    #[to_code_literal(optional)]
2062    pub first_cascade_far_bound: Option<f32>,
2063    /// Optional overlap proportion between cascades.
2064    #[serde(default)]
2065    #[to_code_literal(optional)]
2066    pub overlap_proportion: Option<f32>,
2067}
2068
2069/// Render-graph family used by `bevy_render__fullscreen_material`.
2070#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2071#[serde(rename_all = "snake_case")]
2072#[derive(Default)]
2073pub enum BevyFullscreenGraphKind {
2074    /// Generate `Node2d` post-processing edges.
2075    Core2d,
2076    /// Generate `Node3d` post-processing edges.
2077    #[default]
2078    Core3d,
2079}
2080
2081fn default_parallax_relief_max_steps() -> u32 {
2082    32
2083}
2084
2085fn default_render_alpha_mode_threshold() -> f32 {
2086    0.5
2087}
2088
2089fn default_camera_3d_depth_clear() -> f32 {
2090    0.0
2091}
2092
2093/// Parameters for `bevy_render__atmosphere`.
2094#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
2095pub struct BevyAtmosphereParams {
2096    /// `Assets<ScatteringMedium>` resource expression used to add the generated medium.
2097    #[serde(default = "default_scattering_media_var")]
2098    pub scattering_media_var: String,
2099    /// Optional explicit atmosphere component fields. When omitted, emit `Atmosphere::earthlike`.
2100    #[serde(default)]
2101    pub atmosphere: Option<BevyAtmosphere>,
2102    /// Optional label applied to the generated scattering medium.
2103    #[serde(default)]
2104    pub medium_label: Option<String>,
2105    /// Resolution used to sample each term's falloff distribution.
2106    #[serde(default = "default_scattering_resolution")]
2107    pub falloff_resolution: u32,
2108    /// Resolution used to sample each term's phase function.
2109    #[serde(default = "default_scattering_resolution")]
2110    pub phase_resolution: u32,
2111    /// Optional custom scattering terms. When omitted, emit `ScatteringMedium::earthlike`.
2112    #[serde(default)]
2113    pub terms: Vec<BevyScatteringTerm>,
2114    /// Optional density multiplier applied after building the medium.
2115    #[serde(default)]
2116    pub density_multiplier: Option<f32>,
2117}
2118
2119/// Parameters for `bevy_render__fullscreen_material`.
2120#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
2121pub struct BevyFullscreenMaterialParams {
2122    /// Type implementing `FullscreenMaterial`, e.g. `FullscreenEffect`.
2123    pub material_type: String,
2124    /// Asset path for the fragment shader.
2125    pub shader_path: String,
2126    /// Which core render graph to target.
2127    #[serde(default)]
2128    pub graph: BevyFullscreenGraphKind,
2129    /// Optional starting edge label expression.
2130    #[serde(default)]
2131    pub start_node_expr: Option<String>,
2132    /// Optional ending edge label expression.
2133    #[serde(default)]
2134    pub end_node_expr: Option<String>,
2135}
2136
2137fn default_commands_var() -> String {
2138    "commands".to_string()
2139}
2140
2141fn default_true() -> bool {
2142    true
2143}
2144
2145fn default_scattering_media_var() -> String {
2146    "scattering_media".to_string()
2147}
2148
2149fn default_scattering_resolution() -> u32 {
2150    256
2151}
2152
2153fn tool_err(msg: impl std::fmt::Display) -> ErrorData {
2154    ErrorData::invalid_params(msg.to_string(), None)
2155}
2156
2157fn ok_source(source: String) -> Result<CallToolResult, ErrorData> {
2158    Ok(CallToolResult::success(vec![Content::text(source)]))
2159}
2160
2161fn parse_expr(src: &str, context: &str) -> Result<syn::Expr, ErrorData> {
2162    syn::parse_str::<syn::Expr>(src)
2163        .map_err(|error| tool_err(format!("invalid {context} expression `{src}`: {error}")))
2164}
2165
2166fn parse_type(src: &str, context: &str) -> Result<syn::Type, ErrorData> {
2167    syn::parse_str::<syn::Type>(src)
2168        .map_err(|error| tool_err(format!("invalid {context} type `{src}`: {error}")))
2169}
2170
2171fn expr_tokens(src: &str, context: &str) -> syn::Expr {
2172    parse_expr(src, context).expect("validated expressions must parse")
2173}
2174
2175fn type_tokens(src: &str, context: &str) -> syn::Type {
2176    parse_type(src, context).expect("validated types must parse")
2177}
2178
2179fn uvec2_array_tokens(value: &[u32; 2]) -> TokenStream {
2180    let [x, y] = *value;
2181    quote! { ::bevy::math::UVec2::new(#x, #y) }
2182}
2183
2184fn viewport_depth_tokens(depth: &Option<[f32; 2]>) -> TokenStream {
2185    let [min, max] = depth.unwrap_or([0.0, 1.0]);
2186    quote! { #min..#max }
2187}
2188
2189fn uvec3_array_tokens(value: &[u32; 3]) -> TokenStream {
2190    let [x, y, z] = *value;
2191    quote! { ::bevy::math::UVec3::new(#x, #y, #z) }
2192}
2193
2194fn some_expr_tokens(value: &str) -> TokenStream {
2195    let expr = expr_tokens(value, "optional expression field");
2196    quote! { Some(#expr) }
2197}
2198
2199fn into_expr_tokens(value: &str) -> TokenStream {
2200    let expr = expr_tokens(value, "into expression field");
2201    quote! { (#expr).into() }
2202}
2203
2204fn text_color_tokens(value: &Option<String>) -> TokenStream {
2205    match value.as_deref() {
2206        Some(expr) => {
2207            let expr = expr_tokens(expr, "text color");
2208            quote! { ::bevy::text::TextColor((#expr).into()) }
2209        }
2210        None => quote! { ::bevy::text::TextColor::default() },
2211    }
2212}
2213
2214fn cascade_bounds_tokens(value: &[f32]) -> TokenStream {
2215    let bounds = value.iter().map(|bound| quote! { #bound });
2216    quote! { vec![#(#bounds),*] }
2217}
2218
2219fn deserialize_optional_cascade_bounds<'de, D>(
2220    deserializer: D,
2221) -> Result<Option<BevyCascadeShadowBoundsParams>, D::Error>
2222where
2223    D: Deserializer<'de>,
2224{
2225    let bounds = Option::<Vec<f32>>::deserialize(deserializer)?;
2226    Ok(bounds
2227        .filter(|values| !values.is_empty())
2228        .map(BevyCascadeShadowBoundsParams))
2229}
2230
2231fn emit_code_tokens<T: EmitCode>(value: &T) -> TokenStream {
2232    value.emit_code()
2233}
2234
2235fn bevy_dep() -> Vec<CrateDep> {
2236    vec![CrateDep::new("bevy", "0.18")]
2237}
2238
2239macro_rules! impl_bevy_literal_emit {
2240    ($($ty:ty),+ $(,)?) => {
2241        $(
2242            impl EmitCode for $ty {
2243                fn emit_code(&self) -> TokenStream {
2244                    self.to_code_literal()
2245                }
2246
2247                fn crate_deps(&self) -> Vec<CrateDep> {
2248                    bevy_dep()
2249                }
2250            }
2251        )+
2252    };
2253}
2254
2255fn validate_optional_expr(src: &Option<String>, context: &str) -> Result<(), ErrorData> {
2256    if let Some(src) = src {
2257        let _ = parse_expr(src, context)?;
2258    }
2259    Ok(())
2260}
2261
2262pub(crate) fn validate_render_target(params: &BevyRenderTargetParams) -> Result<(), ErrorData> {
2263    match params.fields.kind {
2264        BevyRenderTargetKind::PrimaryWindow => {
2265            if params.fields.target_expr.is_some() {
2266                return Err(tool_err(
2267                    "primary_window render target does not accept target_expr",
2268                ));
2269            }
2270        }
2271        BevyRenderTargetKind::WindowEntity
2272        | BevyRenderTargetKind::Image
2273        | BevyRenderTargetKind::TextureView => {
2274            let target = params
2275                .fields
2276                .target_expr
2277                .as_deref()
2278                .ok_or_else(|| tool_err("render target kind requires target_expr"))?;
2279            let _ = parse_expr(target, "render target")?;
2280        }
2281    }
2282    Ok(())
2283}
2284
2285fn validate_order_independent_transparency_settings(
2286    params: &BevyOrderIndependentTransparencySettingsParams,
2287) -> Result<(), ErrorData> {
2288    if let Some(layer_count) = params.layer_count
2289        && layer_count <= 0
2290    {
2291        return Err(tool_err(
2292            "order independent transparency layer_count must be positive",
2293        ));
2294    }
2295    if let Some(alpha_threshold) = params.alpha_threshold {
2296        if !alpha_threshold.is_finite() {
2297            return Err(tool_err(
2298                "order independent transparency alpha_threshold must be finite",
2299            ));
2300        }
2301        if alpha_threshold < 0.0 {
2302            return Err(tool_err(
2303                "order independent transparency alpha_threshold must be non-negative",
2304            ));
2305        }
2306    }
2307    Ok(())
2308}
2309
2310fn validate_scaling_mode(params: &BevyScalingModeParams) -> Result<(), ErrorData> {
2311    match params {
2312        BevyScalingModeParams::WindowSize => {}
2313        BevyScalingModeParams::Fixed { width, height } => {
2314            validate_optional_non_negative_f32(Some(*width), "scaling mode width")?;
2315            validate_optional_non_negative_f32(Some(*height), "scaling mode height")?;
2316        }
2317        BevyScalingModeParams::AutoMin {
2318            min_width,
2319            min_height,
2320        } => {
2321            validate_optional_non_negative_f32(Some(*min_width), "scaling mode min_width")?;
2322            validate_optional_non_negative_f32(Some(*min_height), "scaling mode min_height")?;
2323        }
2324        BevyScalingModeParams::AutoMax {
2325            max_width,
2326            max_height,
2327        } => {
2328            validate_optional_non_negative_f32(Some(*max_width), "scaling mode max_width")?;
2329            validate_optional_non_negative_f32(Some(*max_height), "scaling mode max_height")?;
2330        }
2331        BevyScalingModeParams::FixedVertical { viewport_height } => {
2332            validate_optional_non_negative_f32(
2333                Some(*viewport_height),
2334                "scaling mode viewport_height",
2335            )?;
2336        }
2337        BevyScalingModeParams::FixedHorizontal { viewport_width } => {
2338            validate_optional_non_negative_f32(
2339                Some(*viewport_width),
2340                "scaling mode viewport_width",
2341            )?;
2342        }
2343    }
2344    Ok(())
2345}
2346
2347pub(crate) fn validate_perspective_projection(
2348    params: &BevyPerspectiveProjectionParams,
2349) -> Result<(), ErrorData> {
2350    validate_optional_expr(&params.near_clip_plane_expr, "near clip plane")?;
2351    validate_optional_non_negative_f32(params.fov, "perspective fov")?;
2352    validate_optional_non_negative_f32(params.aspect_ratio, "perspective aspect_ratio")?;
2353    validate_optional_non_negative_f32(params.near, "perspective near")?;
2354    validate_optional_non_negative_f32(params.far, "perspective far")?;
2355    Ok(())
2356}
2357
2358pub(crate) fn validate_orthographic_projection(
2359    params: &BevyOrthographicProjectionParams,
2360) -> Result<(), ErrorData> {
2361    validate_optional_expr(&params.fields.viewport_origin_expr, "viewport origin")?;
2362    validate_optional_expr(&params.fields.scaling_mode_expr, "scaling mode")?;
2363    validate_optional_expr(&params.fields.area_expr, "orthographic area")?;
2364    validate_optional_finite_f32(params.fields.near, "orthographic near")?;
2365    validate_optional_finite_f32(params.fields.far, "orthographic far")?;
2366    validate_optional_non_negative_f32(params.fields.scale, "orthographic scale")?;
2367    Ok(())
2368}
2369
2370fn validate_clear_color_config(params: &BevyClearColorConfigParams) -> Result<(), ErrorData> {
2371    match params {
2372        BevyClearColorConfigParams::Default | BevyClearColorConfigParams::None => {}
2373        BevyClearColorConfigParams::Custom(color_expr) => {
2374            let _ = parse_expr(color_expr, "clear color")?;
2375        }
2376    }
2377    Ok(())
2378}
2379
2380fn validate_exposure(params: &BevyExposureParams) -> Result<(), ErrorData> {
2381    if params.fields.preset.is_some() && params.fields.ev100.is_some() {
2382        return Err(tool_err(
2383            "exposure accepts either preset or ev100, but not both",
2384        ));
2385    }
2386    validate_optional_finite_f32(params.fields.ev100, "exposure ev100")
2387}
2388
2389fn validate_clear_color(params: &BevyClearColorParams) -> Result<(), ErrorData> {
2390    validate_optional_expr(&params.color_expr, "clear color")
2391}
2392
2393fn validate_camera_3d_depth_load_op(
2394    params: &BevyCamera3dDepthLoadOpParams,
2395) -> Result<(), ErrorData> {
2396    match params {
2397        BevyCamera3dDepthLoadOpParams::Clear { depth } => {
2398            validate_optional_finite_f32(Some(*depth), "camera 3d depth clear value")
2399        }
2400        BevyCamera3dDepthLoadOpParams::Load => Ok(()),
2401    }
2402}
2403
2404fn validate_screen_space_transmission_quality(
2405    _params: &BevyScreenSpaceTransmissionQualityParams,
2406) -> Result<(), ErrorData> {
2407    Ok(())
2408}
2409
2410fn validate_main_pass_resolution_override(
2411    params: &BevyMainPassResolutionOverrideParams,
2412) -> Result<(), ErrorData> {
2413    if params.fields.width == 0 || params.fields.height == 0 {
2414        return Err(tool_err(
2415            "main_pass_resolution_override width and height must be positive",
2416        ));
2417    }
2418    Ok(())
2419}
2420
2421fn validate_sub_camera_view(params: &BevySubCameraViewParams) -> Result<(), ErrorData> {
2422    if params.fields.full_width == 0 || params.fields.full_height == 0 {
2423        return Err(tool_err("sub_camera_view full size must be positive"));
2424    }
2425    if params.fields.width == 0 || params.fields.height == 0 {
2426        return Err(tool_err("sub_camera_view size must be positive"));
2427    }
2428    if !params.fields.offset_x.is_finite() || !params.fields.offset_y.is_finite() {
2429        return Err(tool_err("sub_camera_view offsets must be finite"));
2430    }
2431    Ok(())
2432}
2433
2434fn validate_visibility_range(params: &BevyVisibilityRangeParams) -> Result<(), ErrorData> {
2435    for (value, context) in [
2436        (
2437            params.fields.start_margin_start,
2438            "visibility_range start_margin_start",
2439        ),
2440        (
2441            params.fields.start_margin_end,
2442            "visibility_range start_margin_end",
2443        ),
2444        (
2445            params.fields.end_margin_start,
2446            "visibility_range end_margin_start",
2447        ),
2448        (
2449            params.fields.end_margin_end,
2450            "visibility_range end_margin_end",
2451        ),
2452    ] {
2453        if !value.is_finite() {
2454            return Err(tool_err(format!("{context} must be finite")));
2455        }
2456        if value < 0.0 {
2457            return Err(tool_err(format!("{context} must be non-negative")));
2458        }
2459    }
2460    if params.fields.start_margin_start > params.fields.start_margin_end {
2461        return Err(tool_err(
2462            "visibility_range start_margin_start must be <= start_margin_end",
2463        ));
2464    }
2465    if params.fields.end_margin_start > params.fields.end_margin_end {
2466        return Err(tool_err(
2467            "visibility_range end_margin_start must be <= end_margin_end",
2468        ));
2469    }
2470    if params.fields.start_margin_end > params.fields.end_margin_start {
2471        return Err(tool_err(
2472            "visibility_range start_margin_end must be <= end_margin_start",
2473        ));
2474    }
2475    Ok(())
2476}
2477
2478fn render_target_tokens(params: &BevyRenderTargetFields) -> TokenStream {
2479    match params.kind {
2480        BevyRenderTargetKind::PrimaryWindow => {
2481            quote! {
2482                ::bevy::camera::RenderTarget::Window(::bevy::window::WindowRef::Primary)
2483            }
2484        }
2485        BevyRenderTargetKind::WindowEntity => {
2486            let target = expr_tokens(
2487                params
2488                    .target_expr
2489                    .as_deref()
2490                    .expect("validated render target must have target expr"),
2491                "window entity",
2492            );
2493            quote! {
2494                ::bevy::camera::RenderTarget::Window(::bevy::window::WindowRef::Entity(#target))
2495            }
2496        }
2497        BevyRenderTargetKind::Image => {
2498            let target = expr_tokens(
2499                params
2500                    .target_expr
2501                    .as_deref()
2502                    .expect("validated render target must have target expr"),
2503                "image target",
2504            );
2505            quote! { ::bevy::camera::RenderTarget::Image((#target).into()) }
2506        }
2507        BevyRenderTargetKind::TextureView => {
2508            let target = expr_tokens(
2509                params
2510                    .target_expr
2511                    .as_deref()
2512                    .expect("validated render target must have target expr"),
2513                "texture-view target",
2514            );
2515            quote! { ::bevy::camera::RenderTarget::TextureView(#target) }
2516        }
2517    }
2518}
2519
2520fn orthographic_projection_tokens(params: &BevyOrthographicProjectionFields) -> TokenStream {
2521    let constructor = if params.use_2d_defaults.unwrap_or(false) {
2522        quote! { ::bevy::camera::OrthographicProjection::default_2d() }
2523    } else {
2524        quote! { ::bevy::camera::OrthographicProjection::default_3d() }
2525    };
2526    if params.near.is_none()
2527        && params.far.is_none()
2528        && params.viewport_origin_expr.is_none()
2529        && params.scaling_mode_expr.is_none()
2530        && params.scale.is_none()
2531        && params.area_expr.is_none()
2532    {
2533        constructor
2534    } else {
2535        let near = params
2536            .near
2537            .map(|value| quote! { near: #value, })
2538            .unwrap_or_default();
2539        let far = params
2540            .far
2541            .map(|value| quote! { far: #value, })
2542            .unwrap_or_default();
2543        let viewport_origin = params
2544            .viewport_origin_expr
2545            .as_deref()
2546            .map(|expr| {
2547                let expr = expr_tokens(expr, "viewport origin");
2548                quote! { viewport_origin: #expr, }
2549            })
2550            .unwrap_or_default();
2551        let scaling_mode = params
2552            .scaling_mode_expr
2553            .as_deref()
2554            .map(|expr| {
2555                let expr = expr_tokens(expr, "scaling mode");
2556                quote! { scaling_mode: #expr, }
2557            })
2558            .unwrap_or_default();
2559        let scale = params
2560            .scale
2561            .map(|value| quote! { scale: #value, })
2562            .unwrap_or_default();
2563        let area = params
2564            .area_expr
2565            .as_deref()
2566            .map(|expr| {
2567                let expr = expr_tokens(expr, "orthographic area");
2568                quote! { area: #expr, }
2569            })
2570            .unwrap_or_default();
2571        quote! {
2572            ::bevy::camera::OrthographicProjection {
2573                #near
2574                #far
2575                #viewport_origin
2576                #scaling_mode
2577                #scale
2578                #area
2579                ..#constructor
2580            }
2581        }
2582    }
2583}
2584
2585impl_bevy_literal_emit!(
2586    BevyRenderTargetParams,
2587    BevyTonemappingParams,
2588    BevyDebandDitherParams,
2589    BevyOrderIndependentTransparencySettingsParams,
2590    BevyScalingModeParams,
2591    BevyPerspectiveProjectionParams,
2592    BevyClearColorConfigParams,
2593    BevyExposureParams,
2594    BevyClearColorParams,
2595    BevyMsaaWritebackParams,
2596    BevyCamera3dDepthLoadOpParams,
2597    BevyScreenSpaceTransmissionQualityParams,
2598    BevyMainPassResolutionOverrideParams,
2599    BevySubCameraViewParams,
2600    BevyNoCpuCullingParams,
2601    BevyNoFrustumCullingParams,
2602    BevyVisibilityRangeParams,
2603    BevyColorParams,
2604    BevyRenderAlphaModeParams,
2605    BevyUvChannelParams,
2606    BevyOpaqueRendererMethodParams,
2607    BevyDefaultOpaqueRendererMethodParams,
2608    BevyDepthPrepassParams,
2609    BevyNormalPrepassParams,
2610    BevyMotionVectorPrepassParams,
2611    BevyDeferredPrepassParams,
2612    BevyDepthPrepassDoubleBufferParams,
2613    BevyDeferredPrepassDoubleBufferParams,
2614    BevyAmbientLightParams,
2615    BevyDirectionalLightParams,
2616    BevyGlobalAmbientLightParams,
2617    BevyPointLightParams,
2618    BevySpotLightParams,
2619    BevyDirectionalLightShadowMapParams,
2620    BevyPointLightShadowMapParams,
2621    BevyEnvironmentMapLightParams,
2622    BevyGeneratedEnvironmentMapLightParams,
2623    BevyAtmosphereEnvironmentMapLightParams,
2624    BevyVolumetricLightParams,
2625    BevyVolumetricFogParams,
2626    BevyLightProbeParams,
2627    BevyIrradianceVolumeParams,
2628    BevySunDiskParams,
2629    BevyWireframeColorParams,
2630    BevyWireframeConfigParams,
2631    BevyWireframe2dColorParams,
2632    BevyWireframe2dConfigParams,
2633    BevyNotShadowCasterParams,
2634    BevyNotShadowReceiverParams,
2635    BevyTransmittedShadowReceiverParams,
2636    BevyShadowFilteringMethodParams,
2637    BevyClusterFarZModeParams,
2638    BevyScreenSpaceReflectionsParams,
2639    BevyViewportParams,
2640    BevyBloomCompositeModeParams,
2641    BevyTemporalAntiAliasingParams,
2642    BevyCascadeShadowConfigBuilderParams,
2643    BevyParallaxMappingMethodParams,
2644    BevyLightmapParams,
2645    BevyColorMaterialParams,
2646    BevySkyboxParams,
2647    BevyFogVolumeParams,
2648    BevyFogSettingsParams,
2649    BevySsaoQualityParams,
2650    BevySsaoParams,
2651    BevyClusterZConfigParams,
2652    BevyClusterConfigParams,
2653    BevyAlphaMode2dParams,
2654    BevyMesh3dParams,
2655    BevyMesh2dParams,
2656    BevyMeshMaterial3dParams,
2657    BevyMeshMaterial2dParams,
2658    BevyClusteredDecalParams,
2659    BevyMesh3dWireframeParams,
2660    BevyMesh2dWireframeParams,
2661    BevyWireframeParams,
2662    BevyNoWireframeParams,
2663    BevyWireframe2dParams,
2664    BevyNoWireframe2dParams,
2665    BevySpriteParams,
2666    BevyTextStyleParams,
2667    BevyCascadeShadowConfigParams,
2668    BevyOrthographicProjectionParams,
2669    BevyStandardMaterialParams,
2670);
2671
2672fn emit_uv_channel_variant_tokens(variant: &BevyUvChannelVariant) -> TokenStream {
2673    let variant = match variant {
2674        BevyUvChannelVariant::Uv0 => quote! { Uv0 },
2675        BevyUvChannelVariant::Uv1 => quote! { Uv1 },
2676    };
2677    quote! { ::bevy::pbr::UvChannel::#variant }
2678}
2679
2680fn default_opaque_renderer_method_tokens(
2681    variant: &BevyDefaultOpaqueRendererMethodVariant,
2682) -> TokenStream {
2683    match variant {
2684        BevyDefaultOpaqueRendererMethodVariant::Default => {
2685            quote! { ::bevy::pbr::DefaultOpaqueRendererMethod::default() }
2686        }
2687        BevyDefaultOpaqueRendererMethodVariant::Forward => {
2688            quote! { ::bevy::pbr::DefaultOpaqueRendererMethod::forward() }
2689        }
2690        BevyDefaultOpaqueRendererMethodVariant::Deferred => {
2691            quote! { ::bevy::pbr::DefaultOpaqueRendererMethod::deferred() }
2692        }
2693    }
2694}
2695
2696fn exposure_tokens(fields: &BevyExposureFields) -> TokenStream {
2697    match (fields.preset, fields.ev100) {
2698        (Some(BevyExposurePreset::Sunlight), None) => {
2699            quote! { ::bevy::camera::Exposure::SUNLIGHT }
2700        }
2701        (Some(BevyExposurePreset::Overcast), None) => {
2702            quote! { ::bevy::camera::Exposure::OVERCAST }
2703        }
2704        (Some(BevyExposurePreset::Indoor), None) => {
2705            quote! { ::bevy::camera::Exposure::INDOOR }
2706        }
2707        (Some(BevyExposurePreset::Blender), None) => {
2708            quote! { ::bevy::camera::Exposure::BLENDER }
2709        }
2710        (None, Some(ev100)) => quote! { ::bevy::camera::Exposure { ev100: #ev100 } },
2711        (None, None) => quote! { ::bevy::camera::Exposure::default() },
2712        (Some(_), Some(_)) => unreachable!("validated exposure params"),
2713    }
2714}
2715
2716fn clear_color_tokens(color_expr: &Option<String>) -> TokenStream {
2717    match color_expr.as_deref() {
2718        Some(expr) => {
2719            let expr = expr_tokens(expr, "clear color");
2720            quote! { ::bevy::camera::ClearColor(#expr) }
2721        }
2722        None => quote! { ::bevy::camera::ClearColor::default() },
2723    }
2724}
2725
2726fn main_pass_resolution_override_tokens(
2727    fields: &BevyMainPassResolutionOverrideFields,
2728) -> TokenStream {
2729    let width = fields.width;
2730    let height = fields.height;
2731    quote! {
2732        ::bevy::camera::MainPassResolutionOverride(::bevy::math::UVec2::new(#width, #height))
2733    }
2734}
2735
2736fn sub_camera_view_tokens(fields: &BevySubCameraViewFields) -> TokenStream {
2737    let full_width = fields.full_width;
2738    let full_height = fields.full_height;
2739    let offset_x = fields.offset_x;
2740    let offset_y = fields.offset_y;
2741    let width = fields.width;
2742    let height = fields.height;
2743    quote! {
2744        ::bevy::camera::SubCameraView {
2745            full_size: ::bevy::math::UVec2::new(#full_width, #full_height),
2746            offset: ::bevy::math::Vec2::new(#offset_x, #offset_y),
2747            size: ::bevy::math::UVec2::new(#width, #height),
2748        }
2749    }
2750}
2751
2752fn visibility_range_tokens(fields: &BevyVisibilityRangeFields) -> TokenStream {
2753    let start_margin_start = fields.start_margin_start;
2754    let start_margin_end = fields.start_margin_end;
2755    let end_margin_start = fields.end_margin_start;
2756    let end_margin_end = fields.end_margin_end;
2757    let use_aabb = fields.use_aabb.unwrap_or(false);
2758    quote! {
2759        ::bevy::camera::visibility::VisibilityRange {
2760            start_margin: #start_margin_start..#start_margin_end,
2761            end_margin: #end_margin_start..#end_margin_end,
2762            use_aabb: #use_aabb,
2763        }
2764    }
2765}
2766
2767impl EmitCode for BevyCamera3dParams {
2768    fn emit_code(&self) -> TokenStream {
2769        let commands = expr_tokens(&self.commands_var, "commands receiver");
2770        let transform = self
2771            .transform_expr
2772            .as_deref()
2773            .map(|expr| {
2774                let expr = expr_tokens(expr, "transform");
2775                quote! { #expr, }
2776            })
2777            .unwrap_or_default();
2778        let hdr = self
2779            .hdr
2780            .map(|value| quote! { ::bevy::camera::Camera { hdr: #value, ..::std::default::Default::default() }, })
2781            .unwrap_or_default();
2782        let render_target = self
2783            .render_target
2784            .as_ref()
2785            .map(|target| {
2786                let target = target.emit_code();
2787                quote! { #target, }
2788            })
2789            .unwrap_or_else(|| {
2790                quote! {
2791                    ::bevy::camera::RenderTarget::Window(::bevy::window::WindowRef::Primary),
2792                }
2793            });
2794        let tonemapping = self
2795            .tonemapping_expr
2796            .as_deref()
2797            .map(|expr| {
2798                let expr = expr_tokens(expr, "tonemapping");
2799                quote! { #expr, }
2800            })
2801            .unwrap_or_default();
2802        let projection = if self.fov.is_none() && self.near.is_none() && self.far.is_none() {
2803            quote! { ::bevy::camera::PerspectiveProjection::default() }
2804        } else {
2805            let fov = self
2806                .fov
2807                .map(|value| quote! { fov: #value, })
2808                .unwrap_or_default();
2809            let near = self
2810                .near
2811                .map(|value| quote! { near: #value, })
2812                .unwrap_or_default();
2813            let far = self
2814                .far
2815                .map(|value| quote! { far: #value, })
2816                .unwrap_or_default();
2817            quote! {
2818                ::bevy::camera::PerspectiveProjection {
2819                    #fov
2820                    #near
2821                    #far
2822                    ..::bevy::camera::PerspectiveProjection::default()
2823                }
2824            }
2825        };
2826        quote! {
2827            #commands.spawn((
2828                ::bevy::camera::Camera3d::default(),
2829                ::bevy::camera::Projection::Perspective(#projection),
2830                #render_target
2831                #tonemapping
2832                #hdr
2833                #transform
2834            ))
2835        }
2836    }
2837
2838    fn crate_deps(&self) -> Vec<CrateDep> {
2839        bevy_dep()
2840    }
2841}
2842
2843impl EmitCode for BevyCamera2dParams {
2844    fn emit_code(&self) -> TokenStream {
2845        let commands = expr_tokens(&self.commands_var, "commands receiver");
2846        let transform = self
2847            .transform_expr
2848            .as_deref()
2849            .map(|expr| {
2850                let expr = expr_tokens(expr, "transform");
2851                quote! { #expr, }
2852            })
2853            .unwrap_or_default();
2854        let hdr = self
2855            .hdr
2856            .map(|value| quote! { ::bevy::camera::Camera { hdr: #value, ..::std::default::Default::default() }, })
2857            .unwrap_or_default();
2858        let render_target = self
2859            .render_target
2860            .as_ref()
2861            .map(|target| {
2862                let target = target.emit_code();
2863                quote! { #target, }
2864            })
2865            .unwrap_or_else(|| {
2866                quote! {
2867                    ::bevy::camera::RenderTarget::Window(::bevy::window::WindowRef::Primary),
2868                }
2869            });
2870        let tonemapping = self
2871            .tonemapping_expr
2872            .as_deref()
2873            .map(|expr| {
2874                let expr = expr_tokens(expr, "tonemapping");
2875                quote! { #expr, }
2876            })
2877            .unwrap_or_default();
2878        let projection = if self.near.is_none() && self.far.is_none() && self.scale.is_none() {
2879            quote! { ::bevy::camera::OrthographicProjection::default_2d() }
2880        } else {
2881            let near = self
2882                .near
2883                .map(|value| quote! { near: #value, })
2884                .unwrap_or_default();
2885            let far = self
2886                .far
2887                .map(|value| quote! { far: #value, })
2888                .unwrap_or_default();
2889            let scale = self
2890                .scale
2891                .map(|value| quote! { scale: #value, })
2892                .unwrap_or_default();
2893            quote! {
2894                ::bevy::camera::OrthographicProjection {
2895                    #near
2896                    #far
2897                    #scale
2898                    ..::bevy::camera::OrthographicProjection::default_2d()
2899                }
2900            }
2901        };
2902        quote! {
2903            #commands.spawn((
2904                ::bevy::camera::Camera2d::default(),
2905                ::bevy::camera::Projection::Orthographic(#projection),
2906                #render_target
2907                #tonemapping
2908                #hdr
2909                #transform
2910            ))
2911        }
2912    }
2913
2914    fn crate_deps(&self) -> Vec<CrateDep> {
2915        bevy_dep()
2916    }
2917}
2918
2919impl EmitCode for BevyBloomSettingsParams {
2920    fn emit_code(&self) -> TokenStream {
2921        let preset = match self.preset {
2922            Some(BevyBloomPreset::Natural) => {
2923                quote! { ::bevy::post_process::bloom::Bloom::NATURAL }
2924            }
2925            Some(BevyBloomPreset::Anamorphic) => {
2926                quote! { ::bevy::post_process::bloom::Bloom::ANAMORPHIC }
2927            }
2928            Some(BevyBloomPreset::OldSchool) => {
2929                quote! { ::bevy::post_process::bloom::Bloom::OLD_SCHOOL }
2930            }
2931            Some(BevyBloomPreset::ScreenBlur) => {
2932                quote! { ::bevy::post_process::bloom::Bloom::SCREEN_BLUR }
2933            }
2934            None => quote! { ::bevy::post_process::bloom::Bloom::default() },
2935        };
2936        if self.intensity.is_none()
2937            && self.low_frequency_boost.is_none()
2938            && self.low_frequency_boost_curvature.is_none()
2939            && self.high_pass_frequency.is_none()
2940            && self.prefilter_threshold.is_none()
2941            && self.prefilter_threshold_softness.is_none()
2942            && self.composite_mode.is_none()
2943            && self.max_mip_dimension.is_none()
2944            && self.scale_expr.is_none()
2945        {
2946            preset
2947        } else {
2948            let intensity = self
2949                .intensity
2950                .map(|value| quote! { intensity: #value, })
2951                .unwrap_or_default();
2952            let low_frequency_boost = self
2953                .low_frequency_boost
2954                .map(|value| quote! { low_frequency_boost: #value, })
2955                .unwrap_or_default();
2956            let low_frequency_boost_curvature = self
2957                .low_frequency_boost_curvature
2958                .map(|value| quote! { low_frequency_boost_curvature: #value, })
2959                .unwrap_or_default();
2960            let high_pass_frequency = self
2961                .high_pass_frequency
2962                .map(|value| quote! { high_pass_frequency: #value, })
2963                .unwrap_or_default();
2964            let prefilter = if self.prefilter_threshold.is_none()
2965                && self.prefilter_threshold_softness.is_none()
2966            {
2967                TokenStream::new()
2968            } else {
2969                let threshold = self
2970                    .prefilter_threshold
2971                    .map(|value| quote! { threshold: #value, })
2972                    .unwrap_or_default();
2973                let threshold_softness = self
2974                    .prefilter_threshold_softness
2975                    .map(|value| quote! { threshold_softness: #value, })
2976                    .unwrap_or_default();
2977                quote! {
2978                    prefilter: ::bevy::post_process::bloom::BloomPrefilter {
2979                        #threshold
2980                        #threshold_softness
2981                        ..(#preset).prefilter
2982                    },
2983                }
2984            };
2985            let composite_mode = self
2986                .composite_mode
2987                .map(|variant| {
2988                    let variant = emit_bloom_composite_mode_tokens(variant);
2989                    quote! { composite_mode: #variant, }
2990                })
2991                .unwrap_or_default();
2992            let max_mip_dimension = self
2993                .max_mip_dimension
2994                .map(|value| quote! { max_mip_dimension: #value, })
2995                .unwrap_or_default();
2996            let scale = self
2997                .scale_expr
2998                .as_deref()
2999                .map(|expr| {
3000                    let expr = expr_tokens(expr, "bloom scale");
3001                    quote! { scale: #expr, }
3002                })
3003                .unwrap_or_default();
3004            quote! {
3005                ::bevy::post_process::bloom::Bloom {
3006                    #intensity
3007                    #low_frequency_boost
3008                    #low_frequency_boost_curvature
3009                    #high_pass_frequency
3010                    #prefilter
3011                    #composite_mode
3012                    #max_mip_dimension
3013                    #scale
3014                    ..#preset
3015                }
3016            }
3017        }
3018    }
3019
3020    fn crate_deps(&self) -> Vec<CrateDep> {
3021        bevy_dep()
3022    }
3023}
3024
3025fn emit_bloom_composite_mode_tokens(variant: BevyBloomCompositeModeVariant) -> TokenStream {
3026    match variant {
3027        BevyBloomCompositeModeVariant::EnergyConserving => {
3028            quote! { ::bevy::post_process::bloom::BloomCompositeMode::EnergyConserving }
3029        }
3030        BevyBloomCompositeModeVariant::Additive => {
3031            quote! { ::bevy::post_process::bloom::BloomCompositeMode::Additive }
3032        }
3033    }
3034}
3035
3036fn emit_falloff_tokens(falloff: &BevyFalloff) -> TokenStream {
3037    match falloff {
3038        BevyFalloff::Linear => quote! { ::bevy::pbr::Falloff::Linear },
3039        BevyFalloff::Exponential { scale } => {
3040            quote! { ::bevy::pbr::Falloff::Exponential { scale: #scale } }
3041        }
3042        BevyFalloff::Tent { center, width } => {
3043            quote! { ::bevy::pbr::Falloff::Tent { center: #center, width: #width } }
3044        }
3045    }
3046}
3047
3048fn emit_phase_tokens(phase: &BevyPhaseFunction) -> TokenStream {
3049    match phase {
3050        BevyPhaseFunction::Isotropic => quote! { ::bevy::pbr::PhaseFunction::Isotropic },
3051        BevyPhaseFunction::Rayleigh => quote! { ::bevy::pbr::PhaseFunction::Rayleigh },
3052        BevyPhaseFunction::Mie { asymmetry } => {
3053            quote! { ::bevy::pbr::PhaseFunction::Mie { asymmetry: #asymmetry } }
3054        }
3055    }
3056}
3057
3058fn emit_scattering_term_tokens(term: &BevyScatteringTerm) -> TokenStream {
3059    let absorption = term.absorption.to_code_literal();
3060    let scattering = term.scattering.to_code_literal();
3061    let falloff = emit_falloff_tokens(&term.falloff);
3062    let phase = emit_phase_tokens(&term.phase);
3063    quote! {
3064        ::bevy::pbr::ScatteringTerm {
3065            absorption: #absorption,
3066            scattering: #scattering,
3067            falloff: #falloff,
3068            phase: #phase,
3069        }
3070    }
3071}
3072
3073fn emit_atmosphere_component_tokens(atmosphere: &BevyAtmosphere) -> TokenStream {
3074    let bottom_radius = atmosphere.bottom_radius;
3075    let top_radius = atmosphere.top_radius;
3076    let ground_albedo = atmosphere.ground_albedo.to_code_literal();
3077    quote! {
3078        ::bevy::pbr::Atmosphere {
3079            bottom_radius: #bottom_radius,
3080            top_radius: #top_radius,
3081            ground_albedo: #ground_albedo,
3082            medium,
3083        }
3084    }
3085}
3086
3087fn default_fullscreen_edge_tokens(graph: BevyFullscreenGraphKind) -> (TokenStream, TokenStream) {
3088    match graph {
3089        BevyFullscreenGraphKind::Core2d => (
3090            quote! { ::bevy::core_pipeline::core_2d::graph::Node2d::Tonemapping },
3091            quote! { ::bevy::core_pipeline::core_2d::graph::Node2d::EndMainPassPostProcessing },
3092        ),
3093        BevyFullscreenGraphKind::Core3d => (
3094            quote! { ::bevy::core_pipeline::core_3d::graph::Node3d::Tonemapping },
3095            quote! { ::bevy::core_pipeline::core_3d::graph::Node3d::EndMainPassPostProcessing },
3096        ),
3097    }
3098}
3099
3100impl EmitCode for BevyAtmosphereParams {
3101    fn emit_code(&self) -> TokenStream {
3102        let scattering_media = expr_tokens(&self.scattering_media_var, "scattering media");
3103        let falloff_resolution = self.falloff_resolution;
3104        let phase_resolution = self.phase_resolution;
3105        let terms = self
3106            .terms
3107            .iter()
3108            .map(emit_scattering_term_tokens)
3109            .collect::<Vec<_>>();
3110        let medium_base = if terms.is_empty() {
3111            quote! {
3112                ::bevy::pbr::ScatteringMedium::earthlike(#falloff_resolution, #phase_resolution)
3113            }
3114        } else {
3115            quote! {
3116                ::bevy::pbr::ScatteringMedium::new(
3117                    #falloff_resolution,
3118                    #phase_resolution,
3119                    [#(#terms),*],
3120                )
3121            }
3122        };
3123        let medium_base = if let Some(label) = &self.medium_label {
3124            let label = syn::LitStr::new(label, proc_macro2::Span::call_site());
3125            quote! { (#medium_base).with_label(#label) }
3126        } else {
3127            medium_base
3128        };
3129        let medium_base = if let Some(multiplier) = self.density_multiplier {
3130            quote! { (#medium_base).with_density_multiplier(#multiplier) }
3131        } else {
3132            medium_base
3133        };
3134        let atmosphere = self
3135            .atmosphere
3136            .as_ref()
3137            .map(emit_atmosphere_component_tokens)
3138            .unwrap_or_else(|| quote! { ::bevy::pbr::Atmosphere::earthlike(medium) });
3139        quote! {{
3140            let medium = (#scattering_media).add(#medium_base);
3141            #atmosphere
3142        }}
3143    }
3144
3145    fn crate_deps(&self) -> Vec<CrateDep> {
3146        bevy_dep()
3147    }
3148}
3149
3150impl EmitCode for BevyFullscreenMaterialParams {
3151    fn emit_code(&self) -> TokenStream {
3152        let material_type = type_tokens(&self.material_type, "fullscreen material");
3153        let shader_path = syn::LitStr::new(&self.shader_path, proc_macro2::Span::call_site());
3154        let (default_start, default_end) = default_fullscreen_edge_tokens(self.graph);
3155        let start = self
3156            .start_node_expr
3157            .as_deref()
3158            .map(|expr| {
3159                let expr = expr_tokens(expr, "fullscreen start node");
3160                quote! { #expr }
3161            })
3162            .unwrap_or(default_start);
3163        let end = self
3164            .end_node_expr
3165            .as_deref()
3166            .map(|expr| {
3167                let expr = expr_tokens(expr, "fullscreen end node");
3168                quote! { #expr }
3169            })
3170            .unwrap_or(default_end);
3171        quote! {
3172            impl ::bevy::core_pipeline::fullscreen_material::FullscreenMaterial for #material_type {
3173                fn fragment_shader() -> ::bevy::shader::ShaderRef {
3174                    #shader_path.into()
3175                }
3176
3177                fn node_edges() -> ::std::vec::Vec<::bevy::render::render_graph::InternedRenderLabel> {
3178                    use ::bevy::render::render_graph::RenderLabel as _;
3179
3180                    vec![
3181                        (#start).intern(),
3182                        Self::node_label().intern(),
3183                        (#end).intern(),
3184                    ]
3185                }
3186            }
3187        }
3188    }
3189
3190    fn crate_deps(&self) -> Vec<CrateDep> {
3191        bevy_dep()
3192    }
3193}
3194
3195elicitation::register_emit!("render_target", BevyRenderTargetParams);
3196elicitation::register_emit!("tonemapping", BevyTonemappingParams);
3197elicitation::register_emit!("deband_dither", BevyDebandDitherParams);
3198elicitation::register_emit!(
3199    "order_independent_transparency_settings",
3200    BevyOrderIndependentTransparencySettingsParams
3201);
3202elicitation::register_emit!("scaling_mode", BevyScalingModeParams);
3203elicitation::register_emit!("perspective_projection", BevyPerspectiveProjectionParams);
3204elicitation::register_emit!("orthographic_projection", BevyOrthographicProjectionParams);
3205elicitation::register_emit!("clear_color_config", BevyClearColorConfigParams);
3206elicitation::register_emit!("msaa_writeback", BevyMsaaWritebackParams);
3207elicitation::register_emit!("exposure", BevyExposureParams);
3208elicitation::register_emit!("clear_color", BevyClearColorParams);
3209elicitation::register_emit!("camera_3d_depth_load_op", BevyCamera3dDepthLoadOpParams);
3210elicitation::register_emit!(
3211    "screen_space_transmission_quality",
3212    BevyScreenSpaceTransmissionQualityParams
3213);
3214elicitation::register_emit!(
3215    "main_pass_resolution_override",
3216    BevyMainPassResolutionOverrideParams
3217);
3218elicitation::register_emit!("sub_camera_view", BevySubCameraViewParams);
3219elicitation::register_emit!("no_cpu_culling", BevyNoCpuCullingParams);
3220elicitation::register_emit!("no_frustum_culling", BevyNoFrustumCullingParams);
3221elicitation::register_emit!("visibility_range", BevyVisibilityRangeParams);
3222elicitation::register_emit!("color", BevyColorParams);
3223elicitation::register_emit!("alpha_mode", BevyRenderAlphaModeParams);
3224elicitation::register_emit!("uv_channel", BevyUvChannelParams);
3225elicitation::register_emit!("parallax_mapping_method", BevyParallaxMappingMethodParams);
3226elicitation::register_emit!("opaque_renderer_method", BevyOpaqueRendererMethodParams);
3227elicitation::register_emit!(
3228    "default_opaque_renderer_method",
3229    BevyDefaultOpaqueRendererMethodParams
3230);
3231elicitation::register_emit!("alpha_mode_2d", BevyAlphaMode2dParams);
3232elicitation::register_emit!("standard_material", BevyStandardMaterialParams);
3233elicitation::register_emit!("lightmap", BevyLightmapParams);
3234elicitation::register_emit!("color_material", BevyColorMaterialParams);
3235elicitation::register_emit!("skybox", BevySkyboxParams);
3236elicitation::register_emit!("depth_prepass", BevyDepthPrepassParams);
3237elicitation::register_emit!("normal_prepass", BevyNormalPrepassParams);
3238elicitation::register_emit!("motion_vector_prepass", BevyMotionVectorPrepassParams);
3239elicitation::register_emit!("deferred_prepass", BevyDeferredPrepassParams);
3240elicitation::register_emit!(
3241    "depth_prepass_double_buffer",
3242    BevyDepthPrepassDoubleBufferParams
3243);
3244elicitation::register_emit!(
3245    "deferred_prepass_double_buffer",
3246    BevyDeferredPrepassDoubleBufferParams
3247);
3248elicitation::register_emit!("ambient_light", BevyAmbientLightParams);
3249elicitation::register_emit!("global_ambient_light", BevyGlobalAmbientLightParams);
3250elicitation::register_emit!("directional_light", BevyDirectionalLightParams);
3251elicitation::register_emit!("point_light", BevyPointLightParams);
3252elicitation::register_emit!("spot_light", BevySpotLightParams);
3253elicitation::register_emit!(
3254    "directional_light_shadow_map",
3255    BevyDirectionalLightShadowMapParams
3256);
3257elicitation::register_emit!("point_light_shadow_map", BevyPointLightShadowMapParams);
3258elicitation::register_emit!("environment_map_light", BevyEnvironmentMapLightParams);
3259elicitation::register_emit!(
3260    "generated_environment_map_light",
3261    BevyGeneratedEnvironmentMapLightParams
3262);
3263elicitation::register_emit!(
3264    "atmosphere_environment_map_light",
3265    BevyAtmosphereEnvironmentMapLightParams
3266);
3267elicitation::register_emit!("volumetric_light", BevyVolumetricLightParams);
3268elicitation::register_emit!("volumetric_fog", BevyVolumetricFogParams);
3269elicitation::register_emit!("fog_volume", BevyFogVolumeParams);
3270elicitation::register_emit!("light_probe", BevyLightProbeParams);
3271elicitation::register_emit!("irradiance_volume", BevyIrradianceVolumeParams);
3272elicitation::register_emit!("sun_disk", BevySunDiskParams);
3273elicitation::register_emit!("not_shadow_caster", BevyNotShadowCasterParams);
3274elicitation::register_emit!("not_shadow_receiver", BevyNotShadowReceiverParams);
3275elicitation::register_emit!(
3276    "transmitted_shadow_receiver",
3277    BevyTransmittedShadowReceiverParams
3278);
3279elicitation::register_emit!("shadow_filtering_method", BevyShadowFilteringMethodParams);
3280elicitation::register_emit!("cluster_far_z_mode", BevyClusterFarZModeParams);
3281elicitation::register_emit!("cluster_z_config", BevyClusterZConfigParams);
3282elicitation::register_emit!("cluster_config", BevyClusterConfigParams);
3283elicitation::register_emit!("screen_space_reflections", BevyScreenSpaceReflectionsParams);
3284elicitation::register_emit!("clustered_decal", BevyClusteredDecalParams);
3285elicitation::register_emit!("mesh_3d", BevyMesh3dParams);
3286elicitation::register_emit!("mesh_2d", BevyMesh2dParams);
3287elicitation::register_emit!("mesh_material_3d", BevyMeshMaterial3dParams);
3288elicitation::register_emit!("mesh_material_2d", BevyMeshMaterial2dParams);
3289elicitation::register_emit!("wireframe", BevyWireframeParams);
3290elicitation::register_emit!("wireframe_color", BevyWireframeColorParams);
3291elicitation::register_emit!("no_wireframe", BevyNoWireframeParams);
3292elicitation::register_emit!("wireframe_config", BevyWireframeConfigParams);
3293elicitation::register_emit!("mesh_3d_wireframe", BevyMesh3dWireframeParams);
3294elicitation::register_emit!("wireframe_2d", BevyWireframe2dParams);
3295elicitation::register_emit!("wireframe_2d_color", BevyWireframe2dColorParams);
3296elicitation::register_emit!("no_wireframe_2d", BevyNoWireframe2dParams);
3297elicitation::register_emit!("wireframe_2d_config", BevyWireframe2dConfigParams);
3298elicitation::register_emit!("mesh_2d_wireframe", BevyMesh2dWireframeParams);
3299elicitation::register_emit!("camera_3d", BevyCamera3dParams);
3300elicitation::register_emit!("camera_2d", BevyCamera2dParams);
3301elicitation::register_emit!("viewport", BevyViewportParams);
3302elicitation::register_emit!("fog_settings", BevyFogSettingsParams);
3303elicitation::register_emit!("bloom_composite_mode", BevyBloomCompositeModeParams);
3304elicitation::register_emit!("bloom_settings", BevyBloomSettingsParams);
3305elicitation::register_emit!("sprite", BevySpriteParams);
3306elicitation::register_emit!("text_style", BevyTextStyleParams);
3307elicitation::register_emit!("ssao_quality", BevySsaoQualityParams);
3308elicitation::register_emit!("ssao", BevySsaoParams);
3309elicitation::register_emit!("temporal_anti_aliasing", BevyTemporalAntiAliasingParams);
3310elicitation::register_emit!("cascade_shadow_config", BevyCascadeShadowConfigParams);
3311elicitation::register_emit!(
3312    "cascade_shadow_config_builder",
3313    BevyCascadeShadowConfigBuilderParams
3314);
3315elicitation::register_emit!("atmosphere", BevyAtmosphereParams);
3316elicitation::register_emit!("fullscreen_material", BevyFullscreenMaterialParams);
3317
3318/// MCP plugin exposing core Bevy render/material fragment tools.
3319#[derive(Debug, ElicitPlugin)]
3320#[plugin(name = "bevy_render")]
3321pub struct BevyRenderPlugin;
3322
3323impl BevyRenderPlugin {
3324    /// Creates a new Bevy render fragment plugin.
3325    #[instrument]
3326    pub fn new() -> Self {
3327        Self
3328    }
3329}
3330
3331impl Default for BevyRenderPlugin {
3332    fn default() -> Self {
3333        Self::new()
3334    }
3335}
3336
3337fn validate_standard_material(params: &BevyStandardMaterialParams) -> Result<(), ErrorData> {
3338    validate_optional_expr(&params.base_color_expr, "base color")?;
3339    validate_optional_expr(&params.base_color_texture_expr, "base color texture")?;
3340    validate_optional_expr(&params.emissive_expr, "emissive")?;
3341    validate_optional_expr(&params.emissive_texture_expr, "emissive texture")?;
3342    validate_optional_expr(
3343        &params.metallic_roughness_texture_expr,
3344        "metallic roughness texture",
3345    )?;
3346    validate_optional_expr(&params.specular_tint_expr, "specular tint")?;
3347    validate_optional_expr(
3348        &params.diffuse_transmission_texture_expr,
3349        "diffuse transmission texture",
3350    )?;
3351    validate_optional_expr(
3352        &params.specular_transmission_texture_expr,
3353        "specular transmission texture",
3354    )?;
3355    validate_optional_expr(&params.thickness_texture_expr, "thickness texture")?;
3356    validate_optional_expr(&params.attenuation_color_expr, "attenuation color")?;
3357    validate_optional_expr(&params.clearcoat_texture_expr, "clearcoat texture")?;
3358    validate_optional_expr(
3359        &params.clearcoat_roughness_texture_expr,
3360        "clearcoat roughness texture",
3361    )?;
3362    validate_optional_expr(
3363        &params.clearcoat_normal_texture_expr,
3364        "clearcoat normal texture",
3365    )?;
3366    validate_optional_expr(&params.anisotropy_texture_expr, "anisotropy texture")?;
3367    validate_optional_expr(&params.normal_map_texture_expr, "normal map texture")?;
3368    validate_optional_expr(&params.occlusion_texture_expr, "occlusion texture")?;
3369    validate_optional_expr(&params.specular_texture_expr, "specular texture")?;
3370    validate_optional_expr(&params.specular_tint_texture_expr, "specular tint texture")?;
3371    validate_optional_expr(&params.alpha_mode_expr, "alpha mode")?;
3372    validate_optional_expr(&params.cull_mode_expr, "cull mode")?;
3373    validate_optional_expr(&params.depth_map_expr, "depth map")?;
3374    validate_optional_expr(
3375        &params.parallax_mapping_method_expr,
3376        "parallax mapping method",
3377    )?;
3378    validate_optional_expr(&params.opaque_render_method_expr, "opaque render method")?;
3379    validate_optional_expr(&params.uv_transform_expr, "uv transform")?;
3380    validate_optional_finite_f32(params.emissive_exposure_weight, "emissive exposure weight")?;
3381    validate_optional_finite_f32(params.depth_bias, "depth bias")?;
3382    validate_optional_finite_f32(params.parallax_depth_scale, "parallax depth scale")?;
3383    validate_optional_non_negative_f32(
3384        params.max_parallax_layer_count,
3385        "max parallax layer count",
3386    )?;
3387    validate_optional_non_negative_f32(params.lightmap_exposure, "lightmap exposure")?;
3388    validate_optional_non_negative_f32(params.diffuse_transmission, "diffuse transmission")?;
3389    validate_optional_non_negative_f32(params.specular_transmission, "specular transmission")?;
3390    validate_optional_non_negative_f32(params.thickness, "thickness")?;
3391    validate_optional_non_negative_f32(params.ior, "index of refraction")?;
3392    validate_optional_non_negative_f32(params.attenuation_distance, "attenuation distance")?;
3393    validate_optional_non_negative_f32(params.clearcoat, "clearcoat")?;
3394    validate_optional_non_negative_f32(
3395        params.clearcoat_perceptual_roughness,
3396        "clearcoat perceptual roughness",
3397    )?;
3398    validate_optional_non_negative_f32(params.anisotropy_strength, "anisotropy strength")?;
3399    validate_optional_finite_f32(params.anisotropy_rotation, "anisotropy rotation")?;
3400    Ok(())
3401}
3402
3403fn validate_uv_channel(_params: &BevyUvChannelParams) -> Result<(), ErrorData> {
3404    Ok(())
3405}
3406
3407fn validate_parallax_mapping_method(
3408    params: &BevyParallaxMappingMethodParams,
3409) -> Result<(), ErrorData> {
3410    match params {
3411        BevyParallaxMappingMethodParams::Occlusion => {}
3412        BevyParallaxMappingMethodParams::Relief { max_steps } => {
3413            if *max_steps == 0 {
3414                return Err(tool_err(
3415                    "relief parallax mapping max_steps must be greater than zero",
3416                ));
3417            }
3418        }
3419    }
3420    Ok(())
3421}
3422
3423fn validate_opaque_renderer_method(
3424    _params: &BevyOpaqueRendererMethodParams,
3425) -> Result<(), ErrorData> {
3426    Ok(())
3427}
3428
3429fn validate_default_opaque_renderer_method(
3430    _params: &BevyDefaultOpaqueRendererMethodParams,
3431) -> Result<(), ErrorData> {
3432    Ok(())
3433}
3434
3435fn validate_alpha_mode_2d(params: &BevyAlphaMode2dParams) -> Result<(), ErrorData> {
3436    if let BevyAlphaMode2dParams::Mask(threshold) = params
3437        && !threshold.is_finite()
3438    {
3439        return Err(tool_err("alpha_mode_2d threshold must be finite"));
3440    }
3441    Ok(())
3442}
3443
3444fn validate_lightmap(params: &BevyLightmapParams) -> Result<(), ErrorData> {
3445    let _ = parse_expr(&params.image_expr, "lightmap image")?;
3446    validate_optional_expr(&params.uv_rect_expr, "lightmap uv_rect")
3447}
3448
3449fn validate_color_material(params: &BevyColorMaterialParams) -> Result<(), ErrorData> {
3450    validate_optional_expr(&params.color_expr, "color material color")?;
3451    validate_optional_expr(&params.alpha_mode_expr, "color material alpha mode")?;
3452    validate_optional_expr(&params.uv_transform_expr, "color material uv transform")?;
3453    validate_optional_expr(&params.texture_expr, "color material texture")
3454}
3455
3456fn validate_skybox(params: &BevySkyboxParams) -> Result<(), ErrorData> {
3457    let _ = parse_expr(&params.image_expr, "skybox image")?;
3458    validate_optional_expr(&params.rotation_expr, "skybox rotation")?;
3459    validate_optional_non_negative_f32(params.brightness, "skybox brightness")
3460}
3461
3462fn validate_depth_prepass(_params: &BevyDepthPrepassParams) -> Result<(), ErrorData> {
3463    Ok(())
3464}
3465
3466fn validate_normal_prepass(_params: &BevyNormalPrepassParams) -> Result<(), ErrorData> {
3467    Ok(())
3468}
3469
3470fn validate_motion_vector_prepass(
3471    _params: &BevyMotionVectorPrepassParams,
3472) -> Result<(), ErrorData> {
3473    Ok(())
3474}
3475
3476fn validate_deferred_prepass(_params: &BevyDeferredPrepassParams) -> Result<(), ErrorData> {
3477    Ok(())
3478}
3479
3480fn validate_depth_prepass_double_buffer(
3481    _params: &BevyDepthPrepassDoubleBufferParams,
3482) -> Result<(), ErrorData> {
3483    Ok(())
3484}
3485
3486fn validate_deferred_prepass_double_buffer(
3487    _params: &BevyDeferredPrepassDoubleBufferParams,
3488) -> Result<(), ErrorData> {
3489    Ok(())
3490}
3491
3492fn validate_ambient_light(params: &BevyAmbientLightParams) -> Result<(), ErrorData> {
3493    validate_optional_expr(&params.color_expr, "ambient light color")?;
3494    validate_optional_non_negative_f32(params.brightness, "ambient light brightness")
3495}
3496
3497fn validate_global_ambient_light(params: &BevyGlobalAmbientLightParams) -> Result<(), ErrorData> {
3498    validate_optional_expr(&params.color_expr, "global ambient light color")?;
3499    validate_optional_non_negative_f32(params.brightness, "global ambient light brightness")
3500}
3501
3502fn validate_directional_light(params: &BevyDirectionalLightParams) -> Result<(), ErrorData> {
3503    validate_optional_expr(&params.color_expr, "directional light color")
3504}
3505
3506fn validate_point_light(params: &BevyPointLightParams) -> Result<(), ErrorData> {
3507    validate_optional_expr(&params.color_expr, "point light color")
3508}
3509
3510fn validate_spot_light(params: &BevySpotLightParams) -> Result<(), ErrorData> {
3511    validate_optional_expr(&params.color_expr, "spot light color")
3512}
3513
3514fn validate_directional_light_shadow_map(
3515    params: &BevyDirectionalLightShadowMapParams,
3516) -> Result<(), ErrorData> {
3517    validate_shadow_map_size(params.size, "directional light shadow map")
3518}
3519
3520fn validate_point_light_shadow_map(
3521    params: &BevyPointLightShadowMapParams,
3522) -> Result<(), ErrorData> {
3523    validate_shadow_map_size(params.size, "point light shadow map")
3524}
3525
3526fn validate_environment_map_light(params: &BevyEnvironmentMapLightParams) -> Result<(), ErrorData> {
3527    let _ = parse_expr(&params.diffuse_map_expr, "environment diffuse map")?;
3528    let _ = parse_expr(&params.specular_map_expr, "environment specular map")?;
3529    validate_optional_expr(&params.rotation_expr, "environment rotation")?;
3530    validate_optional_non_negative_f32(params.intensity, "environment map light intensity")?;
3531    Ok(())
3532}
3533
3534fn validate_generated_environment_map_light(
3535    params: &BevyGeneratedEnvironmentMapLightParams,
3536) -> Result<(), ErrorData> {
3537    let _ = parse_expr(&params.environment_map_expr, "generated environment map")?;
3538    validate_optional_expr(&params.rotation_expr, "generated environment rotation")?;
3539    validate_optional_non_negative_f32(
3540        params.intensity,
3541        "generated environment map light intensity",
3542    )?;
3543    Ok(())
3544}
3545
3546fn validate_atmosphere_environment_map_light(
3547    params: &BevyAtmosphereEnvironmentMapLightParams,
3548) -> Result<(), ErrorData> {
3549    validate_optional_non_negative_f32(
3550        params.intensity,
3551        "atmosphere environment map light intensity",
3552    )?;
3553    if let Some([width, height]) = params.size {
3554        validate_shadow_map_u32_size(width, "atmosphere environment map width")?;
3555        validate_shadow_map_u32_size(height, "atmosphere environment map height")?;
3556    }
3557    Ok(())
3558}
3559
3560fn validate_volumetric_light(_params: &BevyVolumetricLightParams) -> Result<(), ErrorData> {
3561    Ok(())
3562}
3563
3564fn validate_volumetric_fog(params: &BevyVolumetricFogParams) -> Result<(), ErrorData> {
3565    validate_optional_expr(&params.ambient_color_expr, "volumetric fog ambient color")?;
3566    validate_optional_non_negative_f32(
3567        params.ambient_intensity,
3568        "volumetric fog ambient_intensity",
3569    )?;
3570    validate_optional_non_negative_f32(params.jitter, "volumetric fog jitter")?;
3571    if let Some(step_count) = params.step_count
3572        && step_count == 0
3573    {
3574        return Err(tool_err(
3575            "volumetric fog step_count must be greater than zero",
3576        ));
3577    }
3578    Ok(())
3579}
3580
3581fn validate_fog_volume(params: &BevyFogVolumeParams) -> Result<(), ErrorData> {
3582    validate_optional_expr(&params.fog_color_expr, "fog volume color")?;
3583    validate_optional_expr(&params.density_texture_expr, "fog volume density texture")?;
3584    validate_optional_expr(
3585        &params.density_texture_offset_expr,
3586        "fog volume density texture offset",
3587    )?;
3588    validate_optional_expr(&params.light_tint_expr, "fog volume light tint")?;
3589    validate_optional_non_negative_f32(params.density_factor, "fog volume density_factor")?;
3590    validate_optional_non_negative_f32(params.absorption, "fog volume absorption")?;
3591    validate_optional_non_negative_f32(params.scattering, "fog volume scattering")?;
3592    validate_optional_finite_f32(
3593        params.scattering_asymmetry,
3594        "fog volume scattering_asymmetry",
3595    )?;
3596    validate_optional_non_negative_f32(params.light_intensity, "fog volume light_intensity")?;
3597    Ok(())
3598}
3599
3600fn validate_light_probe(_params: &BevyLightProbeParams) -> Result<(), ErrorData> {
3601    Ok(())
3602}
3603
3604fn validate_irradiance_volume(params: &BevyIrradianceVolumeParams) -> Result<(), ErrorData> {
3605    let _ = parse_expr(&params.voxels_expr, "irradiance volume voxels")?;
3606    validate_optional_non_negative_f32(params.intensity, "irradiance volume intensity")?;
3607    Ok(())
3608}
3609
3610fn validate_sun_disk(params: &BevySunDiskParams) -> Result<(), ErrorData> {
3611    validate_optional_non_negative_f32(params.angular_size, "sun disk angular_size")?;
3612    validate_optional_non_negative_f32(params.intensity, "sun disk intensity")
3613}
3614
3615fn validate_not_shadow_caster(_params: &BevyNotShadowCasterParams) -> Result<(), ErrorData> {
3616    Ok(())
3617}
3618
3619fn validate_not_shadow_receiver(_params: &BevyNotShadowReceiverParams) -> Result<(), ErrorData> {
3620    Ok(())
3621}
3622
3623fn validate_transmitted_shadow_receiver(
3624    _params: &BevyTransmittedShadowReceiverParams,
3625) -> Result<(), ErrorData> {
3626    Ok(())
3627}
3628
3629fn validate_shadow_filtering_method(
3630    _params: &BevyShadowFilteringMethodParams,
3631) -> Result<(), ErrorData> {
3632    Ok(())
3633}
3634
3635fn validate_cluster_far_z_mode(params: &BevyClusterFarZModeParams) -> Result<(), ErrorData> {
3636    match params {
3637        BevyClusterFarZModeParams::MaxClusterableObjectRange => {}
3638        BevyClusterFarZModeParams::Constant(constant) => {
3639            validate_optional_non_negative_f32(Some(*constant), "cluster far-z constant")?;
3640        }
3641    }
3642    Ok(())
3643}
3644
3645fn validate_cluster_z_config(params: &BevyClusterZConfigParams) -> Result<(), ErrorData> {
3646    validate_optional_non_negative_f32(
3647        params.first_slice_depth,
3648        "cluster z config first_slice_depth",
3649    )?;
3650    if let Some(mode) = &params.far_z_mode {
3651        validate_cluster_far_z_mode(mode)?;
3652    }
3653    Ok(())
3654}
3655
3656fn validate_cluster_config(params: &BevyClusterConfigParams) -> Result<(), ErrorData> {
3657    match params {
3658        BevyClusterConfigParams::None | BevyClusterConfigParams::Single => {}
3659        BevyClusterConfigParams::XYZ {
3660            dimensions,
3661            z_config,
3662            ..
3663        } => {
3664            let [x, y, z] = *dimensions;
3665            if x == 0 || y == 0 || z == 0 {
3666                return Err(tool_err(
3667                    "cluster config xyz dimensions must all be greater than zero",
3668                ));
3669            }
3670            validate_cluster_z_config(z_config)?;
3671        }
3672        BevyClusterConfigParams::FixedZ {
3673            total,
3674            z_slices,
3675            z_config,
3676            ..
3677        } => {
3678            if *total == 0 || *z_slices == 0 {
3679                return Err(tool_err(
3680                    "cluster config fixed_z total and z_slices must be greater than zero",
3681                ));
3682            }
3683            validate_cluster_z_config(z_config)?;
3684        }
3685    }
3686    Ok(())
3687}
3688
3689fn validate_screen_space_reflections(
3690    params: &BevyScreenSpaceReflectionsParams,
3691) -> Result<(), ErrorData> {
3692    if let Some(value) = params.perceptual_roughness_threshold
3693        && (!value.is_finite() || !(0.0..=1.0).contains(&value))
3694    {
3695        return Err(tool_err(
3696            "screen-space reflections perceptual_roughness_threshold must be in [0.0, 1.0]",
3697        ));
3698    }
3699    validate_optional_non_negative_f32(params.thickness, "screen-space reflections thickness")?;
3700    if let Some(linear_steps) = params.linear_steps
3701        && linear_steps == 0
3702    {
3703        return Err(tool_err(
3704            "screen-space reflections linear_steps must be greater than zero",
3705        ));
3706    }
3707    validate_optional_non_negative_f32(
3708        params.linear_march_exponent,
3709        "screen-space reflections linear_march_exponent",
3710    )?;
3711    Ok(())
3712}
3713
3714fn validate_clustered_decal(params: &BevyClusteredDecalParams) -> Result<(), ErrorData> {
3715    validate_optional_expr(
3716        &params.base_color_texture_expr,
3717        "clustered decal base_color_texture",
3718    )?;
3719    validate_optional_expr(
3720        &params.normal_map_texture_expr,
3721        "clustered decal normal_map_texture",
3722    )?;
3723    validate_optional_expr(
3724        &params.metallic_roughness_texture_expr,
3725        "clustered decal metallic_roughness_texture",
3726    )?;
3727    validate_optional_expr(
3728        &params.emissive_texture_expr,
3729        "clustered decal emissive_texture",
3730    )?;
3731    Ok(())
3732}
3733
3734fn validate_shadow_map_size(size: Option<usize>, context: &str) -> Result<(), ErrorData> {
3735    if let Some(size) = size {
3736        validate_shadow_map_usize_size(size, context)?;
3737    }
3738    Ok(())
3739}
3740
3741fn validate_mesh_3d(params: &BevyMesh3dParams) -> Result<(), ErrorData> {
3742    let _ = parse_expr(&params.mesh_expr, "mesh_3d mesh")?;
3743    Ok(())
3744}
3745
3746fn validate_mesh_2d(params: &BevyMesh2dParams) -> Result<(), ErrorData> {
3747    let _ = parse_expr(&params.mesh_expr, "mesh_2d mesh")?;
3748    Ok(())
3749}
3750
3751fn validate_mesh_material_3d(params: &BevyMeshMaterial3dParams) -> Result<(), ErrorData> {
3752    let _ = parse_expr(&params.material_expr, "mesh_material_3d material")?;
3753    Ok(())
3754}
3755
3756fn validate_mesh_material_2d(params: &BevyMeshMaterial2dParams) -> Result<(), ErrorData> {
3757    let _ = parse_expr(&params.material_expr, "mesh_material_2d material")?;
3758    Ok(())
3759}
3760
3761fn validate_wireframe(_params: &BevyWireframeParams) -> Result<(), ErrorData> {
3762    Ok(())
3763}
3764
3765fn validate_wireframe_color(params: &BevyWireframeColorParams) -> Result<(), ErrorData> {
3766    let _ = parse_expr(&params.color_expr, "wireframe_color color")?;
3767    Ok(())
3768}
3769
3770fn validate_no_wireframe(_params: &BevyNoWireframeParams) -> Result<(), ErrorData> {
3771    Ok(())
3772}
3773
3774fn validate_wireframe_config(params: &BevyWireframeConfigParams) -> Result<(), ErrorData> {
3775    validate_optional_expr(&params.default_color_expr, "wireframe_config default color")
3776}
3777
3778fn validate_mesh_3d_wireframe(params: &BevyMesh3dWireframeParams) -> Result<(), ErrorData> {
3779    let _ = parse_expr(&params.material_expr, "mesh_3d_wireframe material")?;
3780    Ok(())
3781}
3782
3783fn validate_wireframe_2d(_params: &BevyWireframe2dParams) -> Result<(), ErrorData> {
3784    Ok(())
3785}
3786
3787fn validate_wireframe_2d_color(params: &BevyWireframe2dColorParams) -> Result<(), ErrorData> {
3788    let _ = parse_expr(&params.color_expr, "wireframe_2d_color color")?;
3789    Ok(())
3790}
3791
3792fn validate_no_wireframe_2d(_params: &BevyNoWireframe2dParams) -> Result<(), ErrorData> {
3793    Ok(())
3794}
3795
3796fn validate_wireframe_2d_config(params: &BevyWireframe2dConfigParams) -> Result<(), ErrorData> {
3797    validate_optional_expr(
3798        &params.default_color_expr,
3799        "wireframe_2d_config default color",
3800    )
3801}
3802
3803fn validate_mesh_2d_wireframe(params: &BevyMesh2dWireframeParams) -> Result<(), ErrorData> {
3804    let _ = parse_expr(&params.material_expr, "mesh_2d_wireframe material")?;
3805    Ok(())
3806}
3807
3808fn validate_shadow_map_usize_size(size: usize, context: &str) -> Result<(), ErrorData> {
3809    if size == 0 {
3810        return Err(tool_err(format!(
3811            "{context} size must be greater than zero"
3812        )));
3813    }
3814    if !size.is_power_of_two() {
3815        return Err(tool_err(format!("{context} size must be a power of two")));
3816    }
3817    Ok(())
3818}
3819
3820fn validate_shadow_map_u32_size(size: u32, context: &str) -> Result<(), ErrorData> {
3821    if size == 0 {
3822        return Err(tool_err(format!("{context} must be greater than zero")));
3823    }
3824    if !size.is_power_of_two() {
3825        return Err(tool_err(format!("{context} must be a power of two")));
3826    }
3827    Ok(())
3828}
3829
3830fn validate_optional_non_negative_f32(value: Option<f32>, context: &str) -> Result<(), ErrorData> {
3831    if let Some(value) = value
3832        && (!value.is_finite() || value < 0.0)
3833    {
3834        return Err(tool_err(format!(
3835            "{context} must be a finite non-negative number"
3836        )));
3837    }
3838    Ok(())
3839}
3840
3841fn validate_optional_finite_f32(value: Option<f32>, context: &str) -> Result<(), ErrorData> {
3842    if let Some(value) = value
3843        && !value.is_finite()
3844    {
3845        return Err(tool_err(format!("{context} must be finite")));
3846    }
3847    Ok(())
3848}
3849
3850fn validate_camera_3d(params: &BevyCamera3dParams) -> Result<(), ErrorData> {
3851    let _ = parse_expr(&params.commands_var, "commands receiver")?;
3852    validate_optional_expr(&params.transform_expr, "transform")?;
3853    validate_optional_expr(&params.tonemapping_expr, "tonemapping")?;
3854    if let Some(target) = &params.render_target {
3855        validate_render_target(target)?;
3856    }
3857    Ok(())
3858}
3859
3860fn validate_camera_2d(params: &BevyCamera2dParams) -> Result<(), ErrorData> {
3861    let _ = parse_expr(&params.commands_var, "commands receiver")?;
3862    validate_optional_expr(&params.transform_expr, "transform")?;
3863    validate_optional_expr(&params.tonemapping_expr, "tonemapping")?;
3864    if let Some(target) = &params.render_target {
3865        validate_render_target(target)?;
3866    }
3867    Ok(())
3868}
3869
3870fn validate_viewport(params: &BevyViewportParams) -> Result<(), ErrorData> {
3871    if let Some([min, max]) = params.depth
3872        && min > max
3873    {
3874        return Err(tool_err(
3875            "viewport depth min must be less than or equal to max",
3876        ));
3877    }
3878    Ok(())
3879}
3880
3881fn validate_fog_settings(params: &BevyFogSettingsParams) -> Result<(), ErrorData> {
3882    validate_optional_expr(&params.color_expr, "fog color")?;
3883    validate_optional_expr(
3884        &params.directional_light_color_expr,
3885        "fog directional light color",
3886    )?;
3887    validate_optional_expr(&params.falloff_expr, "fog falloff")?;
3888    Ok(())
3889}
3890
3891fn validate_bloom_settings(params: &BevyBloomSettingsParams) -> Result<(), ErrorData> {
3892    if let Some(softness) = params.prefilter_threshold_softness
3893        && !softness.is_finite()
3894    {
3895        return Err(tool_err(
3896            "bloom prefilter threshold softness must be finite",
3897        ));
3898    }
3899    validate_optional_expr(&params.scale_expr, "bloom scale")
3900}
3901
3902fn validate_sprite(params: &BevySpriteParams) -> Result<(), ErrorData> {
3903    validate_optional_expr(&params.image_expr, "sprite image")?;
3904    validate_optional_expr(&params.color_expr, "sprite color")?;
3905    validate_optional_expr(&params.custom_size_expr, "sprite custom size")?;
3906    Ok(())
3907}
3908
3909fn validate_text_style(params: &BevyTextStyleParams) -> Result<(), ErrorData> {
3910    validate_optional_expr(&params.font.font_handle_expr, "font handle")?;
3911    validate_optional_expr(&params.color.color_expr, "text color")?;
3912    validate_optional_expr(&params.layout.justify_expr, "text justify")?;
3913    validate_optional_expr(&params.layout.linebreak_expr, "text linebreak")?;
3914    Ok(())
3915}
3916
3917fn validate_ssao_quality(params: &BevySsaoQualityParams) -> Result<(), ErrorData> {
3918    if let BevySsaoQualityParams::Custom {
3919        slice_count,
3920        samples_per_slice_side,
3921    } = params
3922    {
3923        if *slice_count == 0 {
3924            return Err(tool_err(
3925                "custom ssao slice_count must be greater than zero",
3926            ));
3927        }
3928        if *samples_per_slice_side == 0 {
3929            return Err(tool_err(
3930                "custom ssao samples_per_slice_side must be greater than zero",
3931            ));
3932        }
3933    }
3934    Ok(())
3935}
3936
3937fn validate_ssao(params: &BevySsaoParams) -> Result<(), ErrorData> {
3938    if let Some(quality) = &params.quality_level {
3939        validate_ssao_quality(quality)?;
3940    }
3941    if let Some(value) = params.constant_object_thickness
3942        && (!value.is_finite() || value < 0.0)
3943    {
3944        return Err(tool_err(
3945            "ssao constant_object_thickness must be a finite non-negative number",
3946        ));
3947    }
3948    Ok(())
3949}
3950
3951fn validate_temporal_anti_aliasing(
3952    _params: &BevyTemporalAntiAliasingParams,
3953) -> Result<(), ErrorData> {
3954    Ok(())
3955}
3956
3957fn validate_cascade_shadow_config(params: &BevyCascadeShadowConfigParams) -> Result<(), ErrorData> {
3958    if let Some(value) = params.minimum_distance
3959        && (!value.is_finite() || value < 0.0)
3960    {
3961        return Err(tool_err(
3962            "cascade minimum_distance must be a finite non-negative number",
3963        ));
3964    }
3965    if let Some(value) = params.overlap_proportion
3966        && (!value.is_finite() || !(0.0..1.0).contains(&value))
3967    {
3968        return Err(tool_err(
3969            "cascade overlap_proportion must be in the range [0.0, 1.0)",
3970        ));
3971    }
3972    if let Some(bounds) = &params.bounds {
3973        let mut previous = None;
3974        for bound in &bounds.0 {
3975            if !bound.is_finite() || *bound <= 0.0 {
3976                return Err(tool_err(
3977                    "cascade bounds must be finite positive far-bound distances",
3978                ));
3979            }
3980            if let Some(prev) = previous
3981                && *bound <= prev
3982            {
3983                return Err(tool_err(
3984                    "cascade bounds must be strictly increasing far-bound distances",
3985                ));
3986            }
3987            previous = Some(*bound);
3988        }
3989    }
3990    Ok(())
3991}
3992
3993fn validate_cascade_shadow_config_builder(
3994    params: &BevyCascadeShadowConfigBuilderParams,
3995) -> Result<(), ErrorData> {
3996    const DEFAULT_MINIMUM_DISTANCE: f32 = 0.1;
3997    const DEFAULT_FIRST_CASCADE_FAR_BOUND: f32 = 10.0;
3998
3999    if let Some(num_cascades) = params.num_cascades
4000        && num_cascades == 0
4001    {
4002        return Err(tool_err(
4003            "cascade builder num_cascades must be greater than zero",
4004        ));
4005    }
4006
4007    let minimum_distance = params.minimum_distance.unwrap_or(DEFAULT_MINIMUM_DISTANCE);
4008    if !minimum_distance.is_finite() || minimum_distance < 0.0 {
4009        return Err(tool_err(
4010            "cascade builder minimum_distance must be a finite non-negative number",
4011        ));
4012    }
4013
4014    if let Some(maximum_distance) = params.maximum_distance
4015        && (!maximum_distance.is_finite() || maximum_distance <= minimum_distance)
4016    {
4017        return Err(tool_err(
4018            "cascade builder maximum_distance must be finite and greater than minimum_distance",
4019        ));
4020    }
4021
4022    if let Some(first_cascade_far_bound) = params.first_cascade_far_bound
4023        && (!first_cascade_far_bound.is_finite()
4024            || first_cascade_far_bound <= 0.0
4025            || (params.num_cascades.unwrap_or(4) != 1
4026                && minimum_distance >= first_cascade_far_bound))
4027    {
4028        return Err(tool_err(
4029            "cascade builder first_cascade_far_bound must be finite, positive, and greater than minimum_distance when using multiple cascades",
4030        ));
4031    }
4032
4033    if params.num_cascades.unwrap_or(4) != 1
4034        && params.first_cascade_far_bound.is_none()
4035        && minimum_distance >= DEFAULT_FIRST_CASCADE_FAR_BOUND
4036    {
4037        return Err(tool_err(
4038            "cascade builder minimum_distance must be less than the default first_cascade_far_bound for multi-cascade builds",
4039        ));
4040    }
4041
4042    if let Some(overlap_proportion) = params.overlap_proportion
4043        && (!overlap_proportion.is_finite() || !(0.0..1.0).contains(&overlap_proportion))
4044    {
4045        return Err(tool_err(
4046            "cascade builder overlap_proportion must be in the range [0.0, 1.0)",
4047        ));
4048    }
4049
4050    Ok(())
4051}
4052
4053pub(crate) fn validate_atmosphere(params: &BevyAtmosphereParams) -> Result<(), ErrorData> {
4054    let _ = parse_expr(&params.scattering_media_var, "scattering media")?;
4055    if params.falloff_resolution == 0 {
4056        return Err(tool_err("falloff_resolution must be greater than zero"));
4057    }
4058    if params.phase_resolution == 0 {
4059        return Err(tool_err("phase_resolution must be greater than zero"));
4060    }
4061    if let Some(multiplier) = params.density_multiplier
4062        && !multiplier.is_finite()
4063    {
4064        return Err(tool_err("density_multiplier must be finite"));
4065    }
4066    Ok(())
4067}
4068
4069fn validate_fullscreen_material(params: &BevyFullscreenMaterialParams) -> Result<(), ErrorData> {
4070    let _ = parse_type(&params.material_type, "fullscreen material")?;
4071    if params.shader_path.trim().is_empty() {
4072        return Err(tool_err("shader_path must not be empty"));
4073    }
4074    validate_optional_expr(&params.start_node_expr, "fullscreen start node")?;
4075    validate_optional_expr(&params.end_node_expr, "fullscreen end node")?;
4076    Ok(())
4077}
4078
4079#[elicit_tool(
4080    plugin = "bevy_render",
4081    name = "render_target",
4082    description = "Emit a `RenderTarget` component for primary-window, entity-window, image, or texture-view outputs.",
4083    emit = None
4084)]
4085#[instrument(skip_all)]
4086async fn render_target(p: BevyRenderTargetParams) -> Result<CallToolResult, ErrorData> {
4087    validate_render_target(&p)?;
4088    ok_source(p.emit_code().to_string())
4089}
4090
4091#[elicit_tool(
4092    plugin = "bevy_render",
4093    name = "tonemapping",
4094    description = "Emit a `Tonemapping` enum expression.",
4095    emit = None
4096)]
4097#[instrument(skip_all)]
4098async fn tonemapping(p: BevyTonemappingParams) -> Result<CallToolResult, ErrorData> {
4099    ok_source(p.emit_code().to_string())
4100}
4101
4102#[elicit_tool(
4103    plugin = "bevy_render",
4104    name = "deband_dither",
4105    description = "Emit a `DebandDither` camera component for final-image debanding control.",
4106    emit = None
4107)]
4108#[instrument(skip_all)]
4109async fn deband_dither(p: BevyDebandDitherParams) -> Result<CallToolResult, ErrorData> {
4110    ok_source(p.emit_code().to_string())
4111}
4112
4113#[elicit_tool(
4114    plugin = "bevy_render",
4115    name = "order_independent_transparency_settings",
4116    description = "Emit an `OrderIndependentTransparencySettings` camera component with optional layer-count and alpha-threshold overrides.",
4117    emit = None
4118)]
4119#[instrument(skip_all)]
4120async fn order_independent_transparency_settings(
4121    p: BevyOrderIndependentTransparencySettingsParams,
4122) -> Result<CallToolResult, ErrorData> {
4123    validate_order_independent_transparency_settings(&p)?;
4124    ok_source(p.emit_code().to_string())
4125}
4126
4127#[elicit_tool(
4128    plugin = "bevy_render",
4129    name = "scaling_mode",
4130    description = "Emit a `ScalingMode` expression for orthographic camera projections.",
4131    emit = None
4132)]
4133#[instrument(skip_all)]
4134async fn scaling_mode(p: BevyScalingModeParams) -> Result<CallToolResult, ErrorData> {
4135    validate_scaling_mode(&p)?;
4136    ok_source(p.emit_code().to_string())
4137}
4138
4139#[elicit_tool(
4140    plugin = "bevy_render",
4141    name = "perspective_projection",
4142    description = "Emit a `PerspectiveProjection` literal using Bevy defaults plus optional overrides.",
4143    emit = None
4144)]
4145#[instrument(skip_all)]
4146async fn perspective_projection(
4147    p: BevyPerspectiveProjectionParams,
4148) -> Result<CallToolResult, ErrorData> {
4149    validate_perspective_projection(&p)?;
4150    ok_source(p.emit_code().to_string())
4151}
4152
4153#[elicit_tool(
4154    plugin = "bevy_render",
4155    name = "orthographic_projection",
4156    description = "Emit an `OrthographicProjection` literal using Bevy 2D or 3D defaults plus optional overrides.",
4157    emit = None
4158)]
4159#[instrument(skip_all)]
4160async fn orthographic_projection(
4161    p: BevyOrthographicProjectionParams,
4162) -> Result<CallToolResult, ErrorData> {
4163    validate_orthographic_projection(&p)?;
4164    ok_source(p.emit_code().to_string())
4165}
4166
4167#[elicit_tool(
4168    plugin = "bevy_render",
4169    name = "clear_color_config",
4170    description = "Emit a `ClearColorConfig` expression for camera clear behavior.",
4171    emit = None
4172)]
4173#[instrument(skip_all)]
4174async fn clear_color_config(p: BevyClearColorConfigParams) -> Result<CallToolResult, ErrorData> {
4175    validate_clear_color_config(&p)?;
4176    ok_source(p.emit_code().to_string())
4177}
4178
4179#[elicit_tool(
4180    plugin = "bevy_render",
4181    name = "msaa_writeback",
4182    description = "Emit an `MsaaWriteback` expression for camera layering behavior.",
4183    emit = None
4184)]
4185#[instrument(skip_all)]
4186async fn msaa_writeback(p: BevyMsaaWritebackParams) -> Result<CallToolResult, ErrorData> {
4187    ok_source(p.emit_code().to_string())
4188}
4189
4190#[elicit_tool(
4191    plugin = "bevy_render",
4192    name = "exposure",
4193    description = "Emit an `Exposure` component using a preset or explicit EV100 value.",
4194    emit = None
4195)]
4196#[instrument(skip_all)]
4197async fn exposure(p: BevyExposureParams) -> Result<CallToolResult, ErrorData> {
4198    validate_exposure(&p)?;
4199    ok_source(p.emit_code().to_string())
4200}
4201
4202#[elicit_tool(
4203    plugin = "bevy_render",
4204    name = "clear_color",
4205    description = "Emit a `ClearColor` resource literal using Bevy's default or an explicit color.",
4206    emit = None
4207)]
4208#[instrument(skip_all)]
4209async fn clear_color(p: BevyClearColorParams) -> Result<CallToolResult, ErrorData> {
4210    validate_clear_color(&p)?;
4211    ok_source(p.emit_code().to_string())
4212}
4213
4214#[elicit_tool(
4215    plugin = "bevy_render",
4216    name = "camera_3d_depth_load_op",
4217    description = "Emit a `Camera3dDepthLoadOp` expression for main-pass depth behavior.",
4218    emit = None
4219)]
4220#[instrument(skip_all)]
4221async fn camera_3d_depth_load_op(
4222    p: BevyCamera3dDepthLoadOpParams,
4223) -> Result<CallToolResult, ErrorData> {
4224    validate_camera_3d_depth_load_op(&p)?;
4225    ok_source(p.emit_code().to_string())
4226}
4227
4228#[elicit_tool(
4229    plugin = "bevy_render",
4230    name = "screen_space_transmission_quality",
4231    description = "Emit a `ScreenSpaceTransmissionQuality` resource value.",
4232    emit = None
4233)]
4234#[instrument(skip_all)]
4235async fn screen_space_transmission_quality(
4236    p: BevyScreenSpaceTransmissionQualityParams,
4237) -> Result<CallToolResult, ErrorData> {
4238    validate_screen_space_transmission_quality(&p)?;
4239    ok_source(p.emit_code().to_string())
4240}
4241
4242#[elicit_tool(
4243    plugin = "bevy_render",
4244    name = "main_pass_resolution_override",
4245    description = "Emit a `MainPassResolutionOverride` component for camera render scaling.",
4246    emit = None
4247)]
4248#[instrument(skip_all)]
4249async fn main_pass_resolution_override(
4250    p: BevyMainPassResolutionOverrideParams,
4251) -> Result<CallToolResult, ErrorData> {
4252    validate_main_pass_resolution_override(&p)?;
4253    ok_source(p.emit_code().to_string())
4254}
4255
4256#[elicit_tool(
4257    plugin = "bevy_render",
4258    name = "sub_camera_view",
4259    description = "Emit a `SubCameraView` value for tiled or multi-monitor camera layouts.",
4260    emit = None
4261)]
4262#[instrument(skip_all)]
4263async fn sub_camera_view(p: BevySubCameraViewParams) -> Result<CallToolResult, ErrorData> {
4264    validate_sub_camera_view(&p)?;
4265    ok_source(p.emit_code().to_string())
4266}
4267
4268#[elicit_tool(
4269    plugin = "bevy_render",
4270    name = "no_cpu_culling",
4271    description = "Emit a `NoCpuCulling` marker component.",
4272    emit = None
4273)]
4274#[instrument(skip_all)]
4275async fn no_cpu_culling(p: BevyNoCpuCullingParams) -> Result<CallToolResult, ErrorData> {
4276    ok_source(p.emit_code().to_string())
4277}
4278
4279#[elicit_tool(
4280    plugin = "bevy_render",
4281    name = "no_frustum_culling",
4282    description = "Emit a `NoFrustumCulling` marker component.",
4283    emit = None
4284)]
4285#[instrument(skip_all)]
4286async fn no_frustum_culling(p: BevyNoFrustumCullingParams) -> Result<CallToolResult, ErrorData> {
4287    ok_source(p.emit_code().to_string())
4288}
4289
4290#[elicit_tool(
4291    plugin = "bevy_render",
4292    name = "visibility_range",
4293    description = "Emit a `VisibilityRange` component with explicit near and far fade bands.",
4294    emit = None
4295)]
4296#[instrument(skip_all)]
4297async fn visibility_range(p: BevyVisibilityRangeParams) -> Result<CallToolResult, ErrorData> {
4298    validate_visibility_range(&p)?;
4299    ok_source(p.emit_code().to_string())
4300}
4301
4302#[elicit_tool(
4303    plugin = "bevy_render",
4304    name = "color",
4305    description = "Emit a structured `bevy::color::Color` expression using the selected Bevy color space.",
4306    emit = None
4307)]
4308#[instrument(skip_all)]
4309async fn color(p: BevyColorParams) -> Result<CallToolResult, ErrorData> {
4310    ok_source(p.emit_code().to_string())
4311}
4312
4313#[elicit_tool(
4314    plugin = "bevy_render",
4315    name = "alpha_mode",
4316    description = "Emit an `AlphaMode` enum expression.",
4317    emit = None
4318)]
4319#[instrument(skip_all)]
4320async fn alpha_mode(p: BevyRenderAlphaModeParams) -> Result<CallToolResult, ErrorData> {
4321    ok_source(p.emit_code().to_string())
4322}
4323
4324#[elicit_tool(
4325    plugin = "bevy_render",
4326    name = "uv_channel",
4327    description = "Emit a `UvChannel` enum expression.",
4328    emit = None
4329)]
4330#[instrument(skip_all)]
4331async fn uv_channel(p: BevyUvChannelParams) -> Result<CallToolResult, ErrorData> {
4332    validate_uv_channel(&p)?;
4333    ok_source(p.emit_code().to_string())
4334}
4335
4336#[elicit_tool(
4337    plugin = "bevy_render",
4338    name = "parallax_mapping_method",
4339    description = "Emit a `ParallaxMappingMethod` enum expression.",
4340    emit = None
4341)]
4342#[instrument(skip_all)]
4343async fn parallax_mapping_method(
4344    p: BevyParallaxMappingMethodParams,
4345) -> Result<CallToolResult, ErrorData> {
4346    validate_parallax_mapping_method(&p)?;
4347    ok_source(p.emit_code().to_string())
4348}
4349
4350#[elicit_tool(
4351    plugin = "bevy_render",
4352    name = "opaque_renderer_method",
4353    description = "Emit an `OpaqueRendererMethod` enum expression.",
4354    emit = None
4355)]
4356#[instrument(skip_all)]
4357async fn opaque_renderer_method(
4358    p: BevyOpaqueRendererMethodParams,
4359) -> Result<CallToolResult, ErrorData> {
4360    validate_opaque_renderer_method(&p)?;
4361    ok_source(p.emit_code().to_string())
4362}
4363
4364#[elicit_tool(
4365    plugin = "bevy_render",
4366    name = "default_opaque_renderer_method",
4367    description = "Emit a `DefaultOpaqueRendererMethod` resource constructor expression.",
4368    emit = None
4369)]
4370#[instrument(skip_all)]
4371async fn default_opaque_renderer_method(
4372    p: BevyDefaultOpaqueRendererMethodParams,
4373) -> Result<CallToolResult, ErrorData> {
4374    validate_default_opaque_renderer_method(&p)?;
4375    ok_source(p.emit_code().to_string())
4376}
4377
4378#[elicit_tool(
4379    plugin = "bevy_render",
4380    name = "alpha_mode_2d",
4381    description = "Emit an `AlphaMode2d` enum expression for 2D mesh materials.",
4382    emit = None
4383)]
4384#[instrument(skip_all)]
4385async fn alpha_mode_2d(p: BevyAlphaMode2dParams) -> Result<CallToolResult, ErrorData> {
4386    validate_alpha_mode_2d(&p)?;
4387    ok_source(p.emit_code().to_string())
4388}
4389
4390#[elicit_tool(
4391    plugin = "bevy_render",
4392    name = "standard_material",
4393    description = "Emit a `StandardMaterial` struct literal with common surface fields.",
4394    emit = None
4395)]
4396#[instrument(skip_all)]
4397async fn standard_material(p: BevyStandardMaterialParams) -> Result<CallToolResult, ErrorData> {
4398    validate_standard_material(&p)?;
4399    ok_source(p.emit_code().to_string())
4400}
4401
4402#[elicit_tool(
4403    plugin = "bevy_render",
4404    name = "lightmap",
4405    description = "Emit a `Lightmap` component for baked 3D lighting with optional atlas rect and bicubic sampling.",
4406    emit = None
4407)]
4408#[instrument(skip_all)]
4409async fn lightmap(p: BevyLightmapParams) -> Result<CallToolResult, ErrorData> {
4410    validate_lightmap(&p)?;
4411    ok_source(p.emit_code().to_string())
4412}
4413
4414#[elicit_tool(
4415    plugin = "bevy_render",
4416    name = "color_material",
4417    description = "Emit a `ColorMaterial` asset literal with optional tint, alpha mode, UV transform, and texture handle.",
4418    emit = None
4419)]
4420#[instrument(skip_all)]
4421async fn color_material(p: BevyColorMaterialParams) -> Result<CallToolResult, ErrorData> {
4422    validate_color_material(&p)?;
4423    ok_source(p.emit_code().to_string())
4424}
4425
4426#[elicit_tool(
4427    plugin = "bevy_render",
4428    name = "skybox",
4429    description = "Emit a `Skybox` component with cubemap handle, optional brightness, and optional rotation.",
4430    emit = None
4431)]
4432#[instrument(skip_all)]
4433async fn skybox(p: BevySkyboxParams) -> Result<CallToolResult, ErrorData> {
4434    validate_skybox(&p)?;
4435    ok_source(p.emit_code().to_string())
4436}
4437
4438#[elicit_tool(
4439    plugin = "bevy_render",
4440    name = "depth_prepass",
4441    description = "Emit the `DepthPrepass` camera marker component.",
4442    emit = None
4443)]
4444#[instrument(skip_all)]
4445async fn depth_prepass(p: BevyDepthPrepassParams) -> Result<CallToolResult, ErrorData> {
4446    validate_depth_prepass(&p)?;
4447    ok_source(p.emit_code().to_string())
4448}
4449
4450#[elicit_tool(
4451    plugin = "bevy_render",
4452    name = "normal_prepass",
4453    description = "Emit the `NormalPrepass` camera marker component.",
4454    emit = None
4455)]
4456#[instrument(skip_all)]
4457async fn normal_prepass(p: BevyNormalPrepassParams) -> Result<CallToolResult, ErrorData> {
4458    validate_normal_prepass(&p)?;
4459    ok_source(p.emit_code().to_string())
4460}
4461
4462#[elicit_tool(
4463    plugin = "bevy_render",
4464    name = "motion_vector_prepass",
4465    description = "Emit the `MotionVectorPrepass` camera marker component.",
4466    emit = None
4467)]
4468#[instrument(skip_all)]
4469async fn motion_vector_prepass(
4470    p: BevyMotionVectorPrepassParams,
4471) -> Result<CallToolResult, ErrorData> {
4472    validate_motion_vector_prepass(&p)?;
4473    ok_source(p.emit_code().to_string())
4474}
4475
4476#[elicit_tool(
4477    plugin = "bevy_render",
4478    name = "deferred_prepass",
4479    description = "Emit the `DeferredPrepass` camera marker component.",
4480    emit = None
4481)]
4482#[instrument(skip_all)]
4483async fn deferred_prepass(p: BevyDeferredPrepassParams) -> Result<CallToolResult, ErrorData> {
4484    validate_deferred_prepass(&p)?;
4485    ok_source(p.emit_code().to_string())
4486}
4487
4488#[elicit_tool(
4489    plugin = "bevy_render",
4490    name = "depth_prepass_double_buffer",
4491    description = "Emit the `DepthPrepassDoubleBuffer` marker component for previous-frame depth queries.",
4492    emit = None
4493)]
4494#[instrument(skip_all)]
4495async fn depth_prepass_double_buffer(
4496    p: BevyDepthPrepassDoubleBufferParams,
4497) -> Result<CallToolResult, ErrorData> {
4498    validate_depth_prepass_double_buffer(&p)?;
4499    ok_source(p.emit_code().to_string())
4500}
4501
4502#[elicit_tool(
4503    plugin = "bevy_render",
4504    name = "deferred_prepass_double_buffer",
4505    description = "Emit the `DeferredPrepassDoubleBuffer` marker component for previous-frame deferred g-buffer queries.",
4506    emit = None
4507)]
4508#[instrument(skip_all)]
4509async fn deferred_prepass_double_buffer(
4510    p: BevyDeferredPrepassDoubleBufferParams,
4511) -> Result<CallToolResult, ErrorData> {
4512    validate_deferred_prepass_double_buffer(&p)?;
4513    ok_source(p.emit_code().to_string())
4514}
4515
4516#[elicit_tool(
4517    plugin = "bevy_render",
4518    name = "ambient_light",
4519    description = "Emit an `AmbientLight` struct literal.",
4520    emit = None
4521)]
4522#[instrument(skip_all)]
4523async fn ambient_light(p: BevyAmbientLightParams) -> Result<CallToolResult, ErrorData> {
4524    validate_ambient_light(&p)?;
4525    ok_source(p.emit_code().to_string())
4526}
4527
4528#[elicit_tool(
4529    plugin = "bevy_render",
4530    name = "global_ambient_light",
4531    description = "Emit a `GlobalAmbientLight` resource literal for scene-wide ambient lighting defaults.",
4532    emit = None
4533)]
4534#[instrument(skip_all)]
4535async fn global_ambient_light(
4536    p: BevyGlobalAmbientLightParams,
4537) -> Result<CallToolResult, ErrorData> {
4538    validate_global_ambient_light(&p)?;
4539    ok_source(p.emit_code().to_string())
4540}
4541
4542#[elicit_tool(
4543    plugin = "bevy_render",
4544    name = "directional_light",
4545    description = "Emit a `DirectionalLight` struct literal.",
4546    emit = None
4547)]
4548#[instrument(skip_all)]
4549async fn directional_light(p: BevyDirectionalLightParams) -> Result<CallToolResult, ErrorData> {
4550    validate_directional_light(&p)?;
4551    ok_source(p.emit_code().to_string())
4552}
4553
4554#[elicit_tool(
4555    plugin = "bevy_render",
4556    name = "point_light",
4557    description = "Emit a `PointLight` struct literal.",
4558    emit = None
4559)]
4560#[instrument(skip_all)]
4561async fn point_light(p: BevyPointLightParams) -> Result<CallToolResult, ErrorData> {
4562    validate_point_light(&p)?;
4563    ok_source(p.emit_code().to_string())
4564}
4565
4566#[elicit_tool(
4567    plugin = "bevy_render",
4568    name = "spot_light",
4569    description = "Emit a `SpotLight` struct literal.",
4570    emit = None
4571)]
4572#[instrument(skip_all)]
4573async fn spot_light(p: BevySpotLightParams) -> Result<CallToolResult, ErrorData> {
4574    validate_spot_light(&p)?;
4575    ok_source(p.emit_code().to_string())
4576}
4577
4578#[elicit_tool(
4579    plugin = "bevy_render",
4580    name = "directional_light_shadow_map",
4581    description = "Emit a `DirectionalLightShadowMap` resource expression with an optional power-of-two cascade size.",
4582    emit = None
4583)]
4584#[instrument(skip_all)]
4585async fn directional_light_shadow_map(
4586    p: BevyDirectionalLightShadowMapParams,
4587) -> Result<CallToolResult, ErrorData> {
4588    validate_directional_light_shadow_map(&p)?;
4589    ok_source(p.emit_code().to_string())
4590}
4591
4592#[elicit_tool(
4593    plugin = "bevy_render",
4594    name = "point_light_shadow_map",
4595    description = "Emit a `PointLightShadowMap` resource expression with an optional power-of-two cubemap-face size.",
4596    emit = None
4597)]
4598#[instrument(skip_all)]
4599async fn point_light_shadow_map(
4600    p: BevyPointLightShadowMapParams,
4601) -> Result<CallToolResult, ErrorData> {
4602    validate_point_light_shadow_map(&p)?;
4603    ok_source(p.emit_code().to_string())
4604}
4605
4606#[elicit_tool(
4607    plugin = "bevy_render",
4608    name = "environment_map_light",
4609    description = "Emit an `EnvironmentMapLight` component with diffuse/specular cubemap handles and optional tuning fields.",
4610    emit = None
4611)]
4612#[instrument(skip_all)]
4613async fn environment_map_light(
4614    p: BevyEnvironmentMapLightParams,
4615) -> Result<CallToolResult, ErrorData> {
4616    validate_environment_map_light(&p)?;
4617    ok_source(p.emit_code().to_string())
4618}
4619
4620#[elicit_tool(
4621    plugin = "bevy_render",
4622    name = "generated_environment_map_light",
4623    description = "Emit a `GeneratedEnvironmentMapLight` component for runtime-filtered cubemap lighting.",
4624    emit = None
4625)]
4626#[instrument(skip_all)]
4627async fn generated_environment_map_light(
4628    p: BevyGeneratedEnvironmentMapLightParams,
4629) -> Result<CallToolResult, ErrorData> {
4630    validate_generated_environment_map_light(&p)?;
4631    ok_source(p.emit_code().to_string())
4632}
4633
4634#[elicit_tool(
4635    plugin = "bevy_render",
4636    name = "atmosphere_environment_map_light",
4637    description = "Emit an `AtmosphereEnvironmentMapLight` component for atmosphere-driven image-based lighting.",
4638    emit = None
4639)]
4640#[instrument(skip_all)]
4641async fn atmosphere_environment_map_light(
4642    p: BevyAtmosphereEnvironmentMapLightParams,
4643) -> Result<CallToolResult, ErrorData> {
4644    validate_atmosphere_environment_map_light(&p)?;
4645    ok_source(p.emit_code().to_string())
4646}
4647
4648#[elicit_tool(
4649    plugin = "bevy_render",
4650    name = "volumetric_light",
4651    description = "Emit the `VolumetricLight` marker component used for light shafts and god rays.",
4652    emit = None
4653)]
4654#[instrument(skip_all)]
4655async fn volumetric_light(p: BevyVolumetricLightParams) -> Result<CallToolResult, ErrorData> {
4656    validate_volumetric_light(&p)?;
4657    ok_source(p.emit_code().to_string())
4658}
4659
4660#[elicit_tool(
4661    plugin = "bevy_render",
4662    name = "volumetric_fog",
4663    description = "Emit a `VolumetricFog` component for Bevy 0.18 camera-based volumetric fog.",
4664    emit = None
4665)]
4666#[instrument(skip_all)]
4667async fn volumetric_fog(p: BevyVolumetricFogParams) -> Result<CallToolResult, ErrorData> {
4668    validate_volumetric_fog(&p)?;
4669    ok_source(p.emit_code().to_string())
4670}
4671
4672#[elicit_tool(
4673    plugin = "bevy_render",
4674    name = "fog_volume",
4675    description = "Emit a `FogVolume` component with optional density texture, optical coefficients, and artistic tint controls.",
4676    emit = None
4677)]
4678#[instrument(skip_all)]
4679async fn fog_volume(p: BevyFogVolumeParams) -> Result<CallToolResult, ErrorData> {
4680    validate_fog_volume(&p)?;
4681    ok_source(p.emit_code().to_string())
4682}
4683
4684#[elicit_tool(
4685    plugin = "bevy_render",
4686    name = "light_probe",
4687    description = "Emit the `LightProbe` marker component for probe-bounded indirect lighting regions.",
4688    emit = None
4689)]
4690#[instrument(skip_all)]
4691async fn light_probe(p: BevyLightProbeParams) -> Result<CallToolResult, ErrorData> {
4692    validate_light_probe(&p)?;
4693    ok_source(p.emit_code().to_string())
4694}
4695
4696#[elicit_tool(
4697    plugin = "bevy_render",
4698    name = "irradiance_volume",
4699    description = "Emit an `IrradianceVolume` component with voxel texture, intensity, and lightmap interaction controls.",
4700    emit = None
4701)]
4702#[instrument(skip_all)]
4703async fn irradiance_volume(p: BevyIrradianceVolumeParams) -> Result<CallToolResult, ErrorData> {
4704    validate_irradiance_volume(&p)?;
4705    ok_source(p.emit_code().to_string())
4706}
4707
4708#[elicit_tool(
4709    plugin = "bevy_render",
4710    name = "sun_disk",
4711    description = "Emit a `SunDisk` component for atmosphere-visible directional-light disks.",
4712    emit = None
4713)]
4714#[instrument(skip_all)]
4715async fn sun_disk(p: BevySunDiskParams) -> Result<CallToolResult, ErrorData> {
4716    validate_sun_disk(&p)?;
4717    ok_source(p.emit_code().to_string())
4718}
4719
4720#[elicit_tool(
4721    plugin = "bevy_render",
4722    name = "not_shadow_caster",
4723    description = "Emit the `NotShadowCaster` marker component to disable mesh shadow casting.",
4724    emit = None
4725)]
4726#[instrument(skip_all)]
4727async fn not_shadow_caster(p: BevyNotShadowCasterParams) -> Result<CallToolResult, ErrorData> {
4728    validate_not_shadow_caster(&p)?;
4729    ok_source(p.emit_code().to_string())
4730}
4731
4732#[elicit_tool(
4733    plugin = "bevy_render",
4734    name = "not_shadow_receiver",
4735    description = "Emit the `NotShadowReceiver` marker component to disable mesh shadow reception.",
4736    emit = None
4737)]
4738#[instrument(skip_all)]
4739async fn not_shadow_receiver(p: BevyNotShadowReceiverParams) -> Result<CallToolResult, ErrorData> {
4740    validate_not_shadow_receiver(&p)?;
4741    ok_source(p.emit_code().to_string())
4742}
4743
4744#[elicit_tool(
4745    plugin = "bevy_render",
4746    name = "transmitted_shadow_receiver",
4747    description = "Emit the `TransmittedShadowReceiver` marker component for diffuse transmission shadows.",
4748    emit = None
4749)]
4750#[instrument(skip_all)]
4751async fn transmitted_shadow_receiver(
4752    p: BevyTransmittedShadowReceiverParams,
4753) -> Result<CallToolResult, ErrorData> {
4754    validate_transmitted_shadow_receiver(&p)?;
4755    ok_source(p.emit_code().to_string())
4756}
4757
4758#[elicit_tool(
4759    plugin = "bevy_render",
4760    name = "shadow_filtering_method",
4761    description = "Emit a `ShadowFilteringMethod` camera component for shadow edge filtering mode.",
4762    emit = None
4763)]
4764#[instrument(skip_all)]
4765async fn shadow_filtering_method(
4766    p: BevyShadowFilteringMethodParams,
4767) -> Result<CallToolResult, ErrorData> {
4768    validate_shadow_filtering_method(&p)?;
4769    ok_source(p.emit_code().to_string())
4770}
4771
4772#[elicit_tool(
4773    plugin = "bevy_render",
4774    name = "cluster_far_z_mode",
4775    description = "Emit a `ClusterFarZMode` expression for clustered-lighting depth strategy.",
4776    emit = None
4777)]
4778#[instrument(skip_all)]
4779async fn cluster_far_z_mode(p: BevyClusterFarZModeParams) -> Result<CallToolResult, ErrorData> {
4780    validate_cluster_far_z_mode(&p)?;
4781    ok_source(p.emit_code().to_string())
4782}
4783
4784#[elicit_tool(
4785    plugin = "bevy_render",
4786    name = "cluster_z_config",
4787    description = "Emit a `ClusterZConfig` literal for clustered-lighting depth slicing.",
4788    emit = None
4789)]
4790#[instrument(skip_all)]
4791async fn cluster_z_config(p: BevyClusterZConfigParams) -> Result<CallToolResult, ErrorData> {
4792    validate_cluster_z_config(&p)?;
4793    ok_source(p.emit_code().to_string())
4794}
4795
4796#[elicit_tool(
4797    plugin = "bevy_render",
4798    name = "cluster_config",
4799    description = "Emit a `ClusterConfig` camera component for Bevy clustered-lighting strategy.",
4800    emit = None
4801)]
4802#[instrument(skip_all)]
4803async fn cluster_config(p: BevyClusterConfigParams) -> Result<CallToolResult, ErrorData> {
4804    validate_cluster_config(&p)?;
4805    ok_source(p.emit_code().to_string())
4806}
4807
4808#[elicit_tool(
4809    plugin = "bevy_render",
4810    name = "screen_space_reflections",
4811    description = "Emit a `ScreenSpaceReflections` camera component for deferred screen-space reflections.",
4812    emit = None
4813)]
4814#[instrument(skip_all)]
4815async fn screen_space_reflections(
4816    p: BevyScreenSpaceReflectionsParams,
4817) -> Result<CallToolResult, ErrorData> {
4818    validate_screen_space_reflections(&p)?;
4819    ok_source(p.emit_code().to_string())
4820}
4821
4822#[elicit_tool(
4823    plugin = "bevy_render",
4824    name = "clustered_decal",
4825    description = "Emit a `ClusteredDecal` component with optional texture handles and application tag.",
4826    emit = None
4827)]
4828#[instrument(skip_all)]
4829async fn clustered_decal(p: BevyClusteredDecalParams) -> Result<CallToolResult, ErrorData> {
4830    validate_clustered_decal(&p)?;
4831    ok_source(p.emit_code().to_string())
4832}
4833
4834#[elicit_tool(
4835    plugin = "bevy_render",
4836    name = "mesh_3d",
4837    description = "Emit a `Mesh3d` component from a mesh handle expression.",
4838    emit = None
4839)]
4840#[instrument(skip_all)]
4841async fn mesh_3d(p: BevyMesh3dParams) -> Result<CallToolResult, ErrorData> {
4842    validate_mesh_3d(&p)?;
4843    ok_source(p.emit_code().to_string())
4844}
4845
4846#[elicit_tool(
4847    plugin = "bevy_render",
4848    name = "mesh_2d",
4849    description = "Emit a `Mesh2d` component from a mesh handle expression.",
4850    emit = None
4851)]
4852#[instrument(skip_all)]
4853async fn mesh_2d(p: BevyMesh2dParams) -> Result<CallToolResult, ErrorData> {
4854    validate_mesh_2d(&p)?;
4855    ok_source(p.emit_code().to_string())
4856}
4857
4858#[elicit_tool(
4859    plugin = "bevy_render",
4860    name = "mesh_material_3d",
4861    description = "Emit a generic `MeshMaterial3d<M>` component from a typed material handle expression.",
4862    emit = None
4863)]
4864#[instrument(skip_all)]
4865async fn mesh_material_3d(p: BevyMeshMaterial3dParams) -> Result<CallToolResult, ErrorData> {
4866    validate_mesh_material_3d(&p)?;
4867    ok_source(p.emit_code().to_string())
4868}
4869
4870#[elicit_tool(
4871    plugin = "bevy_render",
4872    name = "mesh_material_2d",
4873    description = "Emit a generic `MeshMaterial2d<M>` component from a typed material handle expression.",
4874    emit = None
4875)]
4876#[instrument(skip_all)]
4877async fn mesh_material_2d(p: BevyMeshMaterial2dParams) -> Result<CallToolResult, ErrorData> {
4878    validate_mesh_material_2d(&p)?;
4879    ok_source(p.emit_code().to_string())
4880}
4881
4882#[elicit_tool(
4883    plugin = "bevy_render",
4884    name = "wireframe",
4885    description = "Emit the `Wireframe` marker component for 3D meshes.",
4886    emit = None
4887)]
4888#[instrument(skip_all)]
4889async fn wireframe(p: BevyWireframeParams) -> Result<CallToolResult, ErrorData> {
4890    validate_wireframe(&p)?;
4891    ok_source(p.emit_code().to_string())
4892}
4893
4894#[elicit_tool(
4895    plugin = "bevy_render",
4896    name = "wireframe_color",
4897    description = "Emit a `WireframeColor` component for overriding 3D wireframe tint.",
4898    emit = None
4899)]
4900#[instrument(skip_all)]
4901async fn wireframe_color(p: BevyWireframeColorParams) -> Result<CallToolResult, ErrorData> {
4902    validate_wireframe_color(&p)?;
4903    ok_source(p.emit_code().to_string())
4904}
4905
4906#[elicit_tool(
4907    plugin = "bevy_render",
4908    name = "no_wireframe",
4909    description = "Emit the `NoWireframe` marker component to opt out of global 3D wireframes.",
4910    emit = None
4911)]
4912#[instrument(skip_all)]
4913async fn no_wireframe(p: BevyNoWireframeParams) -> Result<CallToolResult, ErrorData> {
4914    validate_no_wireframe(&p)?;
4915    ok_source(p.emit_code().to_string())
4916}
4917
4918#[elicit_tool(
4919    plugin = "bevy_render",
4920    name = "wireframe_config",
4921    description = "Emit a `WireframeConfig` resource with optional global flag and fallback color.",
4922    emit = None
4923)]
4924#[instrument(skip_all)]
4925async fn wireframe_config(p: BevyWireframeConfigParams) -> Result<CallToolResult, ErrorData> {
4926    validate_wireframe_config(&p)?;
4927    ok_source(p.emit_code().to_string())
4928}
4929
4930#[elicit_tool(
4931    plugin = "bevy_render",
4932    name = "mesh_3d_wireframe",
4933    description = "Emit a `Mesh3dWireframe` component from a wireframe material handle expression.",
4934    emit = None
4935)]
4936#[instrument(skip_all)]
4937async fn mesh_3d_wireframe(p: BevyMesh3dWireframeParams) -> Result<CallToolResult, ErrorData> {
4938    validate_mesh_3d_wireframe(&p)?;
4939    ok_source(p.emit_code().to_string())
4940}
4941
4942#[elicit_tool(
4943    plugin = "bevy_render",
4944    name = "wireframe_2d",
4945    description = "Emit the `Wireframe2d` marker component for 2D meshes.",
4946    emit = None
4947)]
4948#[instrument(skip_all)]
4949async fn wireframe_2d(p: BevyWireframe2dParams) -> Result<CallToolResult, ErrorData> {
4950    validate_wireframe_2d(&p)?;
4951    ok_source(p.emit_code().to_string())
4952}
4953
4954#[elicit_tool(
4955    plugin = "bevy_render",
4956    name = "wireframe_2d_color",
4957    description = "Emit a `Wireframe2dColor` component for overriding 2D wireframe tint.",
4958    emit = None
4959)]
4960#[instrument(skip_all)]
4961async fn wireframe_2d_color(p: BevyWireframe2dColorParams) -> Result<CallToolResult, ErrorData> {
4962    validate_wireframe_2d_color(&p)?;
4963    ok_source(p.emit_code().to_string())
4964}
4965
4966#[elicit_tool(
4967    plugin = "bevy_render",
4968    name = "no_wireframe_2d",
4969    description = "Emit the `NoWireframe2d` marker component to opt out of global 2D wireframes.",
4970    emit = None
4971)]
4972#[instrument(skip_all)]
4973async fn no_wireframe_2d(p: BevyNoWireframe2dParams) -> Result<CallToolResult, ErrorData> {
4974    validate_no_wireframe_2d(&p)?;
4975    ok_source(p.emit_code().to_string())
4976}
4977
4978#[elicit_tool(
4979    plugin = "bevy_render",
4980    name = "wireframe_2d_config",
4981    description = "Emit a `Wireframe2dConfig` resource with optional global flag and fallback color.",
4982    emit = None
4983)]
4984#[instrument(skip_all)]
4985async fn wireframe_2d_config(p: BevyWireframe2dConfigParams) -> Result<CallToolResult, ErrorData> {
4986    validate_wireframe_2d_config(&p)?;
4987    ok_source(p.emit_code().to_string())
4988}
4989
4990#[elicit_tool(
4991    plugin = "bevy_render",
4992    name = "mesh_2d_wireframe",
4993    description = "Emit a `Mesh2dWireframe` component from a 2D wireframe material handle expression.",
4994    emit = None
4995)]
4996#[instrument(skip_all)]
4997async fn mesh_2d_wireframe(p: BevyMesh2dWireframeParams) -> Result<CallToolResult, ErrorData> {
4998    validate_mesh_2d_wireframe(&p)?;
4999    ok_source(p.emit_code().to_string())
5000}
5001
5002#[elicit_tool(
5003    plugin = "bevy_render",
5004    name = "camera_3d",
5005    description = "Emit a Bevy 0.18 camera spawn tuple with `Camera3d`, `Projection`, and `RenderTarget`.",
5006    emit = None
5007)]
5008#[instrument(skip_all)]
5009async fn camera_3d(p: BevyCamera3dParams) -> Result<CallToolResult, ErrorData> {
5010    validate_camera_3d(&p)?;
5011    ok_source(p.emit_code().to_string())
5012}
5013
5014#[elicit_tool(
5015    plugin = "bevy_render",
5016    name = "camera_2d",
5017    description = "Emit a Bevy 0.18 camera spawn tuple with `Camera2d`, `Projection`, and `RenderTarget`.",
5018    emit = None
5019)]
5020#[instrument(skip_all)]
5021async fn camera_2d(p: BevyCamera2dParams) -> Result<CallToolResult, ErrorData> {
5022    validate_camera_2d(&p)?;
5023    ok_source(p.emit_code().to_string())
5024}
5025
5026#[elicit_tool(
5027    plugin = "bevy_render",
5028    name = "viewport",
5029    description = "Emit a `Viewport` literal with physical position, size, and depth range.",
5030    emit = None
5031)]
5032#[instrument(skip_all)]
5033async fn viewport(p: BevyViewportParams) -> Result<CallToolResult, ErrorData> {
5034    validate_viewport(&p)?;
5035    ok_source(p.emit_code().to_string())
5036}
5037
5038#[elicit_tool(
5039    plugin = "bevy_render",
5040    name = "fog_settings",
5041    description = "Emit a Bevy 0.18 `DistanceFog` literal; this replaces the older `FogSettings` surface.",
5042    emit = None
5043)]
5044#[instrument(skip_all)]
5045async fn fog_settings(p: BevyFogSettingsParams) -> Result<CallToolResult, ErrorData> {
5046    validate_fog_settings(&p)?;
5047    ok_source(p.emit_code().to_string())
5048}
5049
5050#[elicit_tool(
5051    plugin = "bevy_render",
5052    name = "bloom_composite_mode",
5053    description = "Emit a `BloomCompositeMode` enum expression.",
5054    emit = None
5055)]
5056#[instrument(skip_all)]
5057async fn bloom_composite_mode(
5058    p: BevyBloomCompositeModeParams,
5059) -> Result<CallToolResult, ErrorData> {
5060    ok_source(p.emit_code().to_string())
5061}
5062
5063#[elicit_tool(
5064    plugin = "bevy_render",
5065    name = "bloom_settings",
5066    description = "Emit a Bevy 0.18 `Bloom` value, starting from an optional preset and overriding common fields.",
5067    emit = None
5068)]
5069#[instrument(skip_all)]
5070async fn bloom_settings(p: BevyBloomSettingsParams) -> Result<CallToolResult, ErrorData> {
5071    validate_bloom_settings(&p)?;
5072    ok_source(p.emit_code().to_string())
5073}
5074
5075#[elicit_tool(
5076    plugin = "bevy_render",
5077    name = "sprite",
5078    description = "Emit a current Bevy `Sprite` literal with image, tint, flips, and optional custom size.",
5079    emit = None
5080)]
5081#[instrument(skip_all)]
5082async fn sprite(p: BevySpriteParams) -> Result<CallToolResult, ErrorData> {
5083    validate_sprite(&p)?;
5084    ok_source(p.emit_code().to_string())
5085}
5086
5087#[elicit_tool(
5088    plugin = "bevy_render",
5089    name = "text_style",
5090    description = "Emit the current Bevy text-style component tuple: `TextFont`, `TextColor`, and `TextLayout`.",
5091    emit = None
5092)]
5093#[instrument(skip_all)]
5094async fn text_style(p: BevyTextStyleParams) -> Result<CallToolResult, ErrorData> {
5095    validate_text_style(&p)?;
5096    ok_source(p.emit_code().to_string())
5097}
5098
5099#[elicit_tool(
5100    plugin = "bevy_render",
5101    name = "ssao_quality",
5102    description = "Emit a `ScreenSpaceAmbientOcclusionQualityLevel` enum expression, including custom slice/sample counts.",
5103    emit = None
5104)]
5105#[instrument(skip_all)]
5106async fn ssao_quality(p: BevySsaoQualityParams) -> Result<CallToolResult, ErrorData> {
5107    validate_ssao_quality(&p)?;
5108    ok_source(p.emit_code().to_string())
5109}
5110
5111#[elicit_tool(
5112    plugin = "bevy_render",
5113    name = "ssao",
5114    description = "Emit a `ScreenSpaceAmbientOcclusion` component literal for Bevy 0.18.",
5115    emit = None
5116)]
5117#[instrument(skip_all)]
5118async fn ssao(p: BevySsaoParams) -> Result<CallToolResult, ErrorData> {
5119    validate_ssao(&p)?;
5120    ok_source(p.emit_code().to_string())
5121}
5122
5123#[elicit_tool(
5124    plugin = "bevy_render",
5125    name = "temporal_anti_aliasing",
5126    description = "Emit the current Bevy 0.18 `TemporalAntiAliasing` component literal.",
5127    emit = None
5128)]
5129#[instrument(skip_all)]
5130async fn temporal_anti_aliasing(
5131    p: BevyTemporalAntiAliasingParams,
5132) -> Result<CallToolResult, ErrorData> {
5133    validate_temporal_anti_aliasing(&p)?;
5134    ok_source(p.emit_code().to_string())
5135}
5136
5137#[elicit_tool(
5138    plugin = "bevy_render",
5139    name = "cascade_shadow_config",
5140    description = "Emit a `CascadeShadowConfig` expression for Bevy 0.18 directional-light shadows.",
5141    emit = None
5142)]
5143#[instrument(skip_all)]
5144async fn cascade_shadow_config(
5145    p: BevyCascadeShadowConfigParams,
5146) -> Result<CallToolResult, ErrorData> {
5147    validate_cascade_shadow_config(&p)?;
5148    ok_source(p.emit_code().to_string())
5149}
5150
5151#[elicit_tool(
5152    plugin = "bevy_render",
5153    name = "cascade_shadow_config_builder",
5154    description = "Emit a `CascadeShadowConfigBuilder` literal with optional overrides over Bevy's defaults.",
5155    emit = None
5156)]
5157#[instrument(skip_all)]
5158async fn cascade_shadow_config_builder(
5159    p: BevyCascadeShadowConfigBuilderParams,
5160) -> Result<CallToolResult, ErrorData> {
5161    validate_cascade_shadow_config_builder(&p)?;
5162    ok_source(p.emit_code().to_string())
5163}
5164
5165#[elicit_tool(
5166    plugin = "bevy_render",
5167    name = "atmosphere",
5168    description = "Emit a block expression that adds a `ScatteringMedium` asset and returns a Bevy 0.18 `Atmosphere` component.",
5169    emit = None
5170)]
5171#[instrument(skip_all)]
5172async fn atmosphere(p: BevyAtmosphereParams) -> Result<CallToolResult, ErrorData> {
5173    validate_atmosphere(&p)?;
5174    ok_source(p.emit_code().to_string())
5175}
5176
5177#[elicit_tool(
5178    plugin = "bevy_render",
5179    name = "fullscreen_material",
5180    description = "Emit `impl FullscreenMaterial` boilerplate for an existing fullscreen effect component.",
5181    emit = None
5182)]
5183#[instrument(skip_all)]
5184async fn fullscreen_material(p: BevyFullscreenMaterialParams) -> Result<CallToolResult, ErrorData> {
5185    validate_fullscreen_material(&p)?;
5186    ok_source(p.emit_code().to_string())
5187}