First commit 🎉

This commit is contained in:
Tony Bark 2025-07-17 01:49:18 -04:00
commit 43ea213f9b
728 changed files with 37080 additions and 0 deletions

View file

@ -0,0 +1,291 @@
@tool
class_name PopochiuConfig
extends RefCounted
enum DialogStyle {
ABOVE_CHARACTER,
PORTRAIT,
CAPTION,
#PORTRAIT_ABOVE_CHARACTER, # TODO: Create a GUI node to make this option available
#BUBBLE_ABOVE_CHARACTER, # TODO: Create a GUI node to make this option available
}
# Thanks to @drbloop for providing the bases of the new approach for moving the popochiu settings to
# Godot's ProjectSettings instead of using a Resource file.
# ---- GUI -----------------------------------------------------------------------------------------
const SCALE_GUI = "popochiu/gui/experimental_scale_gui"
const FADE_COLOR = "popochiu/gui/fade_color"
const SKIP_CUTSCENE_TIME = "popochiu/gui/skip_cutscene_time"
const TL_FIRST_ROOM = "popochiu/gui/show_transition_layer_in_first_room"
# ---- Dialogs -------------------------------------------------------------------------------------
const TEXT_SPEED = "popochiu/dialogs/text_speed"
const AUTO_CONTINUE_TEXT = "popochiu/dialogs/auto_continue_text"
const USE_TRANSLATIONS = "popochiu/dialogs/use_translations"
const GIBBERISH_SPOKEN_TEXT = 'popochiu/dialogs/gibberish_spoken_text'
const GIBBERISH_DIALOG_OPTIONS = 'popochiu/dialogs/gibberish_dialog_options'
const DIALOG_STYLE = "popochiu/dialogs/dialog_style"
# ---- Inventory -----------------------------------------------------------------------------------
const INVENTORY_LIMIT = "popochiu/inventory/inventory_limit"
const INVENTORY_ITEMS_ON_START = "popochiu/inventory/items_on_start"
# ---- Aseprite Importing --------------------------------------------------------------------------
const ASEPRITE_IMPORT_ANIMATION = "popochiu/aseprite_import/import_animation_by_default"
const ASEPRITE_LOOP_ANIMATION = "popochiu/aseprite_import/loop_animation_by_default"
const ASEPRITE_PROPS_VISIBLE = "popochiu/aseprite_import/new_props_visible_by_default"
const ASEPRITE_PROPS_CLICKABLE = "popochiu/aseprite_import/new_props_clickable_by_default"
const ASEPRITE_WIPE_OLD_ANIMATIONS = "popochiu/aseprite_import/wipe_old_animations"
# ---- Pixel game ----------------------------------------------------------------------------------
const PIXEL_ART_TEXTURES = "popochiu/pixel/pixel_art_textures"
const PIXEL_PERFECT = "popochiu/pixel/pixel_perfect"
# ---- Audio ---------------------------------------------------------------------------------------
const PREFIX_CHARACTER = "popochiu/audio/prefix_character"
const MUSIC_PREFIXES = "popochiu/audio/music_prefixes"
const SOUND_EFFECT_PREFIXES = "popochiu/audio/sound_effect_prefixes"
const VOICE_PREFIXES = "popochiu/audio/voice_prefixes"
const UI_PREFIXES = "popochiu/audio/ui_prefixes"
# ---- DEV -----------------------------------------------------------------------------------------
const DEV_USE_ADDON_TEMPLATE = "popochiu/dev/use_addon_template"
static var defaults := {
SCALE_GUI: false,
FADE_COLOR: Color.BLACK,
SKIP_CUTSCENE_TIME: 0.2,
TL_FIRST_ROOM: false,
TEXT_SPEED: 0.1,
AUTO_CONTINUE_TEXT: false,
USE_TRANSLATIONS: false,
GIBBERISH_SPOKEN_TEXT: false,
GIBBERISH_DIALOG_OPTIONS: false,
DIALOG_STYLE: DialogStyle.ABOVE_CHARACTER,
INVENTORY_LIMIT: 0,
INVENTORY_ITEMS_ON_START: [],
ASEPRITE_IMPORT_ANIMATION: true,
ASEPRITE_LOOP_ANIMATION: true,
ASEPRITE_PROPS_VISIBLE: true,
ASEPRITE_PROPS_CLICKABLE: true,
ASEPRITE_WIPE_OLD_ANIMATIONS: true,
PIXEL_ART_TEXTURES: false,
PIXEL_PERFECT: false,
PREFIX_CHARACTER: "_",
MUSIC_PREFIXES: "mx,",
SOUND_EFFECT_PREFIXES: "sfx,",
VOICE_PREFIXES: "vo,",
UI_PREFIXES: "ui,",
DEV_USE_ADDON_TEMPLATE: false,
}
#region Public #####################################################################################
static func initialize_project_settings():
# ---- GUI -------------------------------------------------------------------------------------
_initialize_project_setting(SCALE_GUI, TYPE_BOOL)
_initialize_project_setting(FADE_COLOR, TYPE_COLOR)
_initialize_project_setting(SKIP_CUTSCENE_TIME, TYPE_FLOAT)
_initialize_project_setting(TL_FIRST_ROOM, TYPE_BOOL)
# ---- Dialogs ---------------------------------------------------------------------------------
_initialize_project_setting(TEXT_SPEED, TYPE_FLOAT, PROPERTY_HINT_RANGE, "0.0,0.1")
_initialize_project_setting(AUTO_CONTINUE_TEXT, TYPE_BOOL)
#_initialize_project_setting(USE_TRANSLATIONS, TYPE_BOOL)
#_initialize_project_setting(
#DIALOG_STYLE,
#TYPE_INT,
#PROPERTY_HINT_ENUM,
## TODO: Add other options: Portrait Above Character, Bubble Above Character
#"Above Character,Portrait,Caption"
#)
_initialize_project_setting(GIBBERISH_SPOKEN_TEXT, TYPE_BOOL)
_initialize_project_setting(GIBBERISH_DIALOG_OPTIONS, TYPE_BOOL)
# ---- Inventory -------------------------------------------------------------------------------
_initialize_project_setting(INVENTORY_LIMIT, TYPE_INT)
_initialize_project_setting(
INVENTORY_ITEMS_ON_START,
TYPE_ARRAY,
PROPERTY_HINT_TYPE_STRING,
"%d:" % [TYPE_STRING]
)
# ---- Aseprite Importing ----------------------------------------------------------------------
_initialize_project_setting(ASEPRITE_IMPORT_ANIMATION, TYPE_BOOL)
_initialize_project_setting(ASEPRITE_LOOP_ANIMATION, TYPE_BOOL)
_initialize_project_setting(ASEPRITE_PROPS_VISIBLE, TYPE_BOOL)
_initialize_project_setting(ASEPRITE_PROPS_CLICKABLE, TYPE_BOOL)
_initialize_project_setting(ASEPRITE_WIPE_OLD_ANIMATIONS, TYPE_BOOL)
# ---- Pixel game ------------------------------------------------------------------------------
_initialize_project_setting(PIXEL_ART_TEXTURES, TYPE_BOOL)
_initialize_project_setting(PIXEL_PERFECT, TYPE_BOOL)
# ---- Audio -----------------------------------------------------------------------------------
_initialize_project_setting(PREFIX_CHARACTER, TYPE_STRING)
_initialize_project_setting(MUSIC_PREFIXES, TYPE_STRING)
_initialize_project_setting(SOUND_EFFECT_PREFIXES, TYPE_STRING)
_initialize_project_setting(VOICE_PREFIXES, TYPE_STRING)
_initialize_project_setting(UI_PREFIXES, TYPE_STRING)
# ---- DEV -------------------------------------------------------------------------------------
_initialize_advanced_project_setting(DEV_USE_ADDON_TEMPLATE, TYPE_BOOL)
ProjectSettings.save()
static func set_project_setting(key: String, value) -> void:
ProjectSettings.set_setting(key, value)
ProjectSettings.save()
# ---- GUI -----------------------------------------------------------------------------------------
static func is_scale_gui() -> bool:
return _get_project_setting(SCALE_GUI)
static func get_fade_color() -> Color:
return _get_project_setting(FADE_COLOR)
static func get_skip_cutscene_time() -> float:
return _get_project_setting(SKIP_CUTSCENE_TIME)
static func should_show_tl_in_first_room() -> bool:
return _get_project_setting(TL_FIRST_ROOM)
# ---- Dialogs -------------------------------------------------------------------------------------
static func get_text_speed() -> float:
return _get_project_setting(TEXT_SPEED)
static func is_auto_continue_text() -> bool:
return _get_project_setting(AUTO_CONTINUE_TEXT)
static func is_use_translations() -> bool:
return _get_project_setting(USE_TRANSLATIONS)
static func get_dialog_style() -> int:
return _get_project_setting(DIALOG_STYLE)
static func should_talk_gibberish() -> bool:
return _get_project_setting(GIBBERISH_SPOKEN_TEXT)
static func should_dialog_options_be_gibberish() -> bool:
return _get_project_setting(GIBBERISH_DIALOG_OPTIONS)
# ---- Inventory -----------------------------------------------------------------------------------
static func get_inventory_limit() -> int:
return _get_project_setting(INVENTORY_LIMIT)
static func set_inventory_items_on_start(items: Array) -> void:
set_project_setting(INVENTORY_ITEMS_ON_START, items)
static func get_inventory_items_on_start() -> Array:
return _get_project_setting(INVENTORY_ITEMS_ON_START)
# ---- Aseprite Importing --------------------------------------------------------------------------
static func is_default_animation_import_enabled() -> bool:
return _get_project_setting(ASEPRITE_IMPORT_ANIMATION)
static func is_default_animation_loop_enabled() -> bool:
return _get_project_setting(ASEPRITE_LOOP_ANIMATION)
static func is_default_animation_prop_visible() -> bool:
return _get_project_setting(ASEPRITE_PROPS_VISIBLE)
static func is_default_animation_prop_clickable() -> bool:
return _get_project_setting(ASEPRITE_PROPS_CLICKABLE)
static func is_default_wipe_old_anims_enabled() -> bool:
return _get_project_setting(ASEPRITE_WIPE_OLD_ANIMATIONS)
# ---- Pixel game ----------------------------------------------------------------------------------
static func set_pixel_art_textures(use_pixel_art_textures: bool) -> void:
set_project_setting(PIXEL_ART_TEXTURES, use_pixel_art_textures)
static func is_pixel_art_textures() -> bool:
return _get_project_setting(PIXEL_ART_TEXTURES)
static func is_pixel_perfect() -> bool:
return _get_project_setting(PIXEL_PERFECT)
# ---- Audio ---------------------------------------------------------------------------------------
static func get_prefix_character() -> String:
return _get_project_setting(PREFIX_CHARACTER)
static func get_music_prefixes() -> String:
return _get_project_setting(MUSIC_PREFIXES)
static func get_sound_effect_prefixes() -> String:
return _get_project_setting(SOUND_EFFECT_PREFIXES)
static func get_voice_prefixes() -> String:
return _get_project_setting(VOICE_PREFIXES)
static func get_ui_prefixes() -> String:
return _get_project_setting(UI_PREFIXES)
# ---- DEV -----------------------------------------------------------------------------------------
static func is_use_addon_template() -> bool:
return _get_project_setting(DEV_USE_ADDON_TEMPLATE)
#endregion
#region Private ####################################################################################
static func _initialize_project_setting(
key: String, type: int, hint := PROPERTY_HINT_NONE, hint_string := ""
) -> void:
_create_setting(key, type, hint, hint_string)
ProjectSettings.set_as_basic(key, true)
static func _initialize_advanced_project_setting(
key: String, type: int, hint := PROPERTY_HINT_NONE, hint_string := ""
) -> void:
_create_setting(key, type, hint, hint_string)
static func _create_setting(
key: String, type: int, hint := PROPERTY_HINT_NONE, hint_string := ""
) -> void:
ProjectSettings.set_setting(key, ProjectSettings.get_setting(key, defaults[key]))
ProjectSettings.set_initial_value(key, defaults[key])
ProjectSettings.add_property_info({
"name": key,
"type": type,
"hint": hint,
"hint_string": hint_string,
})
static func _get_project_setting(key: String):
var p = ProjectSettings.get_setting(key)
return p if p != null else defaults[key]
#endregion

