Skip to content

Commit 7bff0b5

Browse files
committed
add an ability to copy decal settings and use them as defaults
1 parent a2ed816 commit 7bff0b5

11 files changed

Lines changed: 204 additions & 43 deletions

File tree

README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@
1212

1313
## Features
1414

15-
### Works with both mesh instances and CSG geometry
15+
- Works with both mesh instances and CSG geometry
1616

17-
### Auto detection of the collider thickness
17+
- Auto detection of the collider thickness
1818

19-
![auto thickness detection](readme_images/Godot_v4.3-stable_win64_dyrHiUnnqW.png)
19+
![auto thickness detection](readme_images/Godot_v4.3-stable_win64_dyrHiUnnqW.png)
2020

21-
### List/Grid view
21+
- List/Grid view
2222

23-
![list view](readme_images/Godot_v4.3-stable_win64_YetH25lbe2.png)
23+
![list view](readme_images/Godot_v4.3-stable_win64_YetH25lbe2.png)
2424

25-
![grid view](readme_images/Godot_v4.3-stable_win64_WdI7m5o6pS.png)
25+
![grid view](readme_images/Godot_v4.3-stable_win64_WdI7m5o6pS.png)
26+
27+
- Easily copy decal properties to use them as the defaults when placing decals
2628

2729
## Keybinds (when in decal placement mode)
2830

addons/splasher/decal_props.gd

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
extends Resource
2+
3+
@export var size: Vector3
4+
5+
@export var param_emission_energy: float
6+
@export var param_modulate: Color
7+
@export var param_albedo_mix: float
8+
@export var param_normal_fade: float
9+
10+
@export var vertical_fade_upper_fade: float
11+
@export var vertical_fade_lower_fade: float
12+
13+
@export var distance_fade_enabled: bool
14+
@export var distance_fade_begin: float
15+
@export var distance_fade_length: float
16+
17+
@export var cull_mask: int
18+
19+
func apply_to(decal: Decal) -> void:
20+
decal.emission_energy = param_emission_energy
21+
decal.modulate = param_modulate
22+
decal.albedo_mix = param_albedo_mix
23+
decal.normal_fade = param_normal_fade
24+
25+
decal.upper_fade = vertical_fade_upper_fade
26+
decal.lower_fade = vertical_fade_lower_fade
27+
28+
decal.distance_fade_enabled = distance_fade_enabled
29+
decal.distance_fade_begin = distance_fade_begin
30+
decal.distance_fade_length = distance_fade_length
31+
32+
decal.cull_mask = cull_mask
33+
34+
static func make_from(decal: Decal):
35+
var props_res := new()
36+
37+
props_res.param_emission_energy = decal.emission_energy
38+
props_res.param_modulate = decal.modulate
39+
props_res.param_albedo_mix = decal.albedo_mix
40+
props_res.param_normal_fade = decal.normal_fade
41+
42+
props_res.vertical_fade_upper_fade = decal.upper_fade
43+
props_res.vertical_fade_lower_fade = decal.lower_fade
44+
45+
props_res.distance_fade_enabled = decal.distance_fade_enabled
46+
props_res.distance_fade_begin = decal.distance_fade_begin
47+
props_res.distance_fade_length = decal.distance_fade_length
48+
49+
props_res.cull_mask = decal.cull_mask
50+
51+
return props_res

addons/splasher/editor_manager.gd

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
extends Node
33

44
const ObservableList := preload("res://addons/splasher/ui/observable_list.gd")
5+
const DecalPropsResource := preload("res://addons/splasher/decal_props.gd")
56

67
class StoredSettings:
78
var storage: Dictionary = {}
@@ -22,7 +23,7 @@ class StoredSettings:
2223
func emit_changed(prop_name: String, new_value: Variant, old_value: Variant) -> void:
2324
changed.emit(prop_name, new_value, old_value)
2425

25-
class DecalSettings extends StoredSettings:
26+
class DecalPlacementSettings extends StoredSettings:
2627
# Automatically determine decal's thickness based on the size of a collider
2728
var p_auto_thickness: bool:
2829
get:
@@ -69,8 +70,9 @@ var scale_step = 0.5
6970
var rotation_step = 0.05
7071
var snap_step = 0.5
7172

72-
var decal_settings := DecalSettings.new()
73+
var decal_placement_settings := DecalPlacementSettings.new()
7374
var plugin_settings := PluginSettings.new()
75+
var decal_defaults: DecalPropsResource = null
7476

7577
# TODO: move to decal settings
7678
var upper_fade = 0.3

addons/splasher/editor_viewport.gd

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const Globals := preload("res://addons/splasher/globals.gd")
88

99
@export_flags_3d_physics var temporary_layer: int
1010

11-
var decal: Decal
11+
var decal_ref: Decal
1212
var decal_dupe: Decal
1313
var last_collider
1414

@@ -20,24 +20,33 @@ var editor_manager
2020

