mirror of
https://github.com/deunix-educ/aventuriers-des-mots.git
synced 2026-10-13 02:11:58 +02:00
Add project skeleton: Godot setup, tooling, and smoke test
Pins Godot 4.6.3-stable and GUT 9.6.0 (9.6.1+ reference AccessibilityServer, unavailable in 4.6.3) via tools/setup.sh. Wires make check (gdlint + gdformat config for 4-space indent, headless GUT run, and a JSON well-formedness check ahead of real schema validation). Seven autoload stubs match the architecture in the cahier des charges; real logic lands with the following steps. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{gd,py,json,md,cfg,yml,yaml,sh}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
@@ -0,0 +1,30 @@
|
||||
# Texte : fins de ligne normalisees en LF
|
||||
* text=auto eol=lf
|
||||
|
||||
*.gd text eol=lf
|
||||
*.gdshader text eol=lf
|
||||
*.tscn text eol=lf
|
||||
*.tres text eol=lf
|
||||
*.cfg text eol=lf
|
||||
*.json text eol=lf
|
||||
*.md text eol=lf
|
||||
*.cs text eol=lf
|
||||
*.py text eol=lf
|
||||
*.sh text eol=lf
|
||||
Makefile text eol=lf
|
||||
|
||||
# Assets : binaires, jamais de conversion de fin de ligne
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.webp binary
|
||||
*.ogg binary
|
||||
*.wav binary
|
||||
*.mp3 binary
|
||||
*.ttf binary
|
||||
*.otf binary
|
||||
*.woff binary
|
||||
*.woff2 binary
|
||||
*.zip binary
|
||||
*.ico binary
|
||||
*.svg binary
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
# Runtime et artefacts Godot
|
||||
.godot/
|
||||
build/
|
||||
|
||||
# Outillage telecharge par `make setup` (Godot, GUT), non versionne
|
||||
.godot-bin/
|
||||
addons/gut/
|
||||
.venv/
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Secrets et identifiants (export, env, mots de passe, cles)
|
||||
.env
|
||||
*.env
|
||||
*.keystore
|
||||
*.jks
|
||||
*.p12
|
||||
*.mobileprovision
|
||||
secrets.*
|
||||
export_credentials.cfg
|
||||
|
||||
# Fichiers d'edition courants
|
||||
*.swp
|
||||
.DS_Store
|
||||
@@ -0,0 +1 @@
|
||||
4.6.3-stable
|
||||
@@ -0,0 +1,35 @@
|
||||
GODOT_BIN := .godot-bin/godot
|
||||
VENV := .venv
|
||||
GDLINT := $(VENV)/bin/gdlint
|
||||
GDFORMAT := $(VENV)/bin/gdformat
|
||||
GD_SOURCES := autoload scripts tests
|
||||
|
||||
.PHONY: setup run lint format validate-data test check export-linux export-windows
|
||||
|
||||
setup:
|
||||
tools/setup.sh
|
||||
|
||||
run:
|
||||
$(GODOT_BIN) --path .
|
||||
|
||||
lint:
|
||||
$(GDLINT) $(GD_SOURCES)
|
||||
|
||||
format:
|
||||
$(GDFORMAT) $(GD_SOURCES)
|
||||
|
||||
validate-data:
|
||||
$(GODOT_BIN) --headless --path . -s res://scripts/data/validate_data_cli.gd
|
||||
|
||||
test:
|
||||
$(GODOT_BIN) --headless --path . -s res://addons/gut/gut_cmdln.gd -gdir=res://tests -gexit
|
||||
|
||||
check: lint validate-data test
|
||||
|
||||
export-linux:
|
||||
@echo "Export Linux : pas encore configure (voir Ordre de construction, etape 6)."
|
||||
@exit 1
|
||||
|
||||
export-windows:
|
||||
@echo "Export Windows : pas encore configure (voir Ordre de construction, etape 6)."
|
||||
@exit 1
|
||||
@@ -0,0 +1,44 @@
|
||||
# Les Aventuriers des mots (The Word Adventurers)
|
||||
|
||||
An educational French-language game for 7-9 year olds (French grades CE1-CE2): an offline 2D adventure with an explorable map, a guide character, and grammar, spelling, and dictation exercises.
|
||||
|
||||
Open source project, in development. Current status: technical skeleton (see `docs/specs/decisions.md` for scoping decisions and `docs/specs/cahier-des-charges.md` for the full specification, both in French — this is a French-curriculum product).
|
||||
|
||||
## Tech stack
|
||||
|
||||
- Godot 4.6 (typed GDScript)
|
||||
- Exercises and pedagogical content as JSON data, validated on load
|
||||
- Headless tests (GUT), GDScript lint/format (gdtoolkit)
|
||||
|
||||
## Getting started
|
||||
|
||||
```sh
|
||||
make setup # installs Godot (pinned), GUT and gdtoolkit locally, nothing is committed
|
||||
make run # runs the game
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Effect |
|
||||
|---|---|
|
||||
| `make setup` | installs tooling (lint, tests, export templates) |
|
||||
| `make run` | runs the game |
|
||||
| `make lint` / `make format` | GDScript static analysis and formatting |
|
||||
| `make validate-data` | validates the JSON files in `data/` |
|
||||
| `make test` | headless tests |
|
||||
| `make check` | lint + validate-data + test, must pass before every commit |
|
||||
| `make export-linux` / `make export-windows` | exports into `build/` (from the export step onward) |
|
||||
|
||||
## Structure
|
||||
|
||||
- `autoload/`: global modules (game lifecycle, profiles, progress, exercises, saves, audio, settings)
|
||||
- `scenes/`: self-contained Godot scenes communicating via signals
|
||||
- `scripts/`: pure logic (correction, pedagogy) and data loading
|
||||
- `data/`: pedagogical content as JSON, validated against schemas
|
||||
- `assets/`: graphics and audio (placeholder at this stage, see `assets/CREDITS.md`)
|
||||
- `tests/`: headless tests (GUT)
|
||||
- `docs/specs/`: specification and scoping decisions (French)
|
||||
|
||||
## License
|
||||
|
||||
Code and content under the [GNU Affero General Public License v3](LICENSE).
|
||||
@@ -0,0 +1,44 @@
|
||||
# Les Aventuriers des mots
|
||||
|
||||
Jeu éducatif de français pour les CE1-CE2 (7-9 ans) : une aventure 2D hors ligne, avec une carte à explorer, un personnage guide, et des exercices de grammaire, d'orthographe et de dictées.
|
||||
|
||||
Projet open source, en développement. Statut actuel : squelette technique (voir `docs/specs/decisions.md` pour les décisions de cadrage et `docs/specs/cahier-des-charges.md` pour la spécification complète).
|
||||
|
||||
## Pile technique
|
||||
|
||||
- Godot 4.6 (GDScript typé)
|
||||
- Exercices et contenu pédagogique en données JSON, validées au chargement
|
||||
- Tests headless (GUT), lint/format GDScript (gdtoolkit)
|
||||
|
||||
## Démarrer
|
||||
|
||||
```sh
|
||||
make setup # installe Godot (pinné), GUT et gdtoolkit en local, rien n'est commité
|
||||
make run # lance le jeu
|
||||
```
|
||||
|
||||
## Commandes
|
||||
|
||||
| Commande | Effet |
|
||||
|---|---|
|
||||
| `make setup` | installe l'outillage (lint, tests, modèles d'export) |
|
||||
| `make run` | lance le jeu |
|
||||
| `make lint` / `make format` | analyse statique et formatage GDScript |
|
||||
| `make validate-data` | valide les JSON de `data/` |
|
||||
| `make test` | tests headless |
|
||||
| `make check` | lint + validate-data + test, à passer avant chaque commit |
|
||||
| `make export-linux` / `make export-windows` | exports dans `build/` (à partir de l'étape export) |
|
||||
|
||||
## Structure
|
||||
|
||||
- `autoload/` : modules globaux (gestion du jeu, profils, progression, exercices, sauvegardes, audio, réglages)
|
||||
- `scenes/` : scènes Godot, autonomes et communiquant par signaux
|
||||
- `scripts/` : logique pure (correction, pédagogie) et chargement des données
|
||||
- `data/` : contenu pédagogique en JSON, validé contre des schémas
|
||||
- `assets/` : graphismes et audio (provisoires à ce stade, voir `assets/CREDITS.md`)
|
||||
- `tests/` : tests headless (GUT)
|
||||
- `docs/specs/` : cahier des charges et décisions de cadrage
|
||||
|
||||
## Licence
|
||||
|
||||
Code et contenu sous [GNU Affero General Public License v3](LICENSE).
|
||||
@@ -0,0 +1,9 @@
|
||||
# Sources des assets provisoires
|
||||
|
||||
Tous les graphismes et sons actuels sont provisoires, crees pour ce projet, sans asset tiers.
|
||||
|
||||
| Fichier | Origine | Licence |
|
||||
|---|---|---|
|
||||
| `icon.svg` | Forme geometrique simple, creee pour ce projet | AGPL-3.0 (code et assets du depot) |
|
||||
|
||||
Les voix de dictee provisoires (a venir) seront generees par synthese vocale hors ligne et listees ici au fur et a mesure, avec la mention `review_status: draft` correspondante dans les donnees.
|
||||
@@ -0,0 +1,3 @@
|
||||
extends Node
|
||||
## Lecture des voix, dictees, musiques et effets sonores, y compris l'audio provisoire des dictees.
|
||||
## Logique detaillee a partir de l'etape "Scenes" (voir Ordre de construction).
|
||||
@@ -0,0 +1 @@
|
||||
uid://542icpqhkik3
|
||||
@@ -0,0 +1,3 @@
|
||||
extends Node
|
||||
## Chargement et deroulement des exercices a partir des donnees JSON validees.
|
||||
## Logique detaillee a partir de l'etape "Donnees" (voir Ordre de construction).
|
||||
@@ -0,0 +1 @@
|
||||
uid://dvni3nligy7lx
|
||||
@@ -0,0 +1,3 @@
|
||||
extends Node
|
||||
## Cycle de vie de l'application, navigation entre scenes et etat general du jeu.
|
||||
## Logique detaillee a partir de l'etape "Scenes" (voir Ordre de construction).
|
||||
@@ -0,0 +1 @@
|
||||
uid://cw6hsqn7d08bu
|
||||
@@ -0,0 +1,3 @@
|
||||
extends Node
|
||||
## Creation, selection et suppression des profils enfants.
|
||||
## Logique detaillee a partir de l'etape "Profils et sauvegardes".
|
||||
@@ -0,0 +1 @@
|
||||
uid://dl471qrur3sxh
|
||||
@@ -0,0 +1,3 @@
|
||||
extends Node
|
||||
## Competences, missions debloquees et planification des revisions par profil.
|
||||
## Logique detaillee a partir de l'etape "Logique pure" (voir docs/specs/decisions.md, point 5).
|
||||
@@ -0,0 +1 @@
|
||||
uid://ei0m2liq1j86
|
||||
@@ -0,0 +1,4 @@
|
||||
extends Node
|
||||
## Serialisation des sauvegardes par profil dans user:// (ecriture atomique,
|
||||
## copie de secours, migration).
|
||||
## Logique detaillee a partir de l'etape "Profils et sauvegardes".
|
||||
@@ -0,0 +1 @@
|
||||
uid://ce07tiyi8ad46
|
||||
@@ -0,0 +1,3 @@
|
||||
extends Node
|
||||
## Volume, taille du texte et autres preferences de l'enfant ou de l'adulte.
|
||||
## Logique detaillee a partir de l'etape "Scenes" (voir Ordre de construction).
|
||||
@@ -0,0 +1 @@
|
||||
uid://cdsn8dm6pbh6w
|
||||
@@ -0,0 +1,5 @@
|
||||
excluded_directories: !!set
|
||||
.git: null
|
||||
line_length: 100
|
||||
safety_checks: null
|
||||
use_spaces: 4
|
||||
@@ -0,0 +1,47 @@
|
||||
class-definitions-order:
|
||||
- tools
|
||||
- classnames
|
||||
- extends
|
||||
- docstrings
|
||||
- signals
|
||||
- enums
|
||||
- consts
|
||||
- staticvars
|
||||
- exports
|
||||
- pubvars
|
||||
- prvvars
|
||||
- onreadypubvars
|
||||
- onreadyprvvars
|
||||
- others
|
||||
class-load-variable-name: (([A-Z][a-z0-9]*)+|_?[a-z][a-z0-9]*(_[a-z0-9]+)*)
|
||||
class-name: ([A-Z][a-z0-9]*)+
|
||||
class-variable-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)*
|
||||
comparison-with-itself: null
|
||||
constant-name: _?[A-Z][A-Z0-9]*(_[A-Z0-9]+)*
|
||||
disable: []
|
||||
duplicated-load: null
|
||||
enum-element-name: '[A-Z][A-Z0-9]*(_[A-Z0-9]+)*'
|
||||
enum-name: ([A-Z][a-z0-9]*)+
|
||||
excluded_directories: !!set
|
||||
.git: null
|
||||
expression-not-assigned: null
|
||||
function-argument-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)*
|
||||
function-arguments-number: 10
|
||||
function-name: (_on_([A-Z][a-z0-9]*)+(_[a-z0-9]+)*|_?[a-z][a-z0-9]*(_[a-z0-9]+)*)
|
||||
function-preload-variable-name: ([A-Z][a-z0-9]*)+
|
||||
function-variable-name: '[a-z][a-z0-9]*(_[a-z0-9]+)*'
|
||||
load-constant-name: (([A-Z][a-z0-9]*)+|_?[A-Z][A-Z0-9]*(_[A-Z0-9]+)*)
|
||||
loop-variable-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)*
|
||||
max-file-lines: 1000
|
||||
max-line-length: 100
|
||||
max-public-methods: 20
|
||||
max-returns: 6
|
||||
mixed-tabs-and-spaces: null
|
||||
no-elif-return: null
|
||||
no-else-return: null
|
||||
signal-name: '[a-z][a-z0-9]*(_[a-z0-9]+)*'
|
||||
sub-class-name: _?([A-Z][a-z0-9]*)+
|
||||
tab-characters: 1
|
||||
trailing-whitespace: null
|
||||
unnecessary-pass: null
|
||||
unused-argument: null
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<rect width="128" height="128" rx="24" fill="#4a7c59"/>
|
||||
<text x="64" y="86" font-family="sans-serif" font-size="64" fill="#ffffff" text-anchor="middle">M</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 260 B |
@@ -0,0 +1,43 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://blboaodg2nrl7"
|
||||
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.svg"
|
||||
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.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
|
||||
@@ -0,0 +1,26 @@
|
||||
; Engine configuration file.
|
||||
; It's best edited using the editor UI and not directly,
|
||||
; since the parameters that go here are not all obvious.
|
||||
;
|
||||
; Format:
|
||||
; [section] ; section goes between []
|
||||
; param=value ; assign values to parameters
|
||||
|
||||
config_version=5
|
||||
|
||||
[application]
|
||||
|
||||
config/name="Les Aventuriers des mots"
|
||||
run/main_scene="res://scenes/boot/boot.tscn"
|
||||
config/features=PackedStringArray("4.6", "Forward Plus")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
[autoload]
|
||||
|
||||
GameManager="*res://autoload/game_manager.gd"
|
||||
ProfileManager="*res://autoload/profile_manager.gd"
|
||||
ProgressManager="*res://autoload/progress_manager.gd"
|
||||
ExerciseEngine="*res://autoload/exercise_engine.gd"
|
||||
SaveManager="*res://autoload/save_manager.gd"
|
||||
AudioManager="*res://autoload/audio_manager.gd"
|
||||
SettingsManager="*res://autoload/settings_manager.gd"
|
||||
@@ -0,0 +1,3 @@
|
||||
[gd_scene load_steps=1 format=3]
|
||||
|
||||
[node name="Boot" type="Node"]
|
||||
@@ -0,0 +1,46 @@
|
||||
extends SceneTree
|
||||
## Outil headless invoque par `make validate-data`.
|
||||
## A ce stade, verifie seulement que les fichiers data/**/*.json sont du JSON bien forme.
|
||||
## La validation contre les schemas (rule, exercise, dictation, curriculum, save) sera
|
||||
## ajoutee a l'etape "Donnees" (voir Ordre de construction, docs/specs/decisions.md point 2).
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
var json_paths: Array[String] = _find_json_files("res://data")
|
||||
var failures: Array[String] = []
|
||||
for path in json_paths:
|
||||
var file := FileAccess.open(path, FileAccess.READ)
|
||||
if file == null:
|
||||
failures.append("%s : lecture impossible" % path)
|
||||
continue
|
||||
var text := file.get_as_text()
|
||||
if text.strip_edges().is_empty():
|
||||
continue
|
||||
if JSON.parse_string(text) == null:
|
||||
failures.append("%s : JSON invalide" % path)
|
||||
|
||||
if failures.is_empty():
|
||||
print("validate-data : %d fichier(s) JSON valide(s)" % json_paths.size())
|
||||
quit(0)
|
||||
else:
|
||||
for failure in failures:
|
||||
printerr(failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _find_json_files(root_path: String) -> Array[String]:
|
||||
var result: Array[String] = []
|
||||
var dir := DirAccess.open(root_path)
|
||||
if dir == null:
|
||||
return result
|
||||
dir.list_dir_begin()
|
||||
var entry := dir.get_next()
|
||||
while entry != "":
|
||||
if entry != "." and entry != "..":
|
||||
var full_path := root_path.path_join(entry)
|
||||
if dir.current_is_dir():
|
||||
result.append_array(_find_json_files(full_path))
|
||||
elif entry.ends_with(".json"):
|
||||
result.append(full_path)
|
||||
entry = dir.get_next()
|
||||
return result
|
||||
@@ -0,0 +1 @@
|
||||
uid://01g5hgfcb5tq
|
||||
@@ -0,0 +1,14 @@
|
||||
extends GutTest
|
||||
## Verifie que le squelette du projet charge correctement les sept autoloads.
|
||||
## Les tests de logique pedagogique (correction, progression, sauvegardes)
|
||||
## arrivent avec les etapes correspondantes.
|
||||
|
||||
|
||||
func test_autoloads_are_registered() -> void:
|
||||
assert_not_null(GameManager, "GameManager doit etre charge")
|
||||
assert_not_null(ProfileManager, "ProfileManager doit etre charge")
|
||||
assert_not_null(ProgressManager, "ProgressManager doit etre charge")
|
||||
assert_not_null(ExerciseEngine, "ExerciseEngine doit etre charge")
|
||||
assert_not_null(SaveManager, "SaveManager doit etre charge")
|
||||
assert_not_null(AudioManager, "AudioManager doit etre charge")
|
||||
assert_not_null(SettingsManager, "SettingsManager doit etre charge")
|
||||
@@ -0,0 +1 @@
|
||||
uid://bgko12vcwsipr
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
# Installe l'outillage de developpement : binaire Godot pinne, addon GUT,
|
||||
# environnement Python pour gdtoolkit. Rien de ceci n'est commite (voir .gitignore) :
|
||||
# ce script est la seule source de verite pour reconstruire l'outillage.
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
GODOT_VERSION="$(cat .godot-version)"
|
||||
GODOT_BIN_DIR=".godot-bin"
|
||||
GODOT_BIN="${GODOT_BIN_DIR}/godot"
|
||||
GUT_VERSION="v9.6.0" # v9.6.1+ reference AccessibilityServer, absent de Godot 4.6.3
|
||||
GDTOOLKIT_VERSION="4.5.0"
|
||||
|
||||
mkdir -p "${GODOT_BIN_DIR}"
|
||||
|
||||
if [ ! -x "${GODOT_BIN}" ]; then
|
||||
echo "Telechargement de Godot ${GODOT_VERSION}..."
|
||||
TMP_ZIP="$(mktemp)"
|
||||
curl -sL -o "${TMP_ZIP}" \
|
||||
"https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}/Godot_v${GODOT_VERSION}_linux.x86_64.zip"
|
||||
unzip -o -j "${TMP_ZIP}" -d "${GODOT_BIN_DIR}"
|
||||
mv "${GODOT_BIN_DIR}/Godot_v${GODOT_VERSION}_linux.x86_64" "${GODOT_BIN}"
|
||||
chmod +x "${GODOT_BIN}"
|
||||
rm -f "${TMP_ZIP}"
|
||||
else
|
||||
echo "Godot deja present dans ${GODOT_BIN}."
|
||||
fi
|
||||
|
||||
if [ ! -d "addons/gut" ]; then
|
||||
echo "Telechargement de GUT ${GUT_VERSION}..."
|
||||
TMP_TAR="$(mktemp)"
|
||||
TMP_DIR="$(mktemp -d)"
|
||||
curl -sL -o "${TMP_TAR}" \
|
||||
"https://github.com/bitwes/Gut/archive/refs/tags/${GUT_VERSION}.tar.gz"
|
||||
tar xzf "${TMP_TAR}" -C "${TMP_DIR}"
|
||||
mkdir -p addons
|
||||
cp -r "${TMP_DIR}"/Gut-*/addons/gut addons/gut
|
||||
rm -rf "${TMP_TAR}" "${TMP_DIR}"
|
||||
else
|
||||
echo "GUT deja present dans addons/gut."
|
||||
fi
|
||||
|
||||
if [ ! -d ".venv" ]; then
|
||||
echo "Creation de l'environnement Python pour gdtoolkit..."
|
||||
python3 -m venv .venv
|
||||
fi
|
||||
./.venv/bin/pip install --quiet --upgrade pip
|
||||
./.venv/bin/pip install --quiet "gdtoolkit==${GDTOOLKIT_VERSION}"
|
||||
|
||||
echo "Setup termine : Godot ${GODOT_VERSION}, GUT ${GUT_VERSION}, gdtoolkit ${GDTOOLKIT_VERSION}."
|
||||
Reference in New Issue
Block a user