Cleaned up hierarchy
Before Width: | Height: | Size: 939 B After Width: | Height: | Size: 939 B |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 111 B After Width: | Height: | Size: 111 B |
Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 248 B |
Before Width: | Height: | Size: 200 B After Width: | Height: | Size: 200 B |
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 346 B |
Before Width: | Height: | Size: 267 B After Width: | Height: | Size: 267 B |
Before Width: | Height: | Size: 170 B After Width: | Height: | Size: 170 B |
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 268 B |
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 269 B |
Before Width: | Height: | Size: 140 B After Width: | Height: | Size: 140 B |
Before Width: | Height: | Size: 392 B After Width: | Height: | Size: 392 B |
Before Width: | Height: | Size: 409 B After Width: | Height: | Size: 409 B |
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
Before Width: | Height: | Size: 160 B After Width: | Height: | Size: 160 B |
Before Width: | Height: | Size: 252 B After Width: | Height: | Size: 252 B |
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B |
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 134 KiB |
46
demo/Shop.tscn
Normal file
@ -0,0 +1,46 @@
|
||||
[gd_scene load_steps=3 format=1]
|
||||
|
||||
[ext_resource path="res://World.gd" type="Script" id=1]
|
||||
[ext_resource path="res://ShopDialog.tscn" type="PackedScene" id=2]
|
||||
|
||||
[node name="World" type="Node2D"]
|
||||
|
||||
script/script = ExtResource( 1 )
|
||||
|
||||
[node name="ShopButtons" type="VButtonArray" parent="."]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 465.0
|
||||
margin/top = 43.0
|
||||
margin/right = 600.0
|
||||
margin/bottom = 191.0
|
||||
flat = false
|
||||
button/count = 0
|
||||
button/min_button_size = -1.0
|
||||
button/align = 437
|
||||
|
||||
[node name="ShopDialog" parent="." instance=ExtResource( 2 )]
|
||||
|
||||
visibility/visible = false
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 189.0
|
||||
margin/bottom = 14.0
|
||||
text = "Open this scene to test items and shops."
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[connection signal="button_selected" from="ShopButtons" to="." method="_on_ShopButtons_button_selected"]
|
||||
|
||||
|
23
demo/ShopDialog.gd
Normal file
@ -0,0 +1,23 @@
|
||||
extends WindowDialog
|
||||
|
||||
onready var item_list = get_node("VBoxContainer/ItemList")
|
||||
|
||||
|
||||
func create_shop(merchant):
|
||||
var items_of_this_merchant = []
|
||||
var all_shop_items = data.get_items("shop_item")
|
||||
for shop_item in all_shop_items.values():
|
||||
if shop_item.seller == merchant.name:
|
||||
items_of_this_merchant.append(shop_item)
|
||||
|
||||
var i = 0
|
||||
item_list.clear()
|
||||
for shop_item in items_of_this_merchant:
|
||||
item_list.add_item(shop_item.name)
|
||||
item_list.set_item_metadata(i, shop_item)
|
||||
i = i + 1
|
||||
|
||||
get_node("VBoxContainer/MerchantLabel").set_bbcode(merchant.name)
|
||||
get_node("VBoxContainer/GreetingLabel").set_text(merchant.greeting)
|
||||
|
||||
|
75
demo/ShopDialog.tscn
Normal file
@ -0,0 +1,75 @@
|
||||
[gd_scene load_steps=2 format=1]
|
||||
|
||||
[ext_resource path="res://ShopDialog.gd" type="Script" id=1]
|
||||
|
||||
[node name="WindowDialog" type="WindowDialog"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 316.0
|
||||
margin/bottom = 288.0
|
||||
popup/exclusive = false
|
||||
window/title = ""
|
||||
script/script = ExtResource( 1 )
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 0.0
|
||||
margin/bottom = 0.0
|
||||
alignment = 0
|
||||
|
||||
[node name="MerchantLabel" type="RichTextLabel" parent="VBoxContainer"]
|
||||
|
||||
rect/min_size = Vector2( 0, 30 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 316.0
|
||||
margin/bottom = 30.0
|
||||
custom_colors/default_color = Color( 1, 0, 0, 1 )
|
||||
bbcode/enabled = false
|
||||
bbcode/bbcode = "<<MERCHANT>>"
|
||||
visible_characters = -1
|
||||
|
||||
[node name="GreetingLabel" type="Label" parent="VBoxContainer"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 34.0
|
||||
margin/right = 316.0
|
||||
margin/bottom = 48.0
|
||||
text = "<<GREETING>>"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="ItemList" type="ItemList" parent="VBoxContainer"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 52.0
|
||||
margin/right = 316.0
|
||||
margin/bottom = 288.0
|
||||
|
||||
|
19
demo/ShopTest.gd
Normal file
@ -0,0 +1,19 @@
|
||||
extends Node2D
|
||||
|
||||
onready var buttons_array = get_node("ShopButtons")
|
||||
onready var shop_dialog = get_node("ShopDialog")
|
||||
|
||||
|
||||
func _ready():
|
||||
var shop_types = ["Armor Shop", "Weapon Shop", "Inn", "Travelling Salesman"]
|
||||
for shop_type in shop_types:
|
||||
buttons_array.add_button(shop_type)
|
||||
|
||||
|
||||
func _on_ShopButtons_button_selected( button_idx ):
|
||||
var text = buttons_array.get_button_text(button_idx)
|
||||
var all_merchants = data.get_items("merchant")
|
||||
for merchant in all_merchants.values():
|
||||
if merchant.name == text:
|
||||
shop_dialog.create_shop(merchant)
|
||||
shop_dialog.popup_centered()
|
46
demo/ShopTest.tscn
Normal file
@ -0,0 +1,46 @@
|
||||
[gd_scene load_steps=3 format=1]
|
||||
|
||||
[ext_resource path="res://ShopTest.gd" type="Script" id=1]
|
||||
[ext_resource path="res://ShopDialog.tscn" type="PackedScene" id=2]
|
||||
|
||||
[node name="World" type="Node2D"]
|
||||
|
||||
script/script = ExtResource( 1 )
|
||||
|
||||
[node name="ShopButtons" type="VButtonArray" parent="."]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 465.0
|
||||
margin/top = 43.0
|
||||
margin/right = 600.0
|
||||
margin/bottom = 191.0
|
||||
flat = false
|
||||
button/count = 0
|
||||
button/min_button_size = -1.0
|
||||
button/align = 437
|
||||
|
||||
[node name="ShopDialog" parent="." instance=ExtResource( 2 )]
|
||||
|
||||
visibility/visible = false
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 189.0
|
||||
margin/bottom = 14.0
|
||||
text = "Open this scene to test items and shops."
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[connection signal="button_selected" from="ShopButtons" to="." method="_on_ShopButtons_button_selected"]
|
||||
|
||||
|
30
demo/Spellbook.gd
Normal file
@ -0,0 +1,30 @@
|
||||
extends Panel
|
||||
|
||||
onready var spell_list = get_node("LeftVBox/ScrollContainer/SpellList")
|
||||
|
||||
var icon_spell_unknown = preload("res://graphics/icon_spell_unknown.png")
|
||||
|
||||
func _ready():
|
||||
var all_spells = data.get_items("spell")
|
||||
var i = 0
|
||||
for spell in all_spells.values():
|
||||
var icon = null
|
||||
if spell.icon:
|
||||
icon = load(spell.icon)
|
||||
else:
|
||||
icon = icon_spell_unknown
|
||||
spell_list.add_item(spell.name, icon)
|
||||
spell_list.set_item_tooltip(i, spell.name)
|
||||
spell_list.set_item_metadata(i, spell)
|
||||
i = i + 1
|
||||
|
||||
spell_list.select(0)
|
||||
_on_SpellList_item_selected(0)
|
||||
|
||||
func _on_SpellList_item_selected( index ):
|
||||
var spell = spell_list.get_item_metadata(index)
|
||||
get_node("RightVBox/SkillName").set_text(spell.name)
|
||||
get_node("RightVBox/Description").set_text(spell.description)
|
||||
var element = data.get_item("element", spell.element)
|
||||
get_node("RightVBox/Type").set_bbcode("[color=#" + element.color.to_html() + "]" + element.name + "[/color]")
|
||||
get_node("RightVBox/BaseDamage").set_text("Base Damage: " + str(spell.base_damage))
|
162
demo/Spellbook.tscn
Normal file
@ -0,0 +1,162 @@
|
||||
[gd_scene load_steps=3 format=1]
|
||||
|
||||
[ext_resource path="res://Spellbook.gd" type="Script" id=1]
|
||||
[ext_resource path="res://title_font.fnt" type="BitmapFont" id=2]
|
||||
|
||||
[node name="Panel" type="Panel"]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 0.0
|
||||
margin/bottom = 0.0
|
||||
script/script = ExtResource( 1 )
|
||||
|
||||
[node name="LeftVBox" type="VBoxContainer" parent="."]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 200.0
|
||||
margin/bottom = 600.0
|
||||
alignment = 0
|
||||
|
||||
[node name="Label" type="Label" parent="LeftVBox"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 200.0
|
||||
margin/bottom = 21.0
|
||||
custom_fonts/font = ExtResource( 2 )
|
||||
text = "Spellbook"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="LeftVBox"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 25.0
|
||||
margin/right = 200.0
|
||||
margin/bottom = 600.0
|
||||
scroll/horizontal = true
|
||||
scroll/vertical = true
|
||||
|
||||
[node name="SpellList" type="ItemList" parent="LeftVBox/ScrollContainer"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 200.0
|
||||
margin/bottom = 575.0
|
||||
|
||||
[node name="RightVBox" type="VBoxContainer" parent="."]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 270.0
|
||||
margin/top = 20.0
|
||||
margin/right = 0.0
|
||||
margin/bottom = 0.0
|
||||
alignment = 0
|
||||
|
||||
[node name="SkillName" type="Label" parent="RightVBox"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 754.0
|
||||
margin/bottom = 21.0
|
||||
custom_fonts/font = ExtResource( 2 )
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="Description" type="Label" parent="RightVBox"]
|
||||
|
||||
rect/min_size = Vector2( 0, 100 )
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 25.0
|
||||
margin/right = 754.0
|
||||
margin/bottom = 125.0
|
||||
autowrap = true
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="Type" type="RichTextLabel" parent="RightVBox"]
|
||||
|
||||
rect/min_size = Vector2( 0, 20 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 129.0
|
||||
margin/right = 754.0
|
||||
margin/bottom = 149.0
|
||||
bbcode/enabled = true
|
||||
bbcode/bbcode = ""
|
||||
visible_characters = -1
|
||||
|
||||
[node name="BaseDamage" type="Label" parent="RightVBox"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 153.0
|
||||
margin/right = 754.0
|
||||
margin/bottom = 167.0
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 247.0
|
||||
margin/bottom = 14.0
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[connection signal="item_selected" from="LeftVBox/ScrollContainer/SpellList" to="." method="_on_SpellList_item_selected"]
|
||||
|
||||
|
17
demo/addons/godot_data_editor/.gitattributes
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
114
demo/addons/godot_data_editor/README.md
Normal file
@ -0,0 +1,114 @@
|
||||
# Godot Data Editor
|
||||
This repository hosts a plugin for the [Godot Engine]. It allows users to enter data items based on Godot classes which are then serialized in either as json or binaries. Serialized items may be encrypted if desired.
|
||||
|
||||
# Features
|
||||
* Support for binary or json serialization
|
||||
* Create data classes with the click of a button
|
||||
* Use gdscript to add properties and logic to your data classes, all instances will be Nodes
|
||||
* Make use of the built-in [export property hints]
|
||||
* Add instance-specific custom properties
|
||||
* Access data with a simple API using the _data_ singleton
|
||||
* ALPHA: Use the notification/observer system to react to changes in data items
|
||||
* ALPHA: Encrypt your data files
|
||||
|
||||
# Screenshots
|
||||
![editor_screenshot]
|
||||
![class_screenshot]
|
||||
|
||||
# Installation
|
||||
* Open your project folder, e.g. "../MyGame/"
|
||||
* Create a folder named "addons" (if not already present)
|
||||
* In addons, create a folder named "godot_data_editor"
|
||||
* Copy the content of this repository into it. You may remove the "sceenshots" ;)
|
||||
* Open your project in the editor and navigate to the plugin (Scene -> Project Settings -> Plugins)
|
||||
* The plugin "godot_data_editor" should now appear, change the status from "Inactive" to "Active"
|
||||
* Restart the editor to make sure that the _data_ singleton is loaded properly
|
||||
|
||||
I intend to upload the plugin to the AssetLib, once I feel it is stable enough.
|
||||
|
||||
# System Requirements
|
||||
The plugin was written for version *2.1.3* of the Godot Engine. Upcoming minor versions should be supported as well.
|
||||
It is very likely that a number of changes will be necessary, once Godot 3 is released.
|
||||
|
||||
# API / Tutorial
|
||||
I created a little video which shows how to use the plugin to create a simple shop system: [[Link to video which does not exist yet :) ]]
|
||||
|
||||
Working with data is rather simple, use the provided _data_ class to access the items. The following code snippets demonstrates item retrieval as well as the observation feature:
|
||||
```gdscript
|
||||
extends Node
|
||||
|
||||
func _ready():
|
||||
# Get a single item
|
||||
var herb = data.get_item("shop_item", "herb")
|
||||
var price = herb.price
|
||||
|
||||
# Get all items as dictionary (key: id, value: item)
|
||||
var shop_items = data.get_items("shop_item")
|
||||
for shop_item in shop_items.values():
|
||||
print(shop_item.price)
|
||||
pass
|
||||
|
||||
#######################################
|
||||
# Observe Properties:
|
||||
# Please note that you currently have to update properties using the "update_property" to make use of this feature
|
||||
#######################################
|
||||
|
||||
# Be notified when something about this herb changes
|
||||
data.observe_item(self, herb, "herb_changed")
|
||||
herb.update_property("name", "better_herb")
|
||||
|
||||
# Be notified when the price of this herb changes,
|
||||
data.observe_item_property(self, herb, "price", "herb_price_changed")
|
||||
herb.update_property("price", 500)
|
||||
|
||||
# Be notified when any item changes
|
||||
var doge_axe = data.get_item("shop_item", "doge_axe")
|
||||
data.observe_class(self, "shop_item", "shop_item_changed")
|
||||
doge_axe.update_property("price", 500)
|
||||
|
||||
# Overkill: be notified about everything
|
||||
data.observe_all_changes(self, "something_changed")
|
||||
|
||||
#######################################
|
||||
# Stop Observing:
|
||||
# When you are no longer interested in updates, simply unsubscribe/stop observing
|
||||
#######################################
|
||||
data.stop_observing_item_property(self, herb, "price")
|
||||
data.stop_observing_item(self, herb)
|
||||
data.stop_observing_class(self, "shop_item")
|
||||
data.stop_observing_changes(self)
|
||||
|
||||
|
||||
func herb_changed(item, property, value):
|
||||
print("Something about this herb changed!")
|
||||
|
||||
func herb_price_changed(item, property, value):
|
||||
print("Herb price changed!")
|
||||
|
||||
func shop_item_changed(item, property, value):
|
||||
print(item.name + " changed! " + property + " : " + str(value))
|
||||
|
||||
func something_changed(item, property, value):
|
||||
print("I guess something changed.")
|
||||
```
|
||||
|
||||
# Please Contribute!
|
||||
Please feel free to contribute. Unfortunately, the code base still is not documented that well and there are a number of bugs which will need to be ironed out. I am sure that there are many things I have been doing wrong, especially in regard to memory management.
|
||||
|
||||
# Known Issues
|
||||
* The "Rename Class" feature may not properly rename the class file if it still in use
|
||||
* In some cases, the controls are not correctly resized - pressing "Reload" should usually do the trick though
|
||||
* There is no support for undo/redo
|
||||
* Pressing Ctrl+S will not save the data items but the current scene
|
||||
* The _data_ singleton is only visible in the editor when the project is being restarted. This seems to be a limitation of the engine which does not allow reload the engine.cfg file
|
||||
* The "class overview" screen is lacking any kind of useful content
|
||||
|
||||
# HALP! Something went wrong!
|
||||
Stay calm, most issues can be resolved by either pressing the "Reload" button or activating and deactivating the plugin. If the problem persists, there is likely an issue with your data. Check if the name of the class (which are stored in the "classes" folder by default) is the same as the folder name of your instances (by default called "data"). If this is the case, there might be a conflict with duplicate IDs or the like. Please post an issue here if this happened without any external influence (e.g. you edited the files manually in another editor).
|
||||
|
||||
|
||||
|
||||
[Godot Engine]: <https://github.com/godotengine/godot>
|
||||
[export property hints]: <http://docs.godotengine.org/en/latest/learning/scripting/gdscript/gdscript_basics.html#exports>
|
||||
[editor_screenshot]: https://github.com/Stoeoeoe/godot_data_editor/blob/master/screenshots/editor.png "The Godot Data Editor"
|
||||
[class_screenshot]: https://github.com/Stoeoeoe/godot_data_editor/blob/master/screenshots/class.png "Example Class"
|
10
demo/addons/godot_data_editor/class_overview.gd
Normal file
@ -0,0 +1,10 @@
|
||||
tool
|
||||
extends PanelContainer
|
||||
|
||||
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
|
||||
func set_label(text):
|
||||
get_node("Panel/Body/Label").set_text(text)
|
163
demo/addons/godot_data_editor/class_overview.tscn
Normal file
@ -0,0 +1,163 @@
|
||||
[gd_scene load_steps=4 format=1]
|
||||
|
||||
[ext_resource path="res://addons/godot_data_editor/class_overview.gd" type="Script" id=1]
|
||||
[ext_resource path="res://addons/godot_data_editor/style/light_gray_panel.tres" type="StyleBox" id=2]
|
||||
[ext_resource path="res://addons/godot_data_editor/fonts/droid_serif_bold.tres" type="DynamicFont" id=3]
|
||||
|
||||
[node name="ClassOverview" type="PanelContainer"]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 0.0
|
||||
margin/bottom = 0.0
|
||||
script/script = ExtResource( 1 )
|
||||
|
||||
[node name="Panel" type="Panel" parent="."]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 7.0
|
||||
margin/top = 7.0
|
||||
margin/right = 1273.0
|
||||
margin/bottom = 593.0
|
||||
custom_styles/panel = ExtResource( 2 )
|
||||
|
||||
[node name="Body" type="VBoxContainer" parent="Panel"]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 10.0
|
||||
margin/top = 10.0
|
||||
margin/right = 10.0
|
||||
margin/bottom = 10.0
|
||||
alignment = 0
|
||||
|
||||
[node name="ClassPropertiesLabel" type="Label" parent="Panel/Body"]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1246.0
|
||||
margin/bottom = 19.0
|
||||
custom_fonts/font = ExtResource( 3 )
|
||||
text = "Static Class Properties"
|
||||
uppercase = true
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="Panel/Body"]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1246.0
|
||||
margin/bottom = 3.0
|
||||
|
||||
[node name="Control" type="Control" parent="Panel/Body"]
|
||||
|
||||
rect/min_size = Vector2( 0, 15 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1246.0
|
||||
margin/bottom = 15.0
|
||||
|
||||
[node name="Scroll" type="ScrollContainer" parent="Panel/Body"]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 19.0
|
||||
margin/right = 1246.0
|
||||
margin/bottom = 566.0
|
||||
scroll/horizontal = true
|
||||
scroll/vertical = true
|
||||
|
||||
[node name="Statics" type="VBoxContainer" parent="Panel/Body/Scroll"]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1246.0
|
||||
margin/bottom = 0.0
|
||||
alignment = 0
|
||||
|
||||
[node name="NoStaticsPropertiesLabel" type="Label" parent="Panel/Body/Scroll/Statics"]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1246.0
|
||||
margin/bottom = 14.0
|
||||
text = "There are no static properties for this class. Click below to add one."
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="AddStaticPropertyButton" type="Button" parent="Panel/Body/Scroll/Statics"]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 18.0
|
||||
margin/right = 1246.0
|
||||
margin/bottom = 38.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Add static property"
|
||||
flat = false
|
||||
|
||||
[node name="Label" type="Label" parent="Panel/Body"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 19.0
|
||||
margin/right = 1246.0
|
||||
margin/bottom = 33.0
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
|
50
demo/addons/godot_data_editor/class_properties.gd
Normal file
@ -0,0 +1,50 @@
|
||||
tool
|
||||
extends Panel
|
||||
|
||||
var property_item_class = preload("property_item.tscn")
|
||||
|
||||
onready var class_properties_box = get_node("Body/Scroll/ClassProperties")
|
||||
onready var no_class_properties_label = get_node("Body/Scroll/ClassProperties/NoClassPropertiesLabel")
|
||||
|
||||
var item = null
|
||||
|
||||
signal on_item_changed(item)
|
||||
|
||||
|
||||
func build_properties(item):
|
||||
self.item = item
|
||||
for node in class_properties_box.get_children():
|
||||
if node.has_meta("property"):
|
||||
class_properties_box.remove_child(node)
|
||||
|
||||
|
||||
var number_of_properties = 0
|
||||
for property in item.get_property_list():
|
||||
if property["usage"] == (PROPERTY_USAGE_SCRIPT_VARIABLE + PROPERTY_USAGE_STORAGE + PROPERTY_USAGE_EDITOR + PROPERTY_USAGE_NETWORK):
|
||||
no_class_properties_label.hide()
|
||||
number_of_properties += 1
|
||||
var property_item = property_item_class.instance()
|
||||
var property_name = property["name"]
|
||||
var value = item.get(property_name)
|
||||
property_item.initialize(property_name, property["type"], value, property["hint"], property["hint_string"])
|
||||
property_item.connect("property_item_load_button_down", self, "_property_item_requests_file_dialog", [])
|
||||
var changed_values = []
|
||||
property_item.connect("on_property_value_changed", self, "item_changed", changed_values)
|
||||
property_item.set_meta("property", true)
|
||||
class_properties_box.add_child(property_item)
|
||||
pass
|
||||
if number_of_properties == 0:
|
||||
no_class_properties_label.show()
|
||||
|
||||
|
||||
func item_changed(property, value):
|
||||
if item:
|
||||
item.set(property, value)
|
||||
emit_signal("on_item_changed", item)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
116
demo/addons/godot_data_editor/class_properties.tscn
Normal file
@ -0,0 +1,116 @@
|
||||
[gd_scene load_steps=4 format=1]
|
||||
|
||||
[ext_resource path="res://addons/godot_data_editor/style/light_gray_panel.tres" type="StyleBox" id=1]
|
||||
[ext_resource path="res://addons/godot_data_editor/class_properties.gd" type="Script" id=2]
|
||||
[ext_resource path="res://addons/godot_data_editor/fonts/droid_serif_bold.tres" type="DynamicFont" id=3]
|
||||
|
||||
[node name="ClassProperties" type="Panel"]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 0.0
|
||||
margin/bottom = 0.0
|
||||
custom_styles/panel = ExtResource( 1 )
|
||||
script/script = ExtResource( 2 )
|
||||
|
||||
[node name="Body" type="VBoxContainer" parent="."]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 10.0
|
||||
margin/top = 10.0
|
||||
margin/right = 10.0
|
||||
margin/bottom = 10.0
|
||||
alignment = 0
|
||||
|
||||
[node name="TitleLabel" type="Label" parent="Body"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1260.0
|
||||
margin/bottom = 2.0
|
||||
custom_fonts/font = ExtResource( 3 )
|
||||
text = "Class Properties"
|
||||
uppercase = true
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="Body"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 6.0
|
||||
margin/right = 1260.0
|
||||
margin/bottom = 9.0
|
||||
|
||||
[node name="Spacer" type="Control" parent="Body"]
|
||||
|
||||
rect/min_size = Vector2( 0, 15 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 13.0
|
||||
margin/right = 1260.0
|
||||
margin/bottom = 28.0
|
||||
|
||||
[node name="Scroll" type="ScrollContainer" parent="Body"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 32.0
|
||||
margin/right = 1260.0
|
||||
margin/bottom = 580.0
|
||||
scroll/horizontal = true
|
||||
scroll/vertical = true
|
||||
|
||||
[node name="ClassProperties" type="VBoxContainer" parent="Body/Scroll"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 454.0
|
||||
margin/bottom = 14.0
|
||||
alignment = 0
|
||||
|
||||
[node name="NoClassPropertiesLabel" type="Label" parent="Body/Scroll/ClassProperties"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 454.0
|
||||
margin/bottom = 14.0
|
||||
text = "There are currently no class properties. Edit the Class to add new ones."
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
|
77
demo/addons/godot_data_editor/custom_properties.gd
Normal file
@ -0,0 +1,77 @@
|
||||
tool
|
||||
extends Panel
|
||||
|
||||
var item = null
|
||||
var property_item_class = preload("property_item.tscn")
|
||||
var remove_icon = preload("icons/icon_remove.png")
|
||||
|
||||
|
||||
onready var custom_properties_box = get_node("Body/Scroll/CustomProperties")
|
||||
onready var no_custom_properties_label = get_node("Body/Scroll/CustomProperties/NoCustomPropertiesLabel")
|
||||
|
||||
onready var item_manager = null # Item Manager, used to load, modify and save items
|
||||
|
||||
signal on_item_changed(item)
|
||||
signal new_custom_property_created
|
||||
signal custom_property_add_requested
|
||||
signal custom_property_delete_requested(custom_property_id)
|
||||
|
||||
#TODO: Somehow the properties are initialized twice
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
self.item_manager = Globals.get("item_manager")
|
||||
|
||||
func build_properties(item):
|
||||
self.item = item
|
||||
var properties = item._custom_properties
|
||||
for node in custom_properties_box.get_children():
|
||||
if node.has_meta("property"):
|
||||
custom_properties_box.remove_child(node)
|
||||
|
||||
var number_of_properties = 0
|
||||
var property_names = properties.keys()
|
||||
property_names.sort()
|
||||
for property_name in property_names:
|
||||
no_custom_properties_label.hide()
|
||||
number_of_properties += 1
|
||||
|
||||
var container = MarginContainer.new()
|
||||
var property_item = property_item_class.instance()
|
||||
var type = properties[property_name][0]
|
||||
|
||||
# If there already is a value, read it, otherwise set it to null
|
||||
var value = null
|
||||
if properties[property_name].size() == 2:
|
||||
value = properties[property_name][1]
|
||||
|
||||
property_item.initialize(property_name, type, value, 0, "", true)
|
||||
property_item.connect("custom_property_delete_requested", self, "emit_signal", ["custom_property_delete_requested", property_name, ])
|
||||
property_item.connect("property_item_load_button_down", self, "_property_item_requests_file_dialog", [])
|
||||
var changed_values = []
|
||||
property_item.connect("on_property_value_changed", self, "item_changed", changed_values)
|
||||
|
||||
container.set_meta("property", true)
|
||||
container.add_child(property_item)
|
||||
custom_properties_box.add_child(container)
|
||||
|
||||
pass
|
||||
if number_of_properties == 0:
|
||||
no_custom_properties_label.show()
|
||||
|
||||
|
||||
# Fires signal when the item's custom properties is to be updated, delegates to data_editor_gui.
|
||||
func item_changed(property, value):
|
||||
if item:
|
||||
item._custom_properties[property][1] = value
|
||||
emit_signal("on_item_changed", item)
|
||||
|
||||
|
||||
# Delegates the deletion
|
||||
func delete_custom_property(property_name):
|
||||
emit_signal("custom_property_delete_requested", property_name)
|
||||
|
||||
|
||||
# Fires signal when the item's custom properties is to be updated, delegates to data_editor_gui.func _on_NewCustomPropertyButton_button_down():
|
||||
func _on_NewCustomPropertyButton_button_down():
|
||||
emit_signal("custom_property_add_requested")
|
134
demo/addons/godot_data_editor/custom_properties.tscn
Normal file
@ -0,0 +1,134 @@
|
||||
[gd_scene load_steps=4 format=1]
|
||||
|
||||
[ext_resource path="res://addons/godot_data_editor/style/light_gray_panel.tres" type="StyleBox" id=1]
|
||||
[ext_resource path="res://addons/godot_data_editor/custom_properties.gd" type="Script" id=2]
|
||||
[ext_resource path="res://addons/godot_data_editor/fonts/droid_serif_bold.tres" type="DynamicFont" id=3]
|
||||
|
||||
[node name="Panel" type="Panel"]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 0.0
|
||||
margin/bottom = 0.0
|
||||
custom_styles/panel = ExtResource( 1 )
|
||||
script/script = ExtResource( 2 )
|
||||
|
||||
[node name="Body" type="VBoxContainer" parent="."]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 10.0
|
||||
margin/top = 10.0
|
||||
margin/right = 10.0
|
||||
margin/bottom = 10.0
|
||||
alignment = 0
|
||||
|
||||
[node name="TitleLabel" type="Label" parent="Body"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1260.0
|
||||
margin/bottom = 2.0
|
||||
custom_fonts/font = ExtResource( 3 )
|
||||
text = "Custom Properties"
|
||||
uppercase = true
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="Body"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 6.0
|
||||
margin/right = 1260.0
|
||||
margin/bottom = 9.0
|
||||
|
||||
[node name="Spacer" type="Control" parent="Body"]
|
||||
|
||||
rect/min_size = Vector2( 0, 15 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 13.0
|
||||
margin/right = 1260.0
|
||||
margin/bottom = 28.0
|
||||
|
||||
[node name="Scroll" type="ScrollContainer" parent="Body"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 32.0
|
||||
margin/right = 1260.0
|
||||
margin/bottom = 556.0
|
||||
scroll/horizontal = true
|
||||
scroll/vertical = true
|
||||
|
||||
[node name="CustomProperties" type="VBoxContainer" parent="Body/Scroll"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 441.0
|
||||
margin/bottom = 524.0
|
||||
alignment = 0
|
||||
|
||||
[node name="NoCustomPropertiesLabel" type="Label" parent="Body/Scroll/CustomProperties"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 441.0
|
||||
margin/bottom = 14.0
|
||||
text = "There are no custom properties for this item. Click below to add one."
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="NewCustomPropertyButton" type="Button" parent="Body"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 560.0
|
||||
margin/right = 1260.0
|
||||
margin/bottom = 580.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Add new custom property"
|
||||
flat = false
|
||||
|
||||
[connection signal="button_down" from="Body/NewCustomPropertyButton" to="." method="_on_NewCustomPropertyButton_button_down"]
|
||||
|
||||
|
138
demo/addons/godot_data_editor/data.gd
Normal file
@ -0,0 +1,138 @@
|
||||
extends Node
|
||||
|
||||
var item_manager = null
|
||||
var items = {}
|
||||
var values = {}
|
||||
|
||||
|
||||
func _init():
|
||||
# Caution: This item manager may not be in sync with the one used by the editor
|
||||
self.item_manager = preload("item_manager.gd").new()
|
||||
self.items = item_manager.items
|
||||
|
||||
|
||||
func get_item(item_class, id):
|
||||
return item_manager.get_item(item_class, id)
|
||||
|
||||
|
||||
func get_items(item_class):
|
||||
return item_manager.get_items(item_class)
|
||||
|
||||
|
||||
func _load_item(item_class, id):
|
||||
items[item_class][id] = item_manager.load_item(item_class, id)
|
||||
|
||||
|
||||
func load_item_value(item, property):
|
||||
return get_progress(item._class, item._id, property)
|
||||
|
||||
|
||||
func get_progress(item_class, id, property):
|
||||
if items[item_class].has(id) and items[item_class][id].has(property):
|
||||
return items[item_class][id][property]
|
||||
|
||||
|
||||
func set_progress(item_class, id, property, value):
|
||||
var item = item_manager.get_item(item_class, id)
|
||||
var has_value = item.get(property)
|
||||
if item and has_value:
|
||||
item.set(property, value)
|
||||
if has_user_signal("@any_value_changed"):
|
||||
emit_signal("@any_value_changed", item, property, value)
|
||||
|
||||
var signal_name = ""
|
||||
signal_name = "@" + item_class
|
||||
# Class signal
|
||||
if has_user_signal(signal_name):
|
||||
emit_signal(signal_name, item, property, value)
|
||||
|
||||
# Item signal
|
||||
signal_name = "@" + item_class + "|" + id
|
||||
if has_user_signal(signal_name):
|
||||
emit_signal(signal_name, item, property, value)
|
||||
|
||||
# Property signal
|
||||
signal_name = "@" + item_class + "|" + id + "|" + property
|
||||
if has_user_signal(signal_name):
|
||||
emit_signal(signal_name, item, property, value)
|
||||
|
||||
return true
|
||||
else:
|
||||
return false
|
||||
|
||||
func observe_all_changes(observer, method, binds=[], flags = 0):
|
||||
var signal_name = "@any_value_changed"
|
||||
self.add_user_signal(signal_name) # TODO: Args
|
||||
self.connect(signal_name, observer, method, binds, flags)
|
||||
|
||||
func observe_class(observer, item_class, method, binds=[], flags = 0):
|
||||
var signal_name = "@" + item_class
|
||||
self.add_user_signal(signal_name) # TODO: Args
|
||||
self.connect(signal_name, observer, method, binds, flags)
|
||||
|
||||
func observe_item(observer, item, method, binds=[], flags = 0):
|
||||
var signal_name = "@" + item._class + "|" + item._id
|
||||
if not has_user_signal(signal_name):
|
||||
self.add_user_signal(signal_name) # TODO: Args
|
||||
self.connect(signal_name, observer, method, binds, flags)
|
||||
|
||||
|
||||
func observe_item_property(observer, item, property, method, binds=[], flags = 0):
|
||||
var signal_name = "@" + item._class + "|" + item._id + "|" + property
|
||||
if not has_user_signal(signal_name):
|
||||
self.add_user_signal(signal_name) # TODO: Args
|
||||
self.connect(signal_name, observer, method, binds, flags)
|
||||
|
||||
func _get_relevant_connections():
|
||||
var relevant_connections = []
|
||||
var signals = get_signal_list()
|
||||
for s in signals:
|
||||
var name = s["name"]
|
||||
if name.begins_with("@"):
|
||||
for c in get_signal_connection_list(name):
|
||||
relevant_connections.append(c)
|
||||
return relevant_connections
|
||||
|
||||
|
||||
func stop_observing_class(observer, item_class):
|
||||
var connection_list = _get_relevant_connections()
|
||||
for connection in connection_list:
|
||||
var target = connection["target"]
|
||||
var signal_info = connection["signal"].replace("@", "").split("|")
|
||||
if signal_info.size() == 1 and signal_info[0] == item_class and target == observer:
|
||||
self.disconnect(connection["signal"], target, connection["method"])
|
||||
|
||||
func stop_observing_item(observer, item):
|
||||
var connection_list = _get_relevant_connections()
|
||||
for connection in connection_list:
|
||||
var target = connection["target"]
|
||||
var signal_info = connection["signal"].replace("@", "").split("|")
|
||||
if signal_info.size() == 2 and signal_info[0] == item._class and signal_info[1] == item._id and target == observer:
|
||||
self.disconnect(connection["signal"], target, connection["method"])
|
||||
|
||||
func stop_observing_item_property(observer, item, property):
|
||||
var connection_list = _get_relevant_connections()
|
||||
for connection in connection_list:
|
||||
var target = connection["target"]
|
||||
var signal_info = connection["signal"].replace("@", "").split("|")
|
||||
if signal_info.size() == 3 and signal_info[0] == item._class and signal_info[1] == item._id and signal_info[2] == property and target == observer:
|
||||
self.disconnect(connection["signal"], target, connection["method"])
|
||||
|
||||
func stop_observing_changes(observer):
|
||||
var connection_list = _get_relevant_connections()
|
||||
for connection in connection_list:
|
||||
var target = connection["target"]
|
||||
if target == observer:
|
||||
self.disconnect(connection["signal"], target, connection["method"])
|
||||
|
||||
|
||||
# observer.disconnect(
|
||||
|
||||
|
||||
func set_item_progress(item, property, value):
|
||||
set_progress(item._class, item._id, property, value)
|
||||
|
||||
func get_progress_by_item(item):
|
||||
|
||||
|
||||
|
97
demo/addons/godot_data_editor/data_editor.gd
Normal file
@ -0,0 +1,97 @@
|
||||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
var data_editor_class = preload("data_editor_gui.tscn")
|
||||
var data_class = preload("data.gd")
|
||||
var gui = null
|
||||
|
||||
var all_items = {}
|
||||
|
||||
signal data_item_class_opened(item_class)
|
||||
|
||||
func _enter_tree():
|
||||
OS.set_low_processor_usage_mode(true)
|
||||
check_for_data_singleton()
|
||||
check_plugin_settings()
|
||||
gui = data_editor_class.instance()
|
||||
get_editor_viewport().add_child(gui)
|
||||
gui.set_area_as_parent_rect()
|
||||
gui.hide()
|
||||
|
||||
|
||||
# Remove control and data singleton
|
||||
func _exit_tree():
|
||||
OS.set_low_processor_usage_mode(false)
|
||||
get_editor_viewport().remove_child(gui)
|
||||
gui.free()
|
||||
var config = ConfigFile.new()
|
||||
var status = config.load("res://engine.cfg")
|
||||
if status == OK:
|
||||
if config.has_section_key("autoload", "data"):
|
||||
config.set_value("autoload", "data", null)
|
||||
config.save("res://engine.cfg")
|
||||
# Check if the Classes and Data folders exist
|
||||
Globals.clear("item_manager")
|
||||
|
||||
func _ready():
|
||||
gui.connect("class_edit_requested", self, "edit_class", [])
|
||||
Globals.set("debug_is_editor", true)
|
||||
|
||||
# Opens the selected class in the Script Editor
|
||||
func edit_class(item_class):
|
||||
edit_resource(item_class)
|
||||
|
||||
|
||||
func check_for_data_singleton():
|
||||
var config = ConfigFile.new()
|
||||
var status = config.load("res://engine.cfg")
|
||||
|
||||
|
||||
if status == OK:
|
||||
if not config.has_section_key("autoload", "data"):
|
||||
config.set_value("autoload", "data", "*res://addons/godot_data_editor/data.gd")
|
||||
config.save("res://engine.cfg")
|
||||
#var directory = Directory.new()
|
||||
#directory.copy("res://engine.cfg", "res://engine.cfg_BACKUP")
|
||||
|
||||
# Load the plugin settings and adds default if they do not exist.
|
||||
# TODO: Obtain defaults from dialog
|
||||
func check_plugin_settings():
|
||||
var config = ConfigFile.new()
|
||||
var status = config.load("res://addons/godot_data_editor/plugin.cfg")
|
||||
if status == OK:
|
||||
if not config.has_section_key("custom", "class_directory"):
|
||||
config.set_value("custom", "class_directory", "res://classes")
|
||||
# TODO: Create folders
|
||||
if not config.has_section_key("custom", "extension"):
|
||||
config.set_value("custom", "extension", "json")
|
||||
if not config.has_section_key("custom", "output_directory"):
|
||||
config.set_value("custom", "output_directory", "res://data")
|
||||
# TODO: Create folders
|
||||
if not config.has_section_key("custom", "password"):
|
||||
config.set_value("custom", "password", "")
|
||||
if not config.has_section_key("custom", "sanitize_ids"):
|
||||
config.set_value("custom", "sanitize_ids", true)
|
||||
if not config.has_section_key("custom", "serializer"):
|
||||
config.set_value("custom", "serializer", "json")
|
||||
config.save("res://addons/godot_data_editor/plugin.cfg")
|
||||
|
||||
|
||||
# Virtual: Name of the tool button on top
|
||||
func get_name():
|
||||
return "Data"
|
||||
|
||||
# Virtual: Makes sure that the control owns the main screen
|
||||
func has_main_screen():
|
||||
return true
|
||||
|
||||
# Virtual:
|
||||
func make_visible(visible):
|
||||
if(visible):
|
||||
gui.reload()
|
||||
gui.show()
|
||||
|
||||
else:
|
||||
gui.hide()
|
||||
|
||||
|
405
demo/addons/godot_data_editor/data_editor_gui.gd
Normal file
@ -0,0 +1,405 @@
|
||||
tool
|
||||
extends Control
|
||||
|
||||
var selected_item = null
|
||||
var selected_id = null
|
||||
var selected_class = null
|
||||
|
||||
|
||||
onready var item_tree = get_node("VBox/Body/ItemTree")
|
||||
onready var id_label = get_node("VBox/Body/Content/VBox/Container/ItemIdLabel")
|
||||
|
||||
onready var instance_details = get_node("VBox/Body/Content/VBox/InstanceDetails/")
|
||||
onready var class_properties = get_node("VBox/Body/Content/VBox/InstanceDetails/HBox/ClassProperties")
|
||||
onready var custom_properties = get_node("VBox/Body/Content/VBox/InstanceDetails/HBox/CustomProperties")
|
||||
onready var class_overview = get_node("VBox/Body/Content/VBox/ClassOverview")
|
||||
onready var no_classes = get_node("VBox/Body/Content/VBox/NoClasses")
|
||||
|
||||
#onready var last_modified_date = get_node("VBox/Body/Content/VBox/Container/GridContainer/LastModifiedDate")
|
||||
#onready var created_date = get_node("VBox/Body/Content/VBox/Container/GridContainer/CreatedDate")
|
||||
|
||||
|
||||
onready var new_custom_property_dialog = get_node("NewCustomPropertyDialog")
|
||||
onready var new_custom_property_name = get_node("NewCustomPropertyDialog/LineEdit")
|
||||
onready var new_custom_property_type_options = get_node("NewCustomPropertyDialog/TypeOptions")
|
||||
|
||||
onready var add_button = get_node("VBox/Head/Add")
|
||||
onready var delete_button = get_node("VBox/Head/Delete")
|
||||
onready var duplicate_button = get_node("VBox/Head/Duplicate")
|
||||
onready var change_display_name_button = get_node("VBox/Body/Content/VBox/Container/HBox/DisplayName")
|
||||
onready var rename_button = get_node("VBox/Head/Rename")
|
||||
onready var save_button = get_node("VBox/Head/Save")
|
||||
onready var save_all_button = get_node("VBox/Head/SaveAll")
|
||||
|
||||
onready var copy_id_button = get_node("VBox/Body/Content/VBox/Container/HBox/CopyId")
|
||||
onready var edit_class_button = get_node("VBox/Body/Content/VBox/Container/HBox/EditClass")
|
||||
|
||||
# Dialogs
|
||||
onready var input_dialog = get_node("InputDialog")
|
||||
|
||||
onready var new_item_class_dialog = get_node("NewClassDialog")
|
||||
onready var new_item_class_name = get_node("NewClassDialog/ClassName")
|
||||
onready var new_item_class_icon = get_node("NewClassDialog/ClassIconPath")
|
||||
onready var new_item_class_icon_dialog = get_node("NewClassDialog/ClassIconFileDialog")
|
||||
|
||||
|
||||
onready var warn_dialog = get_node("WarnDialog")
|
||||
onready var options_screen = get_node("OptionsDialog")
|
||||
|
||||
var item_tree_class = preload("item_tree.tscn")
|
||||
#var active_element = null
|
||||
var item_manager = null
|
||||
|
||||
signal class_edit_requested(script)
|
||||
signal input_dialog_confirmed(text1, text2)
|
||||
|
||||
# First initialize the item manager which is used for loading, saving and configs
|
||||
func _init():
|
||||
item_manager = preload("item_manager.gd").new() # This item_manager will add itself to the globals
|
||||
|
||||
func _ready():
|
||||
Globals.set("debug_is_editor", false)
|
||||
# Tree signals
|
||||
item_tree.connect("on_new_item_pressed", self, "handle_actions", ["add"])
|
||||
item_tree.connect("on_rename_pressed", self, "handle_actions", ["rename"])
|
||||
item_tree.connect("on_delete_pressed", self, "handle_actions", ["delete"])
|
||||
item_tree.connect("on_duplicate_pressed", self, "handle_actions", ["duplicate"])
|
||||
item_tree.connect("on_item_selected", self, "change_item_context", [])
|
||||
item_tree.connect("on_open", self, "open_item", [])
|
||||
|
||||
custom_properties.connect("custom_property_add_requested", self, "handle_actions", ["add_custom_property"])
|
||||
custom_properties.connect("new_custom_property_created", self, "handle_actions", ["add_custom_property"])
|
||||
custom_properties.connect("custom_property_delete_requested", self, "delete_custom_property", [])
|
||||
class_properties.connect("on_item_changed", self, "toggle_item_dirty_state", [])
|
||||
|
||||
options_screen.connect("extension_changed", item_manager, "rename_extension_of_all_items", [])
|
||||
options_screen.connect("encryption_changed", item_manager, "delete_and_resave", [])
|
||||
|
||||
item_manager.connect("class_insertion_failed", self, "show_warning", [])
|
||||
item_manager.connect("item_insertion_failed", self, "show_warning", [])
|
||||
item_manager.connect("custom_property_insertion_failed", self, "show_warning", [])
|
||||
item_manager.connect("item_duplication_failed", self, "show_warning", [])
|
||||
# item_manager.connect("class_is_invalid", self, "show_warning", [])
|
||||
|
||||
# Add types to the custom property type dropdown
|
||||
var type_names = item_manager.type_names.keys()
|
||||
type_names.sort()
|
||||
new_custom_property_type_options.clear()
|
||||
var index = 0
|
||||
for type in type_names:
|
||||
new_custom_property_type_options.add_item(type)
|
||||
new_custom_property_type_options.set_item_metadata(index, item_manager.type_names[type])
|
||||
index += 1
|
||||
|
||||
# No classes available
|
||||
var has_no_classes = item_manager.classes.size() == 0
|
||||
if has_no_classes:
|
||||
change_display_name_button.set_disabled(has_no_classes)
|
||||
duplicate_button.set_disabled(true)
|
||||
save_button.set_disabled(true)
|
||||
save_all_button.set_disabled(true)
|
||||
save_all_button.set_disabled(true)
|
||||
rename_button.set_disabled(true)
|
||||
add_button.set_disabled(true)
|
||||
delete_button.set_disabled(true)
|
||||
copy_id_button.set_disabled(true)
|
||||
edit_class_button.set_disabled(true)
|
||||
no_classes.show()
|
||||
id_label.set_text("No Classes")
|
||||
instance_details.hide()
|
||||
class_overview.hide()
|
||||
else:
|
||||
# Select the first item in the tree when loading the GUI
|
||||
var all_classes = item_manager.classes.keys()
|
||||
all_classes.sort()
|
||||
selected_class = all_classes[0]
|
||||
change_item_context(selected_item, selected_class)
|
||||
|
||||
# TODO: Implement
|
||||
func open_item():
|
||||
var item_path = item_manager.get_full_path(selected_item)
|
||||
var program = ""
|
||||
var os_name = OS.get_name()
|
||||
if os_name == "Windows":
|
||||
program = "explorer"
|
||||
item_path = item_path.replace("/", "\\") # ~_~...
|
||||
# TODO: Not sure if these work... Probably add the possibility to add a custom editor
|
||||
elif os_name == "OSX":
|
||||
program = "open"
|
||||
else:
|
||||
program = "nautilus"
|
||||
OS.execute(program, [item_path], false)
|
||||
|
||||
func change_item_context(selected_item, selected_class):
|
||||
|
||||
if selected_class:
|
||||
self.selected_class = selected_class
|
||||
|
||||
|
||||
|
||||
# TODO: Move to method, clean up
|
||||
var has_no_classes = item_manager.classes.size() == 0
|
||||
if has_no_classes:
|
||||
change_display_name_button.set_disabled(has_no_classes)
|
||||
duplicate_button.set_disabled(true)
|
||||
save_button.set_disabled(true)
|
||||
save_all_button.set_disabled(true)
|
||||
save_all_button.set_disabled(true)
|
||||
rename_button.set_disabled(true)
|
||||
add_button.set_disabled(true)
|
||||
delete_button.set_disabled(true)
|
||||
copy_id_button.set_disabled(true)
|
||||
edit_class_button.set_disabled(true)
|
||||
no_classes.show()
|
||||
instance_details.hide()
|
||||
class_overview.hide()
|
||||
id_label.set_text("No Classes")
|
||||
|
||||
|
||||
# An item was selected
|
||||
if selected_item:
|
||||
# Context was lost, e.g. because of changes to the classes. Reload.
|
||||
if selected_item and not selected_item.get("_id"):
|
||||
self.item_manager.load_manager()
|
||||
self.item_tree.load_tree(true)
|
||||
selected_item = item_tree.select_first_element()
|
||||
|
||||
change_display_name_button.set_disabled(false)
|
||||
duplicate_button.set_disabled(false)
|
||||
save_button.set_disabled(false)
|
||||
save_all_button.set_disabled(false)
|
||||
rename_button.set_disabled(false)
|
||||
add_button.set_disabled(false)
|
||||
delete_button.set_disabled(false)
|
||||
copy_id_button.set_disabled(false)
|
||||
edit_class_button.set_disabled(false)
|
||||
|
||||
self.selected_item = selected_item
|
||||
self.selected_id = selected_item._id
|
||||
class_overview.hide()
|
||||
no_classes.hide()
|
||||
instance_details.show()
|
||||
if selected_item._display_name == selected_id:
|
||||
id_label.set_text(selected_id)
|
||||
else:
|
||||
id_label.set_text(selected_item._display_name + " (" + selected_id + ")")
|
||||
|
||||
class_properties.build_properties(selected_item)
|
||||
custom_properties.build_properties(selected_item)
|
||||
# A class was selected
|
||||
elif selected_class:
|
||||
change_display_name_button.set_disabled(true)
|
||||
duplicate_button.set_disabled(true)
|
||||
save_button.set_disabled(true)
|
||||
save_all_button.set_disabled(false)
|
||||
rename_button.set_disabled(false)
|
||||
add_button.set_disabled(false)
|
||||
delete_button.set_disabled(false)
|
||||
copy_id_button.set_disabled(false)
|
||||
edit_class_button.set_disabled(false)
|
||||
self.selected_item = null
|
||||
self.selected_id = null
|
||||
id_label.set_text(selected_class.capitalize())
|
||||
if item_manager.invalid_classes.has(selected_class):
|
||||
class_overview.set_label("There is a problem with this class, please check if there are any issues. Press 'Reload' once you are ready.")
|
||||
else:
|
||||
class_overview.set_label("")
|
||||
class_overview.show()
|
||||
instance_details.hide()
|
||||
no_classes.hide()
|
||||
|
||||
|
||||
|
||||
func _on_ItemTree_on_new_item_created(new_item):
|
||||
selected_item = new_item
|
||||
|
||||
|
||||
func create_shortcut(keys):
|
||||
var short_cut = ShortCut.new()
|
||||
var input_event = InputEvent()
|
||||
input_event.type = InputEvent.KEY
|
||||
input_event.ID = keys
|
||||
short_cut.set_shortcut(input_event)
|
||||
|
||||
# TODO: Implement
|
||||
func warn_about_reload():
|
||||
if item_manager.has_unsaved_items():
|
||||
input_dialog.popup(self, "reload_confirmed", tr("Confirm reload"), tr("Some changes have not been saved. \nThey will be discarded if you proceed. Are you sure you want to perform this action?"))
|
||||
|
||||
|
||||
func reload():
|
||||
item_manager.load_manager()
|
||||
item_tree.load_tree(true)
|
||||
if item_manager.get_item(selected_class, selected_id):
|
||||
item_tree.select_item(item_manager.get_item(selected_class, selected_id))
|
||||
|
||||
|
||||
func toggle_item_dirty_state(item):
|
||||
item._dirty = true
|
||||
item_tree.set_tree_item_label_text(item)
|
||||
|
||||
|
||||
# Validation takes place in the item manager
|
||||
func _on_NewCustomPropertyDialog_confirmed():
|
||||
var custom_property_id = new_custom_property_name.get_text().strip_edges()
|
||||
var custom_property_type = new_custom_property_type_options.get_selected_metadata()
|
||||
var success = item_manager.add_custom_property(selected_item, custom_property_id, custom_property_type)
|
||||
if success:
|
||||
item_tree.set_tree_item_label_text(selected_item)
|
||||
toggle_item_dirty_state(selected_item)
|
||||
custom_properties.build_properties(selected_item)
|
||||
|
||||
|
||||
# TODO: Show confirmation dialog
|
||||
func delete_custom_property(property_name):
|
||||
item_manager.delete_custom_property(selected_item, property_name)
|
||||
toggle_item_dirty_state(selected_item)
|
||||
custom_properties.build_properties(selected_item)
|
||||
|
||||
|
||||
# TODO: New Class Dialog is still a mess
|
||||
func _on_AddClassButton_button_down():
|
||||
new_item_class_name.set_text("")
|
||||
new_item_class_icon.set_text("")
|
||||
new_item_class_icon_dialog.set_current_path("")
|
||||
new_item_class_dialog.popup_centered()
|
||||
new_item_class_name.grab_focus()
|
||||
|
||||
|
||||
func _on_NewClassDialog_confirmed():
|
||||
var name = new_item_class_name.get_text().to_lower()
|
||||
var icon_path = new_item_class_icon.get_text()
|
||||
item_manager.create_class(name, icon_path)
|
||||
item_tree.load_tree()
|
||||
item_tree.select_class(name)
|
||||
reload()
|
||||
edit_class()
|
||||
|
||||
|
||||
# New Class Dialog
|
||||
func _on_NewClassIconSearchButton_button_down():
|
||||
new_item_class_icon_dialog.popup_centered()
|
||||
|
||||
# Icon for new class was selected
|
||||
func _on_NewClassIconFileDialog_file_selected(path):
|
||||
new_item_class_icon.set_text(path)
|
||||
|
||||
# General handler for a lot of actions to centralize the GUI logic a bit
|
||||
func handle_actions(action, argument = ""):
|
||||
if action == "add":
|
||||
input_dialog.popup(self, "_on_add_item_confirmed", tr("New Item"), tr("Please enter an ID for and optionally a display name the new item"), tr("ID"), "", tr("Display Name (optional)"), "")
|
||||
elif action == "rename":
|
||||
if selected_item:
|
||||
input_dialog.popup(self, "_on_rename_item_confirmed", tr("Rename Item"), tr("Please enter a new ID for this item."), "ID", selected_id)
|
||||
else:
|
||||
input_dialog.popup(self, "_on_rename_class_confirmed", tr("Rename Class"), tr("Please enter a new name for this class. All pending changes will be discarded!"), "ID", selected_class)
|
||||
elif action == "duplicate":
|
||||
var new_display_name = ""
|
||||
if selected_item._dirty:
|
||||
input_dialog.popup(self, "item_duplication_failed", tr("Item duplication failed"), tr("Before duplicating this item, please first save it."))
|
||||
return
|
||||
selected_item._display_name = ""
|
||||
input_dialog.popup(self, "_on_duplicate_confirmed", tr("Duplicate Item"), tr("Please enter a new ID for this item"), "ID", selected_id, tr("Display Name (optional)"), new_display_name)
|
||||
elif action == "save":
|
||||
item_manager.save_item(selected_item)
|
||||
item_tree.load_tree()
|
||||
#reload()
|
||||
elif action == "save_all":
|
||||
item_manager.save_all_items()
|
||||
item_tree.load_tree()
|
||||
#reload()
|
||||
elif action == "reload":
|
||||
item_manager.load_manager()
|
||||
reload()
|
||||
elif action == "new_class":
|
||||
_on_AddClassButton_button_down() # TODO: Incorporate into dialog handling
|
||||
elif action == "delete":
|
||||
if selected_item:
|
||||
input_dialog.popup(self, "_on_delete_item_confirmed", tr("Delete Item"), tr("Are you sure you want to delete this item?"))
|
||||
else:
|
||||
input_dialog.popup(self, "_on_delete_class_confirmed", tr("Delete Class"), tr("Are you sure you want to delete class along with all items?"))
|
||||
elif action == "options":
|
||||
options_screen.popup_centered()
|
||||
elif action == "edit_class":
|
||||
edit_class()
|
||||
elif action == "copy_id":
|
||||
copy_id()
|
||||
elif action == "change_display_name":
|
||||
input_dialog.popup(self, "change_display_name", tr("Change Display Name"), tr("Please enter a display name for this item."), "Display Name", selected_item._display_name)
|
||||
elif action == "add_custom_property":
|
||||
new_custom_property_name.set_text("")
|
||||
new_custom_property_dialog.popup_centered()
|
||||
new_custom_property_name.grab_focus()
|
||||
|
||||
#########################################################################
|
||||
# Handlers #
|
||||
#########################################################################
|
||||
|
||||
func _on_add_item_confirmed(id, display_name):
|
||||
var new_item = item_manager.create_and_add_new_item(selected_class, id, display_name)
|
||||
if new_item:
|
||||
item_tree.add_leaf(new_item, true)
|
||||
|
||||
|
||||
func _on_rename_item_confirmed(id):
|
||||
item_manager.rename_item(selected_item, id)
|
||||
reload()
|
||||
|
||||
|
||||
func _on_rename_class_confirmed(name):
|
||||
item_manager.rename_class(selected_class, name)
|
||||
reload()
|
||||
|
||||
|
||||
func _on_duplicate_confirmed(id, display_name):
|
||||
var duplicated_item = item_manager.duplicate_item(selected_item, id, display_name, false)
|
||||
item_tree.add_leaf(duplicated_item, true)
|
||||
reload()
|
||||
|
||||
func _on_delete_item_confirmed():
|
||||
item_manager.delete_item(selected_item)
|
||||
reload()
|
||||
|
||||
|
||||
func _on_delete_class_confirmed():
|
||||
item_manager.delete_class(selected_class)
|
||||
if item_manager.classes.size() > 0:
|
||||
item_tree.select_class(item_manager.class_names[0])
|
||||
else:
|
||||
change_item_context(null, null)
|
||||
reload()
|
||||
|
||||
#########################################################################
|
||||
# Buttons on the right #
|
||||
#########################################################################
|
||||
func change_display_name(new_name):
|
||||
selected_item._display_name = new_name
|
||||
toggle_item_dirty_state(selected_item)
|
||||
change_item_context(selected_item, selected_class)
|
||||
|
||||
func copy_id():
|
||||
if selected_item:
|
||||
OS.set_clipboard(selected_id)
|
||||
else:
|
||||
OS.set_clipboard(selected_class)
|
||||
|
||||
func edit_class():
|
||||
var script = item_manager.classes[selected_class]
|
||||
emit_signal("class_edit_requested", script)
|
||||
|
||||
#####################################################
|
||||
# OTHERS
|
||||
#####################################################
|
||||
|
||||
func show_warning(title, text):
|
||||
warn_dialog.set_title(title)
|
||||
warn_dialog.set_text(text)
|
||||
warn_dialog.popup_centered()
|
||||
|
||||
|
||||
func log_text(text):
|
||||
var file = File.new()
|
||||
file.open("res://test.log", File.READ_WRITE)
|
||||
var old_text = file.get_as_text()
|
||||
var date = str(OS.get_datetime()["hour"]) + ":" + str(OS.get_datetime()["minute"]) + ":" + str(OS.get_datetime()["second"]) + "\t"
|
||||
file.store_line(old_text + date + text)
|
834
demo/addons/godot_data_editor/data_editor_gui.tscn
Normal file
@ -0,0 +1,834 @@
|
||||
[gd_scene load_steps=22 format=1]
|
||||
|
||||
[ext_resource path="res://addons/godot_data_editor/data_editor_gui.gd" type="Script" id=1]
|
||||
[ext_resource path="res://addons/godot_data_editor/icons/icon_add.png" type="Texture" id=2]
|
||||
[ext_resource path="res://addons/godot_data_editor/icons/icon_save.png" type="Texture" id=3]
|
||||
[ext_resource path="res://addons/godot_data_editor/icons/icon_rename.png" type="Texture" id=4]
|
||||
[ext_resource path="res://addons/godot_data_editor/icons/icon_duplicate.png" type="Texture" id=5]
|
||||
[ext_resource path="res://addons/godot_data_editor/icons/icon_remove.png" type="Texture" id=6]
|
||||
[ext_resource path="res://addons/godot_data_editor/icons/icon_reload_small.png" type="Texture" id=7]
|
||||
[ext_resource path="res://addons/godot_data_editor/icons/icon_script.png" type="Texture" id=8]
|
||||
[ext_resource path="res://addons/godot_data_editor/icons/icon_options.png" type="Texture" id=9]
|
||||
[ext_resource path="res://addons/godot_data_editor/item_tree.tscn" type="PackedScene" id=10]
|
||||
[ext_resource path="res://addons/godot_data_editor/icons/icon_display-name.png" type="Texture" id=11]
|
||||
[ext_resource path="res://addons/godot_data_editor/icons/icon_copy.png" type="Texture" id=12]
|
||||
[ext_resource path="res://addons/godot_data_editor/icons/icon_edit.png" type="Texture" id=13]
|
||||
[ext_resource path="res://addons/godot_data_editor/fonts/droid_sans_title.tres" type="DynamicFont" id=14]
|
||||
[ext_resource path="res://addons/godot_data_editor/class_properties.tscn" type="PackedScene" id=15]
|
||||
[ext_resource path="res://addons/godot_data_editor/custom_properties.tscn" type="PackedScene" id=16]
|
||||
[ext_resource path="res://addons/godot_data_editor/class_overview.tscn" type="PackedScene" id=17]
|
||||
[ext_resource path="res://addons/godot_data_editor/no_classes.tscn" type="PackedScene" id=18]
|
||||
[ext_resource path="res://addons/godot_data_editor/warn.gd" type="Script" id=19]
|
||||
[ext_resource path="res://addons/godot_data_editor/options.tscn" type="PackedScene" id=20]
|
||||
[ext_resource path="res://addons/godot_data_editor/input_dialog.tscn" type="PackedScene" id=21]
|
||||
|
||||
[node name="godot_data_editor" type="Control"]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
rect/min_size = Vector2( 800, 0 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 0.0
|
||||
margin/bottom = 0.0
|
||||
script/script = ExtResource( 1 )
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="."]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 0.0
|
||||
margin/bottom = 0.0
|
||||
alignment = 0
|
||||
|
||||
[node name="Head" type="HBoxContainer" parent="VBox"]
|
||||
|
||||
rect/min_size = Vector2( 0, 22 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1280.0
|
||||
margin/bottom = 28.0
|
||||
alignment = 0
|
||||
|
||||
[node name="Add" type="ToolButton" parent="VBox/Head"]
|
||||
|
||||
rect/min_size = Vector2( 28, 28 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 56.0
|
||||
margin/bottom = 28.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Add"
|
||||
icon = ExtResource( 2 )
|
||||
flat = true
|
||||
align = 0
|
||||
|
||||
[node name="VSeparator5" type="VSeparator" parent="VBox/Head"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 60.0
|
||||
margin/top = 0.0
|
||||
margin/right = 63.0
|
||||
margin/bottom = 28.0
|
||||
|
||||
[node name="Save" type="ToolButton" parent="VBox/Head"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 67.0
|
||||
margin/top = 0.0
|
||||
margin/right = 127.0
|
||||
margin/bottom = 28.0
|
||||
disabled = true
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Save"
|
||||
icon = ExtResource( 3 )
|
||||
flat = false
|
||||
|
||||
[node name="SaveAll" type="ToolButton" parent="VBox/Head"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 131.0
|
||||
margin/top = 0.0
|
||||
margin/right = 212.0
|
||||
margin/bottom = 28.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Save All"
|
||||
icon = ExtResource( 3 )
|
||||
flat = false
|
||||
|
||||
[node name="VSeparator" type="VSeparator" parent="VBox/Head"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 216.0
|
||||
margin/top = 0.0
|
||||
margin/right = 219.0
|
||||
margin/bottom = 28.0
|
||||
|
||||
[node name="Rename" type="ToolButton" parent="VBox/Head"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 223.0
|
||||
margin/top = 0.0
|
||||
margin/right = 306.0
|
||||
margin/bottom = 28.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Rename"
|
||||
icon = ExtResource( 4 )
|
||||
flat = false
|
||||
|
||||
[node name="Duplicate" type="ToolButton" parent="VBox/Head"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 310.0
|
||||
margin/top = 0.0
|
||||
margin/right = 402.0
|
||||
margin/bottom = 28.0
|
||||
disabled = true
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Duplicate"
|
||||
icon = ExtResource( 5 )
|
||||
flat = false
|
||||
|
||||
[node name="Delete" type="ToolButton" parent="VBox/Head"]
|
||||
|
||||
rect/min_size = Vector2( 28, 28 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 406.0
|
||||
margin/top = 0.0
|
||||
margin/right = 480.0
|
||||
margin/bottom = 28.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Delete"
|
||||
icon = ExtResource( 6 )
|
||||
flat = true
|
||||
|
||||
[node name="VSeparator3" type="VSeparator" parent="VBox/Head"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 484.0
|
||||
margin/top = 0.0
|
||||
margin/right = 487.0
|
||||
margin/bottom = 28.0
|
||||
|
||||
[node name="Refresh2" type="ToolButton" parent="VBox/Head"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 491.0
|
||||
margin/top = 0.0
|
||||
margin/right = 563.0
|
||||
margin/bottom = 28.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Reload"
|
||||
icon = ExtResource( 7 )
|
||||
flat = false
|
||||
|
||||
[node name="VSeparator2" type="VSeparator" parent="VBox/Head"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 567.0
|
||||
margin/top = 0.0
|
||||
margin/right = 570.0
|
||||
margin/bottom = 28.0
|
||||
|
||||
[node name="NewClass" type="ToolButton" parent="VBox/Head"]
|
||||
|
||||
rect/min_size = Vector2( 28, 28 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 574.0
|
||||
margin/top = 0.0
|
||||
margin/right = 670.0
|
||||
margin/bottom = 28.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "New Class"
|
||||
icon = ExtResource( 8 )
|
||||
flat = true
|
||||
align = 0
|
||||
|
||||
[node name="VSeparator4" type="VSeparator" parent="VBox/Head"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 674.0
|
||||
margin/top = 0.0
|
||||
margin/right = 677.0
|
||||
margin/bottom = 28.0
|
||||
|
||||
[node name="Options" type="ToolButton" parent="VBox/Head"]
|
||||
|
||||
rect/min_size = Vector2( 28, 28 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 681.0
|
||||
margin/top = 0.0
|
||||
margin/right = 763.0
|
||||
margin/bottom = 28.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Options"
|
||||
icon = ExtResource( 9 )
|
||||
flat = true
|
||||
align = 0
|
||||
|
||||
[node name="Search" type="LineEdit" parent="VBox/Head"]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 377.0
|
||||
margin/top = 0.0
|
||||
margin/right = 435.0
|
||||
margin/bottom = 28.0
|
||||
placeholder/text = "Search"
|
||||
placeholder/alpha = 0.6
|
||||
focus_mode = 2
|
||||
caret/caret_blink = false
|
||||
caret/caret_blink_speed = 0.65
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBox"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 32.0
|
||||
margin/right = 1280.0
|
||||
margin/bottom = 35.0
|
||||
|
||||
[node name="Body" type="HSplitContainer" parent="VBox"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 39.0
|
||||
margin/right = 1280.0
|
||||
margin/bottom = 600.0
|
||||
split/offset = 0
|
||||
split/collapsed = false
|
||||
split/dragger_visibility = 0
|
||||
|
||||
[node name="ItemTree" parent="VBox/Body" instance=ExtResource( 10 )]
|
||||
|
||||
anchor/right = 0
|
||||
anchor/bottom = 0
|
||||
rect/min_size = Vector2( 165, 0 )
|
||||
size_flags/horizontal = 2
|
||||
size_flags/stretch_ratio = 0.0
|
||||
margin/right = 165.0
|
||||
margin/bottom = 561.0
|
||||
|
||||
[node name="Content" type="Panel" parent="VBox/Body"]
|
||||
|
||||
visibility/self_opacity = 0.0
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 177.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1280.0
|
||||
margin/bottom = 561.0
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="VBox/Body/Content"]
|
||||
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
size_flags/stretch_ratio = 0.0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 0.0
|
||||
margin/bottom = 0.0
|
||||
alignment = 0
|
||||
|
||||
[node name="Container" type="MarginContainer" parent="VBox/Body/Content/VBox"]
|
||||
|
||||
rect/min_size = Vector2( 0, 25 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1103.0
|
||||
margin/bottom = 25.0
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="VBox/Body/Content/VBox/Container"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 8.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1103.0
|
||||
margin/bottom = 25.0
|
||||
custom_constants/separation = 15
|
||||
alignment = 2
|
||||
|
||||
[node name="DisplayName" type="ToolButton" parent="VBox/Body/Content/VBox/Container/HBox"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 0
|
||||
size_flags/vertical = 2
|
||||
margin/left = 722.0
|
||||
margin/top = 0.0
|
||||
margin/right = 892.0
|
||||
margin/bottom = 25.0
|
||||
disabled = true
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Change Display Name"
|
||||
icon = ExtResource( 11 )
|
||||
flat = true
|
||||
align = 0
|
||||
|
||||
[node name="CopyId" type="ToolButton" parent="VBox/Body/Content/VBox/Container/HBox"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 0
|
||||
size_flags/vertical = 2
|
||||
margin/left = 907.0
|
||||
margin/top = 0.0
|
||||
margin/right = 988.0
|
||||
margin/bottom = 25.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Copy ID"
|
||||
icon = ExtResource( 12 )
|
||||
flat = true
|
||||
align = 0
|
||||
|
||||
[node name="EditClass" type="ToolButton" parent="VBox/Body/Content/VBox/Container/HBox"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 0
|
||||
size_flags/vertical = 2
|
||||
margin/left = 1003.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1095.0
|
||||
margin/bottom = 25.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Edit Class"
|
||||
icon = ExtResource( 13 )
|
||||
flat = true
|
||||
align = 0
|
||||
|
||||
[node name="ItemIdLabel" type="Label" parent="VBox/Body/Content/VBox/Container"]
|
||||
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 8.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1103.0
|
||||
margin/bottom = 25.0
|
||||
custom_fonts/font = ExtResource( 14 )
|
||||
custom_colors/font_color_shadow = Color( 0.300781, 0.300781, 0.300781, 1 )
|
||||
custom_constants/shadow_offset_x = 1
|
||||
custom_constants/shadow_offset_y = 1
|
||||
text = "Actor"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="VBox/Body/Content/VBox/Container"]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 0
|
||||
size_flags/vertical = 2
|
||||
margin/left = 555.0
|
||||
margin/top = 0.0
|
||||
margin/right = 555.0
|
||||
margin/bottom = 25.0
|
||||
custom_constants/hseparation = 10
|
||||
columns = 2
|
||||
|
||||
[node name="Created" type="Label" parent="VBox/Body/Content/VBox/Container/GridContainer"]
|
||||
|
||||
visibility/opacity = 0.25
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 91.0
|
||||
margin/bottom = 14.0
|
||||
text = "Created:"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="CreatedDate" type="Label" parent="VBox/Body/Content/VBox/Container/GridContainer"]
|
||||
|
||||
visibility/opacity = 0.25
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 101.0
|
||||
margin/top = 0.0
|
||||
margin/right = 217.0
|
||||
margin/bottom = 14.0
|
||||
text = "01.01.01 01:01:01"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="LastModifiedLabel" type="Label" parent="VBox/Body/Content/VBox/Container/GridContainer"]
|
||||
|
||||
visibility/opacity = 0.25
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 18.0
|
||||
margin/right = 91.0
|
||||
margin/bottom = 32.0
|
||||
text = "Last modified:"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="LastModifiedDate" type="Label" parent="VBox/Body/Content/VBox/Container/GridContainer"]
|
||||
|
||||
visibility/opacity = 0.25
|
||||
focus/ignore_mouse = true
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 0
|
||||
margin/left = 101.0
|
||||
margin/top = 18.0
|
||||
margin/right = 217.0
|
||||
margin/bottom = 32.0
|
||||
text = "01.01.01 01:01:01"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="VBox/Body/Content/VBox/Container"]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 8.0
|
||||
margin/top = 0.0
|
||||
margin/right = 1103.0
|
||||
margin/bottom = 25.0
|
||||
alignment = 0
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBox/Body/Content/VBox"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 29.0
|
||||
margin/right = 1103.0
|
||||
margin/bottom = 32.0
|
||||
|
||||
[node name="Spacer" type="Control" parent="VBox/Body/Content/VBox"]
|
||||
|
||||
rect/min_size = Vector2( 0, 10 )
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 36.0
|
||||
margin/right = 1103.0
|
||||
margin/bottom = 46.0
|
||||
|
||||
[node name="InstanceDetails" type="PanelContainer" parent="VBox/Body/Content/VBox"]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 0.0
|
||||
margin/top = 50.0
|
||||
margin/right = 1103.0
|
||||
margin/bottom = 561.0
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="VBox/Body/Content/VBox/InstanceDetails"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 7.0
|
||||
margin/top = 7.0
|
||||
margin/right = 1096.0
|
||||
margin/bottom = 504.0
|
||||
alignment = 0
|
||||
|
||||
[node name="ClassProperties" parent="VBox/Body/Content/VBox/InstanceDetails/HBox" instance=ExtResource( 15 )]
|
||||
|
||||
anchor/right = 0
|
||||
anchor/bottom = 0
|
||||
margin/right = 542.0
|
||||
margin/bottom = 497.0
|
||||
|
||||
[node name="CustomProperties" parent="VBox/Body/Content/VBox/InstanceDetails/HBox" instance=ExtResource( 16 )]
|
||||
|
||||
anchor/right = 0
|
||||
anchor/bottom = 0
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 3
|
||||
margin/left = 546.0
|
||||
margin/right = 1089.0
|
||||
margin/bottom = 497.0
|
||||
|
||||
[node name="ClassOverview" parent="VBox/Body/Content/VBox" instance=ExtResource( 17 )]
|
||||
|
||||
anchor/right = 0
|
||||
anchor/bottom = 0
|
||||
margin/top = 50.0
|
||||
margin/right = 1103.0
|
||||
margin/bottom = 561.0
|
||||
|
||||
[node name="NoClasses" parent="VBox/Body/Content/VBox" instance=ExtResource( 18 )]
|
||||
|
||||
visibility/visible = false
|
||||
anchor/right = 0
|
||||
anchor/bottom = 0
|
||||
margin/left = 0.0
|
||||
margin/top = 307.0
|
||||
margin/right = 1103.0
|
||||
margin/bottom = 561.0
|
||||
|
||||
[node name="WarnDialog" type="AcceptDialog" parent="."]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 350.0
|
||||
margin/bottom = 110.0
|
||||
popup/exclusive = true
|
||||
window/title = ""
|
||||
dialog/hide_on_ok = true
|
||||
script/script = ExtResource( 19 )
|
||||
|
||||
[node name="NewClassDialog" type="ConfirmationDialog" parent="."]
|
||||
|
||||
editor/display_folded = true
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 519.0
|
||||
margin/top = 193.0
|
||||
margin/right = 990.0
|
||||
margin/bottom = 316.0
|
||||
popup/exclusive = true
|
||||
window/title = "New Class"
|
||||
dialog/text = "Enter the name and the path to an optional icon"
|
||||
dialog/hide_on_ok = true
|
||||
|
||||
[node name="ClassName" type="LineEdit" parent="NewClassDialog"]
|
||||
|
||||
focus_neighbour/bottom = NodePath("../ClassIconPath")
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 8.0
|
||||
margin/top = 27.0
|
||||
margin/right = 466.0
|
||||
margin/bottom = 51.0
|
||||
placeholder/text = "Name"
|
||||
placeholder/alpha = 0.6
|
||||
focus_mode = 2
|
||||
caret/caret_blink = false
|
||||
caret/caret_blink_speed = 0.65
|
||||
|
||||
[node name="ClassIconPath" type="LineEdit" parent="NewClassDialog"]
|
||||
|
||||
focus_neighbour/top = NodePath("../ClassName")
|
||||
focus_neighbour/right = NodePath("../NewClassIconSearchButton")
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 8.0
|
||||
margin/top = 60.0
|
||||
margin/right = 393.0
|
||||
margin/bottom = 84.0
|
||||
placeholder/text = "Icon Path (optional)"
|
||||
placeholder/alpha = 0.6
|
||||
focus_mode = 2
|
||||
caret/caret_blink = false
|
||||
caret/caret_blink_speed = 0.65
|
||||
|
||||
[node name="ClassIconFileDialog" type="FileDialog" parent="NewClassDialog"]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 393.0
|
||||
margin/bottom = 404.0
|
||||
popup/exclusive = true
|
||||
window/title = "Open a File"
|
||||
dialog/hide_on_ok = true
|
||||
mode = 0
|
||||
access = 2
|
||||
filters = StringArray( "*.png" )
|
||||
show_hidden_files = false
|
||||
|
||||
[node name="NewClassIconSearchButton" type="Button" parent="NewClassDialog"]
|
||||
|
||||
focus_neighbour/left = NodePath("../ClassIconPath")
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 399.0
|
||||
margin/top = 61.0
|
||||
margin/right = 466.0
|
||||
margin/bottom = 83.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "Search"
|
||||
flat = false
|
||||
|
||||
[node name="OptionsDialog" parent="." instance=ExtResource( 20 )]
|
||||
|
||||
visibility/visible = false
|
||||
margin/right = 550.0
|
||||
margin/bottom = 310.0
|
||||
|
||||
[node name="InputDialog" parent="." instance=ExtResource( 21 )]
|
||||
|
||||
visibility/visible = false
|
||||
|
||||
[node name="NewCustomPropertyDialog" type="ConfirmationDialog" parent="."]
|
||||
|
||||
visibility/visible = false
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 117.0
|
||||
margin/top = 117.0
|
||||
margin/right = 489.0
|
||||
margin/bottom = 243.0
|
||||
popup/exclusive = false
|
||||
window/title = "New custom property"
|
||||
dialog/text = "Enter the name and type of the property"
|
||||
dialog/hide_on_ok = true
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="NewCustomPropertyDialog"]
|
||||
|
||||
focus_neighbour/bottom = NodePath("../TypeOptions")
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 2
|
||||
margin/left = 7.0
|
||||
margin/top = 29.0
|
||||
margin/right = 363.0
|
||||
margin/bottom = 53.0
|
||||
placeholder/text = "Name"
|
||||
placeholder/alpha = 0.6
|
||||
focus_mode = 2
|
||||
caret/caret_blink = false
|
||||
caret/caret_blink_speed = 0.65
|
||||
|
||||
[node name="TypeOptions" type="OptionButton" parent="NewCustomPropertyDialog"]
|
||||
|
||||
focus_neighbour/top = NodePath("../LineEdit")
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 7.0
|
||||
margin/top = 64.0
|
||||
margin/right = 363.0
|
||||
margin/bottom = 84.0
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
text = "BOOL"
|
||||
flat = false
|
||||
align = 0
|
||||
selected = 0
|
||||
items = [ "BOOL", null, false, -1, 1, "COLOR", null, false, -1, 14, "IMAGE", null, false, -1, 15, "INT", null, false, -1, 2, "NODE_PATH", null, false, -1, 16, "OBJECT", null, false, -1, 18, "PLANE", null, false, -1, 9, "QUAT", null, false, -1, 10, "REAL", null, false, -1, 3, "RECT2", null, false, -1, 6, "STRING", null, false, -1, 4, "TRANSFORM", null, false, -1, 13, "VECTOR2", null, false, -1, 5, "VECTOR3", null, false, -1, 7 ]
|
||||
|
||||
[connection signal="button_down" from="VBox/Head/Add" to="." method="handle_actions" binds= [ "add" ]]
|
||||
|
||||
[connection signal="button_down" from="VBox/Head/Save" to="." method="handle_actions" binds= [ "save" ]]
|
||||
|
||||
[connection signal="button_down" from="VBox/Head/SaveAll" to="." method="handle_actions" binds= [ "save_all" ]]
|
||||
|
||||
[connection signal="button_down" from="VBox/Head/Rename" to="." method="handle_actions" binds= [ "rename" ]]
|
||||
|
||||
[connection signal="button_down" from="VBox/Head/Duplicate" to="." method="handle_actions" binds= [ "duplicate" ]]
|
||||
|
||||
[connection signal="button_down" from="VBox/Head/Delete" to="." method="handle_actions" binds= [ "delete" ]]
|
||||
|
||||
[connection signal="button_down" from="VBox/Head/Refresh2" to="." method="handle_actions" binds= [ "reload" ]]
|
||||
|
||||
[connection signal="button_down" from="VBox/Head/NewClass" to="." method="handle_actions" binds= [ "new_class" ]]
|
||||
|
||||
[connection signal="button_down" from="VBox/Head/Options" to="." method="handle_actions" binds= [ "options" ]]
|
||||
|
||||
[connection signal="button_down" from="VBox/Body/Content/VBox/Container/HBox/DisplayName" to="." method="handle_actions" binds= [ "change_display_name" ]]
|
||||
|
||||
[connection signal="button_down" from="VBox/Body/Content/VBox/Container/HBox/CopyId" to="." method="handle_actions" binds= [ "copy_id" ]]
|
||||
|
||||
[connection signal="button_down" from="VBox/Body/Content/VBox/Container/HBox/EditClass" to="." method="handle_actions" binds= [ "edit_class" ]]
|
||||
|
||||
[connection signal="confirmed" from="NewClassDialog" to="." method="_on_NewClassDialog_confirmed"]
|
||||
|
||||
[connection signal="file_selected" from="NewClassDialog/ClassIconFileDialog" to="." method="_on_NewClassIconFileDialog_file_selected"]
|
||||
|
||||
[connection signal="button_down" from="NewClassDialog/NewClassIconSearchButton" to="." method="_on_NewClassIconSearchButton_button_down"]
|
||||
|
||||
[connection signal="confirmed" from="NewCustomPropertyDialog" to="." method="_on_NewCustomPropertyDialog_confirmed"]
|
||||
|
||||
|
55
demo/addons/godot_data_editor/data_item.gd
Normal file
@ -0,0 +1,55 @@
|
||||
extends Node
|
||||
|
||||
# Class information
|
||||
# No setter, that's why there is a comma
|
||||
var _class setget ,get_class
|
||||
var _class_name setget ,get_class_name
|
||||
|
||||
var _dirty = false # TODO: Exclude
|
||||
var _persistent = false # TODO: Exclude
|
||||
|
||||
var _id = ""
|
||||
var _display_name setget set_display_name,get_display_name
|
||||
var _created = 0
|
||||
var _last_modified = 0
|
||||
|
||||
|
||||
# Instance-level custom properties, consists of arrays containing name, type, (hint and hint_text), default value
|
||||
var _custom_properties = {}
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
|
||||
|
||||
|
||||
func get_class():
|
||||
if _class:
|
||||
return _class
|
||||
else:
|
||||
_class = self.get_script().get_path().get_file().basename()
|
||||
return _class
|
||||
|
||||
|
||||
func get_class_name():
|
||||
return self.get_class().capitalize()
|
||||
|
||||
|
||||
func get_display_name():
|
||||
if _display_name == null or _display_name == "":
|
||||
return self._id
|
||||
else:
|
||||
return _display_name
|
||||
|
||||
|
||||
func set_display_name(name):
|
||||
_display_name = name
|
||||
|
||||
|
||||
func update_property(property, value):
|
||||
var data_singleton = Globals.get_singleton("data")
|
||||
if data_singleton:
|
||||
data_singleton.set_progress(_class, _id, property, value)
|
||||
|
||||
|
||||
func _init(id):
|
||||
self._id = id
|
BIN
demo/addons/godot_data_editor/fonts/DroidSans.ttf
Normal file
BIN
demo/addons/godot_data_editor/fonts/DroidSerif-Bold.ttf
Normal file
BIN
demo/addons/godot_data_editor/fonts/DroidSerif-BoldItalic.ttf
Normal file
BIN
demo/addons/godot_data_editor/fonts/DroidSerif-Italic.ttf
Normal file
11
demo/addons/godot_data_editor/fonts/droid_sans_title.tres
Normal file
@ -0,0 +1,11 @@
|
||||
[gd_resource type="DynamicFont" load_steps=2 format=1]
|
||||
|
||||
[ext_resource path="res://addons/godot_data_editor/fonts/DroidSans.ttf" type="DynamicFontData" id=1]
|
||||
|
||||
[resource]
|
||||
|
||||
font/size = 22
|
||||
font/use_mipmaps = false
|
||||
font/use_filter = false
|
||||
font/font = ExtResource( 1 )
|
||||
|
11
demo/addons/godot_data_editor/fonts/droid_serif_bold.tres
Normal file
@ -0,0 +1,11 @@
|
||||
[gd_resource type="DynamicFont" load_steps=2 format=1]
|
||||
|
||||
[ext_resource path="res://addons/godot_data_editor/fonts/DroidSerif-Bold.ttf" type="DynamicFontData" id=1]
|
||||
|
||||
[resource]
|
||||
|
||||
font/size = 16
|
||||
font/use_mipmaps = false
|
||||
font/use_filter = false
|
||||
font/font = ExtResource( 1 )
|
||||
|
@ -0,0 +1,11 @@
|
||||
[gd_resource type="DynamicFont" load_steps=2 format=1]
|
||||
|
||||
[ext_resource path="res://addons/godot_data_editor/fonts/DroidSerif-Italic.ttf" type="DynamicFontData" id=1]
|
||||
|
||||
[resource]
|
||||
|
||||
font/size = 16
|
||||
font/use_mipmaps = false
|
||||
font/use_filter = false
|
||||
font/font = ExtResource( 1 )
|
||||
|
11
demo/addons/godot_data_editor/fonts/droid_serif_italic.tres
Normal file
@ -0,0 +1,11 @@
|
||||
[gd_resource type="DynamicFont" load_steps=2 format=1]
|
||||
|
||||
[ext_resource path="res://addons/godot_data_editor/fonts/DroidSerif-Italic.ttf" type="DynamicFontData" id=1]
|
||||
|
||||
[resource]
|
||||
|
||||
font/size = 16
|
||||
font/use_mipmaps = false
|
||||
font/use_filter = false
|
||||
font/font = ExtResource( 1 )
|
||||
|
BIN
demo/addons/godot_data_editor/icons/empty.png
Normal file
After Width: | Height: | Size: 939 B |
BIN
demo/addons/godot_data_editor/icons/gom.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
demo/addons/godot_data_editor/icons/icon_add.png
Normal file
After Width: | Height: | Size: 111 B |
BIN
demo/addons/godot_data_editor/icons/icon_copy.png
Normal file
After Width: | Height: | Size: 248 B |
BIN
demo/addons/godot_data_editor/icons/icon_display-name.png
Normal file
After Width: | Height: | Size: 200 B |
BIN
demo/addons/godot_data_editor/icons/icon_duplicate.png
Normal file
After Width: | Height: | Size: 167 B |
BIN
demo/addons/godot_data_editor/icons/icon_edit.png
Normal file
After Width: | Height: | Size: 346 B |
BIN
demo/addons/godot_data_editor/icons/icon_empty.png
Normal file
After Width: | Height: | Size: 267 B |
BIN
demo/addons/godot_data_editor/icons/icon_load.png
Normal file
After Width: | Height: | Size: 170 B |
BIN
demo/addons/godot_data_editor/icons/icon_move_down.png
Normal file
After Width: | Height: | Size: 268 B |
BIN
demo/addons/godot_data_editor/icons/icon_move_up.png
Normal file
After Width: | Height: | Size: 269 B |
BIN
demo/addons/godot_data_editor/icons/icon_multi_line.png
Normal file
After Width: | Height: | Size: 140 B |
BIN
demo/addons/godot_data_editor/icons/icon_options.png
Normal file
After Width: | Height: | Size: 392 B |
BIN
demo/addons/godot_data_editor/icons/icon_reload_small.png
Normal file
After Width: | Height: | Size: 409 B |
BIN
demo/addons/godot_data_editor/icons/icon_remove.png
Normal file
After Width: | Height: | Size: 166 B |
BIN
demo/addons/godot_data_editor/icons/icon_rename.png
Normal file
After Width: | Height: | Size: 160 B |
BIN
demo/addons/godot_data_editor/icons/icon_save.png
Normal file
After Width: | Height: | Size: 252 B |
BIN
demo/addons/godot_data_editor/icons/icon_script.png
Normal file
After Width: | Height: | Size: 262 B |
58
demo/addons/godot_data_editor/input_dialog.gd
Normal file
@ -0,0 +1,58 @@
|
||||
tool
|
||||
extends ConfirmationDialog
|
||||
|
||||
#var text = ""
|
||||
#var title = ""
|
||||
var placeholder_1 = ""
|
||||
var placeholder_2 = ""
|
||||
var caller = null
|
||||
var callback_method = ""
|
||||
|
||||
onready var line_edit_1 = get_node("VBox/LineEdit1")
|
||||
onready var line_edit_2 = get_node("VBox/LineEdit2")
|
||||
|
||||
|
||||
#func _init(text, placerholder_1 = "", placeholder_2 = ""):
|
||||
|
||||
func popup(caller, callback_method, title, text, placeholder_1 = "", default_text_1 = "", placeholder_2 = "", default_text_2 = ""):
|
||||
self.caller = caller
|
||||
self.callback_method = callback_method
|
||||
self.placeholder_1 = placeholder_1
|
||||
self.placeholder_2 = placeholder_2
|
||||
|
||||
if not caller.is_connected("input_dialog_confirmed", caller, callback_method):
|
||||
caller.connect("input_dialog_confirmed", caller, callback_method, [])
|
||||
set_text(text)
|
||||
set_title(title)
|
||||
if placeholder_1 == "":
|
||||
line_edit_1.hide()
|
||||
else:
|
||||
line_edit_1.show()
|
||||
line_edit_1.set_placeholder(placeholder_1)
|
||||
|
||||
|
||||
if placeholder_2 == "":
|
||||
line_edit_2.hide()
|
||||
else:
|
||||
line_edit_2.show()
|
||||
line_edit_2.set_placeholder(placeholder_2)
|
||||
|
||||
line_edit_1.set_text(default_text_1)
|
||||
line_edit_2.set_text(default_text_2)
|
||||
self.popup_centered()
|
||||
|
||||
if not line_edit_1.is_hidden():
|
||||
line_edit_1.grab_focus()
|
||||
|
||||
func _on_ConfirmationDialog_confirmed():
|
||||
var text1 = line_edit_1.get_text().strip_edges()
|
||||
var text2 = line_edit_2.get_text().strip_edges()
|
||||
if placeholder_2:
|
||||
caller.emit_signal("input_dialog_confirmed", text1, text2)
|
||||
elif placeholder_1:
|
||||
caller.emit_signal("input_dialog_confirmed", text1)
|
||||
else:
|
||||
caller.emit_signal("input_dialog_confirmed")
|
||||
|
||||
|
||||
caller.disconnect("input_dialog_confirmed", caller, callback_method)
|
71
demo/addons/godot_data_editor/input_dialog.tscn
Normal file
@ -0,0 +1,71 @@
|
||||
[gd_scene load_steps=2 format=1]
|
||||
|
||||
[ext_resource path="res://addons/godot_data_editor/input_dialog.gd" type="Script" id=1]
|
||||
|
||||
[node name="ConfirmationDialog" type="ConfirmationDialog"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 440.0
|
||||
margin/bottom = 150.0
|
||||
popup/exclusive = true
|
||||
window/title = "Please Confirm..."
|
||||
dialog/text = "Text"
|
||||
dialog/hide_on_ok = true
|
||||
script/script = ExtResource( 1 )
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="."]
|
||||
|
||||
anchor/top = 1
|
||||
anchor/right = 1
|
||||
anchor/bottom = 1
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = false
|
||||
size_flags/horizontal = 2
|
||||
size_flags/vertical = 2
|
||||
margin/left = 8.0
|
||||
margin/top = 103.0
|
||||
margin/right = 8.0
|
||||
margin/bottom = 45.0
|
||||
custom_constants/separation = 10
|
||||
alignment = 0
|
||||
|
||||
[node name="LineEdit1" type="LineEdit" parent="VBox"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 0.0
|
||||
margin/right = 424.0
|
||||
margin/bottom = 24.0
|
||||
placeholder/text = "Hint 1"
|
||||
placeholder/alpha = 0.6
|
||||
focus_mode = 2
|
||||
caret/caret_blink = false
|
||||
caret/caret_blink_speed = 0.65
|
||||
|
||||
[node name="LineEdit2" type="LineEdit" parent="VBox"]
|
||||
|
||||
focus/ignore_mouse = false
|
||||
focus/stop_mouse = true
|
||||
size_flags/horizontal = 3
|
||||
size_flags/vertical = 2
|
||||
margin/left = 0.0
|
||||
margin/top = 34.0
|
||||
margin/right = 424.0
|
||||
margin/bottom = 58.0
|
||||
placeholder/text = "Hint 2"
|
||||
placeholder/alpha = 0.6
|
||||
focus_mode = 2
|
||||
caret/caret_blink = false
|
||||
caret/caret_blink_speed = 0.65
|
||||
|
||||
[connection signal="confirmed" from="." to="." method="_on_ConfirmationDialog_confirmed"]
|
||||
|
||||
|