267 lines
12 KiB
GDScript
267 lines
12 KiB
GDScript
# toolbar_menu.gd
|
|
# This file is part of: SimpleGrassTextured
|
|
# Copyright (c) 2023 IcterusGames
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
# a copy of this software and associated documentation files (the
|
|
# "Software"), to deal in the Software without restriction, including
|
|
# without limitation the rights to use, copy, modify, merge, publish,
|
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
# permit persons to whom the Software is furnished to do so, subject to
|
|
# the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be
|
|
# included in all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
@tool
|
|
extends MenuButton
|
|
|
|
enum MENU_ID {
|
|
TOOL_FOLLOW_NORMAL,
|
|
TOOL_SHAPE_AIRBRUSH,
|
|
TOOL_SHAPE_PENCIL,
|
|
TOOL_SHAPE_ERASER,
|
|
TOOL_SNAP_TO_TERRAIN,
|
|
AUTO_CENTER_POSITION,
|
|
CAST_SHADOW,
|
|
BAKE_HEIGHT_MAP,
|
|
GLOBAL_PARAMETERS,
|
|
CLEAR_ALL,
|
|
HELP_ABOUT,
|
|
RECALCULATE_AABB,
|
|
}
|
|
|
|
enum MENU_SHAPE_ID {
|
|
TOOL_SHAPE_SPHERE,
|
|
TOOL_SHAPE_CYLINDER,
|
|
TOOL_SHAPE_CYLINDER_INF_H,
|
|
TOOL_SHAPE_BOX,
|
|
TOOL_SHAPE_BOX_INF_H,
|
|
}
|
|
|
|
var _plugin: EditorPlugin = null
|
|
var _grass_selected = null
|
|
var _tools_menu: PopupMenu = null
|
|
var _airbrush_shape_menu: PopupMenu = null
|
|
var _pencil_shape_menu: PopupMenu = null
|
|
var _eraser_shape_menu: PopupMenu = null
|
|
|
|
|
|
func set_plugin(plugin :EditorPlugin) -> void:
|
|
var popup := get_popup()
|
|
_plugin = plugin
|
|
_airbrush_shape_menu = PopupMenu.new()
|
|
_airbrush_shape_menu.name = &"AirbrushShapeMenu"
|
|
_airbrush_shape_menu.add_radio_check_item("Cylinder", MENU_SHAPE_ID.TOOL_SHAPE_CYLINDER)
|
|
_airbrush_shape_menu.add_radio_check_item("Box", MENU_SHAPE_ID.TOOL_SHAPE_BOX)
|
|
_pencil_shape_menu = PopupMenu.new()
|
|
_pencil_shape_menu.name = &"PencilShapeMenu"
|
|
_pencil_shape_menu.add_radio_check_item("Cylinder", MENU_SHAPE_ID.TOOL_SHAPE_CYLINDER)
|
|
_pencil_shape_menu.add_radio_check_item("Box", MENU_SHAPE_ID.TOOL_SHAPE_BOX)
|
|
_eraser_shape_menu = PopupMenu.new()
|
|
_eraser_shape_menu.name = &"EraserShapeMenu"
|
|
_eraser_shape_menu.add_radio_check_item("Sphere", MENU_SHAPE_ID.TOOL_SHAPE_SPHERE)
|
|
_eraser_shape_menu.add_radio_check_item("Cylinder", MENU_SHAPE_ID.TOOL_SHAPE_CYLINDER)
|
|
_eraser_shape_menu.add_radio_check_item("Infinite vertical cylinder", MENU_SHAPE_ID.TOOL_SHAPE_CYLINDER_INF_H)
|
|
_eraser_shape_menu.add_radio_check_item("Box", MENU_SHAPE_ID.TOOL_SHAPE_BOX)
|
|
_eraser_shape_menu.add_radio_check_item("Infinite vertical box", MENU_SHAPE_ID.TOOL_SHAPE_BOX_INF_H)
|
|
_tools_menu = PopupMenu.new()
|
|
_tools_menu.add_child(_airbrush_shape_menu)
|
|
_tools_menu.add_child(_pencil_shape_menu)
|
|
_tools_menu.add_child(_eraser_shape_menu)
|
|
_tools_menu.name = &"ToolsMenu"
|
|
_tools_menu.add_check_item("Follow terrain's normal", MENU_ID.TOOL_FOLLOW_NORMAL)
|
|
_tools_menu.add_submenu_item("Airbrush shape", "AirbrushShapeMenu")
|
|
_tools_menu.add_submenu_item("Pencil shape", "PencilShapeMenu")
|
|
_tools_menu.add_submenu_item("Eraser shape", "EraserShapeMenu")
|
|
_tools_menu.add_separator()
|
|
_tools_menu.add_item("Snap to terrain", MENU_ID.TOOL_SNAP_TO_TERRAIN)
|
|
popup.add_child(_tools_menu)
|
|
popup.clear()
|
|
popup.add_submenu_item("Tools", "ToolsMenu")
|
|
popup.add_separator()
|
|
popup.add_item("Auto center position", MENU_ID.AUTO_CENTER_POSITION)
|
|
popup.add_item("Recalculate custom AABB", MENU_ID.RECALCULATE_AABB)
|
|
popup.add_item("Bake height map", MENU_ID.BAKE_HEIGHT_MAP)
|
|
popup.add_check_item("Cast shadow", MENU_ID.CAST_SHADOW)
|
|
popup.add_item("Global parameters", MENU_ID.GLOBAL_PARAMETERS)
|
|
popup.add_separator()
|
|
popup.add_item("Clear all", MENU_ID.CLEAR_ALL)
|
|
popup.add_separator()
|
|
popup.add_item("About SimpleGrassTextured", MENU_ID.HELP_ABOUT)
|
|
popup.id_pressed.connect(_on_sgt_menu_button)
|
|
_tools_menu.id_pressed.connect(_on_sgt_tools_menu_button)
|
|
_airbrush_shape_menu.id_pressed.connect(_on_sgt_shape_menu_pressed.bind("airbrush", _airbrush_shape_menu))
|
|
_pencil_shape_menu.id_pressed.connect(_on_sgt_shape_menu_pressed.bind("pencil", _pencil_shape_menu))
|
|
_eraser_shape_menu.id_pressed.connect(_on_sgt_shape_menu_pressed.bind("eraser", _eraser_shape_menu))
|
|
about_to_popup.connect(_on_about_to_popup)
|
|
|
|
|
|
func set_current_grass(grass_selected) -> void:
|
|
_grass_selected = grass_selected
|
|
if grass_selected == null:
|
|
return
|
|
var popup := get_popup()
|
|
if grass_selected.cast_shadow == GeometryInstance3D.SHADOW_CASTING_SETTING_OFF:
|
|
popup.set_item_checked(popup.get_item_index(MENU_ID.CAST_SHADOW), false)
|
|
else:
|
|
popup.set_item_checked(popup.get_item_index(MENU_ID.CAST_SHADOW), true)
|
|
if _grass_selected.baked_height_map != null:
|
|
popup.set_item_text(popup.get_item_index(MENU_ID.BAKE_HEIGHT_MAP), "Bake height map (already baked)")
|
|
popup.set_item_disabled(popup.get_item_index(MENU_ID.BAKE_HEIGHT_MAP), true)
|
|
else:
|
|
popup.set_item_text(popup.get_item_index(MENU_ID.BAKE_HEIGHT_MAP), "Bake height map")
|
|
popup.set_item_disabled(popup.get_item_index(MENU_ID.BAKE_HEIGHT_MAP), false)
|
|
_tools_menu.set_item_checked(_tools_menu.get_item_index(MENU_ID.TOOL_FOLLOW_NORMAL), _grass_selected.sgt_follow_normal)
|
|
for tool_name in _grass_selected.sgt_tool_shape:
|
|
match tool_name:
|
|
"airbrush":
|
|
_update_shape_menu_from_grass(_airbrush_shape_menu, _grass_selected.sgt_tool_shape[tool_name])
|
|
"pencil":
|
|
_update_shape_menu_from_grass(_pencil_shape_menu, _grass_selected.sgt_tool_shape[tool_name])
|
|
"eraser":
|
|
_update_shape_menu_from_grass(_eraser_shape_menu, _grass_selected.sgt_tool_shape[tool_name])
|
|
|
|
|
|
func _update_shape_menu_from_grass(popupmenu: PopupMenu, plugin_id_shape: int) -> void:
|
|
for i in popupmenu.item_count:
|
|
popupmenu.set_item_checked(i, false)
|
|
var idx := -1
|
|
match _plugin.get_tool_shape_name(plugin_id_shape):
|
|
"sphere":
|
|
idx = popupmenu.get_item_index(MENU_SHAPE_ID.TOOL_SHAPE_SPHERE)
|
|
"cylinder":
|
|
idx = popupmenu.get_item_index(MENU_SHAPE_ID.TOOL_SHAPE_CYLINDER)
|
|
"cylinder_inf_h":
|
|
idx = popupmenu.get_item_index(MENU_SHAPE_ID.TOOL_SHAPE_CYLINDER_INF_H)
|
|
"box":
|
|
idx = popupmenu.get_item_index(MENU_SHAPE_ID.TOOL_SHAPE_BOX)
|
|
"box_inf_h":
|
|
idx = popupmenu.get_item_index(MENU_SHAPE_ID.TOOL_SHAPE_BOX_INF_H)
|
|
_:
|
|
idx = -1
|
|
if idx == -1:
|
|
return
|
|
popupmenu.set_item_checked(idx, true)
|
|
|
|
|
|
func _on_sgt_menu_button(id :int) -> void:
|
|
if _grass_selected == null:
|
|
return
|
|
match id:
|
|
MENU_ID.AUTO_CENTER_POSITION:
|
|
_plugin.get_undo_redo().create_action(_grass_selected.name + " Auto Center Position")
|
|
_plugin.get_undo_redo().add_undo_property(_grass_selected, &"baked_height_map", _grass_selected.baked_height_map)
|
|
_plugin.get_undo_redo().add_undo_property(_grass_selected, &"multimesh", _grass_selected.multimesh)
|
|
_plugin.get_undo_redo().add_undo_property(_grass_selected, &"global_position", _grass_selected.global_position)
|
|
_grass_selected.auto_center_position()
|
|
_plugin.get_undo_redo().add_do_property(_grass_selected, &"baked_height_map", _grass_selected.baked_height_map)
|
|
_plugin.get_undo_redo().add_do_property(_grass_selected, &"multimesh", _grass_selected.multimesh)
|
|
_plugin.get_undo_redo().add_do_property(_grass_selected, &"global_position", _grass_selected.global_position)
|
|
_plugin.get_undo_redo().commit_action()
|
|
MENU_ID.RECALCULATE_AABB:
|
|
_plugin.get_undo_redo().create_action(_grass_selected.name + " Recalculate Custom AABB")
|
|
_plugin.get_undo_redo().add_undo_property(_grass_selected, &"custom_aabb", _grass_selected.custom_aabb)
|
|
_grass_selected.recalculate_custom_aabb()
|
|
_plugin.get_undo_redo().add_do_property(_grass_selected, &"custom_aabb", _grass_selected.custom_aabb)
|
|
_plugin.get_undo_redo().commit_action()
|
|
MENU_ID.CAST_SHADOW:
|
|
_plugin.get_undo_redo().create_action(_grass_selected.name + " Toogle Cast Shadow")
|
|
_plugin.get_undo_redo().add_undo_property(_grass_selected, &"cast_shadow", _grass_selected.cast_shadow)
|
|
for child in _grass_selected.get_children():
|
|
if child.has_meta(&"SimpleGrassTexturedRegion"):
|
|
_plugin.get_undo_redo().add_undo_property(child, &"cast_shadow", child.cast_shadow)
|
|
if _grass_selected.cast_shadow == GeometryInstance3D.SHADOW_CASTING_SETTING_OFF:
|
|
_grass_selected.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_ON
|
|
else:
|
|
_grass_selected.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
|
|
_plugin.get_undo_redo().add_do_property(_grass_selected, &"cast_shadow", _grass_selected.cast_shadow)
|
|
for child in _grass_selected.get_children():
|
|
if child.has_meta(&"SimpleGrassTexturedRegion"):
|
|
child.cast_shadow = _grass_selected.cast_shadow
|
|
_plugin.get_undo_redo().add_do_property(child, &"cast_shadow", child.cast_shadow)
|
|
_plugin.get_undo_redo().commit_action()
|
|
MENU_ID.BAKE_HEIGHT_MAP:
|
|
_grass_selected.bake_height_map()
|
|
MENU_ID.GLOBAL_PARAMETERS:
|
|
var _global_parameters = load("res://addons/simplegrasstextured/gui/global_parameters.tscn").instantiate()
|
|
get_window().add_child(_global_parameters)
|
|
_global_parameters.popup_centered()
|
|
MENU_ID.CLEAR_ALL:
|
|
var win = load("res://addons/simplegrasstextured/gui/clear_all_confirmation_dialog.tscn").instantiate()
|
|
get_window().add_child(win)
|
|
win.confirmed.connect(_on_clear_all_confirmation_dialog_confirmed)
|
|
win.popup_centered()
|
|
MENU_ID.HELP_ABOUT:
|
|
var win = load("res://addons/simplegrasstextured/gui/about.tscn").instantiate()
|
|
get_window().add_child(win)
|
|
win.popup_centered()
|
|
|
|
|
|
func _on_sgt_tools_menu_button(id :int) -> void:
|
|
if _grass_selected == null:
|
|
return
|
|
match id:
|
|
MENU_ID.TOOL_FOLLOW_NORMAL:
|
|
var idx := _tools_menu.get_item_index(id)
|
|
_tools_menu.set_item_checked(idx, not _tools_menu.is_item_checked(idx))
|
|
_grass_selected.sgt_follow_normal = _tools_menu.is_item_checked(idx)
|
|
MENU_ID.TOOL_SNAP_TO_TERRAIN:
|
|
_plugin.get_undo_redo().create_action(_grass_selected.name + " Snap to terrain")
|
|
_plugin.get_undo_redo().add_undo_property(_grass_selected, &"baked_height_map", _grass_selected.baked_height_map)
|
|
_plugin.get_undo_redo().add_undo_property(_grass_selected, &"multimesh", _grass_selected.multimesh.duplicate())
|
|
_plugin.get_undo_redo().add_undo_property(_grass_selected, &"global_position", _grass_selected.global_position)
|
|
_grass_selected.snap_to_terrain()
|
|
_plugin.get_undo_redo().add_do_property(_grass_selected, &"baked_height_map", _grass_selected.baked_height_map)
|
|
_plugin.get_undo_redo().add_do_property(_grass_selected, &"multimesh", _grass_selected.multimesh)
|
|
_plugin.get_undo_redo().add_do_property(_grass_selected, &"global_position", _grass_selected.global_position)
|
|
_plugin.get_undo_redo().commit_action()
|
|
|
|
|
|
func _on_sgt_shape_menu_pressed(id: int, tool_name: String, popupmenu: PopupMenu) -> void:
|
|
if _grass_selected == null:
|
|
return
|
|
for i in popupmenu.item_count:
|
|
popupmenu.set_item_checked(i, false)
|
|
var idx := popupmenu.get_item_index(id)
|
|
if idx == -1:
|
|
return
|
|
popupmenu.set_item_checked(idx, true)
|
|
var shape_name := ""
|
|
match id:
|
|
MENU_SHAPE_ID.TOOL_SHAPE_SPHERE:
|
|
shape_name = "sphere"
|
|
MENU_SHAPE_ID.TOOL_SHAPE_CYLINDER:
|
|
shape_name = "cylinder"
|
|
MENU_SHAPE_ID.TOOL_SHAPE_CYLINDER_INF_H:
|
|
shape_name = "cylinder_inf_h"
|
|
MENU_SHAPE_ID.TOOL_SHAPE_BOX:
|
|
shape_name = "box"
|
|
MENU_SHAPE_ID.TOOL_SHAPE_BOX_INF_H:
|
|
shape_name = "box_inf_h"
|
|
_plugin.set_tool_shape(tool_name, shape_name)
|
|
|
|
|
|
func _on_about_to_popup() -> void:
|
|
set_current_grass(_grass_selected)
|
|
|
|
|
|
func _on_clear_all_confirmation_dialog_confirmed() -> void:
|
|
if _grass_selected == null:
|
|
return
|
|
_plugin.get_undo_redo().create_action(_grass_selected.name + " Clear All Grass")
|
|
_plugin.get_undo_redo().add_undo_property(_grass_selected, &"baked_height_map", _grass_selected.baked_height_map)
|
|
_plugin.get_undo_redo().add_undo_property(_grass_selected, &"multimesh", _grass_selected.multimesh)
|
|
_grass_selected.clear_all()
|
|
_plugin.get_undo_redo().add_do_property(_grass_selected, &"baked_height_map", _grass_selected.baked_height_map)
|
|
_plugin.get_undo_redo().add_do_property(_grass_selected, &"multimesh", _grass_selected.multimesh)
|
|
_plugin.get_undo_redo().commit_action()
|