diff --git a/druid/editor_scripts/component.lua_template b/druid/editor_scripts/component.lua_template new file mode 100644 index 0000000..d50db11 --- /dev/null +++ b/druid/editor_scripts/component.lua_template @@ -0,0 +1,32 @@ +--- For component interest functions +--- see https://github.com/Insality/druid/blob/develop/docs_md/02-creating_custom_components.md +--- Require this component in you gui file: +--- local {COMPONENT_NAME} = require("{COMPONENT_PATH}") +--- And create this component via: +--- self.{COMPONENT_TYPE} = self.druid:new({COMPONENT_NAME}, template, nodes) + +local component = require("druid.component") + +---@class {COMPONENT_TYPE}: druid.base_component{COMPONENT_ANNOTATIONS} +---@field druid druid_instance +local {COMPONENT_NAME} = component.create("{COMPONENT_TYPE}") + +local SCHEME = { +{SCHEME_LIST} +} + + +---@param template string +---@param nodes table +function {COMPONENT_NAME}:init(template, nodes) + self:set_template(template) + self:set_nodes(nodes) + self.druid = self:get_druid(){COMPONENT_DEFINE} +end + + +function {COMPONENT_NAME}:on_remove() +end + +{COMPONENT_FUNCTIONS} +return {COMPONENT_NAME} diff --git a/druid/editor_scripts/create_druid_component.py b/druid/editor_scripts/create_druid_component.py new file mode 100644 index 0000000..054bfa3 --- /dev/null +++ b/druid/editor_scripts/create_druid_component.py @@ -0,0 +1,139 @@ +# @license MIT, Insality 2021 +# @source https://github.com/Insality/druid + +import os +import sys +import deftree + +current_filepath = os.path.abspath(os.path.dirname(__file__)) +TEMPLATE_PATH = current_filepath + "/component.lua_template" + +component_annotations = "" +component_functions = "" +component_define = "" + +def to_camel_case(snake_str): + components = snake_str.split('_') + return ''.join(x.title() for x in components[0:]) + + +def get_id(node_name): + return node_name.upper().replace("/", "_") + + +def process_component(node_name, component_name): + global component_annotations + global component_functions + global component_define + + if node_name == "root": + component_annotations += "\n---@field root node" + component_define += "\n\tself.root = self:get_node(SCHEME.ROOT)" + + if node_name.startswith("button"): + component_annotations += "\n---@field {0} druid.button".format(node_name) + component_functions += "\nfunction {1}:_on_{0}()\n\tprint(\"Click on {0}\")\nend\n\n".format(node_name, component_name) + component_define += "\n\tself.{0} = self.druid:new_button(SCHEME.{1}, self._on_{0})".format(node_name, get_id(node_name)) + + if node_name.startswith("text"): + component_annotations += "\n---@field {0} druid.text".format(node_name) + component_define += "\n\tself.{0} = self.druid:new_text(SCHEME.{1})".format(node_name, get_id(node_name)) + + if node_name.startswith("lang_text"): + component_annotations += "\n---@field {0} druid.text".format(node_name) + component_define += "\n\tself.{0} = self.druid:new_lang_text(SCHEME.{1}, \"lang_id\")".format(node_name, get_id(node_name)) + + if node_name.startswith("grid") or node_name.startswith("static_grid"): + component_annotations += "\n---@field {0} druid.static_grid".format(node_name) + component_define += "\n--TODO: Replace prefab_name with grid element prefab" + component_define += "\n\tself.{0} = self.druid:new_static_grid(SCHEME.{1}, \"prefab_name\", 1)".format(node_name, get_id(node_name)) + + if node_name.startswith("dynamic_grid"): + component_annotations += "\n---@field {0} druid.dynamic_grid".format(node_name) + component_define += "\n\tself.{0} = self.druid:new_dynamic_grid(SCHEME.{1})".format(node_name, get_id(node_name)) + + if node_name.startswith("scroll_view"): + field_name = node_name.replace("_view", "") + content_name = node_name.replace("_view", "_content") + component_annotations += "\n---@field {0} druid.scroll".format(field_name) + component_define += "\n\tself.{0} = self.druid:new_scroll(SCHEME.{1}, SCHEME.{2})".format(field_name, get_id(node_name), get_id(content_name)) + + if node_name.startswith("blocker"): + component_annotations += "\n---@field {0} druid.blocker".format(node_name) + component_define += "\n\tself.{0} = self.druid:new_blocker(SCHEME.{1})".format(node_name, get_id(node_name)) + + if node_name.startswith("slider"): + component_annotations += "\n---@field {0} druid.slider".format(node_name) + component_define += "\n--TODO: Replace slider end position. It should be only vertical or horizontal" + component_define += "\n\tself.{0} = self.druid:new_slider(SCHEME.{1}, vmath.vector3(100, 0, 0), self._on_{0}_change)".format(node_name, get_id(node_name)) + component_functions += "\nfunction {1}:_on_{0}_change(value)\n\tprint(\"Slider change:\", value)\nend\n\n".format(node_name, component_name) + + if node_name.startswith("progress"): + component_annotations += "\n---@field {0} druid.progress".format(node_name) + component_define += "\n\tself.{0} = self.druid:new_progress(SCHEME.{1}, \"x\")".format(node_name, get_id(node_name)) + + if node_name.startswith("timer"): + component_annotations += "\n---@field {0} druid.timer".format(node_name) + component_define += "\n\tself.{0} = self.druid:new_timer(SCHEME.{1}, 59, 0, self._on_{0}_end)".format(node_name, get_id(node_name)) + component_functions += "\nfunction {1}:_on_{0}_end()\n\tprint(\"Timer {0} trigger\")\nend\n\n".format(node_name, component_name) + + +def main(): + global component_annotations + global component_functions + global component_define + + filename = sys.argv[1] + print("Create Druid component from gui file", filename) + tree = deftree.parse(filename) + root = tree.get_root() + + output_directory = os.path.dirname(filename) + output_filename = os.path.splitext(os.path.basename(filename))[0] + + output_full_path = os.path.join(output_directory, output_filename + ".lua") + is_already_exists = os.path.exists(output_full_path) + if is_already_exists: + print("Error: The file is already exists") + print("File:", output_full_path) + return + + component_require_path = os.path.join(output_directory, output_filename).replace("/", ".").replace("..", "") + component_name = to_camel_case(output_filename) + component_type = output_filename + scheme_list = [] + + # Gather nodes from GUI scene + for node in root.iter_elements("nodes"): + node_name = node.get_attribute("id").value + scheme_list.append("\t" + get_id(node_name) + " = \"" + node_name + "\"") + + is_template = node.get_attribute("template") + is_in_template = "/" in node_name + if not is_template and not is_in_template: + process_component(node_name, component_name) + + if len(component_define) > 2: + component_define = "\n" + component_define + + template_file = open(TEMPLATE_PATH, "r") + filedata = template_file.read() + template_file.close() + + filedata = filedata.replace("{COMPONENT_NAME}", component_name) + filedata = filedata.replace("{COMPONENT_TYPE}", component_type) + filedata = filedata.replace("{COMPONENT_PATH}", component_require_path) + filedata = filedata.replace("{COMPONENT_DEFINE}", component_define) + filedata = filedata.replace("{COMPONENT_FUNCTIONS}", component_functions) + filedata = filedata.replace("{COMPONENT_ANNOTATIONS}", component_annotations) + filedata = filedata.replace("{SCHEME_LIST}", ",\n".join(scheme_list)) + + output_file = open(output_full_path, "w") + output_file.write(filedata) + output_file.close() + + print("Success: The file is created") + print("File:", output_full_path) + + +main() diff --git a/druid/editor_scripts/create_druid_component.sh b/druid/editor_scripts/create_druid_component.sh new file mode 100644 index 0000000..56e44f1 --- /dev/null +++ b/druid/editor_scripts/create_druid_component.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# @license MIT, Insality 2022 +# @source https://github.com/Insality/druid + +echo "Run bash for $1" +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +is_defree_installed=$(pip3 list --disable-pip-version-check | grep -E "deftree") +if [ -z "$is_defree_installed" ]; then + echo "The python deftree is not installed. Please install it via" + echo "pip3 install deftree" + exit 0 +fi + +python3 $DIR/create_druid_component.py $@ diff --git a/druid/editor_scripts/gui_scheme.editor_script b/druid/editor_scripts/gui_scheme.editor_script new file mode 100644 index 0000000..3619d60 --- /dev/null +++ b/druid/editor_scripts/gui_scheme.editor_script @@ -0,0 +1,106 @@ +--- @license MIT, Insality 2021 +--- @source https://github.com/Insality/druid + +local M = {} + + +local function ends_with(str, ending) + return ending == "" or str:sub(-#ending) == ending +end + + +function M.get_commands() + return { + { + label = "Print gui scheme", + + locations = { "Outline" }, + + query = { + selection = {type = "outline", cardinality = "many"} + }, + + active = function(opts) + return true + end, + + run = function(opts) + print("local SCHEME = {") + + for i = 1, #opts.selection do + local file = opts.selection[i] + if editor.can_get(file, "id") then + local id = editor.get(file, "id") + print("\t" .. string.upper(id) .. " = \"" .. id .. "\",") + end + end + + print("}") + print("") + end + }, + + { + label = "Assign layers", + + locations = {"Edit"}, + + query = { + selection = {type = "resource", cardinality = "one"} + }, + + active = function(opts) + local path = editor.get(opts.selection, "path") + return ends_with(path, ".gui") + end, + + run = function(opts) + local file = opts.selection + print("Run script for", editor.get(file, "path")) + return { + { + action = "shell", + command = { + "bash", + "./editor_scripts/setup_layers.sh", + "." .. editor.get(file, "path") + } + } + } + end + }, + + { + label = "Create Druid Component", + + locations = {"Edit"}, + + query = { + selection = {type = "resource", cardinality = "one"} + }, + + active = function(opts) + local path = editor.get(opts.selection, "path") + return ends_with(path, ".gui") + end, + + run = function(opts) + local file = opts.selection + print("Run script for", editor.get(file, "path")) + return { + { + action = "shell", + command = { + "bash", + "./editor_scripts/create_druid_component.sh", + "." .. editor.get(file, "path") + } + } + } + end + } + } +end + + +return M diff --git a/druid/editor_scripts/setup_layers.py b/druid/editor_scripts/setup_layers.py new file mode 100644 index 0000000..dd0d580 --- /dev/null +++ b/druid/editor_scripts/setup_layers.py @@ -0,0 +1,44 @@ +# @license MIT, Insality 2021 +# @source https://github.com/Insality/druid + +import sys +import deftree + +def main(): + filename = sys.argv[1] + print("Auto setup layers for file", filename) + tree = deftree.parse(filename) + root = tree.get_root() + + layers = [] + for texture in root.iter_elements("textures"): + layers.append(texture.get_attribute("name").value) + + for fonts in root.iter_elements("fonts"): + layers.append(fonts.get_attribute("name").value) + + to_remove_layers = [] + for layer in root.iter_elements("layers"): + to_remove_layers.append(layer) + for layer in to_remove_layers: + root.remove(layer) + + for layer in layers: + new_layer = root.add_element("layers") + new_layer.add_attribute("name", layer) + + for node in root.iter_elements("nodes"): + texture = node.get_attribute("texture") + font = node.get_attribute("font") + + if texture: + layer = texture.value.split("/")[0] + node.set_attribute("layer", layer) + + if font: + layer = font.value + node.set_attribute("layer", layer) + + tree.write() + +main() \ No newline at end of file diff --git a/druid/editor_scripts/setup_layers.sh b/druid/editor_scripts/setup_layers.sh new file mode 100755 index 0000000..96a4617 --- /dev/null +++ b/druid/editor_scripts/setup_layers.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# @license MIT, Insality 2021 +# @source https://github.com/Insality/druid + +echo "Run bash for $1" +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +is_defree_installed=$(pip3 list --disable-pip-version-check | grep -E "deftree") +if [ -z "$is_defree_installed" ]; then + echo "The python deftree is not installed. Please install it via" + echo "pip3 install deftree" + exit 0 +fi + +python3 $DIR/setup_layers.py $@