├── icon.png ├── icon_spatial.png ├── addons └── dscn_io │ ├── DSCN_Node_Icon.png │ ├── DSCN_Resource_Manager.tscn │ ├── plugin.cfg │ ├── DSCN_IO.tscn │ ├── dscn_main.gd │ ├── DSCN_Node_Icon.png.import │ ├── DSCN_Runtime_Node.gd │ ├── DSCN_Dock.gd │ ├── DSCN Dock.tscn │ ├── DSCN_IO.gd │ └── DSCN_Resource_Manager.gd ├── .gitignore ├── Test_Export_Scenes ├── Test_Polygon2D_Script.gd └── Test_Scene.tscn ├── default_env.tres ├── Test_Import_Scenes └── Test_Scene.tscn ├── icon.png.import ├── icon_spatial.png.import ├── LICENSE ├── project.godot └── README.md /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TwistedTwigleg/DSCN_Plugin/HEAD/icon.png -------------------------------------------------------------------------------- /icon_spatial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TwistedTwigleg/DSCN_Plugin/HEAD/icon_spatial.png -------------------------------------------------------------------------------- /addons/dscn_io/DSCN_Node_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TwistedTwigleg/DSCN_Plugin/HEAD/addons/dscn_io/DSCN_Node_Icon.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot-specific ignores 2 | .import/ 3 | export.cfg 4 | export_presets.cfg 5 | 6 | # Mono-specific ignores 7 | .mono/ 8 | 9 | # System/tool-specific ignores 10 | .directory 11 | *~ 12 | -------------------------------------------------------------------------------- /addons/dscn_io/DSCN_Resource_Manager.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://addons/dscn_io/DSCN_Resource_Manager.gd" type="Script" id=1] 4 | 5 | [node name="DSCN_Resource_Manager" type="Node"] 6 | script = ExtResource( 1 ) 7 | -------------------------------------------------------------------------------- /addons/dscn_io/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="Deep Scene IO" 4 | description="A set of scripts designed to import and export DSCN files, which are just like TSCN or SCN files but they can be loaded from anywhere in the file system!" 5 | author="Noah Beard (TwistedTwigleg)" 6 | version="0.2.0" 7 | script="dscn_main.gd" -------------------------------------------------------------------------------- /Test_Export_Scenes/Test_Polygon2D_Script.gd: -------------------------------------------------------------------------------- 1 | extends Polygon2D 2 | 3 | export (float) var SPEED = 40; 4 | 5 | func _process(delta): 6 | for child in get_children(): 7 | if (child is Node2D): 8 | child.rotation_degrees += delta * SPEED; 9 | 10 | func _on_button_pressed(): 11 | get_node("Sprite").visible = !get_node("Sprite").visible; 12 | -------------------------------------------------------------------------------- /addons/dscn_io/DSCN_IO.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://addons/dscn_io/DSCN_IO.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/dscn_io/DSCN_Resource_Manager.tscn" type="PackedScene" id=2] 5 | 6 | [node name="DSCN_IO" type="Node"] 7 | script = ExtResource( 1 ) 8 | 9 | [node name="DSCN_Resource_Manager" parent="." instance=ExtResource( 2 )] 10 | -------------------------------------------------------------------------------- /default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="ProceduralSky" id=1] 4 | sky_top_color = Color( 0.0470588, 0.454902, 0.976471, 1 ) 5 | sky_horizon_color = Color( 0.556863, 0.823529, 0.909804, 1 ) 6 | sky_curve = 0.25 7 | ground_bottom_color = Color( 0.101961, 0.145098, 0.188235, 1 ) 8 | ground_horizon_color = Color( 0.482353, 0.788235, 0.952941, 1 ) 9 | ground_curve = 0.01 10 | sun_energy = 16.0 11 | 12 | [resource] 13 | background_mode = 2 14 | background_sky = SubResource( 1 ) 15 | -------------------------------------------------------------------------------- /Test_Import_Scenes/Test_Scene.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://addons/dscn_io/DSCN_Runtime_Node.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/dscn_io/DSCN_Node_Icon.png" type="Texture" id=2] 5 | 6 | [node name="Node2D" type="Node2D"] 7 | 8 | [node name="TEST" type="Node2D" parent="."] 9 | 10 | [node name="DSCN_Runtime_Node" type="Node" parent="."] 11 | script = ExtResource( 1 ) 12 | __meta__ = { 13 | "_editor_icon": ExtResource( 2 ) 14 | } 15 | path_to_node = NodePath("../TEST") 16 | filepath = "res://Runtime_Scene.DSCN" 17 | execute_in_ready = true 18 | -------------------------------------------------------------------------------- /addons/dscn_io/dscn_main.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends EditorPlugin 3 | 4 | var DSCN_Dock; 5 | 6 | func _enter_tree(): 7 | DSCN_Dock = preload("res://addons/dscn_io/DSCN Dock.tscn").instance(); 8 | 9 | # Add custom dock(s) 10 | add_control_to_dock(DOCK_SLOT_LEFT_UR, DSCN_Dock); 11 | # Setup custom dock(s) 12 | DSCN_Dock.editor_interface = get_editor_interface(); 13 | # Add custom node(s) 14 | add_custom_type("DSCN_Runtime_Node", "Node", preload("DSCN_Runtime_Node.gd"), preload("DSCN_Node_Icon.png")); 15 | 16 | 17 | func _exit_tree(): 18 | # Remove custom dock(s) 19 | remove_control_from_docks(DSCN_Dock); 20 | # Free custom dock(s) memory 21 | DSCN_Dock.free(); 22 | # Remove custom node(s) 23 | remove_custom_type("DSCN_Runtime_Node"); 24 | -------------------------------------------------------------------------------- /icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://icon.png" 13 | dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=1 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=1 23 | flags/filter=true 24 | flags/mipmaps=true 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=false 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /addons/dscn_io/DSCN_Node_Icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/DSCN_Node_Icon.png-f8d91dde8f1caeadcfb3162349439370.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://addons/dscn_io/DSCN_Node_Icon.png" 13 | dest_files=[ "res://.import/DSCN_Node_Icon.png-f8d91dde8f1caeadcfb3162349439370.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /icon_spatial.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/icon_spatial.png-2df92df4adaf7221443a57c2a50f471d.s3tc.stex" 6 | path.etc2="res://.import/icon_spatial.png-2df92df4adaf7221443a57c2a50f471d.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://icon_spatial.png" 15 | dest_files=[ "res://.import/icon_spatial.png-2df92df4adaf7221443a57c2a50f471d.s3tc.stex", "res://.import/icon_spatial.png-2df92df4adaf7221443a57c2a50f471d.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=1 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 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 | -------------------------------------------------------------------------------- /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 | _global_script_class_icons={ 13 | 14 | } 15 | 16 | [application] 17 | 18 | config/name="Godot DSCN project" 19 | run/main_scene="res://Test_Import_Scenes/Test_Scene.tscn" 20 | config/icon="res://icon.png" 21 | 22 | [editor_plugins] 23 | 24 | enabled=PoolStringArray( "dscn_io" ) 25 | 26 | [input] 27 | 28 | jump={ 29 | "deadzone": 0.5, 30 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null) 31 | ] 32 | } 33 | move_backwards={ 34 | "deadzone": 0.5, 35 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"unicode":0,"echo":false,"script":null) 36 | ] 37 | } 38 | move_forward={ 39 | "deadzone": 0.5, 40 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"unicode":0,"echo":false,"script":null) 41 | ] 42 | } 43 | move_left={ 44 | "deadzone": 0.5, 45 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"unicode":0,"echo":false,"script":null) 46 | ] 47 | } 48 | move_right={ 49 | "deadzone": 0.5, 50 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"unicode":0,"echo":false,"script":null) 51 | ] 52 | } 53 | 54 | [rendering] 55 | 56 | environment/default_environment="res://default_env.tres" 57 | -------------------------------------------------------------------------------- /addons/dscn_io/DSCN_Runtime_Node.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | # A variable to store the DSCN_IO node. 4 | var DSCN_IO = null; 5 | 6 | # The path to the node we want to use to either import/export a DSCN file. 7 | export (NodePath) var path_to_node; 8 | # The mode for this node. Right now you can either import or export DSCN files. 9 | export (int, "IMPORT", "EXPORT") var mode = 0; 10 | # The filepath of/for the DSCN file. This is a multiline export 11 | # so we can easily see the path in the editor. 12 | export (String, MULTILINE) var filepath; 13 | # A boolean for whether this node should try and import/export a DSCN file in 14 | # it's _ready function. 15 | export (bool) var execute_in_ready = false; 16 | 17 | 18 | func _ready(): 19 | 20 | # Load the DSCN node, make a instance of it, and then make it a child of this node. 21 | var DSCN_IO_INSTANCE = preload("res://addons/dscn_io/DSCN_IO.tscn"); 22 | DSCN_IO = DSCN_IO_INSTANCE.instance(); 23 | add_child(DSCN_IO); 24 | 25 | # If we need to execute in _ready, then figure out 26 | # which function we need to call and then call it. 27 | if (execute_in_ready == true): 28 | if (mode == 0): 29 | import_dscn(); 30 | elif (mode == 1): 31 | export_dscn(); 32 | 33 | 34 | func export_dscn(): 35 | 36 | # Get the selected node, and the root node the DSCN_Runtime_Node is in. 37 | var selected_node = get_node(path_to_node); 38 | var scene_root = get_tree().root.get_child(get_tree().root.get_child_count()-1); 39 | 40 | # Export the DSCN file, passing in the filepath, the selected node, and 41 | # the root of the scene the DSCN_Runtime node is in. 42 | var result = DSCN_IO.export_dscn(filepath, selected_node, scene_root); 43 | 44 | # Based on the result of the export, print to the console saying what happened. 45 | if (result == DSCN_IO.DSCN_IO_STATUS.EXPORT_SUCCESS): 46 | print ("DSCN file exported successfully to file: " + filepath); 47 | else: 48 | var reason = ""; 49 | 50 | if (result == DSCN_IO.DSCN_IO_STATUS.IMPORT_SUCCESS): 51 | reason = "Programmer is a clutz and sent import success instead of export success!"; 52 | elif (result == DSCN_IO.DSCN_IO_STATUS.NO_NODE_SELECTED): 53 | reason = "No node was selected!"; 54 | elif (result == DSCN_IO.DSCN_IO_STATUS.SELECTED_NODE_NOT_FOUND): 55 | reason = "The selected node was not found in the currently open scene!"; 56 | elif (result == DSCN_IO.DSCN_IO_STATUS.FILE_NOT_FOUND): 57 | reason = "Could not find file!"; 58 | 59 | print ("DSCN file export failed. Reason: " + reason); 60 | 61 | 62 | func import_dscn(): 63 | 64 | # Get the selected node, and the root node the DSCN_Runtime_Node is in. 65 | var selected_node = get_node(path_to_node); 66 | var scene_root = get_tree().root.get_child(get_tree().root.get_child_count()-1); 67 | 68 | # Import the DSCN file, passing in the filepath, the selected node, and 69 | # the root of the scene the DSCN_Runtime node is in. 70 | var result = DSCN_IO.import_dscn(filepath, selected_node, scene_root); 71 | 72 | # Based on the result of the import, print to the console saying what happened. 73 | if (result == DSCN_IO.DSCN_IO_STATUS.IMPORT_SUCCESS): 74 | print ("DSCN file imported successfully from file: " + filepath); 75 | else: 76 | var reason = ""; 77 | 78 | if (result == DSCN_IO.DSCN_IO_STATUS.EXPORT_SUCCESS): 79 | reason = "Programmer is a clutz and sent export success instead of import success!"; 80 | elif (result == DSCN_IO.DSCN_IO_STATUS.NO_NODE_SELECTED): 81 | reason = "No node was selected!"; 82 | elif (result == DSCN_IO.DSCN_IO_STATUS.SELECTED_NODE_NOT_FOUND): 83 | reason = "The selected node was not found in the currently open scene!"; 84 | elif (result == DSCN_IO.DSCN_IO_STATUS.FILE_NOT_FOUND): 85 | reason = "Could not find file!"; 86 | 87 | print ("DSCN file export failed. Reason: " + reason); 88 | 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DSCN Plugin 2 | 3 | This is a plugin I made to allow for importing/exporting DSCN files in Godot. 4 | 5 | As of when this was written, the **plugin supports Godot 3.1.1**. 6 | 7 | This plugin is released under the `MIT` license. 8 | (Credits to [Godot Engine](https://godotengine.org/) for the Godot logo). 9 | 10 | ### DSCN Feature list 11 | 12 | DSCN files have the following features: 13 | 14 | * DSCN files have **all the flexibility of normal scene files**. 15 | * DSCN files embed all of the resources needed for a scene. This means you can export a DSCN file in one project, and import it in another, and it will just work. 16 | * Almost all of the default nodes are supported. (Support for custom nodes is not yet implemented). If support for a node is missing, make a new issue and let me know! 17 | * Scripts, signals, and groups are all saved in the DSCN file as well! 18 | * DSCN files can be **imported and exported during run time from anywhere in the file system**. 19 | * `.tscn` and `.scn` files can only be opened in the `res://` and `user://` folders. Because `.DSCN` files use Godot's `File` class, you can load scenes from anywhere the `File` class can access! 20 | * Unfortunately because DSCN files require using the `File` class, you can only import/export DSCN files in a Godot project. 21 | * DSCN files are **extremely portable**. 22 | * Because DSCN files store a copy of everything needed to run the scene, they are extremely portable. 23 | * Unfortunately, this comes at the expense of being not quite as lightweight as `.tscn` or `.scn` files. Because DSCN files store one unique copy for each resource used within a scene, DSCN files take up a lot more space. This is because things like images are embedded into the DSCN file, while in `.tscn` files images are just referenced. 24 | * Also, right now DSCN files have no form of password protection or encryption. This means anything you store in a DSCN file *could* be imported into any project that has the DSCN plugin. 25 | * DSCN files **allow for easy mod support**. 26 | * Because DSCN files make a copy of every resource needed in the file, adding DSCN support is a great way to allow people to add modifications to your exported Godot projects. 27 | * This can also make patching/changing scene files easier if your scene files are DSCN files. Then all users will have to do to update/patch the DSCN file is just download a new `.dscn` file and replace the old `.dscn` file. 28 | * This makes it easier for users to add custom resources to your projects. Unfortunately, because DSCN files use Godot's `File` class to import/export DSCN files, this means users will have to convert their resources in a Godot project before they can be imported. 29 | * **WARNING**: *because DSCN files make a copy of every reference needed, and are not sand boxed in any way, this means DSCN files could potentially add harmful code/resources/textures to your game. **I am not responsible for ANY damage DSCN files may cause to your projects and those playing them**, you have been warned* 30 | 31 | ### How to use 32 | 33 | COMING SOON! 34 | 35 | For right now, check out the included import and export scenes, and/or watch the sneak peek video on [Youtube](https://www.youtube.com/watch?v=zyz2C6wGdlE), which (sort of) shows how to export/import DSCN files. 36 | 37 | Right now the DSCN plugin cannot export scenes that have scripts that use `load` or `preload`, because the resource(s) being loaded are not saved into the DSCN file. This means scenes like the KinematicCharacter demo from the Godot demo repository will work fine, but scenes like the 3D Platformer demo will not (without some editing). 38 | 39 | ### Notes 40 | 41 | Right now the DSCN plugin is in a proof-of-concept/alpha stage right now. **I would not suggest using the DSCN plugin in production!** 42 | 43 | While it can be used in production, right now some essential functionality is missing. Personally I would wait until some of the major flaws in the plugin (like no password protection and no support for custom nodes/resources) are added before trying to use this plugin in a professional project. 44 | 45 | Please report any issues, suggestions, and/or bugs to the issue tracker! Feel free to clone and make changes if you want. Hopefully the code is fairly straight forward, though do not hesitate to contact me if you have any questions. You can reach my through my [Twitter](https://twitter.com/TwistedTwigleg), [Facebook](https://www.facebook.com/noah.beard.5680), and email. 46 | 47 | If you want to see more things I've done, take a look at[RandomMomentania](https://randommomentania.com/), where I post game development tutorials and links to games I've created! 48 | 49 | ### Thanks 50 | 51 | Thanks to kb173 for updating the project to work with Godot 3.1.1 52 | 53 | 54 | -------------------------------------------------------------------------------- /addons/dscn_io/DSCN_Dock.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Control 3 | 4 | 5 | var editor_interface = null; 6 | var DSCN_IO = null; 7 | 8 | var DSCN_notice_popup = null; 9 | 10 | 11 | # ======== EXPORTER VARIABLES ============== 12 | var export_get_selected_button = null; 13 | var export_selected_node_label = null; 14 | var export_button = null; 15 | 16 | var export_save_file_dialog = null; 17 | 18 | var export_selected_node = null; 19 | # =========================================== 20 | 21 | 22 | # ======== IMPORTER VARIABLES ============== 23 | var import_get_selected_button = null; 24 | var import_selected_node_label = null; 25 | var import_button = null; 26 | 27 | var import_load_file_dialog = null; 28 | 29 | var import_selected_node = null; 30 | # =========================================== 31 | 32 | 33 | func _ready(): 34 | 35 | DSCN_IO = get_node("DSCN_IO"); 36 | DSCN_notice_popup = get_node("NoticeDialog"); 37 | 38 | # ======== EXPORTER ============== 39 | export_get_selected_button = get_node("ScrollContainer/VBoxContainer/Export_Options/VBoxContainer/Button_Get_Selected"); 40 | export_selected_node_label = get_node("ScrollContainer/VBoxContainer/Export_Options/VBoxContainer/Label_Selected_Node"); 41 | export_button = get_node("ScrollContainer/VBoxContainer/Export_Options/VBoxContainer/Button_Export"); 42 | 43 | export_save_file_dialog = get_node("Save_FileDialog"); 44 | export_save_file_dialog.connect("file_selected", self, "export_dscn"); 45 | 46 | export_get_selected_button.connect("pressed", self, "export_get_select_nodepath"); 47 | export_button.connect("pressed", self, "export_open_popup"); 48 | 49 | export_button.disabled = true; 50 | # ================================ 51 | 52 | 53 | # ======== IMPORTER ============== 54 | import_get_selected_button = get_node("ScrollContainer/VBoxContainer/Import_Options/VBoxContainer/Button_Get_Selected"); 55 | import_selected_node_label = get_node("ScrollContainer/VBoxContainer/Import_Options/VBoxContainer/Label_Selected_Node"); 56 | import_button = get_node("ScrollContainer/VBoxContainer/Import_Options/VBoxContainer/Button_Import"); 57 | 58 | import_load_file_dialog = get_node("Load_FileDialog"); 59 | import_load_file_dialog.connect("file_selected", self, "import_dscn"); 60 | 61 | import_get_selected_button.connect("pressed", self, "import_get_select_nodepath"); 62 | import_button.connect("pressed", self, "import_open_popup"); 63 | 64 | import_button.disabled = true; 65 | # ================================ 66 | 67 | 68 | func show_popup(status_text): 69 | DSCN_notice_popup.get_node("Status_Label").text = status_text; 70 | DSCN_notice_popup.popup_centered(); 71 | 72 | 73 | # ======== EXPORTER FUNCTIONS ============== 74 | 75 | func export_get_select_nodepath(): 76 | 77 | if (editor_interface == null): 78 | print ("Error: No editor interface found!"); 79 | return; 80 | 81 | var selection = editor_interface.get_selection(); 82 | var selected_nodes = selection.get_selected_nodes(); 83 | if (selected_nodes.size() > 0): 84 | export_selected_node = selected_nodes[0]; 85 | 86 | export_selected_node_label.text = "Selected Node: " + export_selected_node.name; 87 | 88 | export_button.disabled = false; 89 | 90 | else: 91 | export_selected_node = null; 92 | export_selected_node_label.text = "Selected Node: NONE"; 93 | export_button.disabled = true; 94 | 95 | 96 | func export_open_popup(): 97 | export_save_file_dialog.popup_centered(); 98 | 99 | 100 | func export_dscn(filepath): 101 | 102 | var result = DSCN_IO.export_dscn(filepath, export_selected_node, editor_interface.get_edited_scene_root()); 103 | 104 | if (result == DSCN_IO.DSCN_IO_STATUS.EXPORT_SUCCESS): 105 | show_popup("DSCN file exported successfully to file\n" + filepath); 106 | else: 107 | var reason = ""; 108 | 109 | if (result == DSCN_IO.DSCN_IO_STATUS.IMPORT_SUCCESS): 110 | reason = "TwistedTwigleg is a clutz and sent import success instead of export success!"; 111 | elif (result == DSCN_IO.DSCN_IO_STATUS.NO_NODE_SELECTED): 112 | reason = "No node was selected!"; 113 | elif (result == DSCN_IO.DSCN_IO_STATUS.SELECTED_NODE_NOT_FOUND): 114 | reason = "The selected node was not found in the currently open scene!"; 115 | elif (result == DSCN_IO.DSCN_IO_STATUS.FILE_NOT_FOUND): 116 | reason = "Could not find file!"; 117 | 118 | show_popup("DSCN file export failed. Reason:\n" + reason); 119 | 120 | # ========================================== 121 | 122 | 123 | # ======== IMPORTER FUNCTIONS ============== 124 | 125 | func import_get_select_nodepath(): 126 | 127 | if (editor_interface == null): 128 | print ("Error: No editor interface found!"); 129 | return; 130 | 131 | var selection = editor_interface.get_selection(); 132 | var selected_nodes = selection.get_selected_nodes(); 133 | if (selected_nodes.size() > 0): 134 | import_selected_node = selected_nodes[0]; 135 | 136 | import_selected_node_label.text = "Selected Node: " + import_selected_node.name; 137 | 138 | import_button.disabled = false; 139 | 140 | else: 141 | import_selected_node = null; 142 | import_selected_node_label.text = "Selected Node: NONE"; 143 | import_button.disabled = true; 144 | 145 | 146 | func import_open_popup(): 147 | import_load_file_dialog.popup_centered(); 148 | 149 | 150 | func import_dscn(filepath): 151 | 152 | var result = DSCN_IO.import_dscn(filepath, import_selected_node, editor_interface.get_edited_scene_root()); 153 | 154 | if (result == DSCN_IO.DSCN_IO_STATUS.IMPORT_SUCCESS): 155 | show_popup("DSCN file imported successfully from file\n" + filepath); 156 | else: 157 | var reason = ""; 158 | 159 | if (result == DSCN_IO.DSCN_IO_STATUS.EXPORT_SUCCESS): 160 | reason = "TwistedTwigleg is a clutz and sent export success instead of import success!"; 161 | elif (result == DSCN_IO.DSCN_IO_STATUS.NO_NODE_SELECTED): 162 | reason = "No node was selected!"; 163 | elif (result == DSCN_IO.DSCN_IO_STATUS.SELECTED_NODE_NOT_FOUND): 164 | reason = "The selected node was not found in the currently open scene!"; 165 | elif (result == DSCN_IO.DSCN_IO_STATUS.FILE_NOT_FOUND): 166 | reason = "Could not find file!"; 167 | 168 | show_popup("DSCN file export failed. Reason:\n" + reason); 169 | 170 | # ========================================== 171 | 172 | 173 | -------------------------------------------------------------------------------- /addons/dscn_io/DSCN Dock.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://addons/dscn_io/DSCN_Dock.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/dscn_io/DSCN_IO.tscn" type="PackedScene" id=2] 5 | 6 | [sub_resource type="StyleBoxFlat" id=1] 7 | bg_color = Color( 0, 0.433594, 0.270996, 1 ) 8 | corner_radius_top_left = 10 9 | corner_radius_top_right = 10 10 | corner_radius_bottom_right = 10 11 | corner_radius_bottom_left = 10 12 | 13 | [sub_resource type="StyleBoxFlat" id=2] 14 | bg_color = Color( 0.34375, 0.0966797, 0, 1 ) 15 | corner_radius_top_left = 10 16 | corner_radius_top_right = 10 17 | corner_radius_bottom_right = 10 18 | corner_radius_bottom_left = 10 19 | 20 | [node name="DSCN Dock" type="Control"] 21 | anchor_right = 1.0 22 | anchor_bottom = 1.0 23 | script = ExtResource( 1 ) 24 | 25 | [node name="ScrollContainer" type="ScrollContainer" parent="."] 26 | anchor_right = 1.0 27 | anchor_bottom = 1.0 28 | margin_bottom = 296.0 29 | 30 | [node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer"] 31 | margin_right = 340.0 32 | margin_bottom = 788.0 33 | 34 | [node name="Label" type="Label" parent="ScrollContainer/VBoxContainer"] 35 | margin_right = 340.0 36 | margin_bottom = 32.0 37 | rect_min_size = Vector2( 340, 32 ) 38 | text = "DSCN Importer/Exporter" 39 | align = 1 40 | valign = 1 41 | 42 | [node name="Export_Options" type="Panel" parent="ScrollContainer/VBoxContainer"] 43 | margin_top = 36.0 44 | margin_right = 340.0 45 | margin_bottom = 400.0 46 | rect_min_size = Vector2( 340, 364 ) 47 | custom_styles/panelf = SubResource( 1 ) 48 | custom_styles/panel = SubResource( 1 ) 49 | custom_styles/panelnc = SubResource( 1 ) 50 | 51 | [node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer/VBoxContainer/Export_Options"] 52 | anchor_right = 1.0 53 | anchor_bottom = 1.0 54 | margin_left = 10.0 55 | margin_right = -10.0 56 | margin_bottom = -5.0 57 | rect_min_size = Vector2( 320, 0 ) 58 | 59 | [node name="Label_Title" type="Label" parent="ScrollContainer/VBoxContainer/Export_Options/VBoxContainer"] 60 | margin_right = 320.0 61 | margin_bottom = 48.0 62 | rect_min_size = Vector2( 0, 48 ) 63 | text = "Export Options" 64 | align = 1 65 | valign = 1 66 | 67 | [node name="Label_Select_Node" type="Label" parent="ScrollContainer/VBoxContainer/Export_Options/VBoxContainer"] 68 | margin_top = 52.0 69 | margin_right = 320.0 70 | margin_bottom = 83.0 71 | text = "Select a node in the open 72 | scene and press the button" 73 | align = 1 74 | valign = 1 75 | 76 | [node name="Button_Get_Selected" type="Button" parent="ScrollContainer/VBoxContainer/Export_Options/VBoxContainer"] 77 | margin_top = 87.0 78 | margin_right = 320.0 79 | margin_bottom = 123.0 80 | rect_min_size = Vector2( 0, 36 ) 81 | text = "Get selected node" 82 | 83 | [node name="Label_Selected_Node" type="Label" parent="ScrollContainer/VBoxContainer/Export_Options/VBoxContainer"] 84 | margin_top = 127.0 85 | margin_right = 320.0 86 | margin_bottom = 159.0 87 | rect_min_size = Vector2( 0, 32 ) 88 | text = "Selected Node: NONE" 89 | align = 1 90 | valign = 1 91 | clip_text = true 92 | 93 | [node name="Control_Spacing" type="Control" parent="ScrollContainer/VBoxContainer/Export_Options/VBoxContainer"] 94 | margin_top = 163.0 95 | margin_right = 320.0 96 | margin_bottom = 291.0 97 | rect_min_size = Vector2( 0, 128 ) 98 | 99 | [node name="Button_Export" type="Button" parent="ScrollContainer/VBoxContainer/Export_Options/VBoxContainer"] 100 | margin_top = 295.0 101 | margin_right = 320.0 102 | margin_bottom = 343.0 103 | rect_min_size = Vector2( 0, 48 ) 104 | disabled = true 105 | text = "EXPORT" 106 | 107 | [node name="Control" type="Control" parent="ScrollContainer/VBoxContainer"] 108 | margin_top = 404.0 109 | margin_right = 340.0 110 | margin_bottom = 420.0 111 | rect_min_size = Vector2( 0, 16 ) 112 | 113 | [node name="Import_Options" type="Panel" parent="ScrollContainer/VBoxContainer"] 114 | margin_top = 424.0 115 | margin_right = 340.0 116 | margin_bottom = 788.0 117 | rect_min_size = Vector2( 340, 364 ) 118 | custom_styles/panelf = SubResource( 2 ) 119 | custom_styles/panel = SubResource( 2 ) 120 | custom_styles/panelnc = SubResource( 2 ) 121 | 122 | [node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer/VBoxContainer/Import_Options"] 123 | anchor_right = 1.0 124 | anchor_bottom = 1.0 125 | margin_left = 10.0 126 | margin_right = -10.0 127 | margin_bottom = -5.0 128 | rect_min_size = Vector2( 320, 0 ) 129 | 130 | [node name="Label_Title" type="Label" parent="ScrollContainer/VBoxContainer/Import_Options/VBoxContainer"] 131 | margin_right = 320.0 132 | margin_bottom = 48.0 133 | rect_min_size = Vector2( 0, 48 ) 134 | text = "Import Options" 135 | align = 1 136 | valign = 1 137 | 138 | [node name="Label_Select_Node" type="Label" parent="ScrollContainer/VBoxContainer/Import_Options/VBoxContainer"] 139 | margin_top = 52.0 140 | margin_right = 320.0 141 | margin_bottom = 83.0 142 | text = "Select a node in the open 143 | scene and press the button" 144 | align = 1 145 | valign = 1 146 | 147 | [node name="Button_Get_Selected" type="Button" parent="ScrollContainer/VBoxContainer/Import_Options/VBoxContainer"] 148 | margin_top = 87.0 149 | margin_right = 320.0 150 | margin_bottom = 123.0 151 | rect_min_size = Vector2( 0, 36 ) 152 | text = "Get selected node" 153 | 154 | [node name="Label_Selected_Node" type="Label" parent="ScrollContainer/VBoxContainer/Import_Options/VBoxContainer"] 155 | margin_top = 127.0 156 | margin_right = 320.0 157 | margin_bottom = 159.0 158 | rect_min_size = Vector2( 0, 32 ) 159 | text = "Selected Node: NONE" 160 | align = 1 161 | valign = 1 162 | clip_text = true 163 | 164 | [node name="Control_Spacing" type="Control" parent="ScrollContainer/VBoxContainer/Import_Options/VBoxContainer"] 165 | margin_top = 163.0 166 | margin_right = 320.0 167 | margin_bottom = 291.0 168 | rect_min_size = Vector2( 0, 128 ) 169 | 170 | [node name="Button_Import" type="Button" parent="ScrollContainer/VBoxContainer/Import_Options/VBoxContainer"] 171 | margin_top = 295.0 172 | margin_right = 320.0 173 | margin_bottom = 343.0 174 | rect_min_size = Vector2( 0, 48 ) 175 | disabled = true 176 | text = "IMPORT" 177 | 178 | [node name="Save_FileDialog" type="FileDialog" parent="."] 179 | margin_right = 400.0 180 | margin_bottom = 300.0 181 | rect_min_size = Vector2( 640, 480 ) 182 | resizable = true 183 | access = 2 184 | filters = PoolStringArray( "*.DSCN ; Deepcopy Scene file" ) 185 | current_dir = "/home/karl/Dropbox/Sync/Data/Personal/DSCN_Plugin" 186 | current_path = "/home/karl/Dropbox/Sync/Data/Personal/DSCN_Plugin/" 187 | 188 | [node name="Load_FileDialog" type="FileDialog" parent="."] 189 | margin_right = 400.0 190 | margin_bottom = 300.0 191 | rect_min_size = Vector2( 640, 480 ) 192 | window_title = "Open a File" 193 | resizable = true 194 | mode = 0 195 | access = 2 196 | filters = PoolStringArray( "*.DSCN ; Deepcopy Scene file" ) 197 | current_dir = "/home/karl/Dropbox/Sync/Data/Personal/DSCN_Plugin" 198 | current_path = "/home/karl/Dropbox/Sync/Data/Personal/DSCN_Plugin/" 199 | 200 | [node name="DSCN_IO" parent="." instance=ExtResource( 2 )] 201 | 202 | [node name="NoticeDialog" type="AcceptDialog" parent="."] 203 | editor/display_folded = true 204 | margin_left = 368.0 205 | margin_top = 160.0 206 | margin_right = 688.0 207 | margin_bottom = 272.0 208 | rect_min_size = Vector2( 320, 112 ) 209 | window_title = "DSCN Plugin" 210 | resizable = true 211 | 212 | [node name="Status_Label" type="Label" parent="NoticeDialog"] 213 | anchor_right = 1.0 214 | anchor_bottom = 1.0 215 | margin_left = 8.0 216 | margin_top = 8.0 217 | margin_right = -8.0 218 | margin_bottom = -36.0 219 | text = "DSCN Import Successful" 220 | align = 1 221 | valign = 1 222 | -------------------------------------------------------------------------------- /Test_Export_Scenes/Test_Scene.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=16 format=2] 2 | 3 | [ext_resource path="res://Test_Export_Scenes/Test_Polygon2D_Script.gd" type="Script" id=1] 4 | [ext_resource path="res://icon.png" type="Texture" id=2] 5 | [ext_resource path="res://icon_spatial.png" type="Texture" id=3] 6 | [ext_resource path="res://addons/dscn_io/DSCN_Runtime_Node.gd" type="Script" id=4] 7 | [ext_resource path="res://addons/dscn_io/DSCN_Node_Icon.png" type="Texture" id=5] 8 | 9 | [sub_resource type="RectangleShape2D" id=1] 10 | extents = Vector2( 32, 32 ) 11 | 12 | [sub_resource type="Animation" id=2] 13 | length = 2.0 14 | loop = true 15 | tracks/0/type = "value" 16 | tracks/0/path = NodePath("Sprite:position") 17 | tracks/0/interp = 1 18 | tracks/0/loop_wrap = true 19 | tracks/0/imported = false 20 | tracks/0/enabled = true 21 | tracks/0/keys = { 22 | "times": PoolRealArray( 0, 1, 2 ), 23 | "transitions": PoolRealArray( 1, 1, 1 ), 24 | "update": 0, 25 | "values": [ Vector2( 179.069, 284.244 ), Vector2( 684.071, 301.244 ), Vector2( 179.069, 284.244 ) ] 26 | } 27 | tracks/1/type = "value" 28 | tracks/1/path = NodePath("Polygon2D_Other:texture_scale") 29 | tracks/1/interp = 1 30 | tracks/1/loop_wrap = true 31 | tracks/1/imported = false 32 | tracks/1/enabled = true 33 | tracks/1/keys = { 34 | "times": PoolRealArray( 0, 1, 2 ), 35 | "transitions": PoolRealArray( 1, 1, 1 ), 36 | "update": 0, 37 | "values": [ Vector2( 1, 1 ), Vector2( 2, 2 ), Vector2( 1, 1 ) ] 38 | } 39 | 40 | [sub_resource type="StyleBoxFlat" id=3] 41 | bg_color = Color( 1, 0, 0, 1 ) 42 | 43 | [sub_resource type="SpatialMaterial" id=4] 44 | albedo_color = Color( 1, 0.973877, 0.582031, 1 ) 45 | albedo_texture = ExtResource( 3 ) 46 | roughness = 0.8 47 | uv1_triplanar = true 48 | 49 | [sub_resource type="CubeMesh" id=5] 50 | 51 | [sub_resource type="SpatialMaterial" id=6] 52 | albedo_color = Color( 0.382813, 0.78302, 1, 1 ) 53 | metallic = 0.3 54 | roughness = 0.4 55 | 56 | [sub_resource type="PlaneMesh" id=7] 57 | material = SubResource( 6 ) 58 | size = Vector2( 8, 8 ) 59 | 60 | [sub_resource type="Animation" id=8] 61 | resource_name = "Idle_Anim" 62 | length = 2.0 63 | loop = true 64 | tracks/0/type = "value" 65 | tracks/0/path = NodePath("Camera:transform") 66 | tracks/0/interp = 1 67 | tracks/0/loop_wrap = true 68 | tracks/0/imported = false 69 | tracks/0/enabled = true 70 | tracks/0/keys = { 71 | "times": PoolRealArray( 0, 1 ), 72 | "transitions": PoolRealArray( 1, 1 ), 73 | "update": 0, 74 | "values": [ Transform( 1, 0, 0, 0, 0.90792, 0.419144, 0, -0.419144, 0.90792, 0, 2.78633, 4.1752 ), Transform( -4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -7.1374, 3.2633, -3.1894 ) ] 75 | } 76 | 77 | [sub_resource type="ProceduralSky" id=9] 78 | sky_top_color = Color( 0.976471, 0.700552, 0.0470588, 1 ) 79 | sky_horizon_color = Color( 0.898775, 0.556863, 0.909804, 1 ) 80 | sky_curve = 0.25 81 | ground_bottom_color = Color( 0.153186, 0.188235, 0.101961, 1 ) 82 | ground_horizon_color = Color( 0.927206, 0.952941, 0.482353, 1 ) 83 | ground_curve = 0.01 84 | sun_energy = 16.0 85 | 86 | [sub_resource type="Environment" id=10] 87 | background_mode = 2 88 | background_sky = SubResource( 9 ) 89 | ambient_light_energy = 0.0 90 | tonemap_mode = 3 91 | dof_blur_far_enabled = true 92 | dof_blur_far_distance = 2.0 93 | 94 | [node name="Test_Scene" type="Node2D"] 95 | 96 | [node name="Polygon2D" type="Polygon2D" parent="."] 97 | polygon = PoolVector2Array( 180, 284, 634.174, 152.626, 733.897, 425.202, 467, 452 ) 98 | script = ExtResource( 1 ) 99 | 100 | [node name="Sprite" type="Sprite" parent="Polygon2D"] 101 | editor/display_folded = true 102 | position = Vector2( 179.069, 284.244 ) 103 | texture = ExtResource( 2 ) 104 | 105 | [node name="StaticBody2D" type="StaticBody2D" parent="Polygon2D/Sprite"] 106 | 107 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Polygon2D/Sprite/StaticBody2D"] 108 | shape = SubResource( 1 ) 109 | 110 | [node name="Sprite2" type="Sprite" parent="Polygon2D"] 111 | position = Vector2( 647.091, 158.449 ) 112 | texture = ExtResource( 2 ) 113 | 114 | [node name="Sprite3" type="Sprite" parent="Polygon2D"] 115 | position = Vector2( 740.166, 436.565 ) 116 | texture = ExtResource( 2 ) 117 | 118 | [node name="Sprite4" type="Sprite" parent="Polygon2D"] 119 | position = Vector2( 468.166, 463.565 ) 120 | texture = ExtResource( 2 ) 121 | 122 | [node name="Polygon2D_Other" type="Polygon2D" parent="Polygon2D"] 123 | editor/display_folded = true 124 | position = Vector2( 449.149, 189.764 ) 125 | color = Color( 0.425781, 1, 0.448212, 1 ) 126 | offset = Vector2( -449.149, -189.764 ) 127 | texture = ExtResource( 2 ) 128 | polygon = PoolVector2Array( 354.047, 132.38, 455.128, 273.17, 544.475, 165.772 ) 129 | script = ExtResource( 1 ) 130 | SPEED = -80.0 131 | 132 | [node name="Sprite" type="Sprite" parent="Polygon2D/Polygon2D_Other"] 133 | modulate = Color( 1, 0, 0, 1 ) 134 | position = Vector2( -88.2695, -57.5458 ) 135 | texture = ExtResource( 2 ) 136 | 137 | [node name="Sprite2" type="Sprite" parent="Polygon2D/Polygon2D_Other"] 138 | modulate = Color( 1, 0, 0, 1 ) 139 | position = Vector2( 6.33975, 77.5406 ) 140 | texture = ExtResource( 2 ) 141 | 142 | [node name="AnimationPlayer" type="AnimationPlayer" parent="Polygon2D"] 143 | autoplay = "Test_Anim" 144 | anims/Test_Anim = SubResource( 2 ) 145 | 146 | [node name="Label" type="Label" parent="Polygon2D"] 147 | margin_left = 304.0 148 | margin_top = 329.0 149 | margin_right = 416.0 150 | margin_bottom = 343.0 151 | rect_rotation = 31.3061 152 | custom_colors/font_color = Color( 0, 0, 0, 1 ) 153 | text = "WOW! Some Text" 154 | 155 | [node name="Panel" type="Panel" parent="Polygon2D"] 156 | margin_left = 570.0 157 | margin_top = 275.0 158 | margin_right = 781.0 159 | margin_bottom = 368.0 160 | custom_styles/panelf = SubResource( 3 ) 161 | custom_styles/panel = SubResource( 3 ) 162 | custom_styles/panelnc = SubResource( 3 ) 163 | 164 | [node name="Spatial" type="Spatial" parent="Polygon2D"] 165 | editor/display_folded = true 166 | 167 | [node name="Camera" type="Camera" parent="Polygon2D/Spatial"] 168 | transform = Transform( 1, 0, 0, 0, 0.90792, 0.419144, 0, -0.419144, 0.90792, 0, 2.78633, 4.1752 ) 169 | 170 | [node name="MeshInstance" type="MeshInstance" parent="Polygon2D/Spatial"] 171 | transform = Transform( 0.80128, 0, 0.59829, 0, 1, 0, -0.59829, 0, 0.80128, 0, 0, 0 ) 172 | material_override = SubResource( 4 ) 173 | mesh = SubResource( 5 ) 174 | material/0 = null 175 | 176 | [node name="DirectionalLight" type="DirectionalLight" parent="Polygon2D/Spatial"] 177 | transform = Transform( 0.680357, 0.629267, -0.375682, -0.109262, 0.593972, 0.797031, 0.72469, -0.501218, 0.472869, -2.67672, 0, 0 ) 178 | shadow_enabled = true 179 | 180 | [node name="MeshInstance2" type="MeshInstance" parent="Polygon2D/Spatial"] 181 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.96323, 0 ) 182 | mesh = SubResource( 7 ) 183 | material/0 = null 184 | 185 | [node name="Camera_Player" type="AnimationPlayer" parent="Polygon2D/Spatial"] 186 | autoplay = "Idle_Anim" 187 | playback_speed = 0.5 188 | anims/Idle_Anim = SubResource( 8 ) 189 | 190 | [node name="WorldEnvironment" type="WorldEnvironment" parent="Polygon2D/Spatial"] 191 | environment = SubResource( 10 ) 192 | 193 | [node name="Button" type="Button" parent="Polygon2D"] 194 | margin_left = 526.0 195 | margin_top = 395.0 196 | margin_right = 677.0 197 | margin_bottom = 471.0 198 | text = "Test Button" 199 | 200 | [node name="DSCN_Runtime_Node" type="Node" parent="."] 201 | script = ExtResource( 4 ) 202 | __meta__ = { 203 | "_editor_icon": ExtResource( 5 ) 204 | } 205 | path_to_node = NodePath("../Polygon2D") 206 | mode = 1 207 | filepath = "res://Runtime_Scene.DSCN" 208 | execute_in_ready = true 209 | [connection signal="pressed" from="Polygon2D/Button" to="Polygon2D/Polygon2D_Other" method="_on_button_pressed"] 210 | [connection signal="pressed" from="Polygon2D/Button" to="Polygon2D" method="_on_button_pressed"] 211 | -------------------------------------------------------------------------------- /addons/dscn_io/DSCN_IO.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Node 3 | 4 | # TODO: rewrite this! 5 | # DSCN FILE FORMAT (0.1.0): 6 | # Number of nodes stored in Node list: 1 (or however many nodes are stored) 7 | # Number of resources stored in Resource list: 1 (or however many resources are stored) 8 | # JSON NodeTree: JSON Dictionary built using the node names as the key, and the children 9 | # nodes as values. Leaf nodes only have a single value, called DSCN_Resources 10 | # which holds all of the resources the leaf node needs. 11 | # Metadata : (Nothing for now, but saving this in case!) 12 | # Export Version : 0.1.0 13 | # Node list : all nodes are dumped using "file.store_var(nodes));" 14 | # Resource list : each node is dumped using "file.store_var(resource);" 15 | 16 | 17 | # All of the results that can be returned when trying to export/import 18 | # a DSCN file. 19 | enum DSCN_IO_STATUS { 20 | IMPORT_SUCCESS, 21 | EXPORT_SUCCESS, 22 | NO_NODE_SELECTED, 23 | SELECTED_NODE_NOT_FOUND, 24 | FILE_NOT_FOUND, 25 | } 26 | 27 | # A variable to hold the DSCN_resource_manager script. 28 | var DSCN_resource_manager = null; 29 | 30 | 31 | func _ready(): 32 | # We are going to assume that every node that has DSCN_IO has a child 33 | # called DSCN_Resource_Manager that holds the DSCN_Resource_Manager.gd script. 34 | DSCN_resource_manager = get_node("DSCN_Resource_Manager"); 35 | 36 | 37 | # ======== EXPORTER FUNCTIONS ============== 38 | 39 | 40 | # Will export a DSCN file. 41 | # 42 | # Needs the following arguments: 43 | # filepath: The file path pointing to where you want to save the DSCN file. 44 | # (This can be anywhere on the file system!) 45 | # selected_node: The node you want to save 46 | # (This will save the children of the selected node as well!) 47 | # scene_root: The root of the scene selected_node is in. 48 | # 49 | # This function needs the scene root to ensure selected_node is in the 50 | # currently open scene. 51 | # (And for argument completeness with the import_dscn function) 52 | # 53 | # Will return one of the values in DSCN_IO_STATUS. 54 | func export_dscn(filepath, selected_node, scene_root): 55 | 56 | # Make sure a node is selected. Return a error if it does not. 57 | if (selected_node == null): 58 | return DSCN_IO_STATUS.NO_NODE_SELECTED; 59 | 60 | # Make sure the node exists in the passed in scene_root. 61 | var path_in_open_scene = scene_root.get_path_to(selected_node); 62 | if (path_in_open_scene != null): 63 | 64 | # Double check to make sure the node exists. 65 | # Return a error if it does not. 66 | if (scene_root.has_node(path_in_open_scene) == false): 67 | return DSCN_IO_STATUS.SELECTED_NODE_NOT_FOUND; 68 | 69 | # Make a new file so we can write the data to it. 70 | # open the file in WRITE mode at the passed in filepath. 71 | var export_file = File.new(); 72 | export_file.open(filepath, export_file.WRITE); 73 | 74 | # Save all of the DSCN data into the file. 75 | _save_dscn(scene_root.get_node(path_in_open_scene), export_file); 76 | 77 | # Close the file. 78 | export_file.close(); 79 | 80 | # If we got this far, then the DSCN file has successfully been exported! 81 | return DSCN_IO_STATUS.EXPORT_SUCCESS; 82 | 83 | # If the node does not exist in the scene, then we need to return a error. 84 | else: 85 | return DSCN_IO_STATUS.SELECTED_NODE_NOT_FOUND; 86 | 87 | 88 | # This function will save all of the DSCN data into the passed in file. 89 | # 90 | # Needs the following arguments: 91 | # node: The node you want to save to into the DSCN file. 92 | # file: The file the DSCN data needs to be saved into. 93 | func _save_dscn(node, file): 94 | 95 | # Duplicate the node (and all it's children). 96 | # Make sure we are also duplicating scripts, groups, and signals! 97 | var duplicate_node = node.duplicate(DUPLICATE_SCRIPTS + DUPLICATE_GROUPS + DUPLICATE_SIGNALS); 98 | 99 | # Make a JSON NodeTree, make the resource list, and make the node list, all using 100 | # the add_node_to_json_node_tree function 101 | 102 | # Make the JSON node tree. This is where we will be storing any/all information 103 | # about the nodes that we will need to convert/parse the DSCN file back into 104 | # a scene. 105 | var JSON_node_tree = {}; 106 | # Make the Resource list. This is a list where we will store all of the resources 107 | # needed in the scene. We will access resources in this list based on the index 108 | # they are assigned with when added to the list. 109 | var resource_list = []; 110 | # Make the Node list. This is a list where all of the nodes (and children nodes) 111 | # needed in the scene will be stored. Like with Resource List, we will access 112 | # nodes in the list using the index they are assigned with when added to the list. 113 | var node_list = []; 114 | 115 | # A temporary dictionary for checking for resources. 116 | # We need this because some resources return new references when we get the data we 117 | # need out of them, and if we do not check the actual object (not the data), we 118 | # would in up storing duplicates of each resource used (which increases file size). 119 | # 120 | # This is primarily used for images, because get_data returns a new reference every 121 | # time it is used. 122 | var resource_check_dict = {}; 123 | 124 | # Start adding the node data into JSON_node_tree, node_list, resource_list, 125 | # and resource_check_dict. 126 | # 127 | # This is a recursive function that will add the node data for all of the 128 | # children of the passed in node until there are no children left. 129 | _add_node_data_to_dscn(duplicate_node, JSON_node_tree, node_list, resource_list, resource_check_dict) 130 | 131 | # Add all of the signals for all of the nodes 132 | for node in node_list: 133 | _add_node_signals(node, node_list, JSON_node_tree); 134 | 135 | # Store the number of nodes in node_list. 136 | file.store_line(str(node_list.size())); 137 | # Store the number of resources in resource_list. 138 | file.store_line(str(resource_list.size())); 139 | 140 | # Store the JSON tree. 141 | file.store_line(to_json(JSON_node_tree)); 142 | 143 | # Store Metadata and Export version 144 | file.store_line("NULL"); 145 | file.store_line("0.1.0"); 146 | 147 | # Store nodes 148 | for node_to_store in node_list: 149 | file.store_var(node_to_store, true); 150 | 151 | # Store resources 152 | for resource_to_store in resource_list: 153 | file.store_var(resource_to_store, true); 154 | 155 | # Print success! 156 | print ("**** DSCN_IO ****"); 157 | print ("Saved the following node tree: ") 158 | print (duplicate_node.print_tree_pretty()); 159 | print ("*****************"); 160 | 161 | 162 | # This function will add all of the data into json_tree, node_list, resource_list 163 | # and resource_check_dict that we need to load the nodes out of DSCN files. 164 | # 165 | # Needs the following arguments: 166 | # node: The node whose data is currently being saved. 167 | # json_tree: The JSON node tree dictionary where we can store data needed 168 | # load the nodes we are saving. 169 | # node_list: A list holding all of the nodes in the scene we want to save. 170 | # This function will populate this list with node and it's children! 171 | # resource_list: A list holding all of the resources in the scene we need to save. 172 | # This function will populate this list with the resources node needs! 173 | # resource_check_dict: A dictionary holding resources we may need to check against 174 | # To avoid storing duplicate data. This function may populate this dictionary. 175 | func _add_node_data_to_dscn(node, json_tree, node_list, resource_list, resource_check_dict): 176 | 177 | # Add the node to the node_list and get it's position in node_list. 178 | node_list.append(node); 179 | var node_position_in_list = node_list.size()-1 180 | 181 | # Get all of the resources this node is dependent on and store them into 182 | # node_dependency_dict. 183 | var node_dependency_dict = {} 184 | DSCN_resource_manager.add_node_resources_to_list_and_dict(node, node_dependency_dict, resource_list, resource_check_dict); 185 | 186 | # Tell all of the children nodes to save their data. 187 | var child_nodes_for_node = node.get_children(); 188 | for child_node in child_nodes_for_node: 189 | _add_node_data_to_dscn(child_node, json_tree, node_list, resource_list, resource_check_dict); 190 | 191 | # Get the positions of the children nodes in node_list so we can later 192 | # reconstruct the node tree when loading DSCN files. 193 | var child_ids = []; 194 | for child in child_nodes_for_node: 195 | child_ids.append(node_list.find(child)); 196 | 197 | # Save the data needed to import this node into json_tree. 198 | json_tree[node_position_in_list] = { 199 | "DSCN_Dependencies":node_dependency_dict, 200 | "DSCN_Children":child_ids, 201 | "DSCN_Node_Name":node.name, 202 | }; 203 | 204 | 205 | # This function will add all of the signals from the passed in node into json_tree. 206 | # 207 | # Needs the following arguments: 208 | # node: The node whose data is currently being saved. 209 | # node_list: A list holding all of the nodes in the scene we want to save. 210 | # json_tree: The JSON node tree dictionary where we can store data needed 211 | # load the nodes we are saving. 212 | func _add_node_signals(node, node_list, json_tree): 213 | 214 | # Figure out where this node is positioned in node_list. 215 | var position_of_node_in_list = node_list.find(node); 216 | 217 | # Get all of the signals this node COULD have connected. 218 | # Make sure this node has at least one (possibly) connected signal. 219 | var signal_list = node.get_signal_list(); 220 | if (signal_list.size() > 0): 221 | 222 | # Add the amount of signals this node has to json_tree. 223 | json_tree[position_of_node_in_list]["DSCN_Signal_Count"] = signal_list.size(); 224 | 225 | # Go through each signal in signal list... 226 | for i in range(0, signal_list.size()): 227 | 228 | # Get the signal data and store it in signal_item. 229 | var signal_item = signal_list[i]; 230 | 231 | # Get all of the connections this signal may have. 232 | # Make sure this signal has at least one connection. 233 | var signal_connections = node.get_signal_connection_list(signal_item["name"]) 234 | if (signal_connections.size() > 0): 235 | 236 | # Add the amount of connections this one signal has to json_tree. 237 | json_tree[position_of_node_in_list]["DSCN_Connection_Count_" + str(i)] = signal_connections.size(); 238 | 239 | # Go through each connection in signal_connections... 240 | for j in range(0, signal_connections.size()): 241 | 242 | # Get the connection data. 243 | var signal_connection = signal_connections[j]; 244 | # Find the source node and target node in node_list. 245 | var source_position = node_list.find(signal_connection["source"]) 246 | var target_position = node_list.find(signal_connection["target"]); 247 | 248 | # Make sure node_list contains both the source and the target. 249 | if (source_position != -1 and target_position != -1): 250 | # Change the source and target variables in the signal_connection 251 | # dictionary to store the position of the source and target nodes 252 | # in node_list. 253 | signal_connection["source"] = source_position; 254 | signal_connection["target"] = target_position; 255 | 256 | # Save the signal connection in json_tree. 257 | json_tree[position_of_node_in_list]["DSCN_Signal_" + str(j)] = signal_connection; 258 | 259 | 260 | 261 | # ========================================== 262 | 263 | 264 | # ======== IMPORTER FUNCTIONS ============== 265 | 266 | 267 | # Will import a DSCN file. 268 | # 269 | # Needs the following arguments: 270 | # filepath: The file path pointing to where the DSCN file you want to load is. 271 | # (This can be anywhere on the the file system!) 272 | # selected_node: The node that will have the nodes in the DSCN file as it's children. 273 | # (Will include the DSCN file's children!) 274 | # scene_root: The root of the scene selected_node is in. 275 | # 276 | # 277 | # Will return one of the values in DSCN_IO_STATUS depending on the import status. 278 | func import_dscn(filepath, selected_node, scene_root): 279 | 280 | # Make sure a node is selected. Return a error if it does not. 281 | if (selected_node == null): 282 | return DSCN_IO_STATUS.NO_NODE_SELECTED; 283 | 284 | # Make sure the node exists in the passed in scene_root. 285 | var path_in_open_scene = scene_root.get_path_to(selected_node); 286 | if (path_in_open_scene != null): 287 | 288 | # Double check to make sure the node exists. 289 | # Return a error if it does not. 290 | if (scene_root.has_node(path_in_open_scene) == false): 291 | return DSCN_IO_STATUS.SELECTED_NODE_NOT_FOUND; 292 | 293 | # Make a new file so we can read the data to it. 294 | # Make sure there is a file at the passed in filepath... 295 | var file = File.new(); 296 | if (file.file_exists(filepath) == false): 297 | return DSCN_IO_STATUS.FILE_NOT_FOUND; 298 | 299 | # Open the file in READ mode. 300 | file.open(filepath, file.READ); 301 | 302 | # Make a new variable to store the root node of the loaded DSCN 303 | # scene file. 304 | var loaded_scene = null; 305 | 306 | # Load all of the nodes in the DSCN file. 307 | loaded_scene = _load_dscn(file); 308 | 309 | # Add the loaded root node (and it's children) to the selected node. 310 | selected_node.add_child(loaded_scene); 311 | 312 | # Set all of the node owners to scene_root so they will be saved 313 | # properly with scene_root. 314 | _set_node_owners(loaded_scene, scene_root); 315 | 316 | # Close the file. 317 | file.close(); 318 | 319 | # Return success 320 | return DSCN_IO_STATUS.IMPORT_SUCCESS; 321 | 322 | 323 | # This function will load all of the DSCN data from the passed in file. 324 | # 325 | # Needs the following arguments: 326 | # file: The file the DSCN data is saved in. 327 | func _load_dscn(file): 328 | 329 | # Get the number of nodes in the saved nodes_list in the DSCN file. 330 | var nodes_in_list = int(file.get_line()); 331 | # Get the number of resources in the saved resource_list in the DSCN file. 332 | var resources_in_list = int(file.get_line()); 333 | # Get the JSON node tree holding all of the data we will need to parse 334 | # the nodes from the saved DSCN file. 335 | var file_JSON_node_tree = parse_json(file.get_line()); 336 | # Get the meta data from the saved DSCN file (as of version 0.1.0, this stores nothing) 337 | var file_meta_data = file.get_line(); 338 | # Get the version of the DSCN file. 339 | var file_export_version = file.get_line(); 340 | 341 | # Make sure the version of the DSCN file is the same version as this plugin. 342 | if (file_export_version != "0.1.0"): 343 | print ("ERROR: Cannot import DSCN file with version: ", file_export_version); 344 | print ("Can only import DSCN files with version: 0.1.0"); 345 | return null; 346 | 347 | # Make a empty node list and resource list. 348 | var node_list = []; 349 | var resource_list = []; 350 | 351 | # Get all of the nodes in the saved DSCN file (using nodes_in_list) 352 | # and place those nodes in node_list. 353 | for i in range(0, nodes_in_list): 354 | var stored_node = file.get_var(true); 355 | node_list.append(stored_node); 356 | 357 | # Get all of the resources in the saved DSCN file (using resources_in_list) 358 | # and place those resources in resource_list. 359 | for i in range(0, resources_in_list): 360 | var stored_resource = file.get_var(true); 361 | resource_list.append(stored_resource); 362 | 363 | # Add resources to all of the nodes in node_list 364 | for i in range(0, node_list.size()): 365 | # Get the node and assign it's name to the name saved in the JSON_node_tree. 366 | var node = node_list[i]; 367 | node.name = file_JSON_node_tree[str(i)]["DSCN_Node_Name"]; 368 | 369 | # Tell DSCN_resource_manager to load the resources for this node from resource_list. 370 | # 371 | # We need to pass in the data in node, file_JSON_node_tree, and resource_list so 372 | # the resource manager can assign the proper resources from resource_list. 373 | DSCN_resource_manager.load_node_resources_from_list(node, file_JSON_node_tree[str(i)], resource_list); 374 | 375 | 376 | # Load all of the signals for all of the nodes in node_list 377 | for node in node_list: 378 | _load_node_signals(node, node_list, file_JSON_node_tree); 379 | 380 | 381 | # Rebuild the node tree, and then get and assign the root of the loaded DSCN file 382 | # to a new variable called final_scene. 383 | var final_scene = _rebuild_node_tree(node_list[0], file_JSON_node_tree, node_list); 384 | 385 | # (Optional) print what we imported. 386 | print ("**** DSCN_IO ****"); 387 | print ("Added the following node tree: ") 388 | print (final_scene.print_tree_pretty()); 389 | print ("*****************"); 390 | 391 | # Return the root node of the imported DSCN file. 392 | return final_scene; 393 | 394 | # This function will rebuild the node tree saved in the DSCN file 395 | # using the data in json_node_tree. 396 | # 397 | # Needs the following arguments: 398 | # node : The current node that is having it's children added 399 | # json_node_tree : The saved json_node_tree from the DSCN file. 400 | # node_list : A list containing every node in the loaded DSCN file. 401 | func _rebuild_node_tree(node, json_node_tree, node_list): 402 | 403 | # Make a empty list of children in this node. 404 | var node_children = []; 405 | 406 | # Find this node's position in node_list. 407 | var node_position = node_list.find(node); 408 | 409 | # If the node was found, then get the children of this node (stored in json_node_tree). 410 | if (node_position != -1): 411 | node_children = json_node_tree[str(node_position)]["DSCN_Children"]; 412 | 413 | # If this node has no children, then return. 414 | if (node_children.size() <= 0): 415 | return node; 416 | 417 | # If this node has children node(s). 418 | else: 419 | # For each child in node_children. 420 | for child in node_children: 421 | # Get the child node using the stored position of the child. 422 | # (which is the data in DSCN_Children) 423 | var child_node = node_list[child]; 424 | # Add the child node as a child of this node. 425 | # We are calling _rebuild_node_tree so if the child node has children, 426 | # then they will be added BEFORE adding this child node as a child of this node. 427 | # 428 | # (confusing, no? This is a recursive depth-first function that adds children 429 | # nodes to the passed in node, going all the way down the scene tree stored 430 | # in json_node_tree) 431 | node.add_child(_rebuild_node_tree(child_node, json_node_tree, node_list)); 432 | 433 | # Return the node, now that it has its children added to it 434 | return node; 435 | 436 | 437 | # This node will set the owner of the passed in node to the passed in owner. 438 | # This will also set the owner of all of the children of the passed in node 439 | # to the same owner as the passed in node. 440 | # 441 | # Needs the following arguments: 442 | # node : The node (and children of this node) whose owner we want to set. 443 | # owner : The thing we want to be the owner of node. 444 | func _set_node_owners(node, owner): 445 | # Set the owner of the node to the passed in owner argument. 446 | node.set_owner(owner); 447 | 448 | # Go through the children in this node... 449 | # (NOTE: this means rebuild_scene_tree has to be called BEFORE _set_node_owners) 450 | for child in node.get_children(): 451 | # and called _set_node_owners on them as well, passing in the owner 452 | # of this node. 453 | _set_node_owners(child, owner); 454 | 455 | 456 | # This function will load all of the signals from the passed in node from json_tree. 457 | # 458 | # Needs the following arguments: 459 | # node: The node whose signals we want to load. 460 | # node_list: A list holding all of the nodes in the loaded DSCN file. 461 | # json_tree: The JSON node tree dictionary loaded from the DSCN file. 462 | func _load_node_signals(node, node_list, json_tree): 463 | 464 | # Find the position of the node in node_list. 465 | var position_of_node_in_list = node_list.find(node); 466 | 467 | # See if the DSCN_Signal_Count key is in the data for this node in json_tree. 468 | if ((json_tree[str(position_of_node_in_list)]).has("DSCN_Signal_Count") == true): 469 | 470 | # If DSCN_Signal_Count is in the data for this node, get it and assign it to signal_count. 471 | var signal_count = json_tree[str(position_of_node_in_list)]["DSCN_Signal_Count"]; 472 | 473 | # Go through each of the (potentially saved) signals... 474 | for i in range(0, signal_count): 475 | # See if the signal's connection count was saved... 476 | if (json_tree[str(position_of_node_in_list)].has("DSCN_Connection_Count_" + str(i))): 477 | # If the signal's connection count was saved, then get it and assign it to connection_count. 478 | var connection_count = json_tree[str(position_of_node_in_list)]["DSCN_Connection_Count_" + str(i)] 479 | 480 | # Go through each of the saved connections... 481 | for j in range(0, connection_count): 482 | # Get the signal connection data and assign it to signal_connection. 483 | var signal_connection = json_tree[str(position_of_node_in_list)]["DSCN_Signal_" + str(j)] 484 | 485 | # Connect the signal. 486 | node.connect(signal_connection["signal"], node_list[signal_connection["target"]], 487 | signal_connection["method"], signal_connection["binds"], signal_connection["flags"]); 488 | 489 | 490 | # ========================================== 491 | 492 | -------------------------------------------------------------------------------- /addons/dscn_io/DSCN_Resource_Manager.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Node 3 | 4 | func _ready(): 5 | pass 6 | 7 | 8 | # This will add all of the resources in a node into the passed 9 | # in resource list. 10 | # And this will return a dictionary containing pointing to the index 11 | # where the resources the node needs are in the passed in resource list. 12 | # 13 | # We will just edit/add-to the passed in dictionary (dep_dict) and list (resources_list) 14 | # directly. 15 | func add_node_resources_to_list_and_dict(node, dep_dict, resources_list, resource_check_dict): 16 | 17 | # Store CUSTOM DATA in the node, if it has the following function: 18 | # DSCN_add_resources. 19 | if (node.has_method("DSCN_add_resources") == true): 20 | node.DSCN_custom_add_resources(node, dep_dict, resources_list); 21 | 22 | 23 | # *** All of the base-type/basic nodes *** 24 | 25 | if (node is Node): 26 | _add_resources_node(node, dep_dict, resources_list, resource_check_dict); 27 | if (node is CanvasItem): 28 | _add_resources_canvas_item(node, dep_dict, resources_list, resource_check_dict); 29 | if (node is Viewport): 30 | _add_resources_viewport(node, dep_dict, resources_list, resource_check_dict); 31 | if (node is AudioStreamPlayer): 32 | _add_resources_audio_stream_player(node, dep_dict, resources_list, resource_check_dict); 33 | if (node is WorldEnvironment): 34 | _add_resources_world_environment(node, dep_dict, resources_list, resource_check_dict); 35 | 36 | 37 | # *** All of the Node2D extending nodes *** 38 | if (node is Node2D): 39 | # Until there is a better way, we'll just do this manually in order of the 40 | # "Inheritied By" section of the documentation, found below: 41 | # http://docs.godotengine.org/en/3.0/classes/class_node2d.html? 42 | # 43 | # And then we'll add anything else that is missing! 44 | # The only nodes here are nodes that have resources to save. 45 | # Other nodes to not seem to have any resources to save. 46 | 47 | if (node is TouchScreenButton): 48 | _add_resources_touch_screen_button(node, dep_dict, resources_list, resource_check_dict); 49 | elif (node is Particles2D): 50 | _add_resources_particles2d(node, dep_dict, resources_list, resource_check_dict); 51 | elif (node is AnimatedSprite): 52 | _add_resources_animated_sprite(node, dep_dict, resources_list, resource_check_dict); 53 | elif (node is Light2D): 54 | _add_resources_light2d(node, dep_dict, resources_list, resource_check_dict); 55 | elif (node is Path2D): 56 | _add_resources_path2d(node, dep_dict, resources_list, resource_check_dict); 57 | elif (node is Line2D): 58 | _add_resources_line2d(node, dep_dict, resources_list, resource_check_dict); 59 | elif (node is AudioStreamPlayer2D): 60 | _add_resources_audio_stream_player2d(node, dep_dict, resources_list, resource_check_dict); 61 | elif (node is Sprite): 62 | _add_resources_sprite(node, dep_dict, resources_list, resource_check_dict); 63 | elif (node is CollisionShape2D): 64 | _add_resources_collision_shape2d(node, dep_dict, resources_list, resource_check_dict); 65 | elif (node is NavigationPolygonInstance): 66 | _add_resources_navigation_polygon_instance(node, dep_dict, resources_list, resource_check_dict); 67 | elif (node is Polygon2D): 68 | _add_resources_polygon2d(node, dep_dict, resources_list, resource_check_dict); 69 | elif (node is LightOccluder2D): 70 | _add_resources_light_occluder2d(node, dep_dict, resources_list, resource_check_dict); 71 | elif (node is TileMap): 72 | _add_resources_tilemap(node, dep_dict, resources_list, resource_check_dict); 73 | 74 | # *** All of the Control extending nodes *** 75 | if (node is Control): 76 | 77 | _add_resources_control(node, dep_dict, resources_list, resource_check_dict); 78 | 79 | if (node is TextureRect): 80 | _add_resources_texture_rect(node, dep_dict, resources_list, resource_check_dict); 81 | elif (node is VideoPlayer): 82 | _add_resources_video_player(node, dep_dict, resources_list, resource_check_dict); 83 | elif (node is NinePatchRect): 84 | _add_resources_nine_patch_rect(node, dep_dict, resources_list, resource_check_dict); 85 | elif (node is Button): 86 | _add_resources_button(node, dep_dict, resources_list, resource_check_dict); 87 | elif (node is TextureButton): 88 | _add_resources_texture_button(node, dep_dict, resources_list, resource_check_dict); 89 | 90 | # *** All of the Spatial extending nodes *** 91 | if (node is Spatial): 92 | 93 | _add_resources_spatial(node, dep_dict, resources_list, resource_check_dict); 94 | 95 | if (node is Camera): 96 | _add_resources_camera(node, dep_dict, resources_list, resource_check_dict); 97 | elif (node is CollisionShape): 98 | _add_resources_collision_shape(node, dep_dict, resources_list, resource_check_dict); 99 | elif (node is AudioStreamPlayer3D): 100 | _add_resources_audio_stream_player3d(node, dep_dict, resources_list, resource_check_dict); 101 | elif (node is Path): 102 | _add_resources_path(node, dep_dict, resources_list, resource_check_dict); 103 | elif (node is BakedLightmap): 104 | _add_resources_baked_lightmap(node, dep_dict, resources_list, resource_check_dict); 105 | elif (node is GIProbe): 106 | _add_resources_gi_probe(node, dep_dict, resources_list, resource_check_dict); 107 | 108 | elif (node is GeometryInstance): 109 | _add_resources_geometry_instance(node, dep_dict, resources_list, resource_check_dict); 110 | 111 | if (node is MultiMesh): 112 | _add_resources_multi_mesh(node, dep_dict, resources_list, resource_check_dict); 113 | elif (node is MeshInstance): 114 | _add_resources_mesh_instance(node, dep_dict, resources_list, resource_check_dict); 115 | elif (node is Particles): 116 | _add_resources_particles(node, dep_dict, resources_list, resource_check_dict); 117 | elif (node is AnimatedSprite3D): 118 | _add_resources_animated_sprite3d(node, dep_dict, resources_list, resource_check_dict); 119 | elif (node is Sprite3D): 120 | _add_resources_sprite3d(node, dep_dict, resources_list, resource_check_dict); 121 | 122 | elif (node is NavigationMeshInstance): 123 | _add_resources_navigation_mesh_instance(node, dep_dict, resources_list, resource_check_dict); 124 | elif (node is GridMap): 125 | _add_resources_grid_map(node, dep_dict, resources_list, resource_check_dict); 126 | 127 | 128 | # This will get the resources the node needs from the passed in resource list, 129 | # using the node's resource dictionary (presumably made with get_node_resource_dependencies_dict) 130 | # and will refill the node with the resources it needs. 131 | # 132 | # We will just edit/add-to the passed in dictionary (dep_dict) and list (resources_list) 133 | # directly. 134 | func load_node_resources_from_list(node, dep_dict, resources_list): 135 | 136 | var dep_dict_resources = dep_dict["DSCN_Dependencies"] 137 | 138 | # *** All of the base-type/basic nodes *** 139 | if (node is Node): 140 | _load_resources_node(node, dep_dict_resources, resources_list); 141 | if (node is CanvasItem): 142 | _load_resources_canvas_item(node, dep_dict_resources, resources_list); 143 | if (node is Viewport): 144 | _load_resources_viewport(node, dep_dict_resources, resources_list); 145 | if (node is AudioStreamPlayer): 146 | _load_resources_audio_stream_player(node, dep_dict_resources, resources_list); 147 | if (node is WorldEnvironment): 148 | _load_resources_world_environment(node, dep_dict_resources, resources_list); 149 | 150 | 151 | 152 | # *** All of the Node2D extending nodes *** 153 | if (node is Node2D): 154 | # Until there is a better way, we'll just do this manually in order of the 155 | # "Inheritied By" section of the documentation, found below: 156 | # http://docs.godotengine.org/en/3.0/classes/class_node2d.html? 157 | # 158 | # And then we'll add anything else that is missing! 159 | # The only nodes here are nodes that have resources to load. 160 | # Other nodes to not seem to have any resources to load. 161 | 162 | if (node is TouchScreenButton): 163 | _load_resources_touch_screen_button(node, dep_dict_resources, resources_list); 164 | elif (node is Particles2D): 165 | _load_resources_particles2d(node, dep_dict_resources, resources_list); 166 | elif (node is AnimatedSprite): 167 | _load_resources_animated_sprite(node, dep_dict_resources, resources_list); 168 | elif (node is Light2D): 169 | _load_resources_light2d(node, dep_dict_resources, resources_list); 170 | elif (node is Path2D): 171 | _load_resources_path2d(node, dep_dict_resources, resources_list); 172 | elif (node is Line2D): 173 | _load_resources_line2d(node, dep_dict_resources, resources_list); 174 | elif (node is AudioStreamPlayer2D): 175 | _load_resources_audio_stream_player2d(node, dep_dict_resources, resources_list); 176 | elif (node is Sprite): 177 | _load_resources_sprite(node, dep_dict_resources, resources_list); 178 | elif (node is CollisionShape2D): 179 | _load_resources_collision_shape2d(node, dep_dict_resources, resources_list); 180 | elif (node is NavigationPolygonInstance): 181 | _load_resources_navigation_polygon_instance(node, dep_dict_resources, resources_list); 182 | elif (node is Polygon2D): 183 | _load_resources_polygon2d(node, dep_dict_resources, resources_list); 184 | elif (node is LightOccluder2D): 185 | _load_resources_light_occluder2d(node, dep_dict_resources, resources_list); 186 | elif (node is TileMap): 187 | _load_resources_tilemap(node, dep_dict_resources, resources_list); 188 | 189 | # *** All of the Control extending nodes *** 190 | if (node is Control): 191 | 192 | _load_resources_control(node, dep_dict_resources, resources_list); 193 | 194 | if (node is TextureRect): 195 | _load_resources_texture_rect(node, dep_dict_resources, resources_list); 196 | elif (node is VideoPlayer): 197 | _load_resources_video_player(node, dep_dict_resources, resources_list); 198 | elif (node is NinePatchRect): 199 | _load_resources_nine_patch_rect(node, dep_dict_resources, resources_list); 200 | elif (node is Button): 201 | _load_resources_button(node, dep_dict_resources, resources_list); 202 | elif (node is TextureButton): 203 | _load_resources_texture_button(node, dep_dict_resources, resources_list); 204 | 205 | # *** All of the Spatial extending nodes *** 206 | if (node is Spatial): 207 | 208 | _load_resources_spatial(node, dep_dict_resources, resources_list); 209 | 210 | if (node is Camera): 211 | _load_resources_camera(node, dep_dict_resources, resources_list); 212 | elif (node is CollisionShape): 213 | _load_resources_collision_shape(node, dep_dict_resources, resources_list); 214 | elif (node is AudioStreamPlayer3D): 215 | _load_resources_audio_stream_player3d(node, dep_dict_resources, resources_list); 216 | elif (node is Path): 217 | _load_resources_path(node, dep_dict_resources, resources_list); 218 | elif (node is BakedLightmap): 219 | _load_resources_baked_lightmap(node, dep_dict_resources, resources_list); 220 | elif (node is GIProbe): 221 | _load_resources_gi_probe(node, dep_dict_resources, resources_list); 222 | elif (node is GeometryInstance): 223 | _load_resources_geometry_instance(node, dep_dict_resources, resources_list); 224 | 225 | if (node is MultiMesh): 226 | _load_resources_multi_mesh(node, dep_dict_resources, resources_list); 227 | elif (node is MeshInstance): 228 | _load_resources_mesh_instance(node, dep_dict_resources, resources_list); 229 | elif (node is Particles): 230 | _load_resources_particles(node, dep_dict_resources, resources_list); 231 | elif (node is AnimatedSprite3D): 232 | _load_resources_animated_sprite3d(node, dep_dict_resources, resources_list); 233 | elif (node is Sprite3D): 234 | _load_resources_sprite3d(node, dep_dict_resources, resources_list); 235 | 236 | elif (node is NavigationMeshInstance): 237 | _load_resources_navigation_mesh_instance(node, dep_dict_resources, resources_list); 238 | elif (node is GridMap): 239 | _load_resources_grid_map(node, dep_dict_resources, resources_list); 240 | 241 | # Load CUSTOM DATA in the node, if it has the following function: 242 | # DSCN_load_resources. 243 | if (node.has_method("DSCN_load_resources") == true): 244 | node.DSCN_custom_load_resources(node, dep_dict, resources_list); 245 | 246 | 247 | 248 | # ========================================== 249 | # ==== RESOURCE DEPENDENCY ADDING FUNCTIONS 250 | 251 | func _check_and_add_resource_to_list(resource, resources_list, resource_to_check_for=null, resource_check_dict=null): 252 | 253 | if (resource_to_check_for != null and resource_check_dict != null): 254 | if (resource_check_dict.has(resource_to_check_for) == true): 255 | return resource_check_dict[resource_to_check_for]; 256 | 257 | 258 | var find_result = resources_list.find(resource); 259 | 260 | if (find_result == -1): 261 | resources_list.append(resource); 262 | 263 | if (resource_to_check_for != null and resource_check_dict != null): 264 | resource_check_dict[resource_to_check_for] = resources_list.size()-1; 265 | 266 | return resources_list.size()-1; 267 | 268 | else: 269 | return find_result; 270 | 271 | 272 | func __add_resources_mesh(mesh, dep_dict, resources_list, resource_check_dict): 273 | 274 | if (mesh is PrimitiveMesh): 275 | if (mesh.material != null): 276 | if (mesh.material is ShaderMaterial): 277 | dep_dict["primitive_mesh_shader_material"] = _check_and_add_resource_to_list(mesh.material, resources_list); 278 | #mesh.material = null; 279 | 280 | elif (mesh.material is SpatialMaterial): 281 | dep_dict = __add_resources_spatial_material(mesh.material, dep_dict, resources_list, resource_check_dict); 282 | dep_dict["primitive_mesh_spatial_material"] = _check_and_add_resource_to_list(mesh.material, resources_list); 283 | #mesh.material = null; 284 | 285 | elif (mesh is ArrayMesh): 286 | var material_count = mesh.get_surface_count(); 287 | 288 | for i in range(0, material_count): 289 | var surface_material = mesh.surface_get_material(i); 290 | 291 | if (surface_material == null): 292 | continue; 293 | 294 | if (surface_material is SpatialMaterial): 295 | dep_dict = __add_resources_spatial_material(surface_material, dep_dict, resources_list, resource_check_dict, "_array_mesh_" + str(i)); 296 | 297 | dep_dict["array_mesh_material_" + str(i)] = _check_and_add_resource_to_list(surface_material, resources_list); 298 | #mesh.surface_set_material(i, null); 299 | 300 | dep_dict["array_mesh_surface_count"] = material_count; 301 | 302 | 303 | func __add_resources_spatial_material(material, dep_dict, resources_list, resource_check_dict, additional_string=""): 304 | 305 | if (material.albedo_texture != null): 306 | dep_dict["spatial_material_albedo_texture" + additional_string] = _check_and_add_resource_to_list( 307 | material.albedo_texture.get_data(), 308 | resources_list, 309 | material.albedo_texture, 310 | resource_check_dict); 311 | #material.albedo_texture = null; 312 | 313 | if (material.anisotropy_flowmap != null): 314 | dep_dict["spatial_material_anisotropy_flowmap" + additional_string] = _check_and_add_resource_to_list( 315 | material.anisotropy_flowmap.get_data(), 316 | resources_list, 317 | material.anisotropy_flowmap, 318 | resource_check_dict); 319 | #material.anisotropy_flowmap = null 320 | 321 | if (material.ao_texture != null): 322 | dep_dict["spatial_material_ao_texture" + additional_string] = _check_and_add_resource_to_list( 323 | material.ao_texture.get_data(), 324 | resources_list, 325 | material.ao_texture, 326 | resource_check_dict); 327 | #material.ao_texture = null 328 | 329 | if (material.clearcoat_texture != null): 330 | dep_dict["spatial_material_clearcoat_texture" + additional_string] = _check_and_add_resource_to_list( 331 | material.clearcoat_texture.get_data(), 332 | resources_list, 333 | material.clearcoat_texture, 334 | resource_check_dict); 335 | #material.clearcoat_texture = null 336 | 337 | if (material.depth_texture != null): 338 | dep_dict["spatial_material_depth_texture" + additional_string] = _check_and_add_resource_to_list( 339 | material.depth_texture.get_data(), 340 | resources_list, 341 | material.depth_texture, 342 | resource_check_dict); 343 | #material.depth_texture = null 344 | 345 | if (material.detail_albedo != null): 346 | dep_dict["spatial_material_detail_albedo" + additional_string] = _check_and_add_resource_to_list( 347 | material.detail_albedo.get_data(), 348 | resources_list, 349 | material.detail_albedo, 350 | resource_check_dict); 351 | #material.detail_albedo = null 352 | 353 | if (material.detail_mask != null): 354 | dep_dict["spatial_material_detail_mask" + additional_string] = _check_and_add_resource_to_list( 355 | material.detail_mask.get_data(), 356 | resources_list, 357 | material.detail_mask, 358 | resource_check_dict); 359 | #material.detail_mask = null 360 | 361 | if (material.detail_normal != null): 362 | dep_dict["spatial_material_detail_normal" + additional_string] = _check_and_add_resource_to_list( 363 | material.detail_normal.get_data(), 364 | resources_list, 365 | material.detail_normal, 366 | resource_check_dict); 367 | #material.detail_normal = null 368 | 369 | if (material.emission_texture != null): 370 | dep_dict["spatial_material_emission_texture" + additional_string] = _check_and_add_resource_to_list( 371 | material.emission_texture.get_data(), 372 | resources_list, 373 | material.emission_texture, 374 | resource_check_dict); 375 | #material.emission_texture = null 376 | 377 | if (material.metallic_texture != null): 378 | dep_dict["spatial_material_metallic_texture" + additional_string] = _check_and_add_resource_to_list( 379 | material.metallic_texture.get_data(), 380 | resources_list, 381 | material.metallic_texture, 382 | resource_check_dict); 383 | #material.metallic_texture = null 384 | 385 | if (material.normal_texture != null): 386 | dep_dict["spatial_material_normal_texture" + additional_string] = _check_and_add_resource_to_list( 387 | material.normal_texture.get_data(), 388 | resources_list, 389 | material.normal_texture, 390 | resource_check_dict); 391 | #material.normal_texture = null 392 | 393 | if (material.refraction_texture != null): 394 | dep_dict["spatial_material_refraction_texture" + additional_string] = _check_and_add_resource_to_list( 395 | material.refraction_texture.get_data(), 396 | resources_list, 397 | material.refraction_texture, 398 | resource_check_dict); 399 | #material.refraction_texture = null 400 | 401 | if (material.rim_texture != null): 402 | dep_dict["spatial_material_rim_texture" + additional_string] = _check_and_add_resource_to_list( 403 | material.rim_texture.get_data(), 404 | resources_list, 405 | material.rim_texture, 406 | resource_check_dict); 407 | #material.rim_texture = null 408 | 409 | if (material.roughness_texture != null): 410 | dep_dict["spatial_material_roughness_texture" + additional_string] = _check_and_add_resource_to_list( 411 | material.roughness_texture.get_data(), 412 | resources_list, 413 | material.roughness_texture, 414 | resource_check_dict); 415 | #material.roughness_texture = null 416 | 417 | if (material.subsurf_scatter_texture != null): 418 | dep_dict["spatial_material_subsurf_scatter_texture" + additional_string] = _check_and_add_resource_to_list( 419 | material.subsurf_scatter_texture.get_data(), 420 | resources_list, 421 | material.subsurf_scatter_texture, 422 | resource_check_dict); 423 | #material.subsurf_scatter_texture = null 424 | 425 | if (material.transmission_texture != null): 426 | dep_dict["spatial_material_transmission_texture" + additional_string] = _check_and_add_resource_to_list( 427 | material.transmission_texture.get_data(), 428 | resources_list, 429 | material.transmittion_texture, 430 | resource_check_dict); 431 | #material.transmission_texture = null 432 | 433 | return dep_dict; 434 | 435 | 436 | # == Node And Other Base Nodes 437 | 438 | func _add_resources_node(node, dep_dict, resources_list, resource_check_dict): 439 | # This will add the Node's resources. 440 | # Right now this adds the following: 441 | # script, groups 442 | 443 | if node.get_script() != null: 444 | dep_dict["script"] = _check_and_add_resource_to_list(node.get_script(), resources_list); 445 | 446 | var node_groups = node.get_groups(); 447 | if (node_groups.size() > 0): 448 | dep_dict["group_size"] = node_groups.size(); 449 | for i in range(0, node_groups.size()): 450 | dep_dict["group_id_" + str(i)] = node_groups[i]; 451 | 452 | 453 | func _add_resources_canvas_item(node, dep_dict, resources_list, resource_check_dict): 454 | # This will add the CanvasItem's resources. 455 | # Right now this adds the following: 456 | # material 457 | 458 | if node.material != null: 459 | dep_dict["material"] = _check_and_add_resource_to_list(node.material, resources_list); 460 | node.material = null; 461 | 462 | func _add_resources_viewport(node, dep_dict, resources_list, resource_check_dict): 463 | # This will add the Viewport's resources. 464 | # Right now this adds the following: 465 | # world, world_2d 466 | 467 | if (node.world != null): 468 | dep_dict["world"] = _check_and_add_resource_to_list(node.world, resources_list); 469 | node.world = null; 470 | 471 | if (node.world_2d != null): 472 | dep_dict["world_2d"] = _check_and_add_resource_to_list(node.world_2d, resources_list); 473 | node.world_2d = null; 474 | 475 | func _add_resources_audio_stream_player(node, dep_dict, resources_list, resource_check_dict): 476 | # This will add the AudioStreamPlayers's resources. 477 | # Right now this adds the following: 478 | # stream 479 | 480 | if (node.stream != null): 481 | dep_dict["stream"] = _check_and_add_resource_to_list(node.stream, resources_list); 482 | node.stream = null; 483 | 484 | func _add_resources_world_environment(node, dep_dict, resources_list, resource_check_dict): 485 | # This will add the WorldEnvironment's resources. 486 | # Right now this adds the following: 487 | # environment 488 | 489 | if (node.environment != null): 490 | dep_dict["environment"] = _check_and_add_resource_to_list(node.environment, resources_list); 491 | node.environment = null; 492 | 493 | # == Node2D (and Node2D extending) nodes 494 | 495 | func _add_resources_touch_screen_button(node, dep_dict, resources_list, resource_check_dict): 496 | # This will add the TouchScreenButton's basic resources. 497 | # Right now this adds the following: 498 | # Bitmask, Normal, Pressed, 499 | 500 | if (node.bitmask != null): 501 | dep_dict["bitmask"] = _check_and_add_resource_to_list(node.bitmask, resources_list); 502 | node.bitmask = null; 503 | 504 | if (node.normal != null): 505 | dep_dict["normal"] = _check_and_add_resource_to_list(node.normal.get_data(), resources_list, node.normal, resource_check_dict); 506 | node.normal = null; 507 | 508 | if (node.pressed != null): 509 | dep_dict["pressed"] = _check_and_add_resource_to_list(node.pressed.get_data(), resources_list, node.pressed, resource_check_dict); 510 | node.pressed = null; 511 | 512 | func _add_resources_particles2d(node, dep_dict, resources_list, resource_check_dict): 513 | # This will add the TouchScreenButton's basic resources. 514 | # Right now this adds the following: 515 | # Normal_map, process_material, texture, 516 | 517 | if (node.normal_map != null): 518 | dep_dict["normal_map"] = _check_and_add_resource_to_list(node.normal_map.get_data(), resources_list, node.normal_map, resource_check_dict); 519 | node.normal_map = null; 520 | 521 | if (node.process_material != null): 522 | dep_dict["process_material"] = _check_and_add_resource_to_list(node.process_material, resources_list); 523 | node.process_material = null; 524 | 525 | if (node.texture != null): 526 | dep_dict["texture"] = _check_and_add_resource_to_list(node.texture.get_data(), resources_list, node.texture, resource_check_dict); 527 | node.texture = null; 528 | 529 | func _add_resources_animated_sprite(node, dep_dict, resources_list, resource_check_dict): 530 | # This will add the AnimatedSprite's basic resources. 531 | # Right now this adds the following: 532 | # Frames 533 | 534 | if (node.frames != null): 535 | dep_dict["frames"] = _check_and_add_resource_to_list(node.frames, resources_list); 536 | node.frames = null; 537 | 538 | func _add_resources_light2d(node, dep_dict, resources_list, resource_check_dict): 539 | # This will add the Light2D's basic resources. 540 | # Right now this adds the following: 541 | # texture 542 | 543 | if (node.texture != null): 544 | dep_dict["texture"] = _check_and_add_resource_to_list(node.texture.get_data(), resources_list, node.texture, resource_check_dict); 545 | node.texture = null; 546 | 547 | func _add_resources_path2d(node, dep_dict, resources_list, resource_check_dict): 548 | # This will add the Path2D's basic resources. 549 | # Right now this adds the following: 550 | # curve 551 | 552 | if (node.curve != null): 553 | dep_dict["curve"] = _check_and_add_resource_to_list(node.curve, resources_list); 554 | node.curve = null; 555 | 556 | func _add_resources_line2d(node, dep_dict, resources_list, resource_check_dict): 557 | # This will add the Line2D's basic resources. 558 | # Right now this adds the following: 559 | # gradient, texture 560 | 561 | if (node.gradient != null): 562 | dep_dict["gradient"] = _check_and_add_resource_to_list(node.gradient, resources_list); 563 | node.gradient = null; 564 | 565 | if (node.texture != null): 566 | dep_dict["texture"] = _check_and_add_resource_to_list(node.texture.get_data(), resources_list, node.texture, resource_check_dict); 567 | node.texture = null; 568 | 569 | func _add_resources_audio_stream_player2d(node, dep_dict, resources_list, resource_check_dict): 570 | # This will add the Line2D's basic resources. 571 | # Right now this adds the following: 572 | # stream 573 | 574 | if (node.stream != null): 575 | dep_dict["stream"] = _check_and_add_resource_to_list(node.steam, resources_list); 576 | node.stream = null; 577 | 578 | func _add_resources_sprite(node, dep_dict, resources_list, resource_check_dict): 579 | # This will add the Sprite's resources. 580 | # Right now this adds the following: 581 | # Texture, Normal Map, 582 | 583 | if (node.texture != null): 584 | dep_dict["texture"] = _check_and_add_resource_to_list(node.texture.get_data(), resources_list, node.texture, resource_check_dict); 585 | node.texture = null; 586 | 587 | if (node.normal_map != null): 588 | dep_dict["normal_map"] = _check_and_add_resource_to_list(node.normal_map.get_data(), resources_list, node.normal_map, resource_check_dict); 589 | node.normal_map = null; 590 | 591 | func _add_resources_collision_shape2d(node, dep_dict, resources_list, resource_check_dict): 592 | # This will add the CollisionShape2D's resources. 593 | # Right now this adds the following: 594 | # shape, 595 | 596 | if (node.shape != null): 597 | dep_dict["shape"] = _check_and_add_resource_to_list(node.shape, resources_list); 598 | node.shape = null; 599 | 600 | func _add_resources_navigation_polygon_instance(node, dep_dict, resources_list, resource_check_dict): 601 | # This will add the NavigationPolygonInstance's resources. 602 | # Right now this adds the following: 603 | # navpoly, 604 | 605 | if (node.navpoly != null): 606 | dep_dict["navpoly"] = _check_and_add_resource_to_list(node.navpoly, resources_list); 607 | node.navpoly = null; 608 | 609 | func _add_resources_polygon2d(node, dep_dict, resources_list, resource_check_dict): 610 | # This will add the NavigationPolygonInstance's resources. 611 | # Right now this adds the following: 612 | # texure, 613 | 614 | if (node.texture != null): 615 | dep_dict["texture"] = _check_and_add_resource_to_list(node.texture.get_data(), resources_list, node.texture, resource_check_dict); 616 | node.texture = null; 617 | 618 | func _add_resources_light_occluder2d(node, dep_dict, resources_list, resource_check_dict): 619 | # This will add the LightOccluder2D's resources. 620 | # Right now this adds the following: 621 | # occluder, 622 | 623 | if (node.occluder != null): 624 | dep_dict["occluder"] = _check_and_add_resource_to_list(node.occluder, resources_list); 625 | node.occluder = null; 626 | 627 | func _add_resources_tilemap(node, dep_dict, resources_list, resource_check_dict): 628 | # This will add the TileMap's basic resources. 629 | # Right now this adds the following: 630 | # tile_set, 631 | 632 | # TODO: add tileset image saving/loading! 633 | 634 | if (node.tile_set != null): 635 | dep_dict["tile_set"] = _check_and_add_resource_to_list(node.tile_set, resources_list); 636 | node.tile_set = null; 637 | 638 | # == 639 | 640 | # == Control (and Control extending) nodes 641 | 642 | func _add_resources_control(node, dep_dict, resources_list, resource_check_dict): 643 | # This will add the Control's basic resources. 644 | # Right now this adds the following: 645 | # theme, 646 | 647 | if (node.theme != null): 648 | dep_dict["theme"] = _check_and_add_resource_to_list(node.theme, resources_list); 649 | node.theme = null; 650 | 651 | func _add_resources_texture_rect(node, dep_dict, resources_list, resource_check_dict): 652 | # This will add the TextureRect's basic resources. 653 | # Right now this adds the following: 654 | # texture, 655 | 656 | if (node.texture != null): 657 | dep_dict["texture"] = _check_and_add_resource_to_list(node.texture.get_data(), resources_list, node.texture, resource_check_dict); 658 | node.texture = null; 659 | 660 | func _add_resources_video_player(node, dep_dict, resources_list, resource_check_dict): 661 | # This will add the VideoPlayer's basic resources. 662 | # Right now this adds the following: 663 | # stream, 664 | 665 | if (node.stream != null): 666 | dep_dict["stream"] = _check_and_add_resource_to_list(node.stream, resources_list); 667 | node.stream = null; 668 | 669 | func _add_resources_nine_patch_rect(node, dep_dict, resources_list, resource_check_dict): 670 | # This will add the NinePathRect's basic resources. 671 | # Right now this adds the following: 672 | # texture, 673 | 674 | if (node.texture != null): 675 | dep_dict["texture"] = _check_and_add_resource_to_list(node.texture.get_data(), resources_list, node.texture, resource_check_dict); 676 | node.texture = null; 677 | 678 | func _add_resources_button(node, dep_dict, resources_list, resource_check_dict): 679 | # This will add the Buttons's basic resources. 680 | # Right now this adds the following: 681 | # icon, 682 | 683 | if (node.icon != null): 684 | dep_dict["icon"] = _check_and_add_resource_to_list(node.icon.get_data(), resources_list, node.icon, resource_check_dict); 685 | node.icon = null; 686 | 687 | func _add_resources_texture_button(node, dep_dict, resources_list, resource_check_dict): 688 | # This will add the NinePathRect's basic resources. 689 | # Right now this adds the following: 690 | # texture_click_mask, texture_disabled, 691 | # texture_focused, texture_hover, texture_normal, 692 | # texture_pressed, 693 | 694 | if (node.texture_click_mask != null): 695 | dep_dict["texture_click_mask"] = _check_and_add_resource_to_list(node.texture_click_mask, resources_list); 696 | node.texture_click_mask = null; 697 | 698 | if (node.texture_disabled != null): 699 | dep_dict["texture_disabled"] = _check_and_add_resource_to_list(node.texture_disabled.get_data(), resources_list, node.texture_disabled, resource_check_dict); 700 | node.texture_disabled = null; 701 | 702 | if (node.texture_focused != null): 703 | dep_dict["texture_focused"] = _check_and_add_resource_to_list(node.texture_focused.get_data(), resources_list, node.texture_focused, resource_check_dict); 704 | node.texture_focused = null; 705 | 706 | if (node.texture_hover != null): 707 | dep_dict["texture_hover"] = _check_and_add_resource_to_list(node.texture_hover.get_data(), resources_list, node.texture_hover, resource_check_dict); 708 | node.texture_hover = null; 709 | 710 | if (node.texture_normal != null): 711 | dep_dict["texture_normal"] = _check_and_add_resource_to_list(node.texture_normal.get_data(), resources_list, node.texture_normal, resource_check_dict); 712 | node.texture_normal = null; 713 | 714 | if (node.texture_pressed != null): 715 | dep_dict["texture_pressed"] = _check_and_add_resource_to_list(node.texture_pressed.get_data(), resources_list, node.texture_pressed, resource_check_dict); 716 | node.texture_pressed = null; 717 | 718 | # == 719 | 720 | # == Spatial (And Spatial extending) nodes 721 | 722 | func _add_resources_spatial(node, dep_dict, resources_list, resource_check_dict): 723 | # This will load the Spatial's basic resources. 724 | # Right now this loads the following: 725 | # gizmo 726 | 727 | if (node.gizmo != null): 728 | dep_dict["gizmo"] = _check_and_add_resource_to_list(node.gizmo, resources_list); 729 | node.gizmo = null; 730 | 731 | func _add_resources_camera(node, dep_dict, resources_list, resource_check_dict): 732 | # This will load the Canera's basic resources. 733 | # Right now this loads the following: 734 | # environment 735 | 736 | if (node.environment != null): 737 | dep_dict["environment"] = _check_and_add_resource_to_list(node.environment, resources_list); 738 | node.environment = null; 739 | 740 | func _add_resources_collision_shape(node, dep_dict, resources_list, resource_check_dict): 741 | # This will load the CollisionShape's basic resources. 742 | # Right now this loads the following: 743 | # shape 744 | 745 | if (node.shape != null): 746 | dep_dict["shape"] = _check_and_add_resource_to_list(node.shape, resources_list); 747 | node.shape = null; 748 | 749 | func _add_resources_audio_stream_player3d(node, dep_dict, resources_list, resource_check_dict): 750 | # This will load the AudioStreamPlayer3D's basic resources. 751 | # Right now this loads the following: 752 | # stream 753 | 754 | if (node.stream != null): 755 | dep_dict["stream"] = _check_and_add_resource_to_list(node.stream, resources_list); 756 | node.stream = null; 757 | 758 | func _add_resources_path(node, dep_dict, resources_list, resource_check_dict): 759 | # This will load the Path's basic resources. 760 | # Right now this loads the following: 761 | # curve 762 | 763 | if (node.curve != null): 764 | dep_dict["curve"] = _check_and_add_resource_to_list(node.curve, resources_list); 765 | node.curve = null; 766 | 767 | func _add_resources_baked_lightmap(node, dep_dict, resources_list, resource_check_dict): 768 | # This will load the BakedLightmap's basic resources. 769 | # Right now this loads the following: 770 | # light_data 771 | 772 | if (node.light_data != null): 773 | dep_dict["light_data"] = _check_and_add_resource_to_list(node.light_data, resources_list); 774 | node.light_data = null; 775 | 776 | func _add_resources_gi_probe(node, dep_dict, resources_list, resource_check_dict): 777 | # This will load the GIProbes's basic resources. 778 | # Right now this loads the following: 779 | # data 780 | 781 | if (node.data != null): 782 | dep_dict["data"] = _check_and_add_resource_to_list(node.data, resources_list); 783 | node.data = null; 784 | 785 | func _add_resources_geometry_instance(node, dep_dict, resources_list, resource_check_dict): 786 | # This will load the GeometryInstance's basic resources. 787 | # Right now this loads the following: 788 | # material_override (ShaderMaterial and SpatialMaterial) 789 | 790 | # TODO: support all nodes that have materials! 791 | 792 | if (node.material_override != null): 793 | 794 | if (node.material_override is SpatialMaterial): 795 | dep_dict = __add_resources_spatial_material(node.material_override, dep_dict, resources_list, resource_check_dict); 796 | dep_dict["material_override_spatial_material"] = _check_and_add_resource_to_list(node.material_override, resources_list); 797 | 798 | elif (node.material_override is ShaderMaterial): 799 | dep_dict["material_override_shader_material"] = _check_and_add_resource_to_list(node.material_override, resources_list); 800 | node.material_override = null; 801 | 802 | 803 | func _add_resources_multi_mesh(node, dep_dict, resources_list, resource_check_dict): 804 | # This will load the MultiMesh's basic resources. 805 | # Right now this loads the following: 806 | # mesh 807 | 808 | if (node.mesh != null): 809 | __add_resources_mesh(node.mesh, dep_dict, resources_list, resource_check_dict); 810 | dep_dict["mesh"] = _check_and_add_resource_to_list(node.mesh, resources_list); 811 | node.mesh = null; 812 | 813 | func _add_resources_mesh_instance(node, dep_dict, resources_list, resource_check_dict): 814 | # This will load the MeshInstance's basic resources. 815 | # Right now this loads the following: 816 | # mesh 817 | 818 | # TODO: support get_surface_material and set_surface_material materials! 819 | 820 | if (node.mesh != null): 821 | __add_resources_mesh(node.mesh, dep_dict, resources_list, resource_check_dict); 822 | dep_dict["mesh"] = _check_and_add_resource_to_list(node.mesh, resources_list); 823 | node.mesh = null; 824 | 825 | func _add_resources_particles(node, dep_dict, resources_list, resource_check_dict): 826 | # This will load the Particles's basic resources. 827 | # Right now this loads the following: 828 | # draw_pass_1, draw_pass_2, draw_pass_3, draw_pass_4, 829 | # process_material 830 | 831 | if (node.draw_pass_1 != null): 832 | __add_resources_mesh(node.draw_pass_1, dep_dict, resources_list, resource_check_dict); 833 | dep_dict["draw_pass_1"] = _check_and_add_resource_to_list(node.draw_pass_1, resources_list); 834 | node.draw_pass_1 = null; 835 | 836 | if (node.draw_pass_2 != null): 837 | __add_resources_mesh(node.draw_pass_2, dep_dict, resources_list, resource_check_dict); 838 | dep_dict["draw_pass_2"] = _check_and_add_resource_to_list(node.draw_pass_2, resources_list); 839 | node.draw_pass_2 = null; 840 | 841 | if (node.draw_pass_3 != null): 842 | __add_resources_mesh(node.draw_pass_3, dep_dict, resources_list, resource_check_dict); 843 | dep_dict["draw_pass_3"] = _check_and_add_resource_to_list(node.draw_pass_3, resources_list); 844 | node.draw_pass_3 = null; 845 | 846 | if (node.draw_pass_4 != null): 847 | __add_resources_mesh(node.draw_pass_4, dep_dict, resources_list, resource_check_dict); 848 | dep_dict["draw_pass_4"] = _check_and_add_resource_to_list(node.draw_pass_4, resources_list); 849 | node.draw_pass_4 = null; 850 | 851 | if (node.process_material != null): 852 | dep_dict["process_material"] = _check_and_add_resource_to_list(node.process_material, resources_list); 853 | node.process_material = null; 854 | 855 | func _add_resources_animated_sprite3d(node, dep_dict, resources_list, resource_check_dict): 856 | # This will load the AnimatedSprite3D's basic resources. 857 | # Right now this loads the following: 858 | # frames 859 | 860 | if (node.frames != null): 861 | dep_dict["frames"] = _check_and_add_resource_to_list(node.frames, resources_list); 862 | node.frames = null; 863 | 864 | func _add_resources_sprite3d(node, dep_dict, resources_list, resource_check_dict): 865 | # This will load the Sprite3D's basic resources. 866 | # Right now this loads the following: 867 | # texture 868 | 869 | if (node.texture != null): 870 | dep_dict["texture"] = _check_and_add_resource_to_list(node.texture.get_data(), resources_list, node.texture, resource_check_dict); 871 | node.texture = null; 872 | 873 | func _add_resources_navigation_mesh_instance(node, dep_dict, resources_list, resource_check_dict): 874 | # This will load the NavigationMeshInstance's basic resources. 875 | # Right now this loads the following: 876 | # navmesh 877 | 878 | if (node.navmesh != null): 879 | dep_dict["navmesh"] = _check_and_add_resource_to_list(node.navmesh, resources_list); 880 | node.navmesh = null; 881 | 882 | func _add_resources_grid_map(node, dep_dict, resources_list, resource_check_dict): 883 | # This will load the GridMap's basic resources. 884 | # Right now this loads the following: 885 | # theme, (with mesh materials!) 886 | 887 | if (node.theme != null): 888 | var theme_list = node.theme.get_item_list(); 889 | 890 | for i in range(0, theme_list.size()): 891 | 892 | var theme_mesh = node.theme.get_item_mesh(i); 893 | if (theme_mesh != null): 894 | __add_resources_mesh(theme_mesh, dep_dict, resources_list, resource_check_dict); 895 | dep_dict["grid_map_theme_mesh_" + str(i)] = _check_and_add_resource_to_list(theme_mesh, resources_list); 896 | 897 | var theme_name = node.theme.get_item_name(i); 898 | if (theme_name != null): 899 | dep_dict["grid_map_theme_name_" + str(i)] = theme_name; 900 | 901 | var theme_navmesh = node.theme.get_item_navmesh(i); 902 | if (theme_navmesh != null): 903 | dep_dict["grid_map_theme_navmesh_" + str(i)] = _check_and_add_resource_to_list(theme_navmesh, resources_list); 904 | 905 | var theme_preview = node.theme.get_item_preview(i); 906 | if (theme_preview != null): 907 | dep_dict["grid_map_theme_preview_" + str(i)] = _check_and_add_resource_to_list(theme_preview.get_data(), resources_list, theme_preview, resource_check_dict); 908 | 909 | var theme_shapes = node.theme.get_item_shapes(i); 910 | if (theme_shapes.size() > 0): 911 | dep_dict["grid_map_theme_shape_size_" + str(i)] = theme_shapes.size(); 912 | for j in range(0, theme_shapes.size()): 913 | dep_dict["grid_map_theme_shape_" + str(i) + str(j)] = _check_and_add_resource_to_list(theme_shapes[j], resources_list); 914 | 915 | dep_dict["grid_map_theme_size"] = theme_list.size(); 916 | 917 | """ 918 | if (node.theme != null): 919 | dep_dict["theme"] = _check_and_add_resource_to_list(node.theme, resources_list); 920 | node.theme = null; 921 | """ 922 | 923 | # == 924 | 925 | # ========================================== 926 | 927 | 928 | 929 | 930 | # ========================================== 931 | # ==== RESOURCE DEPENDENCY LOADING FUNCTIONS 932 | 933 | func _get_resource_from_dep_dict(resource_name, dep_dict, resources_list): 934 | return resources_list[dep_dict[resource_name]]; 935 | 936 | func _get_resource_into_image(image_data): 937 | image_data.setup_local_to_scene(); 938 | image_data.resource_local_to_scene = true; 939 | 940 | var img = ImageTexture.new(); 941 | img.create_from_image(image_data); 942 | 943 | img.setup_local_to_scene(); 944 | img.resource_local_to_scene = true; 945 | 946 | return img; 947 | 948 | 949 | func __load_resources_mesh(mesh, dep_dict, resources_list): 950 | 951 | if (mesh is PrimitiveMesh): 952 | if (dep_dict.has("primitive_mesh_shader_material") == true): 953 | mesh.material = _get_resource_from_dep_dict("primitive_mesh_shader_material", dep_dict, resources_list); 954 | if (dep_dict.has("primitive_mesh_spatial_material") == true): 955 | mesh.material = _get_resource_from_dep_dict("primitive_mesh_spatial_material", dep_dict, resources_list); 956 | __load_resources_spatial_material(mesh.material, dep_dict, resources_list); 957 | 958 | elif (mesh is ArrayMesh): 959 | if (dep_dict.has("array_mesh_surface_count") == true): 960 | # Get the surface count 961 | var surface_count = int(dep_dict["array_mesh_surface_count"]); 962 | 963 | for i in range(0, surface_count): 964 | if (dep_dict.has("array_mesh_material_" + str(i)) == true): 965 | var surface_material = _get_resource_from_dep_dict("array_mesh_material_" + str(i), dep_dict, resources_list); 966 | 967 | if (surface_material is SpatialMaterial): 968 | __load_resources_spatial_material(surface_material, dep_dict, resources_list, "_array_mesh_" + str(i)); 969 | 970 | mesh.surface_set_material(i, surface_material); 971 | 972 | else: 973 | mesh.surface_set_material(i, null); 974 | 975 | 976 | func __load_resources_spatial_material(material, dep_dict, resources_list, additional_string=""): 977 | 978 | if (dep_dict.has("spatial_material_albedo_texture" + additional_string) == true): 979 | var img_data = _get_resource_from_dep_dict("spatial_material_albedo_texture" + additional_string, dep_dict, resources_list); 980 | material.albedo_texture = _get_resource_into_image(img_data); 981 | 982 | if (dep_dict.has("spatial_material_anisotropy_flowmap" + additional_string) == true): 983 | var img_data = _get_resource_from_dep_dict("spatial_material_anisotropy_flowmap" + additional_string, dep_dict, resources_list); 984 | material.anisotropy_flowmap = _get_resource_into_image(img_data); 985 | 986 | if (dep_dict.has("spatial_material_ao_texture" + additional_string) == true): 987 | var img_data = _get_resource_from_dep_dict("spatial_material_ao_texture" + additional_string, dep_dict, resources_list); 988 | material.ao_texture = _get_resource_into_image(img_data); 989 | 990 | if (dep_dict.has("spatial_material_clearcoat_texture" + additional_string) == true): 991 | var img_data = _get_resource_from_dep_dict("spatial_material_clearcoat_texture" + additional_string, dep_dict, resources_list); 992 | material.clearcoat_texture = _get_resource_into_image(img_data); 993 | 994 | if (dep_dict.has("spatial_material_depth_texture" + additional_string) == true): 995 | var img_data = _get_resource_from_dep_dict("spatial_material_depth_texture" + additional_string, dep_dict, resources_list); 996 | material.depth_texture = _get_resource_into_image(img_data); 997 | 998 | if (dep_dict.has("spatial_material_detail_albedo" + additional_string) == true): 999 | var img_data = _get_resource_from_dep_dict("spatial_material_detail_albedo" + additional_string, dep_dict, resources_list); 1000 | material.detail_albedo = _get_resource_into_image(img_data); 1001 | 1002 | if (dep_dict.has("spatial_material_detail_mask" + additional_string) == true): 1003 | var img_data = _get_resource_from_dep_dict("spatial_material_detail_mask" + additional_string, dep_dict, resources_list); 1004 | material.detail_mask = _get_resource_into_image(img_data); 1005 | 1006 | if (dep_dict.has("spatial_material_detail_normal" + additional_string) == true): 1007 | var img_data = _get_resource_from_dep_dict("spatial_material_detail_normal" + additional_string, dep_dict, resources_list); 1008 | material.detail_normal = _get_resource_into_image(img_data); 1009 | 1010 | if (dep_dict.has("spatial_material_emission_texture" + additional_string) == true): 1011 | var img_data = _get_resource_from_dep_dict("spatial_material_emission_texture" + additional_string, dep_dict, resources_list); 1012 | material.emission_texture = _get_resource_into_image(img_data); 1013 | 1014 | if (dep_dict.has("spatial_material_metallic_texture" + additional_string) == true): 1015 | var img_data = _get_resource_from_dep_dict("spatial_material_metallic_texture" + additional_string, dep_dict, resources_list); 1016 | material.metallic_texture = _get_resource_into_image(img_data); 1017 | 1018 | if (dep_dict.has("spatial_material_normal_texture" + additional_string) == true): 1019 | var img_data = _get_resource_from_dep_dict("spatial_material_normal_texture" + additional_string, dep_dict, resources_list); 1020 | material.normal_texture = _get_resource_into_image(img_data); 1021 | 1022 | if (dep_dict.has("spatial_material_refraction_texture" + additional_string) == true): 1023 | var img_data = _get_resource_from_dep_dict("spatial_material_refraction_texture" + additional_string, dep_dict, resources_list); 1024 | material.refraction_texture = _get_resource_into_image(img_data); 1025 | 1026 | if (dep_dict.has("spatial_material_rim_texture" + additional_string) == true): 1027 | var img_data = _get_resource_from_dep_dict("spatial_material_rim_texture" + additional_string, dep_dict, resources_list); 1028 | material.rim_texture = _get_resource_into_image(img_data); 1029 | 1030 | if (dep_dict.has("spatial_material_roughness_texture" + additional_string) == true): 1031 | var img_data = _get_resource_from_dep_dict("spatial_material_roughness_texture" + additional_string, dep_dict, resources_list); 1032 | material.roughness_texture = _get_resource_into_image(img_data); 1033 | 1034 | if (dep_dict.has("spatial_material_subsurf_scatter_texture" + additional_string) == true): 1035 | var img_data = _get_resource_from_dep_dict("spatial_material_subsurf_scatter_texture" + additional_string, dep_dict, resources_list); 1036 | material.subsurf_scatter_texture = _get_resource_into_image(img_data); 1037 | 1038 | if (dep_dict.has("spatial_material_transmission_texture" + additional_string) == true): 1039 | var img_data = _get_resource_from_dep_dict("spatial_material_transmission_texture" + additional_string, dep_dict, resources_list); 1040 | material.transmission_texture = _get_resource_into_image(img_data); 1041 | 1042 | 1043 | # == Node And Other Base Nodes 1044 | 1045 | func _load_resources_node(node, dep_dict, resources_list): 1046 | # This will load the Node's resources. 1047 | # Right now this loads the following: 1048 | # script, groups 1049 | 1050 | if (dep_dict.has("script") == true): 1051 | node.set_script(_get_resource_from_dep_dict("script", dep_dict, resources_list)); 1052 | 1053 | if (dep_dict.has("group_size") == true): 1054 | var node_group_size = dep_dict["group_size"]; 1055 | for i in range(0, node_group_size): 1056 | if (dep_dict.has("group_id_" + str(i)) == true): 1057 | node.add_to_group(dep_dict["group_id_" + str(i)], true); 1058 | 1059 | func _load_resources_canvas_item(node, dep_dict, resources_list): 1060 | # This will load the CanvasItem's resources. 1061 | # Right now this loads the following: 1062 | # Material 1063 | 1064 | if (dep_dict.has("material") == true): 1065 | node.material = _get_resource_from_dep_dict("material", dep_dict, resources_list); 1066 | 1067 | func _load_resources_viewport(node, dep_dict, resources_list): 1068 | # This will load the Viewport's resources. 1069 | # Right now this loads the following: 1070 | # world, world_2d 1071 | 1072 | if (dep_dict.has("world") == true): 1073 | node.world = _get_resource_from_dep_dict("world", dep_dict, resources_list); 1074 | if (dep_dict.has("world_2d") == true): 1075 | node.world_2d = _get_resource_from_dep_dict("world_2d", dep_dict, resources_list); 1076 | 1077 | func _load_resources_audio_stream_player(node, dep_dict, resources_list): 1078 | # This will load the AudioStreamPlayers's resources. 1079 | # Right now this loads the following: 1080 | # stream 1081 | 1082 | if (dep_dict.has("stream") == true): 1083 | node.stream = _get_resource_from_dep_dict("stream", dep_dict, resources_list); 1084 | 1085 | func _load_resources_world_environment(node, dep_dict, resources_list): 1086 | # This will load the WorldEnvironment's resources. 1087 | # Right now this loads the following: 1088 | # environment 1089 | 1090 | if (dep_dict.has("environment") == true): 1091 | node.environment = _get_resource_from_dep_dict("environment", dep_dict, resources_list); 1092 | 1093 | # == Node2D And Extending Nodes 1094 | 1095 | func _load_resources_touch_screen_button(node, dep_dict, resources_list): 1096 | # This will load the TouchScreenButton's basic resources. 1097 | # Right now this loads the following: 1098 | # bitmask, normal, pressed, 1099 | 1100 | if (dep_dict.has["bitmask"] == true): 1101 | node.bitmask = _get_resource_from_dep_dict("bitmask", dep_dict, resources_list); 1102 | if (dep_dict.has["normal"] == true): 1103 | var img_data = _get_resource_from_dep_dict("normal", dep_dict, resources_list); 1104 | node.normal = _get_resource_into_image(img_data); 1105 | if (dep_dict.has["pressed"] == true): 1106 | var img_data = _get_resource_from_dep_dict("pressed", dep_dict, resources_list); 1107 | node.pressed = _get_resource_into_image(img_data); 1108 | 1109 | func _load_resources_particles2d(node, dep_dict, resources_list): 1110 | # This will load the TouchScreenButton's basic resources. 1111 | # Right now this loads the following: 1112 | # normal_map, process_material, texture, 1113 | 1114 | if (dep_dict.has("normal_map") == true): 1115 | var img_data = _get_resource_from_dep_dict("normal_map", dep_dict, resources_list); 1116 | node.normal_map = _get_resource_into_image(img_data); 1117 | if (dep_dict.has("process_material") == true): 1118 | node.process_material = _get_resource_from_dep_dict("process_material", dep_dict, resources_list); 1119 | if (dep_dict.has("texture") == true): 1120 | var img_data = _get_resource_from_dep_dict("texture", dep_dict, resources_list); 1121 | node.texture = _get_resource_into_image(img_data); 1122 | 1123 | func _load_resources_animated_sprite(node, dep_dict, resources_list): 1124 | # This will load the AnimatedSprite's basic resources. 1125 | # Right now this loads the following: 1126 | # frames 1127 | 1128 | if (dep_dict.has["frames"] == true): 1129 | node.frames = _get_resource_from_dep_dict("frames", dep_dict, resources_list); 1130 | 1131 | func _load_resources_light2d(node, dep_dict, resources_list): 1132 | # This will load the Light2D's basic resources. 1133 | # Right now this loads the following: 1134 | # texture 1135 | 1136 | if (dep_dict.has("texture") == true): 1137 | var img_data = _get_resource_from_dep_dict("texture", dep_dict, resources_list); 1138 | node.texture = _get_resource_into_image(img_data); 1139 | 1140 | func _load_resources_path2d(node, dep_dict, resources_list): 1141 | # This will load the Path2D's basic resources. 1142 | # Right now this loads the following: 1143 | # curve 1144 | 1145 | if (dep_dict.has("curve") == true): 1146 | node.curve = _get_resource_from_dep_dict("curve", dep_dict, resources_list); 1147 | 1148 | func _load_resources_line2d(node, dep_dict, resources_list): 1149 | # This will load the Line2D's basic resources. 1150 | # Right now this loads the following: 1151 | # gradient, texture 1152 | 1153 | if (dep_dict.has["gradient"] == true): 1154 | node.gradient = _get_resource_from_dep_dict("gradient", dep_dict, resources_list); 1155 | if (dep_dict.has("texture") == true): 1156 | var img_data = _get_resource_from_dep_dict("texture", dep_dict, resources_list); 1157 | node.texture = _get_resource_into_image(img_data); 1158 | 1159 | func _load_resources_audio_stream_player2d(node, dep_dict, resources_list): 1160 | # This will load the Line2D's basic resources. 1161 | # Right now this loads the following: 1162 | # stream 1163 | 1164 | if (dep_dict.has("stream") == true): 1165 | node.stream = _get_resource_from_dep_dict("stream", dep_dict, resources_list); 1166 | 1167 | func _load_resources_sprite(node, dep_dict, resources_list): 1168 | # This will load the Sprite's resources. 1169 | # Right now this loads the following: 1170 | # texture, Normal Map, 1171 | 1172 | if (dep_dict.has("texture") == true): 1173 | var img_data = _get_resource_from_dep_dict("texture", dep_dict, resources_list); 1174 | node.texture = _get_resource_into_image(img_data); 1175 | if (dep_dict.has("normal_map") == true): 1176 | var img_data = _get_resource_from_dep_dict("normal_map", dep_dict, resources_list); 1177 | node.texture = _get_resource_into_image(img_data); 1178 | 1179 | func _load_resources_collision_shape2d(node, dep_dict, resources_list): 1180 | # This will load the CollisionShape2D's resources. 1181 | # Right now this loads the following: 1182 | # shape, 1183 | 1184 | if (dep_dict.has("shape") == true): 1185 | node.shape = _get_resource_from_dep_dict("shape", dep_dict, resources_list); 1186 | 1187 | func _load_resources_navigation_polygon_instance(node, dep_dict, resources_list): 1188 | # This will load the NavigationPolygonInstance's resources. 1189 | # Right now this loads the following: 1190 | # navpoly, 1191 | 1192 | if (dep_dict.has("navpoly") == true): 1193 | node.navpoly = _get_resource_from_dep_dict("navpoly", dep_dict, resources_list); 1194 | 1195 | func _load_resources_polygon2d(node, dep_dict, resources_list): 1196 | # This will load the NavigationPolygonInstance's resources. 1197 | # Right now this loads the following: 1198 | # texure, 1199 | 1200 | if (dep_dict.has("texture") == true): 1201 | var img_data = _get_resource_from_dep_dict("texture", dep_dict, resources_list); 1202 | node.texture = _get_resource_into_image(img_data); 1203 | 1204 | func _load_resources_light_occluder2d(node, dep_dict, resources_list): 1205 | # This will load the LightOccluder2D's resources. 1206 | # Right now this loads the following: 1207 | # occluder, 1208 | 1209 | if (dep_dict.has("occluder") == true): 1210 | node.occluder = _get_resource_from_dep_dict("occluder", dep_dict, resources_list); 1211 | 1212 | func _load_resources_tilemap(node, dep_dict, resources_list): 1213 | # This will load the TileMap's basic resources. 1214 | # Right now this loads the following: 1215 | # tile_set, 1216 | 1217 | if (dep_dict.has("tile_set") == true): 1218 | node.tile_set = _get_resource_from_dep_dict("tile_set", dep_dict, resources_list); 1219 | 1220 | # == 1221 | 1222 | # == Control And Extending Nodes 1223 | 1224 | func _load_resources_control(node, dep_dict, resources_list): 1225 | # This will load the Control's basic resources. 1226 | # Right now this loads the following: 1227 | # theme, 1228 | 1229 | if (dep_dict.has("theme") == true): 1230 | node.theme = _get_resource_from_dep_dict("theme", dep_dict, resources_list); 1231 | 1232 | func _load_resources_texture_rect(node, dep_dict, resources_list): 1233 | # This will load the TextureRect's basic resources. 1234 | # Right now this loads the following: 1235 | # texture, 1236 | 1237 | if (dep_dict.has("texture") == true): 1238 | var img_data = _get_resource_from_dep_dict("texture", dep_dict, resources_list); 1239 | node.texture = _get_resource_into_image(img_data); 1240 | 1241 | func _load_resources_video_player(node, dep_dict, resources_list): 1242 | # This will load the VideoPlayer's basic resources. 1243 | # Right now this loads the following: 1244 | # stream, 1245 | 1246 | if (dep_dict.has("stream") == true): 1247 | node.stream = _get_resource_from_dep_dict("stream", dep_dict, resources_list); 1248 | 1249 | func _load_resources_nine_patch_rect(node, dep_dict, resources_list): 1250 | # This will load the NinePathRect's basic resources. 1251 | # Right now this loads the following: 1252 | # texture, 1253 | 1254 | if (dep_dict.has("texture") == true): 1255 | var img_data = _get_resource_from_dep_dict("texture", dep_dict, resources_list); 1256 | node.texture = _get_resource_into_image(img_data); 1257 | 1258 | func _load_resources_button(node, dep_dict, resources_list): 1259 | # This will load the Buttons's basic resources. 1260 | # Right now this loads the following: 1261 | # icon, 1262 | 1263 | if (dep_dict.has("icon") == true): 1264 | var img_data = _get_resource_from_dep_dict("icon", dep_dict, resources_list); 1265 | node.icon = _get_resource_into_image(img_data); 1266 | 1267 | func _load_resources_texture_button(node, dep_dict, resources_list): 1268 | # This will load the NinePathRect's basic resources. 1269 | # Right now this loads the following: 1270 | # texture_click_mask, texture_disabled, 1271 | # texture_focused, texture_hover, texture_normal, 1272 | # texture_pressed, 1273 | 1274 | if (dep_dict.has("texture_click_mask") == true): 1275 | var img_data = _get_resource_from_dep_dict("texture_click_mask", dep_dict, resources_list); 1276 | node.texture_click_mask = _get_resource_into_image(img_data); 1277 | 1278 | if (dep_dict.has("texture_disabled") == true): 1279 | var img_data = _get_resource_from_dep_dict("texture_disabled", dep_dict, resources_list); 1280 | node.texture_disabled = _get_resource_into_image(img_data); 1281 | 1282 | if (dep_dict.has("texture_focused") == true): 1283 | var img_data = _get_resource_from_dep_dict("texture_focused", dep_dict, resources_list); 1284 | node.texture_focused = _get_resource_into_image(img_data); 1285 | 1286 | if (dep_dict.has("texture_hover") == true): 1287 | var img_data = _get_resource_from_dep_dict("texture_hover", dep_dict, resources_list); 1288 | node.texture_hover = _get_resource_into_image(img_data); 1289 | 1290 | if (dep_dict.has("texture_normal") == true): 1291 | var img_data = _get_resource_from_dep_dict("texture_normal", dep_dict, resources_list); 1292 | node.texture_normal = _get_resource_into_image(img_data); 1293 | 1294 | if (dep_dict.has("texture_pressed") == true): 1295 | var img_data = _get_resource_from_dep_dict("texture_pressed", dep_dict, resources_list); 1296 | node.texture_pressed = _get_resource_into_image(img_data); 1297 | 1298 | # == 1299 | 1300 | # == Spatial (And Spatial extending) nodes 1301 | 1302 | func _load_resources_spatial(node, dep_dict, resources_list): 1303 | # This will load the Spatial's basic resources. 1304 | # Right now this loads the following: 1305 | # gizmo 1306 | 1307 | if (dep_dict.has("gizmo") == true): 1308 | node.gizmo = _get_resource_from_dep_dict("gizmo", dep_dict, resources_list); 1309 | 1310 | func _load_resources_camera(node, dep_dict, resources_list): 1311 | # This will load the Camera's basic resources. 1312 | # Right now this loads the following: 1313 | # environment 1314 | 1315 | if (dep_dict.has("environment") == true): 1316 | node.environment = _get_resource_from_dep_dict("environment", dep_dict, resources_list); 1317 | 1318 | func _load_resources_collision_shape(node, dep_dict, resources_list): 1319 | # This will load the CollisionShape's basic resources. 1320 | # Right now this loads the following: 1321 | # shape 1322 | 1323 | if (dep_dict.has("shape") == true): 1324 | node.shape = _get_resource_from_dep_dict("shape", dep_dict, resources_list); 1325 | 1326 | func _load_resources_audio_stream_player3d(node, dep_dict, resources_list): 1327 | # This will load the AudioStreamPlayer3D's basic resources. 1328 | # Right now this loads the following: 1329 | # stream 1330 | 1331 | if (dep_dict.has("stream") == true): 1332 | node.stream = _get_resource_from_dep_dict("stream", dep_dict, resources_list); 1333 | 1334 | func _load_resources_path(node, dep_dict, resources_list): 1335 | # This will load the Path's basic resources. 1336 | # Right now this loads the following: 1337 | # curve 1338 | 1339 | if (dep_dict.has("curve") == true): 1340 | node.curve = _get_resource_from_dep_dict("curve", dep_dict, resources_list); 1341 | 1342 | func _load_resources_baked_lightmap(node, dep_dict, resources_list): 1343 | # This will load the BakedLightmap's basic resources. 1344 | # Right now this loads the following: 1345 | # light_data 1346 | 1347 | if (dep_dict.has("light_data") == true): 1348 | node.light_data = _get_resource_from_dep_dict("light_data", dep_dict, resources_list); 1349 | 1350 | func _load_resources_gi_probe(node, dep_dict, resources_list): 1351 | # This will load the GIProbe's basic resources. 1352 | # Right now this loads the following: 1353 | # data 1354 | 1355 | if (dep_dict.has("data") == true): 1356 | node.data = _get_resource_from_dep_dict("data", dep_dict, resources_list); 1357 | 1358 | func _load_resources_geometry_instance(node, dep_dict, resources_list): 1359 | # This will load the GeometryInstance's basic resources. 1360 | # Right now this loads the following: 1361 | # material_override (ShaderMaterial and SpatialMaterial) 1362 | 1363 | if (dep_dict.has("material_override_shader_material") == true): 1364 | node.material_override = _get_resource_from_dep_dict("material_override_shader_material", dep_dict, resources_list); 1365 | elif (dep_dict.has("material_override_spatial_material") == true): 1366 | node.material_override = _get_resource_from_dep_dict("material_override_spatial_material", dep_dict, resources_list); 1367 | __load_resources_spatial_material(node.material_override, dep_dict, resources_list); 1368 | 1369 | 1370 | func _load_resources_multi_mesh(node, dep_dict, resources_list): 1371 | # This will load the MultiMesh's basic resources. 1372 | # Right now this loads the following: 1373 | # mesh 1374 | 1375 | if (dep_dict.has("mesh") == true): 1376 | node.mesh = _get_resource_from_dep_dict("mesh", dep_dict, resources_list); 1377 | __load_resources_mesh(node.mesh, dep_dict, resources_list); 1378 | 1379 | func _load_resources_mesh_instance(node, dep_dict, resources_list): 1380 | # This will load the MeshInstance's basic resources. 1381 | # Right now this loads the following: 1382 | # mesh 1383 | 1384 | if (dep_dict.has("mesh") == true): 1385 | node.mesh = _get_resource_from_dep_dict("mesh", dep_dict, resources_list); 1386 | __load_resources_mesh(node.mesh, dep_dict, resources_list); 1387 | 1388 | func _load_resources_particles(node, dep_dict, resources_list): 1389 | # This will load the Particles's basic resources. 1390 | # Right now this loads the following: 1391 | # draw_pass_1, draw_pass_2, draw_pass_3, draw_pass_4, 1392 | #process_material 1393 | 1394 | if (dep_dict.has("draw_pass_1") == true): 1395 | node.draw_pass_1 = _get_resource_from_dep_dict("draw_pass_1", dep_dict, resources_list); 1396 | 1397 | if (dep_dict.has("draw_pass_2") == true): 1398 | node.draw_pass_2 = _get_resource_from_dep_dict("draw_pass_2", dep_dict, resources_list); 1399 | 1400 | if (dep_dict.has("draw_pass_3") == true): 1401 | node.draw_pass_3 = _get_resource_from_dep_dict("draw_pass_3", dep_dict, resources_list); 1402 | 1403 | if (dep_dict.has("draw_pass_4") == true): 1404 | node.draw_pass_4 = _get_resource_from_dep_dict("draw_pass_4", dep_dict, resources_list); 1405 | 1406 | if (dep_dict.has("process_material") == true): 1407 | node.process_material = _get_resource_from_dep_dict("process_material", dep_dict, resources_list); 1408 | 1409 | func _load_resources_animated_sprite3d(node, dep_dict, resources_list): 1410 | # This will load the AnimatedSprite3D's basic resources. 1411 | # Right now this loads the following: 1412 | # frames 1413 | 1414 | if (dep_dict.has("frames") == true): 1415 | node.frames = _get_resource_from_dep_dict("frames", dep_dict, resources_list); 1416 | 1417 | func _load_resources_sprite3d(node, dep_dict, resources_list): 1418 | # This will load the Sprite3D's basic resources. 1419 | # Right now this loads the following: 1420 | # texture 1421 | 1422 | if (dep_dict.has("texture") == true): 1423 | var img_data = _get_resource_from_dep_dict("texture", dep_dict, resources_list); 1424 | node.texture = _get_resource_into_image(img_data); 1425 | 1426 | func _load_resources_navigation_mesh_instance(node, dep_dict, resources_list): 1427 | # This will load the NavigationMeshInstance's basic resources. 1428 | # Right now this loads the following: 1429 | # navmesh 1430 | 1431 | if (dep_dict.has("navmesh") == true): 1432 | node.navmesh = _get_resource_from_dep_dict("navmesh", dep_dict, resources_list); 1433 | 1434 | func _load_resources_grid_map(node, dep_dict, resources_list): 1435 | # This will load the GridMap's basic resources. 1436 | # Right now this loads the following: 1437 | # theme 1438 | 1439 | if (dep_dict.has("grid_map_theme_size") != null): 1440 | var grid_map_theme = MeshLibrary.new(); 1441 | var theme_list_size = dep_dict["grid_map_theme_size"]; 1442 | 1443 | for i in range(0, theme_list_size): 1444 | grid_map_theme.create_item(i); 1445 | 1446 | if (dep_dict.has("grid_map_theme_mesh_" + str(i)) == true): 1447 | var theme_mesh = _get_resource_from_dep_dict("grid_map_theme_mesh_" + str(i), dep_dict, resources_list); 1448 | __load_resources_mesh(theme_mesh, dep_dict, resources_list); 1449 | grid_map_theme.set_item_mesh(i, theme_mesh); 1450 | 1451 | if (dep_dict.has("grid_map_theme_name_" + str(i)) == true): 1452 | grid_map_theme.set_item_name(i, dep_dict["grid_map_theme_name_" + str(i)]); 1453 | 1454 | if (dep_dict.has("grid_map_theme_navmesh_" + str(i)) == true): 1455 | grid_map_theme.set_item_navmesh(i, _get_resource_from_dep_dict("grid_map_theme_navmesh_" + str(i), dep_dict, resources_list)); 1456 | 1457 | if (dep_dict.has("grid_map_theme_preview_" + str(i)) == true): 1458 | var img_data = _get_resource_from_dep_dict("grid_map_theme_preview_" + str(i), dep_dict, resources_list); 1459 | grid_map_theme.set_item_preview(i, _get_resource_into_image(img_data)); 1460 | 1461 | if (dep_dict.has("grid_map_theme_shape_size_" + str(i)) == true): 1462 | var theme_shape_size = dep_dict["grid_map_theme_shape_size_" + str(i)]; 1463 | var theme_shape_array = []; 1464 | 1465 | for j in range(0, theme_shape_size): 1466 | theme_shape_array.append(_get_resource_from_dep_dict("grid_map_theme_shape_" + str(i) + str(j), dep_dict, resources_list)); 1467 | 1468 | grid_map_theme.set_item_shapes(i, theme_shape_array); 1469 | 1470 | node.theme = grid_map_theme; 1471 | 1472 | """ 1473 | if (dep_dict.has("theme") == true): 1474 | node.theme = _get_resource_from_dep_dict("theme", dep_dict, resources_list); 1475 | """ 1476 | 1477 | # == 1478 | 1479 | # ========================================== 1480 | 1481 | --------------------------------------------------------------------------------