2121
func _ready():
2222
if not Engine.is_editor_hint():
23+
queue_free()
2324
return
25+
2426
editor_manager = Globals.get_editor_manager()
25-
decal = Decal.new()
27+
decal_ref = Decal.new()
28+
29+
editor_manager.select_decal.connect(on_decal_selected)
2630

27-
editor_manager.select_decal.connect(_decal_selected)
31+
func on_decal_selected(path: String):
32+
decal_ref.texture_albedo = ResourceLoader.load(path)
2833

29-
func _decal_selected(path: String):
30-
decal.texture_albedo = ResourceLoader.load(path)
34+
func create_decal_dupe():
35+
if decal_dupe:
36+
return
3137

32-
func _create_decal():
33-
if decal_dupe: return
3438
var root := EditorInterface.get_edited_scene_root()
35-
decal_dupe = decal.duplicate()
39+
decal_dupe = decal_ref.duplicate()
3640
decal_dupe.process_mode = Node.PROCESS_MODE_DISABLED
37-
var upper_fade = editor_manager.upper_fade
38-
var lower_fade = editor_manager.lower_fade
39-
decal_dupe.upper_fade = upper_fade
40-
decal_dupe.lower_fade = lower_fade
41+
42+
if editor_manager.decal_defaults:
43+
editor_manager.decal_defaults.apply_to(decal_dupe)
44+
else:
45+
var upper_fade = editor_manager.upper_fade
46+
var lower_fade = editor_manager.lower_fade
47+
decal_dupe.upper_fade = upper_fade
48+
decal_dupe.lower_fade = lower_fade
49+
4150
var pivot := root
4251
var editor_selection := EditorInterface.get_selection()
4352
if editor_selection.get_selected_nodes().size() == 1:
@@ -135,9 +144,9 @@ func on_ray_hit(hit) -> void:
135144
Globals.get_debug_draw_3d().draw_line(hit_position, hit_position + hit_normal, Color.RED)
136145

137146
if not decal_dupe:
138-
_create_decal()
147+
create_decal_dupe()
139148