View file

@ -0,0 +1 @@
uid://blq0g140jdg7d

View file

@ -0,0 +1,128 @@
@tool
class_name PopochiuEditorConfig
extends RefCounted
enum Icons { COLLAPSED, EXPANDED }
# ASEPRITE IMPORTER --------------------------------------------------------------------------------
const ASEPRITE_IMPORTER_ENABLED = "popochiu/import/aseprite/enable_aseprite_importer"
const ASEPRITE_COMMAND_PATH = "popochiu/import/aseprite/command_path"
const ASEPRITE_REMOVE_JSON_FILE = "popochiu/import/aseprite/remove_json_file"
# GIZMOS -------------------------------------------------------------------------------------------
const GIZMOS_FONT_SIZE = "popochiu/gizmos/font_size"
const GIZMOS_BASELINE_COLOR = "popochiu/gizmos/baseline_color"
const GIZMOS_WALK_TO_POINT_COLOR = "popochiu/gizmos/walk_to_point_color"
const GIZMOS_LOOK_AT_POINT_COLOR = "popochiu/gizmos/look_at_point_color"
const GIZMOS_DIALOG_POS_COLOR = "popochiu/gizmos/dialog_position_color"
const GIZMOS_COLOR_TOOLBAR_BUTTONS = "popochiu/gizmos/apply_colors_to_toolbar_buttons"
const GIZMOS_HANDLER_SIZE = "popochiu/gizmos/handler_size"
const GIZMOS_SHOW_CONNECTORS = "popochiu/gizmos/show_connectors"
const GIZMOS_SHOW_OUTLINE = "popochiu/gizmos/show_handler_outline"
const GIZMOS_SHOW_NODE_NAME = "popochiu/gizmos/show_node_name"
const GIZMOS_ALWAYS_SHOW_WA = "popochiu/gizmos/always_show_walkable_areas"
# Settings default values
static var defaults := {
ASEPRITE_IMPORTER_ENABLED: false,
ASEPRITE_COMMAND_PATH: _default_aseprite_command(),
ASEPRITE_REMOVE_JSON_FILE: true,
GIZMOS_FONT_SIZE: _default_font_size(),
GIZMOS_BASELINE_COLOR: Color.CYAN,
GIZMOS_WALK_TO_POINT_COLOR: Color.GREEN,
GIZMOS_LOOK_AT_POINT_COLOR: Color.RED,
GIZMOS_DIALOG_POS_COLOR: Color.MAGENTA,
GIZMOS_COLOR_TOOLBAR_BUTTONS: true,
GIZMOS_HANDLER_SIZE: 32,
GIZMOS_SHOW_CONNECTORS: true,
GIZMOS_SHOW_OUTLINE: true,
GIZMOS_SHOW_NODE_NAME: true,
GIZMOS_ALWAYS_SHOW_WA: false,
}
static var editor_settings: EditorSettings
#region Public #####################################################################################
static func initialize_editor_settings():
editor_settings = EditorInterface.get_editor_settings()
# Aseprite importer
_initialize_editor_setting(ASEPRITE_IMPORTER_ENABLED, TYPE_BOOL)
_initialize_editor_setting(ASEPRITE_COMMAND_PATH, TYPE_STRING)
_initialize_editor_setting(ASEPRITE_REMOVE_JSON_FILE, TYPE_BOOL)
# Gizmos
_initialize_editor_setting(GIZMOS_BASELINE_COLOR, TYPE_COLOR)
_initialize_editor_setting(GIZMOS_WALK_TO_POINT_COLOR, TYPE_COLOR)
_initialize_editor_setting(GIZMOS_LOOK_AT_POINT_COLOR, TYPE_COLOR)
_initialize_editor_setting(GIZMOS_DIALOG_POS_COLOR, TYPE_COLOR)
_initialize_editor_setting(GIZMOS_COLOR_TOOLBAR_BUTTONS, TYPE_BOOL)
_initialize_editor_setting(GIZMOS_HANDLER_SIZE, TYPE_INT, PROPERTY_HINT_RANGE, "4,64")
_initialize_editor_setting(GIZMOS_FONT_SIZE, TYPE_INT, PROPERTY_HINT_RANGE, "4,64")
_initialize_editor_setting(GIZMOS_SHOW_CONNECTORS, TYPE_BOOL)
_initialize_editor_setting(GIZMOS_SHOW_OUTLINE, TYPE_BOOL)
_initialize_editor_setting(GIZMOS_SHOW_NODE_NAME, TYPE_BOOL)
_initialize_editor_setting(GIZMOS_ALWAYS_SHOW_WA, TYPE_BOOL)
static func get_icon(icon: Icons) -> Texture2D:
match icon:
Icons.COLLAPSED:
return EditorInterface.get_base_control().get_theme_icon(
"GuiTreeArrowRight", "EditorIcons"
)
Icons.EXPANDED:
return EditorInterface.get_base_control().get_theme_icon(
"GuiTreeArrowDown", "EditorIcons"
)
return null
# ASEPRITE IMPORTER --------------------------------------------------------------------------------
static func aseprite_importer_enabled() -> bool:
return get_editor_setting(ASEPRITE_IMPORTER_ENABLED)
static func get_command() -> String:
return get_editor_setting(ASEPRITE_COMMAND_PATH)
static func should_remove_source_files() -> bool:
return get_editor_setting(ASEPRITE_REMOVE_JSON_FILE)
#endregion
#region Private ####################################################################################
static func _default_aseprite_command() -> String:
return 'aseprite'
static func _default_font_size() -> int:
if Engine.is_editor_hint():
return EditorInterface.get_editor_theme().default_font_size
return 16
static func _initialize_editor_setting(
key: String, type: int, hint: int = PROPERTY_HINT_NONE, hint_string : String = ""
) -> void:
if editor_settings.has_setting(key): return
editor_settings.set_setting(key, defaults[key])
editor_settings.set_initial_value(key, defaults[key], false)
editor_settings.add_property_info({
"name": key,
"type": type,
"hint": hint,
"hint_string": hint_string
})
static func get_editor_setting(key: String):
var e = editor_settings.get_setting(key)
return e if e != null else defaults[e]
#endregion

