├── .gitignore ├── LICENSE ├── README.md ├── addons └── godot_db_manager │ ├── assets │ ├── fnt │ │ ├── Roboto-Regular.ttf │ │ ├── roboto_08.tres │ │ ├── roboto_10.tres │ │ ├── roboto_12.tres │ │ ├── roboto_14.tres │ │ ├── roboto_16.tres │ │ ├── roboto_18.tres │ │ ├── roboto_20.tres │ │ ├── roboto_22.tres │ │ ├── roboto_24.tres │ │ └── roboto_26.tres │ └── tex │ │ ├── debug.png │ │ └── gui.png │ ├── core │ ├── GDDBConstants.gd │ ├── GDDBGlobals.gd │ ├── GDDBTypes.gd │ ├── database.gd │ ├── db_data.gd │ ├── db_man.gd │ ├── db_prop.gd │ └── db_table.gd │ ├── data_label.gd │ ├── data_label.tscn │ ├── db_editor.gd │ ├── db_editor.tscn │ ├── db_interface.gd │ ├── db_interface.tscn │ ├── db_manager.gd │ ├── debug │ └── dbg.tscn │ ├── dlgs │ ├── data_dlg.gd │ ├── data_dlg.tscn │ ├── delete_prop_dlg.gd │ ├── delete_prop_dlg.tscn │ ├── delete_table_dlg.gd │ ├── delete_table_dlg.tscn │ ├── edit_string_dlg.gd │ ├── edit_string_dlg.tscn │ ├── error_dlg.tscn │ ├── load_res_path_dlg.gd │ ├── load_res_path_dlg.tscn │ ├── new_db_dlg.gd │ ├── new_db_dlg.tscn │ ├── new_table_dlg.gd │ └── new_table_dlg.tscn │ ├── icon │ ├── icon.png │ └── icon.xcf │ ├── license.txt │ ├── menu.gd │ ├── menu.tscn │ ├── plugin.cfg │ ├── table_cell.gd │ ├── table_cell.tscn │ ├── table_editor.gd │ ├── table_editor.tscn │ ├── table_item.gd │ ├── table_item.tscn │ ├── table_property.gd │ ├── table_property.tscn │ ├── tables_header.gd │ ├── tables_header.tscn │ ├── tables_list.gd │ └── tables_list.tscn ├── assets ├── debug.xcf ├── gui.xcf └── main_layout.xcf ├── default_env.tres ├── docs ├── GDDB.odt ├── GDDB.pdf └── how_to │ ├── 01_database_manager.txt │ └── 02_database.txt ├── examples ├── db_man_test_1.tscn ├── db_test.gd ├── db_test.tscn ├── db_test_1.tscn ├── db_test_2.tscn ├── example_1.tscn ├── game_data.json ├── resource.gd ├── resource.tscn ├── resources │ ├── energy.png │ ├── food.png │ ├── gui_01.xcf │ ├── stone.png │ └── wood.png ├── test_database_1.gd ├── test_database_2.gd └── test_db_manager.gd ├── icon.png └── project.godot /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot-specific ignores 2 | .import/ 3 | export.cfg 4 | export_presets.cfg 5 | 6 | # Imported translations (automatically generated from CSV files) 7 | *.translation 8 | *.import 9 | 10 | # Mono-specific ignores 11 | .mono/ 12 | data_*/ 13 | 14 | # project specific 15 | screenshots/*.png 16 | bkp/*.* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 radubolovan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A database addon for Godot Engine. 2 | 3 | Documentation: 4 | - https://github.com/radubolovan/Godot-Database-Manager/tree/master/docs 5 | 6 | Contributing to the project: 7 | 1) Reporting bugs: 8 | Here is a template 9 | - Title: should be explicit as much as possible. Add "[BUG]" and "[Version]" tags in the title 10 | - Description: must NOT be blank; add as much words as possible explaining the bug and add reproduction steps 11 | - Add links to screenshots / movies if possible. 12 | 13 | 2) Ask for improvements: 14 | Here is a template 15 | - Title: should be explicit as much as possible. Add "[IMPROVEMENT]" tag in the title 16 | - Description: must NOT be blank; add as much words as possible explaining the request of the improvement 17 | - Add links to screenshots / movies if possible. 18 | 19 | 3) Ask to become a collaborator: 20 | - Send an e-mail to the owner of the project 21 | 22 | Current version: 2.1 23 | -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/fnt/roboto_08.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 8 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/fnt/roboto_10.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 10 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/fnt/roboto_12.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 12 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/fnt/roboto_14.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 14 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/fnt/roboto_16.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | font_data = ExtResource( 1 ) 7 | -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/fnt/roboto_18.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 18 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/fnt/roboto_20.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 20 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/fnt/roboto_22.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 22 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/fnt/roboto_24.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 24 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/fnt/roboto_26.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 26 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/tex/debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/addons/godot_db_manager/assets/tex/debug.png -------------------------------------------------------------------------------- /addons/godot_db_manager/assets/tex/gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/addons/godot_db_manager/assets/tex/gui.png -------------------------------------------------------------------------------- /addons/godot_db_manager/core/GDDBConstants.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBConstants 3 | """ 4 | 5 | class_name GDDBConstants 6 | 7 | tool 8 | extends Node 9 | 10 | # GDDB signature 11 | const c_gddb_signature = "GDDB_ver" 12 | 13 | # GDDB ver 14 | const c_gddb_ver = "2.0" 15 | 16 | # invalid id to initialize integer properties 17 | const c_invalid_id = -1 18 | 19 | # maximum database name length 20 | const c_max_db_name_len = 16 21 | 22 | # maximum table name length 23 | const c_max_table_name_len = 16 24 | 25 | # characters that should not be part of the database name 26 | const c_invalid_characters = "`~!@#$%^&*()=+[]{}\\|;:'\",<.>/?" 27 | 28 | # addon main path 29 | const c_addon_main_path = "res://addons/godot_db_manager/" 30 | 31 | # maximum tables list width 32 | const c_max_tables_list_width = 400.0 33 | 34 | # minimum cell width 35 | const c_min_cell_width = 150.0 36 | 37 | # maximum cell width 38 | const c_max_cell_width = 400.0 39 | -------------------------------------------------------------------------------- /addons/godot_db_manager/core/GDDBGlobals.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBGlobals 3 | """ 4 | 5 | class_name GDDBGlobals 6 | 7 | tool 8 | extends Node 9 | 10 | # a flag that tells if the tool's interface is active or not 11 | var m_is_interface_active : bool = false 12 | 13 | # sets the active flag 14 | func set_interface_active(active : bool) -> void : 15 | m_is_interface_active = active 16 | 17 | # returns true if the tool's interface is active 18 | func is_interface_active() -> bool : 19 | return m_is_interface_active 20 | 21 | # returns the name of the data type 22 | func get_data_name(data_type : int) -> String : 23 | if(data_type == gddb_types.e_prop_type_bool): 24 | return "Bool" 25 | elif(data_type == gddb_types.e_prop_type_int): 26 | return "Integer" 27 | elif(data_type == gddb_types.e_prop_type_float): 28 | return "Float" 29 | elif(data_type == gddb_types.e_prop_type_string): 30 | return "String" 31 | elif(data_type == gddb_types.e_prop_type_resource): 32 | return "Resource" 33 | 34 | print("GDDBGlobals::get_data_name(" + str(data_type) + ")") 35 | return "Unknown data type" 36 | 37 | # returns the name of the data filter 38 | func get_data_filter_name(data_filter_type : int) -> String : 39 | if(data_filter_type == gddb_types.e_data_filter_equal): 40 | return "Equal" 41 | elif(data_filter_type == gddb_types.e_data_filter_not_equal): 42 | return "Not equal" 43 | elif(data_filter_type == gddb_types.e_data_filter_less): 44 | return "Less" 45 | elif(data_filter_type == gddb_types.e_data_filter_greater): 46 | return "Greater" 47 | elif(data_filter_type == gddb_types.e_data_filter_lequal): 48 | return "Less or equal" 49 | elif(data_filter_type == gddb_types.e_data_filter_gequal): 50 | return "Greater or equal" 51 | 52 | print("GDDBGlobals::get_data_filter_name(" + str(data_filter_type) + ")") 53 | return "Unknown data filter type" 54 | 55 | # checks the name of the database 56 | func check_db_name(db_name : String) -> bool : 57 | for idx in range(0, db_name.length()): 58 | for jdx in range(0, gddb_constants.c_invalid_characters.length()): 59 | if(db_name[idx] == gddb_constants.c_invalid_characters[jdx]): 60 | return false 61 | return true 62 | 63 | # returns a json from a row from a table 64 | func get_json_from_row(table : Object, row_idx : int) -> String : 65 | var json = "{" 66 | var row = table.get_data_at_row_idx(row_idx) 67 | for jdx in range(0, row.size()): 68 | var prop = table.get_prop_at(jdx) 69 | json += "\"" + prop.get_prop_name() + "\":" 70 | json += "\"" + row[jdx].get_data() + "\"" 71 | if(jdx < row.size() - 1): 72 | json += ", " 73 | json += "}" 74 | return json 75 | 76 | # returns the digits count from a number 77 | func get_digits_count(number : int) -> int : 78 | if(number == 0): 79 | return 1 80 | 81 | var digits_count = 0 82 | while(number > 0): 83 | number /= 10 84 | digits_count += 1 85 | 86 | return digits_count 87 | 88 | # replace special characters in a string to handle properly saving into database 89 | func handle_string(text : String) -> String : 90 | var string = "" 91 | for idx in range(0, text.length()): 92 | if(text[idx] == "\n"): 93 | string += "\\n" 94 | else: 95 | string += text[idx] 96 | return string 97 | -------------------------------------------------------------------------------- /addons/godot_db_manager/core/GDDBTypes.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBTypes 3 | """ 4 | 5 | class_name GDDBTypes 6 | 7 | tool 8 | extends Node 9 | 10 | # Database loading errors 11 | enum { 12 | e_db_invalid_file = -11, 13 | e_db_invalid_ver = -10, 14 | e_db_valid = 0 15 | } 16 | 17 | # Property types 18 | enum { 19 | e_prop_type_bool = 0 20 | e_prop_type_int = 1, 21 | e_prop_type_float = 2, 22 | e_prop_type_string = 3, 23 | 24 | # TODO: insert more data types here and increase e_prop_type_resource 25 | 26 | e_prop_type_resource = 4, 27 | 28 | e_prop_types_count 29 | } 30 | 31 | # Data filters 32 | enum { 33 | e_data_filter_equal = 0, 34 | e_data_filter_not_equal = 1, 35 | e_data_filter_less = 2, 36 | e_data_filter_greater = 3, 37 | e_data_filter_lequal = 4, # less or equal 38 | e_data_filter_gequal = 5 # greater or equal 39 | } 40 | 41 | # new table dlg type 42 | enum { 43 | e_new_dlg_type_new = 0, 44 | e_new_dlg_type_edit = 1 45 | } 46 | -------------------------------------------------------------------------------- /addons/godot_db_manager/core/database.gd: -------------------------------------------------------------------------------- 1 | """ 2 | GDDatabase class 3 | """ 4 | 5 | class_name GDDatabase 6 | 7 | extends Object 8 | 9 | # database types 10 | enum { 11 | e_db_type_json = 0, # JSON database 12 | e_db_type_binary = 1 # binary database - to be designed / implemented 13 | } 14 | 15 | # database type 16 | var m_db_type : int = e_db_type_json 17 | 18 | # the id of the database 19 | var m_db_id : int = gddb_constants.c_invalid_id 20 | 21 | # the name of the database 22 | var m_db_name : String = "" 23 | 24 | # tables in the database 25 | var m_tables : Array = [] 26 | 27 | # the path of the database 28 | var m_db_filepath : String = "" 29 | 30 | # if the database is not saved, it is dirty 31 | var m_is_dirty : bool = false 32 | 33 | # sets the id of the database 34 | func set_db_id(db_id : int) -> void : 35 | m_db_id = db_id 36 | 37 | # returns the database id 38 | func get_db_id() -> int : 39 | return m_db_id 40 | 41 | # set the name of the database 42 | # the name of the database should not contain special characters 43 | func set_db_name(db_name : String) -> bool : 44 | if(!gddb_globals.check_db_name(db_name)): 45 | print("ERROR: GDDatabase::set_db_name(" + db_name + ") - the name of the database contains invalid characters") 46 | return false 47 | # print("GDDatabase::set_db_name(" + db_name + ")") 48 | m_db_name = db_name 49 | return true 50 | 51 | # returns the name of the database 52 | func get_db_name() -> String : 53 | return m_db_name 54 | 55 | # sets the database file path 56 | func set_db_filepath(filepath : String) -> void : 57 | m_db_filepath = filepath 58 | 59 | # returns the path of the database 60 | func get_db_filepath() -> String : 61 | return m_db_filepath 62 | 63 | # checks if a table with the name "table_name" can be added into database 64 | func can_add_table(table_name : String, table_id : int = -1) -> bool : 65 | # print("GDDatabase::can_add_table(" + table_name + ", " + str(table_id) + ")") 66 | for idx in range(0, m_tables.size()): 67 | if(m_tables[idx].get_table_name() == table_name): 68 | if(m_tables[idx].get_table_id() == table_id): 69 | continue 70 | print("WARNING: GDDatabase::can_add_table(" + table_name + ", " + str(table_id) + ") - table already exists") 71 | return false 72 | return true 73 | 74 | # adds a new table 75 | # returns the table id; if already exists, it will fire an warning on output console and returns an invalid id 76 | func add_table(table_name : String) -> int : 77 | if(!can_add_table(table_name)): 78 | print("WARNING: GDDatabase::add_table(" + table_name + ") - cannot add table") 79 | return gddb_constants.c_invalid_id 80 | 81 | # print("GDDatabase::add_table(" + table_name + ") to \"" + m_db_name + "\" database") 82 | 83 | var table_id = generate_new_table_id() 84 | var table = load(gddb_constants.c_addon_main_path + "core/db_table.gd").new() 85 | table.set_table_id(table_id) 86 | table.set_table_name(table_name) 87 | table.set_parent_database(self) 88 | m_tables.push_back(table) 89 | return table_id 90 | 91 | # edits a table name 92 | func edit_table_name(table_name : String, table_id : int) -> bool : 93 | if(!can_add_table(table_name, table_id)): 94 | return false 95 | for idx in range(0, m_tables.size()): 96 | if(m_tables[idx].get_table_id() == table_id): 97 | m_tables[idx].set_table_name(table_name) 98 | break 99 | return true 100 | 101 | # deletes a table at index 102 | func delete_table_at(idx : int) -> void : 103 | if(idx < 0 || idx > m_tables.size() - 1): 104 | print("GDDatabase::delete_table_at(" + str(idx) + ") - index out of bounds") 105 | return 106 | m_tables[idx].clear() 107 | m_tables[idx].free() 108 | m_tables.remove(idx) 109 | 110 | # deletes a table by id 111 | func delete_table_by_id(table_id: int) -> void : 112 | for idx in range(0, m_tables.size()): 113 | if(m_tables[idx].get_table_id() == table_id): 114 | # print("GDDatabase::delete_table_by_id(" + str(table_id) + ")") 115 | m_tables[idx].clear() 116 | m_tables[idx].free() 117 | m_tables.remove(idx) 118 | return 119 | print("ERROR: GDDatabase::delete_table_by_id(" + str(table_id) + ") - cannot erase table; id not found") 120 | 121 | # deletes a table by name 122 | func delete_table_by_name(table_name: String) -> void : 123 | for idx in range(0, m_tables.size()): 124 | if(m_tables[idx].get_table_name() == table_name): 125 | # print("GDDatabase::delete_table_by_name(" + table_name + ")") 126 | m_tables[idx].clear() 127 | m_tables[idx].free() 128 | m_tables.remove(idx) 129 | return 130 | print("ERROR: GDDatabase::delete_table_by_name(" + table_name + ") - cannot erase table; name not found") 131 | 132 | # generates a new table id 133 | func generate_new_table_id() -> int : 134 | if(m_tables.size() == 0): 135 | return 0 136 | return m_tables[m_tables.size()-1].get_table_id() + 1 137 | 138 | # returns the count of the tables in the database 139 | func get_tables_count() -> int : 140 | return m_tables.size() 141 | 142 | # returns true if the table exists in the database, false otherwise 143 | # this is equivalent with (get_table_by_name(table name) != null) function, but without firing the error in case the table doesn't exist 144 | func is_table_exists(table_name : String) -> bool : 145 | for idx in range(0, m_tables.size()): 146 | if(m_tables[idx].get_table_name() == table_name): 147 | return true 148 | return false 149 | 150 | # returns a table by an index or null if the index is invalid 151 | func get_table_at(idx: int) -> Object : 152 | if(idx < 0 || idx >= m_tables.size()): 153 | print("ERROR: GDDatabase::get_table_at(" + str(idx) + ") - cannot obtain table with index") 154 | return null 155 | return m_tables[idx] 156 | 157 | # returns a table by its id or null if a table with id doesn's exist 158 | func get_table_by_id(table_id: int) -> Object : 159 | for idx in range(0, m_tables.size()): 160 | if(m_tables[idx].get_table_id() == table_id): 161 | return m_tables[idx] 162 | print("ERROR: GDDatabase::get_table_by_id(" + str(table_id) + ") - cannot obtain table with id") 163 | return null 164 | 165 | # returns a table by its name or null if the name of the table doesn's exist 166 | func get_table_by_name(table_name: String) -> Object : 167 | for idx in range(0, m_tables.size()): 168 | if(m_tables[idx].get_table_name() == table_name): 169 | return m_tables[idx] 170 | print("ERROR: GDDatabase::get_table_by_id(" + table_name + ") - cannot obtain table with name") 171 | return null 172 | 173 | # deletes all the tables 174 | func clear() -> void : 175 | # print("GDDatabase::clear()") 176 | m_db_name = "" 177 | for idx in range(0, m_tables.size()): 178 | m_tables[idx].clear() 179 | m_tables.clear() 180 | 181 | # sets the database dirty; it is not saved 182 | func set_dirty(dirty : bool) -> void : 183 | m_is_dirty = dirty 184 | 185 | # returns true if a database is dirty (should be saved), false otherwise 186 | func is_dirty() -> bool : 187 | return m_is_dirty 188 | 189 | # serialization 190 | func save_db() -> void : 191 | if(m_db_name.empty()): 192 | print("ERROR: GDDatabase::save_db() - current database doesn't have a name") 193 | return 194 | 195 | if(m_db_filepath.empty()): 196 | print("ERROR: GDDatabase::save_db() - current database doesn't have a path file") 197 | return 198 | 199 | # print("GDDatabase::save_db() - " + m_db_name + " to: " + m_db_filepath) 200 | var text = "{" 201 | text += "\n\t\"" + gddb_constants.c_gddb_signature + "\":\"" + gddb_constants.c_gddb_ver + "\"," 202 | text += "\n\t\"db_name\":\"" + m_db_name + "\"," 203 | text += "\n\t\"tables\":[" 204 | for idx in range(0, m_tables.size()): 205 | text += "\n\t\t{" 206 | text += "\n\t\t\t\"table_name\":\"" + m_tables[idx].get_table_name() + "\"," 207 | text += "\n\t\t\t\"props\":[" 208 | for jdx in range(0, m_tables[idx].get_props_count()): 209 | var db_prop = m_tables[idx].get_prop_at(jdx) 210 | text += "\n\t\t\t\t\t{" 211 | text += "\"name\":\"" + str(db_prop.get_prop_name()) + "\"," 212 | 213 | var prop_type = db_prop.get_prop_type() 214 | if(prop_type < gddb_types.e_prop_types_count): 215 | text += "\"type\":\"" + str(prop_type) + "\"," 216 | else: 217 | # print("GDDatabase::save_db() - prop_type: " + str(prop_type)) 218 | var table_id = prop_type - gddb_types.e_prop_types_count 219 | var table = get_table_by_id(table_id) 220 | if(null == table): 221 | print("GDDatabase::save_db() - table not found with id: " + str(table_id)) 222 | text += "\"type\":\"" + "table" + "\"," 223 | text += "\"table_name\":\"" + table.get_table_name() + "\"," 224 | 225 | text += "\"auto_increment\":\"" + str(int(db_prop.has_autoincrement())) + "\"" 226 | 227 | text += "}" 228 | if(jdx < m_tables[idx].get_props_count() - 1): 229 | text += "," 230 | text += "\n\t\t\t]," 231 | 232 | text += "\n\t\t\t\"data\":[" 233 | for jdx in range(0, m_tables[idx].get_data_size()): 234 | #var the_data = m_tables[idx].get_data_at(jdx) 235 | #print("getting data at " + str(jdx) + " : " + the_data) 236 | text += "\"" + m_tables[idx].get_data_at(jdx) + "\"" 237 | if(jdx < m_tables[idx].get_data_size() - 1): 238 | text += "," 239 | text += "]" # end of data 240 | text += "\n\t\t}" # end of table 241 | 242 | if(idx < m_tables.size() - 1): 243 | text += "," 244 | 245 | text += "\n\t]\n}" 246 | 247 | var save_file = File.new() 248 | save_file.open(m_db_filepath, File.WRITE) 249 | save_file.store_string(text) 250 | save_file.close() 251 | 252 | set_dirty(false) 253 | 254 | # deserialization 255 | func load_db() -> int : 256 | var file = File.new() 257 | file.open(get_db_filepath(), File.READ) 258 | var content = file.get_as_text() 259 | file.close() 260 | var dictionary = JSON.parse(content).result 261 | 262 | # check the signature 263 | if(!dictionary.has(gddb_constants.c_gddb_signature)): 264 | print("GDDatabase::load_db() - invalid database file") 265 | return gddb_types.e_db_invalid_file 266 | 267 | var gddb_signature = dictionary[gddb_constants.c_gddb_signature] 268 | if(gddb_signature != gddb_constants.c_gddb_ver): 269 | print("GDDatabase::load_db() - invalid database version") 270 | return gddb_types.e_db_invalid_ver 271 | 272 | clear() 273 | m_db_name = dictionary["db_name"] 274 | var tables = dictionary["tables"] 275 | for idx in range(0, tables.size()): 276 | var table_id = add_table(tables[idx]["table_name"]) 277 | var table = get_table_by_id(table_id) 278 | 279 | var props_count = tables[idx]["props"].size() 280 | if(props_count == 0): 281 | continue 282 | 283 | for jdx in range(0, props_count): 284 | var prop_type = tables[idx]["props"][jdx]["type"] 285 | 286 | var prop_id = -1 287 | if(prop_type == "table"): 288 | var table_name = tables[idx]["props"][jdx]["table_name"] 289 | prop_id = table.add_table_prop(tables[idx]["props"][jdx]["name"], table_name) 290 | else: 291 | prop_id = table.add_prop(prop_type.to_int(), tables[idx]["props"][jdx]["name"]) 292 | 293 | var prop = table.get_prop_by_id(prop_id) 294 | var enable_autoincrement = tables[idx]["props"][jdx]["auto_increment"].to_int() 295 | prop.enable_autoincrement(bool(enable_autoincrement)) 296 | 297 | var data_count = tables[idx]["data"].size() 298 | #print("********* set data to db - begin") 299 | for jdx in range(0, data_count / props_count): 300 | var row_data = [] 301 | for kdx in range(0, props_count): 302 | var cell_data = tables[idx]["data"][jdx * props_count + kdx] 303 | # print("cell_data: " + cell_data) 304 | row_data.push_back(cell_data) 305 | #print("row_data: " + str(row_data)) 306 | table.add_row(row_data) 307 | #print("********* set data to db - end") 308 | 309 | # link custom data to tables 310 | for idx in range(0, m_tables.size()): 311 | m_tables[idx].link_tables_props() 312 | 313 | return gddb_types.e_db_valid 314 | 315 | # dumps the database 316 | func dump() -> String : 317 | var dump_text = "\nDatabase dump. id: " + str(m_db_id) + ", name: " + m_db_name + ", filepath: " + m_db_filepath 318 | dump_text += "\n------------------------------------------------------------------------------------\n" 319 | 320 | for idx in range(0, m_tables.size()): 321 | dump_text += "\n" + m_tables[idx].dump() 322 | 323 | return dump_text 324 | -------------------------------------------------------------------------------- /addons/godot_db_manager/core/db_data.gd: -------------------------------------------------------------------------------- 1 | """ 2 | GDDBData class 3 | """ 4 | 5 | class_name GDDBData 6 | 7 | extends Object 8 | 9 | var m_prop_id : int = -1 10 | var m_row_idx : int = -1 11 | var m_data : String = "" 12 | 13 | # sets the property id 14 | func set_prop_id(prop_id : int) -> void : 15 | m_prop_id = prop_id 16 | 17 | # returns the property id 18 | func get_prop_id() -> int : 19 | return m_prop_id 20 | 21 | # sets the row index 22 | func set_row_idx(row_idx : int) -> void : 23 | m_row_idx = row_idx 24 | 25 | # returns the row index 26 | func get_row_idx() -> int : 27 | return m_row_idx 28 | 29 | # sets the data 30 | func set_data(data : String) -> void : 31 | m_data = data 32 | 33 | # returns the data 34 | func get_data() -> String : 35 | return m_data 36 | 37 | # dumps the data 38 | func dump() -> String : 39 | var dump_text = "prop_id: " + str(m_prop_id) + ", row_idx: " + str(m_row_idx) + ", data: " + m_data 40 | return dump_text 41 | -------------------------------------------------------------------------------- /addons/godot_db_manager/core/db_man.gd: -------------------------------------------------------------------------------- 1 | """ 2 | GDDBMan class 3 | """ 4 | 5 | class_name GDDBMan 6 | 7 | extends Object 8 | 9 | var m_databases = [] 10 | 11 | # adds a database 12 | func add_database(db_name : String) -> int : 13 | if(!can_add_db(db_name)): 14 | print("ERROR: GDDBMan::add_database(" + db_name + ") already exists") 15 | return gddb_constants.c_invalid_id 16 | # print("GDDBMan::add_database(" + db_name + ")") 17 | var db_id = generate_new_db_id() 18 | var db = load(gddb_constants.c_addon_main_path + "core/database.gd").new() 19 | db.set_db_id(db_id) 20 | db.set_db_name(db_name) 21 | m_databases.push_back(db) 22 | return db_id 23 | 24 | # loads a database from a file 25 | func load_database(filepath : String) -> int : 26 | var db_id = generate_new_db_id() 27 | var db = load(gddb_constants.c_addon_main_path + "core/database.gd").new() 28 | db.set_db_id(db_id) 29 | db.set_db_filepath(filepath) 30 | 31 | if(db.load_db() == gddb_types.e_db_invalid_file): 32 | db.free() 33 | return gddb_types.e_db_invalid_file 34 | 35 | elif(db.load_db() == gddb_types.e_db_invalid_ver): 36 | db.free() 37 | return gddb_types.e_db_invalid_ver 38 | 39 | m_databases.push_back(db) 40 | return db_id 41 | 42 | # erases a database at index 43 | # it does not erase the database file 44 | func erase_db_at(idx : int) -> void : 45 | if(idx < 0 || idx > m_databases.size() - 1): 46 | print("ERROR: GDDBMan::erase_db_at(" + str(idx) + ") - index out of bounds") 47 | 48 | m_databases[idx].clear() 49 | m_databases[idx].free() 50 | m_databases.remove(idx) 51 | 52 | # erases a database by id 53 | # it does not erase the database file 54 | func erase_db_by_id(db_id : int) -> void : 55 | var db_found = false 56 | for idx in range(0, m_databases.size()): 57 | if(m_databases[idx].get_db_id() == db_id): 58 | m_databases[idx].clear() 59 | m_databases[idx].free() 60 | m_databases.remove(idx) 61 | db_found = true 62 | break 63 | 64 | if(!db_found): 65 | print("ERROR: GDDBMan::erase_db_by_id(" + str(db_id) + ") - database not found") 66 | 67 | # erases a database by name 68 | # it does not erase the database file 69 | func erase_db_by_name(db_name : String) -> void : 70 | var db_found = false 71 | for idx in range(0, m_databases.size()): 72 | if(m_databases[idx].get_db_name() == db_name): 73 | m_databases[idx].clear() 74 | m_databases[idx].free() 75 | m_databases.remove(idx) 76 | db_found = true 77 | break 78 | 79 | if(!db_found): 80 | print("ERROR: GDDBMan::erase_db_by_id(" + db_name + ") - database not found") 81 | 82 | # returns the databases count 83 | func get_databases_count() -> int : 84 | return m_databases.size() 85 | 86 | # returns a database at index 87 | func get_db_at(idx : int) -> Object : 88 | if(idx < 0 || idx >= m_databases.size()): 89 | print("ERROR: GDDBMan::get_db_at(" + str(idx) + ") - invalid index") 90 | return null 91 | return m_databases[idx] 92 | 93 | # returns a database by an id 94 | func get_db_by_id(db_id : int) -> Object : 95 | for idx in range(0, m_databases.size()): 96 | if(m_databases[idx].get_db_id() == db_id): 97 | return m_databases[idx] 98 | print("ERROR: GDDBMan::get_db_by_id(" + str(db_id) + ") - invalid id") 99 | return null 100 | 101 | # returns a database by a name 102 | func get_db_by_name(db_name : String) -> Object : 103 | for idx in range(0, m_databases.size()): 104 | if(m_databases[idx].get_db_name() == db_name): 105 | return m_databases[idx] 106 | return null 107 | 108 | # generates a new table id 109 | func generate_new_db_id() -> int : 110 | if(m_databases.size() == 0): 111 | return 0 112 | return m_databases[m_databases.size()-1].get_db_id() + 1 113 | 114 | # checks if a database already exists 115 | func can_add_db(db_name : String) -> bool : 116 | for idx in range(0, m_databases.size()): 117 | if(m_databases[idx].get_db_name() == db_name): 118 | print("ERROR: Database with name \"" + db_name + "\" already exists") 119 | return false 120 | return true 121 | 122 | # deletes all databases 123 | func clear() -> void : 124 | for idx in range(0, m_databases.size()): 125 | m_databases[idx].clear() 126 | m_databases[idx].free() 127 | m_databases.clear() 128 | 129 | # dumps all databases 130 | func dump(to_console : bool = false) -> String : 131 | var dump_text = "\nDatabase manager - dump" 132 | 133 | dump_text += "\n====================================================================================" 134 | for idx in range(0, m_databases.size()): 135 | dump_text += m_databases[idx].dump() 136 | dump_text += "====================================================================================" 137 | 138 | if(to_console): 139 | print(dump_text) 140 | 141 | return dump_text 142 | -------------------------------------------------------------------------------- /addons/godot_db_manager/core/db_prop.gd: -------------------------------------------------------------------------------- 1 | """ 2 | GDDBProperty class 3 | """ 4 | 5 | class_name GDDBProperty 6 | 7 | extends Object 8 | 9 | var m_prop_id : int = -1 10 | var m_prop_type : int = gddb_types.e_prop_type_int 11 | var m_custom_type : String = "" 12 | var m_prop_name : String = "" 13 | 14 | var m_autoincrement : bool = false 15 | 16 | # sets the property id 17 | func set_prop_id(prop_id : int) -> void : 18 | m_prop_id = prop_id 19 | 20 | # returns the property id 21 | func get_prop_id() -> int : 22 | return m_prop_id 23 | 24 | # sets the property type 25 | func set_prop_type(prop_type : int) -> void : 26 | m_prop_type = prop_type 27 | 28 | # returns the property type 29 | func get_prop_type() -> int : 30 | return m_prop_type 31 | 32 | # sets the custom type 33 | func set_prop_custom_type(prop_type : String) -> void : 34 | m_custom_type = prop_type 35 | 36 | # returns the custom type 37 | func get_prop_custom_type() -> String : 38 | return m_custom_type 39 | 40 | # sets the property name 41 | func set_prop_name(prop_name : String) -> void : 42 | m_prop_name = prop_name 43 | 44 | # returns the property name 45 | func get_prop_name() -> String : 46 | return m_prop_name 47 | 48 | # enables or disables the auto increment property 49 | func enable_autoincrement(enable : bool) -> void : 50 | if(enable && m_prop_type != gddb_types.e_prop_type_int): 51 | if(m_prop_type < gddb_types.e_prop_types_count): 52 | print("ERROR: autoincrement option can be set to integer data type only. Type is: " + gddb_types.get_data_name(m_prop_type)) 53 | else: 54 | print("ERROR: autoincrement option can be set to integer data type only. Custom type is: " + m_custom_type) 55 | return 56 | m_autoincrement = enable 57 | 58 | # returns if the property has auto increment 59 | func has_autoincrement() -> bool : 60 | return m_autoincrement 61 | 62 | # dumps the property 63 | func dump() -> String : 64 | var dump_text = "prop_id: " + str(m_prop_id) + ", prop_name: " + m_prop_name 65 | 66 | if(m_prop_type <= gddb_types.e_prop_type_resource): 67 | dump_text += ", prop_type: " + gddb_globals.get_data_name(m_prop_type) 68 | else: 69 | dump_text += ", custom_prop_type: " + m_custom_type 70 | 71 | return dump_text 72 | -------------------------------------------------------------------------------- /addons/godot_db_manager/core/db_table.gd: -------------------------------------------------------------------------------- 1 | """ 2 | GDDBTable class 3 | """ 4 | 5 | class_name GDDBTable 6 | 7 | extends Object 8 | 9 | var m_table_id : int = gddb_constants.c_invalid_id 10 | var m_table_name : String = "" 11 | var m_props : Array = [] 12 | var m_data : Array = [] 13 | var m_rows_count : int = 0 14 | 15 | var m_parent_database : Object = null 16 | 17 | # sets the table id 18 | func set_table_id(table_id : int) -> void : 19 | # print("GDDBDTable::set_table_id(" + str(table_id) + ")") 20 | m_table_id = table_id 21 | 22 | # returns the table id 23 | func get_table_id() -> int : 24 | return m_table_id 25 | 26 | # sets the table name 27 | func set_table_name(table_name: String) -> void : 28 | # print("GDDBDTable::set_table_name(" + table_name + ")") 29 | m_table_name = table_name 30 | 31 | # returns the table name 32 | func get_table_name() -> String : 33 | return m_table_name 34 | 35 | # sets the parent database 36 | func set_parent_database(db : Object) -> void : 37 | # print("GDDBTable::set_parent_database(" + str(db) + ")") 38 | m_parent_database = db 39 | 40 | # returns parent database 41 | func get_parent_database() -> Object : 42 | return m_parent_database 43 | 44 | # adds a property in the table structure as a base type 45 | # returns prop ID 46 | func add_prop(prop_type : int, prop_name : String) -> int : 47 | var prop_id = generate_new_prop_id() 48 | 49 | # print("GDDBDTable::add_prop(" + str(prop_id) + ", " + str(prop_type) + ", " + prop_name + ")") 50 | var prop = load(gddb_constants.c_addon_main_path + "core/db_prop.gd").new() 51 | prop.set_prop_id(prop_id) 52 | prop.set_prop_type(prop_type) 53 | prop.set_prop_name(prop_name) 54 | m_props.push_back(prop) 55 | 56 | # adding blank data to all existing rows 57 | # TODO: find a way to make this better; this is ugly 58 | if(m_data.size() > 0): 59 | var new_data_array = [] 60 | var data_idx = 0 61 | var row_idx = 0 62 | while(true): 63 | var data = m_data[data_idx] 64 | row_idx = data.get_row_idx() 65 | if(data.get_prop_id() + 1 == prop_id): 66 | new_data_array.push_back(data) 67 | var new_data = load(gddb_constants.c_addon_main_path + "core/db_data.gd").new() 68 | new_data.set_prop_id(prop_id) 69 | new_data.set_row_idx(row_idx) 70 | 71 | if(prop_type == gddb_types.e_prop_type_bool): 72 | new_data.set_data("0") 73 | 74 | elif(prop_type == gddb_types.e_prop_type_int): 75 | if(prop.has_autoincrement()): 76 | new_data.set_data(str(m_rows_count+1)) 77 | else: 78 | new_data.set_data("0") 79 | 80 | elif(prop_type == gddb_types.e_prop_type_float): 81 | new_data.set_data("0.0") 82 | 83 | elif(prop_type == gddb_types.e_prop_type_string): 84 | new_data.set_data("") 85 | 86 | elif(prop_type == gddb_types.e_prop_type_resource): 87 | new_data.set_data("res://") 88 | 89 | elif(prop_type >= gddb_types.e_prop_types_count): 90 | new_data.set_data(str(-1)) 91 | 92 | new_data_array.push_back(new_data) 93 | else: 94 | new_data_array.push_back(data) 95 | 96 | data_idx += 1 97 | if(data_idx >= m_data.size()): 98 | break 99 | 100 | m_data.clear() 101 | for idx in range(0, new_data_array.size()): 102 | m_data.push_back(new_data_array[idx]) 103 | 104 | return prop_id 105 | 106 | # adds a property in the table structure as a table type 107 | # returns prop ID 108 | func add_table_prop(prop_name : String, table_name : String) -> int : 109 | # print("GDDBTable::add_table_prop(" + prop_name + ", " + table_name + ")") 110 | var prop_id = generate_new_prop_id() 111 | 112 | # print("GDDBDTable::add_prop(" + str(prop_id) + ", " + str(prop_type) + ", " + prop_name + ")") 113 | var prop = load(gddb_constants.c_addon_main_path + "core/db_prop.gd").new() 114 | prop.set_prop_id(prop_id) 115 | prop.set_prop_name(prop_name) 116 | prop.set_prop_custom_type(table_name) 117 | m_props.push_back(prop) 118 | 119 | return prop_id 120 | 121 | # links custom properties from tables 122 | func link_tables_props() -> void : 123 | for idx in range(0, m_props.size()): 124 | var custom_prop_type = m_props[idx].get_prop_custom_type() 125 | if(!custom_prop_type.empty()): 126 | var table = m_parent_database.get_table_by_name(custom_prop_type) 127 | m_props[idx].set_prop_type(gddb_types.e_prop_types_count + table.get_table_id()) 128 | m_props[idx].set_prop_custom_type("") 129 | 130 | # edits a property in the table structure 131 | func edit_prop(prop_id : int, prop_type : int, prop_name: String) -> void : 132 | for idx in range(0, m_props.size()): 133 | if(m_props[idx].get_prop_id() == prop_id): 134 | m_props[idx].set_prop_type(prop_type) 135 | m_props[idx].set_prop_name(prop_name) 136 | return 137 | 138 | print("ERROR: GDDBDTable::edit_prop(" + str(prop_id) + ", " + str(prop_type) + ", " + prop_name + ") - property not found") 139 | 140 | # enables or disables autoincrement on a property 141 | func enable_prop_autoincrement(prop_id : int, enable : bool) -> void : 142 | for idx in range(0, m_props.size()): 143 | if(m_props[idx].get_prop_id() == prop_id): 144 | m_props[idx].enable_autoincrement(enable) 145 | break 146 | 147 | # deletes a property and all the data from the table have the same property 148 | func delete_prop(prop_id : int) -> void : 149 | # print("db_table::delete_prop(" + str(prop_id) + ")") 150 | var prop_found = false 151 | for idx in range(0, m_props.size()): 152 | if(m_props[idx].get_prop_id() == prop_id): 153 | # print("Removing prop with id " + str(prop_id)) 154 | m_props[idx].free() 155 | m_props.remove(idx) 156 | prop_found = true 157 | break 158 | 159 | if(!prop_found): 160 | print("ERROR: GDDBDTable::delete_prop( " + str(prop_id) + " ) - property not found !") 161 | return 162 | 163 | # remove the data 164 | # this is very ugly, but I can't erase a subarray from an array in GDscript :( 165 | # backup what needs to be saved only 166 | var tmp_data = [] 167 | for idx in range(0, m_data.size()): 168 | if(m_data[idx].get_prop_id() == prop_id): 169 | continue 170 | tmp_data.push_back(m_data[idx]) 171 | # clear and restore data 172 | m_data.clear() 173 | for idx in range(0, tmp_data.size()): 174 | m_data.push_back(tmp_data[idx]) 175 | 176 | # generates a new table id 177 | func generate_new_prop_id() -> int : 178 | if(m_props.size() == 0): 179 | return 0 180 | 181 | return m_props[m_props.size()-1].get_prop_id() + 1 182 | 183 | # returns the properties count 184 | func get_props_count() -> int : 185 | return m_props.size() 186 | 187 | # returns the property at index or null if the index is out of bounds 188 | func get_prop_at(idx : int) -> Object : 189 | if(idx < 0 || idx >= m_props.size()): 190 | print("ERROR: GDDBDTable::get_prop_id( " + str(idx) + " ) - index out of bounds; max properties: " + str(m_props.size())) 191 | return null 192 | 193 | return m_props[idx] 194 | 195 | # returns a property by id or null if the id is not found 196 | func get_prop_by_id(prop_id : int) -> Object : 197 | for idx in range(0, m_props.size()): 198 | if(m_props[idx].get_prop_id() == prop_id): 199 | return m_props[idx] 200 | 201 | print("ERROR: GDDBDTable::get_prop_by_id(" + str(prop_id) + ") - property with id not found") 202 | return null 203 | 204 | # returns a property by name 205 | func get_prop_by_name(pror_name : String) -> Object : 206 | for idx in range(0, m_props.size()): 207 | if(m_props[idx].get_prop_name() == pror_name): 208 | return m_props[idx] 209 | 210 | print("ERROR: GDDBDTable::get_prop_by_name(" + str(pror_name) + ") - property with name not found") 211 | return null 212 | 213 | # adds a row with blank data 214 | func add_blank_row() -> void : 215 | # print("GDDBTable::add_blank_row()") 216 | var prop_type = gddb_types.e_prop_type_bool 217 | 218 | for idx in range(0, m_props.size()): 219 | var data = load(gddb_constants.c_addon_main_path + "core/db_data.gd").new() 220 | data.set_prop_id(m_props[idx].get_prop_id()) 221 | data.set_row_idx(m_rows_count) 222 | 223 | prop_type = m_props[idx].get_prop_type() 224 | 225 | if(prop_type == gddb_types.e_prop_type_bool): 226 | data.set_data("0") 227 | 228 | elif(prop_type == gddb_types.e_prop_type_int): 229 | if(m_props[idx].has_autoincrement()): 230 | data.set_data(str(m_rows_count+1)) 231 | else: 232 | data.set_data("0") 233 | 234 | elif(prop_type == gddb_types.e_prop_type_float): 235 | data.set_data("0.0") 236 | 237 | elif(prop_type == gddb_types.e_prop_type_string): 238 | data.set_data("") 239 | 240 | elif(prop_type == gddb_types.e_prop_type_resource): 241 | data.set_data("res://") 242 | 243 | elif(prop_type >= gddb_types.e_prop_types_count): 244 | data.set_data(str(-1)) 245 | 246 | m_data.push_back(data) 247 | 248 | m_rows_count += 1 249 | 250 | # adds a row with data 251 | func add_row(data_array : Array) -> void : 252 | if(data_array.size() != m_props.size()): 253 | print("ERROR: GDDBDTable::add_row( " + str(data_array) + " ) - cannot add row; properties count = " + str(m_props.size()) + " and data size = " + str(data_array.size())) 254 | return 255 | 256 | var prop_type = gddb_types.e_prop_type_bool 257 | var the_data = "" 258 | 259 | for idx in range(0, m_props.size()): 260 | var data = load(gddb_constants.c_addon_main_path + "core/db_data.gd").new() 261 | # print("adding data: [" + str(m_props[idx].get_prop_id()) + ", " + data_array[idx] + "]") 262 | # print("setting prop id: " + str(m_props[idx].get_prop_id())) 263 | 264 | data.set_prop_id(m_props[idx].get_prop_id()) 265 | data.set_row_idx(m_rows_count) 266 | 267 | # ignore data if the property has autoincrement option 268 | if(m_props[idx].has_autoincrement()): 269 | data.set_data(str(m_rows_count+1)) 270 | m_data.push_back(data) 271 | continue 272 | 273 | prop_type = m_props[idx].get_prop_type() 274 | the_data = data_array[idx] 275 | 276 | if(prop_type == gddb_types.e_prop_type_bool): 277 | data.set_data(str(the_data)) 278 | elif(prop_type == gddb_types.e_prop_type_int): 279 | data.set_data(str(the_data)) 280 | elif(prop_type == gddb_types.e_prop_type_float): 281 | data.set_data(str(the_data)) 282 | elif(prop_type == gddb_types.e_prop_type_string): 283 | data.set_data(gddb_globals.handle_string(the_data)) 284 | elif(prop_type == gddb_types.e_prop_type_resource): 285 | data.set_data(the_data) 286 | else: 287 | print("ERROR: data type doesn't exist - " + str(m_props[idx].get_prop_type())) 288 | 289 | m_data.push_back(data) 290 | 291 | m_rows_count += 1 292 | 293 | # removes a row 294 | func remove_row(row_idx : int) -> void : 295 | for idx in range(m_data.size()-1, 0, -1): 296 | if(m_data[idx].get_row_idx() == row_idx): 297 | m_data[idx].remove(idx) 298 | m_rows_count -= 1 299 | 300 | # returns the rows count 301 | func get_rows_count() -> int : 302 | return m_rows_count 303 | 304 | # edits the data 305 | func edit_data(prop_id : int, row_idx : int, data : String) -> void : 306 | # print("#1: GDDBTable::edit_data( " + str(prop_id) + ", " + str(row_idx) + ", " + data + " )") 307 | for idx in range(0, m_data.size()): 308 | # print("checking ( " + str(m_data[idx].get_row_idx()) + ", " + str(m_data[idx].get_prop_id()) + " )") 309 | if(m_data[idx].get_row_idx() == row_idx && m_data[idx].get_prop_id() == prop_id): 310 | # print("#2: GDDBTable::edit_data( " + str(prop_id) + ", " + str(row_idx) + ", " + data + " )") 311 | m_data[idx].set_data(data) 312 | return 313 | 314 | print("ERROR: GDDBDTable::edit_data(" + str(prop_id) + ", " + str(row_idx) + ", " + data + ") - can't find data to edit") 315 | 316 | # edits the data 317 | func edit_data_by_prop_name(prop_name : String, row_idx : int, data : String) -> void : 318 | # print("#1: GDDBTable::edit_data( " + str(prop_id) + ", " + str(row_idx) + ", " + data + " )") 319 | 320 | var prop_id = get_prop_by_name(prop_name).get_prop_id() 321 | edit_data(prop_id, row_idx, data) 322 | 323 | # returns data count 324 | func get_data_size() -> int : 325 | return m_data.size() 326 | 327 | # returns all data 328 | func get_all_data() -> Array : 329 | return m_data 330 | 331 | # returns the data at index 332 | func get_data_at(idx : int) -> String : 333 | if(idx < 0 || idx >= m_data.size()): 334 | print("ERROR: GDDBDTable::get_data_at( " + str(idx) + ") - max data size: " + str(m_data.size())) 335 | return "" 336 | 337 | return m_data[idx].get_data() 338 | 339 | # returns a dictionary containing the data at index 340 | func get_dictionary_at(idx : int) -> Dictionary : 341 | var dict = {} 342 | 343 | if(idx < 0 || idx >= m_data.size()): 344 | print("ERROR: GDDBDTable::get_data_at( " + str(idx) + ") - max data size: " + str(m_data.size())) 345 | return dict 346 | 347 | var prop_idx = idx % m_props.size() 348 | var data_prop_name = m_props[prop_idx].get_prop_name() 349 | dict[data_prop_name] = m_data[idx].get_data() 350 | 351 | return dict 352 | 353 | # returns the data by a property id and a row index 354 | func get_data(prop_id : int, row_idx : int) -> String : 355 | for idx in range(m_data.size()-1, 0, -1): 356 | if(m_data[idx].get_row_idx() == row_idx && m_data[idx].get_prop_id() == prop_id): 357 | return m_data[idx].get_data() 358 | 359 | print("ERROR: GDDBDTable::get_data(" + str(prop_id) + ", " + str(row_idx) + ")") 360 | return "" 361 | 362 | # returns a dictionary containing the data by a property id and a row index 363 | func get_dictionary(prop_id : int, row_idx : int) -> Dictionary : 364 | var dict = {} 365 | 366 | for idx in range(m_data.size()-1, 0, -1): 367 | if(m_data[idx].get_row_idx() == row_idx && m_data[idx].get_prop_id() == prop_id): 368 | var prop = get_prop_by_id(prop_id) 369 | var data_prop_name = prop.get_prop_name() 370 | dict[data_prop_name] = m_data[idx].get_data() 371 | return dict 372 | 373 | print("ERROR: GDDBDTable::get_data(" + str(prop_id) + ", " + str(row_idx) + ")") 374 | return dict 375 | 376 | # returns an array of data at row index 377 | func get_data_at_row_idx(row_idx : int) -> Array : 378 | var data = [] 379 | for idx in range(0, m_data.size()): 380 | if(m_data[idx].get_row_idx() == row_idx): 381 | data.push_back(m_data[idx]) 382 | 383 | if(data.size() == -1): 384 | print("ERROR: GDDBDTable::get_data_at_row_idx(" + str(row_idx) + ") - invalid row index") 385 | 386 | return data 387 | 388 | # returns a dictionary of data at row index 389 | func get_dictionary_at_row_idx(row_idx : int) -> Dictionary : 390 | var dict = {} 391 | 392 | var prop_idx = 0 393 | for idx in range(0, m_data.size()): 394 | if(m_data[idx].get_row_idx() == row_idx): 395 | var data_prop_name = m_props[prop_idx].get_prop_name() 396 | dict[data_prop_name] = m_data[idx].get_data() 397 | prop_idx += 1 398 | 399 | if(dict.empty()): 400 | print("ERROR: GDDBDTable::get_data_at_row_idx(" + str(row_idx) + ") - invalid row index") 401 | 402 | return dict 403 | 404 | # returns an array of data filtered by property id 405 | func get_data_by_prop_id(prop_id : int, data_filter : int = gddb_types.e_data_filter_equal) -> Array : 406 | var data = [] 407 | 408 | if(data_filter < gddb_types.e_data_filter_equal || data_filter >= gddb_types.e_data_filter_gequal): 409 | print("ERROR: cannot process filter " + str(data_filter)) 410 | return data 411 | 412 | for idx in range(0, m_data.size()): 413 | if(data_filter == gddb_types.e_data_filter_equal): 414 | if(m_data[idx].get_prop_id() == prop_id): 415 | data.push_back(m_data[idx]) 416 | 417 | elif(data_filter == gddb_types.e_data_filter_not_equal): 418 | if(m_data[idx].get_prop_id() != prop_id): 419 | data.push_back(m_data[idx]) 420 | 421 | elif(data_filter == gddb_types.e_data_filter_less): 422 | if(m_data[idx].get_prop_id() < prop_id): 423 | data.push_back(m_data[idx]) 424 | 425 | elif(data_filter == gddb_types.e_data_filter_greater): 426 | if(m_data[idx].get_prop_id() > prop_id): 427 | data.push_back(m_data[idx]) 428 | 429 | elif(data_filter == gddb_types.e_data_filter_lequal): 430 | if(m_data[idx].get_prop_id() <= prop_id): 431 | data.push_back(m_data[idx]) 432 | 433 | elif(data_filter == gddb_types.e_data_filter_gequal): 434 | if(m_data[idx].get_prop_id() >= prop_id): 435 | data.push_back(m_data[idx]) 436 | 437 | if(data.size() == 0): 438 | print("ERROR: GDDBDTable::get_data_by_prop_id(" + str(prop_id) + ", " + gddb_globals.get_data_filter_name(data_filter) + ") - filtered data not found") 439 | 440 | return data 441 | 442 | # returns an array of data by property name 443 | func get_data_by_prop_name(prop_name : String) -> Array : 444 | var prop_id = -1 445 | for idx in range(0, m_props.size()): 446 | if(m_props[idx].get_prop_name() == prop_name): 447 | prop_id = m_props[idx].get_prop_id() 448 | break 449 | 450 | if(prop_id == -1): 451 | print("ERROR: GDDBDTable::get_data_by_prop_name(" + prop_name + ") - property not found") 452 | return [] 453 | 454 | return get_data_by_prop_id(prop_id) 455 | 456 | # returns an array of data filtered by data 457 | # filters "<", ">", "<=" and ">=" are working for integer and float data types 458 | func get_data_by_data(data_value : String, data_filter : int = gddb_types.e_data_filter_equal) -> Array : 459 | var data = [] 460 | 461 | if(data_filter < gddb_types.e_data_filter_equal || data_filter >= gddb_types.e_data_filter_gequal): 462 | print("ERROR: cannot process filter " + str(data_filter)) 463 | return data 464 | 465 | for idx in range(0, m_data.size()): 466 | if(data_filter == gddb_types.e_data_filter_equal): 467 | if(m_data[idx].get_data() == data_value): 468 | data.push_back(m_data[idx]) 469 | 470 | elif(data_filter == gddb_types.e_data_filter_not_equal): 471 | if(m_data[idx].get_data() != data_value): 472 | data.push_back(m_data[idx]) 473 | 474 | elif(data_filter == gddb_types.e_data_filter_less): 475 | if(m_props[idx].get_prop_type() < gddb_types.e_prop_type_resource): 476 | if(m_data[idx].get_data() < data_value): 477 | data.push_back(m_data[idx]) 478 | 479 | elif(data_filter == gddb_types.e_data_filter_greater): 480 | if(m_props[idx].get_prop_type() < gddb_types.e_prop_type_resource): 481 | if(m_data[idx].get_data() > data_value): 482 | data.push_back(m_data[idx]) 483 | 484 | elif(data_filter == gddb_types.e_data_filter_lequal): 485 | if(m_props[idx].get_prop_type() < gddb_types.e_prop_type_resource): 486 | if(m_data[idx].get_data() <= data_value): 487 | data.push_back(m_data[idx]) 488 | 489 | elif(data_filter == gddb_types.e_data_filter_gequal): 490 | if(m_props[idx].get_prop_type() < gddb_types.e_prop_type_resource): 491 | if(m_data[idx].get_data() >= data_value): 492 | data.push_back(m_data[idx]) 493 | 494 | if(data.size() == 0): 495 | print("ERROR: GDDBDTable::get_data_by_data(" + data_value + ", " + gddb_globals.get_data_filter_name(data_filter) + ") - filtered data not found") 496 | 497 | return data 498 | 499 | # returns an array of data by a property name and a data value 500 | # similar to: select * from users where user_id = 1 501 | func get_data_by_prop_name_and_data(prop_name : String, data_value : String) -> Array : 502 | var the_array = [] 503 | 504 | var prop_idx = -1 505 | for idx in range(0, m_props.size()): 506 | if(m_props[idx].get_prop_name() == prop_name): 507 | prop_idx = idx 508 | break 509 | 510 | for idx in range(0, m_rows_count): 511 | var row_data = get_data_at_row_idx(idx) 512 | # print("Comparing row: " + row_data[0].get_data() + ", " + row_data[1].get_data() + ", " + row_data[2].get_data() + ", " + row_data[3].get_data() + ", " + row_data[4].get_data()) 513 | if(row_data[prop_idx].get_data() == data_value): 514 | var dict = get_dictionary_at_row_idx(idx) 515 | the_array.push_back(row_data) 516 | 517 | return the_array 518 | 519 | # returns a dictionary of data by a property name and a data value 520 | # similar to: select * from users where user_id = 1 521 | func get_dictionary_by_prop_name_and_data(prop_name : String, data_value : String) -> Array : 522 | var the_array = [] 523 | 524 | var prop_idx = -1 525 | for idx in range(0, m_props.size()): 526 | if(m_props[idx].get_prop_name() == prop_name): 527 | prop_idx = idx 528 | break 529 | 530 | for idx in range(0, m_rows_count): 531 | var row_data = get_data_at_row_idx(idx) 532 | # print("Comparing row: " + row_data[0].get_data() + ", " + row_data[1].get_data() + ", " + row_data[2].get_data() + ", " + row_data[3].get_data() + ", " + row_data[4].get_data()) 533 | if(row_data[prop_idx].get_data() == data_value): 534 | var dict = get_dictionary_at_row_idx(idx) 535 | the_array.push_back(get_dictionary_at_row_idx(idx)) 536 | 537 | return the_array 538 | 539 | # clears the table's structure and data 540 | func clear() -> void : 541 | # clear data 542 | clear_data() 543 | 544 | # clear properties 545 | for idx in range(0, m_props.size()): 546 | m_props[idx].free() 547 | m_props.clear() 548 | 549 | # clears the table's data 550 | func clear_data() -> void : 551 | for idx in range(0, m_data.size()): 552 | m_data[idx].free() 553 | m_data.clear() 554 | m_rows_count = 0 555 | 556 | # dumps the table 557 | func dump() -> String : 558 | var dump_text = "Table dump. id: " + str(m_table_id) + ", name: " + m_table_name + ", props_count: " + str(m_props.size()) + ", rows_count: " + str(m_rows_count) 559 | dump_text += "\n------------------------------------------------------------------------------------\nProperties:" 560 | 561 | for idx in range(0, m_props.size()): 562 | dump_text += "\n" + m_props[idx].dump() 563 | 564 | dump_text += "\n------------------------------------------------------------------------------------\nData:\n" 565 | 566 | for idx in range(0, m_rows_count): 567 | var tmp_text = "row_idx: " + "%" + str(gddb_globals.get_digits_count(m_rows_count)) + "d" 568 | dump_text += tmp_text % idx 569 | var row = get_data_at_row_idx(idx) 570 | for jdx in range(0, row.size()): 571 | dump_text += " | " + row[jdx].get_data() 572 | dump_text += "\n" 573 | 574 | return dump_text 575 | -------------------------------------------------------------------------------- /addons/godot_db_manager/data_label.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBDataLabel 3 | """ 4 | 5 | class_name GDDBDataLabel 6 | 7 | tool 8 | extends Label 9 | 10 | signal resize_property 11 | 12 | var m_prop_id : int = gddb_constants.c_invalid_id 13 | var m_prop_type : int = gddb_constants.c_invalid_id 14 | 15 | var m_mouse_pos_pressed : Vector2 = Vector2() 16 | var m_mouse_pressed : bool = false 17 | 18 | # Called when the node enters the scene tree for the first time. 19 | func _ready() -> void: 20 | set_custom_minimum_size(Vector2(150.0, 24.0)) 21 | 22 | # called when the node gets an input 23 | func _input(event : InputEvent) -> void : 24 | if(!gddb_globals.is_interface_active()): 25 | return 26 | 27 | var evLocal = $resize_ctrl.make_input_local(event) 28 | 29 | if event is InputEventMouseButton : 30 | if(event.button_index == BUTTON_LEFT): 31 | if(event.pressed): 32 | var rect = Rect2(Vector2(0, 0), $resize_ctrl.get_size()) 33 | var inside = rect.has_point(evLocal.position) 34 | if(inside): 35 | m_mouse_pressed = true 36 | m_mouse_pos_pressed = evLocal.position 37 | else: 38 | m_mouse_pressed = false 39 | 40 | elif event is InputEventMouseMotion : 41 | if(m_mouse_pressed): 42 | var diff_x = evLocal.position.x - m_mouse_pos_pressed.x 43 | emit_signal("resize_property", m_prop_id, diff_x) 44 | 45 | # sets property id 46 | func set_prop_id(id : int) -> void: 47 | m_prop_id = id 48 | 49 | # returns property id 50 | func get_prop_id() -> int: 51 | return m_prop_id 52 | 53 | # sets property type 54 | func set_prop_type(prop_type : int) -> void : 55 | m_prop_type = prop_type 56 | 57 | # returns property type 58 | func get_prop_type() -> int : 59 | return m_prop_type 60 | -------------------------------------------------------------------------------- /addons/godot_db_manager/data_label.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/data_label.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=3] 6 | [ext_resource path="res://addons/godot_db_manager/assets/tex/debug.png" type="Texture" id=4] 7 | 8 | [node name="lbl" type="Label"] 9 | anchor_right = 0.167 10 | margin_right = -0.300018 11 | margin_bottom = 11.52 12 | rect_min_size = Vector2( 150, 32 ) 13 | mouse_filter = 0 14 | custom_fonts/font = ExtResource( 2 ) 15 | text = "ID" 16 | valign = 1 17 | script = ExtResource( 1 ) 18 | __meta__ = { 19 | "_edit_horizontal_guides_": [ 24.0 ], 20 | "_edit_use_anchors_": true 21 | } 22 | 23 | [node name="dbg" type="NinePatchRect" parent="."] 24 | visible = false 25 | anchor_right = 1.0 26 | anchor_bottom = 1.0 27 | texture = ExtResource( 4 ) 28 | region_rect = Rect2( 86, 26, 10, 10 ) 29 | __meta__ = { 30 | "_edit_use_anchors_": false 31 | } 32 | 33 | [node name="resize_ctrl" type="NinePatchRect" parent="."] 34 | anchor_left = 1.0 35 | anchor_right = 1.0 36 | anchor_bottom = 1.0 37 | margin_left = -3.0 38 | mouse_filter = 0 39 | mouse_default_cursor_shape = 10 40 | texture = ExtResource( 3 ) 41 | region_rect = Rect2( 80, 12, 24, 24 ) 42 | __meta__ = { 43 | "_edit_use_anchors_": false 44 | } 45 | -------------------------------------------------------------------------------- /addons/godot_db_manager/db_editor.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBEditor 3 | """ 4 | 5 | class_name GDDBEditor 6 | 7 | tool 8 | extends Tabs 9 | 10 | var m_name = "" 11 | var m_database = null 12 | 13 | var m_filepath = "" 14 | 15 | # Called when the node enters the scene tree for the first time. 16 | func _ready() -> void : 17 | set_tab_align(Tabs.ALIGN_LEFT) 18 | set_tab_close_display_policy(Tabs.CLOSE_BUTTON_SHOW_ALWAYS) 19 | 20 | $tables_list.connect("resize_tables_list", self, "on_resize_the_table_list") 21 | $tables_list.connect("add_table", self, "on_add_table") 22 | $tables_list.connect("edit_table_name", self, "on_edit_table") 23 | $tables_list.connect("delete_table", self, "on_delete_table") 24 | $tables_list.connect("select_table", self, "on_select_table") 25 | 26 | $table_editor.connect("set_dirty", self, "on_set_dirty") 27 | 28 | $delete_table_dlg.connect("delete_table", self, "on_confirm_delete_table") 29 | 30 | $new_table_dlg.connect("cancel_dialog", self, "on_close_new_table_dlg") 31 | $new_table_dlg.get_close_button().connect("pressed", self, "on_close_new_table_dlg") 32 | 33 | $error_dlg.connect("confirmed", self, "on_retry_create_table") 34 | 35 | # resizing the tables list 36 | func on_resize_the_table_list(diff_x : float) -> void : 37 | var size = $tables_list.get_size() 38 | var min_size = $tables_list.get_custom_minimum_size() 39 | size.x += diff_x 40 | 41 | if(size.x < min_size.x): 42 | return 43 | 44 | if(size.x > gddb_constants.c_max_tables_list_width): 45 | return 46 | 47 | $tables_list.resize_content(size) 48 | 49 | var pos = $table_editor.get_position() 50 | size = $table_editor.get_size() 51 | pos.x += diff_x 52 | size.x -= diff_x 53 | $table_editor.set_position(pos) 54 | $table_editor.set_size(size) 55 | 56 | # overrides the member from base class 57 | func set_name(ctrl_name) -> void : 58 | m_name = ctrl_name 59 | .set_name(ctrl_name) 60 | 61 | # sets the database; for easy access 62 | func set_database(db) -> void : 63 | # print("GDDBEditor::set_database(" + db.get_db_name() + ") to " + get_name()) 64 | m_database = db 65 | set_dirty(true) 66 | 67 | var tables_count = db.get_tables_count() 68 | 69 | $table_editor.hide() 70 | 71 | for idx in range(0, tables_count): 72 | var table = db.get_table_at(idx) 73 | $tables_list.create_table(table, idx == 0) 74 | if(idx == 0): 75 | $table_editor.set_table(table) 76 | $table_editor.link_props() 77 | $table_editor.show() 78 | 79 | # returns the database id 80 | func get_db_id() -> int : 81 | if(null == m_database): 82 | return gddb_constants.c_invalid_id 83 | return m_database.get_db_id() 84 | 85 | # returns the database name 86 | func get_db_name() -> String : 87 | if(null == m_database): 88 | return "" 89 | return m_database.get_db_name() 90 | 91 | # sets the database to be dirty; should be saved 92 | func set_dirty(dirty) -> void : 93 | if(dirty): 94 | var title = m_name + "*" 95 | .set_name(title) 96 | else: 97 | .set_name(m_name) 98 | 99 | # called when the user presses the "add_table" button from the "tables_list/tables_header" 100 | func on_add_table() -> void : 101 | # print("GDDBEditor::on_add_table()") 102 | $new_table_dlg.set_dld_type(gddb_types.e_new_dlg_type_new) 103 | $new_table_dlg.set_table_id(gddb_constants.c_invalid_id) 104 | $new_table_dlg.set_init_name("") 105 | $new_table_dlg.connect("create_new_table", self, "on_create_table") 106 | $new_table_dlg.popup_centered() 107 | 108 | # called when the user accepts the name of the table in the "new_table_dlg" 109 | func on_create_table(table_name : String) -> void : 110 | # print("GDDBEditor::on_create_table(" + table_name + ")") 111 | $new_table_dlg.disconnect("create_new_table", self, "on_create_table") 112 | var table_id = m_database.add_table(table_name) 113 | if(table_id == gddb_constants.c_invalid_id): 114 | $error_dlg.set_text("Table with the name \"" + table_name + "\" already exists" ) 115 | $error_dlg.popup_centered() 116 | return 117 | var table = m_database.get_table_by_id(table_id) 118 | $tables_list.create_table(table) 119 | $table_editor.set_table(table) 120 | $table_editor.show() 121 | m_database.set_dirty(true) 122 | set_dirty(true) 123 | 124 | # called when the user retryes to create a table (changed the name) 125 | func on_retry_create_table() -> void : 126 | $new_table_dlg.set_init_name("") 127 | $new_table_dlg.popup_centered() 128 | 129 | # called when the user presses the "edit_table_name" from the "tables/list/table" 130 | func on_edit_table(table_id : int, table_name : String) -> void : 131 | # print("GDDBEditor::on_edit_table(" + str(table_id) + ", " + table_name + ")") 132 | $new_table_dlg.set_dld_type(gddb_types.e_new_dlg_type_edit) 133 | $new_table_dlg.set_table_id(table_id) 134 | $new_table_dlg.set_init_name(table_name) 135 | $new_table_dlg.connect("create_new_table", self, "on_table_name_edited") 136 | $new_table_dlg.popup_centered() 137 | 138 | # gets called when canceling the new_table_dlg 139 | func on_close_new_table_dlg() -> void : 140 | # print("GDDBEditor::on_close_new_table_dlg()") 141 | var dlg_type = $new_table_dlg.get_dlg_type() 142 | if(dlg_type == gddb_types.e_new_dlg_type_new): 143 | $new_table_dlg.disconnect("create_new_table", self, "on_create_table") 144 | elif(dlg_type == gddb_types.e_new_dlg_type_edit): 145 | $new_table_dlg.disconnect("create_new_table", self, "on_table_name_edited") 146 | 147 | # called when the user presses the "delete_table" from the "tables/list/table" 148 | func on_delete_table(table_id : int) -> void : 149 | # print("GDDBEditor::on_delete_table(" + str(table_id) + ")") 150 | var table = m_database.get_table_by_id(table_id) 151 | $delete_table_dlg.set_table_id(table_id) 152 | $delete_table_dlg.set_table_name(table.get_table_name()) 153 | $delete_table_dlg.popup_centered() 154 | 155 | # called when the user accepts the name of the table in the "new_table_dlg" 156 | func on_table_name_edited(table_name : String) -> void : 157 | # print("GDDBEditor::on_table_name_edited(" + table_name + ")") 158 | $new_table_dlg.disconnect("create_new_table", self, "on_table_name_edited") 159 | var table_id = $new_table_dlg.get_table_id() 160 | if(!m_database.edit_table_name(table_name, table_id)): 161 | $error_dlg.set_text("Table with the name \"" + table_name + "\" already exists" ) 162 | $error_dlg.popup_centered() 163 | return 164 | # print("GDDBEditor::on_table_name_edited(" + str(table_id) + ", " + table_name + ")") 165 | $tables_list.edit_table_name(table_id, table_name) 166 | m_database.set_dirty(true) 167 | set_dirty(true) 168 | 169 | # called when the user confirms to delete a table 170 | func on_confirm_delete_table() -> void : 171 | # print("GDDBEditor::on_confirm_delete_table()") 172 | var table_id = $delete_table_dlg.get_table_id() 173 | var selected_table = $tables_list.get_selected_item() 174 | if(null == selected_table): 175 | return 176 | var selected_table_id = selected_table.get_table_id() 177 | m_database.delete_table_by_id(table_id) 178 | $tables_list.delete_table(table_id) 179 | if(selected_table_id == table_id): 180 | $tables_list.select_item_at(0) 181 | var table = m_database.get_table_at(0) 182 | $table_editor.set_table(table) 183 | 184 | m_database.set_dirty(true) 185 | set_dirty(true) 186 | 187 | # called when the user selects a table from the table_list 188 | func on_select_table(table_id : int) -> void : 189 | var table = m_database.get_table_by_id(table_id) 190 | if(null != table): 191 | $table_editor.set_table(table) 192 | $table_editor.link_props() 193 | 194 | # saves current database 195 | func save_database() -> void: 196 | m_database.save_db() 197 | set_dirty(false) 198 | 199 | # returns true if the database can be saved, otherwise false 200 | func can_save_database() -> bool: 201 | return !m_database.get_db_filepath().empty() 202 | 203 | # sets the database's path 204 | func set_database_filepath(filepath : String) -> void: 205 | m_database.set_db_filepath(filepath) 206 | 207 | # called when a table is modified 208 | func on_set_dirty() -> void: 209 | m_database.set_dirty(true) 210 | set_dirty(true) 211 | -------------------------------------------------------------------------------- /addons/godot_db_manager/db_editor.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=8 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/db_editor.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/tables_list.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/dlgs/new_table_dlg.tscn" type="PackedScene" id=3] 6 | [ext_resource path="res://addons/godot_db_manager/table_editor.tscn" type="PackedScene" id=4] 7 | [ext_resource path="res://addons/godot_db_manager/dlgs/error_dlg.tscn" type="PackedScene" id=5] 8 | [ext_resource path="res://addons/godot_db_manager/dlgs/delete_table_dlg.tscn" type="PackedScene" id=6] 9 | [ext_resource path="res://addons/godot_db_manager/debug/dbg.tscn" type="PackedScene" id=7] 10 | 11 | [node name="db_editor" type="Tabs"] 12 | anchor_right = 1.0 13 | anchor_bottom = 1.0 14 | tab_align = 0 15 | tab_close_display_policy = 2 16 | script = ExtResource( 1 ) 17 | __meta__ = { 18 | "_edit_use_anchors_": true, 19 | "_edit_vertical_guides_": [ 170.0, 900.0 ] 20 | } 21 | 22 | [node name="tables_list" parent="." instance=ExtResource( 2 )] 23 | anchor_right = 0.0 24 | margin_right = 170.0 25 | rect_min_size = Vector2( 180, 30 ) 26 | 27 | [node name="table_editor" parent="." instance=ExtResource( 4 )] 28 | margin_left = 181.0 29 | 30 | [node name="dbg" parent="." instance=ExtResource( 7 )] 31 | visible = false 32 | 33 | [node name="new_table_dlg" parent="." instance=ExtResource( 3 )] 34 | visible = false 35 | 36 | [node name="delete_table_dlg" parent="." instance=ExtResource( 6 )] 37 | visible = false 38 | 39 | [node name="error_dlg" parent="." instance=ExtResource( 5 )] 40 | visible = false 41 | -------------------------------------------------------------------------------- /addons/godot_db_manager/db_interface.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBInterface 3 | """ 4 | 5 | class_name GDDBInterface 6 | 7 | tool 8 | extends Control 9 | 10 | var m_db_manager = null 11 | 12 | # Called when the node enters the scene tree for the first time. 13 | func _ready() -> void: 14 | # init db_manager 15 | m_db_manager = load(gddb_constants.c_addon_main_path + "core/db_man.gd").new() 16 | 17 | # menu connections 18 | $dlg/menu.connect("new_database", self, "on_menu_new_database") 19 | $dlg/menu.connect("load_database", self, "on_menu_load_database") 20 | $dlg/menu.connect("save_database", self, "on_menu_save_database") 21 | $dlg/menu.connect("save_database_as", self, "on_menu_save_database_as") 22 | 23 | # dialod notifications 24 | $dlg.connect("about_to_show", self, "on_about_to_show") 25 | $dlg.get_close_button().connect("pressed", self, "on_close") 26 | 27 | # new database connections 28 | $dlg/new_db_dlg.connect("create_new_db", self, "on_new_database") 29 | 30 | # save / load connections 31 | $dlg/load_db_dlg.connect("file_selected", self, "on_file_selected") 32 | 33 | # Called when the node is about to be shown. 34 | func on_about_to_show() -> void : 35 | gddb_globals.set_interface_active(true) 36 | 37 | func on_close() -> void : 38 | gddb_globals.set_interface_active(false) 39 | 40 | # called when creating a new database from the menu 41 | func on_menu_new_database() -> void: 42 | $dlg/new_db_dlg/v_layout/db_info/db_edt.set_text("") 43 | $dlg/new_db_dlg.popup_centered() 44 | 45 | # called when loading a database from the menu 46 | func on_menu_load_database() -> void: 47 | $dlg/load_db_dlg.set_mode(FileDialog.MODE_OPEN_FILE) 48 | $dlg/load_db_dlg.set_title("Load Database ...") 49 | $dlg/load_db_dlg.set_current_file("") 50 | $dlg/load_db_dlg.popup_centered() 51 | 52 | # called when saving a database from the menu 53 | func on_menu_save_database() -> void: 54 | # print("on_menu_save_database") 55 | var currnet_tab = $dlg/databases.get_current_tab_control() 56 | if(currnet_tab.can_save_database()): 57 | currnet_tab.save_database() 58 | else: 59 | on_menu_save_database_as() 60 | 61 | # called when saving a database as another from the menu 62 | func on_menu_save_database_as(): 63 | # print("on_menu_save_database_as") 64 | $dlg/load_db_dlg.set_mode(FileDialog.MODE_SAVE_FILE) 65 | $dlg/load_db_dlg.set_title("Save Database As ...") 66 | 67 | var currnet_tab = $dlg/databases.get_current_tab_control() 68 | 69 | $dlg/load_db_dlg.set_current_file(currnet_tab.get_db_name()) 70 | $dlg/load_db_dlg.popup_centered() 71 | 72 | # called when adding a new database 73 | func on_new_database(db_name : String) -> void: 74 | var tmp_name = db_name.to_lower() 75 | var db_id = m_db_manager.add_database(db_name) 76 | if(db_id == gddb_constants.c_invalid_id): 77 | $dlg/error_dlg.set_text("Database with name \"" + db_name + "\" already exists") 78 | $dlg/error_dlg.popup_centered() 79 | return 80 | 81 | var db = m_db_manager.get_db_by_id(db_id) 82 | # print("new DB added: " + str(db)) 83 | 84 | var db_editor = load(gddb_constants.c_addon_main_path + "db_editor.tscn").instance() 85 | $dlg/databases.add_child(db_editor) 86 | db_editor.set_name(db_name) 87 | db.set_dirty(true) 88 | db_editor.set_database(db) 89 | 90 | $dlg/menu.enable_file_save(true) 91 | $dlg/menu.enable_file_save_as(true) 92 | 93 | $dlg/new_db_dlg.hide() 94 | 95 | # called when selecting a file from save / load dialog 96 | func on_file_selected(filepath : String) -> void: 97 | # print("GDDBInterface::on_file_selected(" + filepath + ")") 98 | 99 | if($dlg/load_db_dlg.get_mode() == FileDialog.MODE_SAVE_FILE): 100 | var filepath_low = filepath.to_lower() 101 | 102 | # check for the file extension 103 | if(!filepath_low.ends_with(".json")): 104 | $dlg/error_dlg.set_text("The extension of the file must be \".json\"") 105 | $dlg/error_dlg.popup_centered() 106 | return 107 | 108 | var current_filename = $dlg/load_db_dlg.get_current_file().to_lower() 109 | var filename_dot = current_filename.length() - 5 110 | current_filename.erase(filename_dot, 5) 111 | 112 | # check the filename 113 | if(!gddb_globals.check_db_name(current_filename)): 114 | $dlg/error_dlg.set_text("Invalid characters in the database filename.\n\nThe filename cannot contain any of these characters: " + gddb_constants.c_invalid_characters) 115 | $dlg/error_dlg.popup_centered() 116 | return 117 | 118 | save_database_as(filepath) 119 | 120 | elif($dlg/load_db_dlg.get_mode() == FileDialog.MODE_OPEN_FILE): 121 | load_database(filepath) 122 | 123 | # saves a database to a given file path 124 | func save_database_as(filepath : String) -> void: 125 | # print("GDDBInterface::save_database_as(" + filepath + ")") 126 | var currnet_tab = $dlg/databases.get_current_tab_control() 127 | currnet_tab.set_database_filepath(filepath) 128 | currnet_tab.save_database() 129 | 130 | func load_database(filepath : String) -> void: 131 | var db_id = m_db_manager.load_database(filepath) 132 | 133 | if(db_id == gddb_types.e_db_invalid_file): 134 | $dlg/error_dlg.set_text("Invalid database") 135 | $dlg/error_dlg.popup_centered() 136 | return 137 | 138 | if(db_id == gddb_types.e_db_invalid_ver): 139 | $dlg/error_dlg.set_text("Wrong database version. Currently is: " + gddb_constants.c_gddb_ver) 140 | $dlg/error_dlg.popup_centered() 141 | return 142 | 143 | var db = m_db_manager.get_db_by_id(db_id) 144 | db.set_dirty(false) 145 | # print("new DB added: " + str(db)) 146 | 147 | var db_editor = load(gddb_constants.c_addon_main_path + "db_editor.tscn").instance() 148 | $dlg/databases.add_child(db_editor) 149 | db_editor.set_name(db.get_db_name()) 150 | db_editor.set_database(db) 151 | 152 | $dlg/menu.enable_file_save(true) 153 | $dlg/menu.enable_file_save_as(true) 154 | 155 | db_editor.set_dirty(false) 156 | -------------------------------------------------------------------------------- /addons/godot_db_manager/db_interface.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/debug/dbg.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/dlgs/error_dlg.tscn" type="PackedScene" id=3] 6 | [ext_resource path="res://addons/godot_db_manager/db_interface.gd" type="Script" id=4] 7 | [ext_resource path="res://addons/godot_db_manager/dlgs/new_db_dlg.tscn" type="PackedScene" id=5] 8 | [ext_resource path="res://addons/godot_db_manager/menu.tscn" type="PackedScene" id=7] 9 | 10 | [node name="db_interface" type="Control"] 11 | script = ExtResource( 4 ) 12 | __meta__ = { 13 | "_edit_horizontal_guides_": [ 30.0, 674.0 ], 14 | "_edit_use_anchors_": false 15 | } 16 | 17 | [node name="dlg" type="WindowDialog" parent="."] 18 | visible = true 19 | margin_right = 1147.0 20 | margin_bottom = 768.0 21 | popup_exclusive = true 22 | window_title = "Godot Database Manager" 23 | resizable = true 24 | __meta__ = { 25 | "_edit_use_anchors_": false 26 | } 27 | 28 | [node name="menu" parent="dlg" instance=ExtResource( 7 )] 29 | 30 | [node name="databases" type="TabContainer" parent="dlg"] 31 | anchor_right = 1.0 32 | anchor_bottom = 1.0 33 | margin_top = 30.0 34 | custom_fonts/font = ExtResource( 2 ) 35 | tab_align = 0 36 | drag_to_rearrange_enabled = true 37 | __meta__ = { 38 | "_edit_use_anchors_": false 39 | } 40 | 41 | [node name="new_db_dlg" parent="dlg" instance=ExtResource( 5 )] 42 | visible = false 43 | margin_right = 3.832 44 | 45 | [node name="error_dlg" parent="dlg" instance=ExtResource( 3 )] 46 | visible = false 47 | anchor_right = 0.187 48 | anchor_bottom = 0.136 49 | margin_right = 0.469986 50 | margin_bottom = -0.0800018 51 | 52 | [node name="load_db_dlg" type="FileDialog" parent="dlg"] 53 | anchor_right = 0.349 54 | anchor_bottom = 0.418 55 | margin_right = -0.309998 56 | margin_bottom = 0.209991 57 | window_title = "Open a File" 58 | mode = 0 59 | filters = PoolStringArray( "*.json" ) 60 | __meta__ = { 61 | "_edit_use_anchors_": false 62 | } 63 | 64 | [node name="dbg" parent="dlg" instance=ExtResource( 1 )] 65 | visible = false 66 | -------------------------------------------------------------------------------- /addons/godot_db_manager/db_manager.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBManager 3 | """ 4 | 5 | class_name GDDBManager 6 | 7 | tool 8 | extends EditorPlugin 9 | 10 | var DBInterface = preload("./db_interface.tscn") 11 | var db_interface : Node 12 | 13 | func _enter_tree(): 14 | add_autoload_singleton("gddb_constants", "res://addons/godot_db_manager/core/GDDBConstants.gd") 15 | add_autoload_singleton("gddb_types", "res://addons/godot_db_manager/core/GDDBTypes.gd") 16 | add_autoload_singleton("gddb_globals", "res://addons/godot_db_manager/core/GDDBGlobals.gd") 17 | 18 | # Initialization of the plugin goes here 19 | db_interface = DBInterface.instance() 20 | 21 | get_editor_interface().get_base_control().add_child(db_interface) 22 | add_tool_menu_item("Godot Database Manager", self, "open_config") 23 | 24 | func _exit_tree(): 25 | # Clean-up of the plugin goes here 26 | remove_tool_menu_item("Godot Database Manager") 27 | if(db_interface): 28 | db_interface.queue_free() 29 | 30 | func open_config(UD): 31 | var window = db_interface.get_node("dlg") as WindowDialog 32 | if(window): 33 | window.popup_centered() 34 | -------------------------------------------------------------------------------- /addons/godot_db_manager/debug/dbg.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/tex/debug.png" type="Texture" id=1] 4 | 5 | [node name="dbg" type="Control"] 6 | anchor_right = 1.0 7 | anchor_bottom = 1.0 8 | mouse_filter = 2 9 | __meta__ = { 10 | "_edit_use_anchors_": false 11 | } 12 | 13 | [node name="1" type="Control" parent="."] 14 | margin_right = 40.0 15 | margin_bottom = 40.0 16 | mouse_filter = 2 17 | __meta__ = { 18 | "_edit_use_anchors_": false 19 | } 20 | 21 | [node name="Sprite" type="Sprite" parent="1"] 22 | scale = Vector2( 4, 4 ) 23 | texture = ExtResource( 1 ) 24 | centered = false 25 | region_enabled = true 26 | region_rect = Rect2( 2, 50, 10, 10 ) 27 | 28 | [node name="2" type="Control" parent="."] 29 | anchor_left = 1.0 30 | anchor_right = 1.0 31 | margin_left = -40.0 32 | margin_bottom = 40.0 33 | mouse_filter = 2 34 | __meta__ = { 35 | "_edit_use_anchors_": false 36 | } 37 | 38 | [node name="Sprite" type="Sprite" parent="2"] 39 | scale = Vector2( 4, 4 ) 40 | texture = ExtResource( 1 ) 41 | centered = false 42 | region_enabled = true 43 | region_rect = Rect2( 2, 50, 10, 10 ) 44 | 45 | [node name="3" type="Control" parent="."] 46 | anchor_top = 1.0 47 | anchor_bottom = 1.0 48 | margin_top = -40.0 49 | margin_right = 40.0 50 | mouse_filter = 2 51 | __meta__ = { 52 | "_edit_use_anchors_": false 53 | } 54 | 55 | [node name="Sprite" type="Sprite" parent="3"] 56 | scale = Vector2( 4, 4 ) 57 | texture = ExtResource( 1 ) 58 | centered = false 59 | region_enabled = true 60 | region_rect = Rect2( 2, 50, 10, 10 ) 61 | 62 | [node name="4" type="Control" parent="."] 63 | anchor_left = 1.0 64 | anchor_top = 1.0 65 | anchor_right = 1.0 66 | anchor_bottom = 1.0 67 | margin_left = -40.0 68 | margin_top = -40.0 69 | mouse_filter = 2 70 | __meta__ = { 71 | "_edit_use_anchors_": false 72 | } 73 | 74 | [node name="Sprite" type="Sprite" parent="4"] 75 | scale = Vector2( 4, 4 ) 76 | texture = ExtResource( 1 ) 77 | centered = false 78 | region_enabled = true 79 | region_rect = Rect2( 2, 50, 10, 10 ) 80 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/data_dlg.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBDataPanel 3 | """ 4 | 5 | class_name GDDBDataPanel 6 | 7 | tool 8 | extends PopupPanel 9 | 10 | signal select_data 11 | 12 | var m_prop_id = gddb_constants.c_invalid_id 13 | var m_row_idx = gddb_constants.c_invalid_id 14 | 15 | var m_table = null 16 | 17 | # Called when the node enters the scene tree for the first time. 18 | func _ready(): 19 | connect("about_to_show", self, "on_about_to_show") 20 | $ItemList.connect("item_selected", self, "on_item_selected") 21 | 22 | # sets property id 23 | func set_prop_id(prop_id : int) -> void : 24 | m_prop_id = prop_id 25 | 26 | # returns property id 27 | func get_prop_id() -> int : 28 | return m_prop_id 29 | 30 | # sets row index 31 | func set_row_idx(row_idx : int) -> void : 32 | m_row_idx = row_idx 33 | 34 | # returns row index 35 | func get_row_idx() -> int : 36 | return m_row_idx 37 | 38 | # sets the table from the database 39 | func set_table(table) -> void: 40 | m_table = table 41 | 42 | # returns the table from the database 43 | func get_table() -> Object: 44 | return m_table 45 | 46 | # called when the popup is about to show 47 | func on_about_to_show() -> void : 48 | $ItemList.clear() 49 | $ItemList.add_item("None") 50 | for idx in range(0, m_table.get_rows_count()): 51 | var option = gddb_globals.get_json_from_row(m_table, idx) 52 | $ItemList.add_item(option) 53 | 54 | # called when an item is selected 55 | func on_item_selected(idx : int) -> void: 56 | # the first index is "" 57 | if(idx == 0): 58 | emit_signal("select_data", m_prop_id, m_row_idx, -1, "{}" ) 59 | else: 60 | emit_signal("select_data", m_prop_id, m_row_idx, idx-1, $ItemList.get_item_text(idx) ) 61 | hide() 62 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/data_dlg.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/dlgs/data_dlg.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_12.tres" type="DynamicFont" id=2] 5 | 6 | [node name="data_dlg" type="PopupPanel"] 7 | anchor_right = 0.285625 8 | anchor_bottom = 0.351111 9 | script = ExtResource( 1 ) 10 | __meta__ = { 11 | "_edit_use_anchors_": false 12 | } 13 | 14 | [node name="ItemList" type="ItemList" parent="."] 15 | anchor_right = 1.0 16 | anchor_bottom = 1.0 17 | margin_left = 4.0 18 | margin_top = 4.0 19 | margin_right = -4.0 20 | margin_bottom = -4.0 21 | custom_fonts/font = ExtResource( 2 ) 22 | items = [ "ababab", null, false, "cdcdcd", null, false, "efefef", null, false ] 23 | __meta__ = { 24 | "_edit_use_anchors_": false 25 | } 26 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/delete_prop_dlg.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBDeletePropDlg 3 | """ 4 | 5 | class_name GDDBDeletePropDlg 6 | 7 | tool 8 | extends WindowDialog 9 | 10 | signal delete_prop 11 | 12 | var m_prop_id = gddb_constants.c_invalid_id 13 | 14 | # Called when the node enters the scene tree for the first time. 15 | func _ready() -> void : 16 | $v_layout/buttons/ok_btn.connect("pressed", self, "on_ok_btn_pressed") 17 | $v_layout/buttons/cancel_btn.connect("pressed", self, "on_cancel_btn_pressed") 18 | 19 | # sets the property id 20 | func set_prop_id(prop_id : int) -> void : 21 | m_prop_id = prop_id 22 | 23 | # returns the property id 24 | func get_prop_id() -> int : 25 | return m_prop_id 26 | 27 | func set_prop_name(prop_name : String) -> void: 28 | var text = "Delete property with name \"" + prop_name + "\" ?" 29 | $v_layout/prop_info/prop_lbl.set_text(text) 30 | 31 | # returns the table id 32 | func get_table_id() -> int : 33 | return m_prop_id 34 | 35 | # called when the OK button is pressed 36 | func on_ok_btn_pressed() -> void : 37 | emit_signal("delete_prop") 38 | hide() 39 | 40 | func on_cancel_btn_pressed() -> void: 41 | hide() 42 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/delete_prop_dlg.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/dlgs/delete_prop_dlg.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_14.tres" type="DynamicFont" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_12.tres" type="DynamicFont" id=3] 6 | 7 | [node name="delete_prop_dlg" type="WindowDialog"] 8 | visible = true 9 | anchor_right = 0.257 10 | anchor_bottom = 0.084 11 | margin_right = 0.799988 12 | margin_bottom = 0.399994 13 | focus_next = NodePath("v_layout/buttons/ok_btn") 14 | focus_mode = 1 15 | custom_fonts/title_font = ExtResource( 2 ) 16 | popup_exclusive = true 17 | window_title = "Delete property" 18 | script = ExtResource( 1 ) 19 | __meta__ = { 20 | "_edit_use_anchors_": false 21 | } 22 | 23 | [node name="v_layout" type="VBoxContainer" parent="."] 24 | anchor_right = 1.0 25 | anchor_bottom = 1.0 26 | custom_constants/separation = 10 27 | alignment = 1 28 | __meta__ = { 29 | "_edit_use_anchors_": false 30 | } 31 | 32 | [node name="prop_info" type="HBoxContainer" parent="v_layout"] 33 | margin_top = 13.0 34 | margin_right = 412.0 35 | margin_bottom = 30.0 36 | alignment = 1 37 | 38 | [node name="prop_lbl" type="Label" parent="v_layout/prop_info"] 39 | margin_left = 152.0 40 | margin_right = 259.0 41 | margin_bottom = 17.0 42 | custom_fonts/font = ExtResource( 2 ) 43 | text = "Property name: " 44 | 45 | [node name="buttons" type="HBoxContainer" parent="v_layout"] 46 | margin_top = 40.0 47 | margin_right = 412.0 48 | margin_bottom = 61.0 49 | custom_constants/separation = 50 50 | alignment = 1 51 | 52 | [node name="ok_btn" type="Button" parent="v_layout/buttons"] 53 | margin_left = 81.0 54 | margin_right = 181.0 55 | margin_bottom = 21.0 56 | rect_min_size = Vector2( 100, 0 ) 57 | custom_fonts/font = ExtResource( 3 ) 58 | text = "OK" 59 | 60 | [node name="cancel_btn" type="Button" parent="v_layout/buttons"] 61 | margin_left = 231.0 62 | margin_right = 331.0 63 | margin_bottom = 21.0 64 | rect_min_size = Vector2( 100, 0 ) 65 | custom_fonts/font = ExtResource( 3 ) 66 | text = "Cancel" 67 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/delete_table_dlg.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBDeleteTableDlg 3 | """ 4 | 5 | class_name GDDBDeleteTableDlg 6 | 7 | tool 8 | extends WindowDialog 9 | 10 | signal delete_table 11 | 12 | var m_table_id = gddb_constants.c_invalid_id 13 | 14 | # Called when the node enters the scene tree for the first time. 15 | func _ready(): 16 | $v_layout/buttons/ok_btn.connect("pressed", self, "on_ok_btn_pressed") 17 | $v_layout/buttons/cancel_btn.connect("pressed", self, "on_cancel_btn_pressed") 18 | 19 | # sets the table id 20 | func set_table_id(table_id : int) -> void: 21 | m_table_id = table_id 22 | 23 | func set_table_name(table_name : String) -> void: 24 | var text = "Delete table with name \"" + table_name + "\" ?" 25 | $v_layout/table_info/table_lbl.set_text(text) 26 | 27 | # returns the table id 28 | func get_table_id() -> int: 29 | return m_table_id 30 | 31 | # called when the OK button is pressed 32 | func on_ok_btn_pressed() -> void: 33 | emit_signal("delete_table") 34 | hide() 35 | 36 | func on_cancel_btn_pressed() -> void: 37 | hide() 38 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/delete_table_dlg.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/dlgs/delete_table_dlg.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_14.tres" type="DynamicFont" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_12.tres" type="DynamicFont" id=3] 6 | 7 | [node name="delete_table_dlg" type="WindowDialog"] 8 | visible = true 9 | anchor_right = 0.257 10 | anchor_bottom = 0.084 11 | margin_right = 0.799988 12 | margin_bottom = 0.399994 13 | focus_next = NodePath("v_layout/buttons/ok_btn") 14 | focus_mode = 1 15 | custom_fonts/title_font = ExtResource( 2 ) 16 | popup_exclusive = true 17 | window_title = "Delete table" 18 | script = ExtResource( 1 ) 19 | __meta__ = { 20 | "_edit_use_anchors_": false 21 | } 22 | 23 | [node name="v_layout" type="VBoxContainer" parent="."] 24 | anchor_right = 1.0 25 | anchor_bottom = 1.0 26 | custom_constants/separation = 10 27 | alignment = 1 28 | __meta__ = { 29 | "_edit_use_anchors_": false 30 | } 31 | 32 | [node name="table_info" type="HBoxContainer" parent="v_layout"] 33 | margin_top = 13.0 34 | margin_right = 412.0 35 | margin_bottom = 30.0 36 | alignment = 1 37 | 38 | [node name="table_lbl" type="Label" parent="v_layout/table_info"] 39 | margin_left = 162.0 40 | margin_right = 249.0 41 | margin_bottom = 17.0 42 | custom_fonts/font = ExtResource( 2 ) 43 | text = "Table name: " 44 | 45 | [node name="buttons" type="HBoxContainer" parent="v_layout"] 46 | margin_top = 40.0 47 | margin_right = 412.0 48 | margin_bottom = 61.0 49 | custom_constants/separation = 50 50 | alignment = 1 51 | 52 | [node name="ok_btn" type="Button" parent="v_layout/buttons"] 53 | margin_left = 81.0 54 | margin_right = 181.0 55 | margin_bottom = 21.0 56 | rect_min_size = Vector2( 100, 0 ) 57 | custom_fonts/font = ExtResource( 3 ) 58 | text = "OK" 59 | 60 | [node name="cancel_btn" type="Button" parent="v_layout/buttons"] 61 | margin_left = 231.0 62 | margin_right = 331.0 63 | margin_bottom = 21.0 64 | rect_min_size = Vector2( 100, 0 ) 65 | custom_fonts/font = ExtResource( 3 ) 66 | text = "Cancel" 67 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/edit_string_dlg.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBEditStringDlg 3 | """ 4 | 5 | class_name GDDBEditStringDlg 6 | 7 | tool 8 | extends WindowDialog 9 | 10 | signal string_edited 11 | 12 | var m_prop_id = gddb_constants.c_invalid_id 13 | var m_row_idx = gddb_constants.c_invalid_id 14 | var m_data_text = "" 15 | 16 | # Called when the node enters the scene tree for the first time. 17 | func _ready(): 18 | $v_layout/btns/ok_btn.connect("pressed", self, "on_ok_btn_pressed") 19 | $v_layout/btns/cancel_btn.connect("pressed", self, "on_cancel_btn_pressed") 20 | 21 | $v_layout/text.connect("text_changed", self, "on_text_changed") 22 | 23 | # sets property id 24 | func set_prop_id(prop_id : int) -> void: 25 | m_prop_id = prop_id 26 | 27 | # returns property id 28 | func get_prop_id() -> int : 29 | return m_prop_id 30 | 31 | # sets row index 32 | func set_row_idx(row_idx : int) -> void : 33 | m_row_idx = row_idx 34 | 35 | # returns row index 36 | func get_row_idx() -> int : 37 | return m_row_idx 38 | 39 | # sets data text 40 | func set_data_text(text : String) -> void : 41 | m_data_text = text 42 | $v_layout/text.set_text(text) 43 | 44 | # returns data text 45 | func get_data_text() -> String : 46 | return m_data_text 47 | 48 | # Called when the OK button is pressed 49 | func on_ok_btn_pressed() -> void : 50 | emit_signal("string_edited") 51 | hide() 52 | 53 | # Called when the Cancel button is pressed 54 | func on_cancel_btn_pressed() -> void : 55 | hide() 56 | 57 | # Called when text is changed 58 | func on_text_changed() -> void: 59 | m_data_text = $v_layout/text.get_text() 60 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/edit_string_dlg.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/dlgs/edit_string_dlg.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_14.tres" type="DynamicFont" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_12.tres" type="DynamicFont" id=3] 6 | 7 | [node name="edit_string_dlg" type="WindowDialog"] 8 | anchor_right = 0.430625 9 | anchor_bottom = 0.423333 10 | focus_next = NodePath("v_layout/text") 11 | custom_fonts/title_font = ExtResource( 3 ) 12 | window_title = "Edit string" 13 | script = ExtResource( 1 ) 14 | __meta__ = { 15 | "_edit_use_anchors_": true 16 | } 17 | 18 | [node name="v_layout" type="VBoxContainer" parent="."] 19 | anchor_right = 1.0 20 | anchor_bottom = 1.0 21 | __meta__ = { 22 | "_edit_use_anchors_": false 23 | } 24 | 25 | [node name="edit_text_btns" type="HBoxContainer" parent="v_layout"] 26 | margin_right = 689.0 27 | margin_bottom = 30.0 28 | rect_min_size = Vector2( 0, 30 ) 29 | 30 | [node name="text" type="TextEdit" parent="v_layout"] 31 | margin_top = 34.0 32 | margin_right = 689.0 33 | margin_bottom = 334.0 34 | rect_min_size = Vector2( 0, 300 ) 35 | custom_fonts/font = ExtResource( 2 ) 36 | caret_blink = true 37 | 38 | [node name="btns" type="HBoxContainer" parent="v_layout"] 39 | margin_top = 338.0 40 | margin_right = 689.0 41 | margin_bottom = 368.0 42 | rect_min_size = Vector2( 0, 30 ) 43 | custom_constants/separation = 200 44 | alignment = 1 45 | 46 | [node name="ok_btn" type="Button" parent="v_layout/btns"] 47 | margin_left = 144.0 48 | margin_right = 244.0 49 | margin_bottom = 30.0 50 | rect_min_size = Vector2( 100, 0 ) 51 | custom_fonts/font = ExtResource( 3 ) 52 | text = "OK" 53 | 54 | [node name="cancel_btn" type="Button" parent="v_layout/btns"] 55 | margin_left = 444.0 56 | margin_right = 544.0 57 | margin_bottom = 30.0 58 | rect_min_size = Vector2( 100, 0 ) 59 | custom_fonts/font = ExtResource( 3 ) 60 | text = "Cancel" 61 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/error_dlg.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene format=2] 2 | 3 | [node name="error_dlg" type="AcceptDialog"] 4 | visible = true 5 | anchor_right = 0.139 6 | anchor_bottom = 0.099 7 | margin_right = 0.599976 8 | margin_bottom = -0.100006 9 | popup_exclusive = true 10 | window_title = "Error" 11 | dialog_autowrap = true 12 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/load_res_path_dlg.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBLoadResourcePathDlg 3 | """ 4 | 5 | class_name GDDBLoadResourcePathDlg 6 | 7 | tool 8 | extends FileDialog 9 | 10 | # TODO: put this list in a config file 11 | const file_filters = [ 12 | # Godot resource file types 13 | "*.res, *.tres ; Godot resource file types", 14 | 15 | # Godot scene files 16 | "*.scn, *.tscn, *escn ; Godot scene file types", 17 | 18 | # Code file types 19 | "*.gd, *.cs, *.h, *.c, *.hpp, *.cpp ; Code file types", 20 | 21 | # Shader file types 22 | "*.shader ; Shader file types", 23 | 24 | # material file types 25 | "*.mat ; Material file types", 26 | 27 | # mesh file types 28 | "*.dae, *.gltf, *.obj, *.fbx ; Mesh file types", 29 | 30 | # animation file types 31 | "*.anim ; Animation file types", 32 | 33 | # font file types 34 | "*.ttf, *.otf ; Font file types", 35 | 36 | # image file types 37 | "*.png, *.jpg, *.jpeg, *.tiff, *.tga, *.bmp, *.webp, *.gif, *.hdr ; Images file types", 38 | 39 | # soung file types 40 | "*.snd, *.wav, *.ogg, *.mp3 ; Sound file types", 41 | 42 | # video file types 43 | "*.ogg, *.mpg, *.mpeg, *.avi, *.mov, *.mp4, *.webm ; Video file types", 44 | 45 | # text file types 46 | "*.txt, *.csv, *.json, *.xml, *.cfg, *.ini ; Text file types", 47 | 48 | # document file types 49 | "*.doc, *.docx, *.xls, *.xlsx, *.odt, *.ods, *.pdf ; Doc file types", 50 | 51 | # binary data file types 52 | "*.dat, *.raw ; Binary data file types" 53 | ] 54 | 55 | var m_prop_id = gddb_constants.c_invalid_id 56 | var m_row_idx = gddb_constants.c_invalid_id 57 | 58 | # Called when the node enters the scene tree for the first time. 59 | func _ready(): 60 | set_filters(PoolStringArray(file_filters)) 61 | 62 | # sets the property id 63 | func set_prop_id(prop_id : int) -> void : 64 | m_prop_id = prop_id 65 | 66 | # returns the property id 67 | func get_prop_id() -> int : 68 | return m_prop_id 69 | 70 | # sets the row index 71 | func set_row_idx(row_idx : int) -> void : 72 | m_row_idx = row_idx 73 | 74 | # returns the row index 75 | func get_row_idx() -> int : 76 | return m_row_idx 77 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/load_res_path_dlg.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/dlgs/load_res_path_dlg.gd" type="Script" id=1] 4 | 5 | [node name="load_res_path_dlg" type="FileDialog"] 6 | anchor_right = 0.404 7 | anchor_bottom = 0.431 8 | margin_right = -0.400024 9 | margin_bottom = 0.0999756 10 | window_title = "Open a File" 11 | resizable = true 12 | mode = 0 13 | script = ExtResource( 1 ) 14 | __meta__ = { 15 | "_edit_use_anchors_": false 16 | } 17 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/new_db_dlg.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBNewDBDlg 3 | """ 4 | 5 | class_name GDDBNewDBDlg 6 | 7 | tool 8 | extends WindowDialog 9 | 10 | signal create_new_db 11 | 12 | var m_current_db_name = "" 13 | 14 | # Called when the node enters the scene tree for the first time. 15 | func _ready() -> void : 16 | $v_layout/buttons/ok_btn.connect("pressed", self, "on_ok_btn_pressed") 17 | $v_layout/buttons/cancel_btn.connect("pressed", self, "on_cancel_btn_pressed") 18 | connect("about_to_show", self, "on_about_to_show") 19 | $v_layout/db_info/db_edt.connect("text_changed", self, "on_text_changed") 20 | $v_layout/db_info/db_edt.connect("text_entered", self, "on_text_confirmed") 21 | 22 | # Called when the node is about to be shown. 23 | func on_about_to_show() -> void : 24 | m_current_db_name = "" 25 | $v_layout/db_info/db_edt.set_text(m_current_db_name) 26 | 27 | # called everytime the text is changed 28 | func on_text_changed(new_text: String) -> void : 29 | var change_text = true 30 | if(!gddb_globals.check_db_name(new_text)): 31 | change_text = false 32 | else: 33 | if(new_text.length() > gddb_constants.c_max_db_name_len): 34 | change_text = false 35 | else: 36 | change_text = true 37 | 38 | if(change_text): 39 | m_current_db_name = $v_layout/db_info/db_edt.get_text() 40 | else: 41 | $v_layout/db_info/db_edt.set_text(m_current_db_name) 42 | $v_layout/db_info/db_edt.set_cursor_position(m_current_db_name.length()) 43 | 44 | # called when the user presses the ENTER key 45 | func on_text_confirmed(text : String) -> void : 46 | # print("GDDBNewDBDlg::on_text_confirmed(" + text + ")") 47 | if(m_current_db_name.empty()): 48 | return 49 | handle_db_name() 50 | hide() 51 | 52 | # called when the OK button is pressed 53 | func on_ok_btn_pressed() -> void : 54 | if(!m_current_db_name.empty()): 55 | handle_db_name() 56 | 57 | # called when the Cancel button is pressed 58 | func on_cancel_btn_pressed() -> void : 59 | hide() 60 | 61 | # handles the name of the database 62 | func handle_db_name() -> void : 63 | emit_signal("create_new_db", m_current_db_name) 64 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/new_db_dlg.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_14.tres" type="DynamicFont" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/dlgs/new_db_dlg.gd" type="Script" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_12.tres" type="DynamicFont" id=3] 6 | 7 | [node name="new_db_dlg" type="WindowDialog"] 8 | visible = true 9 | anchor_right = 0.257 10 | anchor_bottom = 0.1 11 | margin_right = 0.799988 12 | focus_next = NodePath("v_layout/db_info/db_edt") 13 | focus_mode = 2 14 | custom_fonts/title_font = ExtResource( 1 ) 15 | popup_exclusive = true 16 | window_title = "New database (max 16 characters)" 17 | script = ExtResource( 2 ) 18 | __meta__ = { 19 | "_edit_horizontal_guides_": [ 90.0781 ], 20 | "_edit_use_anchors_": false 21 | } 22 | 23 | [node name="v_layout" type="VBoxContainer" parent="."] 24 | anchor_right = 1.0 25 | anchor_bottom = 1.0 26 | custom_constants/separation = 20 27 | alignment = 1 28 | __meta__ = { 29 | "_edit_use_anchors_": false 30 | } 31 | 32 | [node name="db_info" type="HBoxContainer" parent="v_layout"] 33 | margin_top = 11.0 34 | margin_right = 412.0 35 | margin_bottom = 38.0 36 | alignment = 1 37 | __meta__ = { 38 | "_edit_use_anchors_": false 39 | } 40 | 41 | [node name="db_lbl" type="Label" parent="v_layout/db_info"] 42 | margin_left = 18.0 43 | margin_top = 5.0 44 | margin_right = 89.0 45 | margin_bottom = 22.0 46 | custom_fonts/font = ExtResource( 1 ) 47 | text = "DB name: " 48 | 49 | [node name="db_edt" type="LineEdit" parent="v_layout/db_info"] 50 | margin_left = 93.0 51 | margin_right = 393.0 52 | margin_bottom = 27.0 53 | rect_min_size = Vector2( 300, 20 ) 54 | custom_fonts/font = ExtResource( 1 ) 55 | caret_blink = true 56 | caret_blink_speed = 0.5 57 | 58 | [node name="buttons" type="HBoxContainer" parent="v_layout"] 59 | margin_top = 58.0 60 | margin_right = 412.0 61 | margin_bottom = 79.0 62 | custom_constants/separation = 80 63 | alignment = 1 64 | __meta__ = { 65 | "_edit_use_anchors_": false 66 | } 67 | 68 | [node name="ok_btn" type="Button" parent="v_layout/buttons"] 69 | margin_left = 66.0 70 | margin_right = 166.0 71 | margin_bottom = 21.0 72 | rect_min_size = Vector2( 100, 0 ) 73 | custom_fonts/font = ExtResource( 3 ) 74 | text = "OK" 75 | 76 | [node name="cancel_btn" type="Button" parent="v_layout/buttons"] 77 | margin_left = 246.0 78 | margin_right = 346.0 79 | margin_bottom = 21.0 80 | rect_min_size = Vector2( 100, 0 ) 81 | custom_fonts/font = ExtResource( 3 ) 82 | text = "Cancel" 83 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/new_table_dlg.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBNewDBDlg 3 | """ 4 | 5 | class_name GDDBNewTableDlg 6 | 7 | tool 8 | extends WindowDialog 9 | 10 | signal create_new_table 11 | signal cancel_dialog 12 | 13 | var m_dlg_type : int = gddb_types.e_new_dlg_type_new 14 | var m_table_id = gddb_constants.c_invalid_id 15 | var m_current_table_name = "" 16 | 17 | # Called when the node enters the scene tree for the first time. 18 | func _ready(): 19 | $v_layout/buttons/ok_btn.connect("pressed", self, "on_ok_btn_pressed") 20 | $v_layout/buttons/cancel_btn.connect("pressed", self, "on_cancel_btn_pressed") 21 | $v_layout/table_info/table_edt.connect("text_changed", self, "on_text_changed") 22 | $v_layout/table_info/table_edt.connect("text_entered", self, "on_text_confirmed") 23 | m_current_table_name = "" 24 | 25 | # sets the type of the dialog 26 | func set_dld_type(dlg_type : int) -> void : 27 | m_dlg_type = dlg_type 28 | 29 | # returns the dialog type 30 | func get_dlg_type() -> int : 31 | return m_dlg_type 32 | 33 | # sets the table id 34 | func set_table_id(table_id : int) -> void: 35 | m_table_id = table_id 36 | 37 | # returns the table id 38 | func get_table_id() -> int: 39 | return m_table_id 40 | 41 | # sets the table name 42 | func set_init_name(table_name : String) -> void: 43 | # print("cNewTableDlg::set_init_name(" + name + ")") 44 | m_current_table_name = table_name 45 | $v_layout/table_info/table_edt.set_text(m_current_table_name) 46 | 47 | func on_text_changed(new_text: String) -> void: 48 | var change_text = true 49 | if(!gddb_globals.check_db_name(new_text)): 50 | change_text = false 51 | else: 52 | if(new_text.length() > gddb_constants.c_max_db_name_len): 53 | change_text = false 54 | else: 55 | change_text = true 56 | 57 | if(change_text): 58 | m_current_table_name = $v_layout/table_info/table_edt.get_text() 59 | else: 60 | $v_layout/table_info/table_edt.set_text(m_current_table_name) 61 | $v_layout/table_info/table_edt.set_cursor_position(m_current_table_name.length()) 62 | 63 | # called when the user presses the ENTER key 64 | func on_text_confirmed(text : String) -> void: 65 | if(m_current_table_name.empty()): 66 | return 67 | handle_table_name() 68 | hide() 69 | 70 | # called when the OK button is pressed 71 | func on_ok_btn_pressed() -> void: 72 | if(!m_current_table_name.empty()): 73 | handle_table_name() 74 | hide() 75 | 76 | # called when the Cancel button is pressed 77 | func on_cancel_btn_pressed() -> void : 78 | hide() 79 | emit_signal("cancel_dialog") 80 | 81 | # handles the text in the EditLine 82 | func handle_table_name() -> void: 83 | emit_signal("create_new_table", m_current_table_name) 84 | -------------------------------------------------------------------------------- /addons/godot_db_manager/dlgs/new_table_dlg.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_12.tres" type="DynamicFont" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/dlgs/new_table_dlg.gd" type="Script" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_14.tres" type="DynamicFont" id=3] 6 | 7 | [node name="new_table_dlg" type="WindowDialog"] 8 | visible = true 9 | anchor_right = 0.257 10 | anchor_bottom = 0.084 11 | margin_right = 0.799988 12 | margin_bottom = 0.399994 13 | focus_next = NodePath("v_layout/table_info/table_edt") 14 | focus_mode = 1 15 | custom_fonts/title_font = ExtResource( 3 ) 16 | popup_exclusive = true 17 | window_title = "New table (max 16 characters)" 18 | script = ExtResource( 2 ) 19 | 20 | [node name="v_layout" type="VBoxContainer" parent="."] 21 | anchor_right = 1.0 22 | anchor_bottom = 1.0 23 | custom_constants/separation = 10 24 | alignment = 1 25 | __meta__ = { 26 | "_edit_use_anchors_": false 27 | } 28 | 29 | [node name="table_info" type="HBoxContainer" parent="v_layout"] 30 | margin_top = 8.0 31 | margin_right = 412.0 32 | margin_bottom = 35.0 33 | alignment = 1 34 | 35 | [node name="table_lbl" type="Label" parent="v_layout/table_info"] 36 | margin_left = 10.0 37 | margin_top = 5.0 38 | margin_right = 97.0 39 | margin_bottom = 22.0 40 | custom_fonts/font = ExtResource( 3 ) 41 | text = "Table name: " 42 | 43 | [node name="table_edt" type="LineEdit" parent="v_layout/table_info"] 44 | margin_left = 101.0 45 | margin_right = 401.0 46 | margin_bottom = 27.0 47 | rect_min_size = Vector2( 300, 20 ) 48 | custom_fonts/font = ExtResource( 3 ) 49 | caret_blink = true 50 | caret_blink_speed = 0.5 51 | 52 | [node name="buttons" type="HBoxContainer" parent="v_layout"] 53 | margin_top = 45.0 54 | margin_right = 412.0 55 | margin_bottom = 66.0 56 | custom_constants/separation = 80 57 | alignment = 1 58 | 59 | [node name="ok_btn" type="Button" parent="v_layout/buttons"] 60 | margin_left = 66.0 61 | margin_right = 166.0 62 | margin_bottom = 21.0 63 | rect_min_size = Vector2( 100, 0 ) 64 | custom_fonts/font = ExtResource( 1 ) 65 | text = "OK" 66 | 67 | [node name="cancel_btn" type="Button" parent="v_layout/buttons"] 68 | margin_left = 246.0 69 | margin_right = 346.0 70 | margin_bottom = 21.0 71 | rect_min_size = Vector2( 100, 0 ) 72 | custom_fonts/font = ExtResource( 1 ) 73 | text = "Cancel" 74 | -------------------------------------------------------------------------------- /addons/godot_db_manager/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/addons/godot_db_manager/icon/icon.png -------------------------------------------------------------------------------- /addons/godot_db_manager/icon/icon.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/addons/godot_db_manager/icon/icon.xcf -------------------------------------------------------------------------------- /addons/godot_db_manager/license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Radu Bolovan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /addons/godot_db_manager/menu.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBMenu 3 | """ 4 | 5 | class_name GDDBMenu 6 | 7 | tool 8 | extends Control 9 | 10 | signal new_database 11 | signal load_database 12 | signal save_database 13 | signal save_database_as 14 | 15 | enum { 16 | e_file_new_id = 0, 17 | e_file_load_id = 1 18 | e_file_save_id = 2, 19 | e_file_save_as_id = 3, 20 | 21 | e_option_autosave_on_close_id = 4 22 | } 23 | 24 | var m_enable_new_db = true 25 | var m_enable_load_db = true 26 | var m_enable_save_db = false 27 | var m_enable_save_as_db = false 28 | 29 | var m_check_autosave_on_load = false 30 | 31 | func _ready() -> void: 32 | $layout/File.connect("about_to_show", self, "on_about_to_show_file_menu") 33 | $layout/File.get_popup().clear() 34 | $layout/File.get_popup().add_item("New DB", e_file_new_id) 35 | $layout/File.get_popup().add_item("Load DB", e_file_load_id) 36 | $layout/File.get_popup().add_item("Save DB", e_file_save_id) 37 | $layout/File.get_popup().add_item("Save DB As ...", e_file_save_as_id) 38 | $layout/File.get_popup().connect("id_pressed", self, "on_file_id_pressed") 39 | 40 | $layout/Options.connect("about_to_show", self, "on_about_to_show_options_menu") 41 | $layout/Options.get_popup().clear() 42 | $layout/Options.get_popup().add_check_item("Autosave on close", e_option_autosave_on_close_id) 43 | $layout/Options.get_popup().connect("id_pressed", self, "on_options_id_pressed") 44 | 45 | # called before showing the file menu 46 | func on_about_to_show_file_menu() -> void: 47 | for idx in range(0, $layout/File.get_popup().get_item_count()): 48 | var item_id = $layout/File.get_popup().get_item_id(idx) 49 | if(item_id == e_file_new_id): 50 | $layout/File.get_popup().set_item_disabled(idx, !m_enable_new_db) 51 | elif(item_id == e_file_load_id): 52 | $layout/File.get_popup().set_item_disabled(idx, !m_enable_load_db) 53 | elif(item_id == e_file_save_id): 54 | $layout/File.get_popup().set_item_disabled(idx, !m_enable_save_db) 55 | elif(item_id == e_file_save_as_id): 56 | $layout/File.get_popup().set_item_disabled(idx, !m_enable_save_as_db) 57 | raise() 58 | 59 | # enables / disables the possibility to create a new databbase 60 | func enable_file_new(enable) -> void: 61 | m_enable_new_db = enable 62 | 63 | # enables / disables the possibility to load a databbase 64 | func enable_file_load(enable) -> void: 65 | m_enable_load_db = enable 66 | 67 | # enables / disables the possibility to save a databbase 68 | func enable_file_save(enable) -> void: 69 | m_enable_save_db = enable 70 | 71 | # enables / disables the possibility to save a databbase as another 72 | func enable_file_save_as(enable) -> void: 73 | m_enable_save_as_db = enable 74 | 75 | # called when the user clicks on a file menu item 76 | func on_file_id_pressed(id : int) -> void: 77 | if(id == e_file_new_id): 78 | emit_signal("new_database") 79 | elif(id == e_file_load_id): 80 | emit_signal("load_database") 81 | elif(id == e_file_save_id): 82 | emit_signal("save_database") 83 | elif(id == e_file_save_as_id): 84 | emit_signal("save_database_as") 85 | 86 | # called before showing the option menu 87 | func on_about_to_show_options_menu() -> void: 88 | for idx in range(0, $layout/Options.get_popup().get_item_count()): 89 | var item_id = $layout/Options.get_popup().get_item_id(idx) 90 | if(item_id == e_option_autosave_on_close_id): 91 | $layout/Options.get_popup().set_item_checked(idx, m_check_autosave_on_load) 92 | raise() 93 | 94 | # enables / disables the possibility to autosave all databases on close 95 | func enable_autosave_on_close(enable) -> void: 96 | m_check_autosave_on_load = enable 97 | 98 | # called when the user clicks on a options menu item 99 | func on_options_id_pressed(id : int) -> void: 100 | if(id == e_option_autosave_on_close_id): 101 | enable_autosave_on_close(!m_check_autosave_on_load) 102 | -------------------------------------------------------------------------------- /addons/godot_db_manager/menu.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/menu.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=2] 5 | 6 | [node name="menu" type="Control"] 7 | anchor_right = 1.0 8 | rect_min_size = Vector2( 0, 30 ) 9 | script = ExtResource( 1 ) 10 | __meta__ = { 11 | "_edit_horizontal_guides_": [ 30.0 ], 12 | "_edit_use_anchors_": false, 13 | "_edit_vertical_guides_": [ 1024.0 ] 14 | } 15 | 16 | [node name="layout" type="HBoxContainer" parent="."] 17 | margin_right = 1024.0 18 | margin_bottom = 30.0 19 | __meta__ = { 20 | "_edit_use_anchors_": false 21 | } 22 | 23 | [node name="File" type="MenuButton" parent="layout"] 24 | margin_right = 40.0 25 | margin_bottom = 30.0 26 | custom_fonts/font = ExtResource( 2 ) 27 | text = "File" 28 | items = [ "New DB", null, 0, false, false, 0, 0, null, "", false, "Load DB", null, 0, false, false, 1, 0, null, "", false, "Save DB", null, 0, false, false, 2, 0, null, "", false, "Save DB As ...", null, 0, false, false, 3, 0, null, "", false ] 29 | 30 | [node name="Options" type="MenuButton" parent="layout"] 31 | margin_left = 44.0 32 | margin_right = 117.0 33 | margin_bottom = 30.0 34 | custom_fonts/font = ExtResource( 2 ) 35 | text = "Options" 36 | items = [ "Autosave on close", null, 1, false, false, 4, 0, null, "", false ] 37 | -------------------------------------------------------------------------------- /addons/godot_db_manager/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="Godot Database Manager" 4 | description="A database manager plugin for Google Engine." 5 | author="Radu Bolovan" 6 | version="2.1.a" 7 | script="db_manager.gd" 8 | -------------------------------------------------------------------------------- /addons/godot_db_manager/table_cell.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBTableCell 3 | """ 4 | 5 | class_name GDDBTableCell 6 | 7 | tool 8 | extends Control 9 | 10 | signal edit_data 11 | signal choose_resource 12 | signal choose_data 13 | signal edit_string 14 | 15 | const c_cell_min_width = 150 16 | 17 | var m_prop_id : int = -1 18 | var m_prop_type : int = gddb_constants.c_invalid_id 19 | var m_row_idx : int = -1 20 | var m_text : String = "" 21 | 22 | func _ready() -> void : 23 | $LineEdit.connect("text_changed", self, "on_text_changed") 24 | $LineEdit/edit_btn.connect("pressed", self, "on_edit_string") 25 | 26 | $Button.connect("pressed", self, "on_button_pressed") 27 | $Button.set_clip_text(true) 28 | 29 | $CheckBox.connect("toggled", self, "on_toggle_button") 30 | 31 | func _exit_tree() -> void : 32 | $LineEdit.disconnect("text_changed", self, "on_text_changed") 33 | 34 | # sets the property id 35 | func set_prop_id(id : int) -> void : 36 | m_prop_id = id 37 | 38 | # returns the property id 39 | func get_prop_id() -> int : 40 | return m_prop_id 41 | 42 | # sets property type 43 | func set_prop_type(data_type : int) -> void : 44 | # print("GDDBTableCell::set_prop_type(" + str(data_type) + ")") 45 | 46 | var data_type_changed = false 47 | 48 | if(m_prop_type != data_type): 49 | m_prop_type = data_type 50 | data_type_changed = true 51 | 52 | if(!data_type_changed): 53 | return 54 | 55 | if(m_prop_type == gddb_types.e_prop_type_bool): 56 | $LineEdit.hide() 57 | $Button.hide() 58 | $CheckBox.show() 59 | set_text("") 60 | elif(m_prop_type == gddb_types.e_prop_type_int): 61 | $LineEdit.show() 62 | $LineEdit/edit_btn.hide() 63 | $Button.hide() 64 | $CheckBox.hide() 65 | set_text("0") 66 | elif(m_prop_type == gddb_types.e_prop_type_float): 67 | $LineEdit.show() 68 | $LineEdit/edit_btn.hide() 69 | $Button.hide() 70 | $CheckBox.hide() 71 | set_text("0.0") 72 | elif(m_prop_type == gddb_types.e_prop_type_string): 73 | $LineEdit.show() 74 | $LineEdit/edit_btn.show() 75 | $Button.hide() 76 | $CheckBox.hide() 77 | set_text("") 78 | elif(m_prop_type == gddb_types.e_prop_type_resource): 79 | $LineEdit.hide() 80 | $Button.show() 81 | $CheckBox.hide() 82 | set_text("res://") 83 | elif(m_prop_type >= gddb_types.e_prop_types_count): 84 | $LineEdit.hide() 85 | $Button.show() 86 | $CheckBox.hide() 87 | set_text("{}") 88 | 89 | func get_prop_type() -> int : 90 | return m_prop_type 91 | 92 | # sets the row index 93 | func set_row_idx(idx : int) -> void : 94 | m_row_idx = idx 95 | 96 | # returns the property index 97 | func get_row_idx() -> int : 98 | return m_row_idx 99 | 100 | # sets the text 101 | func set_text(text : String) -> void : 102 | # print("GDDBTableCell::set_text(" + text + ")") 103 | m_text = text 104 | $LineEdit.set_text(m_text) 105 | $Button.set_text(m_text) 106 | if(m_prop_type == gddb_types.e_prop_type_bool): 107 | $CheckBox.set_pressed((text == "1")) 108 | 109 | # sets autoincrement 110 | func enable_autoincrement(enable : bool) -> void : 111 | $LineEdit.set_editable(!enable) 112 | 113 | # refreshes the width by the property name 114 | func refresh_width(prop_name : String) -> void : 115 | var size = get_custom_minimum_size() 116 | size.x = max(c_cell_min_width, get_font("normal_font").get_string_size(prop_name).x + 10) 117 | set_custom_minimum_size(size) 118 | 119 | # called when the checkbox is toggled/untoggled 120 | func on_toggle_button(enable : bool) -> void : 121 | var data = "0" 122 | if(enable): 123 | data = "1" 124 | emit_signal("edit_data", m_prop_id, m_row_idx, data) 125 | 126 | # called when the button is pressed 127 | func on_button_pressed() -> void : 128 | if(m_prop_type == gddb_types.e_prop_type_resource): 129 | # print("GDDBTableCell::on_button_pressed()") 130 | emit_signal("choose_resource", m_prop_id, m_row_idx) 131 | elif(m_prop_type >= gddb_types.e_prop_types_count): 132 | emit_signal("choose_data", m_prop_id, m_row_idx, m_prop_type) 133 | 134 | # called when the edit string button is pressed 135 | func on_edit_string() -> void : 136 | emit_signal("edit_string", m_prop_id, m_row_idx, m_text) 137 | 138 | # called when edit the data 139 | func on_text_changed(new_text : String) -> void : 140 | if(new_text.empty()): 141 | m_text = "" 142 | $LineEdit.set_text(m_text) 143 | $LineEdit.set_cursor_position(0) 144 | return 145 | 146 | if(m_prop_type == gddb_types.e_prop_type_int): 147 | if(!check_integer(new_text)): 148 | return 149 | 150 | if(m_prop_type == gddb_types.e_prop_type_float): 151 | if(!check_float(new_text)): 152 | return 153 | 154 | emit_signal("edit_data", m_prop_id, m_row_idx, new_text) 155 | 156 | # checks if the text is integer 157 | func check_integer(text : String) -> bool : 158 | var is_negative = false 159 | 160 | # check if the string is probably a number, but starts with "-" 161 | if(text.begins_with("-")): 162 | text.erase(0, 1) 163 | is_negative = true 164 | 165 | # check if the current string is only "-" 166 | if(text.empty()): 167 | m_text = "-" 168 | $LineEdit.set_text(m_text) 169 | $LineEdit.set_cursor_position(m_text.length()) 170 | return true 171 | 172 | if(text.is_valid_integer()): 173 | if(text.begins_with("0")): 174 | # a negative integer cannot start with "0" 175 | if(is_negative): 176 | m_text = "-" 177 | $LineEdit.set_text(m_text) 178 | $LineEdit.set_cursor_position(1) 179 | return true 180 | 181 | # a positive number starting with "0" can be only "0" 182 | m_text = "0" 183 | $LineEdit.set_text(m_text) 184 | $LineEdit.set_cursor_position(1) 185 | return true 186 | 187 | # don't add more "-" in front of the number 188 | if(text.begins_with("-")): 189 | text.erase(0, 1) 190 | 191 | # add back the "-" 192 | if(is_negative): 193 | m_text = "-" + text 194 | else: 195 | m_text = text 196 | 197 | $LineEdit.set_text(m_text) 198 | $LineEdit.set_cursor_position(m_text.length()) 199 | return true 200 | 201 | $LineEdit.set_text(m_text) 202 | $LineEdit.set_cursor_position(m_text.length()) 203 | return false 204 | 205 | func check_float(text : String) -> bool : 206 | if(text.is_valid_float()): 207 | if(text.begins_with("00") || text.begins_with("01") || text.begins_with("02") 208 | || text.begins_with("03") || text.begins_with("04") || text.begins_with("05") 209 | || text.begins_with("06") || text.begins_with("07") || text.begins_with("08") 210 | || text.begins_with("09")): 211 | m_text = "0" 212 | $LineEdit.set_text(m_text) 213 | $LineEdit.set_cursor_position(1) 214 | return true 215 | 216 | m_text = text 217 | return true 218 | 219 | $LineEdit.set_text(m_text) 220 | $LineEdit.set_cursor_position(m_text.length()) 221 | return false 222 | -------------------------------------------------------------------------------- /addons/godot_db_manager/table_cell.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/table_cell.gd" type="Script" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=3] 6 | 7 | [sub_resource type="AtlasTexture" id=1] 8 | atlas = ExtResource( 1 ) 9 | region = Rect2( 28, 1.86734, 24, 24.1327 ) 10 | 11 | [sub_resource type="AtlasTexture" id=2] 12 | atlas = ExtResource( 1 ) 13 | region = Rect2( 28, 54, 24, 24 ) 14 | 15 | [sub_resource type="AtlasTexture" id=3] 16 | atlas = ExtResource( 1 ) 17 | region = Rect2( 28, 28, 24, 24 ) 18 | 19 | [node name="table_cell" type="Control"] 20 | anchor_right = 1.0 21 | margin_bottom = 15.36 22 | rect_min_size = Vector2( 150, 32 ) 23 | script = ExtResource( 2 ) 24 | __meta__ = { 25 | "_edit_horizontal_guides_": [ 32.0 ], 26 | "_edit_use_anchors_": true 27 | } 28 | 29 | [node name="LineEdit" type="LineEdit" parent="."] 30 | anchor_right = 1.0 31 | anchor_bottom = 0.914286 32 | custom_fonts/font = ExtResource( 3 ) 33 | text = "TESTING WWW" 34 | caret_blink = true 35 | caret_blink_speed = 0.5 36 | __meta__ = { 37 | "_edit_use_anchors_": true 38 | } 39 | 40 | [node name="edit_btn" type="TextureButton" parent="LineEdit"] 41 | anchor_left = 1.0 42 | anchor_right = 1.0 43 | anchor_bottom = 1.0 44 | margin_left = -29.0 45 | margin_top = 4.0 46 | margin_right = -5.0 47 | margin_bottom = -4.0 48 | texture_normal = SubResource( 1 ) 49 | texture_pressed = SubResource( 2 ) 50 | texture_hover = SubResource( 3 ) 51 | __meta__ = { 52 | "_edit_use_anchors_": true 53 | } 54 | 55 | [node name="Button" type="Button" parent="."] 56 | visible = false 57 | anchor_right = 1.0 58 | anchor_bottom = 1.0 59 | custom_fonts/font = ExtResource( 3 ) 60 | clip_text = true 61 | __meta__ = { 62 | "_edit_use_anchors_": false 63 | } 64 | 65 | [node name="CheckBox" type="CheckBox" parent="."] 66 | visible = false 67 | anchor_right = 1.0 68 | anchor_bottom = 1.0 69 | custom_fonts/font = ExtResource( 3 ) 70 | __meta__ = { 71 | "_edit_use_anchors_": false 72 | } 73 | -------------------------------------------------------------------------------- /addons/godot_db_manager/table_editor.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBTableEditor 3 | """ 4 | 5 | class_name GDDBTableEditor 6 | 7 | tool 8 | extends Control 9 | 10 | signal set_dirty 11 | 12 | var m_parent_table = null 13 | 14 | # Called when the node enters the scene tree for the first time. 15 | func _ready() -> void: 16 | $tabs/structure/header/new_property_btn.connect("pressed", self, "on_new_property_btn_pressed") 17 | $tabs/data/add_data_btn.connect("pressed", self, "on_add_row_data_btn_pressed") 18 | $tabs/data/add_data_btn.set_disabled(true) 19 | 20 | $load_res_path_dlg.connect("file_selected", self, "on_select_res_path") 21 | 22 | $data_dlg.connect("select_data", self, "on_select_data") 23 | 24 | $edit_string_dlg.connect("string_edited", self, "on_text_edited") 25 | 26 | $delete_prop_dlg.connect("delete_prop", self, "on_confirm_delete_property") 27 | 28 | # called when resizing a property 29 | func on_resize_property(prop_id : int, diff_x : float) -> void : 30 | var current_prop = null 31 | for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()): 32 | var prop = $tabs/data/scroll/data_holder/data_header.get_child(idx) 33 | if(prop.get_prop_id() == prop_id): 34 | current_prop = prop 35 | break 36 | 37 | var prop_size : Vector2 = current_prop.get_child(0).get_size() 38 | 39 | # print("diff_x: " + str(diff_x)) 40 | prop_size.x += diff_x 41 | 42 | if(prop_size.x < gddb_constants.c_min_cell_width): 43 | return 44 | if(prop_size.x > gddb_constants.c_max_cell_width): 45 | return 46 | 47 | # print("prop_size.x = " + str(prop_size.x)) 48 | 49 | var prop_idx = -1 50 | 51 | var data_size = $tabs/data/scroll.get_size() 52 | data_size.x += diff_x 53 | $tabs/data/scroll/data_holder/data_header.set_size(data_size) 54 | 55 | for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()): 56 | var prop = $tabs/data/scroll/data_holder/data_header.get_child(idx) 57 | if(prop.get_prop_id() == prop_id): 58 | var current_prop_size = prop.get_custom_minimum_size() 59 | current_prop_size.x += diff_x 60 | prop.set_custom_minimum_size(current_prop_size) 61 | prop_idx = idx 62 | 63 | if(prop_idx != -1 && idx > prop_idx): 64 | var pos = prop.get_position() 65 | pos.x += diff_x 66 | prop.set_position(pos) 67 | 68 | for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()): 69 | var row = $tabs/data/scroll/data_holder/data_container.get_child(idx) 70 | for jdx in range(0, row.get_child_count()): 71 | var cell = row.get_child(jdx) 72 | if(cell.get_prop_id() == prop_id): 73 | cell.set_custom_minimum_size(prop_size) 74 | if(jdx > prop_idx): 75 | var pos = cell.get_position() 76 | pos.x += diff_x 77 | cell.set_position(pos) 78 | 79 | # called when the new_property button is pressed 80 | func on_new_property_btn_pressed() -> void: 81 | # print("GDDBTableEditor::on_new_property_btn_pressed()") 82 | if(null == m_parent_table): 83 | print("ERROR: GDDBTableEditor::on_new_property_btn_pressed() - m_parent_table is null") 84 | return 85 | var prop_idx = m_parent_table.get_props_count() 86 | var prop_type = gddb_types.e_prop_type_bool 87 | var prop_name = "Property_" + str(prop_idx+1) 88 | var prop_id = m_parent_table.add_prop(prop_type, prop_name) 89 | add_prop_to_structure(prop_id, prop_type, prop_name) 90 | add_prop_to_data(prop_id, prop_type, prop_name, false) 91 | 92 | # enable add data btn 93 | $tabs/data/add_data_btn.set_disabled(false) 94 | 95 | emit_signal("set_dirty") 96 | 97 | # adds a property to structure tab 98 | func add_prop_to_structure(prop_id : int, prop_type : int, prop_name : String) -> void: 99 | # print("GDDBTableEditor::add_prop_to_structure(" + str(prop_id) + ", " + str(prop_type) + ", " + prop_name + ")") 100 | var prop = load(gddb_constants.c_addon_main_path + "table_property.tscn").instance() 101 | $tabs/structure/scroll/properties.add_child(prop) 102 | prop.set_parent_table(m_parent_table) 103 | prop.setup(prop_id, prop_type, prop_name) 104 | prop.connect("edit_property", self, "on_edit_property") 105 | prop.connect("delete_property", self, "on_delete_property") 106 | prop.connect("enable_autoincrement", self, "on_enable_prop_autoincrement") 107 | 108 | # adds a property to data tab 109 | func add_prop_to_data(prop_id : int, prop_type : int, prop_name : String, has_autoincrement : bool) -> void: 110 | var prop = load(gddb_constants.c_addon_main_path + "data_label.tscn").instance() 111 | $tabs/data/scroll/data_holder/data_header.add_child(prop) 112 | prop.set_prop_id(prop_id) 113 | prop.set_text(prop_name) 114 | prop.connect("resize_property", self, "on_resize_property") 115 | 116 | # add property to the existing rows 117 | for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()): 118 | var row = $tabs/data/scroll/data_holder/data_container.get_child(idx) 119 | var cell = load(gddb_constants.c_addon_main_path + "table_cell.tscn").instance() 120 | row.add_child(cell) 121 | cell.set_prop_id(prop_id) 122 | cell.set_row_idx(idx) 123 | cell.set_prop_type(prop_type) 124 | cell.set_text("") 125 | cell.enable_autoincrement(has_autoincrement) 126 | cell.connect("edit_data", self, "on_edit_data") 127 | cell.connect("choose_resource", self, "on_choose_resource") 128 | cell.connect("choose_data", self, "on_choose_data") 129 | cell.connect("edit_string", self, "on_edit_string") 130 | 131 | # called when the add data button is pressed 132 | func on_add_row_data_btn_pressed() -> void: 133 | # print("GDDBTableEditor::on_add_row_data_btn_pressed") 134 | # add blank row in the table 135 | var row_idx = m_parent_table.get_rows_count() 136 | m_parent_table.add_blank_row() 137 | 138 | # add row in the interface 139 | var row = HBoxContainer.new() 140 | $tabs/data/scroll/data_holder/data_container.add_child(row) 141 | for idx in range(0, $tabs/structure/scroll/properties.get_child_count()): 142 | var cell = load(gddb_constants.c_addon_main_path + "table_cell.tscn").instance() 143 | var prop = $tabs/structure/scroll/properties.get_child(idx) 144 | var db_prop = m_parent_table.get_prop_by_id(idx) 145 | row.add_child(cell) 146 | cell.set_prop_id(idx) 147 | cell.set_row_idx(row_idx) 148 | cell.set_prop_type(prop.get_prop_type()) 149 | var autoincrement = db_prop.has_autoincrement() 150 | cell.enable_autoincrement(db_prop.has_autoincrement()) 151 | if(autoincrement): 152 | cell.set_text(str(row_idx+1)) 153 | cell.connect("edit_data", self, "on_edit_data") 154 | cell.connect("choose_resource", self, "on_choose_resource") 155 | cell.connect("choose_data", self, "on_choose_data") 156 | cell.connect("edit_string", self, "on_edit_string") 157 | 158 | emit_signal("set_dirty") 159 | 160 | # sets the table from database 161 | func set_table(table : Object) -> void: 162 | # print("GDDBTableEditor::set_table(" + table.get_table_name() + ")") 163 | clear_current_layout() 164 | 165 | m_parent_table = table 166 | fill_properties() 167 | fill_data() 168 | 169 | # fills the interface with current table's properties 170 | func fill_properties() -> void: 171 | # print("GDDBTableEditor::fill_properties()") 172 | var props_count = m_parent_table.get_props_count() 173 | for idx in range(0, props_count): 174 | var db_prop = m_parent_table.get_prop_at(idx) 175 | add_prop_to_structure(db_prop.get_prop_id(), db_prop.get_prop_type(), db_prop.get_prop_name()) 176 | var prop = load(gddb_constants.c_addon_main_path + "data_label.tscn").instance() 177 | $tabs/data/scroll/data_holder/data_header.add_child(prop) 178 | prop.set_prop_id(db_prop.get_prop_id()) 179 | prop.set_prop_type(db_prop.get_prop_type()) 180 | prop.set_text(db_prop.get_prop_name()) 181 | prop.connect("resize_property", self, "on_resize_property") 182 | if(props_count > 0): 183 | $tabs/data/add_data_btn.set_disabled(false) 184 | 185 | # fills the interface with current table's data 186 | func fill_data() -> void: 187 | #print("GDDBTableEditor::fill_data()") 188 | var rows_count = m_parent_table.get_rows_count() 189 | #print("Table name: " + m_parent_table.get_table_name()) 190 | #print("rows_count: " + str(rows_count)) 191 | for idx in range(0, rows_count): 192 | var row = HBoxContainer.new() 193 | $tabs/data/scroll/data_holder/data_container.add_child(row) 194 | var data_row = m_parent_table.get_data_at_row_idx(idx) 195 | for jdx in range(0, data_row.size()): 196 | var db_prop = m_parent_table.get_prop_at(jdx) 197 | #print("Prop id: " + str(db_prop.get_prop_id())) 198 | #print("Prop type: " + str(db_prop.get_prop_type())) 199 | #print("Prop name: " + str(db_prop.get_prop_name())) 200 | 201 | var cell = load(gddb_constants.c_addon_main_path + "table_cell.tscn").instance() 202 | var cell_data = data_row[jdx].get_data() 203 | 204 | var prop_type = db_prop.get_prop_type() 205 | if(prop_type >= gddb_types.e_prop_types_count): 206 | var db = m_parent_table.get_parent_database() 207 | var table = db.get_table_by_id(prop_type - gddb_types.e_prop_types_count) 208 | var data_row_idx = cell_data.to_int() 209 | cell_data = gddb_globals.get_json_from_row(table, data_row_idx) 210 | 211 | row.add_child(cell) 212 | 213 | cell.set_prop_id(data_row[jdx].get_prop_id()) 214 | cell.set_row_idx(idx) 215 | cell.set_prop_type(prop_type) 216 | cell.set_text(cell_data) 217 | cell.enable_autoincrement(db_prop.has_autoincrement()) 218 | cell.connect("edit_data", self, "on_edit_data") 219 | cell.connect("choose_resource", self, "on_choose_resource") 220 | cell.connect("choose_data", self, "on_choose_data") 221 | cell.connect("edit_string", self, "on_edit_string") 222 | 223 | # links properties 224 | func link_props() -> void : 225 | # print("GDDBTableEditor::link_props() for table with name: " + m_parent_table.get_table_name()) 226 | for idx in range(0, $tabs/structure/scroll/properties.get_child_count()): 227 | var prop = $tabs/structure/scroll/properties.get_child(idx) 228 | prop.link() 229 | 230 | # refreshes autoincrement props 231 | func refresh_autoincrement_props(prop_id, enable) -> void: 232 | for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()): 233 | var row = $tabs/data/scroll/data_holder/data_container.get_child(idx) 234 | for jdx in range(0, row.get_child_count()): 235 | var cell = row.get_child(jdx) 236 | if(cell.get_prop_id() == prop_id): 237 | cell.enable_autoincrement(enable) 238 | 239 | # cleares current layout 240 | func clear_current_layout() -> void: 241 | # clear structure tab 242 | for idx in range(0, $tabs/structure/scroll/properties.get_child_count()): 243 | $tabs/structure/scroll/properties.get_child(idx).queue_free() 244 | 245 | # clear data from data tab 246 | for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()): 247 | var row = $tabs/data/scroll/data_holder/data_container.get_child(idx) 248 | for jdx in range(0, row.get_child_count()): 249 | row.get_child(jdx).queue_free() 250 | row.queue_free() 251 | 252 | # clear properties from data tab 253 | for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()): 254 | $tabs/data/scroll/data_holder/data_header.get_child(idx).queue_free() 255 | 256 | $tabs/data/add_data_btn.set_disabled(true) 257 | 258 | # called when a property is edited 259 | func on_edit_property(prop_id : int, prop_type : int, prop_name : String) -> void: 260 | """ 261 | print("GDDBTableEditor::on_edit_property(" + str(prop_id) + ", " + str(prop_type) + ", " + prop_name + ")") 262 | if(prop_type >= gddb_types.e_prop_types_count): 263 | var db = m_parent_table.get_parent_database() 264 | var selected_table = db.get_table_by_id(gddb_types.e_prop_types_count - prop_type) 265 | print("GDDBTableEditor::on_edit_property(" + str(prop_id) + ", " + selected_table.get_table_name() + ", " + prop_name + ")") 266 | else: 267 | print("GDDBTableEditor::on_edit_property(" + str(prop_id) + ", " + gddb_globals.get_data_name(prop_type) + ", " + prop_name + ")") 268 | #""" 269 | # edit prop in the table 270 | m_parent_table.edit_prop(prop_id, prop_type, prop_name) 271 | 272 | # refresh the prop name in data tab 273 | for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()): 274 | var prop = $tabs/data/scroll/data_holder/data_header.get_child(idx) 275 | if(prop.get_prop_id() == prop_id): 276 | prop.set_text(prop_name) 277 | 278 | # update data type 279 | for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()): 280 | var row = $tabs/data/scroll/data_holder/data_container.get_child(idx) 281 | for jdx in range(0, row.get_child_count()): 282 | var cell = row.get_child(jdx) 283 | if(cell.get_prop_id() == prop_id): 284 | """ 285 | if(prop_type < gddb_types.e_prop_types_count): 286 | print("Prop type: " + gddb_globals.get_data_name(prop_type)) 287 | else: 288 | print("Prop type: custom") 289 | """ 290 | cell.set_prop_type(prop_type) 291 | 292 | emit_signal("set_dirty") 293 | 294 | # called when a property is deleted 295 | func on_delete_property(prop_id : int) -> void: 296 | # print("GDDBTableEditor::on_delete_property(" + str(prop_id) + ")") 297 | var prop = m_parent_table.get_prop_by_id(prop_id) 298 | $delete_prop_dlg.set_prop_id(prop_id) 299 | $delete_prop_dlg.set_prop_name(prop.get_prop_name()) 300 | $delete_prop_dlg.popup_centered() 301 | 302 | # called when a property is deleted 303 | func on_confirm_delete_property() -> void: 304 | var prop_id = $delete_prop_dlg.get_prop_id() 305 | 306 | # deletes a property from table; also all data by this property 307 | m_parent_table.delete_prop(prop_id) 308 | 309 | # delete cells from data tab 310 | for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()): 311 | var row = $tabs/data/scroll/data_holder/data_container.get_child(idx) 312 | for jdx in range(0, row.get_child_count()): 313 | var cell = row.get_child(jdx) 314 | if(cell.get_prop_id() == prop_id): 315 | cell.disconnect("edit_data", self, "on_edit_data") 316 | cell.queue_free() 317 | break 318 | 319 | # delete property from data tab 320 | for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()): 321 | var prop = $tabs/data/scroll/data_holder/data_header.get_child(idx) 322 | if(prop.get_prop_id() == prop_id): 323 | prop.queue_free() 324 | break 325 | 326 | # delete prop from structure 327 | for idx in range(0, $tabs/structure/scroll/properties.get_child_count()): 328 | var prop = $tabs/structure/scroll/properties.get_child(idx) 329 | if(prop.get_prop_id() == prop_id): 330 | prop.queue_free() 331 | break 332 | 333 | # refresh the add data button 334 | var props_count = m_parent_table.get_props_count() 335 | if(props_count == 0): 336 | $tabs/data/add_data_btn.set_disabled(true) 337 | 338 | emit_signal("set_dirty") 339 | 340 | # called when the property has autoincrement or not 341 | func on_enable_prop_autoincrement(prop_id : int, enable : bool) -> void : 342 | m_parent_table.enable_prop_autoincrement(prop_id, enable) 343 | emit_signal("set_dirty") 344 | refresh_autoincrement_props(prop_id, enable) 345 | 346 | # reindex all data 347 | if(enable): 348 | for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()): 349 | var row = $tabs/data/scroll/data_holder/data_container.get_child(idx) 350 | for jdx in range(0, row.get_child_count()): 351 | var cell = row.get_child(jdx) 352 | if(cell.get_prop_id() == prop_id): 353 | cell.set_text(str(idx + 1)) 354 | 355 | # called when edit data 356 | func on_edit_data(prop_id : int, row_idx : int, data : String) -> void: 357 | m_parent_table.edit_data(prop_id, row_idx, data) 358 | emit_signal("set_dirty") 359 | 360 | # called when choosing a resource 361 | func on_choose_resource(prop_id : int, row_idx : int) -> void: 362 | # print("GDDBTableEditor::on_choose_resource(" + str(prop_id) + ", " + str(row_idx) + ")") 363 | $load_res_path_dlg.set_prop_id(prop_id) 364 | $load_res_path_dlg.set_row_idx(row_idx) 365 | $load_res_path_dlg.popup_centered() 366 | 367 | # called when choosing a data 368 | func on_choose_data(prop_id : int, row_idx : int, prop_type : int) -> void: 369 | # print("GDDBTableEditor::on_choose_data(" + str(prop_id) + ", " + str(row_idx) + ", " + str(prop_type) + ")") 370 | $data_dlg.set_prop_id(prop_id) 371 | $data_dlg.set_row_idx(row_idx) 372 | var table_id = prop_type - gddb_types.e_prop_types_count 373 | var db = m_parent_table.get_parent_database() 374 | var tbl = db.get_table_by_id(table_id) 375 | $data_dlg.set_table(tbl) 376 | $data_dlg.popup_centered() 377 | 378 | # called when choosing to edit string 379 | func on_edit_string(prop_id : int, row_idx : int, text : String) -> void: 380 | $edit_string_dlg.set_prop_id(prop_id) 381 | $edit_string_dlg.set_row_idx(row_idx) 382 | $edit_string_dlg.set_data_text(text) 383 | $edit_string_dlg.popup_centered() 384 | 385 | # called when selecting a resource filepath 386 | func on_select_res_path(filepath : String) -> void: 387 | # print("GDDBTableEditor::on_select_res_path(" + filepath + ")") 388 | var prop_id = $load_res_path_dlg.get_prop_id() 389 | var row_idx = $load_res_path_dlg.get_row_idx() 390 | m_parent_table.edit_data(prop_id, row_idx, filepath) 391 | var row = $tabs/data/scroll/data_holder/data_container.get_child(row_idx) 392 | for idx in range(0, row.get_child_count()): 393 | var cell = row.get_child(idx) 394 | if(cell.get_prop_id() == prop_id): 395 | cell.set_text(filepath) 396 | 397 | emit_signal("set_dirty") 398 | 399 | # called when data from a table is choosen 400 | func on_select_data(prop_id : int, row_idx : int, data_row_idx : int, data : String) -> void: 401 | # set the data in the databes / table 402 | m_parent_table.edit_data(prop_id, row_idx, str(data_row_idx)) 403 | 404 | # fill in the interface cell with data 405 | var row = $tabs/data/scroll/data_holder/data_container.get_child(row_idx) 406 | for idx in range(0, row.get_child_count()): 407 | var cell = row.get_child(idx) 408 | if(cell.get_prop_id() == prop_id): 409 | cell.set_text(data) 410 | break 411 | 412 | emit_signal("set_dirty") 413 | 414 | # called when the text is edited 415 | func on_text_edited(): 416 | var prop_id = $edit_string_dlg.get_prop_id() 417 | var row_idx = $edit_string_dlg.get_row_idx() 418 | var text_data = $edit_string_dlg.get_data_text() 419 | 420 | var data = gddb_globals.handle_string(text_data) 421 | 422 | # print("GDDBTableEditor::on_text_edited() - prop_id: " + str(prop_id) + ", row_idx: " + str(row_idx) + ", data: " + text_data) 423 | 424 | m_parent_table.edit_data(prop_id, row_idx, data) 425 | 426 | var row = $tabs/data/scroll/data_holder/data_container.get_child(row_idx) 427 | for idx in range(0, row.get_child_count()): 428 | var cell = row.get_child(idx) 429 | if(cell.get_prop_id() == prop_id): 430 | cell.set_text(text_data) 431 | break 432 | 433 | emit_signal("set_dirty") 434 | -------------------------------------------------------------------------------- /addons/godot_db_manager/table_editor.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=16 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/dlgs/error_dlg.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/dlgs/load_res_path_dlg.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/table_editor.gd" type="Script" id=3] 6 | [ext_resource path="res://addons/godot_db_manager/dlgs/data_dlg.tscn" type="PackedScene" id=4] 7 | [ext_resource path="res://addons/godot_db_manager/dlgs/edit_string_dlg.tscn" type="PackedScene" id=5] 8 | [ext_resource path="res://addons/godot_db_manager/dlgs/delete_prop_dlg.tscn" type="PackedScene" id=6] 9 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=7] 10 | [ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=8] 11 | 12 | [sub_resource type="AtlasTexture" id=1] 13 | atlas = ExtResource( 8 ) 14 | region = Rect2( 2, 2, 24, 24 ) 15 | 16 | [sub_resource type="AtlasTexture" id=2] 17 | atlas = ExtResource( 8 ) 18 | region = Rect2( 2, 54, 24, 24 ) 19 | 20 | [sub_resource type="AtlasTexture" id=3] 21 | atlas = ExtResource( 8 ) 22 | region = Rect2( 2, 28, 24, 24 ) 23 | 24 | [sub_resource type="AtlasTexture" id=4] 25 | atlas = ExtResource( 8 ) 26 | region = Rect2( 2, 2, 24, 24 ) 27 | 28 | [sub_resource type="AtlasTexture" id=5] 29 | atlas = ExtResource( 8 ) 30 | region = Rect2( 2, 54, 24, 24 ) 31 | 32 | [sub_resource type="AtlasTexture" id=6] 33 | atlas = ExtResource( 8 ) 34 | region = Rect2( 2, 28, 24, 24 ) 35 | 36 | [sub_resource type="AtlasTexture" id=7] 37 | atlas = ExtResource( 8 ) 38 | region = Rect2( 132, 2, 24, 24 ) 39 | 40 | [node name="table" type="Control"] 41 | anchor_right = 1.0 42 | anchor_bottom = 1.0 43 | script = ExtResource( 3 ) 44 | __meta__ = { 45 | "_edit_horizontal_guides_": [ 584.0, 64.0, 70.0 ], 46 | "_edit_use_anchors_": false, 47 | "_edit_vertical_guides_": [ 1000.47 ] 48 | } 49 | 50 | [node name="tabs" type="TabContainer" parent="."] 51 | anchor_right = 1.0 52 | anchor_bottom = 1.0 53 | custom_fonts/font = ExtResource( 7 ) 54 | __meta__ = { 55 | "_edit_use_anchors_": false 56 | } 57 | 58 | [node name="structure" type="Tabs" parent="tabs"] 59 | visible = false 60 | anchor_right = 1.0 61 | anchor_bottom = 1.0 62 | margin_left = 4.0 63 | margin_top = 40.0 64 | margin_right = -4.0 65 | margin_bottom = -4.0 66 | tab_close_display_policy = 2 67 | 68 | [node name="header" type="HBoxContainer" parent="tabs/structure"] 69 | margin_right = 892.0 70 | margin_bottom = 24.0 71 | __meta__ = { 72 | "_edit_use_anchors_": false 73 | } 74 | 75 | [node name="new_property_btn" type="TextureButton" parent="tabs/structure/header"] 76 | margin_right = 24.0 77 | margin_bottom = 24.0 78 | texture_normal = SubResource( 1 ) 79 | texture_pressed = SubResource( 2 ) 80 | texture_hover = SubResource( 3 ) 81 | 82 | [node name="props_lbl" type="Label" parent="tabs/structure/header"] 83 | margin_left = 28.0 84 | margin_top = 1.0 85 | margin_right = 114.0 86 | margin_bottom = 23.0 87 | custom_fonts/font = ExtResource( 7 ) 88 | text = "Properties:" 89 | __meta__ = { 90 | "_edit_use_anchors_": false 91 | } 92 | 93 | [node name="scroll" type="ScrollContainer" parent="tabs/structure"] 94 | anchor_right = 1.0 95 | anchor_bottom = 1.0 96 | margin_top = 30.0 97 | __meta__ = { 98 | "_edit_use_anchors_": false 99 | } 100 | 101 | [node name="properties" type="VBoxContainer" parent="tabs/structure/scroll"] 102 | __meta__ = { 103 | "_edit_use_anchors_": false 104 | } 105 | 106 | [node name="data" type="Tabs" parent="tabs"] 107 | anchor_right = 1.0 108 | anchor_bottom = 1.0 109 | margin_left = 4.0 110 | margin_top = 40.0 111 | margin_right = -4.0 112 | margin_bottom = -4.0 113 | tab_close_display_policy = 2 114 | 115 | [node name="add_data_btn" type="TextureButton" parent="tabs/data"] 116 | margin_right = 24.0 117 | margin_bottom = 24.0 118 | disabled = true 119 | texture_normal = SubResource( 4 ) 120 | texture_pressed = SubResource( 5 ) 121 | texture_hover = SubResource( 6 ) 122 | texture_disabled = SubResource( 7 ) 123 | __meta__ = { 124 | "_edit_use_anchors_": false 125 | } 126 | 127 | [node name="scroll" type="ScrollContainer" parent="tabs/data"] 128 | anchor_right = 1.0 129 | anchor_bottom = 1.0 130 | margin_top = 38.0 131 | __meta__ = { 132 | "_edit_use_anchors_": false 133 | } 134 | 135 | [node name="data_holder" type="VBoxContainer" parent="tabs/data/scroll"] 136 | margin_bottom = 36.0 137 | __meta__ = { 138 | "_edit_use_anchors_": false 139 | } 140 | 141 | [node name="data_header" type="HBoxContainer" parent="tabs/data/scroll/data_holder"] 142 | margin_bottom = 32.0 143 | rect_min_size = Vector2( 0, 32 ) 144 | rect_clip_content = true 145 | 146 | [node name="data_container" type="VBoxContainer" parent="tabs/data/scroll/data_holder"] 147 | margin_top = 36.0 148 | margin_bottom = 36.0 149 | 150 | [node name="error_dlg" parent="." instance=ExtResource( 1 )] 151 | visible = false 152 | 153 | [node name="load_res_path_dlg" parent="." instance=ExtResource( 2 )] 154 | filters = PoolStringArray( "*.res, *.tres ; Godot resource file types", "*.scn, *.tscn, *escn ; Godot scene file types", "*.gd, *.cs, *.h, *.c, *.hpp, *.cpp ; Code file types", "*.shader ; Shader file types", "*.mat ; Material file types", "*.dae, *.gltf, *.obj, *.fbx ; Mesh file types", "*.anim ; Animation file types", "*.ttf, *.otf ; Font file types", "*.png, *.jpg, *.jpeg, *.tiff, *.tga, *.bmp, *.webp, *.gif, *.hdr ; Images file types", "*.snd, *.wav, *.ogg, *.mp3 ; Sound file types", "*.ogg, *.mpg, *.mpeg, *.avi, *.mov, *.mp4, *.webm ; Video file types", "*.txt, *.csv, *.json, *.xml, *.cfg, *.ini ; Text file types", "*.doc, *.docx, *.xls, *.xlsx, *.odt, *.ods, *.pdf ; Doc file types", "*.dat, *.raw ; Binary data file types" ) 155 | 156 | [node name="data_dlg" parent="." instance=ExtResource( 4 )] 157 | 158 | [node name="edit_string_dlg" parent="." instance=ExtResource( 5 )] 159 | 160 | [node name="delete_prop_dlg" parent="." instance=ExtResource( 6 )] 161 | visible = false 162 | -------------------------------------------------------------------------------- /addons/godot_db_manager/table_item.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBTableItem 3 | """ 4 | 5 | class_name GDDBTableItem 6 | 7 | tool 8 | extends Control 9 | 10 | signal select_item 11 | signal edit_table 12 | signal delete_table 13 | 14 | var m_table_id = gddb_constants.c_invalid_id 15 | var m_table_name = "" 16 | 17 | var m_is_selected = false 18 | 19 | # Called when the node enters the scene tree for the first time. 20 | func _ready(): 21 | $select_btn.connect("pressed", self, "on_select_btn_pressed") 22 | $edit_table_btn.connect("pressed", self, "on_edit_table_btn_pressed") 23 | $delete_table_btn.connect("pressed", self, "on_delete_table_btn_pressed") 24 | $select.hide() 25 | 26 | # sets the table id 27 | func set_table_id(id : int) -> void: 28 | m_table_id = id 29 | 30 | # returns the table id 31 | func get_table_id() -> int: 32 | return m_table_id 33 | 34 | func set_selected(select : bool) -> void : 35 | m_is_selected = select 36 | if(m_is_selected): 37 | $select.show() 38 | else: 39 | $select.hide() 40 | 41 | func is_selected(): 42 | return m_is_selected 43 | 44 | # sets the table name 45 | func set_table_name(name : String) -> void: 46 | # print("GDDBTableItem::set_table_name(" + name + ")") 47 | m_table_name = name 48 | $table_name.set_text(m_table_name) 49 | 50 | # returns the table name 51 | func get_table_name() -> String: 52 | return m_table_name 53 | 54 | # called when the user presses the edit_table button 55 | func on_edit_table_btn_pressed(): 56 | # print("GDDBTableItem::on_edit_table_btn_pressed") 57 | emit_signal("edit_table", m_table_id, m_table_name) 58 | 59 | # called when the user presses the delete_table button 60 | func on_delete_table_btn_pressed(): 61 | # print("GDDBTableItem::on_delete_table_btn_pressed") 62 | emit_signal("delete_table", m_table_id) 63 | 64 | # called when select_btn is pressed 65 | func on_select_btn_pressed() -> void: 66 | # print("GDDBTableItem::on_select_btn_pressed()") 67 | emit_signal("select_item", m_table_id) 68 | -------------------------------------------------------------------------------- /addons/godot_db_manager/table_item.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=11 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/table_item.gd" type="Script" id=3] 6 | [ext_resource path="res://addons/godot_db_manager/assets/tex/debug.png" type="Texture" id=4] 7 | 8 | [sub_resource type="AtlasTexture" id=1] 9 | atlas = ExtResource( 2 ) 10 | region = Rect2( 28, 2, 24, 24 ) 11 | 12 | [sub_resource type="AtlasTexture" id=2] 13 | atlas = ExtResource( 2 ) 14 | region = Rect2( 28, 54, 24, 24 ) 15 | 16 | [sub_resource type="AtlasTexture" id=3] 17 | atlas = ExtResource( 2 ) 18 | region = Rect2( 28, 28, 24, 24 ) 19 | 20 | [sub_resource type="AtlasTexture" id=4] 21 | atlas = ExtResource( 2 ) 22 | region = Rect2( 54, 2, 24, 24 ) 23 | 24 | [sub_resource type="AtlasTexture" id=5] 25 | atlas = ExtResource( 2 ) 26 | region = Rect2( 54, 54, 24, 24 ) 27 | 28 | [sub_resource type="AtlasTexture" id=6] 29 | atlas = ExtResource( 2 ) 30 | region = Rect2( 54, 28, 24, 24 ) 31 | 32 | [node name="table_item" type="Control"] 33 | anchor_right = 1.0 34 | anchor_bottom = 0.021 35 | margin_bottom = 0.399998 36 | rect_min_size = Vector2( 180, 34 ) 37 | script = ExtResource( 3 ) 38 | __meta__ = { 39 | "_edit_horizontal_guides_": [ 34.0 ], 40 | "_edit_use_anchors_": false, 41 | "_edit_vertical_guides_": [ 170.0 ] 42 | } 43 | 44 | [node name="dbg" type="NinePatchRect" parent="."] 45 | visible = false 46 | anchor_right = 1.0 47 | anchor_bottom = 1.0 48 | texture = ExtResource( 4 ) 49 | region_rect = Rect2( 38, 38, 10, 10 ) 50 | __meta__ = { 51 | "_edit_use_anchors_": false 52 | } 53 | 54 | [node name="select" type="NinePatchRect" parent="."] 55 | visible = false 56 | anchor_right = 1.0 57 | anchor_bottom = 1.0 58 | texture = ExtResource( 2 ) 59 | region_rect = Rect2( 80, 6, 24, 4 ) 60 | __meta__ = { 61 | "_edit_use_anchors_": false 62 | } 63 | 64 | [node name="table_name" type="Label" parent="."] 65 | anchor_right = 1.0 66 | anchor_bottom = 1.0 67 | margin_right = -6.10352e-05 68 | margin_bottom = -4.0 69 | rect_min_size = Vector2( 100, 0 ) 70 | custom_fonts/font = ExtResource( 1 ) 71 | text = "Table_999" 72 | valign = 1 73 | __meta__ = { 74 | "_edit_use_anchors_": false 75 | } 76 | 77 | [node name="select_btn" type="TextureButton" parent="."] 78 | anchor_right = 1.0 79 | anchor_bottom = 1.0 80 | __meta__ = { 81 | "_edit_use_anchors_": false 82 | } 83 | 84 | [node name="edit_table_btn" type="TextureButton" parent="."] 85 | anchor_left = 1.0 86 | anchor_right = 1.0 87 | anchor_bottom = 1.0 88 | margin_left = -56.0 89 | margin_top = 5.0 90 | margin_right = -32.0 91 | margin_bottom = -5.0 92 | texture_normal = SubResource( 1 ) 93 | texture_pressed = SubResource( 2 ) 94 | texture_hover = SubResource( 3 ) 95 | __meta__ = { 96 | "_edit_use_anchors_": false 97 | } 98 | 99 | [node name="delete_table_btn" type="TextureButton" parent="."] 100 | anchor_left = 1.0 101 | anchor_right = 1.0 102 | anchor_bottom = 1.0 103 | margin_left = -28.0 104 | margin_top = 5.0 105 | margin_right = -4.0 106 | margin_bottom = -5.0 107 | texture_normal = SubResource( 4 ) 108 | texture_pressed = SubResource( 5 ) 109 | texture_hover = SubResource( 6 ) 110 | -------------------------------------------------------------------------------- /addons/godot_db_manager/table_property.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBTableProperty 3 | """ 4 | 5 | class_name GDDBTableProperty 6 | 7 | tool 8 | extends Control 9 | 10 | signal delete_property 11 | signal edit_property 12 | signal enable_autoincrement 13 | 14 | var m_prop_id : int = -1 15 | var m_prop_type : int = 0 16 | var m_prop_name : String = "" 17 | 18 | var m_parent_table = null 19 | 20 | # Called when the node enters the scene tree for the first time. 21 | func _ready() -> void: 22 | $prop_name.connect("text_changed", self, "on_name_changed") 23 | 24 | $prop_type.clear() 25 | for idx in range(0, gddb_types.e_prop_types_count): 26 | $prop_type.add_item(gddb_globals.get_data_name(idx), gddb_types.e_prop_type_bool + idx) 27 | $prop_type.select(0) 28 | 29 | $prop_type.get_popup().connect("about_to_show", self, "on_about_to_show") 30 | $prop_type.connect("item_selected", self, "on_type_changed") 31 | 32 | $delete_button.connect("pressed", self, "on_delete_button_pressed") 33 | 34 | $autoincrement_btn.hide() 35 | $autoincrement_btn.connect("toggled", self, "on_set_autoincrement") 36 | 37 | # setup property 38 | func setup(prop_id : int, prop_type : int, prop_name : String) -> void: 39 | """ 40 | if(prop_type < gddb_types.e_prop_types_count): 41 | print("GDDBTableProperty::setup(" + str(prop_id) + ", " + gddb_globals.get_data_name(prop_type) + ", " + prop_name + ")") 42 | else: 43 | var db = m_parent_table.get_parent_database() 44 | var table = db.get_table_by_id(prop_type - gddb_types.e_prop_types_count) 45 | print("GDDBTableProperty::setup(" + str(prop_id) + ", " + table.get_table_name() + ", " + prop_name + ")") 46 | #""" 47 | set_prop_id(prop_id) 48 | set_prop_type(prop_type) 49 | set_prop_name(prop_name) 50 | 51 | # sets parent table 52 | func set_parent_table(table): 53 | #print("GDDBTableProperty::set_parent_table(" + str(table) + ")") 54 | m_parent_table = table 55 | var db = m_parent_table.get_parent_database() 56 | for idx in range(0, db.get_tables_count()): 57 | var tbl = db.get_table_at(idx) 58 | if(tbl == m_parent_table): 59 | continue 60 | $prop_type.add_item(tbl.get_table_name(), gddb_types.e_prop_types_count + tbl.get_table_id()) 61 | 62 | # sets proprty id 63 | func set_prop_id(prop_id : int) -> void: 64 | # print("GDDBTableProperty::set_prop_id(" + str(prop_id) + ")") 65 | m_prop_id = prop_id 66 | 67 | # returns property id 68 | func get_prop_id() -> int: 69 | return m_prop_id 70 | 71 | # sets property type 72 | func set_prop_type(prop_type : int) -> void: 73 | """ 74 | print("GDDBTableProperty::set_prop_type(" + str(prop_type) + ")") 75 | if(prop_type < gddb_types.e_prop_types_count): 76 | print("GDDBTableProperty::set_prop_type(" + gddb_globals.get_data_name(prop_type) + ")") 77 | else: 78 | var db = m_parent_table.get_parent_database() 79 | var table = db.get_table_by_id(prop_type - gddb_types.e_prop_types_count) 80 | print("GDDBTableProperty::set_prop_type(" + table.get_table_name() + ")") 81 | #""" 82 | #if(prop_type >= gddb_types.e_prop_types_count): 83 | # print("GDDBTableProperty::set_prop_type(" + str(prop_type) + ")") 84 | m_prop_type = prop_type 85 | select_current_prop() 86 | 87 | if(m_prop_type == gddb_types.e_prop_type_int): 88 | $autoincrement_btn.show() 89 | var prop = m_parent_table.get_prop_by_id(m_prop_id) 90 | if(prop.has_autoincrement()): 91 | $autoincrement_btn.set_pressed(true) 92 | else: 93 | $autoincrement_btn.hide() 94 | 95 | # selects current property 96 | func select_current_prop() -> void: 97 | if(m_prop_type < gddb_types.e_prop_types_count): 98 | $prop_type.select(m_prop_type) 99 | 100 | # links property type to other tables 101 | func link(): 102 | # print("GDDBTableProperty::link()") 103 | refill_list() 104 | if(m_prop_type >= gddb_types.e_prop_types_count): 105 | """ 106 | print("m_prop_id : " + str(m_prop_id)) 107 | print("m_prop_type : " + str(m_prop_type)) 108 | print("m_prop_name : " + m_prop_name) 109 | """ 110 | set_selection_by_id(m_prop_type) 111 | else: 112 | $prop_type.select(m_prop_type) 113 | 114 | # returns property type 115 | func get_prop_type() -> int: 116 | return m_prop_type 117 | 118 | # sets property name 119 | func set_prop_name(prop_name : String) -> void: 120 | # print("GDDBTableProperty::set_prop_name(" + prop_name + ")") 121 | m_prop_name = prop_name 122 | $prop_name.set_text(m_prop_name) 123 | 124 | # returns property name 125 | func get_prop_name() -> String: 126 | return m_prop_name 127 | 128 | # called everytime the name of the property is changed 129 | func on_name_changed(new_text : String) -> void: 130 | m_prop_name = new_text 131 | emit_signal("edit_property", m_prop_id, m_prop_type, m_prop_name) 132 | 133 | # called when the popup from option button is about to be shown 134 | func on_about_to_show(): 135 | var selected_id = $prop_type.get_selected_id() 136 | # print("GDDBTableProperty::on_about_to_show() - " + str(selected_id)) 137 | 138 | refill_list() 139 | set_selection_by_id(selected_id) 140 | 141 | # refills the list 142 | func refill_list() -> void : 143 | $prop_type.clear() 144 | for idx in range(0, gddb_types.e_prop_types_count): 145 | $prop_type.add_item(gddb_globals.get_data_name(idx), gddb_types.e_prop_type_bool + idx) 146 | 147 | if(null != m_parent_table): 148 | var db = m_parent_table.get_parent_database() 149 | for idx in range(0, db.get_tables_count()): 150 | var table = db.get_table_at(idx) 151 | if(table == m_parent_table): 152 | continue 153 | """ 154 | print("GDDBTableProperty::refill_list - Add:") 155 | print("table id: " + str(table.get_table_id())) 156 | print("table name: " + table.get_table_name()) 157 | #""" 158 | # print("GDDBTableProperty::prop_type.add_item(" + table.get_table_name() + ", " + str(gddb_types.e_prop_types_count + table.get_table_id()) + ")" ) 159 | $prop_type.add_item(table.get_table_name(), gddb_types.e_prop_types_count + table.get_table_id()) 160 | # $prop_type.select(selected_idx) 161 | 162 | # sets selection 163 | func set_selection_by_id(selected_id : int) -> void : 164 | # print("GDDBTableProperty::set_selection_by_id(" + str(selected_id) + ")") 165 | for idx in range(0, $prop_type.get_item_count()): 166 | if($prop_type.get_item_id(idx) == selected_id): 167 | $prop_type.select(idx) 168 | break 169 | 170 | func on_set_autoincrement(enable : bool) -> void: 171 | # print("GDDBTableProperty::on_set_autoincrement(" + str(enable) + ") - " + str(m_prop_id)) 172 | emit_signal("enable_autoincrement", m_prop_id, enable) 173 | 174 | # called everytime the type of the property is changed 175 | func on_type_changed(option_idx : int) -> void: 176 | var option_id = $prop_type.get_item_id(option_idx) 177 | """ 178 | print("GDDBTableProperty::on_type_changed(" + str(option_idx) + ")") 179 | print("option_id = " + str(option_id)) 180 | if(option_id >= gddb_types.e_prop_types_count): 181 | print("GDDBTableProperty::on_type_changed(" + str(option_id) + ")") 182 | else: 183 | print("GDDBTableProperty::on_type_changed(" + gddb_globals.get_data_name(option_id) + ")") 184 | #""" 185 | m_prop_type = option_id 186 | $autoincrement_btn.set_pressed(false) 187 | if(m_prop_type == gddb_types.e_prop_type_int): 188 | $autoincrement_btn.show() 189 | else: 190 | $autoincrement_btn.hide() 191 | emit_signal("edit_property", m_prop_id, m_prop_type, m_prop_name) 192 | 193 | # called when the delete property button is pressed 194 | func on_delete_button_pressed() -> void: 195 | emit_signal("delete_property", m_prop_id) 196 | -------------------------------------------------------------------------------- /addons/godot_db_manager/table_property.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/table_property.gd" type="Script" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=3] 6 | 7 | [sub_resource type="AtlasTexture" id=1] 8 | atlas = ExtResource( 1 ) 9 | region = Rect2( 54, 2, 24, 24 ) 10 | 11 | [sub_resource type="AtlasTexture" id=2] 12 | atlas = ExtResource( 1 ) 13 | region = Rect2( 54, 54, 24, 24 ) 14 | 15 | [sub_resource type="AtlasTexture" id=3] 16 | atlas = ExtResource( 1 ) 17 | region = Rect2( 54, 28, 24, 24 ) 18 | 19 | [node name="table_property" type="Control"] 20 | anchor_right = 1.0 21 | margin_bottom = 15.36 22 | rect_min_size = Vector2( 900, 32 ) 23 | script = ExtResource( 2 ) 24 | __meta__ = { 25 | "_edit_horizontal_guides_": [ 32.0 ], 26 | "_edit_use_anchors_": true 27 | } 28 | 29 | [node name="delete_button" type="TextureButton" parent="."] 30 | margin_left = 3.0 31 | margin_top = 4.0 32 | margin_right = 27.0 33 | margin_bottom = 28.0 34 | texture_normal = SubResource( 1 ) 35 | texture_pressed = SubResource( 2 ) 36 | texture_hover = SubResource( 3 ) 37 | __meta__ = { 38 | "_edit_use_anchors_": false 39 | } 40 | 41 | [node name="prop_name_label" type="Label" parent="."] 42 | margin_left = 28.0 43 | margin_top = 2.0 44 | margin_right = 97.0 45 | margin_bottom = 24.0 46 | custom_fonts/font = ExtResource( 3 ) 47 | text = " Name:" 48 | __meta__ = { 49 | "_edit_use_anchors_": false 50 | } 51 | 52 | [node name="prop_name" type="LineEdit" parent="."] 53 | margin_left = 109.0 54 | margin_right = 409.0 55 | margin_bottom = 32.0 56 | rect_min_size = Vector2( 300, 0 ) 57 | custom_fonts/font = ExtResource( 3 ) 58 | __meta__ = { 59 | "_edit_use_anchors_": false 60 | } 61 | 62 | [node name="type_label" type="Label" parent="."] 63 | margin_left = 413.0 64 | margin_top = 2.0 65 | margin_right = 473.0 66 | margin_bottom = 24.0 67 | custom_fonts/font = ExtResource( 3 ) 68 | text = " Type:" 69 | 70 | [node name="prop_type" type="OptionButton" parent="."] 71 | margin_left = 485.0 72 | margin_right = 735.0 73 | margin_bottom = 32.0 74 | rect_min_size = Vector2( 250, 0 ) 75 | custom_fonts/font = ExtResource( 3 ) 76 | text = "Bool" 77 | items = [ "Bool", null, false, 0, null, "Integer", null, false, 1, null, "Float", null, false, 2, null, "String", null, false, 3, null, "Resource", null, false, 4, null ] 78 | selected = 0 79 | 80 | [node name="autoincrement_btn" type="CheckBox" parent="."] 81 | visible = false 82 | margin_left = 740.0 83 | margin_right = 891.0 84 | margin_bottom = 32.0 85 | custom_fonts/font = ExtResource( 3 ) 86 | text = "Auto increment" 87 | __meta__ = { 88 | "_edit_use_anchors_": false 89 | } 90 | -------------------------------------------------------------------------------- /addons/godot_db_manager/tables_header.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBTablesHeader 3 | """ 4 | 5 | class_name GDDBTablesHeader 6 | 7 | tool 8 | extends Control 9 | 10 | signal add_table 11 | 12 | # Called when the node enters the scene tree for the first time. 13 | func _ready(): 14 | $add_table_btn.connect("pressed", self, "on_add_table_btn_pressed") 15 | 16 | func on_add_table_btn_pressed(): 17 | emit_signal("add_table") 18 | -------------------------------------------------------------------------------- /addons/godot_db_manager/tables_header.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_20.tres" type="DynamicFont" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/tables_header.gd" type="Script" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=3] 6 | 7 | [sub_resource type="AtlasTexture" id=1] 8 | atlas = ExtResource( 3 ) 9 | region = Rect2( 2, 2, 24, 24 ) 10 | 11 | [sub_resource type="AtlasTexture" id=2] 12 | atlas = ExtResource( 3 ) 13 | region = Rect2( 2, 54, 24, 24 ) 14 | 15 | [sub_resource type="AtlasTexture" id=3] 16 | atlas = ExtResource( 3 ) 17 | region = Rect2( 2, 28, 24, 24 ) 18 | 19 | [node name="tables_header" type="Control"] 20 | anchor_right = 0.188889 21 | anchor_bottom = 0.019 22 | margin_right = 6.10352e-05 23 | margin_bottom = -0.4 24 | rect_min_size = Vector2( 170, 30 ) 25 | script = ExtResource( 2 ) 26 | __meta__ = { 27 | "_edit_use_anchors_": true, 28 | "_edit_vertical_guides_": [ 170.0 ] 29 | } 30 | 31 | [node name="add_table_btn" type="TextureButton" parent="."] 32 | margin_left = 2.0 33 | margin_top = 2.0 34 | margin_right = 26.0 35 | margin_bottom = 26.0 36 | texture_normal = SubResource( 1 ) 37 | texture_pressed = SubResource( 2 ) 38 | texture_hover = SubResource( 3 ) 39 | __meta__ = { 40 | "_edit_use_anchors_": false 41 | } 42 | 43 | [node name="tables_lbl" type="Label" parent="."] 44 | anchor_left = 0.165 45 | anchor_right = 1.0 46 | anchor_bottom = 0.8 47 | margin_left = -0.0500259 48 | margin_right = -0.000152588 49 | custom_fonts/font = ExtResource( 1 ) 50 | text = "Tables " 51 | align = 1 52 | __meta__ = { 53 | "_edit_use_anchors_": false 54 | } 55 | 56 | [node name="line" type="NinePatchRect" parent="."] 57 | anchor_right = 1.0 58 | anchor_bottom = 1.0 59 | margin_top = 29.0 60 | margin_right = -0.000152588 61 | texture = ExtResource( 3 ) 62 | region_rect = Rect2( 80, 2, 24, 2 ) 63 | __meta__ = { 64 | "_edit_use_anchors_": false 65 | } 66 | -------------------------------------------------------------------------------- /addons/godot_db_manager/tables_list.gd: -------------------------------------------------------------------------------- 1 | """ 2 | class GDDBTablesList 3 | """ 4 | 5 | class_name GDDBTablesList 6 | 7 | tool 8 | extends Control 9 | 10 | signal resize_tables_list 11 | 12 | signal add_table 13 | signal edit_table_name 14 | signal delete_table 15 | signal select_table 16 | 17 | var m_tables = [] 18 | 19 | var m_mouse_pos_pressed : Vector2 = Vector2() 20 | var m_mouse_pressed : bool = false 21 | 22 | # Called when the node enters the scene tree for the first time. 23 | func _ready() -> void: 24 | m_mouse_pos_pressed = Vector2() 25 | m_mouse_pressed = false 26 | 27 | $tables_header.connect("add_table", self, "on_add_table") 28 | 29 | # called when the node gets an input 30 | func _input(event : InputEvent) -> void : 31 | if(!gddb_globals.is_interface_active()): 32 | return 33 | 34 | var evLocal = $resize_ctrl.make_input_local(event) 35 | 36 | if event is InputEventMouseButton : 37 | if(event.button_index == BUTTON_LEFT): 38 | if(event.pressed): 39 | var rect = Rect2(Vector2(0, 0), $resize_ctrl.get_size()) 40 | var inside = rect.has_point(evLocal.position) 41 | if(inside): 42 | m_mouse_pressed = true 43 | m_mouse_pos_pressed = evLocal.position 44 | else: 45 | m_mouse_pressed = false 46 | 47 | elif event is InputEventMouseMotion : 48 | if(m_mouse_pressed): 49 | var diff_x = evLocal.position.x - m_mouse_pos_pressed.x 50 | emit_signal("resize_tables_list", diff_x) 51 | 52 | # custom resizing the tables list 53 | func resize_content(size : Vector2) -> void : 54 | set_size(size) 55 | 56 | # I have no idea why I need to do this; this should be done automatically 57 | var content_size = $tables_container/tables.get_size() 58 | content_size.x = size.x 59 | $tables_container/tables.set_custom_minimum_size(content_size) 60 | 61 | # Called when the user presses the "add_table" button from the tables_list/header 62 | func on_add_table() -> void : 63 | # print("GDDBTablesList::on_add_table()") 64 | emit_signal("add_table") 65 | 66 | # creates a table 67 | func create_table(db_table : Object, select_table : bool = true) -> void: 68 | # print("GDDBTablesList::create_table(" + str(db_table) + ")") 69 | var table = load(gddb_constants.c_addon_main_path + "table_item.tscn").instance() 70 | var table_id = db_table.get_table_id() 71 | table.set_table_id(table_id) 72 | table.set_table_name(db_table.get_table_name()) 73 | table.connect("select_item", self, "on_select_item") 74 | table.connect("edit_table", self, "on_edit_table_name") 75 | table.connect("delete_table", self, "on_delete_table") 76 | m_tables.push_back(table) 77 | $tables_container/tables.add_child(table) 78 | if(select_table): 79 | select_item_by_id(table_id) 80 | 81 | # Called when the user presses the "edit_table" button from the tables_list/table 82 | func on_edit_table_name(table_id : int, table_name : String) -> void: 83 | # print("GDDBTablesList::on_edit_table_name(" + str(table_id) + ", " + table_name + ")") 84 | emit_signal("edit_table_name", table_id, table_name) 85 | 86 | # Called when the user presses the "delete_table" button from the tables_list/table 87 | func on_delete_table(table_id : int) -> void: 88 | # print("GDDBTablesList::on_delete_table(" + str(table_id) + ")") 89 | emit_signal("delete_table", table_id) 90 | 91 | # edits the table name 92 | func edit_table_name(table_id: int, table_name : String) -> void: 93 | for idx in range(0, m_tables.size()): 94 | if(m_tables[idx].get_table_id() == table_id): 95 | m_tables[idx].set_table_name(table_name) 96 | break 97 | 98 | # deletes a table from the list 99 | func delete_table(table_id : int) -> void: 100 | for idx in range(0, m_tables.size()): 101 | if(m_tables[idx].get_table_id() == table_id): 102 | $tables_container/tables.remove_child(m_tables[idx]) 103 | m_tables.remove(idx) 104 | break 105 | 106 | # called when the user presses an item 107 | func on_select_item(table_id : int) -> void: 108 | # print("GDDBTablesList::on_select_item(" + str(table_id) + ")") 109 | select_item_by_id(table_id) 110 | emit_signal("select_table", table_id) 111 | 112 | # select an item by index 113 | func select_item_at(table_idx : int) -> void: 114 | for idx in range(0, m_tables.size()): 115 | m_tables[idx].set_selected(idx == table_idx) 116 | 117 | # select an item by id 118 | func select_item_by_id(table_id : int) -> void: 119 | # print("GDDBTablesList::select_item_by_id(" + str(table_id) + ")") 120 | for idx in range(0, m_tables.size()): 121 | m_tables[idx].set_selected(m_tables[idx].get_table_id() == table_id) 122 | 123 | # returns the selected element 124 | func get_selected_item(): 125 | for idx in range(0, m_tables.size()): 126 | if(m_tables[idx].is_selected()): 127 | return m_tables[idx] 128 | print("ERROR: GDDBTablesList::get_selected_item() - there is no selected element") 129 | return null 130 | -------------------------------------------------------------------------------- /addons/godot_db_manager/tables_list.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://addons/godot_db_manager/tables_list.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/tables_header.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://addons/godot_db_manager/debug/dbg.tscn" type="PackedScene" id=3] 6 | [ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=4] 7 | 8 | [node name="tables_list" type="Control"] 9 | anchor_right = 0.2 10 | anchor_bottom = 1.0 11 | margin_right = -9.99991 12 | rect_min_size = Vector2( 180, 225 ) 13 | script = ExtResource( 1 ) 14 | __meta__ = { 15 | "_edit_horizontal_guides_": [ 29.9686, 584.0 ], 16 | "_edit_use_anchors_": false, 17 | "_edit_vertical_guides_": [ 180.0 ] 18 | } 19 | 20 | [node name="tables_header" parent="." instance=ExtResource( 2 )] 21 | anchor_right = 1.0 22 | anchor_bottom = 0.0 23 | margin_right = -9.15527e-05 24 | margin_bottom = 30.0 25 | rect_min_size = Vector2( 180, 30 ) 26 | 27 | [node name="tables_container" type="ScrollContainer" parent="."] 28 | anchor_right = 1.0 29 | anchor_bottom = 1.0 30 | margin_top = 32.0 31 | rect_min_size = Vector2( 180, 0 ) 32 | __meta__ = { 33 | "_edit_use_anchors_": false 34 | } 35 | 36 | [node name="tables" type="VBoxContainer" parent="tables_container"] 37 | rect_clip_content = true 38 | __meta__ = { 39 | "_edit_use_anchors_": false 40 | } 41 | 42 | [node name="resize_ctrl" type="NinePatchRect" parent="."] 43 | anchor_left = 1.0 44 | anchor_right = 1.0 45 | anchor_bottom = 1.0 46 | margin_left = -3.0 47 | mouse_filter = 0 48 | mouse_default_cursor_shape = 15 49 | texture = ExtResource( 4 ) 50 | region_rect = Rect2( 80, 12, 24, 24 ) 51 | patch_margin_left = 1 52 | patch_margin_top = 1 53 | patch_margin_right = 1 54 | patch_margin_bottom = 1 55 | __meta__ = { 56 | "_edit_use_anchors_": false 57 | } 58 | 59 | [node name="dbg" parent="." instance=ExtResource( 3 )] 60 | visible = false 61 | -------------------------------------------------------------------------------- /assets/debug.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/assets/debug.xcf -------------------------------------------------------------------------------- /assets/gui.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/assets/gui.xcf -------------------------------------------------------------------------------- /assets/main_layout.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/assets/main_layout.xcf -------------------------------------------------------------------------------- /default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="ProceduralSky" id=1] 4 | 5 | [resource] 6 | background_mode = 2 7 | background_sky = SubResource( 1 ) 8 | -------------------------------------------------------------------------------- /docs/GDDB.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/docs/GDDB.odt -------------------------------------------------------------------------------- /docs/GDDB.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/docs/GDDB.pdf -------------------------------------------------------------------------------- /docs/how_to/01_database_manager.txt: -------------------------------------------------------------------------------- 1 | Database manager How To: 2 | ================================ 3 | 4 | - Declare a variable for database manager usage 5 | var m_db_man = null 6 | 7 | 8 | - Initialize the database manager 9 | func init_db_manager() -> void : 10 | if(null != m_db_man): 11 | print("Error: database manager is already initializated") 12 | return 13 | 14 | m_db_man = load(gddb_constants.c_addon_main_path + "core/db_man.gd").new() 15 | 16 | 17 | - Clear and destroy the database manager 18 | func done_db_manager() -> void : 19 | if(null == m_db_man): 20 | print("Error: database manager is not initializated") 21 | return 22 | 23 | m_db_man.clear() 24 | m_db_man.free() 25 | m_db_man = null 26 | 27 | 28 | - Adding a database in the manager 29 | func add_database(db_name: String) -> int : 30 | if(null == m_db_man): 31 | print("Error: database manager is not initializated") 32 | return -1 33 | 34 | # returns the database id 35 | return m_db_man.add_database(db_name) 36 | 37 | 38 | - Loading a database from a JSON file - v1 39 | func load_database_1(filepath : String) -> int: 40 | if(null == m_db_man): 41 | print("Error: database manager is not initializated") 42 | return -1 43 | 44 | # returns the loaded database's id 45 | return m_db_man.load_database(filepath) 46 | 47 | 48 | - Loading a database from a JSON file - v2 49 | func load_database_2(filepath : String) -> Object: 50 | if(null == m_db_man): 51 | print("Error: database manager is not initializated") 52 | return null 53 | 54 | # create the database 55 | var db_id = m_db_man.add_database("my_new_database") 56 | 57 | # get the database 58 | var db = m_db_man.get_db_by_id(db_id) 59 | 60 | # set the database filepath 61 | db.set_db_filepath(filepath) 62 | 63 | # load the database 64 | # OBS: after loading the database, its name will be overwritten from the file 65 | db.load_db() 66 | 67 | # returns the loaded database 68 | return db 69 | 70 | 71 | - Looping through databases in the manager example - printing info on the debug console 72 | func test_looping_databases() -> void : 73 | if(null == m_db_man): 74 | print("Error: database manager is not initializated") 75 | return 76 | 77 | for idx in range(0, m_db_man.get_databases_count()): 78 | # getting the database 79 | var db = m_db_man.get_db_at(idx) 80 | 81 | # printing database info 82 | print("Database id: " + str(db.get_db_id())) 83 | print("Database name: " + db.get_db_name()) 84 | print("Database filepath: " + db.get_db_filepath()) 85 | 86 | 87 | - Getting a database at an index 88 | func test_get_database_1(db_idx : int) -> Object : 89 | return m_db_man.get_db_at(db_id) 90 | 91 | 92 | - Getting a database by an id 93 | func test_get_database_2(db_id : int) -> Object : 94 | return m_db_man.get_db_by_id(db_id) 95 | 96 | 97 | - Getting a database by a name 98 | func test_get_database_3(db_name : String) -> Object : 99 | return m_db_man.get_db_by_name(db_name) 100 | 101 | 102 | - Dump the database manager 103 | func dump_db_manager() -> void : 104 | if(null == m_db_man): 105 | print("Error: database manager is not initializated") 106 | return 107 | 108 | # the argument will tell the manager to dump the text in the console(true) or not(false) 109 | var dump_text = m_db_man.dump(true) 110 | 111 | # saving the dump text to a file 112 | var f = File.new() 113 | f.open("res://db_man_dump.txt", File.WRITE) 114 | f.store_string(dump_text) 115 | f.close() 116 | -------------------------------------------------------------------------------- /docs/how_to/02_database.txt: -------------------------------------------------------------------------------- 1 | Database How To: 2 | ================================ 3 | 4 | - Declare a variable for database usage 5 | var m_database = null 6 | 7 | 8 | - Create the database (without using the database manager) 9 | func create_db(db_name : String, db_filepath : String) -> void: 10 | if(null != m_database): 11 | print("Error: database is already created") 12 | return 13 | 14 | # creating the database 15 | m_database = load(gddb_constants.c_addon_main_path + "core/database.gd").new() 16 | 17 | # setting the database name 18 | m_database.set_db_name(db_name) 19 | 20 | # setting the database file path 21 | m_database.set_db_filepath(db_filepath) 22 | 23 | 24 | - Destroy a database (without using the database manager) 25 | func destroy_database() -> void : 26 | if(null == m_database): 27 | print("Error: database doesn not exists") 28 | return 29 | 30 | m_database.clear() 31 | m_database.free() 32 | m_database = null 33 | 34 | 35 | - Creating a table in the database 36 | func create_table(table_name : String) -> Object : 37 | if(null == m_database): 38 | print("Error: database doesn not exists") 39 | return 40 | 41 | # creating the table in the database; the name must be 42 | var table_id = m_database.add_table(table_name) 43 | if(table_id == gddb_constants.c_invalid_id) 44 | return null 45 | 46 | # getting the table from the database 47 | var table = m_database.get_table_by_id() 48 | return table 49 | 50 | 51 | - Erasing a table from the database 52 | func erase_table(table_name : String) -> void: 53 | if(null == m_database): 54 | print("Error: database doesn not exists") 55 | return 56 | 57 | m_database.delete_table_by_name(table_name) 58 | 59 | 60 | - Adding properties and data to a table 61 | func fill_table(table : Object) -> void : 62 | # add properties 63 | table.add_prop(gddb_types.e_prop_type_int, "ID") 64 | table.add_prop(gddb_types.e_prop_type_string, "Name") 65 | 66 | # add 50 rows of data 67 | for idx in range(0, 50): 68 | var data_row = [] 69 | data_row.push_back(idx + 1) 70 | data_row.push_back("Test_" + str(idx + 1)) 71 | table.add_row(data_row) 72 | -------------------------------------------------------------------------------- /examples/db_man_test_1.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://tests/test_db_manager.gd" type="Script" id=1] 4 | 5 | [node name="db_man_test" type="Control"] 6 | anchor_right = 1.0 7 | anchor_bottom = 1.0 8 | margin_left = -1.0 9 | margin_right = -1.0 10 | script = ExtResource( 1 ) 11 | __meta__ = { 12 | "_edit_use_anchors_": false 13 | } 14 | -------------------------------------------------------------------------------- /examples/db_test.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | var m_db_manager = null 4 | var m_database = null 5 | 6 | var m_player_name = "" 7 | var m_player_name_prop_id = -1 8 | 9 | # Called when the node enters the scene tree for the first time. 10 | func _ready() -> void: 11 | # init database manager 12 | m_db_manager = load(gddb_constants.c_addon_main_path + "core/db_man.gd").new() 13 | var db_id = m_db_manager.load_database("res://examples/game_data.json") 14 | 15 | if(db_id == gddb_types.e_db_invalid_file): 16 | return 17 | 18 | if(db_id == gddb_types.e_db_invalid_ver): 19 | return 20 | 21 | # load the database 22 | m_database = m_db_manager.get_db_by_id(db_id) 23 | 24 | # get the tables 25 | var res_table = m_database.get_table_by_name("resources") 26 | var users_table = m_database.get_table_by_name("users") 27 | 28 | # get user data 29 | var user_data = users_table.get_data_at_row_idx(0) 30 | m_player_name = "" 31 | m_player_name_prop_id = -1 32 | for idx in range(0, users_table.get_props_count()): 33 | # set player name 34 | if(users_table.get_prop_at(idx).get_prop_name() == "name"): 35 | m_player_name_prop_id = users_table.get_prop_at(idx).get_prop_id() 36 | m_player_name = user_data[idx].get_data() 37 | 38 | # set energy 39 | elif(users_table.get_prop_at(idx).get_prop_name() == "energy"): 40 | var energy_idx = user_data[idx].get_data().to_int() 41 | var res_row = res_table.get_data_at_row_idx(energy_idx) 42 | for jdx in range(0, res_row.size()): 43 | if(res_table.get_prop_at(jdx).get_prop_name() == "name"): 44 | $energy.set_res_name(res_row[jdx].get_data()) 45 | elif(res_table.get_prop_at(jdx).get_prop_name() == "img_path"): 46 | $energy.set_tex(res_row[jdx].get_data()) 47 | elif(users_table.get_prop_at(idx).get_prop_name() == "energy_amount"): 48 | $energy.set_amount(user_data[idx].get_data().to_int()) 49 | 50 | # set food 51 | elif(users_table.get_prop_at(idx).get_prop_name() == "food"): 52 | var food_idx = user_data[idx].get_data().to_int() 53 | var res_row = res_table.get_data_at_row_idx(food_idx) 54 | for jdx in range(0, res_row.size()): 55 | if(res_table.get_prop_at(jdx).get_prop_name() == "name"): 56 | $food.set_res_name(res_row[jdx].get_data()) 57 | elif(res_table.get_prop_at(jdx).get_prop_name() == "img_path"): 58 | $food.set_tex(res_row[jdx].get_data()) 59 | elif(users_table.get_prop_at(idx).get_prop_name() == "food_amount"): 60 | $food.set_amount(user_data[idx].get_data().to_int()) 61 | 62 | # set wood 63 | elif(users_table.get_prop_at(idx).get_prop_name() == "wood"): 64 | var wood_idx = user_data[idx].get_data().to_int() 65 | var res_row = res_table.get_data_at_row_idx(wood_idx) 66 | for jdx in range(0, res_row.size()): 67 | if(res_table.get_prop_at(jdx).get_prop_name() == "name"): 68 | $wood.set_res_name(res_row[jdx].get_data()) 69 | elif(res_table.get_prop_at(jdx).get_prop_name() == "img_path"): 70 | $wood.set_tex(res_row[jdx].get_data()) 71 | elif(users_table.get_prop_at(idx).get_prop_name() == "wood_amount"): 72 | $wood.set_amount(user_data[idx].get_data().to_int()) 73 | 74 | # set stone 75 | elif(users_table.get_prop_at(idx).get_prop_name() == "stone"): 76 | var stone_idx = user_data[idx].get_data().to_int() 77 | var res_row = res_table.get_data_at_row_idx(stone_idx) 78 | for jdx in range(0, res_row.size()): 79 | if(res_table.get_prop_at(jdx).get_prop_name() == "name"): 80 | $stone.set_res_name(res_row[jdx].get_data()) 81 | if(res_table.get_prop_at(jdx).get_prop_name() == "img_path"): 82 | $stone.set_tex(res_row[jdx].get_data()) 83 | elif(users_table.get_prop_at(idx).get_prop_name() == "stone_amount"): 84 | $stone.set_amount(user_data[idx].get_data().to_int()) 85 | 86 | # init interface with user data 87 | $player_name_btn.set_text(m_player_name) 88 | $player_name_btn.connect("pressed", self, "on_player_name_btn_pressed") 89 | 90 | # init interface dialogs 91 | $edit_player_dlg/OK_btn.connect("pressed", self, "on_change_player_name_btn_pressed") 92 | $error_dlg.add_cancel("Cancel") 93 | $error_dlg.connect("confirmed", self, "on_player_name_btn_pressed") 94 | 95 | # called when player_name_btn is pressed 96 | func on_player_name_btn_pressed() -> void: 97 | $edit_player_dlg/player_name.set_text(m_player_name) 98 | $edit_player_dlg.popup_centered() 99 | 100 | # called when the "OK" button from the edit_player_dlg is pressed 101 | func on_change_player_name_btn_pressed() -> void: 102 | $edit_player_dlg.hide() 103 | 104 | # check if the name entered is empty 105 | var player_name = $edit_player_dlg/player_name.get_text() 106 | if(player_name.empty()): 107 | $error_dlg.popup_centered() 108 | $error_dlg.set_text("Player name is empty. Retry ?") 109 | return 110 | 111 | m_player_name = player_name 112 | 113 | # set the new name in the database 114 | var users_table = m_database.get_table_by_name("users") 115 | users_table.edit_data(m_player_name_prop_id, 0, m_player_name) 116 | 117 | # saving the database 118 | m_database.save_db() 119 | 120 | # set new name in the interface 121 | $player_name_btn.set_text(m_player_name) 122 | -------------------------------------------------------------------------------- /examples/db_test.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://examples/db_test.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_16.tres" type="DynamicFont" id=2] 5 | [ext_resource path="res://examples/resource.tscn" type="PackedScene" id=3] 6 | 7 | [node name="db_test" type="Control"] 8 | anchor_right = 1.0 9 | anchor_bottom = 1.0 10 | script = ExtResource( 1 ) 11 | __meta__ = { 12 | "_edit_use_anchors_": false 13 | } 14 | 15 | [node name="Label" type="Label" parent="."] 16 | anchor_left = 0.006 17 | anchor_top = 0.011 18 | anchor_right = 0.044125 19 | anchor_bottom = 0.032 20 | margin_left = 0.4 21 | margin_top = 0.0999994 22 | margin_right = -0.600006 23 | margin_bottom = 0.199999 24 | custom_fonts/font = ExtResource( 2 ) 25 | text = "Name:" 26 | __meta__ = { 27 | "_edit_use_anchors_": true 28 | } 29 | 30 | [node name="player_name_btn" type="Button" parent="."] 31 | anchor_left = 0.0644531 32 | anchor_top = 0.00807292 33 | anchor_right = 0.153906 34 | anchor_bottom = 0.0408854 35 | margin_top = -0.2 36 | margin_right = 0.399994 37 | margin_bottom = -0.400002 38 | custom_fonts/font = ExtResource( 2 ) 39 | __meta__ = { 40 | "_edit_use_anchors_": true 41 | } 42 | 43 | [node name="edit_player_dlg" type="WindowDialog" parent="."] 44 | anchor_right = 0.142 45 | anchor_bottom = 0.076 46 | margin_right = 0.799988 47 | margin_bottom = -0.400002 48 | __meta__ = { 49 | "_edit_use_anchors_": false 50 | } 51 | 52 | [node name="Label" type="Label" parent="edit_player_dlg"] 53 | anchor_left = 0.044 54 | anchor_top = 0.091 55 | anchor_right = 0.246 56 | anchor_bottom = 0.264 57 | margin_left = -0.0320005 58 | margin_top = -0.0100002 59 | margin_right = -0.0880013 60 | margin_bottom = -0.039999 61 | custom_fonts/font = ExtResource( 2 ) 62 | text = "Name:" 63 | __meta__ = { 64 | "_edit_use_anchors_": false 65 | } 66 | 67 | [node name="player_name" type="LineEdit" parent="edit_player_dlg"] 68 | anchor_left = 0.280702 69 | anchor_top = 0.0454545 70 | anchor_right = 0.965 71 | anchor_bottom = 0.472 72 | margin_right = -0.0200195 73 | margin_bottom = -11.074 74 | custom_fonts/font = ExtResource( 2 ) 75 | __meta__ = { 76 | "_edit_use_anchors_": true 77 | } 78 | 79 | [node name="OK_btn" type="Button" parent="edit_player_dlg"] 80 | anchor_left = 0.425 81 | anchor_top = 0.550807 82 | anchor_right = 0.575 83 | anchor_bottom = 0.918 84 | margin_left = 0.0999985 85 | margin_top = -0.0300026 86 | margin_right = -0.100006 87 | margin_bottom = 0.000911713 88 | custom_fonts/font = ExtResource( 2 ) 89 | text = "OK" 90 | __meta__ = { 91 | "_edit_use_anchors_": true 92 | } 93 | 94 | [node name="error_dlg" type="AcceptDialog" parent="."] 95 | anchor_right = 0.052 96 | anchor_bottom = 0.064 97 | margin_right = -0.200005 98 | margin_bottom = 0.399998 99 | 100 | [node name="energy" parent="." instance=ExtResource( 3 )] 101 | anchor_left = 0.014 102 | anchor_top = 0.0582222 103 | anchor_right = 0.134 104 | anchor_bottom = 0.102 105 | margin_left = -0.400009 106 | margin_top = -0.400009 107 | margin_right = -42.4 108 | margin_bottom = 0.199997 109 | 110 | [node name="food" parent="." instance=ExtResource( 3 )] 111 | anchor_left = 0.014 112 | anchor_top = 0.112667 113 | anchor_right = 0.134 114 | anchor_bottom = 0.157 115 | margin_left = -0.400009 116 | margin_top = -0.400009 117 | margin_right = -42.4 118 | margin_bottom = -0.300003 119 | 120 | [node name="wood" parent="." instance=ExtResource( 3 )] 121 | anchor_left = 0.014 122 | anchor_top = 0.167111 123 | anchor_right = 0.134 124 | anchor_bottom = 0.211 125 | margin_left = -0.400009 126 | margin_top = -0.400009 127 | margin_right = -42.4 128 | margin_bottom = 0.0999908 129 | 130 | [node name="stone" parent="." instance=ExtResource( 3 )] 131 | anchor_left = 0.014 132 | anchor_top = 0.222667 133 | anchor_right = 0.134 134 | anchor_bottom = 0.267 135 | margin_left = -0.400009 136 | margin_top = -0.400009 137 | margin_right = -42.4 138 | margin_bottom = -0.299988 139 | -------------------------------------------------------------------------------- /examples/db_test_1.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://examples/test_database_1.gd" type="Script" id=1] 4 | 5 | [node name="db_test" type="Control"] 6 | anchor_right = 1.0 7 | anchor_bottom = 1.0 8 | script = ExtResource( 1 ) 9 | __meta__ = { 10 | "_edit_use_anchors_": false 11 | } 12 | -------------------------------------------------------------------------------- /examples/db_test_2.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://examples/test_database_2.gd" type="Script" id=1] 4 | 5 | [node name="db_test" type="Control"] 6 | anchor_right = 1.0 7 | anchor_bottom = 1.0 8 | script = ExtResource( 1 ) 9 | __meta__ = { 10 | "_edit_use_anchors_": false 11 | } 12 | -------------------------------------------------------------------------------- /examples/example_1.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene format=2] 2 | 3 | [node name="example_1" type="Control"] 4 | anchor_right = 1.0 5 | anchor_bottom = 1.0 6 | __meta__ = { 7 | "_edit_use_anchors_": false 8 | } 9 | -------------------------------------------------------------------------------- /examples/game_data.json: -------------------------------------------------------------------------------- 1 | {"GDDB_ver":"2.0","db_name":"game_data","tables":[{"table_name":"resources","props":[{"name":"id","type":"1","auto_increment":"1"},{"name":"name","type":"3","auto_increment":"0"},{"name":"img_path","type":"4","auto_increment":"0"}],"data":["1","Energy","res://examples/resources/energy.png","2","Food","res://examples/resources/food.png","3","Wood","res://examples/resources/wood.png","4","Stone","res://examples/resources/stone.png"]},{"table_name":"users","props":[{"name":"id","type":"1","auto_increment":"1"},{"name":"name","type":"3","auto_increment":"0"},{"name":"energy","type":"table","table_name":"resources","auto_increment":"0"},{"name":"energy_amount","type":"1","auto_increment":"0"},{"name":"food","type":"table","table_name":"resources","auto_increment":"0"},{"name":"food_amount","type":"1","auto_increment":"0"},{"name":"wood","type":"table","table_name":"resources","auto_increment":"0"},{"name":"wood_amount","type":"1","auto_increment":"0"},{"name":"stone","type":"table","table_name":"resources","auto_increment":"0"},{"name":"stone_amount","type":"1","auto_increment":"0"}],"data":["1","PlayerName","0","100","1","10000","2","10000","3","10000"]}]} -------------------------------------------------------------------------------- /examples/resource.gd: -------------------------------------------------------------------------------- 1 | extends HBoxContainer 2 | 3 | # Called when the node enters the scene tree for the first time. 4 | func _ready(): 5 | pass # Replace with function body. 6 | 7 | func set_tex(tex_path : String) -> void: 8 | $tex_holder/tex.texture = load(tex_path).duplicate() 9 | 10 | func set_res_name(res_name : String) -> void: 11 | $name.set_text(res_name) 12 | 13 | func set_amount(amount : int) -> void: 14 | $amount.set_text(str(amount)) 15 | -------------------------------------------------------------------------------- /examples/resource.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://examples/resources/energy.png" type="Texture" id=1] 4 | [ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_20.tres" type="DynamicFont" id=2] 5 | [ext_resource path="res://examples/resource.gd" type="Script" id=3] 6 | 7 | 8 | [node name="resource" type="HBoxContainer"] 9 | anchor_right = 0.167 10 | anchor_bottom = 0.044 11 | margin_right = -229.2 12 | margin_bottom = -25.6 13 | script = ExtResource( 3 ) 14 | __meta__ = { 15 | "_edit_use_anchors_": true 16 | } 17 | 18 | [node name="tex_holder" type="Control" parent="."] 19 | margin_right = 60.0 20 | margin_bottom = 40.0 21 | rect_min_size = Vector2( 60, 40 ) 22 | 23 | [node name="tex" type="Sprite" parent="tex_holder"] 24 | texture = ExtResource( 1 ) 25 | centered = false 26 | 27 | [node name="name" type="Label" parent="."] 28 | margin_left = 64.0 29 | margin_top = 8.0 30 | margin_right = 164.0 31 | margin_bottom = 32.0 32 | rect_min_size = Vector2( 100, 0 ) 33 | custom_fonts/font = ExtResource( 2 ) 34 | text = "Name" 35 | 36 | [node name="amount" type="LineEdit" parent="."] 37 | margin_left = 168.0 38 | margin_right = 268.0 39 | margin_bottom = 40.0 40 | rect_min_size = Vector2( 100, 0 ) 41 | custom_fonts/font = ExtResource( 2 ) 42 | text = "10000" 43 | editable = false 44 | -------------------------------------------------------------------------------- /examples/resources/energy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/examples/resources/energy.png -------------------------------------------------------------------------------- /examples/resources/food.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/examples/resources/food.png -------------------------------------------------------------------------------- /examples/resources/gui_01.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/examples/resources/gui_01.xcf -------------------------------------------------------------------------------- /examples/resources/stone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/examples/resources/stone.png -------------------------------------------------------------------------------- /examples/resources/wood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/examples/resources/wood.png -------------------------------------------------------------------------------- /examples/test_database_1.gd: -------------------------------------------------------------------------------- 1 | """ 2 | test_database_1.gd 3 | Testing Godot Database helper script 4 | """ 5 | 6 | extends Node 7 | 8 | const c_base_dbs_path = "res://examples/" 9 | const c_database_name = "test_database" 10 | 11 | var m_db_man = null 12 | 13 | func _ready(): 14 | randomize() 15 | 16 | test_1() 17 | 18 | 19 | # test 1: 20 | # 1) init DB manager 21 | # 2) create a database 22 | # 3) create a table 23 | # 4) create 2 properties: id(integer; autoincrement) and name(string) 24 | # 5) add 100 data rows (random strings) 25 | # 6) dump db_man 26 | # 7) save database 27 | # 8) clear db_man 28 | # 9) load database 29 | # 10) dump db_man 30 | # 11) done db_man 31 | func test_1() -> void : 32 | OS.set_window_size(Vector2(640, 480)) 33 | 34 | # init db_manager 35 | init_db_man() 36 | 37 | # create a database 38 | var db = create_database(c_database_name) 39 | 40 | # create a table 41 | var table_id = db.add_table("table") 42 | var table = db.get_table_by_id(table_id) 43 | 44 | # create "id" property with autoincrement option 45 | var prop_id = table.add_prop(gddb_types.e_prop_type_int, "id") 46 | var prop = table.get_prop_by_id(prop_id) 47 | prop.enable_autoincrement(true) 48 | 49 | # create "name" property 50 | prop_id = table.add_prop(gddb_types.e_prop_type_string, "name") 51 | 52 | # create 100 data rows of data 53 | for idx in range(0, 100): 54 | var data = [] 55 | data.push_back(idx) # TODO: this is redundant if the property has autoincrement option 56 | data.push_back("data_%03d" % (idx + 1)) 57 | table.add_row(data) 58 | 59 | # dump db_man 60 | m_db_man.dump(true) 61 | 62 | # save the database 63 | db.save_db() 64 | 65 | # clear db_man 66 | m_db_man.clear() 67 | 68 | # load the database previously created 69 | m_db_man.load_database(c_base_dbs_path + c_database_name + ".json") 70 | 71 | # dump db_man 72 | m_db_man.dump(true) 73 | 74 | # done db_man 75 | done_db_man() 76 | 77 | 78 | ### helper functions 79 | 80 | # init database manager 81 | func init_db_man() -> void : 82 | m_db_man = load(gddb_constants.c_addon_main_path + "core/db_man.gd").new() 83 | 84 | # destroys database manager 85 | func done_db_man() -> void : 86 | m_db_man.clear() 87 | m_db_man.free() 88 | m_db_man = null 89 | 90 | # creates a database 91 | func create_database(db_name : String) -> Object: 92 | var db_id = m_db_man.add_database(db_name) 93 | var db = m_db_man.get_db_by_id(db_id) 94 | db.set_db_filepath(c_base_dbs_path + db_name + ".json") 95 | return db 96 | -------------------------------------------------------------------------------- /examples/test_database_2.gd: -------------------------------------------------------------------------------- 1 | """ 2 | test_database.gd 3 | Testing Godot Database helper script 4 | """ 5 | 6 | extends Node 7 | 8 | const c_base_dbs_path = "res://examples/" 9 | const c_database_name = "test_database" 10 | 11 | var m_db_man = null 12 | 13 | func _ready(): 14 | randomize() 15 | 16 | test_2() 17 | 18 | 19 | # test 2: 20 | # 1) init DB manager 21 | # 2) create a database 22 | # 3) create 10 tables 23 | # 4) dump db_man 24 | # 5) save database 25 | # 8) clear db_man 26 | # 9) load database 27 | # 10) randomly erase 3 tables 28 | # 11) dump db_man 29 | # 12) done db_man 30 | func test_2() -> void: 31 | OS.set_window_size(Vector2(640, 480)) 32 | 33 | # init db_manager 34 | init_db_man() 35 | 36 | # create a database 37 | var db = create_database(c_database_name) 38 | 39 | # create 10 tables 40 | for idx in range(0, 10): 41 | var table_id = db.add_table("table_" + str(idx + 1)) 42 | 43 | # dump db_man 44 | m_db_man.dump(true) 45 | 46 | # save the database 47 | db.save_db() 48 | 49 | # clear db_man 50 | m_db_man.clear() 51 | 52 | # load the database previously created 53 | var db_id = m_db_man.load_database(c_base_dbs_path + c_database_name + ".json") 54 | db = m_db_man.get_db_by_id(db_id) 55 | 56 | # randomly erase 3 tables 57 | for idx in range(0, 3): 58 | var table_idx = randi() % db.get_tables_count() 59 | var table = db.get_table_at(table_idx) 60 | print("Erasing table with id: " + str(table.get_table_id())) 61 | db.delete_table_at(table_idx) 62 | 63 | # dump db_man 64 | m_db_man.dump(true) 65 | 66 | # done db_man 67 | done_db_man() 68 | 69 | 70 | ### helper functions 71 | 72 | # init database manager 73 | func init_db_man() -> void : 74 | m_db_man = load(gddb_constants.c_addon_main_path + "core/db_man.gd").new() 75 | 76 | # destroys database manager 77 | func done_db_man() -> void : 78 | m_db_man.clear() 79 | m_db_man.free() 80 | m_db_man = null 81 | 82 | # creates a database 83 | func create_database(db_name : String) -> Object: 84 | var db_id = m_db_man.add_database(db_name) 85 | var db = m_db_man.get_db_by_id(db_id) 86 | db.set_db_filepath(c_base_dbs_path + db_name + ".json") 87 | return db 88 | -------------------------------------------------------------------------------- /examples/test_db_manager.gd: -------------------------------------------------------------------------------- 1 | """ 2 | test_db_manager.gd 3 | Testing Godot Database Manager helper script 4 | """ 5 | 6 | extends Node 7 | 8 | const c_base_dbs_path = "res://tests/" 9 | 10 | var m_db_man = null 11 | 12 | func _ready(): 13 | randomize() 14 | 15 | test_1() 16 | 17 | 18 | #### tests 19 | 20 | # test 1 => create / save / load / erase databases test 21 | func test_1() -> void : 22 | OS.set_window_size(Vector2(640, 480)) 23 | 24 | # init db_manager 25 | init_db_man() 26 | 27 | # create 10 databases 28 | for idx in range(0, 10): 29 | var db_name = "db_%02d" % idx 30 | create_database(db_name) 31 | 32 | # dump database manager 33 | m_db_man.dump(true) 34 | 35 | # save all databases 36 | for idx in range(0, m_db_man.get_databases_count()): 37 | var db = m_db_man.get_db_at(idx) 38 | db.save_db() 39 | 40 | # clear db_man 41 | m_db_man.clear() 42 | 43 | # loaded all databases previously created 44 | for idx in range(0, 10): 45 | var db_name = "db_%02d" % idx 46 | m_db_man.load_database(c_base_dbs_path + db_name + ".json") 47 | 48 | # dump database manager 49 | m_db_man.dump(true) 50 | 51 | # randomly erase 3 databases 52 | for idx in range(0, 3): 53 | var db_idx = randi() % m_db_man.get_databases_count() 54 | var db = m_db_man.get_db_at(db_idx) 55 | print("Erasing database with id: " + str(db.get_db_id())) 56 | m_db_man.erase_db_at(db_idx) 57 | 58 | # dump database manager 59 | m_db_man.dump(true) 60 | 61 | # done db_man 62 | done_db_man() 63 | 64 | 65 | ### helper functions 66 | 67 | # init database manager 68 | func init_db_man() -> void : 69 | m_db_man = load(gddb_constants.c_addon_main_path + "core/db_man.gd").new() 70 | 71 | # destroys database manager 72 | func done_db_man() -> void : 73 | m_db_man.clear() 74 | m_db_man.free() 75 | m_db_man = null 76 | 77 | # creates a database 78 | func create_database(db_name : String) -> void: 79 | var db_id = m_db_man.add_database(db_name) 80 | var db = m_db_man.get_db_by_id(db_id) 81 | db.set_db_filepath(c_base_dbs_path + db_name + ".json") 82 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radubolovan/Godot-Database-Manager/c56887e97548482afd75172cc91395178c9a88d3/icon.png -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=4 10 | 11 | _global_script_classes=[ { 12 | "base": "Node", 13 | "class": "GDDBConstants", 14 | "language": "GDScript", 15 | "path": "res://addons/godot_db_manager/core/GDDBConstants.gd" 16 | }, { 17 | "base": "Object", 18 | "class": "GDDBData", 19 | "language": "GDScript", 20 | "path": "res://addons/godot_db_manager/core/db_data.gd" 21 | }, { 22 | "base": "Label", 23 | "class": "GDDBDataLabel", 24 | "language": "GDScript", 25 | "path": "res://addons/godot_db_manager/data_label.gd" 26 | }, { 27 | "base": "PopupPanel", 28 | "class": "GDDBDataPanel", 29 | "language": "GDScript", 30 | "path": "res://addons/godot_db_manager/dlgs/data_dlg.gd" 31 | }, { 32 | "base": "WindowDialog", 33 | "class": "GDDBDeletePropDlg", 34 | "language": "GDScript", 35 | "path": "res://addons/godot_db_manager/dlgs/delete_prop_dlg.gd" 36 | }, { 37 | "base": "WindowDialog", 38 | "class": "GDDBDeleteTableDlg", 39 | "language": "GDScript", 40 | "path": "res://addons/godot_db_manager/dlgs/delete_table_dlg.gd" 41 | }, { 42 | "base": "WindowDialog", 43 | "class": "GDDBEditStringDlg", 44 | "language": "GDScript", 45 | "path": "res://addons/godot_db_manager/dlgs/edit_string_dlg.gd" 46 | }, { 47 | "base": "Tabs", 48 | "class": "GDDBEditor", 49 | "language": "GDScript", 50 | "path": "res://addons/godot_db_manager/db_editor.gd" 51 | }, { 52 | "base": "Node", 53 | "class": "GDDBGlobals", 54 | "language": "GDScript", 55 | "path": "res://addons/godot_db_manager/core/GDDBGlobals.gd" 56 | }, { 57 | "base": "Control", 58 | "class": "GDDBInterface", 59 | "language": "GDScript", 60 | "path": "res://addons/godot_db_manager/db_interface.gd" 61 | }, { 62 | "base": "FileDialog", 63 | "class": "GDDBLoadResourcePathDlg", 64 | "language": "GDScript", 65 | "path": "res://addons/godot_db_manager/dlgs/load_res_path_dlg.gd" 66 | }, { 67 | "base": "Object", 68 | "class": "GDDBMan", 69 | "language": "GDScript", 70 | "path": "res://addons/godot_db_manager/core/db_man.gd" 71 | }, { 72 | "base": "EditorPlugin", 73 | "class": "GDDBManager", 74 | "language": "GDScript", 75 | "path": "res://addons/godot_db_manager/db_manager.gd" 76 | }, { 77 | "base": "Control", 78 | "class": "GDDBMenu", 79 | "language": "GDScript", 80 | "path": "res://addons/godot_db_manager/menu.gd" 81 | }, { 82 | "base": "WindowDialog", 83 | "class": "GDDBNewDBDlg", 84 | "language": "GDScript", 85 | "path": "res://addons/godot_db_manager/dlgs/new_db_dlg.gd" 86 | }, { 87 | "base": "WindowDialog", 88 | "class": "GDDBNewTableDlg", 89 | "language": "GDScript", 90 | "path": "res://addons/godot_db_manager/dlgs/new_table_dlg.gd" 91 | }, { 92 | "base": "Object", 93 | "class": "GDDBProperty", 94 | "language": "GDScript", 95 | "path": "res://addons/godot_db_manager/core/db_prop.gd" 96 | }, { 97 | "base": "Object", 98 | "class": "GDDBTable", 99 | "language": "GDScript", 100 | "path": "res://addons/godot_db_manager/core/db_table.gd" 101 | }, { 102 | "base": "Control", 103 | "class": "GDDBTableCell", 104 | "language": "GDScript", 105 | "path": "res://addons/godot_db_manager/table_cell.gd" 106 | }, { 107 | "base": "Control", 108 | "class": "GDDBTableEditor", 109 | "language": "GDScript", 110 | "path": "res://addons/godot_db_manager/table_editor.gd" 111 | }, { 112 | "base": "Control", 113 | "class": "GDDBTableItem", 114 | "language": "GDScript", 115 | "path": "res://addons/godot_db_manager/table_item.gd" 116 | }, { 117 | "base": "Control", 118 | "class": "GDDBTableProperty", 119 | "language": "GDScript", 120 | "path": "res://addons/godot_db_manager/table_property.gd" 121 | }, { 122 | "base": "Control", 123 | "class": "GDDBTablesHeader", 124 | "language": "GDScript", 125 | "path": "res://addons/godot_db_manager/tables_header.gd" 126 | }, { 127 | "base": "Control", 128 | "class": "GDDBTablesList", 129 | "language": "GDScript", 130 | "path": "res://addons/godot_db_manager/tables_list.gd" 131 | }, { 132 | "base": "Node", 133 | "class": "GDDBTypes", 134 | "language": "GDScript", 135 | "path": "res://addons/godot_db_manager/core/GDDBTypes.gd" 136 | }, { 137 | "base": "Object", 138 | "class": "GDDatabase", 139 | "language": "GDScript", 140 | "path": "res://addons/godot_db_manager/core/database.gd" 141 | } ] 142 | _global_script_class_icons={ 143 | "GDDBConstants": "", 144 | "GDDBData": "", 145 | "GDDBDataLabel": "", 146 | "GDDBDataPanel": "", 147 | "GDDBDeletePropDlg": "", 148 | "GDDBDeleteTableDlg": "", 149 | "GDDBEditStringDlg": "", 150 | "GDDBEditor": "", 151 | "GDDBGlobals": "", 152 | "GDDBInterface": "", 153 | "GDDBLoadResourcePathDlg": "", 154 | "GDDBMan": "", 155 | "GDDBManager": "", 156 | "GDDBMenu": "", 157 | "GDDBNewDBDlg": "", 158 | "GDDBNewTableDlg": "", 159 | "GDDBProperty": "", 160 | "GDDBTable": "", 161 | "GDDBTableCell": "", 162 | "GDDBTableEditor": "", 163 | "GDDBTableItem": "", 164 | "GDDBTableProperty": "", 165 | "GDDBTablesHeader": "", 166 | "GDDBTablesList": "", 167 | "GDDBTypes": "", 168 | "GDDatabase": "" 169 | } 170 | 171 | [application] 172 | 173 | config/name="GodotDBMan" 174 | run/main_scene="res://examples/db_test.tscn" 175 | config/icon="res://icon.png" 176 | 177 | [autoload] 178 | 179 | gddb_constants="*res://addons/godot_db_manager/core/GDDBConstants.gd" 180 | gddb_types="*res://addons/godot_db_manager/core/GDDBTypes.gd" 181 | gddb_globals="*res://addons/godot_db_manager/core/GDDBGlobals.gd" 182 | 183 | [debug] 184 | 185 | gdscript/warnings/enable=false 186 | gdscript/warnings/unassigned_variable=false 187 | gdscript/warnings/unassigned_variable_op_assign=false 188 | gdscript/warnings/unused_variable=false 189 | gdscript/warnings/unused_argument=false 190 | 191 | [display] 192 | 193 | window/size/height=768 194 | 195 | [editor_plugins] 196 | 197 | enabled=PoolStringArray( "godot_db_manager" ) 198 | 199 | [rendering] 200 | 201 | environment/default_environment="res://default_env.tres" 202 | --------------------------------------------------------------------------------