nightshade-editor 0.13.3

An interactive editor for the Nightshade game engine
use nightshade::ecs::graphics::{
    ColorGradingPreset, DepthOfField, DepthOfFieldQuality, Fog, TonemapAlgorithm, VertexSnap,
};
use nightshade::prelude::*;

pub fn visual_effects_panel_ui(
    ui_context: &egui::Context,
    world: &mut World,
    show_window: &mut bool,
    grayscale_enabled: &mut bool,
) {
    if !*show_window {
        return;
    }

    let mut window_open = *show_window;

    egui::Window::new("Visual Effects")
        .open(&mut window_open)
        .default_width(350.0)
        .default_height(600.0)
        .resizable(true)
        .show(ui_context, |ui| {
            egui::ScrollArea::vertical().show(ui, |ui| {
                vertex_snapping_section(ui, world);
                texture_mapping_section(ui, world);
                fog_section(ui, world);
                post_processing_section(ui, grayscale_enabled);
                color_grading_section(ui, world);
                bloom_section(ui, world);
                depth_of_field_section(ui, world);
            });
        });

    *show_window = window_open;
}

fn vertex_snapping_section(ui: &mut egui::Ui, world: &mut World) {
    ui.collapsing("Vertex Snapping", |ui| {
        let mut snap_enabled = world.resources.graphics.vertex_snap.is_some();
        if ui.checkbox(&mut snap_enabled, "Enable").changed() {
            if snap_enabled {
                world.resources.graphics.vertex_snap = Some(VertexSnap::default());
            } else {
                world.resources.graphics.vertex_snap = None;
            }
        }
        if let Some(ref mut vertex_snap) = world.resources.graphics.vertex_snap {
            ui.horizontal(|ui| {
                ui.label("Resolution X:");
                ui.add(
                    egui::Slider::new(&mut vertex_snap.resolution[0], 80.0..=640.0).max_decimals(0),
                );
            });
            ui.horizontal(|ui| {
                ui.label("Resolution Y:");
                ui.add(
                    egui::Slider::new(&mut vertex_snap.resolution[1], 60.0..=480.0).max_decimals(0),
                );
            });
        }
    });
}

fn texture_mapping_section(ui: &mut egui::Ui, world: &mut World) {
    ui.collapsing("Texture Mapping", |ui| {
        ui.checkbox(
            &mut world.resources.graphics.affine_texture_mapping,
            "Affine Texture Mapping",
        );
    });
}

fn fog_section(ui: &mut egui::Ui, world: &mut World) {
    ui.collapsing("Distance Fog", |ui| {
        let mut fog_enabled = world.resources.graphics.fog.is_some();
        if ui.checkbox(&mut fog_enabled, "Enable").changed() {
            if fog_enabled {
                world.resources.graphics.fog = Some(Fog::default());
            } else {
                world.resources.graphics.fog = None;
            }
        }
        if let Some(ref mut fog) = world.resources.graphics.fog {
            ui.horizontal(|ui| {
                ui.label("Start:");
                ui.add(egui::Slider::new(&mut fog.start, 0.5..=10.0));
            });
            ui.horizontal(|ui| {
                ui.label("End:");
                ui.add(egui::Slider::new(&mut fog.end, 5.0..=50.0));
            });
            ui.horizontal(|ui| {
                ui.label("Color:");
                ui.color_edit_button_rgb(&mut fog.color);
            });
        }
    });
}

fn post_processing_section(ui: &mut egui::Ui, grayscale_enabled: &mut bool) {
    ui.collapsing("Post-Processing", |ui| {
        ui.checkbox(grayscale_enabled, "Grayscale");
    });
}

fn color_grading_section(ui: &mut egui::Ui, world: &mut World) {
    ui.collapsing("Color Grading", |ui| {
        let color_grading = &mut world.resources.graphics.color_grading;

        ui.horizontal(|ui| {
            ui.label("Preset:");
            ui.label(color_grading.preset.name());
        });

        ui.horizontal_wrapped(|ui| {
            for preset in ColorGradingPreset::ALL {
                if *preset == ColorGradingPreset::Custom {
                    continue;
                }
                let is_selected = color_grading.preset == *preset;
                if ui.selectable_label(is_selected, preset.name()).clicked() {
                    *color_grading = preset.to_color_grading();
                }
            }
        });

        ui.add_space(4.0);

        ui.horizontal(|ui| {
            ui.label("Tonemap:");
            egui::ComboBox::from_id_salt("tonemap_algorithm_ve")
                .selected_text(color_grading.tonemap_algorithm.name())
                .show_ui(ui, |ui| {
                    for algorithm in TonemapAlgorithm::ALL {
                        if ui
                            .selectable_value(
                                &mut color_grading.tonemap_algorithm,
                                *algorithm,
                                algorithm.name(),
                            )
                            .changed()
                        {
                            color_grading.preset = ColorGradingPreset::Custom;
                        }
                    }
                });
        });

        ui.horizontal(|ui| {
            ui.label("Gamma:");
            if ui
                .add(egui::Slider::new(&mut color_grading.gamma, 1.0..=3.0).fixed_decimals(2))
                .changed()
            {
                color_grading.preset = ColorGradingPreset::Custom;
            }
        });

        ui.horizontal(|ui| {
            ui.label("Saturation:");
            if ui
                .add(egui::Slider::new(&mut color_grading.saturation, 0.0..=2.0).fixed_decimals(2))
                .changed()
            {
                color_grading.preset = ColorGradingPreset::Custom;
            }
        });

        ui.horizontal(|ui| {
            ui.label("Brightness:");
            if ui
                .add(egui::Slider::new(&mut color_grading.brightness, -0.5..=0.5).fixed_decimals(2))
                .changed()
            {
                color_grading.preset = ColorGradingPreset::Custom;
            }
        });

        ui.horizontal(|ui| {
            ui.label("Contrast:");
            if ui
                .add(egui::Slider::new(&mut color_grading.contrast, 0.5..=2.0).fixed_decimals(2))
                .changed()
            {
                color_grading.preset = ColorGradingPreset::Custom;
            }
        });
    });
}