View file

@ -0,0 +1 @@
uid://c2xn0h6paw2xy

View file

@ -0,0 +1,70 @@
@tool
extends RefCounted
const LOCAL_OBJ_CONFIG_META_NAME = "_popochiu_aseprite_config_"
const LOCAL_OBJ_CONFIG_MARKER = "popochiu_aseprite_config"
const SEPARATOR = "|="
# ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ PUBLIC ░░░░
static func encode(object: Dictionary):
var text = "%s\n" % LOCAL_OBJ_CONFIG_MARKER
for prop in object:
text += "%s%s%s\n" % [prop, SEPARATOR, object[prop]]
return Marshalls.utf8_to_base64(text)
static func decode(string: String):
var decoded = _decode_base64(string)
if not _is_valid_config(decoded):
return null
print(decoded)
var cfg = decoded.split("\n")
var config = {}
for c in cfg:
var parts = c.split(SEPARATOR, 1)
if parts.size() == 2:
var key = parts[0].strip_edges()
var value = parts[1].strip_edges()
#Convert bool properties
if key in ["only_visible_layers", "wipe_old_anims", "op_exp"]:
match value:
"True":
config[key] = true
"False":
config[key] = false
_:
config[key] = false
else:
config[key] = value
return config
static func load_config(node:Node):
# Check if node is not null to avoid showing error messages in Output when inspecting nodes in
# the Debugger
if node and node.has_meta(LOCAL_OBJ_CONFIG_META_NAME):
return node.get_meta(LOCAL_OBJ_CONFIG_META_NAME)
static func save_config(node:Node, cfg:Dictionary):
node.set_meta(LOCAL_OBJ_CONFIG_META_NAME, cfg)
# ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ PRIVATE ░░░░
static func _decode_base64(string: String):
if string != "":
return Marshalls.base64_to_utf8(string)
return null
static func _is_valid_config(cfg) -> bool:
return cfg != null and cfg.begins_with(LOCAL_OBJ_CONFIG_MARKER)

