forked from joey/godottest
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
007a45d543 | ||
|
|
9732bf52ff |
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -11,5 +11,6 @@
|
|||||||
"color": "default"
|
"color": "default"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"VsCodeTaskButtons.showCounter": false
|
"VsCodeTaskButtons.showCounter": false,
|
||||||
|
"rust-analyzer.checkOnSave": true
|
||||||
}
|
}
|
||||||
|
|||||||
5
Justfile
Normal file
5
Justfile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
test:
|
||||||
|
RUST_BACKTRACE=1 godot --path godot res://tests/test_runner.tscn -- --quiet-run
|
||||||
|
|
||||||
|
bench:
|
||||||
|
RUST_BACKTRACE=1 godot --path godot res://tests/test_runner.tscn -- --bench
|
||||||
@ -1,3 +1,9 @@
|
|||||||
# godottest
|
# godottest
|
||||||
|
|
||||||
messing around with godot and rust
|
messing around with godot and rust
|
||||||
|
|
||||||
|
## run tests
|
||||||
|
|
||||||
|
```sh
|
||||||
|
RUST_BACKTRACE=1 godot --path godot res://tests/test_runner.tscn -- --quiet-run
|
||||||
|
```
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
[configuration]
|
[configuration]
|
||||||
entry_symbol = "gdext_rust_init"
|
entry_symbol = "gdext_rust_init"
|
||||||
compatibility_minimum = 4.1
|
compatibility_minimum = 4.1
|
||||||
|
reloadable = true
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
"android.debug" = "res://../rust/target/debug/godottest_rs.so"
|
"android.debug" = "res://../rust/target/debug/godottest_rs.so"
|
||||||
@ -65,6 +66,6 @@ compatibility_minimum = 4.1
|
|||||||
"windows.editor.x86_64" = "res://../rust/target/x86_64-pc-windows-msvc/debug/godottest_rs.dll"
|
"windows.editor.x86_64" = "res://../rust/target/x86_64-pc-windows-msvc/debug/godottest_rs.dll"
|
||||||
|
|
||||||
[icons]
|
[icons]
|
||||||
AsyncRuntime = "res://addons/rust/NodeRustFerris.svg"
|
|
||||||
Player = "res://addons/rust/NodeRustFerris.svg"
|
Player = "res://addons/rust/NodeRustFerris.svg"
|
||||||
|
AsyncRuntime = "res://addons/rust/NodeRustFerris.svg"
|
||||||
Mappy = "res://addons/rust/NodeRustFerris.svg"
|
Mappy = "res://addons/rust/NodeRustFerris.svg"
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
uid://dx7md3kauujl
|
uid://yljs7ohq1dqw
|
||||||
|
|||||||
20
godot/addons/panku_console/LICENSE
Normal file
20
godot/addons/panku_console/LICENSE
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2023 Feo (k2kra) Wu
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
1
godot/addons/panku_console/README.md
Normal file
1
godot/addons/panku_console/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
This repository is a mirror that tracks the latest version of [PankuConsole](https://github.com/Ark2000/PankuConsole), so you can add it as a submodule in you addons folder.
|
||||||
35
godot/addons/panku_console/common/buffered_rich_text.gd
Normal file
35
godot/addons/panku_console/common/buffered_rich_text.gd
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
extends VBoxContainer
|
||||||
|
|
||||||
|
# it is like, an infinite scroll game.
|
||||||
|
|
||||||
|
# specifically, the first buffer will be cleared and sent to the last
|
||||||
|
# when the last buffer is full.
|
||||||
|
|
||||||
|
# with buffers, we can constanly output lots of fancy stuff while keeping a smooth experience.
|
||||||
|
|
||||||
|
const BUFFER_MAX_PARAGRAPHS = 64
|
||||||
|
const BUFFERS = 4
|
||||||
|
|
||||||
|
var cur_label_idx:int = 0
|
||||||
|
|
||||||
|
func add_text(text:String):
|
||||||
|
var cur_label:RichTextLabel = get_child(cur_label_idx)
|
||||||
|
cur_label.text += text
|
||||||
|
if cur_label.get_paragraph_count() > BUFFER_MAX_PARAGRAPHS:
|
||||||
|
cur_label_idx += 1
|
||||||
|
if cur_label_idx == BUFFERS:
|
||||||
|
cur_label_idx = BUFFERS - 1
|
||||||
|
var first_label:RichTextLabel = get_child(0)
|
||||||
|
first_label.text = ""
|
||||||
|
move_child(first_label, BUFFERS - 1)
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
set("theme_override_constants/separation", 0)
|
||||||
|
for child in get_children():
|
||||||
|
child.queue_free()
|
||||||
|
for i in range(BUFFERS):
|
||||||
|
var new_buffer:RichTextLabel = RichTextLabel.new()
|
||||||
|
new_buffer.fit_content = true
|
||||||
|
new_buffer.bbcode_enabled = true
|
||||||
|
new_buffer.selection_enabled = true
|
||||||
|
add_child(new_buffer)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://hxsdaekjx5k0
|
||||||
126
godot/addons/panku_console/common/config.gd
Normal file
126
godot/addons/panku_console/common/config.gd
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
class_name PankuConfig
|
||||||
|
|
||||||
|
const CONFIG_SECTION = "panku"
|
||||||
|
const OPTIONS = {
|
||||||
|
# See https://github.com/Ark2000/PankuConsole/issues/170
|
||||||
|
DISABLE_ON_RELEASE = 'disable_on_release',
|
||||||
|
# See https://github.com/Ark2000/PankuConsole/issues/173
|
||||||
|
CUSTOM_DEFAULT_CONFIG = 'custom_default_config',
|
||||||
|
}
|
||||||
|
|
||||||
|
const INITIAL_DEFAULT_CONFIG_FILE_PATH = "res://addons/panku_console/default_panku_config.cfg"
|
||||||
|
const USER_CONFIG_FILE_PATH = "user://panku_config.cfg"
|
||||||
|
|
||||||
|
|
||||||
|
# Full option name in project settings.
|
||||||
|
static func panku_option(option: String) -> String:
|
||||||
|
return CONFIG_SECTION + "/" + option
|
||||||
|
|
||||||
|
|
||||||
|
# A helper function to add custom project settings
|
||||||
|
# See https://dfaction.net/handling-custom-project-settings-using-gdscript/
|
||||||
|
static func add_custom_project_setting(
|
||||||
|
name: String,
|
||||||
|
default_value,
|
||||||
|
type: int,
|
||||||
|
hint: int = PROPERTY_HINT_NONE, hint_string: String = ""
|
||||||
|
) -> void:
|
||||||
|
if ProjectSettings.has_setting(name): return
|
||||||
|
|
||||||
|
var setting_info: Dictionary = {
|
||||||
|
"name": name,
|
||||||
|
"type": type,
|
||||||
|
"hint": hint,
|
||||||
|
"hint_string": hint_string
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectSettings.set_setting(name, default_value)
|
||||||
|
ProjectSettings.add_property_info(setting_info)
|
||||||
|
ProjectSettings.set_initial_value(name, default_value)
|
||||||
|
ProjectSettings.set_as_basic(name, true)
|
||||||
|
|
||||||
|
|
||||||
|
static func init_all_project_settings() -> void:
|
||||||
|
# Seems we can't add descriptions to custom settings now.
|
||||||
|
|
||||||
|
# Disable Panku Console in release builds
|
||||||
|
add_custom_project_setting(
|
||||||
|
panku_option(OPTIONS.DISABLE_ON_RELEASE),
|
||||||
|
false,
|
||||||
|
TYPE_BOOL
|
||||||
|
)
|
||||||
|
|
||||||
|
# Path to the custom
|
||||||
|
# `res://` path default config file, useful if you are going to keep panku console in release builds.
|
||||||
|
add_custom_project_setting(
|
||||||
|
panku_option(OPTIONS.CUSTOM_DEFAULT_CONFIG),
|
||||||
|
INITIAL_DEFAULT_CONFIG_FILE_PATH,
|
||||||
|
TYPE_STRING,
|
||||||
|
PROPERTY_HINT_FILE,
|
||||||
|
"*.cfg"
|
||||||
|
)
|
||||||
|
|
||||||
|
# save_project_settings()
|
||||||
|
|
||||||
|
|
||||||
|
static func clear_all_project_settings() -> void:
|
||||||
|
for option in OPTIONS.values():
|
||||||
|
var opt: String = panku_option(option)
|
||||||
|
if ProjectSettings.has_setting(opt):
|
||||||
|
ProjectSettings.clear(opt)
|
||||||
|
|
||||||
|
save_project_settings()
|
||||||
|
|
||||||
|
|
||||||
|
static func save_project_settings() -> void:
|
||||||
|
var error: int = ProjectSettings.save()
|
||||||
|
if error != OK:
|
||||||
|
push_error("Encountered error %d when saving project settings." % error)
|
||||||
|
|
||||||
|
|
||||||
|
# Get custom config file path from project settings
|
||||||
|
static func get_custom_default_config_path() -> String:
|
||||||
|
return ProjectSettings.get_setting(panku_option(OPTIONS.CUSTOM_DEFAULT_CONFIG), INITIAL_DEFAULT_CONFIG_FILE_PATH)
|
||||||
|
|
||||||
|
# Check if custom config file from project settings exist
|
||||||
|
static func is_custom_default_config_exists() -> bool:
|
||||||
|
return FileAccess.file_exists(get_custom_default_config_path())
|
||||||
|
|
||||||
|
|
||||||
|
# load config from file, always return a dictionary
|
||||||
|
static func _get_config(file_path:String) -> Dictionary:
|
||||||
|
if FileAccess.file_exists(file_path):
|
||||||
|
var file = FileAccess.open(file_path, FileAccess.READ)
|
||||||
|
var content := file.get_as_text()
|
||||||
|
var config:Dictionary = str_to_var(content)
|
||||||
|
if config: return config
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
# save user config to file
|
||||||
|
static func set_config(config:Dictionary):
|
||||||
|
var file = FileAccess.open(USER_CONFIG_FILE_PATH, FileAccess.WRITE)
|
||||||
|
var content = var_to_str(config)
|
||||||
|
file.store_string(content)
|
||||||
|
|
||||||
|
|
||||||
|
# get config, if user config exists, return user config, otherwise return default config configured by plugin user
|
||||||
|
static func get_config() -> Dictionary:
|
||||||
|
var user_config:Dictionary = _get_config(USER_CONFIG_FILE_PATH)
|
||||||
|
if not user_config.is_empty():
|
||||||
|
return user_config
|
||||||
|
# if no user config, return default config, which is read-only
|
||||||
|
if is_custom_default_config_exists():
|
||||||
|
return _get_config(get_custom_default_config_path())
|
||||||
|
|
||||||
|
return _get_config(INITIAL_DEFAULT_CONFIG_FILE_PATH)
|
||||||
|
|
||||||
|
|
||||||
|
static func get_value(key:String, default:Variant) -> Variant:
|
||||||
|
return get_config().get(key, default)
|
||||||
|
|
||||||
|
|
||||||
|
static func set_value(key:String, val:Variant) -> void:
|
||||||
|
var config = _get_config(USER_CONFIG_FILE_PATH)
|
||||||
|
config[key] = val
|
||||||
|
set_config(config)
|
||||||
1
godot/addons/panku_console/common/config.gd.uid
Normal file
1
godot/addons/panku_console/common/config.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://bd0ob776pkvry
|
||||||
276
godot/addons/panku_console/common/gdexprenv.gd
Normal file
276
godot/addons/panku_console/common/gdexprenv.gd
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
class_name PankuGDExprEnv
|
||||||
|
|
||||||
|
const type_names = {
|
||||||
|
TYPE_NIL: "null",
|
||||||
|
TYPE_BOOL: "bool",
|
||||||
|
TYPE_INT: "int",
|
||||||
|
TYPE_FLOAT: "float",
|
||||||
|
TYPE_STRING: "String",
|
||||||
|
TYPE_VECTOR2: "Vector2",
|
||||||
|
TYPE_VECTOR2I: "Vector2i",
|
||||||
|
TYPE_RECT2: "Rect2",
|
||||||
|
TYPE_RECT2I: "Rect2i",
|
||||||
|
TYPE_VECTOR3: "Vector3",
|
||||||
|
TYPE_VECTOR3I: "Vector3i",
|
||||||
|
TYPE_TRANSFORM2D: "Transform2D",
|
||||||
|
TYPE_VECTOR4: "Vector4",
|
||||||
|
TYPE_VECTOR4I: "Vector4i",
|
||||||
|
TYPE_PLANE: "Plane",
|
||||||
|
TYPE_QUATERNION: "Quaternion",
|
||||||
|
TYPE_AABB: "AABB",
|
||||||
|
TYPE_BASIS: "Basis",
|
||||||
|
TYPE_TRANSFORM3D: "Transform3D",
|
||||||
|
TYPE_PROJECTION: "Projection",
|
||||||
|
TYPE_COLOR: "Color",
|
||||||
|
TYPE_STRING_NAME: "StringName",
|
||||||
|
TYPE_NODE_PATH: "NodePath",
|
||||||
|
TYPE_RID: "RID",
|
||||||
|
TYPE_OBJECT: "Object",
|
||||||
|
TYPE_CALLABLE: "Callable",
|
||||||
|
TYPE_SIGNAL: "Signal",
|
||||||
|
TYPE_DICTIONARY: "Dictionary",
|
||||||
|
TYPE_ARRAY: "Array",
|
||||||
|
TYPE_PACKED_BYTE_ARRAY: "PackedByteArray",
|
||||||
|
TYPE_PACKED_INT32_ARRAY: "PackedInt32Array",
|
||||||
|
TYPE_PACKED_INT64_ARRAY: "PackedInt64Array",
|
||||||
|
TYPE_PACKED_FLOAT32_ARRAY: "PackedFloat32Array",
|
||||||
|
TYPE_PACKED_FLOAT64_ARRAY: "PackedFloat64Array",
|
||||||
|
TYPE_PACKED_STRING_ARRAY: "PackedStringArray",
|
||||||
|
TYPE_PACKED_VECTOR2_ARRAY: "PackedVector2Array",
|
||||||
|
TYPE_PACKED_VECTOR3_ARRAY: "PackedVector3Array",
|
||||||
|
TYPE_PACKED_COLOR_ARRAY: "PackedColorArray",
|
||||||
|
}
|
||||||
|
|
||||||
|
var _envs = {}
|
||||||
|
var _envs_info = {}
|
||||||
|
var _expression = Expression.new()
|
||||||
|
var _base_instance:Object
|
||||||
|
|
||||||
|
func set_base_instance(base_instance:Object):
|
||||||
|
_base_instance = base_instance
|
||||||
|
#add info of base instance
|
||||||
|
var env_info = extract_info_from_script(_base_instance.get_script())
|
||||||
|
for k in env_info: _envs_info[k] = env_info[k]
|
||||||
|
|
||||||
|
func get_base_instance():
|
||||||
|
return _base_instance
|
||||||
|
|
||||||
|
## Register an environment that run expressions.
|
||||||
|
## [br][code]env_name[/code]: the name of the environment
|
||||||
|
## [br][code]env[/code]: The base instance that runs the expressions. For exmaple your player node.
|
||||||
|
func register_env(env_name:String, env:Object):
|
||||||
|
_envs[env_name] = env
|
||||||
|
# output("[color=green][Info][/color] [b]%s[/b] env loaded!"%env_name)
|
||||||
|
if env is Node:
|
||||||
|
env.tree_exiting.connect(
|
||||||
|
func(): remove_env(env_name)
|
||||||
|
)
|
||||||
|
if env.get_script():
|
||||||
|
var env_info = extract_info_from_script(env.get_script())
|
||||||
|
for k in env_info:
|
||||||
|
var keyword = "%s.%s" % [env_name, k]
|
||||||
|
_envs_info[keyword] = env_info[k]
|
||||||
|
|
||||||
|
## Return the environment object or [code]null[/code] by its name.
|
||||||
|
func get_env(env_name:String) -> Node:
|
||||||
|
return _envs.get(env_name)
|
||||||
|
|
||||||
|
## Remove the environment named [code]env_name[/code]
|
||||||
|
func remove_env(env_name:String):
|
||||||
|
if _envs.has(env_name):
|
||||||
|
_envs.erase(env_name)
|
||||||
|
for k in _envs_info.keys():
|
||||||
|
if k.begins_with(env_name + "."):
|
||||||
|
_envs_info.erase(k)
|
||||||
|
|
||||||
|
#Execute an expression in a preset environment.
|
||||||
|
func execute(exp:String) -> Dictionary:
|
||||||
|
return execute_exp(exp, _expression, _base_instance, _envs)
|
||||||
|
|
||||||
|
# TODO: not used
|
||||||
|
func get_available_export_objs() -> Array:
|
||||||
|
var result = []
|
||||||
|
for obj_name in _envs:
|
||||||
|
var obj = _envs[obj_name]
|
||||||
|
if !obj.get_script():
|
||||||
|
continue
|
||||||
|
var export_properties = get_export_properties_from_script(obj.get_script())
|
||||||
|
if export_properties.is_empty():
|
||||||
|
continue
|
||||||
|
result.push_back(obj_name)
|
||||||
|
return result
|
||||||
|
|
||||||
|
func get_help_info(k:String) -> String:
|
||||||
|
return _envs_info[k]["help"]
|
||||||
|
|
||||||
|
#TODO: refactor all those mess
|
||||||
|
func parse_exp(exp:String, allow_empty:=false):
|
||||||
|
var result:Array
|
||||||
|
var empty_flag = allow_empty and exp.is_empty()
|
||||||
|
|
||||||
|
if empty_flag:
|
||||||
|
result = _envs_info.keys()
|
||||||
|
else:
|
||||||
|
result = search_and_sort_and_highlight(exp, _envs_info.keys())
|
||||||
|
|
||||||
|
var hints_bbcode = []
|
||||||
|
var hints_value = []
|
||||||
|
|
||||||
|
for r in result:
|
||||||
|
var keyword:String
|
||||||
|
var bbcode_main:String
|
||||||
|
|
||||||
|
if empty_flag:
|
||||||
|
keyword = r
|
||||||
|
bbcode_main = r
|
||||||
|
else:
|
||||||
|
keyword = r["keyword"]
|
||||||
|
bbcode_main = r["bbcode"]
|
||||||
|
|
||||||
|
var bbcode_postfix = _envs_info[keyword]["bbcode_postfix"]
|
||||||
|
var keyword_type = _envs_info[keyword]["type"]
|
||||||
|
hints_value.push_back(keyword)
|
||||||
|
hints_bbcode.push_back(bbcode_main + bbcode_postfix)
|
||||||
|
return {
|
||||||
|
"hints_bbcode": hints_bbcode,
|
||||||
|
"hints_value": hints_value
|
||||||
|
}
|
||||||
|
|
||||||
|
static func search_and_sort_and_highlight(s:String, li:Array):
|
||||||
|
s = s.lstrip(" ").rstrip(" ")
|
||||||
|
var matched = []
|
||||||
|
if s == "": return matched
|
||||||
|
for k in li:
|
||||||
|
var start = k.find(s)
|
||||||
|
if start >= 0:
|
||||||
|
var similarity = 1.0 * s.length() / k.length()
|
||||||
|
matched.append({
|
||||||
|
"keyword": k,
|
||||||
|
"similarity": similarity,
|
||||||
|
"start": start,
|
||||||
|
"bbcode": ""
|
||||||
|
})
|
||||||
|
|
||||||
|
matched.sort_custom(
|
||||||
|
func(k1, k2):
|
||||||
|
if k1["start"] != k2["start"]:
|
||||||
|
return k1["start"] > k2["start"]
|
||||||
|
else:
|
||||||
|
return k1["similarity"] < k2["similarity"]
|
||||||
|
)
|
||||||
|
|
||||||
|
var line_format = "%s[color=green][b]%s[/b][/color]%s"
|
||||||
|
|
||||||
|
for m in matched:
|
||||||
|
var p = ["", "", ""]
|
||||||
|
if m["start"] < 0:
|
||||||
|
p[0] = m["keyword"]
|
||||||
|
else:
|
||||||
|
p[0] = m["keyword"].substr(0, m["start"])
|
||||||
|
p[1] = s
|
||||||
|
p[2] = m["keyword"].substr(m["start"] + s.length(), -1)
|
||||||
|
|
||||||
|
m["bbcode"] = line_format % p
|
||||||
|
|
||||||
|
return matched
|
||||||
|
|
||||||
|
static func extract_info_from_script(script:Script):
|
||||||
|
var result = {}
|
||||||
|
|
||||||
|
var methods = []
|
||||||
|
var properties = []
|
||||||
|
var constants = []
|
||||||
|
var constants_bbcode_postfix = {}
|
||||||
|
|
||||||
|
for m in script.get_script_method_list():
|
||||||
|
if m["name"] != "" and m["name"].is_valid_identifier() and !m["name"].begins_with("_"):
|
||||||
|
var args = []
|
||||||
|
for a in m["args"]:
|
||||||
|
args.push_back("[color=cyan]%s[/color][color=gray]:[/color][color=orange]%s[/color]"%[a["name"], type_names[a["type"]]])
|
||||||
|
result[m["name"]] = {
|
||||||
|
"type": "method",
|
||||||
|
"bbcode_postfix": "(%s)"%("[color=gray], [/color]".join(PackedStringArray(args)))
|
||||||
|
}
|
||||||
|
for p in script.get_script_property_list():
|
||||||
|
if p["name"] != "" and !p["name"].begins_with("_") and p["name"].is_valid_identifier():
|
||||||
|
result[p["name"]] = {
|
||||||
|
"type": "property",
|
||||||
|
"bbcode_postfix":"[color=gray]:[/color][color=orange]%s[/color]"%type_names[p["type"]]
|
||||||
|
}
|
||||||
|
|
||||||
|
var constant_map = script.get_script_constant_map()
|
||||||
|
var help_info = {}
|
||||||
|
for c in constant_map:
|
||||||
|
if !c.begins_with("_"):
|
||||||
|
result[c] = {
|
||||||
|
"type": "constant",
|
||||||
|
"bbcode_postfix":"[color=gray]:[/color][color=orange]%s[/color]"%type_names[typeof(constant_map[c])]
|
||||||
|
}
|
||||||
|
elif c.begins_with("_HELP_") and c.length() > 6 and typeof(constant_map[c]) == TYPE_STRING:
|
||||||
|
var key = c.lstrip("_HELP_")
|
||||||
|
help_info[key] = constant_map[c]
|
||||||
|
|
||||||
|
for k in result:
|
||||||
|
if help_info.has(k):
|
||||||
|
result[k]["help"] = help_info[k]
|
||||||
|
else:
|
||||||
|
result[k]["help"] = "No help information provided."
|
||||||
|
|
||||||
|
#keyword -> {type, bbcode_postfix, help}
|
||||||
|
return result
|
||||||
|
|
||||||
|
static func execute_exp(exp_str:String, expression:Expression, base_instance:Object, env:Dictionary):
|
||||||
|
var failed := false
|
||||||
|
var result = null
|
||||||
|
|
||||||
|
var error = expression.parse(exp_str, env.keys())
|
||||||
|
if error != OK:
|
||||||
|
failed = true
|
||||||
|
result = expression.get_error_text()
|
||||||
|
else:
|
||||||
|
result = expression.execute(env.values(), base_instance, true)
|
||||||
|
if expression.has_execute_failed():
|
||||||
|
failed = true
|
||||||
|
result = expression.get_error_text()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"failed": failed,
|
||||||
|
"result": result
|
||||||
|
}
|
||||||
|
|
||||||
|
static func get_export_properties_from_script(script:Script):
|
||||||
|
var result = []
|
||||||
|
var data = script.get_script_property_list()
|
||||||
|
for d in data:
|
||||||
|
if !(d.usage == PROPERTY_USAGE_SCRIPT_VARIABLE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE):
|
||||||
|
continue
|
||||||
|
result.append(d)
|
||||||
|
return result
|
||||||
|
|
||||||
|
static func generate_help_text_from_script(script:Script):
|
||||||
|
var result = ["[color=cyan][b]User script defined identifiers[/b][/color]: "]
|
||||||
|
var env_info = extract_info_from_script(script)
|
||||||
|
var keys = env_info.keys()
|
||||||
|
keys.sort()
|
||||||
|
for k in keys:
|
||||||
|
result.push_back("%s - [i]%s[/i]"%[k + env_info[k]["bbcode_postfix"], env_info[k]["help"]])
|
||||||
|
return "\n".join(PackedStringArray(result))
|
||||||
|
|
||||||
|
#returns a string containing all public script properties of an object
|
||||||
|
#please BE AWARE when using this function on an object with custom getters.
|
||||||
|
static func get_object_outline(obj:Object) -> String:
|
||||||
|
var result := PackedStringArray()
|
||||||
|
if obj == null: return "null"
|
||||||
|
var script = obj.get_script()
|
||||||
|
if script == null:
|
||||||
|
return "this object has no script attached."
|
||||||
|
var properties = script.get_script_property_list()
|
||||||
|
for p in properties:
|
||||||
|
if p.usage & PROPERTY_USAGE_SCRIPT_VARIABLE == 0:
|
||||||
|
continue
|
||||||
|
if p.name.begins_with("_"):
|
||||||
|
continue
|
||||||
|
result.append("%s: %s" % [p.name, str(obj.get(p.name))])
|
||||||
|
if result.is_empty():
|
||||||
|
return "this object has no public script variables."
|
||||||
|
return "\n".join(result)
|
||||||
1
godot/addons/panku_console/common/gdexprenv.gd.uid
Normal file
1
godot/addons/panku_console/common/gdexprenv.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://xnce2n76k5p6
|
||||||
9
godot/addons/panku_console/common/lynx_window2/border.gd
Normal file
9
godot/addons/panku_console/common/lynx_window2/border.gd
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
extends Panel
|
||||||
|
|
||||||
|
func hey_i_am_here():
|
||||||
|
modulate.a = 0.0
|
||||||
|
var t = create_tween()
|
||||||
|
t.set_speed_scale(1.0 / Engine.time_scale)
|
||||||
|
for i in range(2):
|
||||||
|
t.tween_property(self, "modulate:a", 0.3, 0.1)
|
||||||
|
t.tween_property(self, "modulate:a", 0.0, 0.1)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://b2oil1la5ccpf
|
||||||
298
godot/addons/panku_console/common/lynx_window2/lynx_window_2.gd
Normal file
298
godot/addons/panku_console/common/lynx_window2/lynx_window_2.gd
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
class_name PankuLynxWindow extends ColorRect
|
||||||
|
|
||||||
|
#Do not connect the button node directly, use these signals to detect click event.
|
||||||
|
signal title_btn_clicked
|
||||||
|
signal window_closed
|
||||||
|
|
||||||
|
const lynx_window_shader_material:ShaderMaterial = preload("./lynx_window_shader_material.tres")
|
||||||
|
const OS_WINDOW_MARKER = "PankuOSWindow"
|
||||||
|
|
||||||
|
@export var _window_title_container:HBoxContainer
|
||||||
|
@export var _title_btn:PankuButton
|
||||||
|
@export var _close_btn:PankuButton
|
||||||
|
@export var _options_btn:PankuButton
|
||||||
|
@export var _resize_btn:Button
|
||||||
|
@export var _shadow_focus:Panel
|
||||||
|
@export var _shadow:NinePatchRect
|
||||||
|
@export var _container:Panel
|
||||||
|
@export var _pop_btn:PankuButton
|
||||||
|
|
||||||
|
@export var no_resize := false
|
||||||
|
@export var no_resize_x := false
|
||||||
|
@export var no_resize_y := false
|
||||||
|
@export var no_move := false
|
||||||
|
@export var no_snap := false
|
||||||
|
|
||||||
|
@export var no_title := false:
|
||||||
|
set(v):
|
||||||
|
no_title = v
|
||||||
|
_window_title_container.visible = !v
|
||||||
|
|
||||||
|
@export var queue_free_on_close := true
|
||||||
|
@export var flicker := true
|
||||||
|
|
||||||
|
var transform_interp_speed := 40.0
|
||||||
|
var bounds_interp_speed := 50.0
|
||||||
|
var anim_interp_speed := 10.0
|
||||||
|
|
||||||
|
var _is_dragging := false
|
||||||
|
var _drag_start_position:Vector2
|
||||||
|
var _drag_start_position_global:Vector2
|
||||||
|
var _is_resizing := false
|
||||||
|
var _resize_start_position:Vector2
|
||||||
|
var _os_window:Window
|
||||||
|
var _content:Control
|
||||||
|
var _size_before_folded:Vector2
|
||||||
|
var _folded:bool = false
|
||||||
|
var _size_animation:bool = false
|
||||||
|
var _target_size:Vector2
|
||||||
|
|
||||||
|
func add_options_button(callback:Callable):
|
||||||
|
_options_btn.show()
|
||||||
|
_options_btn.pressed.connect(callback)
|
||||||
|
|
||||||
|
func get_layout_position(layout:Control.LayoutPreset) -> Vector2:
|
||||||
|
var window_rect = get_rect()
|
||||||
|
var screen_rect = get_viewport_rect()
|
||||||
|
var new_position = Vector2.ZERO
|
||||||
|
var end_position = screen_rect.size - window_rect.size
|
||||||
|
var center_position = end_position / 2
|
||||||
|
if layout == PRESET_TOP_LEFT:
|
||||||
|
pass
|
||||||
|
elif layout == PRESET_CENTER_TOP:
|
||||||
|
new_position.x = center_position.x
|
||||||
|
elif layout == PRESET_TOP_RIGHT:
|
||||||
|
new_position.x = end_position.x
|
||||||
|
elif layout == PRESET_CENTER_LEFT:
|
||||||
|
new_position.y = center_position.y
|
||||||
|
elif layout == PRESET_CENTER:
|
||||||
|
new_position = center_position
|
||||||
|
elif layout == PRESET_CENTER_RIGHT:
|
||||||
|
new_position.x = end_position.x
|
||||||
|
new_position.y = center_position.y
|
||||||
|
elif layout == PRESET_BOTTOM_LEFT:
|
||||||
|
new_position.y = end_position.y
|
||||||
|
elif layout == PRESET_CENTER_BOTTOM:
|
||||||
|
new_position.x = center_position.x
|
||||||
|
new_position.y = end_position.y
|
||||||
|
elif layout == PRESET_BOTTOM_RIGHT:
|
||||||
|
new_position = end_position
|
||||||
|
return new_position
|
||||||
|
|
||||||
|
func get_content():
|
||||||
|
return _content
|
||||||
|
|
||||||
|
func set_content(node:Control):
|
||||||
|
_content = node
|
||||||
|
if _os_window and _os_window.visible:
|
||||||
|
if _os_window.get_child_count() > 0:
|
||||||
|
push_error("Error: error in set_content")
|
||||||
|
return
|
||||||
|
_os_window.add_child(node)
|
||||||
|
return
|
||||||
|
if _container.get_child_count() > 0:
|
||||||
|
push_error("Error: error in set_content.")
|
||||||
|
return
|
||||||
|
_container.add_child(node)
|
||||||
|
|
||||||
|
func highlight(v:bool):
|
||||||
|
_shadow_focus.visible = v
|
||||||
|
|
||||||
|
func _init_os_window():
|
||||||
|
_os_window = Window.new()
|
||||||
|
_os_window.set_meta(OS_WINDOW_MARKER, true)
|
||||||
|
var color_rect = ColorRect.new()
|
||||||
|
color_rect.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||||
|
_os_window.add_child(color_rect)
|
||||||
|
get_tree().root.add_child(_os_window)
|
||||||
|
#destructor
|
||||||
|
tree_exiting.connect(
|
||||||
|
func():
|
||||||
|
_os_window.queue_free()
|
||||||
|
)
|
||||||
|
#switch back to embed window when os window close requested
|
||||||
|
_os_window.close_requested.connect(
|
||||||
|
func():
|
||||||
|
_os_window.remove_child(_content)
|
||||||
|
_os_window.hide()
|
||||||
|
set_content(_content)
|
||||||
|
show()
|
||||||
|
)
|
||||||
|
if get_parent().has_method("get_os_window_bg_color"):
|
||||||
|
color_rect.color = get_parent().get_os_window_bg_color()
|
||||||
|
|
||||||
|
func switch_to_os_window():
|
||||||
|
if _content == null:
|
||||||
|
push_error("Error: No content. ")
|
||||||
|
return
|
||||||
|
if _os_window == null:
|
||||||
|
_init_os_window()
|
||||||
|
_container.remove_child(_content)
|
||||||
|
_os_window.add_child(_content)
|
||||||
|
_os_window.size = size
|
||||||
|
_os_window.title = _title_btn.text
|
||||||
|
_os_window.position = Vector2(DisplayServer.window_get_position(0)) + position
|
||||||
|
_content.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||||
|
_os_window.show()
|
||||||
|
hide()
|
||||||
|
|
||||||
|
func show_window():
|
||||||
|
if _os_window and _os_window.visible:
|
||||||
|
return
|
||||||
|
show()
|
||||||
|
move_to_front()
|
||||||
|
modulate.a = 0.0
|
||||||
|
create_tween().tween_property(self, "modulate:a", 1.0, 0.2)
|
||||||
|
|
||||||
|
func hide_window():
|
||||||
|
if _os_window and _os_window.visible:
|
||||||
|
_os_window.close_requested.emit()
|
||||||
|
hide()
|
||||||
|
|
||||||
|
func toggle_window_visibility():
|
||||||
|
if _os_window.visible or visible:
|
||||||
|
hide_window()
|
||||||
|
else:
|
||||||
|
show_window()
|
||||||
|
|
||||||
|
func set_window_visibility(b:bool):
|
||||||
|
if b: show_window()
|
||||||
|
else: hide_window()
|
||||||
|
|
||||||
|
func get_window_visibility() -> bool:
|
||||||
|
return visible or _os_window.visible
|
||||||
|
|
||||||
|
func set_window_title_text(text:String):
|
||||||
|
if _os_window and _os_window.visible:
|
||||||
|
_os_window.title = text
|
||||||
|
else:
|
||||||
|
_title_btn.text = " " + text
|
||||||
|
|
||||||
|
func get_normal_window_size():
|
||||||
|
if _folded: return _size_before_folded
|
||||||
|
return size
|
||||||
|
|
||||||
|
func get_title_bar_height():
|
||||||
|
return _window_title_container.size.y
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
custom_minimum_size = _window_title_container.get_minimum_size()
|
||||||
|
|
||||||
|
_options_btn.visible = false
|
||||||
|
|
||||||
|
_title_btn.button_down.connect(
|
||||||
|
func():
|
||||||
|
_is_dragging = true
|
||||||
|
_drag_start_position = get_local_mouse_position()
|
||||||
|
_drag_start_position_global = get_global_mouse_position()
|
||||||
|
)
|
||||||
|
_title_btn.button_up.connect(
|
||||||
|
func():
|
||||||
|
_is_dragging = false
|
||||||
|
)
|
||||||
|
_resize_btn.button_down.connect(
|
||||||
|
func():
|
||||||
|
_is_resizing = true
|
||||||
|
_resize_start_position = _resize_btn.get_local_mouse_position()
|
||||||
|
)
|
||||||
|
_resize_btn.button_up.connect(
|
||||||
|
func():
|
||||||
|
_is_resizing = false
|
||||||
|
)
|
||||||
|
_close_btn.pressed.connect(
|
||||||
|
func():
|
||||||
|
window_closed.emit()
|
||||||
|
if queue_free_on_close:
|
||||||
|
queue_free()
|
||||||
|
else:
|
||||||
|
hide()
|
||||||
|
)
|
||||||
|
|
||||||
|
_title_btn.button.gui_input.connect(
|
||||||
|
func(e):
|
||||||
|
if e is InputEventMouseButton and !e.pressed:
|
||||||
|
if e.button_index != MOUSE_BUTTON_NONE:
|
||||||
|
if (get_global_mouse_position() - _drag_start_position_global).length_squared() < 4:
|
||||||
|
title_btn_clicked.emit()
|
||||||
|
)
|
||||||
|
visibility_changed.connect(
|
||||||
|
func():
|
||||||
|
if is_visible_in_tree() and flicker:
|
||||||
|
$Border.hey_i_am_here()
|
||||||
|
)
|
||||||
|
|
||||||
|
if flicker:
|
||||||
|
$Border.hey_i_am_here()
|
||||||
|
|
||||||
|
_pop_btn.pressed.connect(switch_to_os_window)
|
||||||
|
|
||||||
|
if _container.get_child_count() > 0:
|
||||||
|
_content = _container.get_child(0)
|
||||||
|
|
||||||
|
if get_parent().has_method("get_enable_os_popup_btns"):
|
||||||
|
_pop_btn.visible = get_parent().get_enable_os_popup_btns()
|
||||||
|
|
||||||
|
# feature: foldable window
|
||||||
|
title_btn_clicked.connect(
|
||||||
|
func():
|
||||||
|
if _folded:
|
||||||
|
_target_size = _size_before_folded
|
||||||
|
else:
|
||||||
|
if !_size_animation:
|
||||||
|
_size_before_folded = size
|
||||||
|
_target_size = _window_title_container.size
|
||||||
|
_size_animation = true
|
||||||
|
_folded = !_folded
|
||||||
|
_resize_btn.visible = !_folded
|
||||||
|
)
|
||||||
|
|
||||||
|
func _input(e):
|
||||||
|
#release focus when you click outside of the window
|
||||||
|
if is_visible:
|
||||||
|
if e is InputEventMouseButton and e.pressed:
|
||||||
|
if !get_global_rect().has_point(get_global_mouse_position()):
|
||||||
|
var f = get_viewport().gui_get_focus_owner()
|
||||||
|
if f and is_ancestor_of(f):
|
||||||
|
f.release_focus()
|
||||||
|
if e is InputEventKey and e.keycode == KEY_ESCAPE and e.pressed and get_global_rect().has_point(get_global_mouse_position()):
|
||||||
|
window_closed.emit()
|
||||||
|
if queue_free_on_close:
|
||||||
|
queue_free()
|
||||||
|
else:
|
||||||
|
hide()
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
if !no_move and _is_dragging:
|
||||||
|
var tp := position + get_local_mouse_position() - _drag_start_position
|
||||||
|
position = PankuUtils.interp(position, tp, transform_interp_speed, delta)
|
||||||
|
elif !no_resize and _is_resizing:
|
||||||
|
var ts := size + _resize_btn.get_local_mouse_position() - _resize_start_position
|
||||||
|
ts.x = min(ts.x, get_viewport_rect().size.x)
|
||||||
|
ts.y = min(ts.y, get_viewport_rect().size.y)
|
||||||
|
if !no_resize_x:
|
||||||
|
size.x = PankuUtils.interp(size.x, ts.x, transform_interp_speed, delta)
|
||||||
|
if !no_resize_y:
|
||||||
|
size.y = PankuUtils.interp(size.y, ts.y, transform_interp_speed, delta)
|
||||||
|
elif !no_snap:
|
||||||
|
var window_rect := get_rect()
|
||||||
|
var screen_rect := get_viewport_rect()
|
||||||
|
var target_position := window_rect.position
|
||||||
|
var target_size := window_rect.size.clamp(Vector2.ZERO, screen_rect.size)
|
||||||
|
if window_rect.position.y < 0:
|
||||||
|
target_position.y = 0
|
||||||
|
if window_rect.end.y > screen_rect.end.y:
|
||||||
|
target_position.y = screen_rect.end.y - window_rect.size.y
|
||||||
|
if window_rect.end.y > screen_rect.end.y + window_rect.size.y / 2:
|
||||||
|
target_position.y = screen_rect.end.y - get_title_bar_height()
|
||||||
|
if window_rect.position.x < 0:
|
||||||
|
target_position.x = 0
|
||||||
|
if window_rect.end.x > screen_rect.end.x:
|
||||||
|
target_position.x = screen_rect.end.x - window_rect.size.x
|
||||||
|
var current_position = window_rect.position
|
||||||
|
current_position = PankuUtils.interp(current_position, target_position, bounds_interp_speed, delta)
|
||||||
|
size = PankuUtils.interp(size, target_size, bounds_interp_speed, delta)
|
||||||
|
position = current_position
|
||||||
|
if _size_animation:
|
||||||
|
if _target_size.is_equal_approx(size):
|
||||||
|
_size_animation = false
|
||||||
|
size = PankuUtils.interp(size, _target_size, anim_interp_speed, delta)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://buw6hpyf4b2an
|
||||||
@ -0,0 +1,204 @@
|
|||||||
|
[gd_scene load_steps=19 format=3 uid="uid://s88loppa6gja"]
|
||||||
|
|
||||||
|
[ext_resource type="Material" uid="uid://dyipeqsa8lcpc" path="res://addons/panku_console/common/lynx_window2/lynx_window_shader_material.tres" id="1_tvp6i"]
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/common/lynx_window2/lynx_window_2.gd" id="2_1ul5o"]
|
||||||
|
[ext_resource type="Theme" uid="uid://bk18yfu0d77wk" path="res://addons/panku_console/res/panku_console_theme.tres" id="2_3fhqk"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dosm26riekruh" path="res://addons/panku_console/res/icons2/menu.svg" id="4_4dlyn"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://drn5t13m088fb" path="res://addons/panku_console/common/panku_button.tscn" id="4_dnesi"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://gav3m4qtvgje" path="res://addons/panku_console/res/icons2/pop-out-svgrepo-com.svg" id="4_im81u"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://8g5afcuanbl6" path="res://addons/panku_console/res/icons2/close.svg" id="5_l4qpm"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dvr12fl5prm78" path="res://addons/panku_console/res/effect/square_shadow.png" id="6_mfp1h"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://ciu5jiw4xmkq0" path="res://addons/panku_console/res/icons2/resize-svgrepo-com.svg" id="7_duwqn"]
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/common/lynx_window2/border.gd" id="8_gj3ji"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_hv45g"]
|
||||||
|
draw_center = false
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_top = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color(1, 1, 1, 0.25098)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6i67d"]
|
||||||
|
content_margin_left = 8.0
|
||||||
|
content_margin_top = 8.0
|
||||||
|
content_margin_right = 8.0
|
||||||
|
content_margin_bottom = 8.0
|
||||||
|
draw_center = false
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color(1, 1, 1, 0.25098)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_lct0k"]
|
||||||
|
draw_center = false
|
||||||
|
shadow_color = Color(0, 0, 0, 0.0627451)
|
||||||
|
shadow_size = 16
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_p3y6j"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_r0x7y"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_p7tml"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_5muk4"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uldta"]
|
||||||
|
draw_center = false
|
||||||
|
border_width_left = 4
|
||||||
|
border_width_top = 4
|
||||||
|
border_width_right = 4
|
||||||
|
border_width_bottom = 4
|
||||||
|
border_color = Color(1, 1, 1, 1)
|
||||||
|
|
||||||
|
[node name="LynxWindow2" type="ColorRect" node_paths=PackedStringArray("_window_title_container", "_title_btn", "_close_btn", "_options_btn", "_resize_btn", "_shadow_focus", "_shadow", "_container", "_pop_btn")]
|
||||||
|
material = ExtResource("1_tvp6i")
|
||||||
|
offset_right = 413.0
|
||||||
|
offset_bottom = 305.0
|
||||||
|
theme = ExtResource("2_3fhqk")
|
||||||
|
script = ExtResource("2_1ul5o")
|
||||||
|
_window_title_container = NodePath("MainBody/VBoxContainer/Up")
|
||||||
|
_title_btn = NodePath("MainBody/VBoxContainer/Up/TitleButton")
|
||||||
|
_close_btn = NodePath("MainBody/VBoxContainer/Up/CloseButton")
|
||||||
|
_options_btn = NodePath("MainBody/VBoxContainer/Up/MenuButton")
|
||||||
|
_resize_btn = NodePath("Button")
|
||||||
|
_shadow_focus = NodePath("Shadow2")
|
||||||
|
_shadow = NodePath("Shadow")
|
||||||
|
_container = NodePath("MainBody/VBoxContainer/Down")
|
||||||
|
_pop_btn = NodePath("MainBody/VBoxContainer/Up/PopupButton")
|
||||||
|
|
||||||
|
[node name="MainBody" type="Control" parent="."]
|
||||||
|
clip_contents = true
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="MainBody"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
|
||||||
|
[node name="Up" type="HBoxContainer" parent="MainBody/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
|
||||||
|
[node name="TitleButton" parent="MainBody/VBoxContainer/Up" instance=ExtResource("4_dnesi")]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_hv45g")
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="MainBody/VBoxContainer/Up/TitleButton/HBoxContainer" index="0"]
|
||||||
|
texture = null
|
||||||
|
|
||||||
|
[node name="Label" parent="MainBody/VBoxContainer/Up/TitleButton/HBoxContainer" index="1"]
|
||||||
|
text = "Window Title"
|
||||||
|
|
||||||
|
[node name="PopupButton" parent="MainBody/VBoxContainer/Up" instance=ExtResource("4_dnesi")]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_hv45g")
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="MainBody/VBoxContainer/Up/PopupButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("4_im81u")
|
||||||
|
|
||||||
|
[node name="Label" parent="MainBody/VBoxContainer/Up/PopupButton/HBoxContainer" index="1"]
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="MenuButton" parent="MainBody/VBoxContainer/Up" instance=ExtResource("4_dnesi")]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_hv45g")
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="MainBody/VBoxContainer/Up/MenuButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("4_4dlyn")
|
||||||
|
|
||||||
|
[node name="Label" parent="MainBody/VBoxContainer/Up/MenuButton/HBoxContainer" index="1"]
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="CloseButton" parent="MainBody/VBoxContainer/Up" instance=ExtResource("4_dnesi")]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_hv45g")
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="MainBody/VBoxContainer/Up/CloseButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("5_l4qpm")
|
||||||
|
|
||||||
|
[node name="Label" parent="MainBody/VBoxContainer/Up/CloseButton/HBoxContainer" index="1"]
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="Down" type="Panel" parent="MainBody/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_6i67d")
|
||||||
|
|
||||||
|
[node name="Shadow" type="NinePatchRect" parent="."]
|
||||||
|
modulate = Color(1, 1, 1, 0.501961)
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -64.0
|
||||||
|
offset_top = -79.0
|
||||||
|
offset_right = 63.0
|
||||||
|
offset_bottom = 47.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
texture = ExtResource("6_mfp1h")
|
||||||
|
draw_center = false
|
||||||
|
region_rect = Rect2(0, 0, 512, 512)
|
||||||
|
patch_margin_left = 64
|
||||||
|
patch_margin_top = 80
|
||||||
|
patch_margin_right = 64
|
||||||
|
patch_margin_bottom = 48
|
||||||
|
|
||||||
|
[node name="Shadow2" type="Panel" parent="."]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_lct0k")
|
||||||
|
|
||||||
|
[node name="Button" type="Button" parent="."]
|
||||||
|
self_modulate = Color(1, 1, 1, 0.501961)
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 3
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -12.0
|
||||||
|
offset_top = -12.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
grow_vertical = 0
|
||||||
|
mouse_default_cursor_shape = 12
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxEmpty_p3y6j")
|
||||||
|
theme_override_styles/hover = SubResource("StyleBoxEmpty_r0x7y")
|
||||||
|
theme_override_styles/pressed = SubResource("StyleBoxEmpty_p7tml")
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_5muk4")
|
||||||
|
icon = ExtResource("7_duwqn")
|
||||||
|
flat = true
|
||||||
|
expand_icon = true
|
||||||
|
|
||||||
|
[node name="Border" type="Panel" parent="."]
|
||||||
|
modulate = Color(1, 1, 1, 0)
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_uldta")
|
||||||
|
script = ExtResource("8_gj3ji")
|
||||||
|
|
||||||
|
[editable path="MainBody/VBoxContainer/Up/TitleButton"]
|
||||||
|
[editable path="MainBody/VBoxContainer/Up/PopupButton"]
|
||||||
|
[editable path="MainBody/VBoxContainer/Up/MenuButton"]
|
||||||
|
[editable path="MainBody/VBoxContainer/Up/CloseButton"]
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://dyipeqsa8lcpc"]
|
||||||
|
|
||||||
|
[ext_resource type="Shader" path="res://addons/panku_console/res/shader/simple_fast_blur.gdshader" id="1_3h55m"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
shader = ExtResource("1_3h55m")
|
||||||
|
shader_parameter/lod = 4.0
|
||||||
|
shader_parameter/modulate = Color(0, 0, 0, 0.12549)
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
#A simple control node managing its child windows
|
||||||
|
class_name PankuLynxWindowsManager extends Control
|
||||||
|
|
||||||
|
const CFG_ENABLE_OS_WINDOW = "enable_os_window"
|
||||||
|
const CFG_OS_WINDOW_BGCOLOR = "os_window_bg_color"
|
||||||
|
|
||||||
|
@onready var console:PankuConsole = get_node(PankuConsole.SingletonPath)
|
||||||
|
|
||||||
|
var os_popup_btn_enabled:bool
|
||||||
|
var os_window_bg_color:Color
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
load_data()
|
||||||
|
|
||||||
|
func _input(e):
|
||||||
|
if e is InputEventMouseButton and e.pressed:
|
||||||
|
var flag = true
|
||||||
|
#traverse child windows in reverse order, use double shadow to highlight current active window.
|
||||||
|
for i in range(get_child_count() - 1, -1, -1):
|
||||||
|
var w:Control = get_child(i)
|
||||||
|
if w.visible and w.get_global_rect().has_point(get_global_mouse_position()):
|
||||||
|
var forefront = get_child(get_child_count() - 1)
|
||||||
|
if forefront.has_method("highlight"): forefront.highlight(false)
|
||||||
|
w.move_to_front()
|
||||||
|
forefront = get_child(get_child_count() - 1)
|
||||||
|
if forefront.has_method("highlight"): forefront.highlight(true)
|
||||||
|
flag = false
|
||||||
|
break
|
||||||
|
if flag and get_child_count() > 0:
|
||||||
|
var forefront = get_child(get_child_count() - 1)
|
||||||
|
if forefront.has_method("highlight"): forefront.highlight(false)
|
||||||
|
|
||||||
|
func create_window(content:Control) -> PankuLynxWindow:
|
||||||
|
var new_window:PankuLynxWindow = preload("lynx_window_2.tscn").instantiate()
|
||||||
|
content.anchors_preset = Control.PRESET_FULL_RECT
|
||||||
|
new_window.set_content(content)
|
||||||
|
add_child(new_window)
|
||||||
|
new_window.show_window()
|
||||||
|
return new_window
|
||||||
|
|
||||||
|
func enable_os_popup_btns(b:bool):
|
||||||
|
#note that this may affect your project
|
||||||
|
get_viewport().gui_embed_subwindows = !b
|
||||||
|
os_popup_btn_enabled = b
|
||||||
|
for w in get_children():
|
||||||
|
#maybe there's a better way to get node type
|
||||||
|
if !w.has_method("switch_to_os_window"):
|
||||||
|
continue
|
||||||
|
w._pop_btn.visible = b
|
||||||
|
|
||||||
|
func get_enable_os_popup_btns() -> bool:
|
||||||
|
return os_popup_btn_enabled
|
||||||
|
|
||||||
|
func set_os_window_bg_color(c:Color):
|
||||||
|
os_window_bg_color = c
|
||||||
|
for w in get_children():
|
||||||
|
#maybe there's a better way to get node type
|
||||||
|
if !w.has_method("switch_to_os_window"):
|
||||||
|
continue
|
||||||
|
if w._os_window != null:
|
||||||
|
w._os_window.get_child(0).color = c
|
||||||
|
|
||||||
|
func get_os_window_bg_color() -> Color:
|
||||||
|
return os_window_bg_color
|
||||||
|
|
||||||
|
func save_data():
|
||||||
|
var cfg = PankuConfig.get_config()
|
||||||
|
cfg[CFG_ENABLE_OS_WINDOW] = os_popup_btn_enabled
|
||||||
|
cfg[CFG_OS_WINDOW_BGCOLOR] = os_window_bg_color
|
||||||
|
PankuConfig.set_config(cfg)
|
||||||
|
|
||||||
|
func load_data():
|
||||||
|
var cfg = PankuConfig.get_config()
|
||||||
|
enable_os_popup_btns(cfg.get(CFG_ENABLE_OS_WINDOW, false))
|
||||||
|
set_os_window_bg_color(cfg.get(CFG_OS_WINDOW_BGCOLOR, Color("#2b2e32")))
|
||||||
|
|
||||||
|
func _notification(what):
|
||||||
|
#quit event
|
||||||
|
if what == NOTIFICATION_WM_CLOSE_REQUEST:
|
||||||
|
save_data()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://xjhlmbdx8fjf
|
||||||
54
godot/addons/panku_console/common/module_manager.gd
Normal file
54
godot/addons/panku_console/common/module_manager.gd
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
class_name PankuModuleManager
|
||||||
|
|
||||||
|
var _modules:Array[PankuModule]
|
||||||
|
var _modules_table:Dictionary
|
||||||
|
var _core:PankuConsole
|
||||||
|
|
||||||
|
func init_manager(_core:PankuConsole, _modules:Array[PankuModule]):
|
||||||
|
self._modules = _modules
|
||||||
|
self._core = _core
|
||||||
|
load_modules()
|
||||||
|
|
||||||
|
func load_modules():
|
||||||
|
|
||||||
|
# The extra tree structure is purely used for avoiding using RefCounted which may cause uncessary leaked instance warnings.
|
||||||
|
var manager_node:Node = Node.new()
|
||||||
|
manager_node.name = "_Modules_"
|
||||||
|
_core.add_child(manager_node)
|
||||||
|
|
||||||
|
for _m in _modules:
|
||||||
|
var module:PankuModule = _m
|
||||||
|
_modules_table[module.get_module_name()] = module
|
||||||
|
|
||||||
|
module.name = module.get_module_name()
|
||||||
|
manager_node.add_child(module)
|
||||||
|
|
||||||
|
for _m in _modules:
|
||||||
|
var module:PankuModule = _m
|
||||||
|
module.core = _core
|
||||||
|
module._init_module()
|
||||||
|
#print("[info] %s module loaded!" % module.get_module_name())
|
||||||
|
|
||||||
|
func update_modules(delta:float):
|
||||||
|
for _m in _modules:
|
||||||
|
var module:PankuModule = _m
|
||||||
|
module.update_module(delta)
|
||||||
|
|
||||||
|
func get_module(module_name:String):
|
||||||
|
return _modules_table[module_name]
|
||||||
|
|
||||||
|
func has_module(module_name:String):
|
||||||
|
return _modules_table.has(module_name)
|
||||||
|
|
||||||
|
func get_module_option_objects():
|
||||||
|
var objects = []
|
||||||
|
for _m in _modules:
|
||||||
|
var module:PankuModule = _m
|
||||||
|
if module._opt != null:
|
||||||
|
objects.append(module._opt)
|
||||||
|
return objects
|
||||||
|
|
||||||
|
func quit_modules():
|
||||||
|
for _m in _modules:
|
||||||
|
var module:PankuModule = _m
|
||||||
|
module.quit_module()
|
||||||
1
godot/addons/panku_console/common/module_manager.gd.uid
Normal file
1
godot/addons/panku_console/common/module_manager.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://rkefpsd8kk4q
|
||||||
11
godot/addons/panku_console/common/module_options.gd
Normal file
11
godot/addons/panku_console/common/module_options.gd
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class_name ModuleOptions extends Resource
|
||||||
|
|
||||||
|
var _module:PankuModule
|
||||||
|
|
||||||
|
var _loaded := false
|
||||||
|
|
||||||
|
#FIXME: Tricky part of saving data, needs to be reworked
|
||||||
|
func update_setting(key: String, value: Variant):
|
||||||
|
self.set(key, value)
|
||||||
|
if _loaded and _module:
|
||||||
|
_module.save_module_data(key, value)
|
||||||
1
godot/addons/panku_console/common/module_options.gd.uid
Normal file
1
godot/addons/panku_console/common/module_options.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://dhh5181ty0ng6
|
||||||
39
godot/addons/panku_console/common/panku_button.gd
Normal file
39
godot/addons/panku_console/common/panku_button.gd
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
class_name PankuButton extends Control
|
||||||
|
|
||||||
|
signal pressed
|
||||||
|
signal button_down
|
||||||
|
signal button_up
|
||||||
|
|
||||||
|
@export
|
||||||
|
var button:Button
|
||||||
|
|
||||||
|
@export
|
||||||
|
var trect:TextureRect
|
||||||
|
|
||||||
|
@export
|
||||||
|
var label:Label
|
||||||
|
|
||||||
|
var icon:
|
||||||
|
set(v):
|
||||||
|
trect.texture = v
|
||||||
|
get:
|
||||||
|
return trect.texture
|
||||||
|
|
||||||
|
var text:
|
||||||
|
set(v):
|
||||||
|
label.text = v
|
||||||
|
get:
|
||||||
|
return label.text
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
|
||||||
|
button.pressed.connect(
|
||||||
|
func():
|
||||||
|
pressed.emit()
|
||||||
|
)
|
||||||
|
button.button_down.connect(
|
||||||
|
func(): button_down.emit()
|
||||||
|
)
|
||||||
|
button.button_up.connect(
|
||||||
|
func(): button_up.emit()
|
||||||
|
)
|
||||||
1
godot/addons/panku_console/common/panku_button.gd.uid
Normal file
1
godot/addons/panku_console/common/panku_button.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://bdhu7gchsjvpf
|
||||||
42
godot/addons/panku_console/common/panku_button.tscn
Normal file
42
godot/addons/panku_console/common/panku_button.tscn
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
[gd_scene load_steps=5 format=3 uid="uid://drn5t13m088fb"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/common/panku_button.gd" id="1_7kf5f"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dchvk7qgfe37m" path="res://addons/panku_console/res/icons2/fold-svgrepo-com.svg" id="2_su653"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_v3kpx"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_cwnaw"]
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
|
||||||
|
[node name="PankuButton" type="PanelContainer" node_paths=PackedStringArray("button", "trect", "label")]
|
||||||
|
editor_description = "Godot's Button can't handle scaling icons properly as descripted in https://github.com/godotengine/godot-proposals/issues/660, so I have to make a new one."
|
||||||
|
self_modulate = Color(1, 1, 1, 0)
|
||||||
|
offset_right = 112.0
|
||||||
|
offset_bottom = 31.0
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxEmpty_v3kpx")
|
||||||
|
script = ExtResource("1_7kf5f")
|
||||||
|
button = NodePath("Button")
|
||||||
|
trect = NodePath("HBoxContainer/TextureRect")
|
||||||
|
label = NodePath("HBoxContainer/Label")
|
||||||
|
|
||||||
|
[node name="Button" type="Button" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
|
||||||
|
[node name="TextureRect" type="TextureRect" parent="HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
texture = ExtResource("2_su653")
|
||||||
|
expand_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 1
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_cwnaw")
|
||||||
|
vertical_alignment = 1
|
||||||
101
godot/addons/panku_console/common/panku_module.gd
Normal file
101
godot/addons/panku_console/common/panku_module.gd
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
class_name PankuModule extends Node
|
||||||
|
# extends Node: A hacky way to avoid cyclic RefCounted verbose warnings which is uncessary to worry about.
|
||||||
|
|
||||||
|
var core:PankuConsole
|
||||||
|
|
||||||
|
var _env:RefCounted = null
|
||||||
|
var _opt:ModuleOptions = null
|
||||||
|
|
||||||
|
# dir name of the module
|
||||||
|
func get_module_name() -> String:
|
||||||
|
return get_script().resource_path.get_base_dir().get_file()
|
||||||
|
|
||||||
|
# called when the module is loaded
|
||||||
|
func init_module():
|
||||||
|
pass
|
||||||
|
|
||||||
|
# called when the module is unloaded (quit program)
|
||||||
|
func quit_module():
|
||||||
|
if _opt:
|
||||||
|
_opt._loaded = false
|
||||||
|
|
||||||
|
# called at the start of each physics frame
|
||||||
|
func update_module(delta:float):
|
||||||
|
pass
|
||||||
|
|
||||||
|
func save_module_data(key:String, value:Variant):
|
||||||
|
var cfg:Dictionary = PankuConfig.get_config()
|
||||||
|
var module_name:String = get_module_name()
|
||||||
|
if !cfg.has(module_name):
|
||||||
|
cfg[module_name] = {}
|
||||||
|
cfg[module_name][key] = value
|
||||||
|
PankuConfig.set_config(cfg)
|
||||||
|
|
||||||
|
func load_module_data(key:String, default_value:Variant = null) -> Variant:
|
||||||
|
var cfg:Dictionary = PankuConfig.get_config()
|
||||||
|
var module_name:String = get_module_name()
|
||||||
|
var module_data = cfg.get(module_name, {})
|
||||||
|
return module_data.get(key, default_value)
|
||||||
|
|
||||||
|
func has_module_data(key:String) -> bool:
|
||||||
|
var cfg:Dictionary = PankuConfig.get_config()
|
||||||
|
var module_name:String = get_module_name()
|
||||||
|
var module_data = cfg.get(module_name, {})
|
||||||
|
return module_data.has(key)
|
||||||
|
|
||||||
|
func load_window_data(window:PankuLynxWindow):
|
||||||
|
window.position = load_module_data("window_position", window.get_layout_position([
|
||||||
|
Control.PRESET_TOP_LEFT,
|
||||||
|
Control.PRESET_CENTER_TOP,
|
||||||
|
Control.PRESET_TOP_RIGHT,
|
||||||
|
Control.PRESET_CENTER_LEFT,
|
||||||
|
Control.PRESET_CENTER,
|
||||||
|
Control.PRESET_CENTER_RIGHT,
|
||||||
|
Control.PRESET_BOTTOM_LEFT,
|
||||||
|
Control.PRESET_CENTER_BOTTOM,
|
||||||
|
Control.PRESET_BOTTOM_RIGHT,
|
||||||
|
][randi()%9]))
|
||||||
|
window.size = load_module_data("window_size", window.get_normal_window_size())
|
||||||
|
window.set_window_visibility(load_module_data("window_visibility", false))
|
||||||
|
|
||||||
|
func save_window_data(window:PankuLynxWindow):
|
||||||
|
_save_window_geometry(window)
|
||||||
|
save_module_data("window_visibility", window.visible)
|
||||||
|
|
||||||
|
|
||||||
|
func _save_window_geometry(window:PankuLynxWindow):
|
||||||
|
save_module_data("window_position", window.position)
|
||||||
|
save_module_data("window_size", window.get_normal_window_size())
|
||||||
|
|
||||||
|
|
||||||
|
# Add hook to window to auto save its geometry on close.
|
||||||
|
func add_auto_save_hook(window: PankuLynxWindow) -> void:
|
||||||
|
# Here some global settings check can be implemented,
|
||||||
|
# if we decide to make "save on close" feature optional
|
||||||
|
window.window_closed.connect(_save_window_geometry.bind(window))
|
||||||
|
|
||||||
|
|
||||||
|
func get_module_env() -> RefCounted:
|
||||||
|
return _env
|
||||||
|
|
||||||
|
func get_module_opt() -> ModuleOptions:
|
||||||
|
return _opt
|
||||||
|
|
||||||
|
func _init_module():
|
||||||
|
var module_script_dir:String = get_script().resource_path.get_base_dir()
|
||||||
|
var env_script_path = module_script_dir + "/env.gd"
|
||||||
|
var opt_script_path = module_script_dir + "/opt.gd"
|
||||||
|
|
||||||
|
if ResourceLoader.exists(env_script_path, "GDScript"):
|
||||||
|
_env = load(env_script_path).new()
|
||||||
|
_env._module = self
|
||||||
|
core.gd_exprenv.register_env(get_module_name(), _env)
|
||||||
|
|
||||||
|
if ResourceLoader.exists(opt_script_path, "GDScript"):
|
||||||
|
#print(opt_script_path)
|
||||||
|
_opt = load(opt_script_path).new() as ModuleOptions
|
||||||
|
_opt._module = self
|
||||||
|
|
||||||
|
init_module()
|
||||||
|
if _opt:
|
||||||
|
_opt._loaded = true
|
||||||
1
godot/addons/panku_console/common/panku_module.gd.uid
Normal file
1
godot/addons/panku_console/common/panku_module.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://ce7g5hrgs5lql
|
||||||
23
godot/addons/panku_console/common/repl_base_instance.gd
Normal file
23
godot/addons/panku_console/common/repl_base_instance.gd
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
var _core:PankuConsole
|
||||||
|
|
||||||
|
const _HELP_help := "List all environment variables."
|
||||||
|
var help:String:
|
||||||
|
get:
|
||||||
|
var result = ["Registered objects:\n"]
|
||||||
|
var colors = ["#7c3f58", "#eb6b6f", "#f9a875", "#fff6d3"]
|
||||||
|
var i = 0
|
||||||
|
for k in _core.gd_exprenv._envs:
|
||||||
|
var c = colors[i%4]
|
||||||
|
i = i + 1
|
||||||
|
result.push_back("[b][color=%s]%s[/color][/b] "%[c, k])
|
||||||
|
result.push_back("\n")
|
||||||
|
result.push_back("You can type [b]helpe(object)[/b] to get more information.")
|
||||||
|
return "".join(PackedStringArray(result))
|
||||||
|
|
||||||
|
const _HELP_helpe := "Provide detailed information about one specific environment variable."
|
||||||
|
func helpe(obj:Object) -> String:
|
||||||
|
if !obj:
|
||||||
|
return "Invalid!"
|
||||||
|
if !obj.get_script():
|
||||||
|
return "It has no attached script!"
|
||||||
|
return PankuGDExprEnv.generate_help_text_from_script(obj.get_script())
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://b8fo6s8tlpkh4
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
extends PanelContainer
|
||||||
|
|
||||||
|
@export var clip_container:Control
|
||||||
|
|
||||||
|
@export var scrollbar:VScrollBar
|
||||||
|
|
||||||
|
@export var follow_content:bool = true
|
||||||
|
|
||||||
|
@onready var content:Control = clip_container.get_child(0)
|
||||||
|
|
||||||
|
var scroll_progress:float = 0.0
|
||||||
|
var prev_content_size_y:float = 0.0
|
||||||
|
|
||||||
|
func init_progressbar() -> void:
|
||||||
|
scrollbar.min_value = 0.0
|
||||||
|
scrollbar.allow_greater = true
|
||||||
|
scrollbar.allow_lesser = true
|
||||||
|
scrollbar.value = 0.0
|
||||||
|
|
||||||
|
func _gui_input(event: InputEvent) -> void:
|
||||||
|
if event is InputEventMouseButton and event.is_pressed():
|
||||||
|
var step:float = clip_container.size.y / 8.0
|
||||||
|
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
|
||||||
|
scrollbar.value -= step
|
||||||
|
if event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
|
||||||
|
scrollbar.value += step
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
# add a tiny optimization here
|
||||||
|
if not is_visible_in_tree(): return
|
||||||
|
|
||||||
|
# See https://github.com/Ark2000/PankuConsole/issues/183, looks quirky
|
||||||
|
# content.size = Vector2(clip_container.size.x, 0)
|
||||||
|
# content.position = Vector2.ZERO
|
||||||
|
content.size.x = clip_container.size.x
|
||||||
|
content.size.y = 0
|
||||||
|
content.position.y = 0
|
||||||
|
content.position.x = 0
|
||||||
|
|
||||||
|
scrollbar.max_value = content.size.y
|
||||||
|
var scrollbar_value_max = max(0, scrollbar.max_value - clip_container.size.y)
|
||||||
|
scrollbar.value = PankuUtils.interp(scrollbar.value, clampf(scrollbar.value, 0.0, scrollbar_value_max), 10, delta)
|
||||||
|
scrollbar.page = clip_container.size.y
|
||||||
|
scrollbar.visible = content.size.y > clip_container.size.y
|
||||||
|
|
||||||
|
scroll_progress = PankuUtils.interp(scroll_progress, scrollbar.value, 10, delta)
|
||||||
|
content.position.y = - scroll_progress
|
||||||
|
|
||||||
|
if !follow_content: return
|
||||||
|
if prev_content_size_y != content.size.y:
|
||||||
|
var should_follow:bool = (scrollbar.value + scrollbar.page) / prev_content_size_y > 0.99
|
||||||
|
prev_content_size_y = content.size.y
|
||||||
|
if should_follow:
|
||||||
|
scrollbar.value = scrollbar.max_value - scrollbar.page
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
init_progressbar()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://dtang12b2rua7
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://dyq4rjkkjs55d"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/common/smooth_scroll/smooth_scroll.gd" id="1_ma8ku"]
|
||||||
|
[ext_resource type="Theme" uid="uid://bk18yfu0d77wk" path="res://addons/panku_console/res/panku_console_theme.tres" id="1_pa7xs"]
|
||||||
|
|
||||||
|
[node name="SmoothScrollContainer" type="PanelContainer" node_paths=PackedStringArray("clip_container", "scrollbar")]
|
||||||
|
self_modulate = Color(1, 1, 1, 0)
|
||||||
|
clip_contents = true
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme = ExtResource("1_pa7xs")
|
||||||
|
script = ExtResource("1_ma8ku")
|
||||||
|
clip_container = NodePath("HBoxContainer/Control")
|
||||||
|
scrollbar = NodePath("HBoxContainer/VScrollBar")
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="HBoxContainer"]
|
||||||
|
clip_contents = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="VScrollBar" type="VScrollBar" parent="HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
page = 20.0
|
||||||
|
value = 80.0
|
||||||
43
godot/addons/panku_console/common/utils.gd
Normal file
43
godot/addons/panku_console/common/utils.gd
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#@tool
|
||||||
|
#extends EditorScript
|
||||||
|
class_name PankuUtils
|
||||||
|
|
||||||
|
# It will be included if you download the plugin from mirror repo(https://github.com/Ark2000/panku_console)
|
||||||
|
const COMMIT_SHA_FILE_PATH = "res://addons/panku_console/COMMIT_SHA"
|
||||||
|
|
||||||
|
static func get_plugin_version() -> String:
|
||||||
|
var error_result = "Unknown version"
|
||||||
|
#load version string from plugin.cfg
|
||||||
|
var cfg = ConfigFile.new()
|
||||||
|
if cfg.load("res://addons/panku_console/plugin.cfg") != OK:
|
||||||
|
return error_result
|
||||||
|
return cfg.get_value("plugin", "version", error_result)
|
||||||
|
|
||||||
|
static func get_commit_sha() -> String:
|
||||||
|
if FileAccess.file_exists(COMMIT_SHA_FILE_PATH):
|
||||||
|
return FileAccess.get_file_as_string(COMMIT_SHA_FILE_PATH)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
static func get_commit_sha_short() -> String:
|
||||||
|
return get_commit_sha().substr(0, 7)
|
||||||
|
|
||||||
|
static func get_commit_url() -> String:
|
||||||
|
var sha := get_commit_sha()
|
||||||
|
if sha != "":
|
||||||
|
return "https://github.com/Ark2000/PankuConsole/commit/" + sha
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# Framerate-independent interpolation.
|
||||||
|
static func interp(from, to, lambda: float, delta: float):
|
||||||
|
if from is Vector2:
|
||||||
|
if abs(from.x - to.x) < 1.0: from.x = to.x
|
||||||
|
if abs(from.y - to.y) < 1.0: from.y = to.y
|
||||||
|
if from is float:
|
||||||
|
if abs(from - to) < 0.01: from = to
|
||||||
|
return lerp(from, to, 1.0 - exp(-lambda * delta))
|
||||||
|
|
||||||
|
#func _run():
|
||||||
|
# print("plugin_version: ", get_plugin_version())
|
||||||
|
# print("commit_sha: ", get_commit_sha())
|
||||||
|
# print("commit_sha_short: ", get_commit_sha_short())
|
||||||
|
# print("commit_url: ", get_commit_url())
|
||||||
1
godot/addons/panku_console/common/utils.gd.uid
Normal file
1
godot/addons/panku_console/common/utils.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://yw3dk5jaii26
|
||||||
86
godot/addons/panku_console/console.gd
Normal file
86
godot/addons/panku_console/console.gd
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
class_name PankuConsole extends CanvasLayer
|
||||||
|
# `console.gd` is a global singleton that provides all modules with a common interface
|
||||||
|
# you can also use some of its members to interact with the console
|
||||||
|
|
||||||
|
signal interactive_shell_visibility_changed(visible:bool)
|
||||||
|
signal new_expression_entered(expression:String, result)
|
||||||
|
signal new_notification_created(bbcode:String, id:int)
|
||||||
|
signal toggle_console_action_just_pressed()
|
||||||
|
|
||||||
|
const SingletonName = "Panku"
|
||||||
|
const SingletonPath = "/root/" + SingletonName
|
||||||
|
const ToggleConsoleAction = "toggle_console"
|
||||||
|
|
||||||
|
# create_data_controller(objs:Array[Object]) -> PankuLynxWindow
|
||||||
|
var create_data_controller_window:Callable = func(objs:Array): return null
|
||||||
|
|
||||||
|
var windows_manager:PankuLynxWindowsManager
|
||||||
|
var module_manager:PankuModuleManager = PankuModuleManager.new()
|
||||||
|
var gd_exprenv:PankuGDExprEnv = PankuGDExprEnv.new()
|
||||||
|
var _shell_visibility := false
|
||||||
|
|
||||||
|
# notification whose id>=0 will be fixed to the bottom of the notification list
|
||||||
|
# useful for loop print
|
||||||
|
# you can use `get_instance_id()` as notification's unique id
|
||||||
|
func notify(any, id=-1) -> void:
|
||||||
|
var text = str(any)
|
||||||
|
new_notification_created.emit(text, id)
|
||||||
|
|
||||||
|
func get_shell_visibility() -> bool:
|
||||||
|
return _shell_visibility
|
||||||
|
|
||||||
|
func _input(event: InputEvent):
|
||||||
|
if event.is_action_pressed(ToggleConsoleAction):
|
||||||
|
toggle_console_action_just_pressed.emit()
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
assert(get_tree().current_scene != self, "Do not run console.tscn as a scene!")
|
||||||
|
|
||||||
|
# Yep, seems like double check project settings in the main singleton
|
||||||
|
# is the only "correct" way to work with custom project setting
|
||||||
|
# https://github.com/godotengine/godot/issues/56598#issuecomment-1904100640
|
||||||
|
PankuConfig.init_all_project_settings()
|
||||||
|
|
||||||
|
if not PankuConfig.is_custom_default_config_exists():
|
||||||
|
push_warning("[Panku Console] Default config file not found. Using code-level default config.")
|
||||||
|
|
||||||
|
windows_manager = $LynxWindowsManager
|
||||||
|
var base_instance = preload("./common/repl_base_instance.gd").new()
|
||||||
|
base_instance._core = self
|
||||||
|
gd_exprenv.set_base_instance(base_instance)
|
||||||
|
|
||||||
|
# add default input action if not defined by user
|
||||||
|
if not InputMap.has_action(ToggleConsoleAction):
|
||||||
|
InputMap.add_action(ToggleConsoleAction)
|
||||||
|
var default_toggle_console_event = InputEventKey.new()
|
||||||
|
default_toggle_console_event.physical_keycode = KEY_QUOTELEFT
|
||||||
|
InputMap.action_add_event(ToggleConsoleAction, default_toggle_console_event)
|
||||||
|
|
||||||
|
# since panku console servers numerous purposes
|
||||||
|
# we use a module system to manage all different features
|
||||||
|
# modules are invisible to each other by design to avoid coupling
|
||||||
|
# you can add or remove any modules here as you wish
|
||||||
|
var modules:Array[PankuModule] = [
|
||||||
|
PankuModuleNativeLogger.new(),
|
||||||
|
PankuModuleScreenNotifier.new(),
|
||||||
|
PankuModuleSystemReport.new(),
|
||||||
|
PankuModuleHistoryManager.new(),
|
||||||
|
PankuModuleEngineTools.new(),
|
||||||
|
PankuModuleKeyboardShortcuts.new(),
|
||||||
|
PankuModuleCheckLatestRelease.new(),
|
||||||
|
PankuModuleInteractiveShell.new(),
|
||||||
|
PankuModuleGeneralSettings.new(),
|
||||||
|
PankuModuleDataController.new(),
|
||||||
|
PankuModuleScreenCrtEffect.new(),
|
||||||
|
PankuModuleExpressionMonitor.new(),
|
||||||
|
PankuModuleTextureViewer.new(),
|
||||||
|
PankuModuleVariableTracker.new(),
|
||||||
|
PankuModuleAbout.new(),
|
||||||
|
PankuModuleSnakeGame.new(),
|
||||||
|
]
|
||||||
|
module_manager.init_manager(self, modules)
|
||||||
|
|
||||||
|
func _notification(what):
|
||||||
|
# quit event
|
||||||
|
if what == NOTIFICATION_WM_CLOSE_REQUEST:
|
||||||
|
module_manager.quit_modules()
|
||||||
1
godot/addons/panku_console/console.gd.uid
Normal file
1
godot/addons/panku_console/console.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://otltxiojr8qu
|
||||||
22
godot/addons/panku_console/console.tscn
Normal file
22
godot/addons/panku_console/console.tscn
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://cyftuo4syatlv"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/console.gd" id="1_dohs1"]
|
||||||
|
[ext_resource type="Theme" uid="uid://bk18yfu0d77wk" path="res://addons/panku_console/res/panku_console_theme.tres" id="2_wxhx6"]
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/common/lynx_window2/lynx_windows_manager_2.gd" id="10_f7qaq"]
|
||||||
|
|
||||||
|
[node name="Console" type="CanvasLayer"]
|
||||||
|
process_mode = 3
|
||||||
|
layer = 128
|
||||||
|
script = ExtResource("1_dohs1")
|
||||||
|
|
||||||
|
[node name="LynxWindowsManager" type="Control" parent="."]
|
||||||
|
z_index = 1
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme = ExtResource("2_wxhx6")
|
||||||
|
script = ExtResource("10_f7qaq")
|
||||||
80
godot/addons/panku_console/default_panku_config.cfg
Normal file
80
godot/addons/panku_console/default_panku_config.cfg
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"enable_os_window": false,
|
||||||
|
"engine_tools": {
|
||||||
|
"time_scale": 1.0
|
||||||
|
},
|
||||||
|
"exp_history": [],
|
||||||
|
"expression_monitor": {
|
||||||
|
"monitor_data": [{
|
||||||
|
"expressions": ["engine_tools.get_performance_info()"],
|
||||||
|
"group_name": "default group"
|
||||||
|
}],
|
||||||
|
"window_position": Vector2(0, 49),
|
||||||
|
"window_size": Vector2(85, 74),
|
||||||
|
"window_visibility": false
|
||||||
|
},
|
||||||
|
"general_settings": {
|
||||||
|
"enable_os_window": false,
|
||||||
|
"lynx_window_base_color": Color(0, 0.0470588, 0.0941176, 0.501961),
|
||||||
|
"lynx_window_blur_effect": true,
|
||||||
|
"lynx_window_enable_os_window": false,
|
||||||
|
"lynx_window_os_window_bg_color": Color(0, 0, 0, 0.658824),
|
||||||
|
"os_window_bg_color": Color(0, 0, 0, 0.992157),
|
||||||
|
"window_blur_effect": true,
|
||||||
|
"window_position": Vector2(429.546, 94.1911),
|
||||||
|
"window_size": Vector2(512.568, 478.128),
|
||||||
|
"window_visibility": true
|
||||||
|
},
|
||||||
|
"history_manager": {
|
||||||
|
"window_position": Vector2(317.728, 138.82),
|
||||||
|
"window_size": Vector2(411.987, 339.537),
|
||||||
|
"window_visibility": false
|
||||||
|
},
|
||||||
|
"interactive_shell": {
|
||||||
|
"gui_mode": 0,
|
||||||
|
"histories": [],
|
||||||
|
"init_expr": "",
|
||||||
|
"output_font_size": 14.0,
|
||||||
|
"pause_if_input": false,
|
||||||
|
"pause_if_popup": false,
|
||||||
|
"show_side_menu": true,
|
||||||
|
"unified_visibility": false,
|
||||||
|
"unified_window_visibility": false,
|
||||||
|
"window_position": Vector2(427.419, 75.3913),
|
||||||
|
"window_size": Vector2(510.736, 410.437),
|
||||||
|
"window_visibility": true
|
||||||
|
},
|
||||||
|
"keyboard_shortcuts": {
|
||||||
|
"key_mapper": [],
|
||||||
|
"window_position": Vector2(0, 49),
|
||||||
|
"window_size": Vector2(85, 74),
|
||||||
|
"window_visibility": false
|
||||||
|
},
|
||||||
|
"native_logger": {
|
||||||
|
"font_size": 17.0,
|
||||||
|
"logger_tags": ["[error]", "[warning]", "[info]"],
|
||||||
|
"screen_overlay": 0,
|
||||||
|
"screen_overlay_alpha": 0.44,
|
||||||
|
"screen_overlay_font_shadow": true,
|
||||||
|
"screen_overlay_font_size": 20.0,
|
||||||
|
"show_timestamp": true,
|
||||||
|
"window_position": Vector2(284.123, 124.547),
|
||||||
|
"window_size": Vector2(483.998, 379.028),
|
||||||
|
"window_visibility": false
|
||||||
|
},
|
||||||
|
"os_window_bg_color": Color(0, 0, 0, 0.992157),
|
||||||
|
"os_window_bgcolor": Color(0, 0, 0, 0.658824),
|
||||||
|
"snake": {
|
||||||
|
"leader_board": [{
|
||||||
|
"score": 40,
|
||||||
|
"timestamp": "2024-01-29T16:00:00"
|
||||||
|
}, {
|
||||||
|
"score": 20,
|
||||||
|
"timestamp": "2024-01-29T16:01:14"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"variable_tracker": {
|
||||||
|
"tracking_delay": 0.5,
|
||||||
|
"use_last_as_current": true
|
||||||
|
}
|
||||||
|
}
|
||||||
25
godot/addons/panku_console/logo.svg
Normal file
25
godot/addons/panku_console/logo.svg
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Created with Vectornator (http://vectornator.io/) -->
|
||||||
|
<svg height="100%" stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;" version="1.1" viewBox="0 0 512 512" width="100%" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs>
|
||||||
|
<path d="M78.6372 264.735L139.342 44.5235L459.206 45.5892L389.109 263.19L78.6372 264.735Z" id="Fill"/>
|
||||||
|
</defs>
|
||||||
|
<g id="图层-2" vectornator:layerName="图层 2">
|
||||||
|
<path d="M0 0L512 0L512 512L0 512L0 0Z" fill="#478cbf" fill-rule="nonzero" opacity="1" stroke="none" vectornator:layerName="长方形 4"/>
|
||||||
|
</g>
|
||||||
|
<g id="图层-1" vectornator:layerName="图层 1">
|
||||||
|
<g opacity="1">
|
||||||
|
<use fill="#478cbf" fill-rule="nonzero" stroke="none" xlink:href="#Fill"/>
|
||||||
|
<mask height="220.212" id="StrokeMask" maskUnits="userSpaceOnUse" width="380.569" x="78.6372" y="44.5235">
|
||||||
|
<rect fill="#000000" height="220.212" stroke="none" width="380.569" x="78.6372" y="44.5235"/>
|
||||||
|
<use fill="#ffffff" fill-rule="evenodd" stroke="none" xlink:href="#Fill"/>
|
||||||
|
</mask>
|
||||||
|
<use fill="none" mask="url(#StrokeMask)" stroke="#ffffff" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="60" xlink:href="#Fill"/>
|
||||||
|
</g>
|
||||||
|
<path d="M229.891 266.654C231.828 264.177 218.37 242.519 220.63 240.48C222.442 238.844 247.135 257.79 249.114 256.443C252.197 254.345 249.038 231.287 252.413 229.909C255.736 228.551 268.109 253.653 271.582 253.015C276.859 252.047 283.021 228.024 288.263 228.781C292.516 229.396 287.421 254.697 291.378 256.495C294.114 257.738 316.072 234.87 318.567 236.696C321.621 238.932 308.408 265.782 310.691 268.58C323.902 284.773 319.362 303.216 304.973 321.62C288.099 343.204 257.612 348.397 236.879 333.219C216.145 318.04 213.017 288.238 229.891 266.654Z" fill="#ffffff" fill-rule="nonzero" opacity="1" stroke="#478cbf" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="8"/>
|
||||||
|
<path d="M73.5951 243.897C40.3754 235.104 50.2275 296.435 80.0691 306.613C92.3236 310.793 154.435 321.768 181.637 337.332C195.509 345.269 187.644 368.316 185.141 375.17C182.469 382.484 173.867 401.273 150.162 406.311C124.07 411.856 84.5598 401.403 73.382 396.752C63.9879 392.842 67.7167 451.378 72.7168 456.046C82.0707 464.776 137.282 465.493 181.93 463.32C225.448 461.202 227.232 403.857 264.785 403.333C285.04 403.051 309.943 401.305 316.067 408.513C331.898 427.144 299.954 467.823 315.414 467.474C337.118 466.984 374.108 467.477 374.108 467.477C374.108 467.477 385.778 455.386 389.874 430.9C393.969 406.415 393.91 386.546 390.488 369.534C386.006 347.25 298.321 345.372 278.96 345.427C268.776 345.456 233.057 349.793 219.907 317.792C214.983 305.809 213.961 301.983 216.883 287.594C220.32 270.672 230.493 259.169 227.398 259.66C184.391 266.486 117.357 255.48 73.5951 243.897Z" fill="#ffffff" fill-rule="nonzero" opacity="1" stroke="#478cbf" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="8"/>
|
||||||
|
<path d="M313.794 266.658C311.539 271.238 320.142 279.678 320.035 289.379C319.921 299.638 313.692 312.301 309.736 317.886C305.122 324.399 309.5 330.672 315.154 330.78C338.818 331.232 376.929 316.129 396.221 307.535C434.181 290.624 458.655 238.94 423.225 234.033C418.517 233.381 397.473 251.601 370.075 259.473C346.488 266.25 315.889 262.405 313.794 266.658Z" fill="#ffffff" fill-rule="nonzero" opacity="1" stroke="#478cbf" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="8"/>
|
||||||
|
<path d="M237.026 95.9347L336.678 154.629L215.794 203.182" fill="none" opacity="1" stroke="#ffffff" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="30"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.7 KiB |
43
godot/addons/panku_console/logo.svg.import
Normal file
43
godot/addons/panku_console/logo.svg.import
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://rkxm4c3bbf34"
|
||||||
|
path="res://.godot/imported/logo.svg-5c6f042742ccac523c072414b9eb3caf.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/panku_console/logo.svg"
|
||||||
|
dest_files=["res://.godot/imported/logo.svg-5c6f042742ccac523c072414b9eb3caf.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
26
godot/addons/panku_console/modules/about/about.gd
Normal file
26
godot/addons/panku_console/modules/about/about.gd
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
extends Control
|
||||||
|
|
||||||
|
var _module:PankuModule
|
||||||
|
|
||||||
|
@export var intro:Label
|
||||||
|
@export var project_page_button:Button
|
||||||
|
@export var check_update_button:Button
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
var version:String = PankuUtils.get_plugin_version()
|
||||||
|
var sha:String = PankuUtils.get_commit_sha_short()
|
||||||
|
if sha == "": sha = "Unknown"
|
||||||
|
|
||||||
|
intro.text = intro.text.replace("<version>", version)
|
||||||
|
intro.text = intro.text.replace("<commit>", sha)
|
||||||
|
|
||||||
|
project_page_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
OS.shell_open("https://github.com/Ark2000/PankuConsole")
|
||||||
|
)
|
||||||
|
|
||||||
|
check_update_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
_module.core.gd_exprenv.execute("check_latest_release.check()")
|
||||||
|
)
|
||||||
1
godot/addons/panku_console/modules/about/about.gd.uid
Normal file
1
godot/addons/panku_console/modules/about/about.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://pkgdt4duvguc
|
||||||
215
godot/addons/panku_console/modules/about/about.tscn
Normal file
215
godot/addons/panku_console/modules/about/about.tscn
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
[gd_scene load_steps=10 format=3 uid="uid://cgwg3foes57mq"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/modules/about/about.gd" id="1_kpix3"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dyq4rjkkjs55d" path="res://addons/panku_console/common/smooth_scroll/smooth_scroll.tscn" id="2_sev6e"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://rkxm4c3bbf34" path="res://addons/panku_console/logo.svg" id="3_eycho"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cxmplwhfv5l88" path="res://addons/panku_console/modules/about/url_button.tscn" id="4_cqu2c"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_knn3o"]
|
||||||
|
content_margin_left = 8.0
|
||||||
|
content_margin_top = 8.0
|
||||||
|
content_margin_right = 8.0
|
||||||
|
content_margin_bottom = 8.0
|
||||||
|
bg_color = Color(0, 0, 0, 0.270588)
|
||||||
|
|
||||||
|
[sub_resource type="FontVariation" id="FontVariation_v70xy"]
|
||||||
|
variation_embolden = 0.5
|
||||||
|
|
||||||
|
[sub_resource type="FontVariation" id="FontVariation_wgi7f"]
|
||||||
|
variation_embolden = 0.5
|
||||||
|
|
||||||
|
[sub_resource type="SystemFont" id="SystemFont_6on77"]
|
||||||
|
font_names = PackedStringArray("Monospace")
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_cqcex"]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color(0, 0, 0, 0.25098)
|
||||||
|
corner_radius_top_left = 4
|
||||||
|
corner_radius_top_right = 4
|
||||||
|
corner_radius_bottom_right = 4
|
||||||
|
corner_radius_bottom_left = 4
|
||||||
|
|
||||||
|
[node name="about" type="Control" node_paths=PackedStringArray("intro", "project_page_button", "check_update_button")]
|
||||||
|
clip_contents = true
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_kpix3")
|
||||||
|
intro = NodePath("VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/PanelContainer/HBoxContainer/Label")
|
||||||
|
project_page_button = NodePath("VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/HBoxContainer/ProjectPageButton")
|
||||||
|
check_update_button = NodePath("VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/HBoxContainer/CheckUpdateButton")
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = -1
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 8.0
|
||||||
|
offset_top = 8.0
|
||||||
|
offset_right = -8.0
|
||||||
|
offset_bottom = -8.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="SmoothScrollContainer" parent="VBoxContainer" instance=ExtResource("2_sev6e")]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
follow_content = false
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control" index="0"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 10
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_bottom = 995.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
|
||||||
|
[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_knn3o")
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/PanelContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="TextureRect" type="TextureRect" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/PanelContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
texture = ExtResource("3_eycho")
|
||||||
|
expand_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/PanelContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Panku Console <version> [<commit>]
|
||||||
|
© 2022-present Panku Console contributors.
|
||||||
|
© 2022 Ark2000.
|
||||||
|
"
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Panku Console is a feature-packed real-time debugging toolkit for Godot Engine."
|
||||||
|
clip_text = true
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="ProjectPageButton" type="Button" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme_override_fonts/font = SubResource("FontVariation_v70xy")
|
||||||
|
text = "Project Page"
|
||||||
|
|
||||||
|
[node name="CheckUpdateButton" type="Button" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme_override_fonts/font = SubResource("FontVariation_v70xy")
|
||||||
|
text = "Check Update"
|
||||||
|
|
||||||
|
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_fonts/font = SubResource("FontVariation_wgi7f")
|
||||||
|
text = "Project Manager"
|
||||||
|
|
||||||
|
[node name="Button" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer" instance=ExtResource("4_cqu2c")]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Feo Wu (Ark2000)"
|
||||||
|
url = "https://github.com/Ark2000"
|
||||||
|
|
||||||
|
[node name="Label2" type="Label" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_fonts/font = SubResource("FontVariation_wgi7f")
|
||||||
|
text = "Contributors"
|
||||||
|
|
||||||
|
[node name="Button2" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer" instance=ExtResource("4_cqu2c")]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Feo Wu (Ark2000)"
|
||||||
|
url = "https://github.com/Ark2000"
|
||||||
|
|
||||||
|
[node name="Button3" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer" instance=ExtResource("4_cqu2c")]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Rafael Correa (scriptsengineer)"
|
||||||
|
url = "https://github.com/scriptsengineer"
|
||||||
|
|
||||||
|
[node name="Button4" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer" instance=ExtResource("4_cqu2c")]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "worron"
|
||||||
|
url = "https://github.com/worron"
|
||||||
|
|
||||||
|
[node name="Button5" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer" instance=ExtResource("4_cqu2c")]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "mieldepoche"
|
||||||
|
url = "https://github.com/mieldepoche"
|
||||||
|
|
||||||
|
[node name="Button6" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer" instance=ExtResource("4_cqu2c")]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Eggbertx"
|
||||||
|
url = "https://github.com/Eggbertx"
|
||||||
|
|
||||||
|
[node name="Button7" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer" instance=ExtResource("4_cqu2c")]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "univeous"
|
||||||
|
url = "https://github.com/univeous"
|
||||||
|
|
||||||
|
[node name="Button8" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer" instance=ExtResource("4_cqu2c")]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "CheapMeow"
|
||||||
|
url = "https://github.com/CheapMeow"
|
||||||
|
|
||||||
|
[node name="Button9" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer" instance=ExtResource("4_cqu2c")]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "winston-yallow (Winston)"
|
||||||
|
url = "https://github.com/winston-yallow"
|
||||||
|
|
||||||
|
[node name="Label3" type="Label" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_fonts/font = SubResource("FontVariation_wgi7f")
|
||||||
|
text = "Icons"
|
||||||
|
|
||||||
|
[node name="Button10" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer" instance=ExtResource("4_cqu2c")]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "SVG Repo"
|
||||||
|
url = "https://www.svgrepo.com/page/licensing/"
|
||||||
|
|
||||||
|
[node name="Label4" type="Label" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_fonts/font = SubResource("FontVariation_wgi7f")
|
||||||
|
text = "License"
|
||||||
|
|
||||||
|
[node name="Label5" type="Label" parent="VBoxContainer/SmoothScrollContainer/HBoxContainer/Control/VBoxContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_fonts/font = SubResource("SystemFont_6on77")
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxFlat_cqcex")
|
||||||
|
text = "The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2022-present Panku Console contributors.
|
||||||
|
Copyright (c) 2022 Ark2000
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the \"Software\"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
|
||||||
|
clip_text = true
|
||||||
|
|
||||||
|
[editable path="VBoxContainer/SmoothScrollContainer"]
|
||||||
5
godot/addons/panku_console/modules/about/env.gd
Normal file
5
godot/addons/panku_console/modules/about/env.gd
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
var _module:PankuModule
|
||||||
|
|
||||||
|
const _HELP_open = "Open about window"
|
||||||
|
func open() -> void:
|
||||||
|
_module.open_window()
|
||||||
1
godot/addons/panku_console/modules/about/env.gd.uid
Normal file
1
godot/addons/panku_console/modules/about/env.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://cbd0wepa77b0c
|
||||||
15
godot/addons/panku_console/modules/about/module.gd
Normal file
15
godot/addons/panku_console/modules/about/module.gd
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
class_name PankuModuleAbout extends PankuModule
|
||||||
|
|
||||||
|
var window:PankuLynxWindow
|
||||||
|
const ui = preload("./about.tscn")
|
||||||
|
|
||||||
|
func open_window():
|
||||||
|
if window: return
|
||||||
|
var ui_instance = ui.instantiate()
|
||||||
|
ui_instance._module = self
|
||||||
|
window = core.windows_manager.create_window(ui_instance)
|
||||||
|
window.set_window_title_text("About")
|
||||||
|
window.show_window()
|
||||||
|
window.window_closed.connect(
|
||||||
|
func(): window = null
|
||||||
|
)
|
||||||
1
godot/addons/panku_console/modules/about/module.gd.uid
Normal file
1
godot/addons/panku_console/modules/about/module.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://bhcijrphn6uto
|
||||||
9
godot/addons/panku_console/modules/about/url_button.gd
Normal file
9
godot/addons/panku_console/modules/about/url_button.gd
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
extends Button
|
||||||
|
|
||||||
|
@export var url:String
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
pressed.connect(
|
||||||
|
func():
|
||||||
|
OS.shell_open(url)
|
||||||
|
)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://btw5pitk8auv6
|
||||||
17
godot/addons/panku_console/modules/about/url_button.tscn
Normal file
17
godot/addons/panku_console/modules/about/url_button.tscn
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://cxmplwhfv5l88"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/modules/about/url_button.gd" id="1_01blg"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ivnlg"]
|
||||||
|
content_margin_left = 8.0
|
||||||
|
bg_color = Color(0, 0, 0, 0.243137)
|
||||||
|
corner_radius_top_left = 4
|
||||||
|
corner_radius_top_right = 4
|
||||||
|
corner_radius_bottom_right = 4
|
||||||
|
corner_radius_bottom_left = 4
|
||||||
|
|
||||||
|
[node name="Button" type="Button"]
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxFlat_ivnlg")
|
||||||
|
text = "Button Text"
|
||||||
|
alignment = 0
|
||||||
|
script = ExtResource("1_01blg")
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
var _module:PankuModule
|
||||||
|
|
||||||
|
const _HELP_check = "Fetch latest release information from Github"
|
||||||
|
func check():
|
||||||
|
_module.check()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://dad7nd3c3hjqv
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
class_name PankuModuleCheckLatestRelease extends PankuModule
|
||||||
|
|
||||||
|
signal check_lasted_release_requested()
|
||||||
|
signal check_lasted_release_responded(msg:Dictionary)
|
||||||
|
|
||||||
|
func send_request() -> Node:
|
||||||
|
var node = preload("./network.gd").new()
|
||||||
|
core.add_child(node)
|
||||||
|
node.check_latest_release()
|
||||||
|
node.response_received.connect(
|
||||||
|
func(_v): node.queue_free()
|
||||||
|
)
|
||||||
|
return node
|
||||||
|
|
||||||
|
func check_update():
|
||||||
|
send_request().response_received.connect(
|
||||||
|
func(msg:Dictionary):
|
||||||
|
check_lasted_release_responded.emit(msg)
|
||||||
|
)
|
||||||
|
|
||||||
|
func check():
|
||||||
|
send_request().response_received.connect(
|
||||||
|
func(msg:Dictionary):
|
||||||
|
if !msg["success"]:
|
||||||
|
core.notify("[color=red][Error][/color] Failed! " + msg["msg"])
|
||||||
|
else:
|
||||||
|
core.notify("[color=green][info][/color] Latest: [%s] [url=%s]%s[/url]" % [msg["published_at"], msg["html_url"], msg["name"]])
|
||||||
|
)
|
||||||
|
|
||||||
|
func init_module():
|
||||||
|
# implement core functions
|
||||||
|
check_lasted_release_requested.connect(check_update)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://ba42o6b87vvna
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
extends HTTPRequest
|
||||||
|
|
||||||
|
signal response_received(msg:Dictionary)
|
||||||
|
|
||||||
|
const LATEST_RELEASE_URL = "https://api.github.com/repos/Ark2000/PankuConsole/releases/latest"
|
||||||
|
|
||||||
|
const REQUEST_RESULT = {
|
||||||
|
RESULT_SUCCESS: "SUCCESS",
|
||||||
|
RESULT_CHUNKED_BODY_SIZE_MISMATCH: "CHUNKED_BODY_SIZE_MISMATCH",
|
||||||
|
RESULT_CANT_CONNECT: "CANT_CONNECT",
|
||||||
|
RESULT_CANT_RESOLVE: "CANT_RESOLVE",
|
||||||
|
RESULT_CONNECTION_ERROR: "CONNECTION_ERROR",
|
||||||
|
RESULT_TLS_HANDSHAKE_ERROR: "TLS_HANDSHAKE_ERROR",
|
||||||
|
RESULT_NO_RESPONSE: "NO_RESPONSE",
|
||||||
|
RESULT_BODY_SIZE_LIMIT_EXCEEDED: "BODY_SIZE_LIMIT_EXCEEDED",
|
||||||
|
RESULT_BODY_DECOMPRESS_FAILED: "BODY_DECOMPRESS_FAILED",
|
||||||
|
RESULT_REQUEST_FAILED: "REQUEST_FAILED",
|
||||||
|
RESULT_DOWNLOAD_FILE_CANT_OPEN: "DOWNLOAD_FILE_CANT_OPEN",
|
||||||
|
RESULT_DOWNLOAD_FILE_WRITE_ERROR: "DOWNLOAD_FILE_WRITE_ERROR",
|
||||||
|
RESULT_REDIRECT_LIMIT_REACHED: "REDIRECT_LIMIT_REACHED",
|
||||||
|
RESULT_TIMEOUT: "TIMEOUT"
|
||||||
|
}
|
||||||
|
|
||||||
|
static func dget(dict:Dictionary, key, default_value=""):
|
||||||
|
return default_value if !dict.has(key) else dict[key]
|
||||||
|
|
||||||
|
var is_busy := false
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
request_completed.connect(_on_request_completed)
|
||||||
|
|
||||||
|
func check_latest_release():
|
||||||
|
if is_busy: return
|
||||||
|
is_busy = true
|
||||||
|
var error = request(LATEST_RELEASE_URL)
|
||||||
|
if error != OK:
|
||||||
|
is_busy = false
|
||||||
|
response_received.emit({
|
||||||
|
"success": false,
|
||||||
|
"msg": "An error occurred in the HTTP request."
|
||||||
|
})
|
||||||
|
|
||||||
|
func _on_request_completed(result:int, response_code:int, headers:PackedStringArray, body:PackedByteArray):
|
||||||
|
is_busy = false
|
||||||
|
if result != RESULT_SUCCESS:
|
||||||
|
response_received.emit({
|
||||||
|
"success": false,
|
||||||
|
"msg": REQUEST_RESULT[result]
|
||||||
|
})
|
||||||
|
return
|
||||||
|
var json = JSON.new()
|
||||||
|
json.parse(body.get_string_from_utf8())
|
||||||
|
var response:Dictionary = json.get_data()
|
||||||
|
response_received.emit({
|
||||||
|
"success": true,
|
||||||
|
"published_at": dget(response, "published_at", "???"),
|
||||||
|
"name": dget(response, "name", "???"),
|
||||||
|
"html_url": dget(response, "html_url", "???")
|
||||||
|
})
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://dojjr6xbfugxm
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
extends ModuleOptions
|
||||||
|
|
||||||
|
@export_group("check_latest_release")
|
||||||
|
|
||||||
|
@export var export_button_check_update := "Check Update"
|
||||||
|
|
||||||
|
func check_update():
|
||||||
|
_module.check()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://dwah7jcf3nn6i
|
||||||
30
godot/addons/panku_console/modules/engine_tools/env.gd
Normal file
30
godot/addons/panku_console/modules/engine_tools/env.gd
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
var _module:PankuModule
|
||||||
|
|
||||||
|
const _HELP_toggle_fullscreen = "Toggle [fullscreen / windowed] mode"
|
||||||
|
func toggle_fullscreen() -> void:
|
||||||
|
_module.toggle_fullscreen()
|
||||||
|
|
||||||
|
const _HELP_set_time_scale = "Equals to [color=green]Engine.time_scale[/color]"
|
||||||
|
func set_time_scale(val:float) -> void:
|
||||||
|
_module.set_time_scale(val)
|
||||||
|
|
||||||
|
const _HELP_get_performance_info = "Show performance info"
|
||||||
|
func get_performance_info(count_nodes := false) -> String:
|
||||||
|
return _module.get_performance_info(count_nodes)
|
||||||
|
|
||||||
|
const _HELP_take_screenshot = "Take a screenshot of current window"
|
||||||
|
func take_screenshot() -> void:
|
||||||
|
_module.take_screenshot()
|
||||||
|
|
||||||
|
const _HELP_quit = "Quit application"
|
||||||
|
func quit() -> void:
|
||||||
|
_module.quit()
|
||||||
|
|
||||||
|
const _HELP_toggle_2d_collision_shape_visibility = "Toggle visibility of 2D collision shapes, useful for debugging"
|
||||||
|
func toggle_2d_collision_shape_visibility() -> void:
|
||||||
|
_module.toggle_2d_collision_shape_visibility()
|
||||||
|
|
||||||
|
const _HELP_reload_current_scene = "Reload current scene"
|
||||||
|
func reload_current_scene() -> void:
|
||||||
|
_module.reload_current_scene()
|
||||||
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://b02ldrmvchylr
|
||||||
72
godot/addons/panku_console/modules/engine_tools/module.gd
Normal file
72
godot/addons/panku_console/modules/engine_tools/module.gd
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
class_name PankuModuleEngineTools extends PankuModule
|
||||||
|
|
||||||
|
func init_module():
|
||||||
|
get_module_opt().count_nodes = load_module_data("count_nodes", false)
|
||||||
|
super.init_module()
|
||||||
|
|
||||||
|
func toggle_fullscreen() -> void:
|
||||||
|
if DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_WINDOWED:
|
||||||
|
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
|
||||||
|
else:
|
||||||
|
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
|
||||||
|
core.notify("Fullscreen: " + str(DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN))
|
||||||
|
|
||||||
|
func set_time_scale(val:float) -> void:
|
||||||
|
Engine.time_scale = val
|
||||||
|
|
||||||
|
class ClsCountNodesInTree:
|
||||||
|
func calc_children_count(core: PankuConsole, node_path: String) -> int:
|
||||||
|
var nd: Node = core.get_tree().current_scene.get_node(node_path)
|
||||||
|
return count_all_children(nd)
|
||||||
|
func count_all_children(nd: Node) -> int:
|
||||||
|
var count: int = nd.get_children().size()
|
||||||
|
for child: Node in nd.get_children():
|
||||||
|
count += count_all_children(child)
|
||||||
|
return count
|
||||||
|
|
||||||
|
func get_performance_info(count_nodes:bool) -> String:
|
||||||
|
var result = "FPS: %d | Mem: %.2fMB | Objs: %d" % [
|
||||||
|
Engine.get_frames_per_second(),
|
||||||
|
OS.get_static_memory_usage()/1048576.0,
|
||||||
|
Performance.get_monitor(Performance.OBJECT_COUNT)
|
||||||
|
]
|
||||||
|
if count_nodes:
|
||||||
|
var cls_count: ClsCountNodesInTree = ClsCountNodesInTree.new()
|
||||||
|
var root_count: int = cls_count.calc_children_count(core, "/root")
|
||||||
|
var panku_count: int = cls_count.calc_children_count(core, "/root/Panku")
|
||||||
|
result += " | Nodes: %d" % [root_count - panku_count]
|
||||||
|
return result
|
||||||
|
|
||||||
|
func take_screenshot() -> void:
|
||||||
|
var image = core.get_viewport().get_texture().get_image()
|
||||||
|
var time = str(int(Time.get_unix_time_from_system() * 1000.0))
|
||||||
|
var file_name = "screenshot_%s.png" % time
|
||||||
|
var path = "user://".path_join(file_name)
|
||||||
|
var real_path = OS.get_user_data_dir().path_join(file_name)
|
||||||
|
image.save_png(path)
|
||||||
|
core.notify("[b]Screenshot[/b] saved at [color=green][url=%s]%s[/url][/color]" % [real_path, real_path])
|
||||||
|
|
||||||
|
func quit() -> void:
|
||||||
|
core.get_tree().root.propagate_notification(core.NOTIFICATION_WM_CLOSE_REQUEST)
|
||||||
|
core.get_tree().quit()
|
||||||
|
|
||||||
|
# Currently godot can't toggle visibility of 2D collision shapes at runtime, this is a workaround.
|
||||||
|
# See https://github.com/godotengine/godot-proposals/issues/2072
|
||||||
|
func toggle_2d_collision_shape_visibility() -> void:
|
||||||
|
var tree := core.get_tree()
|
||||||
|
tree.debug_collisions_hint = not tree.debug_collisions_hint
|
||||||
|
|
||||||
|
# Traverse tree to call queue_redraw on instances of
|
||||||
|
# CollisionShape2D and CollisionPolygon2D.
|
||||||
|
var node_stack: Array[Node] = [tree.get_root()]
|
||||||
|
while not node_stack.is_empty():
|
||||||
|
var node: Node = node_stack.pop_back()
|
||||||
|
if is_instance_valid(node):
|
||||||
|
if node is CollisionShape2D or node is CollisionPolygon2D:
|
||||||
|
node.queue_redraw()
|
||||||
|
node_stack.append_array(node.get_children())
|
||||||
|
core.notify("2D Debug Draw: " + str(tree.debug_collisions_hint))
|
||||||
|
|
||||||
|
func reload_current_scene() -> void:
|
||||||
|
core.get_tree().reload_current_scene()
|
||||||
|
core.notify("Scene reloaded")
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://dan217hmehfix
|
||||||
40
godot/addons/panku_console/modules/engine_tools/opt.gd
Normal file
40
godot/addons/panku_console/modules/engine_tools/opt.gd
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
extends ModuleOptions
|
||||||
|
|
||||||
|
@export_group("engine_tools")
|
||||||
|
|
||||||
|
@export var export_button_toggle_fullscreen := "Toggle Fullscreen"
|
||||||
|
|
||||||
|
func toggle_fullscreen():
|
||||||
|
_module.toggle_fullscreen()
|
||||||
|
|
||||||
|
@export var export_button_take_screenshot := "Take Screenshot"
|
||||||
|
|
||||||
|
func take_screenshot():
|
||||||
|
_module.take_screenshot()
|
||||||
|
|
||||||
|
@export var export_button_quit := "Quit"
|
||||||
|
|
||||||
|
func quit():
|
||||||
|
_module.quit()
|
||||||
|
|
||||||
|
@export var export_button_toggle_2d_debug_draw := "Toggle 2D Debug Draw"
|
||||||
|
|
||||||
|
func toggle_2d_debug_draw():
|
||||||
|
_module.toggle_2d_collision_shape_visibility()
|
||||||
|
|
||||||
|
@export var export_button_reload_current_scene := "Reload Current Scene"
|
||||||
|
|
||||||
|
func reload_current_scene():
|
||||||
|
_module.reload_current_scene()
|
||||||
|
|
||||||
|
@export_range(0.1, 10.0, 0.01) var time_scale := 1.0:
|
||||||
|
set(v):
|
||||||
|
time_scale = v
|
||||||
|
_module.set_time_scale(time_scale)
|
||||||
|
|
||||||
|
@export var export_comment_count_nodes = "Show node count in performance info (can issue extra performance hit)."
|
||||||
|
@export var count_nodes := false
|
||||||
|
|
||||||
|
@export var readonly_performance_info:String:
|
||||||
|
get:
|
||||||
|
return _module.get_performance_info(count_nodes)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://v2u6b17gkyxf
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
var _module:PankuModule
|
||||||
|
|
||||||
|
func open_window():
|
||||||
|
_module.open_window()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://cwk00j0krbxbk
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
extends Control
|
||||||
|
|
||||||
|
signal expr_changed(new_expr:String)
|
||||||
|
signal removing
|
||||||
|
|
||||||
|
@export var x_btn:Button
|
||||||
|
@export var ledit:LineEdit
|
||||||
|
@export var label:Label
|
||||||
|
|
||||||
|
func set_result(text:String):
|
||||||
|
label.text = text
|
||||||
|
label.get_parent().visible = (text != "")
|
||||||
|
|
||||||
|
func set_expr(text:String):
|
||||||
|
ledit.text = text
|
||||||
|
|
||||||
|
func get_expr() -> String:
|
||||||
|
return ledit.text
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
x_btn.pressed.connect(
|
||||||
|
func():
|
||||||
|
removing.emit()
|
||||||
|
queue_free()
|
||||||
|
)
|
||||||
|
ledit.focus_exited.connect(
|
||||||
|
func():
|
||||||
|
expr_changed.emit(ledit.text)
|
||||||
|
)
|
||||||
|
ledit.text_submitted.connect(
|
||||||
|
func(new_text:String):
|
||||||
|
expr_changed.emit(new_text)
|
||||||
|
)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://cncy7a8mdovjf
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://om8bp40jo1e"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/modules/expression_monitor/expression_item.gd" id="1_dnu23"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://8g5afcuanbl6" path="res://addons/panku_console/res/icons2/close.svg" id="2_bc3ds"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://drn5t13m088fb" path="res://addons/panku_console/common/panku_button.tscn" id="3_n03xa"]
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" node_paths=PackedStringArray("x_btn", "ledit", "label")]
|
||||||
|
anchors_preset = 10
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_bottom = 31.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
script = ExtResource("1_dnu23")
|
||||||
|
x_btn = NodePath("expression_item/PankuButton/Button")
|
||||||
|
ledit = NodePath("expression_item/LineEdit")
|
||||||
|
label = NodePath("HBoxContainer/Label")
|
||||||
|
|
||||||
|
[node name="expression_item" type="HBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="PankuButton" parent="expression_item" instance=ExtResource("3_n03xa")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="expression_item/PankuButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("2_bc3ds")
|
||||||
|
|
||||||
|
[node name="LineEdit" type="LineEdit" parent="expression_item"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
placeholder_text = "Input expression here..."
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="ColorRect" type="ColorRect" parent="HBoxContainer"]
|
||||||
|
custom_minimum_size = Vector2(8, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
color = Color(0.239216, 0.533333, 0.886275, 0.752941)
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
autowrap_mode = 1
|
||||||
|
|
||||||
|
[editable path="expression_item/PankuButton"]
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
extends Control
|
||||||
|
|
||||||
|
@onready var monitor_groups_ui := $SmoothScrollContainer/HBoxContainer/Control/MonitorGroupsUI
|
||||||
|
|
||||||
|
var _module:PankuModule
|
||||||
|
|
||||||
|
func _physics_process(delta: float) -> void:
|
||||||
|
if Engine.get_physics_frames() % 10 != 1:
|
||||||
|
return
|
||||||
|
if !is_visible_in_tree():
|
||||||
|
return
|
||||||
|
|
||||||
|
var exprss = monitor_groups_ui.get_expressions_by_group()
|
||||||
|
var resultss = []
|
||||||
|
for exprs in exprss:
|
||||||
|
var results = []
|
||||||
|
for expr in exprs:
|
||||||
|
if expr == "":
|
||||||
|
continue
|
||||||
|
var eval_result_dict = _module.core.gd_exprenv.execute(expr)
|
||||||
|
var eval_result:String = str(eval_result_dict["result"])
|
||||||
|
results.append(eval_result)
|
||||||
|
resultss.append(results)
|
||||||
|
monitor_groups_ui.set_results_by_group(resultss)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://jkmkx3lj1vj3
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://biuybfe60pr4u"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/modules/expression_monitor/expression_monitor2.gd" id="1_ha27e"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dyq4rjkkjs55d" path="res://addons/panku_console/common/smooth_scroll/smooth_scroll.tscn" id="2_6rd5x"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://ctgf7kewoa1cn" path="res://addons/panku_console/modules/expression_monitor/monitor_groups_ui.tscn" id="2_sa5u0"]
|
||||||
|
|
||||||
|
[node name="expression_monitor2" type="Control"]
|
||||||
|
clip_contents = true
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_ha27e")
|
||||||
|
|
||||||
|
[node name="SmoothScrollContainer" parent="." instance=ExtResource("2_6rd5x")]
|
||||||
|
layout_mode = 1
|
||||||
|
|
||||||
|
[node name="MonitorGroupsUI" parent="SmoothScrollContainer/HBoxContainer/Control" index="0" instance=ExtResource("2_sa5u0")]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_right = 0.0
|
||||||
|
offset_bottom = 0.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[editable path="SmoothScrollContainer"]
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
class_name PankuModuleExpressionMonitor extends PankuModule
|
||||||
|
|
||||||
|
var monitor
|
||||||
|
var monitor_window:PankuLynxWindow
|
||||||
|
|
||||||
|
func init_module():
|
||||||
|
init_monitor_window()
|
||||||
|
load_window_data(monitor_window)
|
||||||
|
monitor.monitor_groups_ui.load_persistent_data(load_module_data("monitor_data", [{
|
||||||
|
"group_name": "default group",
|
||||||
|
"expressions": []
|
||||||
|
}]))
|
||||||
|
|
||||||
|
func quit_module():
|
||||||
|
super.quit_module()
|
||||||
|
save_window_data(monitor_window)
|
||||||
|
save_module_data("monitor_data", monitor.monitor_groups_ui.get_persistent_data())
|
||||||
|
|
||||||
|
func init_monitor_window():
|
||||||
|
monitor = preload("./expression_monitor2.tscn").instantiate()
|
||||||
|
monitor._module = self
|
||||||
|
# monitor.set_data(load_module_data("exprs", []))
|
||||||
|
monitor_window = core.windows_manager.create_window(monitor)
|
||||||
|
add_auto_save_hook(monitor_window)
|
||||||
|
monitor_window.queue_free_on_close = false
|
||||||
|
monitor_window.set_window_title_text("Expression Monitor")
|
||||||
|
|
||||||
|
func open_window():
|
||||||
|
monitor_window.show_window()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://bk4d660m07xto
|
||||||
@ -0,0 +1,133 @@
|
|||||||
|
extends VBoxContainer
|
||||||
|
|
||||||
|
signal group_move_up
|
||||||
|
signal group_move_down
|
||||||
|
|
||||||
|
const exp_item_ui_prefab:PackedScene = preload("./expression_item.tscn")
|
||||||
|
const play_icon:Texture2D = preload("res://addons/panku_console/res/icons2/play-1001-svgrepo-com.svg")
|
||||||
|
const pause_icon:Texture2D = preload("res://addons/panku_console/res/icons2/pause-1010-svgrepo-com.svg")
|
||||||
|
const expand_icon:Texture2D = preload("res://addons/panku_console/res/icons2/chevron_right.svg")
|
||||||
|
const collapse_icon:Texture2D = preload("res://addons/panku_console/res/icons2/expand_more.svg")
|
||||||
|
|
||||||
|
@onready var group_toggle_button:Button = $GroupManager/ToggleButton
|
||||||
|
@onready var rename_line_edit:LineEdit = $GroupManager/RenameLineEdit
|
||||||
|
@onready var state_control_button:PankuButton = $GroupManager/StateControlButton
|
||||||
|
@onready var rename_button:PankuButton = $GroupManager/RenameButton
|
||||||
|
@onready var confirm_rename_button:PankuButton = $GroupManager/ConfirmRenameButton
|
||||||
|
@onready var cancel_rename_button:PankuButton = $GroupManager/CancelRenameButton
|
||||||
|
@onready var move_up_button:PankuButton = $GroupManager/MoveUpButton
|
||||||
|
@onready var move_down_button:PankuButton = $GroupManager/MoveDownButton
|
||||||
|
|
||||||
|
@onready var exp_body_container:Control = $PanelContainer
|
||||||
|
@onready var exp_container:Control = $PanelContainer/VBoxContainer/ExpressionContainer
|
||||||
|
@onready var add_exp_button:Button = $PanelContainer/VBoxContainer/AddNewExpressionButton
|
||||||
|
@onready var remove_this_group_button:PankuButton = $GroupManager/RemoveButton
|
||||||
|
|
||||||
|
@onready var normal_ui_group:Array = [
|
||||||
|
group_toggle_button,
|
||||||
|
state_control_button,
|
||||||
|
rename_button
|
||||||
|
]
|
||||||
|
|
||||||
|
@onready var edit_ui_group:Array = [
|
||||||
|
rename_line_edit,
|
||||||
|
confirm_rename_button,
|
||||||
|
cancel_rename_button,
|
||||||
|
move_up_button,
|
||||||
|
move_down_button,
|
||||||
|
remove_this_group_button
|
||||||
|
]
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
edit_ui_group.map(func(item): item.hide())
|
||||||
|
normal_ui_group.map(func(item): item.show())
|
||||||
|
exp_body_container.hide()
|
||||||
|
|
||||||
|
group_toggle_button.toggle_mode = true
|
||||||
|
group_toggle_button.button_pressed = false
|
||||||
|
group_toggle_button.toggled.connect(
|
||||||
|
func(button_pressed:bool):
|
||||||
|
exp_body_container.visible = button_pressed
|
||||||
|
group_toggle_button.icon = collapse_icon if button_pressed else expand_icon
|
||||||
|
)
|
||||||
|
|
||||||
|
add_exp_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
var exp_item = exp_item_ui_prefab.instantiate()
|
||||||
|
exp_container.add_child(exp_item)
|
||||||
|
)
|
||||||
|
|
||||||
|
state_control_button.button.toggle_mode = true
|
||||||
|
state_control_button.button.button_pressed = false
|
||||||
|
state_control_button.button.toggled.connect(
|
||||||
|
func(button_pressed:bool):
|
||||||
|
state_control_button.icon = pause_icon if button_pressed else play_icon
|
||||||
|
)
|
||||||
|
|
||||||
|
rename_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
edit_ui_group.map(func(item): item.show())
|
||||||
|
normal_ui_group.map(func(item): item.hide())
|
||||||
|
rename_line_edit.text = group_toggle_button.text
|
||||||
|
)
|
||||||
|
|
||||||
|
cancel_rename_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
edit_ui_group.map(func(item): item.hide())
|
||||||
|
normal_ui_group.map(func(item): item.show())
|
||||||
|
)
|
||||||
|
|
||||||
|
confirm_rename_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
edit_ui_group.map(func(item): item.hide())
|
||||||
|
normal_ui_group.map(func(item): item.show())
|
||||||
|
group_toggle_button.text = rename_line_edit.text
|
||||||
|
)
|
||||||
|
|
||||||
|
move_up_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
group_move_up.emit()
|
||||||
|
)
|
||||||
|
|
||||||
|
move_down_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
group_move_down.emit()
|
||||||
|
)
|
||||||
|
|
||||||
|
remove_this_group_button.pressed.connect(queue_free)
|
||||||
|
|
||||||
|
load_persistent_data({
|
||||||
|
"group_name": "Unnamed Group",
|
||||||
|
"expressions": []
|
||||||
|
})
|
||||||
|
|
||||||
|
func get_expressions(show_hidden := false) -> Array:
|
||||||
|
# optimization?
|
||||||
|
var exps = []
|
||||||
|
if state_control_button.button.button_pressed or show_hidden:
|
||||||
|
for child in exp_container.get_children():
|
||||||
|
exps.append(child.get_expr())
|
||||||
|
return exps
|
||||||
|
|
||||||
|
func set_results(results:Array):
|
||||||
|
if results.size() > exp_container.get_child_count():
|
||||||
|
push_error("unexpected parameters.")
|
||||||
|
return
|
||||||
|
for i in range(results.size()):
|
||||||
|
var result:String = results[i]
|
||||||
|
exp_container.get_child(i).set_result(result)
|
||||||
|
|
||||||
|
func get_persistent_data() -> Dictionary:
|
||||||
|
return {
|
||||||
|
"group_name": group_toggle_button.text,
|
||||||
|
"expressions": get_expressions(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func load_persistent_data(data:Dictionary):
|
||||||
|
group_toggle_button.text = data["group_name"]
|
||||||
|
for child in exp_container.get_children():
|
||||||
|
child.queue_free()
|
||||||
|
for exp in data["expressions"]:
|
||||||
|
var exp_item = exp_item_ui_prefab.instantiate()
|
||||||
|
exp_container.add_child(exp_item)
|
||||||
|
exp_item.set_expr(exp)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://pnr5pml8b4y6
|
||||||
@ -0,0 +1,145 @@
|
|||||||
|
[gd_scene load_steps=17 format=3 uid="uid://dlnkho5p7p2aq"]
|
||||||
|
|
||||||
|
[ext_resource type="Theme" uid="uid://bk18yfu0d77wk" path="res://addons/panku_console/res/panku_console_theme.tres" id="1_5nvur"]
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/modules/expression_monitor/monitor_group_ui.gd" id="1_b5egi"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://ws58gucuygx1" path="res://addons/panku_console/res/icons2/chevron_right.svg" id="1_k5xby"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://ecmevhk0tuas" path="res://addons/panku_console/res/icons2/play-1001-svgrepo-com.svg" id="2_wnb5s"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://2cjvp0dp8ede" path="res://addons/panku_console/res/icons2/check-svgrepo-com.svg" id="3_h1h1v"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://8g5afcuanbl6" path="res://addons/panku_console/res/icons2/close.svg" id="4_2d3kd"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://brf6iwx4r6bdd" path="res://addons/panku_console/res/icons2/rename-svgrepo-com.svg" id="4_3tm8i"]
|
||||||
|
[ext_resource type="Gradient" uid="uid://nr65cgweqh8n" path="res://addons/panku_console/res/green_gradient_1d.tres" id="4_gsqii"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://drn5t13m088fb" path="res://addons/panku_console/common/panku_button.tscn" id="5_6smru"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://d0k813mm5y0d5" path="res://addons/panku_console/res/icons2/arrow-up-md-svgrepo-com.svg" id="5_xed2e"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://cdxbns8lyctqp" path="res://addons/panku_console/res/icons2/arrow-down-svgrepo-com.svg" id="6_168yw"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://om8bp40jo1e" path="res://addons/panku_console/modules/expression_monitor/expression_item.tscn" id="9_2py4a"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://cngs5d4uosvmt" path="res://addons/panku_console/res/icons2/bin-cancel-delete-remove-trash-garbage-svgrepo-com.svg" id="10_jdwtu"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dprpfr0l5xvmu" path="res://addons/panku_console/res/icons2/add.svg" id="10_l2ajq"]
|
||||||
|
|
||||||
|
[sub_resource type="GradientTexture1D" id="GradientTexture1D_c12ue"]
|
||||||
|
gradient = ExtResource("4_gsqii")
|
||||||
|
width = 128
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fdb5g"]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color(0, 0, 0, 0.12549)
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_top = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color(0.8, 0.8, 0.8, 0.501961)
|
||||||
|
|
||||||
|
[node name="MonitorGroupUI" type="VBoxContainer"]
|
||||||
|
offset_right = 431.0
|
||||||
|
offset_bottom = 124.0
|
||||||
|
theme = ExtResource("1_5nvur")
|
||||||
|
script = ExtResource("1_b5egi")
|
||||||
|
|
||||||
|
[node name="GroupManager" type="HBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="ToggleButton" type="Button" parent="GroupManager"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "Default Group"
|
||||||
|
icon = ExtResource("1_k5xby")
|
||||||
|
flat = true
|
||||||
|
alignment = 0
|
||||||
|
expand_icon = true
|
||||||
|
|
||||||
|
[node name="TextureRect" type="TextureRect" parent="GroupManager/ToggleButton"]
|
||||||
|
show_behind_parent = true
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
texture = SubResource("GradientTexture1D_c12ue")
|
||||||
|
expand_mode = 1
|
||||||
|
|
||||||
|
[node name="RenameLineEdit" type="LineEdit" parent="GroupManager"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "Default Group"
|
||||||
|
|
||||||
|
[node name="StateControlButton" parent="GroupManager" instance=ExtResource("5_6smru")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="GroupManager/StateControlButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("2_wnb5s")
|
||||||
|
|
||||||
|
[node name="RenameButton" parent="GroupManager" instance=ExtResource("5_6smru")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="GroupManager/RenameButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("4_3tm8i")
|
||||||
|
|
||||||
|
[node name="ConfirmRenameButton" parent="GroupManager" instance=ExtResource("5_6smru")]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="GroupManager/ConfirmRenameButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("3_h1h1v")
|
||||||
|
|
||||||
|
[node name="CancelRenameButton" parent="GroupManager" instance=ExtResource("5_6smru")]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="GroupManager/CancelRenameButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("4_2d3kd")
|
||||||
|
|
||||||
|
[node name="MoveUpButton" parent="GroupManager" instance=ExtResource("5_6smru")]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="GroupManager/MoveUpButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("5_xed2e")
|
||||||
|
|
||||||
|
[node name="MoveDownButton" parent="GroupManager" instance=ExtResource("5_6smru")]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="GroupManager/MoveDownButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("6_168yw")
|
||||||
|
|
||||||
|
[node name="RemoveButton" parent="GroupManager" instance=ExtResource("5_6smru")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="GroupManager/RemoveButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("10_jdwtu")
|
||||||
|
|
||||||
|
[node name="PanelContainer" type="PanelContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_fdb5g")
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="ExpressionContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" parent="PanelContainer/VBoxContainer/ExpressionContainer" instance=ExtResource("9_2py4a")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer2" parent="PanelContainer/VBoxContainer/ExpressionContainer" instance=ExtResource("9_2py4a")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="AddNewExpressionButton" type="Button" parent="PanelContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Add New Expression"
|
||||||
|
icon = ExtResource("10_l2ajq")
|
||||||
|
alignment = 0
|
||||||
|
expand_icon = true
|
||||||
|
|
||||||
|
[editable path="GroupManager/StateControlButton"]
|
||||||
|
[editable path="GroupManager/RenameButton"]
|
||||||
|
[editable path="GroupManager/ConfirmRenameButton"]
|
||||||
|
[editable path="GroupManager/CancelRenameButton"]
|
||||||
|
[editable path="GroupManager/MoveUpButton"]
|
||||||
|
[editable path="GroupManager/MoveDownButton"]
|
||||||
|
[editable path="GroupManager/RemoveButton"]
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
extends VBoxContainer
|
||||||
|
|
||||||
|
const MonitorGroup:GDScript = preload("./monitor_group_ui.gd")
|
||||||
|
const group_prefab:PackedScene = preload("./monitor_group_ui.tscn")
|
||||||
|
|
||||||
|
@onready var groups_container:Control = $Groups
|
||||||
|
@onready var add_group_button:Button = $AddGroupButton
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
add_group_button.pressed.connect(add_group)
|
||||||
|
|
||||||
|
func get_expressions_by_group() -> Array:
|
||||||
|
var result := []
|
||||||
|
for child in groups_container.get_children():
|
||||||
|
var group:MonitorGroup = child
|
||||||
|
result.append(group.get_expressions())
|
||||||
|
return result
|
||||||
|
|
||||||
|
func set_results_by_group(results:Array):
|
||||||
|
if results.size() > groups_container.get_child_count():
|
||||||
|
push_error("unexpected parameters.")
|
||||||
|
return
|
||||||
|
for i in range(results.size()):
|
||||||
|
groups_container.get_child(i).set_results(results[i])
|
||||||
|
|
||||||
|
func add_group() -> MonitorGroup:
|
||||||
|
var group_ui:Node = group_prefab.instantiate()
|
||||||
|
groups_container.add_child(group_ui)
|
||||||
|
group_ui.group_move_up.connect(
|
||||||
|
func():
|
||||||
|
groups_container.move_child(group_ui, group_ui.get_index() - 1)
|
||||||
|
)
|
||||||
|
group_ui.group_move_down.connect(
|
||||||
|
func():
|
||||||
|
groups_container.move_child(group_ui, group_ui.get_index() + 1)
|
||||||
|
)
|
||||||
|
return group_ui
|
||||||
|
|
||||||
|
func get_persistent_data() -> Array:
|
||||||
|
var data := []
|
||||||
|
for child in groups_container.get_children():
|
||||||
|
data.append(child.get_persistent_data())
|
||||||
|
return data
|
||||||
|
|
||||||
|
func load_persistent_data(data:Array):
|
||||||
|
for child in groups_container.get_children():
|
||||||
|
child.queue_free()
|
||||||
|
for group_data in data:
|
||||||
|
var group_ui = add_group()
|
||||||
|
group_ui.load_persistent_data(group_data)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://c7nca3l6nwgyw
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
[gd_scene load_steps=5 format=3 uid="uid://ctgf7kewoa1cn"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/modules/expression_monitor/monitor_groups_ui.gd" id="1_8ojgn"]
|
||||||
|
[ext_resource type="Theme" uid="uid://bk18yfu0d77wk" path="res://addons/panku_console/res/panku_console_theme.tres" id="1_gc4dk"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dlnkho5p7p2aq" path="res://addons/panku_console/modules/expression_monitor/monitor_group_ui.tscn" id="1_l15o5"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dprpfr0l5xvmu" path="res://addons/panku_console/res/icons2/add.svg" id="4_utrvo"]
|
||||||
|
|
||||||
|
[node name="MonitorGroupsUI" type="VBoxContainer"]
|
||||||
|
offset_right = 411.0
|
||||||
|
offset_bottom = 309.0
|
||||||
|
theme = ExtResource("1_gc4dk")
|
||||||
|
script = ExtResource("1_8ojgn")
|
||||||
|
|
||||||
|
[node name="Groups" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="MonitorGroupUI" parent="Groups" instance=ExtResource("1_l15o5")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="MonitorGroupUI2" parent="Groups" instance=ExtResource("1_l15o5")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="MonitorGroupUI3" parent="Groups" instance=ExtResource("1_l15o5")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="AddGroupButton" type="Button" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Add New Group"
|
||||||
|
icon = ExtResource("4_utrvo")
|
||||||
|
alignment = 0
|
||||||
|
expand_icon = true
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
var _module:PankuModule
|
||||||
|
|
||||||
|
func open():
|
||||||
|
_module.open_settings_window()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://b0m1kd1d2kjyc
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
class_name PankuModuleGeneralSettings extends PankuModule
|
||||||
|
|
||||||
|
var window:PankuLynxWindow
|
||||||
|
|
||||||
|
func open_settings_window():
|
||||||
|
if window: return
|
||||||
|
# create a new exporter window
|
||||||
|
window = core.create_data_controller_window.call(
|
||||||
|
core.module_manager.get_module_option_objects()
|
||||||
|
)
|
||||||
|
window.set_window_title_text("General Settings")
|
||||||
|
load_window_data(window)
|
||||||
|
window.show_window()
|
||||||
|
window.window_closed.connect(
|
||||||
|
func():
|
||||||
|
save_window_data(window)
|
||||||
|
window = null
|
||||||
|
)
|
||||||
|
|
||||||
|
# Taken from https://github.com/godotengine/godot/blob/master/editor/editor_settings.cpp#L1539
|
||||||
|
static func get_auto_display_scale() -> float:
|
||||||
|
var flag := false
|
||||||
|
match OS.get_name():
|
||||||
|
"macOS":
|
||||||
|
flag = true
|
||||||
|
"Linux", "FreeBSD", "NetBSD", "OpenBSD", "BSD":
|
||||||
|
if DisplayServer.get_name() == "Wayland":
|
||||||
|
flag = true
|
||||||
|
"Android":
|
||||||
|
flag = true
|
||||||
|
"iOS":
|
||||||
|
flag = true
|
||||||
|
if flag:
|
||||||
|
return DisplayServer.screen_get_max_scale()
|
||||||
|
|
||||||
|
var screen := DisplayServer.window_get_current_screen()
|
||||||
|
|
||||||
|
if (DisplayServer.screen_get_size(screen) == Vector2i()):
|
||||||
|
# Invalid screen size, skip.
|
||||||
|
return 1.0
|
||||||
|
|
||||||
|
# Use the smallest dimension to use a correct display scale on portrait displays.
|
||||||
|
var smallest_dimension = min(DisplayServer.screen_get_size().x, DisplayServer.screen_get_size().y)
|
||||||
|
if DisplayServer.screen_get_dpi(screen) >= 192 and smallest_dimension >= 1400:
|
||||||
|
# hiDPI display.
|
||||||
|
return 2.0
|
||||||
|
elif smallest_dimension >= 1700:
|
||||||
|
# Likely a hiDPI display, but we aren't certain due to the returned DPI.
|
||||||
|
# Use an intermediate scale to handle this situation.
|
||||||
|
return 1.5
|
||||||
|
elif smallest_dimension <= 800:
|
||||||
|
# Small loDPI display. Use a smaller display scale so that editor elements fit more easily.
|
||||||
|
# Icons won't look great, but this is better than having editor elements overflow from its window.
|
||||||
|
return 0.75
|
||||||
|
return 1.0
|
||||||
|
|
||||||
|
func init_module():
|
||||||
|
# load settings
|
||||||
|
get_module_opt().window_blur_effect = load_module_data("window_blur_effect", true)
|
||||||
|
get_module_opt().window_base_color = load_module_data("window_base_color", Color("#000c1880"))
|
||||||
|
get_module_opt().enable_os_window = load_module_data("enable_os_window", false)
|
||||||
|
get_module_opt().os_window_bg_color = load_module_data("os_window_bg_color", Color(0, 0, 0, 0))
|
||||||
|
get_module_opt().global_font_size = load_module_data("global_font_size", int(16 * get_auto_display_scale()))
|
||||||
|
|
||||||
|
func quit_module():
|
||||||
|
super.quit_module()
|
||||||
|
if window:
|
||||||
|
save_window_data(window)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://bqx8byqbawedh
|
||||||
49
godot/addons/panku_console/modules/general_settings/opt.gd
Normal file
49
godot/addons/panku_console/modules/general_settings/opt.gd
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
extends ModuleOptions
|
||||||
|
|
||||||
|
@export_group("general_settings")
|
||||||
|
|
||||||
|
@export var window_blur_effect:bool = true:
|
||||||
|
set(v):
|
||||||
|
PankuLynxWindow.lynx_window_shader_material.set("shader_parameter/lod", 4.0 if v else 0.0)
|
||||||
|
get:
|
||||||
|
return PankuLynxWindow.lynx_window_shader_material.get("shader_parameter/lod") > 0.0
|
||||||
|
|
||||||
|
@export var window_base_color:Color = Color(0.0, 0.0, 0.0, 0.1):
|
||||||
|
set(v):
|
||||||
|
PankuLynxWindow.lynx_window_shader_material.set("shader_parameter/modulate", v)
|
||||||
|
get:
|
||||||
|
return PankuLynxWindow.lynx_window_shader_material.get("shader_parameter/modulate")
|
||||||
|
|
||||||
|
@export var enable_os_window := false:
|
||||||
|
set(v):
|
||||||
|
_module.core.windows_manager.enable_os_popup_btns(v)
|
||||||
|
get:
|
||||||
|
return _module.core.windows_manager.os_popup_btn_enabled
|
||||||
|
|
||||||
|
@export var os_window_bg_color:Color:
|
||||||
|
set(v):
|
||||||
|
_module.core.windows_manager.set_os_window_bg_color(v)
|
||||||
|
get:
|
||||||
|
return _module.core.windows_manager.os_window_bg_color
|
||||||
|
|
||||||
|
@export var global_font_size:int:
|
||||||
|
set(v):
|
||||||
|
_module.core.windows_manager.theme.default_font_size = v
|
||||||
|
get:
|
||||||
|
return _module.core.windows_manager.theme.default_font_size
|
||||||
|
|
||||||
|
@export var export_comment_auto_global_font_size = (
|
||||||
|
"Adjust global font size automatically according to your device DPI"
|
||||||
|
)
|
||||||
|
|
||||||
|
@export var export_button_auto_global_font_size := "Auto Global Font Size"
|
||||||
|
func auto_global_font_size():
|
||||||
|
global_font_size = int(16 * _module.get_auto_display_scale())
|
||||||
|
|
||||||
|
@export var export_button_report_bugs := "Report Bugs"
|
||||||
|
func report_bugs():
|
||||||
|
OS.shell_open("https://github.com/Ark2000/PankuConsole/issues")
|
||||||
|
|
||||||
|
@export var export_button_suggest_features := "Suggest Features"
|
||||||
|
func suggest_features():
|
||||||
|
OS.shell_open("https://github.com/Ark2000/PankuConsole/issues")
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://bkxa6b0jf83y3
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
var _module:PankuModule
|
||||||
|
|
||||||
|
func open() -> void:
|
||||||
|
_module.open_window()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://cr2kkri0xrsqv
|
||||||
@ -0,0 +1,206 @@
|
|||||||
|
extends Control
|
||||||
|
|
||||||
|
@onready var console:PankuConsole
|
||||||
|
|
||||||
|
const exp_item_prefab = preload("./exp_history_item.tscn")
|
||||||
|
const CFG_EXP_HISTORY = "exp_history"
|
||||||
|
|
||||||
|
@export var item_container:VBoxContainer
|
||||||
|
@export var copy_button:Button
|
||||||
|
@export var monitor_button:Button
|
||||||
|
@export var favorite_button:Button
|
||||||
|
@export var delete_button:Button
|
||||||
|
@export var reverse_select_button:Button
|
||||||
|
@export var prev_page_button:Button
|
||||||
|
@export var next_page_button:Button
|
||||||
|
@export var first_page_button:Button
|
||||||
|
@export var last_page_button:Button
|
||||||
|
@export var page_ledit:LineEdit
|
||||||
|
@export var page_label:Label
|
||||||
|
|
||||||
|
var current_page := 1
|
||||||
|
var all_pages := 1
|
||||||
|
var items_per_page := 5
|
||||||
|
#[checked:bool, fav:bool, exp:String]
|
||||||
|
var item_data := []
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
load_data()
|
||||||
|
copy_button.pressed.connect(copy_selected)
|
||||||
|
monitor_button.pressed.connect(monitor_selected)
|
||||||
|
favorite_button.pressed.connect(star_selected)
|
||||||
|
delete_button.pressed.connect(remove_selected)
|
||||||
|
reverse_select_button.pressed.connect(invert_selected)
|
||||||
|
prev_page_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
current_page -= 1
|
||||||
|
reload()
|
||||||
|
)
|
||||||
|
next_page_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
current_page += 1
|
||||||
|
reload()
|
||||||
|
)
|
||||||
|
first_page_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
current_page = 1;
|
||||||
|
reload()
|
||||||
|
)
|
||||||
|
last_page_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
current_page = 99999999;
|
||||||
|
reload()
|
||||||
|
)
|
||||||
|
page_ledit.text_submitted.connect(
|
||||||
|
func(_new_text:String):
|
||||||
|
current_page = page_ledit.text.to_int()
|
||||||
|
reload()
|
||||||
|
)
|
||||||
|
page_ledit.focus_exited.connect(
|
||||||
|
func():
|
||||||
|
current_page = page_ledit.text.to_int()
|
||||||
|
reload()
|
||||||
|
)
|
||||||
|
create_tween().set_loops().set_process_mode(Tween.TWEEN_PROCESS_PHYSICS).tween_callback(
|
||||||
|
func():
|
||||||
|
if !is_visible_in_tree(): return
|
||||||
|
if item_container.get_child_count() < 1: return
|
||||||
|
var item_height = item_container.get_child(0).size.y
|
||||||
|
var item_gap = item_container.get("theme_override_constants/separation")
|
||||||
|
var container_height = item_container.get_parent().size.y
|
||||||
|
var _items_per_page = floor((container_height + item_gap) / (item_height + item_gap))
|
||||||
|
_items_per_page = max(5, _items_per_page)
|
||||||
|
if _items_per_page != items_per_page:
|
||||||
|
items_per_page = _items_per_page
|
||||||
|
reload()
|
||||||
|
).set_delay(0.1)
|
||||||
|
|
||||||
|
visibility_changed.connect(
|
||||||
|
func():
|
||||||
|
if is_visible_in_tree(): reload()
|
||||||
|
)
|
||||||
|
|
||||||
|
func reload():
|
||||||
|
#calculate pages
|
||||||
|
all_pages = max(1, ceil(1.0 * item_data.size() / items_per_page))
|
||||||
|
current_page = clamp(current_page, 1, all_pages)
|
||||||
|
page_label.text = " / %d" % all_pages
|
||||||
|
page_ledit.text = str(current_page)
|
||||||
|
|
||||||
|
#remove existing list items
|
||||||
|
var start_idx := (current_page - 1) * items_per_page
|
||||||
|
var end_idx := mini(start_idx + items_per_page, item_data.size())
|
||||||
|
for c in item_container.get_children():
|
||||||
|
c.queue_free()
|
||||||
|
|
||||||
|
#add new list items
|
||||||
|
for i in range(start_idx, end_idx):
|
||||||
|
var list_item = exp_item_prefab.instantiate()
|
||||||
|
list_item.checkbox.button_pressed = item_data[i][0]
|
||||||
|
list_item.fav_icon.visible = item_data[i][1]
|
||||||
|
list_item.line_edit.text = item_data[i][2]
|
||||||
|
list_item.checkbox.toggled.connect(
|
||||||
|
func(val:bool): item_data[i][0] = val
|
||||||
|
)
|
||||||
|
list_item.line_edit.text_changed.connect(
|
||||||
|
func(val:String): item_data[i][2] = val
|
||||||
|
)
|
||||||
|
item_container.add_child(list_item)
|
||||||
|
|
||||||
|
func copy_selected():
|
||||||
|
var result = combine_selected()
|
||||||
|
if result != "":
|
||||||
|
DisplayServer.clipboard_set(result)
|
||||||
|
console.notify("Combined expression has beed added to clipboard!")
|
||||||
|
clear_selected()
|
||||||
|
|
||||||
|
func monitor_selected():
|
||||||
|
var result = combine_selected()
|
||||||
|
if result != "":
|
||||||
|
pass
|
||||||
|
# console.add_monitor_window(result, 0.1).centered()
|
||||||
|
clear_selected()
|
||||||
|
|
||||||
|
func combine_selected() -> String:
|
||||||
|
var selected_exp = []
|
||||||
|
var combined_exp = ""
|
||||||
|
for d in item_data:
|
||||||
|
if !d[0]: continue
|
||||||
|
selected_exp.append(d[2])
|
||||||
|
if selected_exp.size() > 8:
|
||||||
|
console.notify("Maximum 8 items!")
|
||||||
|
return ""
|
||||||
|
if selected_exp.size() == 0:
|
||||||
|
console.notify("Nothing to copy!")
|
||||||
|
return ""
|
||||||
|
elif selected_exp.size() == 1:
|
||||||
|
combined_exp = selected_exp[0]
|
||||||
|
else:
|
||||||
|
for i in range(selected_exp.size()):
|
||||||
|
selected_exp[i] = "'%s: ' + str(%s)" % [selected_exp[i], selected_exp[i]]
|
||||||
|
combined_exp = " + '\\n' + ".join(PackedStringArray(selected_exp))
|
||||||
|
return combined_exp
|
||||||
|
|
||||||
|
func clear_selected():
|
||||||
|
for d in item_data:
|
||||||
|
d[0] = false
|
||||||
|
reload()
|
||||||
|
|
||||||
|
func invert_selected():
|
||||||
|
for d in item_data:
|
||||||
|
d[0] = !d[0]
|
||||||
|
reload()
|
||||||
|
|
||||||
|
func star_selected():
|
||||||
|
var flag := true
|
||||||
|
for d in item_data:
|
||||||
|
if !d[0]: continue
|
||||||
|
d[1] = !d[1]
|
||||||
|
d[0] = false
|
||||||
|
flag = false
|
||||||
|
if flag:
|
||||||
|
console.notify("No selected items!")
|
||||||
|
return
|
||||||
|
|
||||||
|
#sort favorite
|
||||||
|
var fav_id := 0
|
||||||
|
var fav_items := []
|
||||||
|
var items := []
|
||||||
|
for d in item_data:
|
||||||
|
if d[1]: fav_items.append(d)
|
||||||
|
else: items.append(d)
|
||||||
|
item_data = fav_items + items
|
||||||
|
reload()
|
||||||
|
|
||||||
|
func remove_selected():
|
||||||
|
var result = []
|
||||||
|
for d in item_data:
|
||||||
|
if d[0]: continue
|
||||||
|
result.append(d)
|
||||||
|
if item_data.size() == result.size():
|
||||||
|
console.notify("No selected items!")
|
||||||
|
return
|
||||||
|
console.notify("Removed %d items." % (item_data.size() - result.size()))
|
||||||
|
item_data = result
|
||||||
|
reload()
|
||||||
|
|
||||||
|
func load_data():
|
||||||
|
#get saved data from cfg
|
||||||
|
var cfg = PankuConfig.get_config()
|
||||||
|
item_data = cfg.get(CFG_EXP_HISTORY, [])
|
||||||
|
|
||||||
|
func save_data():
|
||||||
|
var cfg = PankuConfig.get_config()
|
||||||
|
cfg[CFG_EXP_HISTORY] = item_data
|
||||||
|
PankuConfig.set_config(cfg)
|
||||||
|
|
||||||
|
func _notification(what):
|
||||||
|
if what == NOTIFICATION_WM_CLOSE_REQUEST:
|
||||||
|
save_data()
|
||||||
|
|
||||||
|
func add_history(exp:String):
|
||||||
|
#ignore consecutive same
|
||||||
|
if item_data.size() > 0 and exp == item_data.back()[2]:
|
||||||
|
return
|
||||||
|
item_data.append([false, false, exp])
|
||||||
|
if is_visible_in_tree(): reload()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://nsybsat5vf4e
|
||||||
@ -0,0 +1,149 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://fladd1y6sa1j"]
|
||||||
|
|
||||||
|
[ext_resource type="Theme" uid="uid://bk18yfu0d77wk" path="res://addons/panku_console/res/panku_console_theme.tres" id="1_q7hjy"]
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/modules/history_manager/exp_history.gd" id="2_kgk33"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dhsvbbxqlb1xy" path="res://addons/panku_console/modules/history_manager/exp_history_item.tscn" id="3_wac0s"]
|
||||||
|
|
||||||
|
[node name="ExpHistory" type="Control" node_paths=PackedStringArray("item_container", "copy_button", "monitor_button", "favorite_button", "delete_button", "reverse_select_button", "prev_page_button", "next_page_button", "first_page_button", "last_page_button", "page_ledit", "page_label")]
|
||||||
|
clip_contents = true
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 0
|
||||||
|
offset_left = 227.0
|
||||||
|
offset_top = 149.0
|
||||||
|
offset_right = 634.0
|
||||||
|
offset_bottom = 437.0
|
||||||
|
theme = ExtResource("1_q7hjy")
|
||||||
|
script = ExtResource("2_kgk33")
|
||||||
|
item_container = NodePath("VBoxContainer2/Control/ItemContainer")
|
||||||
|
copy_button = NodePath("VBoxContainer2/HBoxContainer/CopyButton")
|
||||||
|
monitor_button = NodePath("VBoxContainer2/HBoxContainer/MonitorButton")
|
||||||
|
favorite_button = NodePath("VBoxContainer2/HBoxContainer/FavoriteButton")
|
||||||
|
delete_button = NodePath("VBoxContainer2/HBoxContainer/DeleteButton")
|
||||||
|
reverse_select_button = NodePath("VBoxContainer2/HBoxContainer/InvertSelect")
|
||||||
|
prev_page_button = NodePath("VBoxContainer2/HBoxContainer2/PrevPageButton")
|
||||||
|
next_page_button = NodePath("VBoxContainer2/HBoxContainer2/NextPageButton")
|
||||||
|
first_page_button = NodePath("VBoxContainer2/HBoxContainer2/FirstpageButton")
|
||||||
|
last_page_button = NodePath("VBoxContainer2/HBoxContainer2/LastPageButton")
|
||||||
|
page_ledit = NodePath("VBoxContainer2/HBoxContainer2/PageNumberEdit")
|
||||||
|
page_label = NodePath("VBoxContainer2/HBoxContainer2/TotalPageLabel")
|
||||||
|
metadata/_edit_vertical_guides_ = [161.838]
|
||||||
|
|
||||||
|
[node name="Panel" type="Panel" parent="."]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer2" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 4.0
|
||||||
|
offset_top = 4.0
|
||||||
|
offset_right = -4.0
|
||||||
|
offset_bottom = -4.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="CopyButton" type="Button" parent="VBoxContainer2/HBoxContainer"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "Copy"
|
||||||
|
|
||||||
|
[node name="MonitorButton" type="Button" parent="VBoxContainer2/HBoxContainer"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "Monitor"
|
||||||
|
|
||||||
|
[node name="FavoriteButton" type="Button" parent="VBoxContainer2/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "Favorite"
|
||||||
|
|
||||||
|
[node name="DeleteButton" type="Button" parent="VBoxContainer2/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "Delete"
|
||||||
|
|
||||||
|
[node name="InvertSelect" type="Button" parent="VBoxContainer2/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "Invert Select"
|
||||||
|
|
||||||
|
[node name="HSeparator2" type="HSeparator" parent="VBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="VBoxContainer2"]
|
||||||
|
clip_contents = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="ItemContainer" type="VBoxContainer" parent="VBoxContainer2/Control"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_constants/separation = 2
|
||||||
|
|
||||||
|
[node name="ExpItem" parent="VBoxContainer2/Control/ItemContainer" instance=ExtResource("3_wac0s")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="ExpItem2" parent="VBoxContainer2/Control/ItemContainer" instance=ExtResource("3_wac0s")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="ExpItem3" parent="VBoxContainer2/Control/ItemContainer" instance=ExtResource("3_wac0s")]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HSeparator" type="HSeparator" parent="VBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="FirstpageButton" type="Button" parent="VBoxContainer2/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "<<<"
|
||||||
|
|
||||||
|
[node name="PrevPageButton" type="Button" parent="VBoxContainer2/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "<"
|
||||||
|
|
||||||
|
[node name="PageNumberEdit" type="LineEdit" parent="VBoxContainer2/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "1"
|
||||||
|
|
||||||
|
[node name="TotalPageLabel" type="Label" parent="VBoxContainer2/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "/ 10"
|
||||||
|
vertical_alignment = 1
|
||||||
|
|
||||||
|
[node name="NextPageButton" type="Button" parent="VBoxContainer2/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = ">"
|
||||||
|
|
||||||
|
[node name="LastPageButton" type="Button" parent="VBoxContainer2/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = ">>>"
|
||||||
|
|
||||||
|
[node name="HFlowContainer" type="HFlowContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
offset_right = 399.0
|
||||||
|
size_flags_vertical = 0
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
extends HBoxContainer
|
||||||
|
|
||||||
|
@export var checkbox:CheckBox
|
||||||
|
@export var fav_icon:TextureRect
|
||||||
|
@export var line_edit:LineEdit
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://dy7ywh6we3xug
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://dhsvbbxqlb1xy"]
|
||||||
|
|
||||||
|
[ext_resource type="Theme" uid="uid://bk18yfu0d77wk" path="res://addons/panku_console/res/panku_console_theme.tres" id="1_rsfup"]
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/modules/history_manager/exp_history_item.gd" id="2_a3mfr"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://hf6h8otb8qkv" path="res://addons/panku_console/res/icons2/favorite.svg" id="3_1odvn"]
|
||||||
|
|
||||||
|
[node name="ExpItem" type="HBoxContainer" node_paths=PackedStringArray("checkbox", "fav_icon", "line_edit")]
|
||||||
|
offset_right = 155.0
|
||||||
|
offset_bottom = 20.0
|
||||||
|
theme = ExtResource("1_rsfup")
|
||||||
|
script = ExtResource("2_a3mfr")
|
||||||
|
checkbox = NodePath("CheckBox")
|
||||||
|
fav_icon = NodePath("TextureRect")
|
||||||
|
line_edit = NodePath("LineEdit")
|
||||||
|
|
||||||
|
[node name="CheckBox" type="CheckBox" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[node name="TextureRect" type="TextureRect" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
texture = ExtResource("3_1odvn")
|
||||||
|
stretch_mode = 3
|
||||||
|
|
||||||
|
[node name="LineEdit" type="LineEdit" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
26
godot/addons/panku_console/modules/history_manager/module.gd
Normal file
26
godot/addons/panku_console/modules/history_manager/module.gd
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
class_name PankuModuleHistoryManager extends PankuModule
|
||||||
|
|
||||||
|
var window:PankuLynxWindow
|
||||||
|
|
||||||
|
func init_module():
|
||||||
|
# setup ui
|
||||||
|
var ui = preload("./exp_history.tscn").instantiate()
|
||||||
|
ui.console = core
|
||||||
|
core.new_expression_entered.connect(
|
||||||
|
func(expression, result):
|
||||||
|
ui.add_history(expression)
|
||||||
|
)
|
||||||
|
|
||||||
|
# bind window
|
||||||
|
window = core.windows_manager.create_window(ui)
|
||||||
|
add_auto_save_hook(window)
|
||||||
|
window.queue_free_on_close = false
|
||||||
|
window.set_window_title_text("History Manager")
|
||||||
|
load_window_data(window)
|
||||||
|
|
||||||
|
func quit_module():
|
||||||
|
super.quit_module()
|
||||||
|
save_window_data(window)
|
||||||
|
|
||||||
|
func open_window():
|
||||||
|
window.show_window()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://du280gsd10ts4
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
extends ModuleOptions
|
||||||
|
|
||||||
|
@export_group("history_manager")
|
||||||
|
|
||||||
|
@export var export_button_open_window := "Open Window"
|
||||||
|
func open_window():
|
||||||
|
_module.open_window()
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user