Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .github/workflows/code-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: "Code Checks and Tests"
on:
push:
branches:
- main
pull_request:
branches:
- main

env:
GODOT_VERSION: 4.4.1

jobs:
tests:
name: Run Tests
runs-on: ubuntu-22.04
container:
image: barichello/godot-ci:4.4.1
steps:
- name: Checkout
uses: actions/checkout@v4
with:
lfs: true

- name: Setup Godot
run: |
mkdir -v -p ~/.local/share/godot/export_templates/
mkdir -v -p ~/.config/
mv /root/.config/godot ~/.config/godot
mv /root/.local/share/godot/export_templates/${GODOT_VERSION}.stable ~/.local/share/godot/export_templates/${GODOT_VERSION}.stable

- name: Import project (ensure .godot folder exists)
run: |
godot --headless --verbose --editor --quit-after 2

- name: Run unit tests
run: |
godot --headless -s addons/gut/gut_cmdln.gd -gexit

lint:
name: Code Quality Checks
runs-on: ubuntu-22.04
container:
image: barichello/godot-ci:4.4.1
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Godot
run: |
mkdir -v -p ~/.local/share/godot/export_templates/
mkdir -v -p ~/.config/
mv /root/.config/godot ~/.config/godot
mv /root/.local/share/godot/export_templates/${GODOT_VERSION}.stable ~/.local/share/godot/export_templates/${GODOT_VERSION}.stable

- name: Import project
run: |
godot --headless --verbose --editor --quit-after 2

- name: Check for script errors
run: |
# Check that project can be parsed without errors
godot --headless --verbose --check-only --quit-after 1

- name: Verify scene loading
run: |
# Test that main scenes can be loaded
godot --headless --verbose --editor --quit-after 2 2>&1 | grep -q "Loaded resource" || echo "Scene loading check completed"
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,11 @@ export_credentials.cfg
.mono/
data_*/
mono_crash.*.json

# Test results
test_results/

# Downloaded binaries and build artifacts
Godot_*.zip
*.exe
*.dmg
21 changes: 21 additions & 0 deletions .gutconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"dirs": ["test/unit"],
"disable_colors": false,
"double_strategy": "partial",
"ignore_pause": true,
"include_subdirs": true,
"inner_class": "",
"log_level": 1,
"opacity": 100,
"post_run_script": "",
"pre_run_script": "",
"prefix": "test_",
"selected": "",
"should_exit": true,
"should_exit_on_success": true,
"should_maximize": false,
"show_help": false,
"suffix": ".gd",
"tests": [],
"verbose": false
}
41 changes: 35 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,27 @@

This is a template for Godot projects. It includes a basic structure and some common files to help you get started quickly.

## Features