View file

@ -0,0 +1 @@
uid://d26rqfocnhh7v

View file

@ -0,0 +1,75 @@
@tool
extends RefCounted
class_name ResultCodes
enum {
## Base codes
FAILURE, # generic failure state
SUCCESS, # generic success state
## Aseprite importer errors
ERR_ASEPRITE_CMD_NOT_FULL_PATH,
ERR_ASEPRITE_CMD_NOT_FOUND,
ERR_SOURCE_FILE_NOT_FOUND,
ERR_OUTPUT_FOLDER_NOT_FOUND,
ERR_ASEPRITE_EXPORT_FAILED,
ERR_UNKNOWN_EXPORT_MODE,
ERR_NO_VALID_LAYERS_FOUND,
ERR_INVALID_ASEPRITE_SPRITESHEET,
ERR_NO_ANIMATION_PLAYER_FOUND,
ERR_NO_SPRITE_FOUND,
ERR_UNNAMED_TAG_DETECTED,
ERR_TAGS_OPTIONS_ARRAY_EMPTY,
## Popochiu Object factories errors
ERR_CANT_CREATE_OBJ_FOLDER,
ERR_CANT_CREATE_OBJ_STATE,
ERR_CANT_OPEN_OBJ_SCRIPT_TEMPLATE,
ERR_CANT_CREATE_OBJ_SCRIPT,
ERR_CANT_SAVE_OBJ_SCENE,
ERR_CANT_SAVE_OBJ_RESOURCE,
}
# ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ PUBLIC ░░░░
static func get_error_message(code: int):
## TODO: these messages are a bit dull, having params would be better.
## Maybe add a param argument
match code:
# Aseprite importers error messages
ERR_ASEPRITE_CMD_NOT_FULL_PATH:
return "Aseprite command not found at given path. Please check \"Editor Settings > Popochiu > Import > Command Path\" to hold the FULL path to a valid Aseprite executable."
ERR_ASEPRITE_CMD_NOT_FOUND:
return "Aseprite command failed. Please, check if the right command is in your PATH or configured through \"Editor Settings > Popochiu > Import > Command Path\"."
ERR_SOURCE_FILE_NOT_FOUND:
return "Source file does not exist"
ERR_OUTPUT_FOLDER_NOT_FOUND:
return "Output location does not exist"
ERR_ASEPRITE_EXPORT_FAILED:
return "Unable to import file"
ERR_INVALID_ASEPRITE_SPRITESHEET:
return "Aseprite generated invalid data file"
ERR_NO_VALID_LAYERS_FOUND:
return "No valid layers found"
ERR_NO_ANIMATION_PLAYER_FOUND:
return "No AnimationPlayer found in target node"
ERR_NO_SPRITE_FOUND:
return "No sprite found in target node"
ERR_UNNAMED_TAG_DETECTED:
return "Unnamed tag detected"
ERR_TAGS_OPTIONS_ARRAY_EMPTY:
return "Tags options array is empty"
# Popochiu object factories error messages
ERR_CANT_CREATE_OBJ_FOLDER:
return "Can't create folder to host new Popochiu object"
ERR_CANT_CREATE_OBJ_STATE:
return "Can't create new Popochiu object's state resource (_state.tres, _state.gd)"
ERR_CANT_OPEN_OBJ_SCRIPT_TEMPLATE:
return "Can't open script template for new Popochiu object"
ERR_CANT_CREATE_OBJ_SCRIPT:
return "Can't create new Popochiu object's script file (.gd)"
ERR_CANT_SAVE_OBJ_SCENE:
return "Can't create new Popochiu object's scene (.tscn)"
ERR_CANT_SAVE_OBJ_RESOURCE:
return "Can't create new Popochiu object's resource (.tres)"
# Generic error message
_:
return "Import failed with code %d" % code

View file

@ -0,0 +1 @@
uid://cbxik5o1u00hf