diff --git a/.github/actions/init-version-gdext/action.yml b/.github/actions/init-version-gdext/action.yml index ca39fd9..8cd29c5 100644 --- a/.github/actions/init-version-gdext/action.yml +++ b/.github/actions/init-version-gdext/action.yml @@ -15,7 +15,7 @@ runs: echo "GDEXTENSION_VERSION=${GDEXTENSION_VERSION}" >> "$GITHUB_ENV" - cd ../limboai + cd .. echo "LIMBOAI_VERSION=$( (git describe --tags --exact-match HEAD || git rev-parse --short HEAD) | sed 's/\(.*\)-\(.*\)/\1.\2/g' )" >> "$GITHUB_ENV" - name: Set NAME_PREFIX diff --git a/.github/workflows/gdextension.yml b/.github/workflows/gdextension.yml index e27e397..0a83767 100644 --- a/.github/workflows/gdextension.yml +++ b/.github/workflows/gdextension.yml @@ -167,6 +167,12 @@ jobs: BIN: liblimboai.${{matrix.opts.platform}}.${{matrix.opts.target}}.${{matrix.opts.arch}} steps: + - name: Clone LimboAI module + uses: actions/checkout@v4 + with: + fetch-tags: true + ref: ${{ inputs.limboai-ref }} + - name: Clone godot-cpp uses: actions/checkout@v4 with: @@ -175,15 +181,8 @@ jobs: path: godot-cpp ref: ${{ inputs.godot-cpp-ref }} - - name: Clone LimboAI module - uses: actions/checkout@v4 - with: - path: limboai - fetch-tags: true - ref: ${{ inputs.limboai-ref }} - # Inits GDEXTENSION_VERSION, LIMBOAI_VERSION and NAME_PREFIX environment variables. - - uses: ./limboai/.github/actions/init-version-gdext + - uses: ./.github/actions/init-version-gdext - name: Output NAME_PREFIX id: output-name-prefix @@ -191,7 +190,7 @@ jobs: - name: Setup Linux toolchain if: matrix.opts.platform == 'linux' - uses: ./limboai/.github/actions/setup-linux-toolchain + uses: ./.github/actions/setup-linux-toolchain with: arch: ${{matrix.opts.arch}} @@ -257,15 +256,6 @@ jobs: ${{env.BIN}}-${{inputs.godot-cpp-ref}}-${{inputs.limboai-ref}} ${{env.BIN}}-${{inputs.godot-cpp-ref}} - - name: Setup project structure for GDExtension - shell: bash - run: | - bash ./limboai/gdextension/setup_gdextension.sh --copy-all - echo "---" - ls -l - echo "---" - ls -l -R ./demo/ - - name: Compilation shell: bash env: @@ -279,9 +269,9 @@ jobs: run: | mkdir out mv demo/addons/ out/ - cp limboai/{README,LICENSE,LOGO_LICENSE}.md out/addons/limboai/ - cp -R limboai/demo/demo/ out/demo/ - cp limboai/demo/LICENSE_ASSETS.md out/demo/ + cp {README,LICENSE,LOGO_LICENSE}.md out/addons/limboai/ + cp -R demo/demo/ out/demo/ + cp demo/LICENSE_ASSETS.md out/demo/ rm -f out/addons/limboai/bin/*.{exp,lib,pdb} echo "${LIMBOAI_VERSION}" > out/addons/limboai/version.txt echo "---" diff --git a/.gitignore b/.gitignore index 8fcda8a..b8dbf90 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ demo/addons/ demo/script_templates/ icons/*.import +godot-cpp # Godot auto generated files *.gen.* diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..06bc33a --- /dev/null +++ b/SConstruct @@ -0,0 +1,136 @@ +#!/usr/bin/env python +import os +import sys + +# This is SConstruct file for building GDExtension variant using SCons build system. +# For module variant, see SCsub file. + +# Use --project=DIR to customize output path for built targets. +# - Built targets are placed into "DIR/addons/limboai/bin". +# - For example: scons --project="../my_project" +# - built targets will be placed into "../my_project/addons/limboai/bin". +# - If not specified, built targets are put into the demo/ project. + +AddOption( + "--project", + dest="project", + type="string", + nargs=1, + action="store", + metavar="DIR", + default="demo", + help="Specify project directory", +) + +help_text = """ +Options: + --project=DIR Specify project directory (default: "demo"); + built targets will be placed in DIR/addons/limboai/bin +""" +Help(help_text) + +project_dir = GetOption("project") +if not os.path.isdir(project_dir): + print("Project directory not found: " + project_dir) + Exit(1) + +# Parse LimboAI-specific variables. +vars = Variables() +vars.AddVariables( + BoolVariable("deploy_manifest", help="Deploy limboai.gdextension into PROJECT/addons/limboai/bin", default=True), + BoolVariable("deploy_icons", help="Deploy icons into PROJECT/addons/limboai/icons", default=True), +) +env = Environment(tools=["default"], PLATFORM="", variables=vars) +Help(vars.GenerateHelpText(env)) + +# Read LimboAI-specific variables. +deploy_manifest = env["deploy_manifest"] +deploy_icons = env["deploy_icons"] + +# Remove processed variables from ARGUMENTS to avoid godot-cpp warnings. +for o in vars.options: + if o.key in ARGUMENTS: + del ARGUMENTS[o.key] + +# For reference: +# - CCFLAGS are compilation flags shared between C and C++ +# - CFLAGS are for C-specific compilation flags +# - CXXFLAGS are for C++-specific compilation flags +# - CPPFLAGS are for pre-processor flags +# - CPPDEFINES are for pre-processor defines +# - LINKFLAGS are for linking flags + +env = SConscript("godot-cpp/SConstruct") + +# Generate version header. +from limboai_version import generate_module_version_header + +print("Generating LimboAI version header...") +generate_module_version_header() + +# Update icon entries in limboai.gdextension file. +# Note: This will remove everything after [icons] section, and rebuild it with generated icon entries. +sys.path.append("gdextension") +from update_icon_entries import update_icon_entries + +print("Updating LimboAI icon entries...") +update_icon_entries(silent=True) +sys.path.remove("gdextension") + +# Tweak this if you want to use different folders, or more folders, to store your source code in. +env.Append(CPPDEFINES=["LIMBOAI_GDEXTENSION"]) +sources = Glob("*.cpp") +sources += Glob("blackboard/*.cpp") +sources += Glob("blackboard/bb_param/*.cpp") +sources += Glob("bt/*.cpp") +sources += Glob("bt/tasks/*.cpp") +sources += Glob("bt/tasks/blackboard/*.cpp") +sources += Glob("bt/tasks/composites/*.cpp") +sources += Glob("bt/tasks/decorators/*.cpp") +sources += Glob("bt/tasks/scene/*.cpp") +sources += Glob("bt/tasks/utility/*.cpp") +sources += Glob("gdextension/*.cpp") +sources += Glob("editor/debugger/*.cpp") +sources += Glob("editor/*.cpp") +sources += Glob("hsm/*.cpp") +sources += Glob("util/*.cpp") + +# Generate documentation header. +if env["target"] in ["editor", "template_debug"]: + doc_data = env.GodotCPPDocData("gen/doc_data.gen.cpp", source=Glob("doc_classes/*.xml")) + sources.append(doc_data) + +# Build library. +if env["platform"] == "macos": + library = env.SharedLibrary( + project_dir + + "/addons/limboai/bin/liblimboai.{}.{}.framework/liblimboai.{}.{}".format( + env["platform"], env["target"], env["platform"], env["target"] + ), + source=sources, + ) +else: + library = env.SharedLibrary( + project_dir + "/addons/limboai/bin/liblimboai{}{}".format(env["suffix"], env["SHLIBSUFFIX"]), + source=sources, + ) + +Default(library) + +# Deploy icons into PROJECT/addons/limboai/icons. +if deploy_icons: + cmd_deploy_icons = env.Command( + project_dir + "/addons/limboai/icons/", + "icons/", + Copy("$TARGET", "$SOURCE"), + ) + Default(cmd_deploy_icons) + +# Deploy limboai.gdextension into PROJECT/addons/limboai/bin. +if deploy_manifest: + cmd_deploy_manifest = env.Command( + project_dir + "/addons/limboai/bin/limboai.gdextension", + "gdextension/limboai.gdextension", + Copy("$TARGET", "$SOURCE"), + ) + Default(cmd_deploy_manifest) diff --git a/gdextension/SConstruct b/gdextension/SConstruct deleted file mode 100644 index 122f0be..0000000 --- a/gdextension/SConstruct +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -env = SConscript("godot-cpp/SConstruct") - -# For reference: -# - CCFLAGS are compilation flags shared between C and C++ -# - CFLAGS are for C-specific compilation flags -# - CXXFLAGS are for C++-specific compilation flags -# - CPPFLAGS are for pre-processor flags -# - CPPDEFINES are for pre-processor defines -# - LINKFLAGS are for linking flags - -# Generate version header. -sys.path.append("./limboai") -import limboai_version - -os.chdir("./limboai") -limboai_version.generate_module_version_header() -os.chdir("..") -sys.path.remove("./limboai") - -# Tweak this if you want to use different folders, or more folders, to store your source code in. -env.Append(CPPPATH=["limboai/"]) -env.Append(CPPDEFINES=["LIMBOAI_GDEXTENSION"]) -sources = Glob("limboai/*.cpp") -sources += Glob("limboai/blackboard/*.cpp") -sources += Glob("limboai/blackboard/bb_param/*.cpp") -sources += Glob("limboai/bt/*.cpp") -sources += Glob("limboai/bt/tasks/*.cpp") -sources += Glob("limboai/bt/tasks/blackboard/*.cpp") -sources += Glob("limboai/bt/tasks/composites/*.cpp") -sources += Glob("limboai/bt/tasks/decorators/*.cpp") -sources += Glob("limboai/bt/tasks/scene/*.cpp") -sources += Glob("limboai/bt/tasks/utility/*.cpp") -sources += Glob("limboai/gdextension/*.cpp") -sources += Glob("limboai/editor/debugger/*.cpp") -sources += Glob("limboai/editor/*.cpp") -sources += Glob("limboai/hsm/*.cpp") -sources += Glob("limboai/util/*.cpp") - -# Generate documentation header. -if env["target"] in ["editor", "template_debug"]: - doc_data = env.GodotCPPDocData("limboai/gen/doc_data.gen.cpp", source=Glob("limboai/doc_classes/*.xml")) - sources.append(doc_data) - -if env["platform"] == "macos": - library = env.SharedLibrary( - "demo/addons/limboai/bin/liblimboai.{}.{}.framework/liblimboai.{}.{}".format( - env["platform"], env["target"], env["platform"], env["target"] - ), - source=sources, - ) -else: - library = env.SharedLibrary( - "demo/addons/limboai/bin/liblimboai{}{}".format(env["suffix"], env["SHLIBSUFFIX"]), - source=sources, - ) - -Default(library) diff --git a/gdextension/fix_demo_imports.sh b/gdextension/fix_demo_imports.sh new file mode 100755 index 0000000..278605e --- /dev/null +++ b/gdextension/fix_demo_imports.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +## This script fixes icon imports in the demo project. +## It enables scaling and color conversion for SVG icons in the demo project. +## +## Dependencies: bash, sed, find. + +# Colors +HIGHLIGHT_COLOR='\033[1;36m' # Light Cyan +NC='\033[0m' # No Color +ERROR_COLOR="\033[0;31m" # Red + +usage() { echo -e "Usage: $0 [--silent]\nRun from limboai root directory!"; } + +msg () { echo -e "$@"; } +highlight() { echo -e "${HIGHLIGHT_COLOR}$@${NC}"; } +error () { echo -e "${ERROR_COLOR}$@${NC}" >&2; } + +# Exit if a command returns non-zero status. +set -e + +if [ ! -d "${PWD}/demo/" ]; then + error Aborting: \"demo\" subdirectory is not found. + msg Tip: Run this script from the limboai root directory. + msg Command: bash ./gdextension/fix_demo_imports.sh + exit 1 +fi + +if test -z "$(find demo/addons/limboai/icons/ -maxdepth 1 -name '*.svg' -print -quit)"; then + error "No icons found in the demo project!" + msg Make sure to copy/link the icons into the demo project \(icons/ -\> demo/addons/limboai/icons/\). + exit 1 +fi + +if test -z "$(find demo/addons/limboai/icons/ -maxdepth 1 -name '*.import' -print -quit)"; then + error "No icon import files found!" + msg Make sure to open the demo project in Godot Editor before running this script. + exit 1 +fi + +highlight "--- Listing icons dir:" +ls demo/addons/limboai/icons/ +highlight "---" + +highlight Applying scale settings... +sed -i 's|editor/scale_with_editor_scale=false|editor/scale_with_editor_scale=true|' demo/addons/limboai/icons/*.import + +highlight Applying color conversion settings... +sed -i 's|editor/convert_colors_with_editor_theme=false|editor/convert_colors_with_editor_theme=true|' demo/addons/limboai/icons/*.import + +highlight Done! diff --git a/gdextension/setup_gdextension.sh b/gdextension/setup_gdextension.sh index 4329e29..c6c471d 100755 --- a/gdextension/setup_gdextension.sh +++ b/gdextension/setup_gdextension.sh @@ -1,27 +1,24 @@ #!/bin/bash -## This script creates project structure needed for LimboAI development using GDExtension. -## Works only on Unix-likes. You can still use the directory layout below, if you are on Windows. +## This script sets up limboai project for development with GDExtension. +## It adds missing files to the demo project for development with GDExtension, and downloads godot-cpp. +## Tested only on Unix-likes. You can perform similar steps manually, if you are on Windows. Check Overview below. ## ## Instructions: -## 1) Create the project root directory, name doesn't matter. -## 2) Inside the project root directory, clone the limboai repository: +## 1) Clone the limboai repository: ## git clone https://github.com/limbonaut/limboai -## 3) From the project root directory, run: -## bash ./limboai/gdextension/setup_gdextension.sh +## 2) From the limboai root directory, run: +## bash ./gdextension/setup_gdextension.sh ## -## Directory layout: -## project/ -- call this script from here, directory name doesn't matter. -## project/limboai/ -- LimboAI repository should be here after you clone it. -## project/godot-cpp/ -- will be created by this script, unless cloned manually. -## project/demo/ -- symbolic link (leads to limboai/demo). -## project/demo/addons/limboai/limboai.gdextension -- symbolid link (leads to limboai/gdextension/limboai.gdextension). -## project/demo/addons/limboai/icons/ -- symbolic link (leads to icons/). -## project/SConstruct -- symbolic link (leads to limboai/gdextension/SContruct). +## Overview: +## limboai/ -- LimboAI repository after you clone it - call this script from here. +## limboai/godot-cpp/ -- git repo that will be cloned by this script, unless already exists. +## limboai/demo/addons/limboai/limboai.gdextension -- symbolic link created (leads to limboai/gdextension/limboai.gdextension). +## limboai/demo/addons/limboai/icons/ -- symbolic link created (leads to limboai/icons/). ## -## Note: Symbolic links will be created by this script. +## Note: Script creates symbolic links unless --copy-all is set, in which case it copies the files. ## -## Dependencies: bash, git, python3. +## Dependencies: bash, git, python3, trash (optional). # Script Settings GODOT_CPP_VERSION=4.2 @@ -32,16 +29,16 @@ HIGHLIGHT_COLOR='\033[1;36m' # Light Cyan NC='\033[0m' # No Color ERROR_COLOR="\033[0;31m" # Red -usage() { echo "Usage: $0 [--copy-demo] [--copy-all] [--trash-old]"; } +usage() { echo "Usage: $0 [--copy-all] [--trash-old]"; } msg () { echo -e "$@"; } highlight() { echo -e "${HIGHLIGHT_COLOR}$@${NC}"; } error () { echo -e "${ERROR_COLOR}$@${NC}" >&2; } -if [ ! -d "${PWD}/limboai/" ]; then - error Aborting: \"limboai\" subdirectory is not found. - msg Tip: Run this script from the project root directory with limboai repository cloned into \"limboai\" subdirectory. - msg Command: bash ./limboai/gdextension/setup_gdextension.sh +if [ ! -d "${PWD}/demo/" ]; then + error Aborting: \"demo\" subdirectory is not found. + msg Tip: Run this script from the limboai root directory. + msg Command: bash ./gdextension/setup_gdextension.sh exit 1 fi @@ -50,7 +47,6 @@ trap exit SIGINT set -e -copy_demo=0 copy_all=0 trash_old=0 @@ -58,10 +54,6 @@ trash_old=0 for i in "$@" do case "${i}" in - --copy-demo) - copy_demo=1 - shift - ;; --copy-all) copy_demo=1 copy_all=1 @@ -80,7 +72,7 @@ done highlight Setup started. -${PYTHON} limboai/gdextension/update_icons.py --silent +${PYTHON} gdextension/update_icon_entries.py --silent highlight -- Icon declarations updated. transfer="ln -s" @@ -95,7 +87,7 @@ if [ ${trash_old} == 1 ]; then error trash command not available. Aborting. exit 1 fi - trash SConstruct limboai/demo/addons demo || /bin/true + trash demo/addons/limboai || /bin/true highlight -- Trashed old setup. fi @@ -107,33 +99,10 @@ else highlight -- Skipping \"godot-cpp\". Directory already exists! fi -if [ ! -f "${PWD}/SConstruct" ]; then - ${transfer} limboai/gdextension/SConstruct SConstruct - highlight -- ${transfer_word} SConstruct. -else - highlight -- Skipping \"SConstruct\". File already exists! -fi - -if [ ! -e "${PWD}/demo" ]; then - if [ ${copy_demo} == 1 ]; then - cp -R limboai/demo demo - highlight -- Copied demo. - else - ln -s limboai/demo demo - highlight -- Linked demo project. - fi -else - highlight -- Skipping \"demo\". File already exists! -fi - if [ ! -e "${PWD}/demo/addons/limboai/bin/limboai.gdextension" ]; then mkdir -p ./demo/addons/limboai/bin/ cd ./demo/addons/limboai/bin/ - if [ -f "../../../../gdextension/limboai.gdextension" ]; then - ${transfer} ../../../../gdextension/limboai.gdextension limboai.gdextension - else - ${transfer} ../../../../limboai/gdextension/limboai.gdextension limboai.gdextension - fi + ${transfer} ../../../../gdextension/limboai.gdextension limboai.gdextension cd - highlight -- ${transfer_word} limboai.gdextension. else @@ -142,11 +111,7 @@ fi if [ ! -e "${PWD}/demo/addons/limboai/icons/" ]; then cd ./demo/addons/limboai/ - if [ -d "../../../icons" ]; then - ${transfer} ../../../icons icons - else - ${transfer} ../../../limboai/icons icons - fi + ${transfer} ../../../icons icons cd - highlight -- ${transfer_word} icons. else diff --git a/gdextension/update_icons.py b/gdextension/update_icon_entries.py similarity index 67% rename from gdextension/update_icons.py rename to gdextension/update_icon_entries.py index a8dcf59..850b048 100755 --- a/gdextension/update_icons.py +++ b/gdextension/update_icon_entries.py @@ -1,7 +1,7 @@ #!/usr/bin/python """ -Usage: update_icons.py [--silent] -Update icon declarations in limboai.gdextension file. +Usage: update_icon_entries.py [--silent] +Update icon entries in limboai.gdextension file. Options: -s, --silent Don't print anything. @@ -28,7 +28,44 @@ def get_script_dir(): return os.path.dirname(os.path.realpath(__file__)) -def main(): +def update_icon_entries(silent=False): + config_dir = get_script_dir() + config_path = os.path.join(config_dir, "limboai.gdextension") + content = "" + new_content = "" + + f = open(config_path, "r") + for line in f: + content += line + f.close() + + index = content.find("[icons]") + new_content = content[0:index] + new_content += "[icons]\n\n" + + icon_files = [] + icons_dir = os.path.join(config_dir, "../icons/") + for icon_file in glob.glob(icons_dir + "/*.svg"): + icon_file = os.path.basename(icon_file) + icon_files.append(icon_file) + + icon_files.sort() + for icon_file in icon_files: + new_content += os.path.splitext(icon_file)[0] + ' = "res://addons/limboai/icons/' + icon_file + '"\n' + + if new_content != content: + f = open(config_path, "w") + f.write(new_content) + f.close() + if not silent: + print(new_content) + print("=== Icon entries updated ===") + else: + if not silent: + print("=== No update needed for icon entries ===") + + +if __name__ == "__main__": silent = False try: opts, args = getopt.getopt(sys.argv[1:], "s", ["silent"]) @@ -50,37 +87,4 @@ def main(): elif opt in ("-s", "--silent"): silent = True - config_dir = get_script_dir() - config_path = os.path.join(config_dir, "limboai.gdextension") - content = "" - - f = open(config_path, "r") - for line in f: - if line.startswith("[icons]"): - break - content += line - f.close() - - content += "[icons]\n\n" - - icon_files = [] - icons_dir = os.path.join(config_dir, "../icons/") - for icon_file in glob.glob(icons_dir + "/*.svg"): - icon_file = os.path.basename(icon_file) - icon_files.append(icon_file) - - icon_files.sort() - for icon_file in icon_files: - content += os.path.splitext(icon_file)[0] + ' = "res://addons/limboai/icons/' + icon_file + '"\n' - - f = open(config_path, "w") - f.write(content) - f.close() - - if not silent: - print(content) - print("======= Icon declarations updated =======") - - -if __name__ == "__main__": - main() + update_icon_entries(silent)