|
| 1 | +mod ao_baker; |
1 | 2 | mod building_imports;
|
| 3 | +mod gltf; |
| 4 | +pub mod ui; |
2 | 5 |
|
| 6 | +use std::num::NonZero; |
| 7 | + |
| 8 | +use ao_baker::AoBaker; |
| 9 | +use gltf::GltfImporter; |
| 10 | +use godot::builtin::{Dictionary, VariantType}; |
3 | 11 | use godot::classes::notify::NodeNotification;
|
4 |
| -use godot::classes::{EditorPlugin, IEditorPlugin}; |
5 |
| -use godot::obj::{Base, Gd, WithBaseField}; |
| 12 | +use godot::classes::{EditorPlugin, GltfDocument, IEditorPlugin, ProjectSettings}; |
| 13 | +use godot::global::PropertyHint; |
| 14 | +use godot::obj::{Base, Gd, NewGd, OnReady, WithBaseField}; |
6 | 15 | use godot::register::{godot_api, GodotClass};
|
7 | 16 |
|
8 | 17 | use building_imports::SetupBuildingImports;
|
9 | 18 |
|
10 | 19 | use crate::engine_callable;
|
| 20 | +use crate::util::variant_type_default_value; |
11 | 21 |
|
12 | 22 | #[derive(GodotClass)]
|
13 | 23 | #[class(tool, base=EditorPlugin)]
|
14 | 24 | struct EditorExtension {
|
15 | 25 | setup_building_imports: Gd<SetupBuildingImports>,
|
| 26 | + gltf_importer: Gd<GltfImporter>, |
| 27 | + ao_baker: OnReady<Gd<AoBaker>>, |
| 28 | + |
16 | 29 | base: Base<EditorPlugin>,
|
17 | 30 | }
|
18 | 31 |
|
| 32 | +const fn new_non_zero(value: u32) -> NonZero<u32> { |
| 33 | + NonZero::new(value).unwrap() |
| 34 | +} |
| 35 | + |
| 36 | +#[godot_api] |
| 37 | +impl EditorExtension { |
| 38 | + fn define_project_settings( |
| 39 | + settings: &[(&'static str, VariantType, PropertyHint, &'static str)], |
| 40 | + project_settings: &mut Gd<ProjectSettings>, |
| 41 | + ) { |
| 42 | + for (name, ty, hint, hint_str) in settings { |
| 43 | + Self::define_project_settings_property(name, *ty, *hint, hint_str, project_settings); |
| 44 | + } |
| 45 | + } |
| 46 | + |
| 47 | + fn define_project_settings_property( |
| 48 | + name: &'static str, |
| 49 | + ty: VariantType, |
| 50 | + hint: PropertyHint, |
| 51 | + hint_str: &'static str, |
| 52 | + project_settings: &mut Gd<ProjectSettings>, |
| 53 | + ) { |
| 54 | + let default_value = variant_type_default_value(ty); |
| 55 | + |
| 56 | + if !project_settings.has_setting(name) { |
| 57 | + project_settings.set_setting(name, &default_value); |
| 58 | + } |
| 59 | + |
| 60 | + project_settings.set_initial_value(name, &default_value); |
| 61 | + |
| 62 | + let mut property = Dictionary::new(); |
| 63 | + |
| 64 | + property.set("name", name); |
| 65 | + property.set("type", ty); |
| 66 | + property.set("hint", hint); |
| 67 | + property.set("hint_string", hint_str); |
| 68 | + |
| 69 | + project_settings.add_property_info(&property); |
| 70 | + } |
| 71 | +} |
| 72 | + |
19 | 73 | #[godot_api]
|
20 | 74 | impl IEditorPlugin for EditorExtension {
|
21 | 75 | fn init(base: Base<EditorPlugin>) -> Self {
|
22 | 76 | Self {
|
23 | 77 | setup_building_imports: SetupBuildingImports::new(base.to_gd().get_editor_interface()),
|
| 78 | + gltf_importer: GltfImporter::new_gd(), |
| 79 | + ao_baker: OnReady::manual(), |
24 | 80 | base,
|
25 | 81 | }
|
26 | 82 | }
|
27 | 83 |
|
28 | 84 | fn enter_tree(&mut self) {
|
29 | 85 | let building_imports = self.setup_building_imports.clone();
|
30 | 86 |
|
| 87 | + Self::define_project_settings(&AoBaker::SETTINGS, &mut ProjectSettings::singleton()); |
| 88 | + |
31 | 89 | self.base_mut().add_tool_menu_item(
|
32 | 90 | "Setup Building Imports...",
|
33 | 91 | &engine_callable!(&building_imports, SetupBuildingImports::start),
|
34 | 92 | );
|
| 93 | + |
| 94 | + let ao_baker = { |
| 95 | + let mut base = self.base_mut(); |
| 96 | + |
| 97 | + AoBaker::new( |
| 98 | + base.get_editor_interface() |
| 99 | + .expect("editor interface should be available after entering the tree"), |
| 100 | + base.get_tree() |
| 101 | + .expect("SceneTree should be available after entering the tree"), |
| 102 | + ) |
| 103 | + }; |
| 104 | + |
| 105 | + self.ao_baker.init(ao_baker); |
| 106 | + |
| 107 | + let callable = &engine_callable!(&self.ao_baker, AoBaker::bake); |
| 108 | + |
| 109 | + self.base_mut() |
| 110 | + .add_tool_menu_item("Bake Ambient Occlusion...", callable); |
| 111 | + |
| 112 | + GltfDocument::register_gltf_document_extension(&self.gltf_importer); |
35 | 113 | }
|
36 | 114 |
|
37 | 115 | fn on_notification(&mut self, what: NodeNotification) {
|
38 | 116 | if what == NodeNotification::PREDELETE {
|
39 | 117 | self.setup_building_imports.clone().free();
|
40 | 118 | }
|
41 | 119 | }
|
| 120 | + |
| 121 | + fn exit_tree(&mut self) { |
| 122 | + GltfDocument::unregister_gltf_document_extension(&self.gltf_importer); |
| 123 | + } |
42 | 124 | }
|
0 commit comments