In RPG #26 - Objects dock I’ve implemented a dock to show all resources of the game. Having that implemented already gives me access to Godot’s Inspector which allows me to edit any selected resource. This saves me some time having to write custom forms for each resource.
In order to make the inspector a little more useful I decided to implement a couple of generic custom editors for the Inspector.
I’ve followed Inspector plugins to do the first implementation.
ValidatedLineEdit
First I created the ValidatedLineEdit
which is generic editor using a LineEdit
with the additional feature that it can validate its current value.
extends EditorProperty
const ErrorFieldStyle = preload('res://addons/dod_editor/inspector_editors/error_field.tres')
var line_edit_control := LineEdit.new()
var current_value := ""
var updating := false
func _init():
add_child(line_edit_control)
add_focusable(line_edit_control)
line_edit_control.text = current_value
line_edit_control.connect("text_changed", self, "_on_text_changed")
func _on_text_changed(new_text: String) -> void:
# Ignore the signal if the property is currently being updated.
if updating:
return
# Set the current value
current_value = new_text
emit_changed(get_edited_property(), current_value)
# Validate the current value
if not _is_valid(current_value):
line_edit_control.add_stylebox_override('focus', ErrorFieldStyle)
line_edit_control.add_stylebox_override('normal', ErrorFieldStyle)
else:
line_edit_control.add_stylebox_override('focus', null)
line_edit_control.add_stylebox_override('normal', null)
func update_property():
# Read the current value from the property.
var new_value = get_edited_object()[get_edited_property()]
if (new_value == current_value):
return
# Update the control with the new value.
updating = true
current_value = new_value
line_edit_control.text = str(current_value)
updating = false
func _is_valid(current_value: String) -> bool:
return true
This custom editor will call _is_valid()
every time the value is changed.
This function is designed to be overriden by inherited editors to do some actual verification.
RegExValidatedLineEdit
I then implemented a flexible validated editor that validates field values according to a regular expression. The value is only considered valid when it matches the regular expression.
extends "res://addons/dod_editor/inspector_editors/ValidatedLineEdit.gd"
var compiled_regular_expression: RegEx
func _init(regular_expression: String) -> void:
compiled_regular_expression = RegEx.new()
compiled_regular_expression.compile(regular_expression)
func _is_valid(current_value: String) -> bool:
return compiled_regular_expression.search(current_value) != null
LoadedModuleResourceValidatedLineEdit
An editor more specific to my game is the LoadedModuleResourceValidatedLineEdit
.
This editor considers the value as valid if the current value matches with the resource_field
of any resource of the type resource_type
.
For example, a field could validate if the value matches with the id
field of a loaded map
resource.
This is very useful for e.g. markers
which refer to a map
by their id
field.
extends "res://addons/dod_editor/inspector_editors/ValidatedLineEdit.gd"
var plugin: EditorPlugin
var resource_type: String
var resource_field: String
func _init(plugin: EditorPlugin, resource_type: String, resource_field: String) -> void:
self.plugin = plugin
self.resource_type = resource_type
self.resource_field = resource_field
func _is_valid(current_value: String) -> bool:
var loaded_modules = plugin.objects_dock.loaded_modules
for loaded_module_id in loaded_modules:
var loaded_module = loaded_modules[loaded_module_id]
var resources = loaded_module.get(resource_type)
if resources:
for resource in resources:
var resource_field_value = resource.get(resource_field)
if resource_field_value == current_value:
return true
return false
Conclusion
Implementing a custom EditorProperty
was quite simple.
While the new editors that I’ve introduced are quite simple, they make sure that I can only enter valid values.
Now that I know how to implemented custom editors also opens up the possibility to implement more advanced ones. One idea that I’m keen to try is implementing a custom editor for container items for example.