fn bloom_section(ui: &mut egui::Ui, world: &mut World) {
    ui.collapsing("Bloom", |ui| {
        ui.checkbox(&mut world.resources.graphics.bloom_enabled, "Enable");
        ui.add_enabled_ui(world.resources.graphics.bloom_enabled, |ui| {
            ui.horizontal(|ui| {
                ui.label("Intensity:");
                ui.add(egui::Slider::new(
                    &mut world.resources.graphics.bloom_intensity,
                    0.0..=2.0,
                ));
            });
            ui.horizontal(|ui| {
                ui.label("Threshold:");
                ui.add(egui::Slider::new(
                    &mut world.resources.graphics.bloom_threshold,
                    0.0..=5.0,
                ));
            });
        });
    });
}

fn depth_of_field_section(ui: &mut egui::Ui, world: &mut World) {
    let default_open = world.resources.graphics.depth_of_field.enabled;
    egui::CollapsingHeader::new("Depth of Field")
        .default_open(default_open)
        .show(ui, |ui| {
            let dof = &mut world.resources.graphics.depth_of_field;

            ui.checkbox(&mut dof.enabled, "Enable");

            ui.add_enabled_ui(dof.enabled, |ui| {
                ui.horizontal(|ui| {
                    ui.label("Focus Distance:");
                    ui.add(
                        egui::Slider::new(&mut dof.focus_distance, 0.5..=100.0).logarithmic(true),
                    );
                });

                ui.horizontal(|ui| {
                    ui.label("Focus Range:");
                    ui.add(egui::Slider::new(&mut dof.focus_range, 0.1..=50.0).logarithmic(true));
                });

                ui.horizontal(|ui| {
                    ui.label("Max Blur:");
                    ui.add(egui::Slider::new(&mut dof.max_blur_radius, 1.0..=20.0));
                });

                ui.horizontal(|ui| {
                    ui.label("Bokeh Threshold:");
                    ui.add(egui::Slider::new(&mut dof.bokeh_threshold, 0.0..=1.0));
                });

                ui.horizontal(|ui| {
                    ui.label("Bokeh Intensity:");
                    ui.add(egui::Slider::new(&mut dof.bokeh_intensity, 0.0..=3.0));
                });

                ui.horizontal(|ui| {
                    ui.label("Quality:");
                    egui::ComboBox::from_id_salt("dof_quality_ve")
                        .selected_text(dof.quality.name())
                        .show_ui(ui, |ui| {
                            for quality in DepthOfFieldQuality::ALL {
                                ui.selectable_value(&mut dof.quality, *quality, quality.name());
                            }
                        });
                });

                ui.checkbox(&mut dof.visualize_coc, "Visualize CoC");

                ui.separator();
                ui.label("Tilt Shift");

                ui.checkbox(&mut dof.tilt_shift_enabled, "Enable Tilt Shift");

                ui.add_enabled_ui(dof.tilt_shift_enabled, |ui| {
                    ui.horizontal(|ui| {
                        ui.label("Angle:");
                        ui.add(
                            egui::Slider::new(&mut dof.tilt_shift_angle, -90.0..=90.0).suffix("°"),
                        );
                    });

                    ui.horizontal(|ui| {
                        ui.label("Center:");
                        ui.add(egui::Slider::new(&mut dof.tilt_shift_center, -1.0..=1.0));
                    });

                    ui.horizontal(|ui| {
                        ui.label("Blur Amount:");
                        ui.add(egui::Slider::new(
                            &mut dof.tilt_shift_blur_amount,
                            0.1..=3.0,
                        ));
                    });

                    ui.checkbox(&mut dof.visualize_tilt_shift, "Visualize Focus Band");
                });

                ui.separator();
                ui.label("Presets:");
                ui.horizontal_wrapped(|ui| {
                    if ui.button("Portrait").clicked() {
                        *dof = DepthOfField::portrait();
                    }
                    if ui.button("Cinematic").clicked() {
                        *dof = DepthOfField::cinematic();
                    }
                    if ui.button("Macro").clicked() {
                        *dof = DepthOfField::macro_shot();
                    }
                    if ui.button("Landscape").clicked() {
                        *dof = DepthOfField::landscape();
                    }
                    if ui.button("Tilt Shift").clicked() {
                        *dof = DepthOfField::tilt_shift();
                    }
                });
            });
        });
}