Skip to content

Commit

Permalink
Event UI picker updates (#1070)
Browse files Browse the repository at this point in the history
* Event UI picker updates

# File picker
Adds a file picker. You can give it some placeholder text and a file filter (e.g. '*.png'). You can drag and drop files that fit that filter into the picker.

# "Simple" Condition picker
Pretty complex picker that allows to switch between "simple" editing and complex one. Simple editing provides three drop-downs.

# Complex Picker
doesn't use a popup anymore, instead it uses a ItemList node.

* Update condition picker to use {Variable} style
  • Loading branch information
Jowan-Spooner authored Aug 2, 2022
1 parent 40bc0c7 commit 9258872
Show file tree
Hide file tree
Showing 18 changed files with 475 additions and 74 deletions.
20 changes: 16 additions & 4 deletions addons/dialogic/Editor/Events/EventNode/EventNode.gd
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ func build_editor():
if p.name == "linebreak":
editor_node = Control.new()
editor_node.theme_type_variation = "LineBreak"

### STRINGS
elif p.dialogic_type == resource.ValueType.MultilineText:
editor_node = load("res://addons/dialogic/Editor/Events/Fields/MultilineText.tscn").instantiate()
Expand All @@ -178,6 +179,17 @@ func build_editor():
elif p.dialogic_type == resource.ValueType.Bool:
editor_node = load("res://addons/dialogic/Editor/Events/Fields/Bool.tscn").instantiate()

elif p.dialogic_type == resource.ValueType.File:
editor_node = load("res://addons/dialogic/Editor/Events/Fields/FilePicker.tscn").instantiate()
editor_node.file_filter = p.display_info.get('file_filter', '')
editor_node.placeholder = p.display_info.get('placeholder', '')
editor_node.resource_icon = p.display_info.get('icon', null)
if editor_node.resource_icon == null and p.display_info.has('editor_icon'):
editor_node.resource_icon = callv('get_theme_icon', p.display_info.editor_icon)

elif p.dialogic_type == resource.ValueType.Condition:
editor_node = load("res://addons/dialogic/Editor/Events/Fields/ConditionPicker.tscn").instantiate()

## Complex Picker
elif p.dialogic_type == resource.ValueType.ComplexPicker:
editor_node = load("res://addons/dialogic/Editor/Events/Fields/ComplexPicker.tscn").instantiate()
Expand Down Expand Up @@ -235,10 +247,10 @@ func build_editor():
editor_node.set_value(resource.get(p.name))
if editor_node.has_signal('value_changed'):
editor_node.value_changed.connect(set_property)
if editor_node.has_method('set_left_text') and p.has('left_text'):
editor_node.set_left_text(p.left_text)
if editor_node.has_method('set_right_text') and p.has('right_text'):
editor_node.set_right_text(p.right_text)
if editor_node.has_method('set_left_text'):
editor_node.set_left_text(p.get('left_text', ''))
if editor_node.has_method('set_right_text'):
editor_node.set_right_text(p.get('right_text', ''))
if p.has('condition'):
edit_conditions_list.append([editor_node, p.condition])

Expand Down
72 changes: 32 additions & 40 deletions addons/dialogic/Editor/Events/Fields/ComplexPicker.gd
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ extends Control
var file_extension = ""
var get_suggestions_func = [self, 'get_default_suggestions']
var empty_text = ""
var disable_pretty_name := false
@export var disable_pretty_name := false

var resource_icon:Texture = null:
get:
Expand All @@ -21,10 +21,6 @@ var resource_icon:Texture = null:
else:
$Search.theme_type_variation = "LineEditWithIcon"

# I'm so sorry for this, but the popup_hide signal get's triggered if the popup is hidden by me,
# and I don't want it to change the resource, if one was just selected by clicking
var ignore_popup_hide_once = false

## STORING VALUE AND REFERENCE TO RESOURCE
var event_resource : DialogicEvent = null
var property_name : String
Expand Down Expand Up @@ -90,11 +86,9 @@ func _ready():
$Search/Icon.position.x = 10
$Search/SelectButton.icon = get_theme_icon("Collapse", "EditorIcons")
$Search.placeholder_text = placeholder_text
$Search/Suggestions.hide()
$Search/Suggestions.index_pressed.connect(suggestion_selected)
$Search/Suggestions.popup_hide.connect(popup_hide)
#TODO: Invalid call. Nonexistent function 'add_theme_stylebox_override' in base 'PopupMenu'.
#$Search/Suggestions.add_theme_stylebox_override('panel', load("res://addons/dialogic/Editor/Events/styles/ResourceMenuPanelBackground.tres"))
%Suggestions.add_theme_stylebox_override('bg', load("res://addons/dialogic/Editor/Events/styles/ResourceMenuPanelBackground.tres"))
%Suggestions.hide()
%Suggestions.item_selected.connect(suggestion_selected)
if resource_icon == null:
self.resource_icon = null

Expand All @@ -103,44 +97,45 @@ func _ready():
## SEARCH & SUGGESTION POPUP
################################################################################
func _on_Search_text_entered(new_text = ""):
if $Search/Suggestions.get_item_count() and not $Search.text.is_empty():
if %Suggestions.get_item_count() and not $Search.text.is_empty():
suggestion_selected(0)
else:
changed_to_empty()

func _on_Search_text_changed(new_text, just_update = false):
$Search/Suggestions.clear()
%Suggestions.clear()

if new_text == "" and !just_update:
changed_to_empty()

ignore_popup_hide_once = just_update


var suggestions = get_suggestions_func[0].call(get_suggestions_func[1], new_text)

var line_length = 0
var more_hidden = false
var idx = 0
for element in suggestions:
if new_text != "" or idx < 12:
line_length = max(get_theme_font('font', 'Label').get_string_size(element, HORIZONTAL_ALIGNMENT_LEFT, -1, get_theme_font_size("font_size", 'Label')).x+80, line_length)
%Suggestions.add_item(element)
if suggestions[element].has('icon'):
$Search/Suggestions.add_icon_item(suggestions[element].icon, element)
%Suggestions.set_item_icon(idx, suggestions[element].icon)
elif suggestions[element].has('editor_icon'):
$Search/Suggestions.add_icon_item(get_theme_icon(suggestions[element].editor_icon[0],suggestions[element].editor_icon[1]), element)
else:
$Search/Suggestions.add_item(element)
$Search/Suggestions.set_item_tooltip(idx, suggestions[element].get('tooltip', ''))
$Search/Suggestions.set_item_metadata(idx, suggestions[element].value)
%Suggestions.set_item_icon(idx, get_theme_icon(suggestions[element].editor_icon[0],suggestions[element].editor_icon[1]))

%Suggestions.set_item_tooltip(idx, suggestions[element].get('tooltip', ''))
%Suggestions.set_item_metadata(idx, suggestions[element].value)
else:
more_hidden = true
break
idx += 1

if more_hidden:
$Search/Suggestions.add_item('...')
$Search/Suggestions.set_item_disabled(idx, true)
%Suggestions.add_item('...', null, false)

if not $Search/Suggestions.visible:
$Search/Suggestions.popup_on_parent(Rect2i($Search.get_global_rect().position+Vector2(0,$Search.size.y), Vector2($Search.size.x, 50)))
if not %Suggestions.visible:
%Suggestions.show()
%Suggestions.global_position = $Search.global_position+Vector2(0,1)*$Search.size.y
%Suggestions.custom_minimum_size.x = max($Search.size.x, line_length)

$Search.grab_focus()

Expand All @@ -155,30 +150,27 @@ func get_default_suggestions(search_text):
return suggestions

func suggestion_selected(index):
$Search.text = $Search/Suggestions.get_item_text(index)
$Search.text = %Suggestions.get_item_text(index)

# if this is a resource:
if file_extension:
var file = load($Search/Suggestions.get_item_metadata(index))
var file = load(%Suggestions.get_item_metadata(index))
current_value = file
else:
current_value = $Search/Suggestions.get_item_metadata(index)
current_value = %Suggestions.get_item_metadata(index)

ignore_popup_hide_once = true
$Search/Suggestions.hide()
hide_suggestions()

emit_signal("value_changed", property_name, current_value)

func popup_hide():

func _input(event):
if event is InputEventMouseButton and event.pressed:
if !%Suggestions.get_global_rect().has_point(get_global_mouse_position()):
if %Suggestions.visible: hide_suggestions()

func hide_suggestions():
$Search/SelectButton.button_pressed = false
if ignore_popup_hide_once:
ignore_popup_hide_once = false
return
if $Search/Suggestions.get_item_count() and not $Search.text.is_empty():
suggestion_selected(0)
else:
set_value(null)
changed_to_empty()
%Suggestions.hide()

func _on_Search_focus_entered():
if $Search.text == "" or current_value == null or (typeof(current_value) == TYPE_STRING and current_value.is_empty()):
Expand Down
47 changes: 40 additions & 7 deletions addons/dialogic/Editor/Events/Fields/ComplexPicker.tscn
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
[gd_scene load_steps=5 format=3 uid="uid://dpwhshre1n4t6"]
[gd_scene load_steps=7 format=3 uid="uid://dpwhshre1n4t6"]

[ext_resource type="Script" path="res://addons/dialogic/Editor/Events/Fields/ComplexPicker.gd" id="1"]
[ext_resource type="Theme" uid="uid://d3g4i4dshtdpu" path="res://addons/dialogic/Editor/Events/styles/InputFieldsStyle.tres" id="2_lcu5c"]
[ext_resource type="StyleBox" uid="uid://c8k6tbipodsg" path="res://addons/dialogic/Editor/Events/styles/ResourceMenuPanelBackground.tres" id="3_66uah"]

[sub_resource type="Image" id="Image_by40g"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_vnmqh"]
content_margin_left = 25.0
content_margin_top = 5.0
content_margin_right = 25.0
content_margin_bottom = 5.0
bg_color = Color(0.113725, 0.121569, 0.145098, 1)
border_width_left = 1
border_width_top = 1
border_width_right = 1
border_width_bottom = 1
border_color = Color(0.0784314, 0.0862745, 0.101961, 1)
corner_radius_top_left = 3
corner_radius_top_right = 3
corner_radius_bottom_right = 3
corner_radius_bottom_left = 3

[sub_resource type="Image" id="Image_g62mn"]
data = {
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
"format": "RGBA8",
Expand All @@ -12,8 +29,8 @@ data = {
"width": 16
}

[sub_resource type="ImageTexture" id="ImageTexture_2kfue"]
image = SubResource("Image_by40g")
[sub_resource type="ImageTexture" id="ImageTexture_2yvt7"]
image = SubResource("Image_g62mn")

[node name="ComplexPicker" type="HBoxContainer"]
custom_minimum_size = Vector2(200, 0)
Expand All @@ -35,9 +52,11 @@ offset_right = 195.0
offset_bottom = 33.0
size_flags_horizontal = 3
size_flags_vertical = 4
focus_next = NodePath("Suggestions")
mouse_filter = 1
theme = ExtResource("2_lcu5c")
theme_override_styles/normal = SubResource("StyleBoxFlat_vnmqh")
theme_override_styles/focus = SubResource("StyleBoxFlat_vnmqh")
theme_override_styles/read_only = SubResource("StyleBoxFlat_vnmqh")
placeholder_text = "Select Resource"
expand_to_text_length = true
caret_blink = true
Expand All @@ -51,18 +70,32 @@ offset_right = 33.0
ignore_texture_size = true
stretch_mode = 3

[node name="Suggestions" type="PopupMenu" parent="Search"]
[node name="Suggestions3" type="PopupMenu" parent="Search"]
handle_input_locally = false
allow_search = false

[node name="Suggestions" type="ItemList" parent="Search"]
unique_name_in_owner = true
visible = false
top_level = true
custom_minimum_size = Vector2(100, 0)
offset_left = -5.0
offset_right = 95.0
offset_bottom = 104.0
theme_override_styles/bg = ExtResource("3_66uah")
max_text_lines = 3
auto_height = true
item_count = 1
item_0/text = ""

[node name="SelectButton" type="Button" parent="Search"]
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 0
toggle_mode = true
shortcut_in_tooltip = false
icon = SubResource("ImageTexture_2kfue")
icon = SubResource("ImageTexture_2yvt7")
flat = true

[node name="RightText" type="Label" parent="."]
Expand Down
109 changes: 109 additions & 0 deletions addons/dialogic/Editor/Events/Fields/ConditionPicker.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
@tool
extends Control

var property_name : String
signal value_changed

var operators = {'==':0, '<':1, '>':2, '<=':3, '>=':4, '!=':5}

func _ready():
%ToggleComplex.icon = get_theme_icon("Enum", "EditorIcons")

%Value1.resource_icon = get_theme_icon("ClassList", "EditorIcons")
%Value1.get_suggestions_func = [self, 'get_value1_suggestions']
%Value1.value_changed.connect(something_changed)

%Operator.item_selected.connect(something_changed)

%Value2.resource_icon = get_theme_icon("Variant", "EditorIcons")
%Value2.get_suggestions_func = [self, 'get_value2_suggestions']
%Value2.value_changed.connect(something_changed)

func set_right_text(value:String):
$RightText.text = str(value)
$RightText.visible = !value.is_empty()

func set_left_text(value:String):
$LeftText.text = str(value)
$LeftText.visible = !value.is_empty()

func set_value(value:String):
var too_complex = is_too_complex(value)
%ToggleComplex.disabled = too_complex
%ToggleComplex.button_pressed = too_complex
%ComplexEditor.visible = too_complex
%SimpleEditor.visible = !too_complex
%ComplexEditor.text = value
if not too_complex:
var data = complex2simple(value)
%Value1.set_value(data[0])
%Operator.select(operators[data[1]])
%Value2.set_value(data[2])

func something_changed(fake_arg1=null, fake_arg2 = null):
if %ComplexEditor.visible:
value_changed.emit(property_name, %ComplexEditor.text)
elif %SimpleEditor.visible:
value_changed.emit(property_name, simple2complex(%Value1.current_value, %Operator.get_item_text(%Operator.selected), %Value2.current_value))

func is_too_complex(condition:String) -> bool:
return !condition.is_empty() and len(condition.split(' ', false)) != 3

func complex2simple(condition:String) -> Array:
if is_too_complex(condition):
return ['', '==','']
return Array(condition.split(' ', false))

func simple2complex(value1, operator, value2) -> String:
if value1 == null: value1 = ''
if value1.is_empty():
return ''
if value2 == null: value2 = ''
return value1 +" "+ operator +" "+ value2

func _on_toggle_complex_toggled(button_pressed) -> void:
if button_pressed:
%ComplexEditor.show()
%SimpleEditor.hide()
%ComplexEditor.text = simple2complex(%Value1.current_value, %Operator.get_item_text(%Operator.selected), %Value2.current_value)
else:
if !is_too_complex(%ComplexEditor.text):
%ComplexEditor.hide()
%SimpleEditor.show()
var data = complex2simple(%ComplexEditor.text)
%Value1.set_value(data[0])
%Operator.select(operators[data[1]])
%Value2.set_value(data[2])

func _on_complex_editor_text_changed(new_text):
%ToggleComplex.disabled = is_too_complex(%ComplexEditor.text)
something_changed()

func get_value1_suggestions(filter:String) -> Dictionary:
var suggestions = {}
if filter:
suggestions[filter] = {'value':filter, 'editor_icon':["GuiScrollArrowRight", "EditorIcons"]}
var vars = DialogicUtil.get_project_setting('dialogic/variables', {})
for var_path in list_variables(vars):
if filter.is_empty() or filter.to_lower() in var_path.to_lower():
suggestions[var_path] = {'value':'{'+var_path+"}", 'editor_icon':["ClassList", "EditorIcons"]}
return suggestions

func list_variables(dict, path = "") -> Array:
var array = []
for key in dict.keys():
if typeof(dict[key]) == TYPE_DICTIONARY:
array.append_array(list_variables(dict[key], path+key+"."))
else:
array.append(path+key)
return array

func get_value2_suggestions(filter:String) -> Dictionary:
var suggestions = {}
if filter:
suggestions[filter] = {'value':filter, 'editor_icon':["GuiScrollArrowRight", "EditorIcons"]}
var vars = DialogicUtil.get_project_setting('dialogic/variables', {})
for var_path in list_variables(vars):
if filter.is_empty() or filter.to_lower() in var_path.to_lower():
suggestions[var_path] = {'value':'{'+var_path+"}", 'editor_icon':["ClassList", "EditorIcons"]}
return suggestions
Loading

0 comments on commit 9258872

Please sign in to comment.