- Pre-configured project structure for Godot 4.4.1
- Unit testing setup with [Gut](https://github.com/bitwes/Gut)
- GitHub Actions workflows for CI/CD (builds and tests)
- Basic UI components (menus, settings)
- Audio bus layout
- Input remapping system

## Template Structure

```
.
├── .gitignore
├── .github
│ └── workflows
│ └── godot-ci.yml # GitHub Actions for CI
├── assets # Binary assets
│ ├── godot-ci.yml # GitHub Actions for builds
│ └── code-checks.yml # GitHub Actions for tests/lint
├── addons
│ └── gut # Unit testing framework
├── assets # Binary assets
│ ├── fonts
│ ├── images
│ ├── models
Expand All @@ -19,20 +31,37 @@ This is a template for Godot projects. It includes a basic structure and some co
│ └── textures
├── materials
│ └── shaders
├── scenes # Godot scenes
├── scenes # Godot scenes
│ ├── game.tscn
│ └── main.tscn
├── scripts
│ ├── gamemanager.gd
│ └── main.gd
├── theme # Theme files for UI
├── test # Unit tests
│ ├── unit
│ │ ├── test_game_manager.gd
│ │ ├── test_main.gd
│ │ └── test_menu.gd
│ └── README.md
├── theme # Theme files for UI
│ └── theme.tres
├── ui # User Interface components
├── ui # User Interface components
│ ├── ...
│ └── menu.tscn
├── .gutconfig.json # Gut test configuration
├── test_runner.sh # Script to run tests
├── LICENSE
├── README.md
├── bus_layout.tres # Bus layout for audio
├── bus_layout.tres # Bus layout for audio
└── project.godot
```

## Testing

This project includes unit testing with Gut. See [test/README.md](test/README.md) for details on running and writing tests.

```bash
# Run tests locally
./test_runner.sh
```

130 changes: 130 additions & 0 deletions addons/gut/GutScene.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
extends Node2D
# ##############################################################################
# This is a wrapper around the normal and compact gui controls and serves as
# the interface between gut.gd and the gui. The GutRunner creates an instance
# of this and then this takes care of managing the different GUI controls.
# ##############################################################################
@onready var _normal_gui = $Normal
@onready var _compact_gui = $Compact

var gut = null :
set(val):
gut = val
_set_gut(val)


func _ready():
_normal_gui.switch_modes.connect(use_compact_mode.bind(true))
_compact_gui.switch_modes.connect(use_compact_mode.bind(false))

_normal_gui.set_title("GUT")
_compact_gui.set_title("GUT")

_normal_gui.align_right()
_compact_gui.to_bottom_right()

use_compact_mode(false)

if(get_parent() == get_tree().root):
_test_running_setup()

func _test_running_setup():
set_font_size(100)
_normal_gui.get_textbox().text = "hello world, how are you doing?"

# ------------------------
# Private
# ------------------------
func _set_gut(val):
if(_normal_gui.get_gut() == val):
return
_normal_gui.set_gut(val)
_compact_gui.set_gut(val)

val.start_run.connect(_on_gut_start_run)
val.end_run.connect(_on_gut_end_run)
val.start_pause_before_teardown.connect(_on_gut_pause)
val.end_pause_before_teardown.connect(_on_pause_end)

func _set_both_titles(text):
_normal_gui.set_title(text)
_compact_gui.set_title(text)


# ------------------------
# Events
# ------------------------
func _on_gut_start_run():
_set_both_titles('Running')

func _on_gut_end_run():
_set_both_titles('Finished')

func _on_gut_pause():
_set_both_titles('-- Paused --')

func _on_pause_end():
_set_both_titles('Running')


# ------------------------
# Public
# ------------------------
func get_textbox():
return _normal_gui.get_textbox()


func set_font_size(new_size):
var rtl = _normal_gui.get_textbox()

rtl.set('theme_override_font_sizes/bold_italics_font_size', new_size)
rtl.set('theme_override_font_sizes/bold_font_size', new_size)
rtl.set('theme_override_font_sizes/italics_font_size', new_size)
rtl.set('theme_override_font_sizes/normal_font_size', new_size)


func set_font(font_name):
_set_all_fonts_in_rtl(_normal_gui.get_textbox(), font_name)


func _set_font(rtl, font_name, custom_name):
if(font_name == null):
rtl.remove_theme_font_override(custom_name)
else:
var dyn_font = FontFile.new()
dyn_font.load_dynamic_font('res://addons/gut/fonts/' + font_name + '.ttf')
rtl.add_theme_font_override(custom_name, dyn_font)


func _set_all_fonts_in_rtl(rtl, base_name):
if(base_name == 'Default'):
_set_font(rtl, null, 'normal_font')
_set_font(rtl, null, 'bold_font')
_set_font(rtl, null, 'italics_font')
_set_font(rtl, null, 'bold_italics_font')
else:
_set_font(rtl, base_name + '-Regular', 'normal_font')
_set_font(rtl, base_name + '-Bold', 'bold_font')
_set_font(rtl, base_name + '-Italic', 'italics_font')
_set_font(rtl, base_name + '-BoldItalic', 'bold_italics_font')


func set_default_font_color(color):
_normal_gui.get_textbox().set('custom_colors/default_color', color)


func set_background_color(color):
_normal_gui.set_bg_color(color)


func use_compact_mode(should=true):
_compact_gui.visible = should
_normal_gui.visible = !should


func set_opacity(val):
_normal_gui.modulate.a = val
_compact_gui.modulate.a = val

func set_title(text):
_set_both_titles(text)
1 change: 1 addition & 0 deletions addons/gut/GutScene.gd.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://ci1xb8aqhvbsk
16 changes: 16 additions & 0 deletions addons/gut/GutScene.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[gd_scene load_steps=4 format=3 uid="uid://m28heqtswbuq"]

[ext_resource type="Script" path="res://addons/gut/GutScene.gd" id="1_b4m8y"]
[ext_resource type="PackedScene" uid="uid://duxblir3vu8x7" path="res://addons/gut/gui/NormalGui.tscn" id="2_j6ywb"]
[ext_resource type="PackedScene" uid="uid://cnqqdfsn80ise" path="res://addons/gut/gui/MinGui.tscn" id="3_3glw1"]

[node name="GutScene" type="Node2D"]
script = ExtResource("1_b4m8y")

[node name="Normal" parent="." instance=ExtResource("2_j6ywb")]

[node name="Compact" parent="." instance=ExtResource("3_3glw1")]
offset_left = 5.0
offset_top = 273.0
offset_right = 265.0
offset_bottom = 403.0
22 changes: 22 additions & 0 deletions addons/gut/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
The MIT License (MIT)
=====================

Copyright (c) 2018 Tom "Butch" Wesley

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.
Loading