[
  {
    "path": ".gitattributes",
    "content": "# Normalize EOL for all files that Git considers text files.\n* text=auto eol=lf\n\n# Ignore everything outside of the addons folder when exporting.\n/.github                   export-ignore\n/.gitattributes            export-ignore\n/.gitignore                export-ignore\n/file_format.sh            export-ignore\n/icon.png                  export-ignore\n/icon.png.import           export-ignore\n/LICENSE.md                export-ignore\n/project.godot             export-ignore\n/README.md                 export-ignore\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n"
  },
  {
    "path": ".github/workflows/static_checks.yml",
    "content": "name: 📊 Static Checks\non: [push, pull_request]\n\njobs:\n  format:\n    name: File formatting (file_format.sh)\n    runs-on: ubuntu-20.04\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Install dependencies\n        run: |\n          sudo apt-get update -qq\n          sudo apt-get install -qq dos2unix recode\n\n      - name: File formatting checks (file_format.sh)\n        run: |\n          bash ./file_format.sh\n"
  },
  {
    "path": ".gitignore",
    "content": "# Godot 4+ specific ignores\n.godot/\n\n# Godot-specific ignores\n.import/\nexport.cfg\nexport_presets.cfg\n\n# Imported translations (automatically generated from CSV files)\n*.translation\n\n# Mono-specific ignores\n.mono/\ndata_*/\nmono_crash.*.json\n\n# System/tool-specific ignores\n.directory\n*~\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018-2021 Will Nations\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# godot-plugin-refresher\n\nThis plugin simplifies plugin development for those wanting to make tools for the Godot Editor.\n\n> The `master` branch supports Godot 4.2+. For Godot 4.0-4.1, see the `4.0` branch. For Godot 3, see the `3.x` branch.\n\nThe plugin adds a dropdown and refresh button to the main toolbar in the top-right corner of the Godot Editor. *Other* plugins' names will show up in the dropdown. Clicking the refresh button will toggle the plugin off and then back on. Disabled plugins still appear in the list & be toggleable (effectively just enabling them), but will ask to confirm beforehand.\n\nHere's an example of working on a WIP internal \"GodotTools\" plugin amidst an in-development project:\n\n![example of dropdown](./example_dropdown.png)\n\nThis makes it much easier to iterate on a single plugin since rather than having to...\n\n1. Click Project Settings.\n2. Go to Plugins tab (first time).\n3. Find the desired plugin.\n4. Click the dropdown.\n5. Select the opposite option.\n6. Click the dropdown again.\n7. Click the original option.\n8. Close the Project Settings.\n\nYou instead just...\n\n1. Click the dropdown (first time).\n2. Select your WIP plugin (first time).\n3. Click the refresh button.\n\nPlease consider starring the repo if you like the project and let me know if you have any feedback for bugs / feature improvements in the Issues. If you'd like to support my work, please [send tips to my Kofi](https://ko-fi.com/willnationsdev). Cheers!\n"
  },
  {
    "path": "addons/godot-plugin-refresher/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018-2021 Will Nations\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "addons/godot-plugin-refresher/plugin.cfg",
    "content": "[plugin]\n\nname=\"Godot Plugin Refresher\"\ndescription=\"A toolbar addition to facilitate toggling off/on a selected plugin. Updated for Godot 4.3\"\nauthor=\"willnationsdev\"\nversion=\"1.2\"\nscript=\"plugin_refresher_plugin.gd\"\n"
  },
  {
    "path": "addons/godot-plugin-refresher/plugin_refresher.gd",
    "content": "@tool\nextends HBoxContainer\n\nsignal request_refresh_plugin(p_name: String)\nsignal confirm_refresh_plugin(p_name: String)\n\n@onready var options: OptionButton = $OptionButton\n\n\nfunc _ready() -> void:\n\tif get_tree().edited_scene_root == self:\n\t\treturn # This is the scene opened in the editor!\n\t$RefreshButton.icon = EditorInterface.get_editor_theme().get_icon(\"Reload\", \"EditorIcons\")\n\n\nfunc update_items(p_plugins_info: Array) -> void:\n\tif not options:\n\t\treturn\n\toptions.clear()\n\n\tvar plugins := p_plugins_info[0] as Dictionary\n\tvar display_names_map := p_plugins_info[1] as Dictionary\n\n\tvar plugin_dirs: Array[String] = []\n\tplugin_dirs.assign(plugins.keys())\n\tfor idx in plugin_dirs.size():\n\t\tvar plugin_dirname := plugin_dirs[idx]\n\t\tvar plugin_data = plugins[plugin_dirname] # Array[String] used as a Tuple<String, String>.\n\t\tvar plugin_name := plugin_data[0] as String\n\t\tvar plugin_path := plugin_data[1] as String\n\t\tvar display_name := display_names_map[plugin_path] as String\n\n\t\toptions.add_item(display_name, idx)\n\t\toptions.set_item_metadata(idx, plugin_path)\n\n\n# Note: For whatever reason, statically typing `p_name` inexplicably causes\n# an error about converting from Nil to String, even if the value is converted.\nfunc select_plugin(p_name) -> void:\n\tif not options or not p_name:\n\t\treturn\n\n\tfor idx in options.get_item_count():\n\t\tvar plugin := str(options.get_item_metadata(idx))\n\t\tif plugin == str(p_name):\n\t\t\toptions.selected = options.get_item_id(idx)\n\t\t\tbreak\n\n\nfunc _on_RefreshButton_pressed() -> void:\n\tif options.selected == -1:\n\t\treturn # nothing selected\n\n\tvar plugin := str(options.get_item_metadata(options.selected))\n\tif not plugin:\n\t\treturn\n\temit_signal(\"request_refresh_plugin\", plugin)\n\n\nfunc show_warning(p_name: String) -> void:\n\t$ConfirmationDialog.dialog_text = (\n\t\t\"\"\"\n\t\tPlugin `%s` is currently disabled.\\n\n\t\tDo you want to enable it now?\n\t\"\"\"\n\t\t% [p_name]\n\t)\n\t$ConfirmationDialog.popup_centered()\n\n\nfunc _on_ConfirmationDialog_confirmed() -> void:\n\tvar plugin := options.get_item_metadata(options.selected) as String\n\temit_signal(\"confirm_refresh_plugin\", plugin)\n"
  },
  {
    "path": "addons/godot-plugin-refresher/plugin_refresher.tscn",
    "content": "[gd_scene load_steps=2 format=3 uid=\"uid://dnladpgp5dwts\"]\n\n[ext_resource type=\"Script\" path=\"res://addons/godot-plugin-refresher/plugin_refresher.gd\" id=\"1\"]\n\n[node name=\"HBoxContainer\" type=\"HBoxContainer\"]\nscript = ExtResource(\"1\")\n\n[node name=\"VSeparator\" type=\"VSeparator\" parent=\".\"]\nlayout_mode = 2\n\n[node name=\"OptionButton\" type=\"OptionButton\" parent=\".\"]\nlayout_mode = 2\n\n[node name=\"RefreshButton\" type=\"Button\" parent=\".\"]\nlayout_mode = 2\n\n[node name=\"ConfirmationDialog\" type=\"ConfirmationDialog\" parent=\".\"]\ndialog_autowrap = true\n\n[connection signal=\"pressed\" from=\"RefreshButton\" to=\".\" method=\"_on_RefreshButton_pressed\"]\n[connection signal=\"confirmed\" from=\"ConfirmationDialog\" to=\".\" method=\"_on_ConfirmationDialog_confirmed\"]\n"
  },
  {
    "path": "addons/godot-plugin-refresher/plugin_refresher_plugin.gd",
    "content": "@tool\nextends EditorPlugin\n\nconst ADDONS_PATH := \"res://addons/\"\nconst PLUGIN_CONFIG_DIR := \"plugins/plugin_refresher\"\nconst PLUGIN_CONFIG := \"settings.cfg\"\nconst PLUGIN_NAME := \"Godot Plugin Refresher\"\nconst SETTINGS := \"settings\"\nconst SETTING_RECENT := \"recently_used\"\nconst Refresher := preload(\"plugin_refresher.gd\")\n\nvar plugin_config := ConfigFile.new()\nvar refresher: Refresher = null\n\n\nfunc _enter_tree() -> void:\n\trefresher = preload(\"plugin_refresher.tscn\").instantiate() as Refresher\n\tadd_control_to_container(CONTAINER_TOOLBAR, refresher)\n\n\t# Watch whether any plugin is changed, added or removed on the filesystem\n\tvar efs := EditorInterface.get_resource_filesystem()\n\tefs.filesystem_changed.connect(_on_filesystem_changed)\n\n\trefresher.request_refresh_plugin.connect(_on_request_refresh_plugin)\n\trefresher.confirm_refresh_plugin.connect(_on_confirm_refresh_plugin)\n\n\t_reload_plugins_list()\n\t_load_settings()\n\n\nfunc _exit_tree() -> void:\n\tremove_control_from_container(CONTAINER_TOOLBAR, refresher)\n\trefresher.free()\n\n\nfunc _reload_plugins_list() -> void:\n\tvar cfg_paths: Array[String] = []\n\tvar plugins := {}\n\tvar display_names_map := {} # full path to display name\n\n\tfind_cfgs(ADDONS_PATH, cfg_paths)\n\n\tfor cfg_path in cfg_paths:\n\t\tvar plugin_cfg := ConfigFile.new()\n\t\tvar err := plugin_cfg.load(cfg_path)\n\t\tif err:\n\t\t\tpush_error(\"ERROR LOADING PLUGIN FILE: %s\" % err)\n\t\telse:\n\t\t\tvar plugin_name := plugin_cfg.get_value(\"plugin\", \"name\")\n\t\t\tif plugin_name != PLUGIN_NAME:\n\t\t\t\tvar addon_dir_name = cfg_path.split(\"addons/\")[-1].split(\"/plugin.cfg\")[0]\n\t\t\t\tplugins[addon_dir_name] = [plugin_name, cfg_path]\n\n\t# This will be an array of the addon/* directory names.\n\tvar plugin_dirs: Array[String] = []\n\tplugin_dirs.assign(plugins.keys()) # typed array \"casting\"\n\n\tvar plugin_names: Array[String] = []\n\tplugin_names.assign(plugin_dirs.map(func(k): return plugins[k][0]))\n\n\tfor plugin_dirname in plugin_dirs:\n\t\tvar plugin_name = plugins[plugin_dirname][0]\n\t\tvar display_name = plugin_name if plugin_names.count(plugin_name) == 1 else \"%s (%s)\" % [plugin_name, plugin_dirname]\n\t\tdisplay_names_map[plugins[plugin_dirname][1]] = display_name\n\n\trefresher.update_items([plugins, display_names_map])\n\n\nfunc find_cfgs(dir_path: String, cfgs: Array):\n\tvar dir := DirAccess.open(dir_path)\n\tvar cfg_path := dir_path.path_join(\"plugin.cfg\")\n\n\tif dir.file_exists(cfg_path):\n\t\tcfgs.append(cfg_path)\n\t\treturn\n\n\tif dir:\n\t\tdir.list_dir_begin()\n\t\tvar file_name := dir.get_next()\n\t\twhile file_name != \"\":\n\t\t\tif dir.current_is_dir():\n\t\t\t\tfind_cfgs(dir_path.path_join(file_name), cfgs)\n\t\t\tfile_name = dir.get_next()\n\n\nfunc _load_settings() -> void:\n\tvar path := get_settings_path()\n\n\tif not FileAccess.file_exists(path):\n\t\t# Create new if running for the first time\n\t\tvar config := ConfigFile.new()\n\t\tDirAccess.make_dir_recursive_absolute(path.get_base_dir())\n\t\tconfig.save(path)\n\telse:\n\t\tplugin_config.load(path)\n\n\nfunc _save_settings() -> void:\n\tplugin_config.save(get_settings_path())\n\n\nfunc get_settings_path() -> String:\n\tvar editor_paths := EditorInterface.get_editor_paths()\n\tvar dir := editor_paths.get_project_settings_dir()\n\n\tvar home := dir.path_join(PLUGIN_CONFIG_DIR)\n\tvar path := home.path_join(PLUGIN_CONFIG)\n\n\treturn path\n\n\nfunc _on_filesystem_changed() -> void:\n\tif refresher:\n\t\t_reload_plugins_list()\n\t\tvar recent = get_recent_plugin()\n\t\tif recent:\n\t\t\trefresher.select_plugin(recent)\n\n\nfunc get_recent_plugin() -> String:\n\tif not plugin_config.has_section_key(SETTINGS, SETTING_RECENT):\n\t\treturn \"\" # not saved yet\n\n\tvar recent = str(plugin_config.get_value(SETTINGS, SETTING_RECENT))\n\treturn recent\n\n\nfunc _on_request_refresh_plugin(p_path: String) -> void:\n\tassert(not p_path.is_empty())\n\n\tvar disabled := not EditorInterface.is_plugin_enabled(p_path)\n\tif disabled:\n\t\trefresher.show_warning(p_path)\n\telse:\n\t\trefresh_plugin(p_path)\n\n\nfunc _on_confirm_refresh_plugin(p_path: String) -> void:\n\trefresh_plugin(p_path)\n\n\nfunc get_plugin_path() -> String:\n\treturn get_script().resource_path.get_base_dir()\n\n\nfunc refresh_plugin(p_path: String) -> void:\n\tprint(\"Refreshing plugin: \", p_path)\n\n\tvar enabled := EditorInterface.is_plugin_enabled(p_path)\n\tif enabled: # can only disable an active plugin\n\t\tEditorInterface.set_plugin_enabled(p_path, false)\n\n\tEditorInterface.set_plugin_enabled(p_path, true)\n\n\tplugin_config.set_value(SETTINGS, SETTING_RECENT, p_path)\n\t_save_settings()\n"
  },
  {
    "path": "file_format.sh",
    "content": "#!/usr/bin/env bash\n\n# This script ensures proper POSIX text file formatting and a few other things.\n\nset -uo pipefail\nIFS=$'\\n\\t'\n\n# Loops through all text files tracked by Git.\ngit grep -zIl '' |\nwhile IFS= read -rd '' f; do\n    # Ensure that files are UTF-8 formatted.\n    recode UTF-8 \"$f\" 2> /dev/null\n    # Ensure that files have LF line endings and do not contain a BOM.\n    dos2unix \"$f\" 2> /dev/null\n    # Remove trailing space characters and ensures that files end\n    # with newline characters. -l option handles newlines conveniently.\n    perl -i -ple 's/\\s*$//g' \"$f\"\n    # Remove the character sequence \"== true\" if it has a leading space.\n    perl -i -pe 's/\\x20== true//g' \"$f\"\ndone\n\ngit diff > patch.patch\nFILESIZE=\"$(stat -c%s patch.patch)\"\nMAXSIZE=5\n\n# If no patch has been generated all is OK, clean up, and exit.\nif (( FILESIZE < MAXSIZE )); then\n    printf \"Files in this commit comply with the formatting rules.\\n\"\n    rm -f patch.patch\n    exit 0\nfi\n\n# A patch has been created, notify the user, clean up, and exit.\nprintf \"\\n*** The following differences were found between the code \"\nprintf \"and the formatting rules:\\n\\n\"\ncat patch.patch\nprintf \"\\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\\n\"\nrm -f patch.patch\nexit 1\n"
  },
  {
    "path": "icon.png.import",
    "content": "[remap]\n\nimporter=\"texture\"\ntype=\"CompressedTexture2D\"\nuid=\"uid://c1hfjj7vmjkda\"\npath=\"res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex\"\nmetadata={\n\"vram_texture\": false\n}\n\n[deps]\n\nsource_file=\"res://icon.png\"\ndest_files=[\"res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex\"]\n\n[params]\n\ncompress/mode=0\ncompress/high_quality=false\ncompress/lossy_quality=0.7\ncompress/hdr_compression=1\ncompress/normal_map=0\ncompress/channel_pack=0\nmipmaps/generate=false\nmipmaps/limit=-1\nroughness/mode=0\nroughness/src_normal=\"\"\nprocess/fix_alpha_border=true\nprocess/premult_alpha=false\nprocess/normal_map_invert_y=false\nprocess/hdr_as_srgb=false\nprocess/hdr_clamp_exposure=false\nprocess/size_limit=0\ndetect_3d/compress_to=1\n"
  },
  {
    "path": "project.godot",
    "content": "; Engine configuration file.\n; It's best edited using the editor UI and not directly,\n; since the parameters that go here are not all obvious.\n;\n; Format:\n;   [section] ; section goes between []\n;   param=value ; assign values to parameters\n\nconfig_version=5\n\n[application]\n\nconfig/name=\"Godot Plugin Refresher\"\nrun/main_scene=\"res://addons/godot-plugin-refresher/plugin_refresher.tscn\"\nconfig/features=PackedStringArray(\"4.3\")\nconfig/icon=\"res://icon.png\"\n\n[dotnet]\n\nproject/assembly_name=\"Godot Plugin Refresher\"\n\n[editor_plugins]\n\nenabled=PackedStringArray(\"res://addons/godot-plugin-refresher/plugin.cfg\")\n\n[input]\n\nui_accept={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n, Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n, Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n, Object(InputEventJoypadButton,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"button_index\":0,\"pressure\":0.0,\"pressed\":false,\"script\":null)\n]\n}\nui_select={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n, Object(InputEventJoypadButton,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"button_index\":3,\"pressure\":0.0,\"pressed\":false,\"script\":null)\n]\n}\nui_cancel={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n, Object(InputEventJoypadButton,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"button_index\":1,\"pressure\":0.0,\"pressed\":false,\"script\":null)\n]\n}\nui_focus_next={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n]\n}\nui_focus_prev={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n]\n}\nui_left={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n, Object(InputEventJoypadButton,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"button_index\":14,\"pressure\":0.0,\"pressed\":false,\"script\":null)\n]\n}\nui_right={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n, Object(InputEventJoypadButton,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"button_index\":15,\"pressure\":0.0,\"pressed\":false,\"script\":null)\n]\n}\nui_up={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n, Object(InputEventJoypadButton,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"button_index\":12,\"pressure\":0.0,\"pressed\":false,\"script\":null)\n]\n}\nui_down={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n, Object(InputEventJoypadButton,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"button_index\":13,\"pressure\":0.0,\"pressed\":false,\"script\":null)\n]\n}\nui_page_up={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n]\n}\nui_page_down={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n]\n}\nui_home={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n]\n}\nui_end={\n\"deadzone\": 0.5,\n\"events\": [Object(InputEventKey,\"resource_local_to_scene\":false,\"resource_name\":\"\",\"device\":0,\"window_id\":0,\"alt_pressed\":false,\"shift_pressed\":false,\"ctrl_pressed\":false,\"meta_pressed\":false,\"pressed\":false,\"keycode\":0,\"physical_keycode\":0,\"key_label\":0,\"unicode\":0,\"location\":0,\"echo\":false,\"script\":null)\n]\n}\n\n[rendering]\n\nquality/driver/driver_name=\"GLES2\"\nvram_compression/import_etc=true\nvram_compression/import_etc2=false\n"
  }
]