140-
if editor_manager.decal_settings.p_grid_snap:
149+
if editor_manager.decal_placement_settings.p_grid_snap:
141150
var snap_to := Vector3(
142151
editor_manager.snap_step,
143152
editor_manager.snap_step,
@@ -148,7 +157,7 @@ func on_ray_hit(hit) -> void:
148157
decal_dupe.global_position = hit_position
149158
decal_dupe.size = add_scale
150159

151-
if editor_manager.decal_settings.p_auto_thickness:
160+
if editor_manager.decal_placement_settings.p_auto_thickness:
152161
var hit_collider = hit.collider
153162
var hit_collider_layer = hit_collider.collision_layer
154163
var hit_collider_mask = hit_collider.collision_mask

addons/splasher/icons/copy.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[remap]
2+
3+
importer="texture"
4+
type="CompressedTexture2D"
5+
uid="uid://cf8x67lx8ukns"
6+
path="res://.godot/imported/copy.svg-e0fdfecfab9da15a225603325d35d437.ctex"
7+
metadata={
8+
"has_editor_variant": true,
9+
"vram_texture": false
10+
}
11+
12+
[deps]
13+
14+
source_file="res://addons/splasher/icons/copy.svg"
15+
dest_files=["res://.godot/imported/copy.svg-e0fdfecfab9da15a225603325d35d437.ctex"]
16+
17+
[params]
18+
19+
compress/mode=0
20+
compress/high_quality=false
21+
compress/lossy_quality=0.7
22+
compress/hdr_compression=1
23+
compress/normal_map=0
24+
compress/channel_pack=0
25+
mipmaps/generate=false
26+
mipmaps/limit=-1
27+
roughness/mode=0
28+
roughness/src_normal=""
29+
process/fix_alpha_border=true
30+
process/premult_alpha=false
31+
process/normal_map_invert_y=false
32+
process/hdr_as_srgb=false
33+
process/hdr_clamp_exposure=false
34+
process/size_limit=0
35+
detect_3d/compress_to=1
36+
svg/scale=1.0
37+
editor/scale_with_editor_scale=true
38+
editor/convert_colors_with_editor_theme=true

addons/splasher/splasher.gd

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ func _exit_tree():
3535
remove_autoload_singleton(Globals.EDITOR_VIEWPORT_NAME)
3636
remove_autoload_singleton(Globals.EDITOR_MANAGER_NAME)
3737

38+
func _handles(object: Object) -> bool:
39+
return object is Decal
40+
41+
func _make_visible(visible: bool) -> void:
42+
viewport_panel.enable(visible)
43+
3844
func _save_external_data() -> void:
3945
if not save_timer.is_stopped():
4046
save_timer.stop()
@@ -48,7 +54,7 @@ func watch_settings() -> void:
4854
manager.plugin_settings.changed.connect(func (_p, _n, _o):
4955
queue_settings_save()
5056
)
51-
manager.decal_settings.changed.connect(func (_p, _n, _o):
57+
manager.decal_placement_settings.changed.connect(func (_p, _n, _o):
5258
queue_settings_save()
5359
)
5460

@@ -64,7 +70,7 @@ func queue_settings_save() -> void:
6470
func save_settings() -> void:
6571
var manager = Globals.get_editor_manager()
6672
var res := StorageResource.new()
67-
res.decal_settings = manager.decal_settings.storage
73+
res.decal_placement_settings = manager.decal_placement_settings.storage
6874
res.plugin_settings = manager.plugin_settings.storage
6975

7076
for decal in manager.decal_list.items:
@@ -82,7 +88,7 @@ func load_settings() -> void:
8288
return
8389

8490
var manager = Globals.get_editor_manager()
85-
manager.decal_settings.set_storage(res.decal_settings)
91+
manager.decal_placement_settings.set_storage(res.decal_placement_settings)
8692
manager.plugin_settings.set_storage(res.plugin_settings)
8793

8894
for stored_decal: StoredDecalResource in res.decal_registry:

addons/splasher/storage.gd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ enum StorageVersion {
55
}
66

77
@export var decal_registry: Array = []
8-
@export var decal_settings: Dictionary = {}
8+
@export var decal_placement_settings: Dictionary = {}
99
@export var plugin_settings: Dictionary = {}
1010
@export var version: StorageVersion = StorageVersion.Version_Alpha

addons/splasher/ui_viewport_panel.gd

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,30 @@
22
extends Control
33

44
const Globals := preload("res://addons/splasher/globals.gd")
5+
const DecalPropsResource := preload("res://addons/splasher/decal_props.gd")
56

67
@onready var toolbar: Control = $Toolbar
78
@onready var info_label: Label = $Toolbar/HBoxContainer/InfoLabel
89

910
@onready var auto_thickness_btn: Button = $Toolbar/HBoxContainer/AutoThickness
1011
@onready var grid_snap_btn: Button = $Toolbar/HBoxContainer/GridSnap
12+
@onready var copy_decal_props: Button = $Toolbar/HBoxContainer/CopyDecalProps
1113

1214
func _ready() -> void:
13-
# TODO: this
14-
Globals.get_editor_manager().viewport_panel = self
15+
var manager = Globals.get_editor_manager()
16+
manager.viewport_panel = self
1517

1618
enable(false)
1719

1820
# Initialize based on settings
1921

20-
var settings = Globals.get_editor_manager().decal_settings
22+
var settings = manager.decal_placement_settings
2123
auto_thickness_btn.set_pressed_no_signal(settings.p_auto_thickness)
2224
grid_snap_btn.set_pressed_no_signal(settings.p_grid_snap)
2325

2426
# Connect change signal
2527

26-
Globals.get_editor_manager().changed.connect(_editor_manager_changed)
28+
manager.changed.connect(_editor_manager_changed)
2729

2830
func _editor_manager_changed() -> void:
2931
var manager = Globals.get_editor_manager()
@@ -35,13 +37,30 @@ func enable(value: bool) -> void:
3537
if value:
3638
info_label.text = get_info_label_text()
3739

40+
var manager = Globals.get_editor_manager()
41+
42+
var editor_selection := EditorInterface.get_selection()
43+
copy_decal_props.visible = editor_selection.get_selected_nodes().size() == 1 and editor_selection.get_selected_nodes()[0] is Decal
44+
45+
auto_thickness_btn.visible = manager.enabled
46+
grid_snap_btn.visible = manager.enabled
47+
3848
func get_info_label_text() -> String:
39-
return "decal placement"
49+
return "Decal"
4050

4151
# Events
4252

4353
func _on_auto_thickness_toggled(toggled_on: bool) -> void:
44-
Globals.get_editor_manager().decal_settings.p_auto_thickness = toggled_on
54+
Globals.get_editor_manager().decal_placement_settings.p_auto_thickness = toggled_on
4555

4656
func _on_grid_snap_toggled(toggled_on: bool) -> void:
47-
Globals.get_editor_manager().decal_settings.p_grid_snap = toggled_on
57+
Globals.get_editor_manager().decal_placement_settings.p_grid_snap = toggled_on
58+
59+
func _on_copy_decal_props_pressed() -> void:
60+
var editor_selection := EditorInterface.get_selection()
61+
62+
if editor_selection.get_selected_nodes().size() == 1 and editor_selection.get_selected_nodes()[0] is Decal:
63+
var decal := editor_selection.get_selected_nodes()[0] as Decal
64+
var defaults_res := DecalPropsResource.make_from(decal) as DecalPropsResource
65+
var manager = Globals.get_editor_manager()
66+
manager.decal_defaults = defaults_res

0 commit comments

Comments
 (0)