1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-02-08 19:39:50 +00:00
Pixelorama/src/Preferences/PreferencesDialog.gd

331 lines
12 KiB
GDScript3
Raw Normal View History

extends AcceptDialog
# Array of Preference(s)
var preferences := [
Preference.new("open_last_project", "Startup/StartupContainer/OpenLastProject", "pressed"),
Preference.new("quit_confirmation", "Startup/StartupContainer/QuitConfirmation", "pressed"),
Preference.new("shrink", "Interface/ShrinkContainer/ShrinkHSlider", "value"),
Preference.new("dim_on_popup", "Interface/DimPopup/CheckBox", "pressed"),
Preference.new("icon_color_from", "Interface/IconColorFrom/IconColorOptionButton", "selected"),
Preference.new("custom_icon_color", "Interface/IconColorFrom/IconColorButton", "color"),
Preference.new(
"tool_button_size", "Interface/ToolButtonSize/ToolButtonSizeOptionButton", "selected"
),
Preference.new(
"pressure_sensitivity_mode",
"Startup/PressureSentivity/PressureSensitivityOptionButton",
"selected"
),
Preference.new(
"show_left_tool_icon", "Cursors/CursorsContainer/LeftToolIconCheckbox", "pressed"
),
Preference.new(
"show_right_tool_icon", "Cursors/CursorsContainer/RightToolIconCheckbox", "pressed"
),
Preference.new(
"left_square_indicator_visible", "Cursors/CursorsContainer/LeftIndicatorCheckbox", "pressed"
),
Preference.new(
"right_square_indicator_visible",
"Cursors/CursorsContainer/RightIndicatorCheckbox",
"pressed"
),
Preference.new("native_cursors", "Cursors/CursorsContainer/NativeCursorsCheckbox", "pressed"),
Preference.new("cross_cursor", "Cursors/CursorsContainer/CrossCursorCheckbox", "pressed"),
Preference.new("autosave_interval", "Backup/AutosaveContainer/AutosaveInterval", "value"),
Preference.new("enable_autosave", "Backup/AutosaveContainer/EnableAutosave", "pressed"),
Preference.new("default_width", "Image/ImageOptions/ImageDefaultWidth", "value"),
Preference.new("default_height", "Image/ImageOptions/ImageDefaultHeight", "value"),
Preference.new("default_fill_color", "Image/ImageOptions/DefaultFillColor", "color"),
Preference.new("smooth_zoom", "Canvas/ZoomOptions/SmoothZoom", "pressed"),
Preference.new("grid_type", "Canvas/GridOptions/GridType", "selected"),
Preference.new("grid_width", "Canvas/GridOptions/GridWidthValue", "value"),
Preference.new("grid_height", "Canvas/GridOptions/GridHeightValue", "value"),
Preference.new(
"grid_isometric_cell_bounds_width",
"Canvas/GridOptions/IsometricCellBoundsWidthValue",
"value"
),
Preference.new(
"grid_isometric_cell_bounds_height",
"Canvas/GridOptions/IsometricCellBoundsHeightValue",
"value"
),
Preference.new("grid_offset_x", "Canvas/GridOptions/GridOffsetXValue", "value"),
Preference.new("grid_offset_y", "Canvas/GridOptions/GridOffsetYValue", "value"),
Preference.new(
"grid_draw_over_tile_mode", "Canvas/GridOptions/GridDrawOverTileMode", "pressed"
),
Preference.new("grid_color", "Canvas/GridOptions/GridColor", "color"),
Preference.new("pixel_grid_show_at_zoom", "Canvas/PixelGridOptions/ShowAtZoom", "value"),
Preference.new("pixel_grid_color", "Canvas/PixelGridOptions/GridColor", "color"),
Preference.new("guide_color", "Canvas/GuideOptions/GuideColor", "color"),
Preference.new("checker_size", "Canvas/CheckerOptions/CheckerSizeValue", "value"),
Preference.new("checker_color_1", "Canvas/CheckerOptions/CheckerColor1", "color"),
Preference.new("checker_color_2", "Canvas/CheckerOptions/CheckerColor2", "color"),
Preference.new(
"checker_follow_movement", "Canvas/CheckerOptions/CheckerFollowMovement", "pressed"
),
Preference.new("checker_follow_scale", "Canvas/CheckerOptions/CheckerFollowScale", "pressed"),
Preference.new("tilemode_opacity", "Canvas/CheckerOptions/TileModeOpacity", "value"),
Preference.new("selection_animated_borders", "Selection/SelectionOptions/Animate", "pressed"),
Preference.new("selection_border_color_1", "Selection/SelectionOptions/BorderColor1", "color"),
Preference.new("selection_border_color_2", "Selection/SelectionOptions/BorderColor2", "color"),
Preference.new("fps_limit", "Performance/PerformanceContainer/SetFPSLimit", "value"),
Preference.new(
"pause_when_unfocused", "Performance/PerformanceContainer/PauseAppFocus", "pressed"
),
2020-05-31 20:04:59 +00:00
]
var content_list := []
var selected_item := 0
var restore_default_button_tcsn = preload("res://src/Preferences/RestoreDefaultButton.tscn")
onready var list: ItemList = $HSplitContainer/List
onready var right_side: VBoxContainer = $HSplitContainer/ScrollContainer/VBoxContainer
onready var autosave_container: Container = right_side.get_node("Backup/AutosaveContainer")
onready var autosave_interval: SpinBox = autosave_container.get_node("AutosaveInterval")
onready var shrink_label: Label = right_side.get_node("Interface/ShrinkContainer/ShrinkLabel")
onready var themes: BoxContainer = right_side.get_node("Interface/Themes")
Implement a basic extension system Importing .pck or .zip Godot resource pack files into Pixelorama is now possible. This needs to be documented properly, but here's the basic idea, for now at least. This is super early work and I haven't tested it with a proper extension yet, so all of this could be a subject of change. I tested it with a custom theme extension though and it seems to be working perfectly. Importing resource pack files, either by dragging and dropping them into the app window or by going to Edit>Preferences>Extensions>Add Extension, copies the files into user://extensions/. Extensions can be enabled/disabled and uninstalled. Uninstalling them deletes the resource pack files from user://extensions/. The extension project source files need to be in a folder inside src/Extensions/ with the same name as the .pck or .zip file. **This is required for now, otherwise it will not work.** Inside that folder there also needs to be an extension.json file, with a structure similar to this: { "name": "ExtensionName", "display_name": "Extension Name", "description": "A Pixelorama extension", "author": "Orama Interactive", "version": "0.1", "license": "MIT", "nodes": [ "ExtensionExample.tscn" ] } The `nodes` array leads to the packed scene files with the nodes that are to be instantiated. **The root nodes of these scenes need to have the same name as the .tscn files they belong to.** The scripts of these nodes should have _enter_tree() and _exit_tree() methods to handle the extension enabling/disabling (or even uninstalling) logic. Note that .json files need to be included in the export options while exporting the extension from Godot. Enabling an extension means that the scenes found in the extension.json's "nodes" array get instantiated, and disabling gets rid of these nodes from Pixelorama's SceneTree.
2022-02-19 01:21:08 +00:00
onready var extensions: BoxContainer = right_side.get_node("Extensions")
class Preference:
var prop_name: String
var node_path: String
var value_type: String
var default_value
func _init(_prop_name: String, _node_path: String, _value_type: String) -> void:
prop_name = _prop_name
node_path = _node_path
value_type = _value_type
default_value = Global.get(prop_name)
func _ready() -> void:
# Replace OK since preference changes are being applied immediately, not after OK confirmation
get_ok().text = tr("Close")
for child in right_side.get_children():
content_list.append(child.name)
2020-05-31 20:43:24 +00:00
if OS.get_name() == "HTML5":
content_list.erase("Startup")
right_side.get_node("Startup").queue_free()
right_side.get_node("Language").visible = true
Global.open_last_project = false
2020-05-31 20:04:59 +00:00
for pref in preferences:
var node: Node = right_side.get_node(pref.node_path)
var node_position := node.get_index()
var restore_default_button: BaseButton = restore_default_button_tcsn.instance()
restore_default_button.setting_name = pref.prop_name
restore_default_button.value_type = pref.value_type
restore_default_button.default_value = pref.default_value
restore_default_button.node = node
node.get_parent().add_child(restore_default_button)
node.get_parent().move_child(restore_default_button, node_position)
2020-05-31 20:43:24 +00:00
match pref.value_type:
2020-05-31 20:04:59 +00:00
"pressed":
node.connect(
"toggled",
self,
"_on_Preference_toggled",
[pref.prop_name, pref.default_value, restore_default_button]
)
2020-05-31 20:04:59 +00:00
"value":
node.connect(
"value_changed",
self,
"_on_Preference_value_changed",
[pref.prop_name, pref.default_value, restore_default_button]
)
2020-05-31 20:04:59 +00:00
"color":
node.get_picker().presets_visible = false
node.connect(
"color_changed",
self,
"_on_Preference_color_changed",
[pref.prop_name, pref.default_value, restore_default_button]
)
2020-05-31 20:04:59 +00:00
"selected":
node.connect(
"item_selected",
self,
"_on_Preference_item_selected",
[pref.prop_name, pref.default_value, restore_default_button]
)
2020-05-31 20:04:59 +00:00
if Global.config_cache.has_section_key("preferences", pref.prop_name):
var value = Global.config_cache.get_value("preferences", pref.prop_name)
Global.set(pref.prop_name, value)
node.set(pref.value_type, value)
var global_value = Global.get(pref.prop_name)
# This is needed because color_changed doesn't fire if the color changes in code
if pref.value_type == "color":
preference_update(pref.prop_name)
disable_restore_default_button(
restore_default_button, global_value.is_equal_approx(pref.default_value)
)
elif pref.value_type == "selected":
preference_update(pref.prop_name)
disable_restore_default_button(
restore_default_button, global_value == pref.default_value
)
func _on_Preference_toggled(
button_pressed: bool, prop: String, default_value, restore_default_button: BaseButton
) -> void:
2020-05-31 20:04:59 +00:00
Global.set(prop, button_pressed)
Global.config_cache.set_value("preferences", prop, button_pressed)
preference_update(prop)
disable_restore_default_button(restore_default_button, Global.get(prop) == default_value)
func _on_Preference_value_changed(
value: float, prop: String, default_value, restore_default_button: BaseButton
) -> void:
2020-05-31 20:04:59 +00:00
Global.set(prop, value)
Global.config_cache.set_value("preferences", prop, value)
preference_update(prop)
disable_restore_default_button(restore_default_button, Global.get(prop) == default_value)
func _on_Preference_color_changed(
color: Color, prop: String, default_value, restore_default_button: BaseButton
) -> void:
2020-05-31 20:04:59 +00:00
Global.set(prop, color)
Global.config_cache.set_value("preferences", prop, color)
preference_update(prop)
disable_restore_default_button(
restore_default_button, Global.get(prop).is_equal_approx(default_value)
)
func _on_Preference_item_selected(
id: int, prop: String, default_value, restore_default_button: BaseButton
) -> void:
2020-05-31 20:04:59 +00:00
Global.set(prop, id)
Global.config_cache.set_value("preferences", prop, id)
preference_update(prop)
disable_restore_default_button(restore_default_button, Global.get(prop) == default_value)
2020-05-31 20:04:59 +00:00
func preference_update(prop: String) -> void:
2020-05-31 20:04:59 +00:00
if prop in ["autosave_interval", "enable_autosave"]:
OpenSave.update_autosave()
autosave_interval.editable = Global.enable_autosave
if autosave_interval.editable:
autosave_interval.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
else:
autosave_interval.mouse_default_cursor_shape = Control.CURSOR_FORBIDDEN
2020-05-31 20:43:24 +00:00
if "grid" in prop:
Global.canvas.grid.update()
2020-05-31 20:43:24 +00:00
if prop in ["pixel_grid_show_at_zoom", "pixel_grid_color"]:
Global.canvas.pixel_grid.update()
if "checker" in prop:
Global.transparent_checker.update_rect()
2020-05-31 20:43:24 +00:00
2020-05-31 20:04:59 +00:00
if prop in ["guide_color"]:
for guide in Global.canvas.get_children():
if guide is SymmetryGuide:
# Add a subtle difference to the normal guide color by mixing in some blue
guide.default_color = Global.guide_color.linear_interpolate(Color(.2, .2, .65), .6)
elif guide is Guide:
guide.default_color = Global.guide_color
2020-05-31 20:43:24 +00:00
if prop in ["fps_limit"]:
Engine.set_target_fps(Global.fps_limit)
if "selection" in prop:
var marching_ants: Sprite = Global.canvas.selection.marching_ants_outline
marching_ants.material.set_shader_param("animated", Global.selection_animated_borders)
marching_ants.material.set_shader_param("first_color", Global.selection_border_color_1)
marching_ants.material.set_shader_param("second_color", Global.selection_border_color_2)
Global.canvas.selection.update()
if prop in ["icon_color_from", "custom_icon_color"]:
if Global.icon_color_from == Global.IconColorFrom.THEME:
2022-02-17 18:36:10 +00:00
var current_theme: Theme = themes.themes[themes.theme_index]
Global.modulate_icon_color = current_theme.get_color("modulate_color", "Icons")
else:
Global.modulate_icon_color = Global.custom_icon_color
themes.change_icon_colors()
if prop == "tool_button_size":
Tools.set_button_size(Global.tool_button_size)
if prop == "native_cursors":
var image
if Global.native_cursors:
image = null
else:
image = Global.control.cursor_image
Input.set_custom_mouse_cursor(image, Input.CURSOR_CROSS, Vector2(15, 15))
if prop == "cross_cursor":
if Global.cross_cursor:
Global.main_viewport.mouse_default_cursor_shape = Control.CURSOR_CROSS
else:
Global.main_viewport.mouse_default_cursor_shape = Control.CURSOR_ARROW
2020-05-31 20:04:59 +00:00
Global.config_cache.save("user://cache.ini")
2020-02-15 05:34:42 +00:00
2020-04-07 22:56:05 +00:00
func disable_restore_default_button(button: BaseButton, disable: bool) -> void:
button.disabled = disable
if disable:
button.mouse_default_cursor_shape = Control.CURSOR_ARROW
button.hint_tooltip = ""
else:
button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
button.hint_tooltip = "Restore default value"
func _on_PreferencesDialog_about_to_show() -> void:
add_tabs(false)
func add_tabs(changed_language := false) -> void:
for item in content_list:
list.add_item(" " + tr(item))
var language_index := content_list.find("Language")
list.select(language_index if changed_language else selected_item)
autosave_interval.suffix = tr("minute(s)")
func _on_PreferencesDialog_popup_hide() -> void:
2020-05-31 20:04:59 +00:00
list.clear()
2020-04-07 22:56:05 +00:00
func _on_List_item_selected(index: int) -> void:
selected_item = index
for child in right_side.get_children():
child.visible = child.name == content_list[index]
func _on_ShrinkHSlider_value_changed(value: float) -> void:
shrink_label.text = str(value)
func _on_ShrinkApplyButton_pressed() -> void:
get_tree().set_screen_stretch(
SceneTree.STRETCH_MODE_DISABLED,
SceneTree.STRETCH_ASPECT_IGNORE,
Vector2(1024, 576),
Global.shrink
)
hide()
popup_centered(Vector2(400, 280))
Global.dialog_open(true)
yield(Global.get_tree().create_timer(0.01), "timeout")
Global.camera.fit_to_frame(Global.current_project.size)