diff options
Diffstat (limited to 'addons/voxel-core/controls/voxel_viewer/voxel_viewer.gd')
-rw-r--r-- | addons/voxel-core/controls/voxel_viewer/voxel_viewer.gd | 824 |
1 files changed, 824 insertions, 0 deletions
diff --git a/addons/voxel-core/controls/voxel_viewer/voxel_viewer.gd b/addons/voxel-core/controls/voxel_viewer/voxel_viewer.gd new file mode 100644 index 0000000..1c3f881 --- /dev/null +++ b/addons/voxel-core/controls/voxel_viewer/voxel_viewer.gd @@ -0,0 +1,824 @@ +tool +extends Control +# 2D / 3D preview of a voxel, that allows for selection and editing of faces. + + + +## Signals +# Emitted when a voxel face has been selected +signal selected_face(face) +# Emitted when a voxel face has been unselected +signal unselected_face(face) + + + +## Enums +# View modes available +enum ViewModes { VIEW_2D, VIEW_3D } + + + +## Constants +# Default environment used +var DefaultEnv := preload("res://addons/voxel-core/controls/voxel_viewer/voxel_viewer_env.tres") + + + +## Exported Variables +# Number of uv positions that can be selected at any one time +export(int, 0, 6) var selection_max := 0 setget set_selection_max + +# Flag indicating whether edits are allowed +export var allow_edit := false setget set_allow_edit + +# Current view being shown +export(ViewModes) var view_mode := ViewModes.VIEW_3D setget set_view_mode + +# View sensitivity for the 3D view +export(int, 0, 100) var camera_sensitivity := 8 + +# ID of voxel to represented +export var voxel_id : int setget set_voxel_id + +# VoxelSet beings used +export(Resource) var voxel_set = null setget set_voxel_set + +# Environment used in 3D view +export(Environment) var environment := DefaultEnv setget set_environment + + + +## Public Variables +# UndoRedo used to commit operations +var undo_redo : UndoRedo + + + +## Private Variables +# Selected voxel ids +var _selections := [] + +# VoxelTool used for Mesh generation +var _voxel_tool := VoxelTool.new() + +# Internal flag used to know whether user is dragging in 3D view +var _is_dragging := false + +# Internal flag used to know the last face the user hovered +var _last_hovered_face := Vector3.ZERO + +# Internal value used to revert to old versions of voxel data +var _unedited_voxel := {} + +# Internal flag used to indicate the operation being committed +var _editing_action := -1 + +# Internal flag used to indicate the face being edited +var _editing_face := Vector3.ZERO + +# Internal flag used to indicate whether multiple faces are being edited +var _editing_multiple := false + + + +## OnReady Variables +onready var View2D := get_node("View2D") + +onready var View3D := get_node("View3D") + +onready var ViewPort := get_node("View3D/Viewport") + +onready var CameraPivot := get_node("View3D/Viewport/CameraPivot") + +onready var CameraRef := get_node("View3D/Viewport/CameraPivot/Camera") + +onready var VoxelPreview := get_node("View3D/Viewport/VoxelPreview") + +onready var Select := get_node("View3D/Viewport/Select") + +onready var ViewModeRef := get_node("ToolBar/ViewMode") + +onready var ViewerHint := get_node("ToolBar/Hint") + +onready var ContextMenu := get_node("ContextMenu") + +onready var ColorMenu := get_node("ColorMenu") + +onready var VoxelColor := get_node("ColorMenu/VBoxContainer/VoxelColor") + +onready var TextureMenu := get_node("TextureMenu") + +onready var VoxelTexture := get_node("TextureMenu/VBoxContainer/ScrollContainer/VoxelTexture") + +onready var MaterialMenu := get_node("MaterialMenu") + +onready var MaterialRef := get_node("MaterialMenu/VBoxContainer/VBoxContainer/HBoxContainer6/Material") + +onready var Metallic := get_node("MaterialMenu/VBoxContainer/VBoxContainer/HBoxContainer/Metallic") + +onready var Specular := get_node("MaterialMenu/VBoxContainer/VBoxContainer/HBoxContainer2/Specular") + +onready var Roughness := get_node("MaterialMenu/VBoxContainer/VBoxContainer/HBoxContainer3/Roughness") + +onready var Energy := get_node("MaterialMenu/VBoxContainer/VBoxContainer/HBoxContainer4/Energy") + +onready var EnergyColor := get_node("MaterialMenu/VBoxContainer/VBoxContainer/HBoxContainer5/EnergyColor") + +onready var EnvironmentMenu := get_node("EnvironmentMenu") + + + +## Built-In Virtual Methods +func _ready(): + set_view_mode(view_mode) + set_voxel_set(voxel_set) + load_environment() + + if not is_instance_valid(undo_redo): + undo_redo = UndoRedo.new() + + + +## Public Methods +# Saves the used environment path +func save_environment() -> void: + if environment == DefaultEnv: + var dir := Directory.new() + if dir.file_exists("res://addons/voxel-core/controls/voxel_viewer/config.var"): + dir.remove("res://addons/voxel-core/controls/voxel_viewer/config.var") + elif is_instance_valid(environment): + var file := File.new() + var opened = file.open( + "res://addons/voxel-core/controls/voxel_viewer/config.var", + File.WRITE) + if opened == OK: + file.store_string(environment.resource_path) + if file.is_open(): + file.close() + + +# Loads and sets the environment file +func load_environment() -> void: + var loaded := false + var file := File.new() + var opened = file.open( + "res://addons/voxel-core/controls/voxel_viewer/config.var", + File.READ) + if opened == OK: + var environment_path = file.get_as_text() + if file.file_exists(environment_path): + var _environment := load(environment_path) + if _environment is Environment: + set_environment(_environment) + loaded = true + + if not loaded: + set_environment(DefaultEnv) + + if file.is_open(): + file.close() + + +# Resets the environment to default +func reset_environment() -> void: + set_environment(DefaultEnv) + save_environment() + + +func set_selection_max(value : int, update := true) -> void: + selection_max = clamp(value, 0, 6) + unselect_shrink() + if update: + self.update() + + +# Sets allow_edit +func set_allow_edit(value : bool) -> void: + allow_edit = value + + +# Sets view_mode +func set_view_mode(value : int) -> void: + _last_hovered_face = Vector3.ZERO + view_mode = int(clamp(value, 0, ViewModes.size())) + + if is_instance_valid(ViewModeRef): + ViewModeRef.selected = view_mode + if is_instance_valid(View2D): + View2D.visible = view_mode == ViewModes.VIEW_2D + if is_instance_valid(View3D): + View3D.visible = view_mode == ViewModes.VIEW_3D + + +# Sets voxel_id, calls on update_view by defalut +func set_voxel_id(value : int, update := true) -> void: + voxel_id = value + if update: + update_view() + + +# Returns true if face is selected +func has_selected(face : Vector3) -> bool: + return _selections.has(face) + + +# Returns face selected at given index +func get_selected(index : int) -> Vector3: + return _selections[index] + + +# Returns array of selected faces +func get_selections() -> Array: + return _selections.duplicate() + + +# Returns number of faces selected +func get_selected_size() -> int: + return _selections.size() + + +# Sets voxel_set, and calls on update by default +func set_voxel_set(value : Resource, update := true) -> void: + if not (typeof(value) == TYPE_NIL or value is VoxelSet): + printerr("Invalid Resource given expected VoxelSet") + return + + if is_instance_valid(voxel_set): + if voxel_set.is_connected("requested_refresh", self, "update_view"): + voxel_set.disconnect("requested_refresh", self, "update_view") + + voxel_set = value + if is_instance_valid(voxel_set): + if not voxel_set.is_connected("requested_refresh", self, "update_view"): + voxel_set.connect("requested_refresh", self, "update_view") + if is_instance_valid(VoxelTexture): + VoxelTexture.voxel_set = voxel_set + + if update: + update_view() + + +func set_environment(value : Environment) -> void: + environment = value + if is_instance_valid(ViewPort): + ViewPort.transparent_bg = environment == DefaultEnv + ViewPort.world.environment = environment + + +# Return normal associated with given name +func string_to_face(string : String) -> Vector3: + string = string.to_upper() + var normal := Vector3.ZERO + match string: + "RIGHT": + normal = Vector3.RIGHT + "LEFT": + normal = Vector3.LEFT + "TOP": + normal = Vector3.UP + "BOTTOM": + normal = Vector3.DOWN + "FRONT": + normal = Vector3.FORWARD + "BACK": + normal = Vector3.BACK + return normal + +# Return name associated with given face +func face_to_string(face : Vector3) -> String: + var string := "" + match face: + Vector3.RIGHT: + string = "RIGHT" + Vector3.LEFT: + string = "LEFT" + Vector3.UP: + string = "TOP" + Vector3.DOWN: + string = "BOTTOM" + Vector3.FORWARD: + string = "FRONT" + Vector3.BACK: + string = "BACK" + return string + + +# Quick setup of voxel_set, voxel_id; calls on update_view and update_hint +func setup(voxel_set : VoxelSet, voxel_set_id : int) -> void: + set_voxel_set(voxel_set, false) + set_voxel_id(voxel_set_id, false) + update_view() + update_hint() + + +# Returns the voxel data of current voxel, returns a empty Dictionary if not set +func get_viewing_voxel() -> Dictionary: + return voxel_set.get_voxel(voxel_id) if is_instance_valid(voxel_set) else {} + + +# Returns the VoxelButton associated with face normal +func get_voxle_button(face_normal : Vector3): + return View2D.find_node(face_to_string(face_normal).capitalize()) + + +# Selects given face, and emits selected_face +func select(face : Vector3, emit := true) -> void: + if selection_max != 0: + unselect_shrink(selection_max - 1) + _selections.append(face) + var voxel_button = get_voxle_button(face) + if is_instance_valid(voxel_button): + voxel_button.pressed = true + if emit: + emit_signal("selected_face", face) + + +# Unselects given face, and emits unselected_face +func unselect(face : Vector3, emit := true) -> void: + if _selections.has(face): + _selections.erase(face) + var voxel_button = get_voxle_button(face) + if is_instance_valid(voxel_button): + voxel_button.pressed = false + if emit: + emit_signal("unselected_face", face) + + +# Unselects all the faces +func unselect_all() -> void: + while not _selections.empty(): + unselect(_selections.back()) + + +# Unselects all faces until given size is met +func unselect_shrink(size := selection_max, emit := true) -> void: + if size >= 0: + while _selections.size() > size: + unselect(_selections.back(), emit) + + +# Updates the hint message +func update_hint() -> void: + if is_instance_valid(ViewerHint): + ViewerHint.text = "" + + if not _selections.empty(): + for i in range(len(_selections)): + if i > 0: + ViewerHint.text += ", " + ViewerHint.text += face_to_string(_selections[i]).to_upper() + + if _last_hovered_face != Vector3.ZERO: + if not ViewerHint.text.empty(): + ViewerHint.text += " | " + ViewerHint.text += face_to_string(_last_hovered_face).to_upper() + + +# Updates the view +func update_view() -> void: + if not is_instance_valid(voxel_set): + return + + if is_instance_valid(View2D): + for voxel_button in View2D.get_children(): + voxel_button.setup(voxel_set, voxel_id, string_to_face(voxel_button.name)) + voxel_button.hint_tooltip = voxel_button.name + + if is_instance_valid(VoxelPreview): + _voxel_tool.begin(voxel_set, true) + for face in Voxel.Faces: + _voxel_tool.add_face( + get_viewing_voxel(), + face, -Vector3.ONE / 2) + VoxelPreview.mesh = _voxel_tool.commit() + + _voxel_tool.begin(voxel_set, true) + for selection in _selections: + _voxel_tool.add_face( + Voxel.colored(Color(0, 0, 0, 0.75)), + selection, -Vector3.ONE / 2) + Select.mesh = _voxel_tool.commit() + + +# Shows the context menu and options +func show_context_menu(global_position : Vector2, face := _last_hovered_face) -> void: + if not is_instance_valid(ContextMenu): + return + ContextMenu.clear() + if _last_hovered_face == Vector3.ZERO: + ContextMenu.add_item("Change environment", 14) + if environment != DefaultEnv: + ContextMenu.add_item("Reset environment", 15) + elif allow_edit: + _editing_face = face + _editing_multiple = false + var selected_hovered := _selections.has(_editing_face) + if is_instance_valid(voxel_set): + var voxel := get_viewing_voxel() + + if _selections.size() < 6: + ContextMenu.add_item("Select all", 13) + if _selections.size() > 0: + ContextMenu.add_item("Unselect all", 11) + + if _selections.size() == 0 or not selected_hovered: + ContextMenu.add_separator() + ContextMenu.add_item("Color side", 0) + if Voxel.has_face_color(voxel, _editing_face): + ContextMenu.add_item("Remove side color", 1) + + if voxel_set.uv_ready(): + ContextMenu.add_item("Texture side", 2) + if Voxel.has_face_uv(voxel, _editing_face): + ContextMenu.add_item("Remove side uv", 3) + + if selected_hovered and _selections.size() >= 1: + ContextMenu.add_separator() + ContextMenu.add_item("Color side(s)", 7) + if Voxel.has_face_color(voxel, _editing_face): + ContextMenu.add_item("Remove side color(s)", 8) + + if voxel_set.uv_ready(): + ContextMenu.add_item("Texture side(s)", 9) + if Voxel.has_face_uv(voxel, _editing_face): + ContextMenu.add_item("Remove side uv(s)", 10) + + ContextMenu.add_separator() + ContextMenu.add_item("Color voxel", 4) + + ContextMenu.add_item("Modify material", 12) + + if voxel_set.uv_ready(): + ContextMenu.add_item("Texture voxel", 5) + if Voxel.has_uv(voxel): + ContextMenu.add_item("Remove voxel uv", 6) + ContextMenu.set_as_minsize() + + ContextMenu.popup(Rect2( + global_position, + ContextMenu.rect_size)) + + +# Shows the color menu centered with given color +func show_color_menu(color : Color) -> void: + if is_instance_valid(ColorMenu): + VoxelColor.color = color + ColorMenu.popup_centered() + + +# Closes the color menu +func hide_color_menu() -> void: + if is_instance_valid(ColorMenu): + ColorMenu.hide() + update_view() + + +# Shows the texture menu centered with given color +func show_texture_menu(uv : Vector2) -> void: + if is_instance_valid(TextureMenu): + VoxelTexture.unselect_all() + VoxelTexture.select(uv) + TextureMenu.popup_centered() + + +# Closes the texture menu +func hide_texture_menu() -> void: + if is_instance_valid(TextureMenu): + TextureMenu.hide() + update_view() + + +# Shows the material menu with given voxel data +func show_material_menu(voxel := get_viewing_voxel()) -> void: + if is_instance_valid(MaterialMenu): + MaterialRef.value = Voxel.get_material(voxel) + MaterialRef.max_value = voxel_set.materials.size() - 1 + Metallic.value = Voxel.get_metallic(voxel) + Specular.value = Voxel.get_specular(voxel) + Roughness.value = Voxel.get_roughness(voxel) + Energy.value = Voxel.get_energy(voxel) + EnergyColor.color = Voxel.get_energy_color(voxel) + MaterialMenu.popup_centered() + + +# Closes the material menu +func hide_material_menu() -> void: + if is_instance_valid(MaterialMenu): + MaterialMenu.hide() + update_view() + + +func show_environment_change_menu() -> void: + EnvironmentMenu.popup_centered() + +func hide_environment_change_menu() -> void: + EnvironmentMenu.hide() + + + +## Private Methods +func _set_last_hovered_face(face : Vector3): + _last_hovered_face = face + + +func _voxel_backup() -> void: + _unedited_voxel = get_viewing_voxel().duplicate(true) + + +func _voxel_restore() -> void: + voxel_set.set_voxel(voxel_id, _unedited_voxel) + + +func _on_Face_gui_input(event : InputEvent, normal : Vector3) -> void: + _last_hovered_face = normal + if event is InputEventMouseButton and event.pressed: + if event.button_index == BUTTON_LEFT: + if selection_max > 0: + if _selections.has(normal): + unselect(normal) + else: + select(normal) + accept_event() + else: + get_voxle_button(normal).pressed = false + elif event.button_index == BUTTON_RIGHT: + if allow_edit: + show_context_menu(event.global_position, _last_hovered_face) + update_hint() + + +func _on_View3D_gui_input(event : InputEvent) -> void: + if event is InputEventMouse: + var from = CameraRef.project_ray_origin(event.position) + var to = from + CameraRef.project_ray_normal(event.position) * 1000 + var hit = CameraRef.get_world().direct_space_state.intersect_ray(from, to) + if hit.empty(): + _last_hovered_face = Vector3.ZERO + else: + hit["normal"] = hit["normal"].round() + _last_hovered_face = hit["normal"] + + if event is InputEventMouseMotion: + if _is_dragging: + var motion = event.relative.normalized() + CameraPivot.rotation_degrees.x += -motion.y * camera_sensitivity + CameraPivot.rotation_degrees.y += -motion.x * camera_sensitivity + elif event is InputEventMouseButton: + if event.button_index == BUTTON_LEFT: + if event.doubleclick: + if not hit.empty() and selection_max > 0: + if _selections.has(hit["normal"]): + unselect(hit["normal"]) + else: + select(hit["normal"]) + elif event.is_pressed(): + _is_dragging = true + else: + _is_dragging = false + elif event.button_index == BUTTON_RIGHT and not event.is_pressed(): + show_context_menu(event.global_position, _last_hovered_face) + + if _is_dragging: + View3D.set_default_cursor_shape(Control.CURSOR_MOVE) + elif hit: + View3D.set_default_cursor_shape(Control.CURSOR_POINTING_HAND) + else: + View3D.set_default_cursor_shape(Control.CURSOR_ARROW) + update_hint() + update_view() + + +func _on_ContextMenu_id_pressed(id : int): + _editing_action = id + _editing_multiple = false + _voxel_backup() + match id: + 0: # Color editing face + show_color_menu(Voxel.get_face_color(get_viewing_voxel(), _editing_face)) + 1: # Remove editing face color + var voxel = get_viewing_voxel() + Voxel.remove_face_color(voxel, _editing_face) + Voxel.clean(voxel) + + undo_redo.create_action("VoxelViewer : Remove voxel face color") + undo_redo.add_do_method(voxel_set, "set_voxel", voxel_id, voxel) + undo_redo.add_undo_method(voxel_set, "set_voxel", voxel_id, _unedited_voxel) + undo_redo.add_do_method(voxel_set, "request_refresh") + undo_redo.add_undo_method(voxel_set, "request_refresh") + undo_redo.commit_action() + 2: # Texture editing face + show_texture_menu(Voxel.get_face_uv(get_viewing_voxel(), _editing_face)) + 3: # Remove editing face uv + var voxel := get_viewing_voxel() + Voxel.remove_face_uv(voxel, _editing_face) + Voxel.clean(voxel) + + undo_redo.create_action("VoxelViewer : Remove voxel face uv") + undo_redo.add_do_method(voxel_set, "set_voxel", voxel_id, voxel) + undo_redo.add_undo_method(voxel_set, "set_voxel", voxel_id, _unedited_voxel) + undo_redo.add_do_method(voxel_set, "request_refresh") + undo_redo.add_undo_method(voxel_set, "request_refresh") + undo_redo.commit_action() + 7: # Color selected faces + _editing_multiple = true + show_color_menu(Voxel.get_face_color(get_viewing_voxel(), _editing_face)) + 8: # Remove selected faces color + _editing_multiple = true + var voxel = get_viewing_voxel() + for selection in _selections: + Voxel.remove_face_color(voxel, selection) + Voxel.clean(voxel) + + undo_redo.create_action("VoxelViewer : Remove voxel face(s) color") + undo_redo.add_do_method(voxel_set, "set_voxel", voxel_id, voxel) + undo_redo.add_undo_method(voxel_set, "set_voxel", voxel_id, _unedited_voxel) + undo_redo.add_do_method(voxel_set, "request_refresh") + undo_redo.add_undo_method(voxel_set, "request_refresh") + undo_redo.commit_action() + 9: # Texture selected face + _editing_multiple = true + show_texture_menu(Voxel.get_face_uv(get_viewing_voxel(), _editing_face)) + 10: # Remove selected face uv + _editing_multiple = true + var voxel := get_viewing_voxel() + for selection in _selections: + Voxel.remove_face_uv(voxel, selection) + Voxel.clean(voxel) + + undo_redo.create_action("VoxelViewer : Remove voxel face(s) uv") + undo_redo.add_do_method(voxel_set, "set_voxel", voxel_id, voxel) + undo_redo.add_undo_method(voxel_set, "set_voxel", voxel_id, _unedited_voxel) + undo_redo.add_do_method(voxel_set, "request_refresh") + undo_redo.add_undo_method(voxel_set, "request_refresh") + undo_redo.commit_action() + 4: # Set voxel color + show_color_menu(Voxel.get_color(get_viewing_voxel())) + 5: # Set voxel uv + show_texture_menu(Voxel.get_uv(get_viewing_voxel())) + 6: # Remove voxel uv + var voxel = voxel_set.get_voxel(voxel_id) + Voxel.remove_uv(voxel) + Voxel.clean(voxel) + + undo_redo.create_action("VoxelViewer : Remove voxel uv") + undo_redo.add_do_method(voxel_set, "set_voxel", voxel_id, voxel) + undo_redo.add_undo_method(voxel_set, "set_voxel", voxel_id, _unedited_voxel) + undo_redo.add_do_method(voxel_set, "request_refresh") + undo_redo.add_undo_method(voxel_set, "request_refresh") + undo_redo.commit_action() + 13: # Select all + unselect_all() + for face in Voxel.Faces: + select(face) + 11: # Unselect all + unselect_all() + 12: # Modify material + show_material_menu() + 14: + show_environment_change_menu() + 15: + reset_environment() + + +func _on_ColorPicker_color_changed(color : Color): + match _editing_action: + 0, 7: + for selection in (_selections if _editing_multiple else [_editing_face]): + Voxel.set_face_color(get_viewing_voxel(), selection, color) + 4: Voxel.set_color(get_viewing_voxel(), color) + update_view() + + +func _on_ColorMenu_Cancel_pressed(): + _voxel_restore() + + hide_color_menu() + + +func _on_ColorMenu_Confirm_pressed(): + match _editing_action: + 0, 7: + var voxel = get_viewing_voxel() + Voxel.clean(voxel) + + undo_redo.create_action("VoxelViewer : Set voxel face(s) color") + undo_redo.add_do_method(voxel_set, "set_voxel", voxel_id, voxel) + undo_redo.add_undo_method(voxel_set, "set_voxel", voxel_id, _unedited_voxel) + undo_redo.add_do_method(voxel_set, "request_refresh") + undo_redo.add_undo_method(voxel_set, "request_refresh") + undo_redo.commit_action() + 4: + var voxel = get_viewing_voxel() + Voxel.clean(voxel) + + undo_redo.create_action("VoxelViewer : Set voxel color") + undo_redo.add_do_method(voxel_set, "set_voxel", voxel_id, voxel) + undo_redo.add_undo_method(voxel_set, "set_voxel", voxel_id, _unedited_voxel) + undo_redo.add_do_method(voxel_set, "request_refresh") + undo_redo.add_undo_method(voxel_set, "request_refresh") + undo_redo.commit_action() + hide_color_menu() + + +func _on_VoxelTexture_selected_uv(uv : Vector2): + match _editing_action: + 2, 9: + for selection in (_selections if _editing_multiple else [_editing_face]): + Voxel.set_face_uv(get_viewing_voxel(), selection, uv) + 5: Voxel.set_uv(get_viewing_voxel(), uv) + update_view() + + +func _on_TextureMenu_Cancel_pressed(): + _voxel_restore() + + hide_texture_menu() + + +func _on_TextureMenu_Confirm_pressed(): + match _editing_action: + 2, 9: + var voxel = get_viewing_voxel() + Voxel.clean(voxel) + + undo_redo.create_action("VoxelViewer : Set voxel face(s) uv") + undo_redo.add_do_method(voxel_set, "set_voxel", voxel_id, voxel) + undo_redo.add_undo_method(voxel_set, "set_voxel", voxel_id, _unedited_voxel) + undo_redo.add_do_method(voxel_set, "request_refresh") + undo_redo.add_undo_method(voxel_set, "request_refresh") + undo_redo.commit_action() + 5: + var voxel = get_viewing_voxel() + Voxel.clean(voxel) + + undo_redo.create_action("VoxelViewer : Set voxel uv") + undo_redo.add_do_method(voxel_set, "set_voxel", voxel_id, voxel) + undo_redo.add_undo_method(voxel_set, "set_voxel", voxel_id, _unedited_voxel) + undo_redo.add_do_method(voxel_set, "request_refresh") + undo_redo.add_undo_method(voxel_set, "request_refresh") + undo_redo.commit_action() + hide_texture_menu() + + +func _on_Metallic_value_changed(metallic : float): + Voxel.set_metallic(get_viewing_voxel(), metallic) + update_view() + + +func _on_Specular_value_changed(specular : float): + Voxel.set_specular(get_viewing_voxel(), specular) + update_view() + + +func _on_Roughness_value_changed(roughness : float): + Voxel.set_roughness(get_viewing_voxel(), roughness) + update_view() + + +func _on_Energy_value_changed(emergy : float): + Voxel.set_energy(get_viewing_voxel(), emergy) + update_view() + + +func _on_EnergyColor_changed(color : Color): + Voxel.set_energy_color(get_viewing_voxel(), color) + update_view() + + +func _on_Material_value_changed(value : int): + Metallic.editable = value == -1 + Specular.editable = value == -1 + Roughness.editable = value == -1 + Energy.editable = value == -1 + EnergyColor.disabled = value > -1 + + Voxel.set_material(get_viewing_voxel(), value) + update_view() + + +func _on_MaterialMenu_Cancel_pressed(): + _voxel_restore() + + hide_material_menu() + + +func _on_MaterialMenu_Confirm_pressed(): + var voxel = get_viewing_voxel() + Voxel.clean(voxel) + + undo_redo.create_action("VoxelViewer : Set voxel material") + undo_redo.add_do_method(voxel_set, "set_voxel", voxel_id, voxel) + undo_redo.add_undo_method(voxel_set, "set_voxel", voxel_id, _unedited_voxel) + undo_redo.add_do_method(voxel_set, "request_refresh") + undo_redo.add_undo_method(voxel_set, "request_refresh") + undo_redo.commit_action() + + hide_material_menu() + + +func _on_EnvironmentMenu_file_selected(path): + var _environment = load(path) + if _environment is Environment: + set_environment(_environment) + property_list_changed_notify() + save_environment() |