Initial project scaffold for Dimma

This commit is contained in:
2026-06-10 20:53:30 +02:00
commit 64f55c81b0
17 changed files with 702 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
# Build outputs
build/
*.exe
*.dll
*.so
*.dylib
*.app
*.o
*.a
# Odin
odin/bin/
# Go
bin/
# IDE
.idea/
.vscode/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# Logs
*.log
+201
View File
@@ -0,0 +1,201 @@
# Dimma
A cross-platform desktop application built with Odin (raylib + raygui) and Go (auto-updater).
## Project Structure
```
dimma/
├── odin/ # Odin source code (GUI application)
│ ├── main.odin # Main application entry point
│ ├── raylib.odin # raylib C interop bindings
│ ├── raygui.odin # raygui C interop bindings
│ ├── build.odin # Odin build script
│ └── odin.json # Odin project configuration
├── go/ # Go source code (auto-updater)
│ ├── main.go # Auto-updater CLI
│ ├── go.mod # Go module definition
│ ├── build.sh # Unix build script
│ └── build.ps1 # Windows build script
├── build/ # Compiled binaries (gitignored)
├── assets/ # Static files
│ ├── icon.png # Application icon
│ └── version.txt # Current version file
├── scripts/ # Build/utility scripts
│ ├── build-all.sh # Build all platforms (Unix)
│ ├── build-all.ps1 # Build all platforms (Windows)
│ ├── run.sh # Run script (Unix)
│ └── run.ps1 # Run script (Windows)
├── .gitignore
└── README.md
```
## Prerequisites
### Odin
- [Odin compiler](https://odin-lang.org/) (latest stable, e.g., `odin dev-2024-11`)
- raylib and raygui installed system-wide or via submodules
- C compiler (gcc/clang) for raylib compilation
### Go
- Go 1.21+
### Dependencies
- raylib (for Odin GUI)
- raygui (for Odin GUI)
## Build Instructions
### Odin (GUI Application)
Navigate to the `odin/` directory and build:
```bash
cd odin
odin build main.odin -build-mode:exe -target:. -out:../build/dimma
```
**With raylib/raygui:**
```bash
odin build main.odin \
-build-mode:exe \
-target:. \
-out:../build/dimma \
-raylib:include-path:/path/to/raylib/include \
-raylib:lib-path:/path/to/raylib/lib \
-raylib:static
```
### Go (Auto-Updater)
Navigate to the `go/` directory and build:
```bash
cd go
go build -o ../build/go-updater ./
```
For cross-compilation:
```bash
GOOS=linux GOARCH=amd64 go build -o ../build/go-updater-linux-amd64 ./
GOOS=windows GOARCH=amd64 go build -o ../build/go-updater-windows-amd64.exe ./
GOOS=darwin GOARCH=amd64 go build -o ../build/go-updater-darwin-amd64 ./
```
### Cross-Platform Build
Use the scripts in `scripts/` directory:
**Unix (Linux/macOS):**
```bash
chmod +x scripts/*.sh
./scripts/build-all.sh
```
**Windows (PowerShell):**
```powershell
.\scripts\build-all.ps1
```
## Testing
### Run the Odin Application
```bash
# Build first
cd odin
odin build main.odin -build-mode:exe -out:../build/dimma
# Then run
./scripts/run.sh
```
### Test the Auto-Updater
```bash
cd go
go run main.go --check
```
This will:
1. Fetch the latest version from `https://gitea.sanplex.xyz/Sansan/dimma/releases/latest`
2. Compare it to the hardcoded version `v0.1.0`
3. Print "Update available: {version}" or "Up to date"
## Cross-Compilation Notes
### Odin
Set the target OS and architecture using Odin's `-target` flag:
```bash
odin build main.odin -target:linux_amd64 -build-mode:exe
odin build main.odin -target:windows_amd64 -build-mode:exe
odin build main.odin -target:macos_amd64 -build-mode:exe
```
### Go
Use environment variables:
```bash
GOOS=linux GOARCH=amd64 go build ./
GOOS=windows GOARCH=amd64 go build ./
GOOS=darwin GOARCH=amd64 go build ./
```
## Git Setup
### Initialize Repository
The repository is already initialized. For a fresh clone:
```bash
git init
git add .
git commit -m "Initial project scaffold for Dimma"
```
### Add Remote
```bash
git remote add origin gitea.sanplex.xyz:Sansan/dimma.git
```
Or with HTTPS:
```bash
git remote add origin https://gitea.sanplex.xyz/Sansan/dimma.git
```
### First Push
```bash
git push -u origin main
```
Note: You'll need to authenticate with Gitea and may need to create the repository on the Gitea web interface first.
## Version Management
The current version is defined in:
- `assets/version.txt` - Plain text version file
- `odin/main.odin` - `CURRENT_VERSION` constant
- `go/main.go` - `CurrentVersion` constant
Update all three files when releasing a new version.
## Future Auto-Updater Implementation
The auto-updater will eventually:
1. Download the new binary from Gitea release assets
2. Replace the old binary (with appropriate permissions)
3. Restart the application
The Odin app will spawn the updater process and exit, allowing the updater to replace the binary safely.
## License
[License information to be added]
View File
+1
View File
@@ -0,0 +1 @@
v0.1.0
+30
View File
@@ -0,0 +1,30 @@
# Build script for Go updater (PowerShell)
# Usage: .\build.ps1 [os] [arch]
# Default: builds for current OS/architecture
$MODULE = "gitea.sanplex.xyz/Sansan/dimma-updater"
$OUTPUT_DIR = "..\build"
$BIN_NAME = "go-updater"
$OS = if ($args.Count -gt 0) { $args[0] } else { $env:GOOS }
$ARCH = if ($args.Count -gt 1) { $args[1] } else { $env:GOARCH }
if ($OS -eq "windows") { $EXT = ".exe" } else { $EXT = "" }
$OUTPUT = "$OUTPUT_DIR\$BIN_NAME-$OS-$ARCH$EXT"
New-Item -ItemType Directory -Force -Path $OUTPUT_DIR | Out-Null
Write-Host "Building Go updater for $OS/$ARCH..."
Write-Host "Output: $OUTPUT"
go build -o $OUTPUT .\
if ($OS -eq "linux" -or $OS -eq "darwin") {
# On Unix-like systems, make executable
if ($IsLinux -or $IsMacOS) {
chmod +x $OUTPUT
}
}
Write-Host "Build complete: $OUTPUT"
Executable
+32
View File
@@ -0,0 +1,32 @@
#!/bin/bash
# Build script for Go updater
# Usage: ./build.sh [os] [arch]
# Default: builds for current OS/architecture
MODULE="gitea.sanplex.xyz/Sansan/dimma-updater"
OUTPUT_DIR="../build"
BIN_NAME="go-updater"
OS=${1:-$(go env GOOS)}
ARCH=${2:-$(go env GOARCH)}
case "$OS" in
windows) EXT=".exe" ;;
*) EXT="" ;;
esac
OUTPUT="${OUTPUT_DIR}/${BIN_NAME}-${OS}-${ARCH}${EXT}"
mkdir -p "$OUTPUT_DIR"
echo "Building Go updater for ${OS}/${ARCH}..."
echo "Output: ${OUTPUT}"
go build -o "$OUTPUT" ./
if [ "$OS" = "linux" ] || [ "$OS" = "darwin" ]; then
chmod +x "$OUTPUT"
fi
echo "Build complete: ${OUTPUT}"
+7
View File
@@ -0,0 +1,7 @@
module gitea.sanplex.xyz/Sansan/dimma-updater
go 1.21
require (
github.com/inconshreveable/go-update v0.0.0-20230525132907-6d786845c5a3
)
+100
View File
@@ -0,0 +1,100 @@
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"net/http"
"os"
"strings"
)
const (
CurrentVersion = "v0.1.0"
ReleaseURL = "https://gitea.sanplex.xyz/Sansan/dimma/releases/latest"
)
type ReleaseInfo struct {
TagName string `json:"tag_name"`
}
func main() {
check := flag.Bool("check", false, "Check for updates")
flag.Parse()
if !*check {
flag.Usage()
return
}
fmt.Printf("Current version: %s\n", CurrentVersion)
latestVersion, err := fetchLatestVersion()
if err != nil {
fmt.Printf("Error fetching latest version: %v\n", err)
return
}
fmt.Printf("Latest version: %s\n", latestVersion)
if compareVersions(latestVersion, CurrentVersion) > 0 {
fmt.Printf("Update available: %s\n", latestVersion)
} else {
fmt.Println("Up to date")
}
}
func fetchLatestVersion() (string, error) {
resp, err := http.Get(ReleaseURL)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("HTTP %d", resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
// Gitea releases API returns JSON with tag_name
var release ReleaseInfo
if err := json.Unmarshal(body, &release); err != nil {
// Try to extract from HTML if not JSON
release.TagName = extractVersionFromHTML(string(body))
if release.TagName == "" {
return "", fmt.Errorf("failed to parse release info")
}
}
return release.TagName, nil
}
func extractVersionFromHTML(html string) string {
// Simple extraction from HTML (fallback for non-API URLs)
// Looks for patterns like "v0.1.0" or "0.1.0"
parts := strings.Split(html, "v")
for _, part := range parts {
if len(part) > 0 && part[0] >= '0' && part[0] <= '9' {
version := "v" + strings.Split(part, "\"")[0]
version = strings.Split(version, " ")[0]
version = strings.Split(version, ">")[0]
version = strings.TrimSpace(version)
if version != "" {
return version
}
}
}
return ""
}
func compareVersions(a, b string) int {
// Simple version comparison (v0.1.0 format)
a = strings.TrimPrefix(a, "v")
b = strings.TrimPrefix(b, "v")
return strings.Compare(a, b)
}
+18
View File
@@ -0,0 +1,18 @@
{
"name": "dimma",
"root": ".",
"vendor": false,
"definition_files": [
"main.odin"
],
"flags": [
"-raylib:include-path:/usr/local/include",
"-raylib:lib-path:/usr/local/lib",
"-raylib:static"
],
"build_flags": [
"-build-mode:exe",
"-target:.",
"-out:../build/dimma"
]
}
+37
View File
@@ -0,0 +1,37 @@
// Odin build script for Dimma
// Usage: odin build build.odin
package build
import "core:os"
import "core:fmt"
const (
OUTPUT_DIR = "../build/"
APP_NAME = "dimma"
)
main :: proc() {
// Determine OS and architecture
os_name := os.GetEnv("ODIN_OS")
if os_name == "" {
os_name = os.Environ()[0] // Fallback
}
arch := os.GetEnv("ODIN_ARCH")
if arch == "" {
arch = "amd64" // Default
}
output_path := OUTPUT_DIR + APP_NAME + "-" + os_name + "-" + arch
// Create build directory
os.MkdirAll(OUTPUT_DIR, 0755)
fmt.printf("Building Dimma for %s/%s...\n", os_name, arch)
fmt.printf("Output: %s\n", output_path)
// Build command would be:
// odin build main.odin -out:%s -build-mode:exe -target:.)...
// with appropriate raylib/raygui paths
}
+44
View File
@@ -0,0 +1,44 @@
package main
import "core:fmt"
import "core:os"
import raylib "./raylib.odin"
import raygui "./raygui.odin"
const (
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 450
APP_TITLE = "Dimma"
CURRENT_VERSION = "v0.1.0"
)
main :: proc() {
raylib.InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, APP_TITLE)
defer raylib.CloseWindow()
raylib.SetTargetFPS(60)
for !raylib.WindowShouldClose() {
raylib.BeginDrawing()
defer raylib.EndDrawing()
raylib.ClearBackground(raylib.RAYWHITE)
// Draw raygui
raygui.Draw()
}
}
// GUI procedure to be called from main loop
Draw :: proc() {
// Draw version label
pos := raylib.Vector2{10, 10}
raygui.Label(pos, "Current Version: " + CURRENT_VERSION)
// Draw update button
btn_pos := raylib.Vector2{10, 40}
btn_size := raylib.Vector2{200, 30}
if raygui.Button(btn_pos, btn_size, "Check for Updates") {
fmt.println("Check for Updates clicked")
}
}
+17
View File
@@ -0,0 +1,17 @@
// Placeholder for raygui C interop bindings
// Assumes raygui headers are available system-wide
package raygui
import raylib "../raylib.odin"
// GUI control functions
Label :: proc(pos: raylib.Vector2, text: rawstring) #cdecl
Button :: proc(pos: raylib.Vector2, size: raylib.Vector2, text: rawstring) -> bool #cdecl
// Layout functions
GuiSetStyle :: proc(control: i32, property: i32, value: i32) #cdecl
GuiLoadStyle :: proc(fileName: rawstring) -> bool #cdecl
GuiEnable :: proc() #cdecl
GuiDisable :: proc() #cdecl
GuiLock :: proc() #cdecl
GuiUnlock :: proc() #cdecl
+25
View File
@@ -0,0 +1,25 @@
// Placeholder for raylib C interop bindings
// Assumes raylib headers are available system-wide
package raylib
@(import_c)
const (
RAYWHITE = 0xF5F5F5FF
)
// Window functions
InitWindow :: proc(width: i32, height: i32, title: rawstring) #cdecl
CloseWindow :: proc() #cdecl
WindowShouldClose :: proc() -> bool #cdecl
SetTargetFPS :: proc(fps: i32) #cdecl
// Drawing functions
BeginDrawing :: proc() #cdecl
EndDrawing :: proc() #cdecl
ClearBackground :: proc(color: u32) #cdecl
// Vector2 type
Vector2 :: struct {
X: f32,
Y: f32,
}
+53
View File
@@ -0,0 +1,53 @@
# Cross-platform build script for Dimma (PowerShell)
# Builds Odin app + Go updater for all platforms
$ErrorActionPreference = "Stop"
$PROJECT_DIR = Resolve-Path (Split-Path $PSScriptRoot -Parent)
$BUILD_DIR = "$PROJECT_DIR\build"
$ODIN_DIR = "$PROJECT_DIR\odin"
$GO_DIR = "$PROJECT_DIR\go"
New-Item -ItemType Directory -Force -Path $BUILD_DIR | Out-Null
# Build Go updater for all platforms
$GO_PLATFORMS = @(
@("linux", "amd64"),
@("linux", "arm64"),
@("darwin", "amd64"),
@("darwin", "arm64"),
@("windows", "amd64")
)
foreach ($platform in $GO_PLATFORMS) {
$os = $platform[0]
$arch = $platform[1]
Write-Host "Building Go updater for $os/$arch..."
Push-Location $GO_DIR
$env:GOOS = $os
$env:GOARCH = $arch
.\build.ps1 $os $arch
Pop-Location
}
# Build Odin app for all platforms
$ODIN_PLATFORMS = @(
@("linux", "amd64"),
@("windows", "amd64"),
@("darwin", "amd64")
)
foreach ($platform in $ODIN_PLATFORMS) {
$os = $platform[0]
$arch = $platform[1]
Write-Host "Building Odin app for $os/$arch..."
# odin build $ODIN_DIR\main.odin `
# -out:`$BUILD_DIR\dimma-$os-$arch.exe `
# -build-mode:exe `
# -target:. `
# -raylib:include-path:C:\path\to\raylib\include `
# -raylib:lib-path:C:\path\to\raylib\lib
Write-Host " (Run: odin build $ODIN_DIR\main.odin -out:`$BUILD_DIR\dimma-$os-$arch -build-mode:exe)"
}
Write-Host "All builds complete. Output in $BUILD_DIR"
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
# Cross-platform build script for Dimma
# Builds Odin app + Go updater for all platforms
set -e
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
BUILD_DIR="$PROJECT_DIR/build"
ODIN_DIR="$PROJECT_DIR/odin"
GO_DIR="$PROJECT_DIR/go"
mkdir -p "$BUILD_DIR"
# Build Go updater for all platforms
GO_PLATFORMS=("linux/amd64" "linux/arm64" "darwin/amd64" "darwin/arm64" "windows/amd64")
for platform in "${GO_PLATFORMS[@]}"; do
IFS='/' read -r os arch <<< "$platform"
echo "Building Go updater for $os/$arch..."
(cd "$GO_DIR" && GOOS=$os GOARCH=$arch ./build.sh $os $arch)
done
# Build Odin app for all platforms
ODIN_PLATFORMS=("linux:amd64" "windows:amd64" "darwin:amd64")
for platform in "${ODIN_PLATFORMS[@]}"; do
IFS=':' read -r os arch <<< "$platform"
echo "Building Odin app for $os/$arch..."
# odin build $ODIN_DIR/main.odin \
# -out:$BUILD_DIR/dimma-$os-$arch \
# -build-mode:exe \
# -target:. \
# -raylib:include-path:/path/to/raylib/include \
# -raylib:lib-path:/path/to/raylib/lib
echo " (Run: odin build $ODIN_DIR/main.odin -out:$BUILD_DIR/dimma-$os-$arch -build-mode:exe)"
done
echo "All builds complete. Output in $BUILD_DIR/"
+26
View File
@@ -0,0 +1,26 @@
# Run script for Dimma (PowerShell)
# Usage: .\run.ps1 [platform] [arch]
# Platform can be: linux, windows, darwin
# Default: auto-detects current platform
$PROJECT_DIR = Resolve-Path (Split-Path $PSScriptRoot -Parent)
$BUILD_DIR = "$PROJECT_DIR\build"
$PLATFORM = if ($args.Count -gt 0) { $args[0] } else { $env:GOOS }
$ARCH = if ($args.Count -gt 1) { $args[1] } else { $env:GOARCH }
if ($PLATFORM -eq "") { $PLATFORM = $IsWindows -as [string] ? "windows" : ($IsLinux -as [string] ? "linux" : "darwin") }
if ($ARCH -eq "") { $ARCH = $env:PROCESSOR_ARCHITEW6432 -replace "AMD64", "amd64" -replace "ARM64", "arm64" }
$BINARY = "$BUILD_DIR\dimma-$PLATFORM-$ARCH"
if ($PLATFORM -eq "windows") { $BINARY = "$BINARY.exe" }
if (-not (Test-Path $BINARY)) {
Write-Host "Binary not found: $BINARY"
Write-Host "Available binaries in $BUILD_DIR:"
Get-ChildItem $BUILD_DIR
exit 1
}
Write-Host "Running: $BINARY"
& $BINARY
Executable
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash
# Run script for Dimma
# Usage: ./run.sh [platform]
# Platform can be: linux, windows, darwin
# Default: auto-detects current platform
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
BUILD_DIR="$PROJECT_DIR/build"
PLATFORM=${1:-$(uname -s | tr '[:upper:]' '[:lower:]')}
ARCH=${2:-$(uname -m)}
# Map uname output to platform
case "$PLATFORM" in
linux*) PLATFORM="linux" ;;
darwin*) PLATFORM="darwin" ;;
mingw*|cygwin*|msys*) PLATFORM="windows" ;;
windows) PLATFORM="windows" ;;
esac
# Map architecture
case "$ARCH" in
x86_64) ARCH="amd64" ;;
aarch64) ARCH="arm64" ;;
i?86) ARCH="386" ;;
armv*) ARCH="arm" ;;
esac
BINARY="$BUILD_DIR/dimma-$PLATFORM-$ARCH"
if [ "$PLATFORM" = "windows" ]; then
BINARY="$BINARY.exe"
fi
if [ ! -f "$BINARY" ]; then
echo "Binary not found: $BINARY"
echo "Available binaries in $BUILD_DIR/:"
ls -la "$BUILD_DIR/"
exit 1
fi
chmod +x "$BINARY"
echo "Running: $BINARY"
"$BINARY"