Merge pull request 'Migrate to Godot 4' (#1) from feature/godot-migration into main
Build Puzzle Quest / Validate GDScript (push) Successful in 25s
Build Puzzle Quest / Lint GDScript (push) Successful in 26s
Build Puzzle Quest / Export Windows (push) Successful in 6m19s
Build Puzzle Quest / Export Linux (push) Successful in 6m58s
Build Puzzle Quest / Export Android (push) Successful in 7m19s

Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
2026-05-17 21:32:25 +02:00
438 changed files with 6728 additions and 67169 deletions
+43
View File
@@ -0,0 +1,43 @@
name: Setup Godot
description: Download a Godot headless Linux binary and (optionally) export templates.
inputs:
version:
description: Godot version (e.g. 4.6). Templates land under <version>.stable.
required: false
default: "4.6"
templates:
description: Install export templates too. "true" / "false".
required: false
default: "false"
runs:
using: composite
steps:
- name: Install Godot ${{ inputs.version }}
shell: bash
run: |
set -euo pipefail
VER="${{ inputs.version }}"
URL="https://github.com/godotengine/godot/releases/download/${VER}-stable/Godot_v${VER}-stable_linux.x86_64.zip"
wget -q "$URL" -O /tmp/godot.zip
mkdir -p "$HOME/bin"
unzip -q /tmp/godot.zip -d /tmp
mv "/tmp/Godot_v${VER}-stable_linux.x86_64" "$HOME/bin/godot"
chmod +x "$HOME/bin/godot"
echo "$HOME/bin" >> "$GITHUB_PATH"
"$HOME/bin/godot" --version
- name: Install export templates
if: inputs.templates == 'true'
shell: bash
run: |
set -euo pipefail
VER="${{ inputs.version }}"
URL="https://github.com/godotengine/godot/releases/download/${VER}-stable/Godot_v${VER}-stable_export_templates.tpz"
wget -q "$URL" -O /tmp/templates.tpz
DEST="$HOME/.local/share/godot/export_templates/${VER}.stable"
mkdir -p "$DEST"
unzip -q /tmp/templates.tpz -d /tmp/templates_extracted
mv /tmp/templates_extracted/templates/* "$DEST/"
ls "$DEST" | head
+118
View File
@@ -0,0 +1,118 @@
# Gitea Actions CI
Workflow defined in [`build.yml`](./build.yml). Triggered on push / PR to
`dev` and `main`, or manually via `workflow_dispatch`.
## Jobs
All jobs run on the default `ubuntu-latest` runner image (which already
ships Node, Python, git, wget, unzip, etc.). Godot is installed per-job
via the local composite action [`.gitea/actions/setup-godot`](../actions/setup-godot/action.yml),
which downloads the official Linux binary from the godotengine GitHub
release and (optionally) export templates into `$HOME`.
| Job | Tooling installed by the job | Role |
|------------------|---------------------------------------------------------------------------|------------------------------------------------------------------------------------------|
| `validate` | Godot binary (no templates) | `godot --headless --import` then grep for `SCRIPT ERROR` / `Parse Error`. Uploads `.godot/` cache. |
| `lint` | `gdtoolkit==4.*` via `pip` | `gdlint scripts db scenes`. Parallel to `validate`; does not gate exports yet. |
| `export-desktop` | Godot binary + export templates | Matrix: Windows / Linux / macOS. Reuses the import cache, uploads each binary as artifact. |
| `export-android` | Godot binary + export templates + JDK 17 + Android SDK (under `$GITHUB_WORKSPACE/.android-sdk`) | Provisions keystore, writes `editor_settings-4.tres` with SDK / JDK paths, exports APK. |
Artifacts are kept 14 days, accessible from the Gitea run page.
## Prerequisites before the first successful run
1. **Godot version**`GODOT_VERSION` is set at the top of the workflow
(currently `4.6`). The setup action expects a stable release on the
godotengine GitHub releases page; bump in lockstep with the project.
2. **macOS preset missing** — add it in Godot Editor → Project → Export →
Add → macOS, name it exactly `macOS` (or change the matrix entry). The
`.zip` will be unsigned; on Mac it needs
`xattr -dr com.apple.quarantine` to launch.
3. **`Linux/X11Debug` preset** — Godot-3-era name. Reopen the project in
Godot 4 once and re-save the preset (the editor may rename it). Update
the matrix `preset:` field accordingly if it does.
4. **Gitea runner**`act_runner` with the default
`catthehacker/ubuntu:act-latest` image is enough; no Docker-in-Docker
needed now that no job uses `container:`. The runner must reach
`github.com` (for actions + Godot release downloads) and
`dl.google.com` (for the Android SDK).
5. **Optional secret** `ANDROID_KEYSTORE_BASE64``base64 -w0 debug.keystore`,
stored as a Gitea repo secret. Without it, a throwaway keystore is
generated per run, so the APK signature changes every build.
## Linting
`gdlint` (from Scony's `gdtoolkit`) runs in the `lint` job over `scripts/`,
`db/`, and `scenes/`. `addons/` (third-party LOD plugin) and `developers/`
(sandbox) are intentionally excluded.
The job is **non-blocking** today — the export jobs only depend on
`validate`, so a lint failure prints warnings but still produces binaries.
Once the codebase is clean, switch the export jobs' `needs: validate` to
`needs: [validate, lint]` to make lint a hard gate.
Suppress specific rules per-line with `# gdlint: disable=<rule>` or
project-wide with a `gdlintrc` file at the repo root (see
[gdtoolkit docs](https://github.com/Scony/godot-gdscript-toolkit/wiki)).
## Known issues from first runs
Captured from the first triggered runs on `feature/godot-migration`
(2026-05-17). Both must be resolved before the workflow can pass.
### 1. Container jobs failed with `node: not found` (resolved 2026-05-17)
The first runs used `container: barichello/godot-ci:4.6` for the Godot
jobs. That image does not ship Node.js, so `actions/checkout@v4` (a JS
action) crashed at startup with
`OCI runtime exec failed: exec: "node": executable file not found`.
Resolved by removing every `container:` block. The runner's default
`catthehacker/ubuntu:act-latest` image already has Node / Python / git /
JDK, and Godot is now installed at the start of each job via the local
composite action `.gitea/actions/setup-godot/`.
### 2. `actions/checkout` clones the wrong URL (resolved 2026-05-17)
The first runs failed at clone time because the runner asked for
`https://dev.stilobique.com/darknight/puzzle-quest/info/refs` while
Gitea was mounted under `/gitea/` behind YunoHost — the request was
intercepted by the YunoHost SSO at the root and redirected before
reaching Gitea.
Resolved by relocating Gitea to the root: it now serves at
`https://dev.stilobique.com/` directly (API at `/api/v1/...`,
`clone_url` at `/<owner>/<repo>.git`). The runner-injected
`GITHUB_SERVER_URL` and the actual Gitea base URL now agree.
If Gitea is ever moved back under a sub-path, the fix is `ROOT_URL` in
`app.ini` (`[server] ROOT_URL = https://<host>/<prefix>/`) or
re-registering `act_runner` with the full instance URL.
### 3. Default-branch mismatch
The Gitea API reports `default_branch: main` for the repo, but
`CLAUDE.md` describes `dev` as the default. The workflow listens to both,
so jobs trigger correctly either way, but the "Workflows" sidebar in the
Gitea UI reads from whatever the actual default branch is. If you intend
`dev` to be the default, update it under repo Settings → Branches.
## Differences from the old `.drone.yml`
- No more Drone, no more Butler — build only, artifacts downloadable from
the Gitea UI.
- GDScript validation step before export (didn't exist).
- `.godot/` import cache shared between jobs (faster reruns).
- Keystore via Gitea secret instead of a public pCloud link.
- macOS target added (preset still to be created in Godot).
- `master` / empty `ReleaseVersion` pipeline → replaced by triggers on
`main` (release branch per `CLAUDE.md`).
## Future: itch.io deploy via Butler
Not wired. When you want it back, add a `deploy-itch` job gated on tag
push (`v*`) that downloads the artifacts and runs
`butler push <dir> dev-crea/ahog:<channel>` with `BUTLER_API_KEY` from
secrets. Channels used historically:
`windows`, `linux`, `android`, `mac`.
+217
View File
@@ -0,0 +1,217 @@
name: Build Puzzle Quest
on:
push:
branches: [dev, main, feature/godot-migration]
pull_request:
branches: [dev, main]
workflow_dispatch:
env:
GODOT_VERSION: "4.6"
jobs:
# ---------------------------------------------------------------------------
# 1. GDScript validation — parse every script and fail on errors / warnings.
# ---------------------------------------------------------------------------
validate:
name: Validate GDScript
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.gitea/actions/setup-godot
with:
version: ${{ env.GODOT_VERSION }}
- name: Import project (parses every .gd / .tscn)
run: |
godot --headless --import 2>&1 | tee /tmp/godot-import.log || true
- name: Fail on parse / script errors
run: |
if grep -qE "SCRIPT ERROR|Parse Error|ERROR: .*\.gd" /tmp/godot-import.log; then
echo "::error::GDScript errors detected during import"
grep -E "SCRIPT ERROR|Parse Error|ERROR: .*\.gd" /tmp/godot-import.log
exit 1
fi
# ---------------------------------------------------------------------------
# 2. Static analysis — gdlint from Scony's gdtoolkit (Python, no Godot).
# Runs in parallel with `validate`. Exports do NOT depend on this job,
# so a lint failure does not block builds while the Godot-3 leftovers
# are still being cleaned up. Once the tree is clean, add this job to
# the `needs:` of the export jobs to make it a hard gate.
# ---------------------------------------------------------------------------
lint:
name: Lint GDScript
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install gdtoolkit
run: |
python3 -m venv /tmp/gdlint-venv
/tmp/gdlint-venv/bin/pip install --quiet "gdtoolkit==4.*"
echo "/tmp/gdlint-venv/bin" >> "$GITHUB_PATH"
- name: Run gdlint
run: gdlint scripts db scenes
# ---------------------------------------------------------------------------
# 3. Desktop exports — runs in parallel.
# macOS is commented out until a preset is added in the Godot editor
# (export_presets.cfg has none today). Restore the entry once the preset
# exists; the matrix is otherwise ready to take it.
# ---------------------------------------------------------------------------
export-desktop:
name: Export ${{ matrix.platform }}
needs: validate
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- platform: Windows
preset: WindowsDebug
output: releases/windows/Puzzle-Quest.exe
artifact_path: releases/windows
- platform: Linux
preset: Linux/X11Debug
output: releases/linux/Puzzle-Quest.x86_64
artifact_path: releases/linux
# - platform: macOS
# preset: macOS
# output: releases/macos/Puzzle-Quest.zip
# artifact_path: releases/macos
steps:
- uses: actions/checkout@v4
- uses: ./.gitea/actions/setup-godot
with:
version: ${{ env.GODOT_VERSION }}
templates: "true"
- name: Import project
run: godot --headless --import || true
- name: Prepare output dir
run: mkdir -p "${{ matrix.artifact_path }}"
- name: Export ${{ matrix.platform }}
run: godot --headless --export-debug "${{ matrix.preset }}" "${{ matrix.output }}"
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: PuzzleQuest-${{ matrix.platform }}
path: ${{ matrix.artifact_path }}
if-no-files-found: error
retention-days: 14
# ---------------------------------------------------------------------------
# 4. Android export — Godot + JDK 17 + Android SDK installed in $HOME.
# Provide ANDROID_KEYSTORE_BASE64 as a Gitea secret for a stable signature;
# otherwise a fresh debug keystore is generated on each run.
# ---------------------------------------------------------------------------
export-android:
name: Export Android
needs: validate
runs-on: ubuntu-latest
env:
ANDROID_HOME: ${{ github.workspace }}/.android-sdk
steps:
- uses: actions/checkout@v4
- uses: ./.gitea/actions/setup-godot
with:
version: ${{ env.GODOT_VERSION }}
templates: "true"
- name: Install JDK 17
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends openjdk-17-jdk
echo "JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64" >> "$GITHUB_ENV"
- name: Install Android command-line tools + SDK
run: |
set -euo pipefail
mkdir -p "$ANDROID_HOME/cmdline-tools"
wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O /tmp/cmdline.zip
unzip -q /tmp/cmdline.zip -d "$ANDROID_HOME/cmdline-tools"
mv "$ANDROID_HOME/cmdline-tools/cmdline-tools" "$ANDROID_HOME/cmdline-tools/latest"
# `yes |` returns 141 (SIGPIPE) under `set -o pipefail` once sdkmanager
# closes its stdin — feed a finite stream of "y" answers instead.
printf 'y\n%.0s' {1..50} | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses >/dev/null
"$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" \
"platform-tools" "platforms;android-34" "build-tools;34.0.0" >/dev/null
- name: Provision debug keystore
env:
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
run: |
if [ -n "${ANDROID_KEYSTORE_BASE64:-}" ]; then
echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > /tmp/debug.keystore
else
keytool -keyalg RSA -genkeypair -alias androiddebugkey -keypass android \
-keystore /tmp/debug.keystore -storepass android \
-dname "CN=Android Debug,O=Android,C=US" -validity 9999
fi
# Godot rejects exports unless all three keystore/debug{,_user,_password}
# are set together (or all three empty) — patch every one.
sed -i 's@keystore/debug=".*"@keystore/debug="/tmp/debug.keystore"@g' export_presets.cfg
sed -i 's@keystore/debug_user=".*"@keystore/debug_user="androiddebugkey"@g' export_presets.cfg
sed -i 's@keystore/debug_password=".*"@keystore/debug_password="android"@g' export_presets.cfg
- name: Write Godot editor settings (Android SDK / JDK paths)
run: |
mkdir -p ~/.config/godot
# Godot 4.5+ uses a minor-version-suffixed settings file
# (editor_settings-4.6.tres for 4.6), not the major-only -4.tres.
cat > ~/.config/godot/editor_settings-${GODOT_VERSION}.tres <<EOF
[gd_resource type="EditorSettings" format=3]
[resource]
export/android/android_sdk_path = "${ANDROID_HOME}"
export/android/java_sdk_path = "/usr/lib/jvm/java-17-openjdk-amd64"
export/android/debug_keystore = "/tmp/debug.keystore"
export/android/debug_keystore_user = "androiddebugkey"
export/android/debug_keystore_pass = "android"
EOF
- name: Import project
run: godot --headless --import || true
- name: Prepare output dir
run: mkdir -p releases/android
- name: Export Android APK
run: godot --headless --export-debug "AndroidDebug" "releases/android/Puzzle-Quest.apk"
- name: Sign + verify APK
run: |
set -euo pipefail
APK="releases/android/Puzzle-Quest.apk"
APKSIGNER="$ANDROID_HOME/build-tools/34.0.0/apksigner"
# Godot 4.6 sometimes ships an unsigned APK from the headless
# export (sign step skips silently when its internal apksigner
# call can't locate java). Re-sign unconditionally — idempotent
# if Godot did sign, and guarantees a valid APK if it didn't.
"$APKSIGNER" sign \
--ks /tmp/debug.keystore \
--ks-pass pass:android \
--ks-key-alias androiddebugkey \
--key-pass pass:android \
--v1-signing-enabled true \
--v2-signing-enabled true \
--v3-signing-enabled true \
"$APK"
"$APKSIGNER" verify --verbose "$APK"
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: PuzzleQuest-Android
path: releases/android
if-no-files-found: error
retention-days: 14
+13 -2
View File
@@ -3,8 +3,17 @@
### Godot ### ### Godot ###
# Godot-specific ignores # Godot 3.x cache directory (replaced by .godot/ in Godot 4.x)
.import/ .import/
# Godot 4.x project cache (re-generated on open; do not commit)
.godot/
# Android build template directory generated by the editor
# (the .gdignore file is kept; everything else under android/ is build output)
android/*
!android/.gdignore
export.cfg export.cfg
# Imported translations (automatically generated from CSV files) # Imported translations (automatically generated from CSV files)
@@ -58,7 +67,9 @@ $RECYCLE.BIN/
# End of https://www.toptal.com/developers/gitignore/api/godot,linux,windows # End of https://www.toptal.com/developers/gitignore/api/godot,linux,windows
# Ignore folders releases and build Android # Ignore folders releases and build Android
releases # (the .gdignore marker is tracked so Godot skips scanning this directory)
releases/*
!releases/.gdignore
# Ignore override godot # Ignore override godot
override.cfg override.cfg
+1
View File
@@ -0,0 +1 @@
+173
View File
@@ -0,0 +1,173 @@
# Puzzle Quest
Hidden-object game built with **Godot 4.6** (single renderer: Forward+).
Branched from a Godot 3.3 codebase — migration is recent, expect leftover
Godot-3-isms to occasionally surface.
## Run
```
godot --editor # open project in the editor
godot # run the main scene (scenes/Main.tscn)
```
The system package `godot` (Arch `extra/godot`) is the project's Godot. There
is no in-repo Godot binary.
## Architecture
**Autoloads** (declared in `project.godot [autoload]`, loaded in this order):
| Name | Source | Role |
|------------------|---------------------------------------|-------------------------------------------------------------------|
| `Loading` | `scenes/UI/loading/Loading.tscn` | Full-screen transition overlay (BG + animated border + progress) |
| `Global` | `scripts/Global.gd` | Async scene loader (`goto_scene(path)`) + `database` reference |
| `Setting` | `scripts/Setting.gd` | Reads/writes the settings table; applies locale/resolution/fullscreen |
| `Event` | `scripts/Event.gd` | Static handlers connected to scene buttons (Warcraft / Home / reset / back) |
| `GlobalAnimation`| `scripts/Animation.gd` | Tween-based dissolve + HUD slide/warning animations |
**Database (`scripts/Database.gd`)**
- Plain JSON at `db/ahog.json`. Three tables: `settings`, `levels`, `scenes`.
- On Android the file is copied once to `user://database.json` and written
there (game saves modify lock state per item).
- `Global.database` is a `Database.DB` instance exposing
`get_table_by_name(name)` and `save_db()`. Each `Table` exposes
`get_data_at_row_idx(row_id)`, `edit_data(prop_id, row_id, value)`,
`m_rows_count`, `get_data_by_prop_name_and_data(prop_name, value)`,
`get_dictionary_by_prop_name_and_data(prop_name, value)`.
- `db/M*.gd` are typed accessors (MBase / MScene / MLevel / MSetting) that
read rows via the API above — extend these, not the JSON shape directly.
**Scene transitions** (`Global.goto_scene(path)`)
Uses `ResourceLoader.load_threaded_request` + `load_threaded_get_status` +
`load_threaded_get` (Godot 4 API; the original `load_interactive`/`poll()`
was removed). The Loading overlay (autoload) plays `BorderAnim` while the
new scene loads in a background thread; `Event._loading_is_started/finished`
flip `Global.loaded` so the poll only runs once the entry animation has set
the boolean. Don't call `current_scene.queue_free()` outside this function
— it will leak the resource and break the loader state.
**Levels.tscn / level scenes**
`scenes/levels/Levels.tscn` is the shared shell; concrete levels
(`warcraft/WarCraft.tscn`, `home/Home.tscn`) inherit from it. Each scene
has a `HiddenObjectsItems/<Item>` `MeshInstance3D` with an `Area3D`
collision shape; clicking it triggers `Levels._check_collider`
`_start_dissolve(name)``GlobalAnimation.start_dissolve(mesh, material)`
which runs the dissolve shader on `material.dissolve_amount`.
The runtime hidden-object list lives under
`scenes/levels/parts/ListObjects.tscn` and is populated dynamically from
the `scenes` table for the current `Global.current_scene_int`.
## Migration notes (Godot 3 → 4)
The conversion is mostly done but a few classes of mistake keep surfacing
because `godot --convert-3to4` does not handle them:
- **Label**: `align/valign``horizontal_alignment/vertical_alignment`.
- **Button**: `pressed` (property) → `button_pressed`; `set_pressed()`
assignment to `button_pressed`. The `pressed` *signal* still exists.
- **ScrollContainer**: `scroll_horizontal_enabled = false`
`horizontal_scroll_mode = 0` (and same for vertical). ScrollContainer
also ships a non-empty default panel style in Godot 4 — set
`theme_override_styles/panel = StyleBoxEmpty` if you need transparency.
- **TextureRect / TextureButton**: `expand = true``expand_mode = 1`.
`stretch_mode` enum values **shifted down by 1** between 3 and 4 (the
deprecated "Scale on Expand" at index 0 was removed): G3's Tile (2) is
G4's Tile (1), G3's Keep (3) is G4's Keep (2), etc.
- **Environment**: `background_mode` enum changed (G3 3=Sky → G4 2=Sky;
G4 3 is Canvas which renders black). `background_sky``sky`;
`background_energy``background_energy_multiplier`;
`fog_color``fog_light_color`; `fog_height_min``fog_height`;
`fog_mode = 1` (Depth) needed to keep `fog_depth_*` semantics, otherwise
Godot 4 falls back to dense `fog_density` exponential fog.
- **AnimationPlayer**: `add_animation(name, anim)` removed — go through
`get_animation_library("")` (create one with `add_animation_library("")`
if it returns null) and call `lib.add_animation(name, anim)`.
- **Tween**: no longer a Node — call `create_tween()` from any Node and use
`tween.tween_method(...)`. Delete any `[node type="Tween"]` from older
`.tscn` files (the loader will crash otherwise).
- **PhysicsRayQuery**: `space_state.intersect_ray(from, to, ...)`
`PhysicsRayQueryParameters3D.create(from, to)`, set fields, then
`space_state.intersect_ray(query)`.
- **PackedScene.instance()** → `instantiate()`.
- **String / cast operators**: `String(x)` constructor doesn't exist — use
`str(x)`. `x as int/String/bool` does **not** parse strings — use
`int(s)`, `str(x)`, `bool(int(s))`.
- **Internationalization**: project setting is `[internationalization]
locale/translations=...`, not `[locale] translations=...`. Locale codes
must match `.po` filenames exactly (`fr.po` → `"fr"`; G3-style `fr_FR`
no longer auto-falls-back).
- **Inherited scenes**: nodes from an instanced child scene need
`layout_mode = 1` + `anchors_preset = 15` explicitly set in the parent
scene file, otherwise Godot 4 treats them as Position-mode and zeroes
the anchors. Watch for stale per-Label `layout_mode = 0` /
`anchor_right = 0` overrides in Main.tscn-style parent scenes.
## Plugins
- `addons/lod/` — Calinou's Level-of-Detail plugin (Spatial / OmniLight /
SpotLight / Particles → 3D variants). Class declarations use the Godot 4
form (`@icon("...") class_name X` + `extends Node3D` separately).
- `addons/godot_db_manager/` — **removed during migration**. Don't restore
it; it relies on `WindowDialog`/`Tabs`/`PopupPanel` which were dropped in
Godot 4. The replacement is `scripts/Database.gd` (see above).
## Custom shaders / materials
Drop-in shaders live in `.material` resources (binary `RSCC` format) next
to each prop. `scripts/migrate_shaders.gd` is a one-shot tool that walks
`assets/` and rewrites the embedded shader code (Godot 3 → 4 keyword
renames: `depth_draw_alpha_prepass`, `hint_color`, `NORMALMAP`). Re-run it
with `godot --headless --script scripts/migrate_shaders.gd` after adding
new materials authored in Godot 3.
`assets/fonts/text_outline.material` is a VisualShader graph from Godot 3
that doesn't connect cleanly in 4 (out-of-bounds `p_from_port` errors,
COLOR never written). It has been detached from the Summary menu labels;
re-author it with Godot 4's built-in `theme_override_constants/outline_size`
+ `theme_override_colors/font_outline_color` instead.
## Known visual issues to revisit
- **Baked lightmap is gone.** `scenes/levels/warcraft/WarCraft.lmbake` is
in Godot 3's binary format (incompatible). The `LightmapGI` node still
exists in `WarCraft.tscn` but its `light_data` reference is cleared.
Open the scene in the editor and re-bake (Scene → Bake Lightmaps).
- **`assets/ui/themes/tab_select/UI-level-btn-shadow.png`** is 83% opaque
black with feathered edges (a drop-shadow texture). In Godot 4 it
renders stretched and opaque, which looked like a black square below
each level tile, so its `BackgroundTile` TextureRect is currently
`visible = false`. Replace with a proper 9-patch / shader if the shadow
effect is wanted.
- `developers/aurelien/` is a sandbox — files there (`ui_scrolls.tscn`,
`ui_tile.tscn`, `CheckLightmap.tscn`) still use Godot-3 property names
in places. Not on the main flow, low priority.
## CI
Gitea Actions workflow at `.gitea/workflows/build.yml`, documented in
`.gitea/workflows/README.md`. Three jobs: GDScript validation
(`godot --headless --import` + error grep), desktop matrix
(Windows / Linux / macOS), and Android. Build only — no Butler / itch.io
deploy currently wired (channels used historically were
`dev-crea/ahog:windows|android|linux|mac`). Drone pipeline removed.
Branches: default `dev`, releases from `main`. Long-running migration work
on `feature/godot-migration`.
## Conventions
- Don't commit `db/ahog.json` runtime mutations (lock progress saved
during play). The README documents using `git update-index --skip-worktree`
but the cleaner alternative is just to `git checkout db/ahog.json`
before staging.
- `android/`, `.godot/`, and `releases/` are in `.gitignore`. The
`.import` sidecars next to assets **are** committed (they carry the
stable UIDs Godot 4 generates).
- Commit messages: imperative, English, explain the *why* (especially for
migration commits — the next person reading the diff won't have the
Godot 3 context).
-2
View File
@@ -1,5 +1,3 @@
[![Build Status](https://drone.dev-crea.com/api/badges/Athena/game-source/status.svg)](https://drone.dev-crea.com/Athena/game-source)
- Hidden Object - Hidden Object
- Tips - Tips
- Log on Android - Log on Android
@@ -1,7 +0,0 @@
[gd_resource type="DynamicFont" load_steps=2 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1]
[resource]
size = 8
font_data = ExtResource( 1 )
@@ -1,7 +0,0 @@
[gd_resource type="DynamicFont" load_steps=2 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1]
[resource]
size = 10
font_data = ExtResource( 1 )
@@ -1,7 +0,0 @@
[gd_resource type="DynamicFont" load_steps=2 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1]
[resource]
size = 12
font_data = ExtResource( 1 )
@@ -1,7 +0,0 @@
[gd_resource type="DynamicFont" load_steps=2 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1]
[resource]
size = 14
font_data = ExtResource( 1 )
@@ -1,6 +0,0 @@
[gd_resource type="DynamicFont" load_steps=2 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1]
[resource]
font_data = ExtResource( 1 )
@@ -1,7 +0,0 @@
[gd_resource type="DynamicFont" load_steps=2 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1]
[resource]
size = 18
font_data = ExtResource( 1 )
@@ -1,7 +0,0 @@
[gd_resource type="DynamicFont" load_steps=2 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1]
[resource]
size = 20
font_data = ExtResource( 1 )
@@ -1,7 +0,0 @@
[gd_resource type="DynamicFont" load_steps=2 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1]
[resource]
size = 22
font_data = ExtResource( 1 )
@@ -1,7 +0,0 @@
[gd_resource type="DynamicFont" load_steps=2 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1]
[resource]
size = 24
font_data = ExtResource( 1 )
@@ -1,7 +0,0 @@
[gd_resource type="DynamicFont" load_steps=2 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/Roboto-Regular.ttf" type="DynamicFontData" id=1]
[resource]
size = 26
font_data = ExtResource( 1 )
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

@@ -1,34 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/debug.png-72578d6223132f8bc16d1922f9da1248.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/godot_db_manager/assets/tex/debug.png"
dest_files=[ "res://.import/debug.png-72578d6223132f8bc16d1922f9da1248.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

@@ -1,34 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/gui.png-1d6d47ba1ecd00882b63b6f57f502e61.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/godot_db_manager/assets/tex/gui.png"
dest_files=[ "res://.import/gui.png-1d6d47ba1ecd00882b63b6f57f502e61.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0
@@ -1,38 +0,0 @@
"""
class GDDBConstants
"""
class_name GDDBConstants
tool
extends Node
# GDDB signature
const c_gddb_signature = "GDDB_ver"
# GDDB ver
const c_gddb_ver = "2.0"
# invalid id to initialize integer properties
const c_invalid_id = -1
# maximum database name length
const c_max_db_name_len = 16
# maximum table name length
const c_max_table_name_len = 16
# characters that should not be part of the database name
const c_invalid_characters = "`~!@#$%^&*()=+[]{}\\|;:'\",<.>/?"
# addon main path
const c_addon_main_path = "res://addons/godot_db_manager/"
# maximum tables list width
const c_max_tables_list_width = 400.0
# minimum cell width
const c_min_cell_width = 150.0
# maximum cell width
const c_max_cell_width = 400.0
@@ -1,96 +0,0 @@
"""
class GDDBGlobals
"""
class_name GDDBGlobals
tool
extends Node
# a flag that tells if the tool's interface is active or not
var m_is_interface_active : bool = false
# sets the active flag
func set_interface_active(active : bool) -> void :
m_is_interface_active = active
# returns true if the tool's interface is active
func is_interface_active() -> bool :
return m_is_interface_active
# returns the name of the data type
func get_data_name(data_type : int) -> String :
if(data_type == gddb_types.e_prop_type_bool):
return "Bool"
elif(data_type == gddb_types.e_prop_type_int):
return "Integer"
elif(data_type == gddb_types.e_prop_type_float):
return "Float"
elif(data_type == gddb_types.e_prop_type_string):
return "String"
elif(data_type == gddb_types.e_prop_type_resource):
return "Resource"
print("GDDBGlobals::get_data_name(" + str(data_type) + ")")
return "Unknown data type"
# returns the name of the data filter
func get_data_filter_name(data_filter_type : int) -> String :
if(data_filter_type == gddb_types.e_data_filter_equal):
return "Equal"
elif(data_filter_type == gddb_types.e_data_filter_not_equal):
return "Not equal"
elif(data_filter_type == gddb_types.e_data_filter_less):
return "Less"
elif(data_filter_type == gddb_types.e_data_filter_greater):
return "Greater"
elif(data_filter_type == gddb_types.e_data_filter_lequal):
return "Less or equal"
elif(data_filter_type == gddb_types.e_data_filter_gequal):
return "Greater or equal"
print("GDDBGlobals::get_data_filter_name(" + str(data_filter_type) + ")")
return "Unknown data filter type"
# checks the name of the database
func check_db_name(db_name : String) -> bool :
for idx in range(0, db_name.length()):
for jdx in range(0, gddb_constants.c_invalid_characters.length()):
if(db_name[idx] == gddb_constants.c_invalid_characters[jdx]):
return false
return true
# returns a json from a row from a table
func get_json_from_row(table : Object, row_idx : int) -> String :
var json = "{"
var row = table.get_data_at_row_idx(row_idx)
for jdx in range(0, row.size()):
var prop = table.get_prop_at(jdx)
json += "\"" + prop.get_prop_name() + "\":"
json += "\"" + row[jdx].get_data() + "\""
if(jdx < row.size() - 1):
json += ", "
json += "}"
return json
# returns the digits count from a number
func get_digits_count(number : int) -> int :
if(number == 0):
return 1
var digits_count = 0
while(number > 0):
number /= 10
digits_count += 1
return digits_count
# replace special characters in a string to handle properly saving into database
func handle_string(text : String) -> String :
var string = ""
for idx in range(0, text.length()):
if(text[idx] == "\n"):
string += "\\n"
else:
string += text[idx]
return string
-45
View File
@@ -1,45 +0,0 @@
"""
class GDDBTypes
"""
class_name GDDBTypes
tool
extends Node
# Database loading errors
enum {
e_db_invalid_file = -11,
e_db_invalid_ver = -10,
e_db_valid = 0
}
# Property types
enum {
e_prop_type_bool = 0
e_prop_type_int = 1,
e_prop_type_float = 2,
e_prop_type_string = 3,
# TODO: insert more data types here and increase e_prop_type_resource
e_prop_type_resource = 4,
e_prop_types_count
}
# Data filters
enum {
e_data_filter_equal = 0,
e_data_filter_not_equal = 1,
e_data_filter_less = 2,
e_data_filter_greater = 3,
e_data_filter_lequal = 4, # less or equal
e_data_filter_gequal = 5 # greater or equal
}
# new table dlg type
enum {
e_new_dlg_type_new = 0,
e_new_dlg_type_edit = 1
}
-323
View File
@@ -1,323 +0,0 @@
"""
GDDatabase class
"""
class_name GDDatabase
extends Object
# database types
enum {
e_db_type_json = 0, # JSON database
e_db_type_binary = 1 # binary database - to be designed / implemented
}
# database type
var m_db_type : int = e_db_type_json
# the id of the database
var m_db_id : int = gddb_constants.c_invalid_id
# the name of the database
var m_db_name : String = ""
# tables in the database
var m_tables : Array = []
# the path of the database
var m_db_filepath : String = ""
# if the database is not saved, it is dirty
var m_is_dirty : bool = false
# sets the id of the database
func set_db_id(db_id : int) -> void :
m_db_id = db_id
# returns the database id
func get_db_id() -> int :
return m_db_id
# set the name of the database
# the name of the database should not contain special characters
func set_db_name(db_name : String) -> bool :
if(!gddb_globals.check_db_name(db_name)):
print("ERROR: GDDatabase::set_db_name(" + db_name + ") - the name of the database contains invalid characters")
return false
# print("GDDatabase::set_db_name(" + db_name + ")")
m_db_name = db_name
return true
# returns the name of the database
func get_db_name() -> String :
return m_db_name
# sets the database file path
func set_db_filepath(filepath : String) -> void :
m_db_filepath = filepath
# returns the path of the database
func get_db_filepath() -> String :
return m_db_filepath
# checks if a table with the name "table_name" can be added into database
func can_add_table(table_name : String, table_id : int = -1) -> bool :
# print("GDDatabase::can_add_table(" + table_name + ", " + str(table_id) + ")")
for idx in range(0, m_tables.size()):
if(m_tables[idx].get_table_name() == table_name):
if(m_tables[idx].get_table_id() == table_id):
continue
print("WARNING: GDDatabase::can_add_table(" + table_name + ", " + str(table_id) + ") - table already exists")
return false
return true
# adds a new table
# returns the table id; if already exists, it will fire an warning on output console and returns an invalid id
func add_table(table_name : String) -> int :
if(!can_add_table(table_name)):
print("WARNING: GDDatabase::add_table(" + table_name + ") - cannot add table")
return gddb_constants.c_invalid_id
# print("GDDatabase::add_table(" + table_name + ") to \"" + m_db_name + "\" database")
var table_id = generate_new_table_id()
var table = load(gddb_constants.c_addon_main_path + "core/db_table.gd").new()
table.set_table_id(table_id)
table.set_table_name(table_name)
table.set_parent_database(self)
m_tables.push_back(table)
return table_id
# edits a table name
func edit_table_name(table_name : String, table_id : int) -> bool :
if(!can_add_table(table_name, table_id)):
return false
for idx in range(0, m_tables.size()):
if(m_tables[idx].get_table_id() == table_id):
m_tables[idx].set_table_name(table_name)
break
return true
# deletes a table at index
func delete_table_at(idx : int) -> void :
if(idx < 0 || idx > m_tables.size() - 1):
print("GDDatabase::delete_table_at(" + str(idx) + ") - index out of bounds")
return
m_tables[idx].clear()
m_tables[idx].free()
m_tables.remove(idx)
# deletes a table by id
func delete_table_by_id(table_id: int) -> void :
for idx in range(0, m_tables.size()):
if(m_tables[idx].get_table_id() == table_id):
# print("GDDatabase::delete_table_by_id(" + str(table_id) + ")")
m_tables[idx].clear()
m_tables[idx].free()
m_tables.remove(idx)
return
print("ERROR: GDDatabase::delete_table_by_id(" + str(table_id) + ") - cannot erase table; id not found")
# deletes a table by name
func delete_table_by_name(table_name: String) -> void :
for idx in range(0, m_tables.size()):
if(m_tables[idx].get_table_name() == table_name):
# print("GDDatabase::delete_table_by_name(" + table_name + ")")
m_tables[idx].clear()
m_tables[idx].free()
m_tables.remove(idx)
return
print("ERROR: GDDatabase::delete_table_by_name(" + table_name + ") - cannot erase table; name not found")
# generates a new table id
func generate_new_table_id() -> int :
if(m_tables.size() == 0):
return 0
return m_tables[m_tables.size()-1].get_table_id() + 1
# returns the count of the tables in the database
func get_tables_count() -> int :
return m_tables.size()
# returns true if the table exists in the database, false otherwise
# this is equivalent with (get_table_by_name(table name) != null) function, but without firing the error in case the table doesn't exist
func is_table_exists(table_name : String) -> bool :
for idx in range(0, m_tables.size()):
if(m_tables[idx].get_table_name() == table_name):
return true
return false
# returns a table by an index or null if the index is invalid
func get_table_at(idx: int) -> Object :
if(idx < 0 || idx >= m_tables.size()):
print("ERROR: GDDatabase::get_table_at(" + str(idx) + ") - cannot obtain table with index")
return null
return m_tables[idx]
# returns a table by its id or null if a table with id doesn's exist
func get_table_by_id(table_id: int) -> Object :
for idx in range(0, m_tables.size()):
if(m_tables[idx].get_table_id() == table_id):
return m_tables[idx]
print("ERROR: GDDatabase::get_table_by_id(" + str(table_id) + ") - cannot obtain table with id")
return null
# returns a table by its name or null if the name of the table doesn's exist
func get_table_by_name(table_name: String) -> Object :
for idx in range(0, m_tables.size()):
if(m_tables[idx].get_table_name() == table_name):
return m_tables[idx]
print("ERROR: GDDatabase::get_table_by_id(" + table_name + ") - cannot obtain table with name")
return null
# deletes all the tables
func clear() -> void :
# print("GDDatabase::clear()")
m_db_name = ""
for idx in range(0, m_tables.size()):
m_tables[idx].clear()
m_tables.clear()
# sets the database dirty; it is not saved
func set_dirty(dirty : bool) -> void :
m_is_dirty = dirty
# returns true if a database is dirty (should be saved), false otherwise
func is_dirty() -> bool :
return m_is_dirty
# serialization
func save_db() -> void :
if(m_db_name.empty()):
print("ERROR: GDDatabase::save_db() - current database doesn't have a name")
return
if(m_db_filepath.empty()):
print("ERROR: GDDatabase::save_db() - current database doesn't have a path file")
return
# print("GDDatabase::save_db() - " + m_db_name + " to: " + m_db_filepath)
var text = "{"
text += "\n\t\"" + gddb_constants.c_gddb_signature + "\":\"" + gddb_constants.c_gddb_ver + "\","
text += "\n\t\"db_name\":\"" + m_db_name + "\","
text += "\n\t\"tables\":["
for idx in range(0, m_tables.size()):
text += "\n\t\t{"
text += "\n\t\t\t\"table_name\":\"" + m_tables[idx].get_table_name() + "\","
text += "\n\t\t\t\"props\":["
for jdx in range(0, m_tables[idx].get_props_count()):
var db_prop = m_tables[idx].get_prop_at(jdx)
text += "\n\t\t\t\t\t{"
text += "\"name\":\"" + str(db_prop.get_prop_name()) + "\","
var prop_type = db_prop.get_prop_type()
if(prop_type < gddb_types.e_prop_types_count):
text += "\"type\":\"" + str(prop_type) + "\","
else:
# print("GDDatabase::save_db() - prop_type: " + str(prop_type))
var table_id = prop_type - gddb_types.e_prop_types_count
var table = get_table_by_id(table_id)
if(null == table):
print("GDDatabase::save_db() - table not found with id: " + str(table_id))
text += "\"type\":\"" + "table" + "\","
text += "\"table_name\":\"" + table.get_table_name() + "\","
text += "\"auto_increment\":\"" + str(int(db_prop.has_autoincrement())) + "\""
text += "}"
if(jdx < m_tables[idx].get_props_count() - 1):
text += ","
text += "\n\t\t\t],"
text += "\n\t\t\t\"data\":["
for jdx in range(0, m_tables[idx].get_data_size()):
#var the_data = m_tables[idx].get_data_at(jdx)
#print("getting data at " + str(jdx) + " : " + the_data)
text += "\"" + m_tables[idx].get_data_at(jdx) + "\""
if(jdx < m_tables[idx].get_data_size() - 1):
text += ","
text += "]" # end of data
text += "\n\t\t}" # end of table
if(idx < m_tables.size() - 1):
text += ","
text += "\n\t]\n}"
var save_file = File.new()
save_file.open(m_db_filepath, File.WRITE)
save_file.store_string(text)
save_file.close()
set_dirty(false)
# deserialization
func load_db() -> int :
var file = File.new()
file.open(get_db_filepath(), File.READ)
var content = file.get_as_text()
file.close()
var dictionary = JSON.parse(content).result
# check the signature
if(!dictionary.has(gddb_constants.c_gddb_signature)):
print("GDDatabase::load_db() - invalid database file")
return gddb_types.e_db_invalid_file
var gddb_signature = dictionary[gddb_constants.c_gddb_signature]
if(gddb_signature != gddb_constants.c_gddb_ver):
print("GDDatabase::load_db() - invalid database version")
return gddb_types.e_db_invalid_ver
clear()
m_db_name = dictionary["db_name"]
var tables = dictionary["tables"]
for idx in range(0, tables.size()):
var table_id = add_table(tables[idx]["table_name"])
var table = get_table_by_id(table_id)
var props_count = tables[idx]["props"].size()
if(props_count == 0):
continue
for jdx in range(0, props_count):
var prop_type = tables[idx]["props"][jdx]["type"]
var prop_id = -1
if(prop_type == "table"):
var table_name = tables[idx]["props"][jdx]["table_name"]
prop_id = table.add_table_prop(tables[idx]["props"][jdx]["name"], table_name)
else:
prop_id = table.add_prop(prop_type.to_int(), tables[idx]["props"][jdx]["name"])
var prop = table.get_prop_by_id(prop_id)
var enable_autoincrement = tables[idx]["props"][jdx]["auto_increment"].to_int()
prop.enable_autoincrement(bool(enable_autoincrement))
var data_count = tables[idx]["data"].size()
#print("********* set data to db - begin")
for jdx in range(0, data_count / props_count):
var row_data = []
for kdx in range(0, props_count):
var cell_data = tables[idx]["data"][jdx * props_count + kdx]
# print("cell_data: " + cell_data)
row_data.push_back(cell_data)
#print("row_data: " + str(row_data))
table.add_row(row_data)
#print("********* set data to db - end")
# link custom data to tables
for idx in range(0, m_tables.size()):
m_tables[idx].link_tables_props()
return gddb_types.e_db_valid
# dumps the database
func dump() -> String :
var dump_text = "\nDatabase dump. id: " + str(m_db_id) + ", name: " + m_db_name + ", filepath: " + m_db_filepath
dump_text += "\n------------------------------------------------------------------------------------\n"
for idx in range(0, m_tables.size()):
dump_text += "\n" + m_tables[idx].dump()
return dump_text
-40
View File
@@ -1,40 +0,0 @@
"""
GDDBData class
"""
class_name GDDBData
extends Object
var m_prop_id : int = -1
var m_row_idx : int = -1
var m_data : String = ""
# sets the property id
func set_prop_id(prop_id : int) -> void :
m_prop_id = prop_id
# returns the property id
func get_prop_id() -> int :
return m_prop_id
# sets the row index
func set_row_idx(row_idx : int) -> void :
m_row_idx = row_idx
# returns the row index
func get_row_idx() -> int :
return m_row_idx
# sets the data
func set_data(data : String) -> void :
m_data = data
# returns the data
func get_data() -> String :
return m_data
# dumps the data
func dump() -> String :
var dump_text = "prop_id: " + str(m_prop_id) + ", row_idx: " + str(m_row_idx) + ", data: " + m_data
return dump_text
-141
View File
@@ -1,141 +0,0 @@
"""
GDDBMan class
"""
class_name GDDBMan
extends Object
var m_databases = []
# adds a database
func add_database(db_name : String) -> int :
if(!can_add_db(db_name)):
print("ERROR: GDDBMan::add_database(" + db_name + ") already exists")
return gddb_constants.c_invalid_id
# print("GDDBMan::add_database(" + db_name + ")")
var db_id = generate_new_db_id()
var db = load(gddb_constants.c_addon_main_path + "core/database.gd").new()
db.set_db_id(db_id)
db.set_db_name(db_name)
m_databases.push_back(db)
return db_id
# loads a database from a file
func load_database(filepath : String) -> int :
var db_id = generate_new_db_id()
var db = load(gddb_constants.c_addon_main_path + "core/database.gd").new()
db.set_db_id(db_id)
db.set_db_filepath(filepath)
if(db.load_db() == gddb_types.e_db_invalid_file):
db.free()
return gddb_types.e_db_invalid_file
elif(db.load_db() == gddb_types.e_db_invalid_ver):
db.free()
return gddb_types.e_db_invalid_ver
m_databases.push_back(db)
return db_id
# erases a database at index
# it does not erase the database file
func erase_db_at(idx : int) -> void :
if(idx < 0 || idx > m_databases.size() - 1):
print("ERROR: GDDBMan::erase_db_at(" + str(idx) + ") - index out of bounds")
m_databases[idx].clear()
m_databases[idx].free()
m_databases.remove(idx)
# erases a database by id
# it does not erase the database file
func erase_db_by_id(db_id : int) -> void :
var db_found = false
for idx in range(0, m_databases.size()):
if(m_databases[idx].get_db_id() == db_id):
m_databases[idx].clear()
m_databases[idx].free()
m_databases.remove(idx)
db_found = true
break
if(!db_found):
print("ERROR: GDDBMan::erase_db_by_id(" + str(db_id) + ") - database not found")
# erases a database by name
# it does not erase the database file
func erase_db_by_name(db_name : String) -> void :
var db_found = false
for idx in range(0, m_databases.size()):
if(m_databases[idx].get_db_name() == db_name):
m_databases[idx].clear()
m_databases[idx].free()
m_databases.remove(idx)
db_found = true
break
if(!db_found):
print("ERROR: GDDBMan::erase_db_by_id(" + db_name + ") - database not found")
# returns the databases count
func get_databases_count() -> int :
return m_databases.size()
# returns a database at index
func get_db_at(idx : int) -> Object :
if(idx < 0 || idx >= m_databases.size()):
print("ERROR: GDDBMan::get_db_at(" + str(idx) + ") - invalid index")
return null
return m_databases[idx]
# returns a database by an id
func get_db_by_id(db_id : int) -> Object :
for idx in range(0, m_databases.size()):
if(m_databases[idx].get_db_id() == db_id):
return m_databases[idx]
print("ERROR: GDDBMan::get_db_by_id(" + str(db_id) + ") - invalid id")
return null
# returns a database by a name
func get_db_by_name(db_name : String) -> Object :
for idx in range(0, m_databases.size()):
if(m_databases[idx].get_db_name() == db_name):
return m_databases[idx]
return null
# generates a new table id
func generate_new_db_id() -> int :
if(m_databases.size() == 0):
return 0
return m_databases[m_databases.size()-1].get_db_id() + 1
# checks if a database already exists
func can_add_db(db_name : String) -> bool :
for idx in range(0, m_databases.size()):
if(m_databases[idx].get_db_name() == db_name):
print("ERROR: Database with name \"" + db_name + "\" already exists")
return false
return true
# deletes all databases
func clear() -> void :
for idx in range(0, m_databases.size()):
m_databases[idx].clear()
m_databases[idx].free()
m_databases.clear()
# dumps all databases
func dump(to_console : bool = false) -> String :
var dump_text = "\nDatabase manager - dump"
dump_text += "\n===================================================================================="
for idx in range(0, m_databases.size()):
dump_text += m_databases[idx].dump()
dump_text += "===================================================================================="
if(to_console):
print(dump_text)
return dump_text
-71
View File
@@ -1,71 +0,0 @@
"""
GDDBProperty class
"""
class_name GDDBProperty
extends Object
var m_prop_id : int = -1
var m_prop_type : int = gddb_types.e_prop_type_int
var m_custom_type : String = ""
var m_prop_name : String = ""
var m_autoincrement : bool = false
# sets the property id
func set_prop_id(prop_id : int) -> void :
m_prop_id = prop_id
# returns the property id
func get_prop_id() -> int :
return m_prop_id
# sets the property type
func set_prop_type(prop_type : int) -> void :
m_prop_type = prop_type
# returns the property type
func get_prop_type() -> int :
return m_prop_type
# sets the custom type
func set_prop_custom_type(prop_type : String) -> void :
m_custom_type = prop_type
# returns the custom type
func get_prop_custom_type() -> String :
return m_custom_type
# sets the property name
func set_prop_name(prop_name : String) -> void :
m_prop_name = prop_name
# returns the property name
func get_prop_name() -> String :
return m_prop_name
# enables or disables the auto increment property
func enable_autoincrement(enable : bool) -> void :
if(enable && m_prop_type != gddb_types.e_prop_type_int):
if(m_prop_type < gddb_types.e_prop_types_count):
print("ERROR: autoincrement option can be set to integer data type only. Type is: " + gddb_types.get_data_name(m_prop_type))
else:
print("ERROR: autoincrement option can be set to integer data type only. Custom type is: " + m_custom_type)
return
m_autoincrement = enable
# returns if the property has auto increment
func has_autoincrement() -> bool :
return m_autoincrement
# dumps the property
func dump() -> String :
var dump_text = "prop_id: " + str(m_prop_id) + ", prop_name: " + m_prop_name
if(m_prop_type <= gddb_types.e_prop_type_resource):
dump_text += ", prop_type: " + gddb_globals.get_data_name(m_prop_type)
else:
dump_text += ", custom_prop_type: " + m_custom_type
return dump_text
-574
View File
@@ -1,574 +0,0 @@
"""
GDDBTable class
"""
class_name GDDBTable
extends Object
var m_table_id : int = gddb_constants.c_invalid_id
var m_table_name : String = ""
var m_props : Array = []
var m_data : Array = []
var m_rows_count : int = 0
var m_parent_database : Object = null
# sets the table id
func set_table_id(table_id : int) -> void :
# print("GDDBDTable::set_table_id(" + str(table_id) + ")")
m_table_id = table_id
# returns the table id
func get_table_id() -> int :
return m_table_id
# sets the table name
func set_table_name(table_name: String) -> void :
# print("GDDBDTable::set_table_name(" + table_name + ")")
m_table_name = table_name
# returns the table name
func get_table_name() -> String :
return m_table_name
# sets the parent database
func set_parent_database(db : Object) -> void :
# print("GDDBTable::set_parent_database(" + str(db) + ")")
m_parent_database = db
# returns parent database
func get_parent_database() -> Object :
return m_parent_database
# adds a property in the table structure as a base type
# returns prop ID
func add_prop(prop_type : int, prop_name : String) -> int :
var prop_id = generate_new_prop_id()
# print("GDDBDTable::add_prop(" + str(prop_id) + ", " + str(prop_type) + ", " + prop_name + ")")
var prop = load(gddb_constants.c_addon_main_path + "core/db_prop.gd").new()
prop.set_prop_id(prop_id)
prop.set_prop_type(prop_type)
prop.set_prop_name(prop_name)
m_props.push_back(prop)
# adding blank data to all existing rows
# TODO: find a way to make this better; this is ugly
if(m_data.size() > 0):
var new_data_array = []
var data_idx = 0
var row_idx = 0
while(true):
var data = m_data[data_idx]
row_idx = data.get_row_idx()
if(data.get_prop_id() + 1 == prop_id):
new_data_array.push_back(data)
var new_data = load(gddb_constants.c_addon_main_path + "core/db_data.gd").new()
new_data.set_prop_id(prop_id)
new_data.set_row_idx(row_idx)
if(prop_type == gddb_types.e_prop_type_bool):
new_data.set_data("0")
elif(prop_type == gddb_types.e_prop_type_int):
if(prop.has_autoincrement()):
new_data.set_data(str(m_rows_count+1))
else:
new_data.set_data("0")
elif(prop_type == gddb_types.e_prop_type_float):
new_data.set_data("0.0")
elif(prop_type == gddb_types.e_prop_type_string):
new_data.set_data("")
elif(prop_type == gddb_types.e_prop_type_resource):
new_data.set_data("res://")
elif(prop_type >= gddb_types.e_prop_types_count):
new_data.set_data(str(-1))
new_data_array.push_back(new_data)
else:
new_data_array.push_back(data)
data_idx += 1
if(data_idx >= m_data.size()):
break
m_data.clear()
for idx in range(0, new_data_array.size()):
m_data.push_back(new_data_array[idx])
return prop_id
# adds a property in the table structure as a table type
# returns prop ID
func add_table_prop(prop_name : String, table_name : String) -> int :
# print("GDDBTable::add_table_prop(" + prop_name + ", " + table_name + ")")
var prop_id = generate_new_prop_id()
# print("GDDBDTable::add_prop(" + str(prop_id) + ", " + str(prop_type) + ", " + prop_name + ")")
var prop = load(gddb_constants.c_addon_main_path + "core/db_prop.gd").new()
prop.set_prop_id(prop_id)
prop.set_prop_name(prop_name)
prop.set_prop_custom_type(table_name)
m_props.push_back(prop)
return prop_id
# links custom properties from tables
func link_tables_props() -> void :
for idx in range(0, m_props.size()):
var custom_prop_type = m_props[idx].get_prop_custom_type()
if(!custom_prop_type.empty()):
var table = m_parent_database.get_table_by_name(custom_prop_type)
m_props[idx].set_prop_type(gddb_types.e_prop_types_count + table.get_table_id())
m_props[idx].set_prop_custom_type("")
# edits a property in the table structure
func edit_prop(prop_id : int, prop_type : int, prop_name: String) -> void :
for idx in range(0, m_props.size()):
if(m_props[idx].get_prop_id() == prop_id):
m_props[idx].set_prop_type(prop_type)
m_props[idx].set_prop_name(prop_name)
return
print("ERROR: GDDBDTable::edit_prop(" + str(prop_id) + ", " + str(prop_type) + ", " + prop_name + ") - property not found")
# enables or disables autoincrement on a property
func enable_prop_autoincrement(prop_id : int, enable : bool) -> void :
for idx in range(0, m_props.size()):
if(m_props[idx].get_prop_id() == prop_id):
m_props[idx].enable_autoincrement(enable)
break
# deletes a property and all the data from the table have the same property
func delete_prop(prop_id : int) -> void :
# print("db_table::delete_prop(" + str(prop_id) + ")")
var prop_found = false
for idx in range(0, m_props.size()):
if(m_props[idx].get_prop_id() == prop_id):
# print("Removing prop with id " + str(prop_id))
m_props[idx].free()
m_props.remove(idx)
prop_found = true
break
if(!prop_found):
print("ERROR: GDDBDTable::delete_prop( " + str(prop_id) + " ) - property not found !")
return
# remove the data
# this is very ugly, but I can't erase a subarray from an array in GDscript :(
# backup what needs to be saved only
var tmp_data = []
for idx in range(0, m_data.size()):
if(m_data[idx].get_prop_id() == prop_id):
continue
tmp_data.push_back(m_data[idx])
# clear and restore data
m_data.clear()
for idx in range(0, tmp_data.size()):
m_data.push_back(tmp_data[idx])
# generates a new table id
func generate_new_prop_id() -> int :
if(m_props.size() == 0):
return 0
return m_props[m_props.size()-1].get_prop_id() + 1
# returns the properties count
func get_props_count() -> int :
return m_props.size()
# returns the property at index or null if the index is out of bounds
func get_prop_at(idx : int) -> Object :
if(idx < 0 || idx >= m_props.size()):
print("ERROR: GDDBDTable::get_prop_id( " + str(idx) + " ) - index out of bounds; max properties: " + str(m_props.size()))
return null
return m_props[idx]
# returns a property by id or null if the id is not found
func get_prop_by_id(prop_id : int) -> Object :
for idx in range(0, m_props.size()):
if(m_props[idx].get_prop_id() == prop_id):
return m_props[idx]
print("ERROR: GDDBDTable::get_prop_by_id(" + str(prop_id) + ") - property with id not found")
return null
# returns a property by name
func get_prop_by_name(pror_name : String) -> Object :
for idx in range(0, m_props.size()):
if(m_props[idx].get_prop_name() == pror_name):
return m_props[idx]
print("ERROR: GDDBDTable::get_prop_by_name(" + str(pror_name) + ") - property with name not found")
return null
# adds a row with blank data
func add_blank_row() -> void :
# print("GDDBTable::add_blank_row()")
var prop_type = gddb_types.e_prop_type_bool
for idx in range(0, m_props.size()):
var data = load(gddb_constants.c_addon_main_path + "core/db_data.gd").new()
data.set_prop_id(m_props[idx].get_prop_id())
data.set_row_idx(m_rows_count)
prop_type = m_props[idx].get_prop_type()
if(prop_type == gddb_types.e_prop_type_bool):
data.set_data("0")
elif(prop_type == gddb_types.e_prop_type_int):
if(m_props[idx].has_autoincrement()):
data.set_data(str(m_rows_count+1))
else:
data.set_data("0")
elif(prop_type == gddb_types.e_prop_type_float):
data.set_data("0.0")
elif(prop_type == gddb_types.e_prop_type_string):
data.set_data("")
elif(prop_type == gddb_types.e_prop_type_resource):
data.set_data("res://")
elif(prop_type >= gddb_types.e_prop_types_count):
data.set_data(str(-1))
m_data.push_back(data)
m_rows_count += 1
# adds a row with data
func add_row(data_array : Array) -> void :
if(data_array.size() != m_props.size()):
print("ERROR: GDDBDTable::add_row( " + str(data_array) + " ) - cannot add row; properties count = " + str(m_props.size()) + " and data size = " + str(data_array.size()))
return
var prop_type = gddb_types.e_prop_type_bool
var the_data = ""
for idx in range(0, m_props.size()):
var data = load(gddb_constants.c_addon_main_path + "core/db_data.gd").new()
# print("adding data: [" + str(m_props[idx].get_prop_id()) + ", " + data_array[idx] + "]")
# print("setting prop id: " + str(m_props[idx].get_prop_id()))
data.set_prop_id(m_props[idx].get_prop_id())
data.set_row_idx(m_rows_count)
# ignore data if the property has autoincrement option
if(m_props[idx].has_autoincrement()):
data.set_data(str(m_rows_count+1))
m_data.push_back(data)
continue
prop_type = m_props[idx].get_prop_type()
the_data = data_array[idx]
if(prop_type == gddb_types.e_prop_type_bool):
data.set_data(str(the_data))
elif(prop_type == gddb_types.e_prop_type_int):
data.set_data(str(the_data))
elif(prop_type == gddb_types.e_prop_type_float):
data.set_data(str(the_data))
elif(prop_type == gddb_types.e_prop_type_string):
data.set_data(gddb_globals.handle_string(the_data))
elif(prop_type == gddb_types.e_prop_type_resource):
data.set_data(the_data)
else:
print("ERROR: data type doesn't exist - " + str(m_props[idx].get_prop_type()))
m_data.push_back(data)
m_rows_count += 1
# removes a row
func remove_row(row_idx : int) -> void :
for idx in range(m_data.size()-1, 0, -1):
if(m_data[idx].get_row_idx() == row_idx):
m_data[idx].remove(idx)
m_rows_count -= 1
# returns the rows count
func get_rows_count() -> int :
return m_rows_count
# edits the data
func edit_data(prop_id : int, row_idx : int, data : String) -> void :
# print("#1: GDDBTable::edit_data( " + str(prop_id) + ", " + str(row_idx) + ", " + data + " )")
for idx in range(0, m_data.size()):
# print("checking ( " + str(m_data[idx].get_row_idx()) + ", " + str(m_data[idx].get_prop_id()) + " )")
if(m_data[idx].get_row_idx() == row_idx && m_data[idx].get_prop_id() == prop_id):
# print("#2: GDDBTable::edit_data( " + str(prop_id) + ", " + str(row_idx) + ", " + data + " )")
m_data[idx].set_data(data)
return
print("ERROR: GDDBDTable::edit_data(" + str(prop_id) + ", " + str(row_idx) + ", " + data + ") - can't find data to edit")
# edits the data
func edit_data_by_prop_name(prop_name : String, row_idx : int, data : String) -> void :
# print("#1: GDDBTable::edit_data( " + str(prop_id) + ", " + str(row_idx) + ", " + data + " )")
var prop_id = get_prop_by_name(prop_name).get_prop_id()
edit_data(prop_id, row_idx, data)
# returns data count
func get_data_size() -> int :
return m_data.size()
# returns all data
func get_all_data() -> Array :
return m_data
# returns the data at index
func get_data_at(idx : int) -> String :
if(idx < 0 || idx >= m_data.size()):
print("ERROR: GDDBDTable::get_data_at( " + str(idx) + ") - max data size: " + str(m_data.size()))
return ""
return m_data[idx].get_data()
# returns a dictionary containing the data at index
func get_dictionary_at(idx : int) -> Dictionary :
var dict = {}
if(idx < 0 || idx >= m_data.size()):
print("ERROR: GDDBDTable::get_data_at( " + str(idx) + ") - max data size: " + str(m_data.size()))
return dict
var prop_idx = idx % m_props.size()
var data_prop_name = m_props[prop_idx].get_prop_name()
dict[data_prop_name] = m_data[idx].get_data()
return dict
# returns the data by a property id and a row index
func get_data(prop_id : int, row_idx : int) -> String :
for idx in range(m_data.size()-1, 0, -1):
if(m_data[idx].get_row_idx() == row_idx && m_data[idx].get_prop_id() == prop_id):
return m_data[idx].get_data()
print("ERROR: GDDBDTable::get_data(" + str(prop_id) + ", " + str(row_idx) + ")")
return ""
# returns a dictionary containing the data by a property id and a row index
func get_dictionary(prop_id : int, row_idx : int) -> Dictionary :
var dict = {}
for idx in range(m_data.size()-1, 0, -1):
if(m_data[idx].get_row_idx() == row_idx && m_data[idx].get_prop_id() == prop_id):
var prop = get_prop_by_id(prop_id)
var data_prop_name = prop.get_prop_name()
dict[data_prop_name] = m_data[idx].get_data()
return dict
print("ERROR: GDDBDTable::get_data(" + str(prop_id) + ", " + str(row_idx) + ")")
return dict
# returns an array of data at row index
func get_data_at_row_idx(row_idx : int) -> Array :
var data = []
for idx in range(0, m_data.size()):
if(m_data[idx].get_row_idx() == row_idx):
data.push_back(m_data[idx])
if(data.size() == -1):
print("ERROR: GDDBDTable::get_data_at_row_idx(" + str(row_idx) + ") - invalid row index")
return data
# returns a dictionary of data at row index
func get_dictionary_at_row_idx(row_idx : int) -> Dictionary :
var dict = {}
var prop_idx = 0
for idx in range(0, m_data.size()):
if(m_data[idx].get_row_idx() == row_idx):
var data_prop_name = m_props[prop_idx].get_prop_name()
dict[data_prop_name] = m_data[idx].get_data()
prop_idx += 1
if(dict.empty()):
print("ERROR: GDDBDTable::get_data_at_row_idx(" + str(row_idx) + ") - invalid row index")
return dict
# returns an array of data filtered by property id
func get_data_by_prop_id(prop_id : int, data_filter : int = gddb_types.e_data_filter_equal) -> Array :
var data = []
if(data_filter < gddb_types.e_data_filter_equal || data_filter >= gddb_types.e_data_filter_gequal):
print("ERROR: cannot process filter " + str(data_filter))
return data
for idx in range(0, m_data.size()):
if(data_filter == gddb_types.e_data_filter_equal):
if(m_data[idx].get_prop_id() == prop_id):
data.push_back(m_data[idx])
elif(data_filter == gddb_types.e_data_filter_not_equal):
if(m_data[idx].get_prop_id() != prop_id):
data.push_back(m_data[idx])
elif(data_filter == gddb_types.e_data_filter_less):
if(m_data[idx].get_prop_id() < prop_id):
data.push_back(m_data[idx])
elif(data_filter == gddb_types.e_data_filter_greater):
if(m_data[idx].get_prop_id() > prop_id):
data.push_back(m_data[idx])
elif(data_filter == gddb_types.e_data_filter_lequal):
if(m_data[idx].get_prop_id() <= prop_id):
data.push_back(m_data[idx])
elif(data_filter == gddb_types.e_data_filter_gequal):
if(m_data[idx].get_prop_id() >= prop_id):
data.push_back(m_data[idx])
if(data.size() == 0):
print("ERROR: GDDBDTable::get_data_by_prop_id(" + str(prop_id) + ", " + gddb_globals.get_data_filter_name(data_filter) + ") - filtered data not found")
return data
# returns an array of data by property name
func get_data_by_prop_name(prop_name : String) -> Array :
var prop_id = -1
for idx in range(0, m_props.size()):
if(m_props[idx].get_prop_name() == prop_name):
prop_id = m_props[idx].get_prop_id()
break
if(prop_id == -1):
print("ERROR: GDDBDTable::get_data_by_prop_name(" + prop_name + ") - property not found")
return []
return get_data_by_prop_id(prop_id)
# returns an array of data filtered by data
# filters "<", ">", "<=" and ">=" are working for integer and float data types
func get_data_by_data(data_value : String, data_filter : int = gddb_types.e_data_filter_equal) -> Array :
var data = []
if(data_filter < gddb_types.e_data_filter_equal || data_filter >= gddb_types.e_data_filter_gequal):
print("ERROR: cannot process filter " + str(data_filter))
return data
for idx in range(0, m_data.size()):
if(data_filter == gddb_types.e_data_filter_equal):
if(m_data[idx].get_data() == data_value):
data.push_back(m_data[idx])
elif(data_filter == gddb_types.e_data_filter_not_equal):
if(m_data[idx].get_data() != data_value):
data.push_back(m_data[idx])
elif(data_filter == gddb_types.e_data_filter_less):
if(m_props[idx].get_prop_type() < gddb_types.e_prop_type_resource):
if(m_data[idx].get_data() < data_value):
data.push_back(m_data[idx])
elif(data_filter == gddb_types.e_data_filter_greater):
if(m_props[idx].get_prop_type() < gddb_types.e_prop_type_resource):
if(m_data[idx].get_data() > data_value):
data.push_back(m_data[idx])
elif(data_filter == gddb_types.e_data_filter_lequal):
if(m_props[idx].get_prop_type() < gddb_types.e_prop_type_resource):
if(m_data[idx].get_data() <= data_value):
data.push_back(m_data[idx])
elif(data_filter == gddb_types.e_data_filter_gequal):
if(m_props[idx].get_prop_type() < gddb_types.e_prop_type_resource):
if(m_data[idx].get_data() >= data_value):
data.push_back(m_data[idx])
if(data.size() == 0):
print("ERROR: GDDBDTable::get_data_by_data(" + data_value + ", " + gddb_globals.get_data_filter_name(data_filter) + ") - filtered data not found")
return data
# returns an array of data by a property name and a data value
# similar to: select * from users where user_id = 1
func get_data_by_prop_name_and_data(prop_name : String, data_value : String) -> Array :
var the_array = []
var prop_idx = -1
for idx in range(0, m_props.size()):
if(m_props[idx].get_prop_name() == prop_name):
prop_idx = idx
break
for idx in range(0, m_rows_count):
var row_data = get_data_at_row_idx(idx)
# print("Comparing row: " + row_data[0].get_data() + ", " + row_data[1].get_data() + ", " + row_data[2].get_data() + ", " + row_data[3].get_data() + ", " + row_data[4].get_data())
if(row_data[prop_idx].get_data() == data_value):
var dict = get_dictionary_at_row_idx(idx)
the_array.push_back(row_data)
return the_array
# returns a dictionary of data by a property name and a data value
# similar to: select * from users where user_id = 1
func get_dictionary_by_prop_name_and_data(prop_name : String, data_value : String) -> Array :
var the_array = []
var prop_idx = -1
for idx in range(0, m_props.size()):
if(m_props[idx].get_prop_name() == prop_name):
prop_idx = idx
break
for idx in range(0, m_rows_count):
var row_data = get_data_at_row_idx(idx)
# print("Comparing row: " + row_data[0].get_data() + ", " + row_data[1].get_data() + ", " + row_data[2].get_data() + ", " + row_data[3].get_data() + ", " + row_data[4].get_data())
if(row_data[prop_idx].get_data() == data_value):
var dict = get_dictionary_at_row_idx(idx)
the_array.push_back(get_dictionary_at_row_idx(idx))
return the_array
# clears the table's structure and data
func clear() -> void :
# clear data
clear_data()
# clear properties
for idx in range(0, m_props.size()):
m_props[idx].free()
m_props.clear()
# clears the table's data
func clear_data() -> void :
for idx in range(0, m_data.size()):
m_data[idx].free()
m_data.clear()
m_rows_count = 0
# dumps the table
func dump() -> String :
var dump_text = "Table dump. id: " + str(m_table_id) + ", name: " + m_table_name + ", props_count: " + str(m_props.size()) + ", rows_count: " + str(m_rows_count)
dump_text += "\n------------------------------------------------------------------------------------\nProperties:"
for idx in range(0, m_props.size()):
dump_text += "\n" + m_props[idx].dump()
dump_text += "\n------------------------------------------------------------------------------------\nData:\n"
for idx in range(0, m_rows_count):
var tmp_text = "row_idx: " + "%" + str(gddb_globals.get_digits_count(m_rows_count)) + "d"
dump_text += tmp_text % idx
var row = get_data_at_row_idx(idx)
for jdx in range(0, row.size()):
dump_text += " | " + row[jdx].get_data()
dump_text += "\n"
return dump_text
-59
View File
@@ -1,59 +0,0 @@
"""
class GDDBDataLabel
"""
class_name GDDBDataLabel
tool
extends Label
signal resize_property
var m_prop_id : int = gddb_constants.c_invalid_id
var m_prop_type : int = gddb_constants.c_invalid_id
var m_mouse_pos_pressed : Vector2 = Vector2()
var m_mouse_pressed : bool = false
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
set_custom_minimum_size(Vector2(150.0, 24.0))
# called when the node gets an input
func _input(event : InputEvent) -> void :
if(!gddb_globals.is_interface_active()):
return
var evLocal = $resize_ctrl.make_input_local(event)
if event is InputEventMouseButton :
if(event.button_index == BUTTON_LEFT):
if(event.pressed):
var rect = Rect2(Vector2(0, 0), $resize_ctrl.get_size())
var inside = rect.has_point(evLocal.position)
if(inside):
m_mouse_pressed = true
m_mouse_pos_pressed = evLocal.position
else:
m_mouse_pressed = false
elif event is InputEventMouseMotion :
if(m_mouse_pressed):
var diff_x = evLocal.position.x - m_mouse_pos_pressed.x
emit_signal("resize_property", m_prop_id, diff_x)
# sets property id
func set_prop_id(id : int) -> void:
m_prop_id = id
# returns property id
func get_prop_id() -> int:
return m_prop_id
# sets property type
func set_prop_type(prop_type : int) -> void :
m_prop_type = prop_type
# returns property type
func get_prop_type() -> int :
return m_prop_type
-44
View File
@@ -1,44 +0,0 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://addons/godot_db_manager/data_label.gd" type="Script" id=1]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=2]
[ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=3]
[ext_resource path="res://addons/godot_db_manager/assets/tex/debug.png" type="Texture" id=4]
[node name="lbl" type="Label"]
anchor_right = 0.167
margin_right = -0.300018
margin_bottom = 11.52
rect_min_size = Vector2( 150, 32 )
mouse_filter = 0
custom_fonts/font = ExtResource( 2 )
text = "ID"
valign = 1
script = ExtResource( 1 )
__meta__ = {
"_edit_horizontal_guides_": [ 24.0 ],
"_edit_use_anchors_": true
}
[node name="dbg" type="NinePatchRect" parent="."]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
texture = ExtResource( 4 )
region_rect = Rect2( 86, 26, 10, 10 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="resize_ctrl" type="NinePatchRect" parent="."]
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -3.0
mouse_filter = 0
mouse_default_cursor_shape = 10
texture = ExtResource( 3 )
region_rect = Rect2( 80, 12, 24, 24 )
__meta__ = {
"_edit_use_anchors_": false
}
-210
View File
@@ -1,210 +0,0 @@
"""
class GDDBEditor
"""
class_name GDDBEditor
tool
extends Tabs
var m_name = ""
var m_database = null
var m_filepath = ""
# Called when the node enters the scene tree for the first time.
func _ready() -> void :
set_tab_align(Tabs.ALIGN_LEFT)
set_tab_close_display_policy(Tabs.CLOSE_BUTTON_SHOW_ALWAYS)
$tables_list.connect("resize_tables_list", self, "on_resize_the_table_list")
$tables_list.connect("add_table", self, "on_add_table")
$tables_list.connect("edit_table_name", self, "on_edit_table")
$tables_list.connect("delete_table", self, "on_delete_table")
$tables_list.connect("select_table", self, "on_select_table")
$table_editor.connect("set_dirty", self, "on_set_dirty")
$delete_table_dlg.connect("delete_table", self, "on_confirm_delete_table")
$new_table_dlg.connect("cancel_dialog", self, "on_close_new_table_dlg")
$new_table_dlg.get_close_button().connect("pressed", self, "on_close_new_table_dlg")
$error_dlg.connect("confirmed", self, "on_retry_create_table")
# resizing the tables list
func on_resize_the_table_list(diff_x : float) -> void :
var size = $tables_list.get_size()
var min_size = $tables_list.get_custom_minimum_size()
size.x += diff_x
if(size.x < min_size.x):
return
if(size.x > gddb_constants.c_max_tables_list_width):
return
$tables_list.resize_content(size)
var pos = $table_editor.get_position()
size = $table_editor.get_size()
pos.x += diff_x
size.x -= diff_x
$table_editor.set_position(pos)
$table_editor.set_size(size)
# overrides the member from base class
func set_name(ctrl_name) -> void :
m_name = ctrl_name
.set_name(ctrl_name)
# sets the database; for easy access
func set_database(db) -> void :
# print("GDDBEditor::set_database(" + db.get_db_name() + ") to " + get_name())
m_database = db
set_dirty(true)
var tables_count = db.get_tables_count()
$table_editor.hide()
for idx in range(0, tables_count):
var table = db.get_table_at(idx)
$tables_list.create_table(table, idx == 0)
if(idx == 0):
$table_editor.set_table(table)
$table_editor.link_props()
$table_editor.show()
# returns the database id
func get_db_id() -> int :
if(null == m_database):
return gddb_constants.c_invalid_id
return m_database.get_db_id()
# returns the database name
func get_db_name() -> String :
if(null == m_database):
return ""
return m_database.get_db_name()
# sets the database to be dirty; should be saved
func set_dirty(dirty) -> void :
if(dirty):
var title = m_name + "*"
.set_name(title)
else:
.set_name(m_name)
# called when the user presses the "add_table" button from the "tables_list/tables_header"
func on_add_table() -> void :
# print("GDDBEditor::on_add_table()")
$new_table_dlg.set_dld_type(gddb_types.e_new_dlg_type_new)
$new_table_dlg.set_table_id(gddb_constants.c_invalid_id)
$new_table_dlg.set_init_name("")
$new_table_dlg.connect("create_new_table", self, "on_create_table")
$new_table_dlg.popup_centered()
# called when the user accepts the name of the table in the "new_table_dlg"
func on_create_table(table_name : String) -> void :
# print("GDDBEditor::on_create_table(" + table_name + ")")
$new_table_dlg.disconnect("create_new_table", self, "on_create_table")
var table_id = m_database.add_table(table_name)
if(table_id == gddb_constants.c_invalid_id):
$error_dlg.set_text("Table with the name \"" + table_name + "\" already exists" )
$error_dlg.popup_centered()
return
var table = m_database.get_table_by_id(table_id)
$tables_list.create_table(table)
$table_editor.set_table(table)
$table_editor.show()
m_database.set_dirty(true)
set_dirty(true)
# called when the user retryes to create a table (changed the name)
func on_retry_create_table() -> void :
$new_table_dlg.set_init_name("")
$new_table_dlg.popup_centered()
# called when the user presses the "edit_table_name" from the "tables/list/table"
func on_edit_table(table_id : int, table_name : String) -> void :
# print("GDDBEditor::on_edit_table(" + str(table_id) + ", " + table_name + ")")
$new_table_dlg.set_dld_type(gddb_types.e_new_dlg_type_edit)
$new_table_dlg.set_table_id(table_id)
$new_table_dlg.set_init_name(table_name)
$new_table_dlg.connect("create_new_table", self, "on_table_name_edited")
$new_table_dlg.popup_centered()
# gets called when canceling the new_table_dlg
func on_close_new_table_dlg() -> void :
# print("GDDBEditor::on_close_new_table_dlg()")
var dlg_type = $new_table_dlg.get_dlg_type()
if(dlg_type == gddb_types.e_new_dlg_type_new):
$new_table_dlg.disconnect("create_new_table", self, "on_create_table")
elif(dlg_type == gddb_types.e_new_dlg_type_edit):
$new_table_dlg.disconnect("create_new_table", self, "on_table_name_edited")
# called when the user presses the "delete_table" from the "tables/list/table"
func on_delete_table(table_id : int) -> void :
# print("GDDBEditor::on_delete_table(" + str(table_id) + ")")
var table = m_database.get_table_by_id(table_id)
$delete_table_dlg.set_table_id(table_id)
$delete_table_dlg.set_table_name(table.get_table_name())
$delete_table_dlg.popup_centered()
# called when the user accepts the name of the table in the "new_table_dlg"
func on_table_name_edited(table_name : String) -> void :
# print("GDDBEditor::on_table_name_edited(" + table_name + ")")
$new_table_dlg.disconnect("create_new_table", self, "on_table_name_edited")
var table_id = $new_table_dlg.get_table_id()
if(!m_database.edit_table_name(table_name, table_id)):
$error_dlg.set_text("Table with the name \"" + table_name + "\" already exists" )
$error_dlg.popup_centered()
return
# print("GDDBEditor::on_table_name_edited(" + str(table_id) + ", " + table_name + ")")
$tables_list.edit_table_name(table_id, table_name)
m_database.set_dirty(true)
set_dirty(true)
# called when the user confirms to delete a table
func on_confirm_delete_table() -> void :
# print("GDDBEditor::on_confirm_delete_table()")
var table_id = $delete_table_dlg.get_table_id()
var selected_table = $tables_list.get_selected_item()
if(null == selected_table):
return
var selected_table_id = selected_table.get_table_id()
m_database.delete_table_by_id(table_id)
$tables_list.delete_table(table_id)
if(selected_table_id == table_id):
$tables_list.select_item_at(0)
var table = m_database.get_table_at(0)
$table_editor.set_table(table)
m_database.set_dirty(true)
set_dirty(true)
# called when the user selects a table from the table_list
func on_select_table(table_id : int) -> void :
var table = m_database.get_table_by_id(table_id)
if(null != table):
$table_editor.set_table(table)
$table_editor.link_props()
# saves current database
func save_database() -> void:
m_database.save_db()
set_dirty(false)
# returns true if the database can be saved, otherwise false
func can_save_database() -> bool:
return !m_database.get_db_filepath().empty()
# sets the database's path
func set_database_filepath(filepath : String) -> void:
m_database.set_db_filepath(filepath)
# called when a table is modified
func on_set_dirty() -> void:
m_database.set_dirty(true)
set_dirty(true)
-40
View File
@@ -1,40 +0,0 @@
[gd_scene load_steps=8 format=2]
[ext_resource path="res://addons/godot_db_manager/db_editor.gd" type="Script" id=1]
[ext_resource path="res://addons/godot_db_manager/tables_list.tscn" type="PackedScene" id=2]
[ext_resource path="res://addons/godot_db_manager/dlgs/new_table_dlg.tscn" type="PackedScene" id=3]
[ext_resource path="res://addons/godot_db_manager/table_editor.tscn" type="PackedScene" id=4]
[ext_resource path="res://addons/godot_db_manager/dlgs/error_dlg.tscn" type="PackedScene" id=5]
[ext_resource path="res://addons/godot_db_manager/dlgs/delete_table_dlg.tscn" type="PackedScene" id=6]
[ext_resource path="res://addons/godot_db_manager/debug/dbg.tscn" type="PackedScene" id=7]
[node name="db_editor" type="Tabs"]
anchor_right = 1.0
anchor_bottom = 1.0
tab_align = 0
tab_close_display_policy = 2
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": true,
"_edit_vertical_guides_": [ 170.0, 900.0 ]
}
[node name="tables_list" parent="." instance=ExtResource( 2 )]
anchor_right = 0.0
margin_right = 170.0
rect_min_size = Vector2( 180, 30 )
[node name="table_editor" parent="." instance=ExtResource( 4 )]
margin_left = 181.0
[node name="dbg" parent="." instance=ExtResource( 7 )]
visible = false
[node name="new_table_dlg" parent="." instance=ExtResource( 3 )]
visible = false
[node name="delete_table_dlg" parent="." instance=ExtResource( 6 )]
visible = false
[node name="error_dlg" parent="." instance=ExtResource( 5 )]
visible = false
-155
View File
@@ -1,155 +0,0 @@
"""
class GDDBInterface
"""
class_name GDDBInterface
tool
extends Control
var m_db_manager = null
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
# init db_manager
m_db_manager = load(gddb_constants.c_addon_main_path + "core/db_man.gd").new()
# menu connections
$dlg/menu.connect("new_database", self, "on_menu_new_database")
$dlg/menu.connect("load_database", self, "on_menu_load_database")
$dlg/menu.connect("save_database", self, "on_menu_save_database")
$dlg/menu.connect("save_database_as", self, "on_menu_save_database_as")
# dialod notifications
$dlg.connect("about_to_show", self, "on_about_to_show")
$dlg.get_close_button().connect("pressed", self, "on_close")
# new database connections
$dlg/new_db_dlg.connect("create_new_db", self, "on_new_database")
# save / load connections
$dlg/load_db_dlg.connect("file_selected", self, "on_file_selected")
# Called when the node is about to be shown.
func on_about_to_show() -> void :
gddb_globals.set_interface_active(true)
func on_close() -> void :
gddb_globals.set_interface_active(false)
# called when creating a new database from the menu
func on_menu_new_database() -> void:
$dlg/new_db_dlg/v_layout/db_info/db_edt.set_text("")
$dlg/new_db_dlg.popup_centered()
# called when loading a database from the menu
func on_menu_load_database() -> void:
$dlg/load_db_dlg.set_mode(FileDialog.MODE_OPEN_FILE)
$dlg/load_db_dlg.set_title("Load Database ...")
$dlg/load_db_dlg.set_current_file("")
$dlg/load_db_dlg.popup_centered()
# called when saving a database from the menu
func on_menu_save_database() -> void:
# print("on_menu_save_database")
var currnet_tab = $dlg/databases.get_current_tab_control()
if(currnet_tab.can_save_database()):
currnet_tab.save_database()
else:
on_menu_save_database_as()
# called when saving a database as another from the menu
func on_menu_save_database_as():
# print("on_menu_save_database_as")
$dlg/load_db_dlg.set_mode(FileDialog.MODE_SAVE_FILE)
$dlg/load_db_dlg.set_title("Save Database As ...")
var currnet_tab = $dlg/databases.get_current_tab_control()
$dlg/load_db_dlg.set_current_file(currnet_tab.get_db_name())
$dlg/load_db_dlg.popup_centered()
# called when adding a new database
func on_new_database(db_name : String) -> void:
var tmp_name = db_name.to_lower()
var db_id = m_db_manager.add_database(db_name)
if(db_id == gddb_constants.c_invalid_id):
$dlg/error_dlg.set_text("Database with name \"" + db_name + "\" already exists")
$dlg/error_dlg.popup_centered()
return
var db = m_db_manager.get_db_by_id(db_id)
# print("new DB added: " + str(db))
var db_editor = load(gddb_constants.c_addon_main_path + "db_editor.tscn").instance()
$dlg/databases.add_child(db_editor)
db_editor.set_name(db_name)
db.set_dirty(true)
db_editor.set_database(db)
$dlg/menu.enable_file_save(true)
$dlg/menu.enable_file_save_as(true)
$dlg/new_db_dlg.hide()
# called when selecting a file from save / load dialog
func on_file_selected(filepath : String) -> void:
# print("GDDBInterface::on_file_selected(" + filepath + ")")
if($dlg/load_db_dlg.get_mode() == FileDialog.MODE_SAVE_FILE):
var filepath_low = filepath.to_lower()
# check for the file extension
if(!filepath_low.ends_with(".json")):
$dlg/error_dlg.set_text("The extension of the file must be \".json\"")
$dlg/error_dlg.popup_centered()
return
var current_filename = $dlg/load_db_dlg.get_current_file().to_lower()
var filename_dot = current_filename.length() - 5
current_filename.erase(filename_dot, 5)
# check the filename
if(!gddb_globals.check_db_name(current_filename)):
$dlg/error_dlg.set_text("Invalid characters in the database filename.\n\nThe filename cannot contain any of these characters: " + gddb_constants.c_invalid_characters)
$dlg/error_dlg.popup_centered()
return
save_database_as(filepath)
elif($dlg/load_db_dlg.get_mode() == FileDialog.MODE_OPEN_FILE):
load_database(filepath)
# saves a database to a given file path
func save_database_as(filepath : String) -> void:
# print("GDDBInterface::save_database_as(" + filepath + ")")
var currnet_tab = $dlg/databases.get_current_tab_control()
currnet_tab.set_database_filepath(filepath)
currnet_tab.save_database()
func load_database(filepath : String) -> void:
var db_id = m_db_manager.load_database(filepath)
if(db_id == gddb_types.e_db_invalid_file):
$dlg/error_dlg.set_text("Invalid database")
$dlg/error_dlg.popup_centered()
return
if(db_id == gddb_types.e_db_invalid_ver):
$dlg/error_dlg.set_text("Wrong database version. Currently is: " + gddb_constants.c_gddb_ver)
$dlg/error_dlg.popup_centered()
return
var db = m_db_manager.get_db_by_id(db_id)
db.set_dirty(false)
# print("new DB added: " + str(db))
var db_editor = load(gddb_constants.c_addon_main_path + "db_editor.tscn").instance()
$dlg/databases.add_child(db_editor)
db_editor.set_name(db.get_db_name())
db_editor.set_database(db)
$dlg/menu.enable_file_save(true)
$dlg/menu.enable_file_save_as(true)
db_editor.set_dirty(false)
-65
View File
@@ -1,65 +0,0 @@
[gd_scene load_steps=7 format=2]
[ext_resource path="res://addons/godot_db_manager/debug/dbg.tscn" type="PackedScene" id=1]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=2]
[ext_resource path="res://addons/godot_db_manager/dlgs/error_dlg.tscn" type="PackedScene" id=3]
[ext_resource path="res://addons/godot_db_manager/db_interface.gd" type="Script" id=4]
[ext_resource path="res://addons/godot_db_manager/dlgs/new_db_dlg.tscn" type="PackedScene" id=5]
[ext_resource path="res://addons/godot_db_manager/menu.tscn" type="PackedScene" id=7]
[node name="db_interface" type="Control"]
script = ExtResource( 4 )
__meta__ = {
"_edit_horizontal_guides_": [ 30.0, 674.0 ],
"_edit_use_anchors_": false
}
[node name="dlg" type="WindowDialog" parent="."]
visible = true
margin_right = 1147.0
margin_bottom = 768.0
popup_exclusive = true
window_title = "Godot Database Manager"
resizable = true
__meta__ = {
"_edit_use_anchors_": false
}
[node name="menu" parent="dlg" instance=ExtResource( 7 )]
[node name="databases" type="TabContainer" parent="dlg"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_top = 30.0
custom_fonts/font = ExtResource( 2 )
tab_align = 0
drag_to_rearrange_enabled = true
__meta__ = {
"_edit_use_anchors_": false
}
[node name="new_db_dlg" parent="dlg" instance=ExtResource( 5 )]
visible = false
margin_right = 3.832
[node name="error_dlg" parent="dlg" instance=ExtResource( 3 )]
visible = false
anchor_right = 0.187
anchor_bottom = 0.136
margin_right = 0.469986
margin_bottom = -0.0800018
[node name="load_db_dlg" type="FileDialog" parent="dlg"]
anchor_right = 0.349
anchor_bottom = 0.418
margin_right = -0.309998
margin_bottom = 0.209991
window_title = "Open a File"
mode = 0
filters = PoolStringArray( "*.json" )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="dbg" parent="dlg" instance=ExtResource( 1 )]
visible = false
-33
View File
@@ -1,33 +0,0 @@
"""
class GDDBManager
"""
class_name GDDBManager
tool
extends EditorPlugin
var DBInterface = preload("./db_interface.tscn")
var db_interface : Node
func _enter_tree():
add_autoload_singleton("gddb_constants", "res://addons/godot_db_manager/core/GDDBConstants.gd")
add_autoload_singleton("gddb_types", "res://addons/godot_db_manager/core/GDDBTypes.gd")
add_autoload_singleton("gddb_globals", "res://addons/godot_db_manager/core/GDDBGlobals.gd")
# Initialization of the plugin goes here
db_interface = DBInterface.instance()
get_editor_interface().get_base_control().add_child(db_interface)
add_tool_menu_item("Godot Database Manager", self, "open_config")
func _exit_tree():
# Clean-up of the plugin goes here
remove_tool_menu_item("Godot Database Manager")
if(db_interface):
db_interface.queue_free()
func open_config(UD):
var window = db_interface.get_node("dlg") as WindowDialog
if(window):
window.popup_centered()
-79
View File
@@ -1,79 +0,0 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/tex/debug.png" type="Texture" id=1]
[node name="dbg" type="Control"]
anchor_right = 1.0
anchor_bottom = 1.0
mouse_filter = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="1" type="Control" parent="."]
margin_right = 40.0
margin_bottom = 40.0
mouse_filter = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Sprite" type="Sprite" parent="1"]
scale = Vector2( 4, 4 )
texture = ExtResource( 1 )
centered = false
region_enabled = true
region_rect = Rect2( 2, 50, 10, 10 )
[node name="2" type="Control" parent="."]
anchor_left = 1.0
anchor_right = 1.0
margin_left = -40.0
margin_bottom = 40.0
mouse_filter = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Sprite" type="Sprite" parent="2"]
scale = Vector2( 4, 4 )
texture = ExtResource( 1 )
centered = false
region_enabled = true
region_rect = Rect2( 2, 50, 10, 10 )
[node name="3" type="Control" parent="."]
anchor_top = 1.0
anchor_bottom = 1.0
margin_top = -40.0
margin_right = 40.0
mouse_filter = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Sprite" type="Sprite" parent="3"]
scale = Vector2( 4, 4 )
texture = ExtResource( 1 )
centered = false
region_enabled = true
region_rect = Rect2( 2, 50, 10, 10 )
[node name="4" type="Control" parent="."]
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -40.0
margin_top = -40.0
mouse_filter = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Sprite" type="Sprite" parent="4"]
scale = Vector2( 4, 4 )
texture = ExtResource( 1 )
centered = false
region_enabled = true
region_rect = Rect2( 2, 50, 10, 10 )
-61
View File
@@ -1,61 +0,0 @@
"""
class GDDBDataPanel
"""
class_name GDDBDataPanel
tool
extends PopupPanel
signal select_data
var m_prop_id = gddb_constants.c_invalid_id
var m_row_idx = gddb_constants.c_invalid_id
var m_table = null
# Called when the node enters the scene tree for the first time.
func _ready():
connect("about_to_show", self, "on_about_to_show")
$ItemList.connect("item_selected", self, "on_item_selected")
# sets property id
func set_prop_id(prop_id : int) -> void :
m_prop_id = prop_id
# returns property id
func get_prop_id() -> int :
return m_prop_id
# sets row index
func set_row_idx(row_idx : int) -> void :
m_row_idx = row_idx
# returns row index
func get_row_idx() -> int :
return m_row_idx
# sets the table from the database
func set_table(table) -> void:
m_table = table
# returns the table from the database
func get_table() -> Object:
return m_table
# called when the popup is about to show
func on_about_to_show() -> void :
$ItemList.clear()
$ItemList.add_item("None")
for idx in range(0, m_table.get_rows_count()):
var option = gddb_globals.get_json_from_row(m_table, idx)
$ItemList.add_item(option)
# called when an item is selected
func on_item_selected(idx : int) -> void:
# the first index is ""
if(idx == 0):
emit_signal("select_data", m_prop_id, m_row_idx, -1, "{}" )
else:
emit_signal("select_data", m_prop_id, m_row_idx, idx-1, $ItemList.get_item_text(idx) )
hide()
@@ -1,25 +0,0 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://addons/godot_db_manager/dlgs/data_dlg.gd" type="Script" id=1]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_12.tres" type="DynamicFont" id=2]
[node name="data_dlg" type="PopupPanel"]
anchor_right = 0.285625
anchor_bottom = 0.351111
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ItemList" type="ItemList" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 4.0
margin_right = -4.0
margin_bottom = -4.0
custom_fonts/font = ExtResource( 2 )
items = [ "ababab", null, false, "cdcdcd", null, false, "efefef", null, false ]
__meta__ = {
"_edit_use_anchors_": false
}
@@ -1,41 +0,0 @@
"""
class GDDBDeletePropDlg
"""
class_name GDDBDeletePropDlg
tool
extends WindowDialog
signal delete_prop
var m_prop_id = gddb_constants.c_invalid_id
# Called when the node enters the scene tree for the first time.
func _ready() -> void :
$v_layout/buttons/ok_btn.connect("pressed", self, "on_ok_btn_pressed")
$v_layout/buttons/cancel_btn.connect("pressed", self, "on_cancel_btn_pressed")
# sets the property id
func set_prop_id(prop_id : int) -> void :
m_prop_id = prop_id
# returns the property id
func get_prop_id() -> int :
return m_prop_id
func set_prop_name(prop_name : String) -> void:
var text = "Delete property with name \"" + prop_name + "\" ?"
$v_layout/prop_info/prop_lbl.set_text(text)
# returns the table id
func get_table_id() -> int :
return m_prop_id
# called when the OK button is pressed
func on_ok_btn_pressed() -> void :
emit_signal("delete_prop")
hide()
func on_cancel_btn_pressed() -> void:
hide()
@@ -1,66 +0,0 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://addons/godot_db_manager/dlgs/delete_prop_dlg.gd" type="Script" id=1]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_14.tres" type="DynamicFont" id=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_12.tres" type="DynamicFont" id=3]
[node name="delete_prop_dlg" type="WindowDialog"]
visible = true
anchor_right = 0.257
anchor_bottom = 0.084
margin_right = 0.799988
margin_bottom = 0.399994
focus_next = NodePath("v_layout/buttons/ok_btn")
focus_mode = 1
custom_fonts/title_font = ExtResource( 2 )
popup_exclusive = true
window_title = "Delete property"
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="v_layout" type="VBoxContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
custom_constants/separation = 10
alignment = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="prop_info" type="HBoxContainer" parent="v_layout"]
margin_top = 13.0
margin_right = 412.0
margin_bottom = 30.0
alignment = 1
[node name="prop_lbl" type="Label" parent="v_layout/prop_info"]
margin_left = 152.0
margin_right = 259.0
margin_bottom = 17.0
custom_fonts/font = ExtResource( 2 )
text = "Property name: "
[node name="buttons" type="HBoxContainer" parent="v_layout"]
margin_top = 40.0
margin_right = 412.0
margin_bottom = 61.0
custom_constants/separation = 50
alignment = 1
[node name="ok_btn" type="Button" parent="v_layout/buttons"]
margin_left = 81.0
margin_right = 181.0
margin_bottom = 21.0
rect_min_size = Vector2( 100, 0 )
custom_fonts/font = ExtResource( 3 )
text = "OK"
[node name="cancel_btn" type="Button" parent="v_layout/buttons"]
margin_left = 231.0
margin_right = 331.0
margin_bottom = 21.0
rect_min_size = Vector2( 100, 0 )
custom_fonts/font = ExtResource( 3 )
text = "Cancel"
@@ -1,37 +0,0 @@
"""
class GDDBDeleteTableDlg
"""
class_name GDDBDeleteTableDlg
tool
extends WindowDialog
signal delete_table
var m_table_id = gddb_constants.c_invalid_id
# Called when the node enters the scene tree for the first time.
func _ready():
$v_layout/buttons/ok_btn.connect("pressed", self, "on_ok_btn_pressed")
$v_layout/buttons/cancel_btn.connect("pressed", self, "on_cancel_btn_pressed")
# sets the table id
func set_table_id(table_id : int) -> void:
m_table_id = table_id
func set_table_name(table_name : String) -> void:
var text = "Delete table with name \"" + table_name + "\" ?"
$v_layout/table_info/table_lbl.set_text(text)
# returns the table id
func get_table_id() -> int:
return m_table_id
# called when the OK button is pressed
func on_ok_btn_pressed() -> void:
emit_signal("delete_table")
hide()
func on_cancel_btn_pressed() -> void:
hide()
@@ -1,66 +0,0 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://addons/godot_db_manager/dlgs/delete_table_dlg.gd" type="Script" id=1]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_14.tres" type="DynamicFont" id=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_12.tres" type="DynamicFont" id=3]
[node name="delete_table_dlg" type="WindowDialog"]
visible = true
anchor_right = 0.257
anchor_bottom = 0.084
margin_right = 0.799988
margin_bottom = 0.399994
focus_next = NodePath("v_layout/buttons/ok_btn")
focus_mode = 1
custom_fonts/title_font = ExtResource( 2 )
popup_exclusive = true
window_title = "Delete table"
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="v_layout" type="VBoxContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
custom_constants/separation = 10
alignment = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="table_info" type="HBoxContainer" parent="v_layout"]
margin_top = 13.0
margin_right = 412.0
margin_bottom = 30.0
alignment = 1
[node name="table_lbl" type="Label" parent="v_layout/table_info"]
margin_left = 162.0
margin_right = 249.0
margin_bottom = 17.0
custom_fonts/font = ExtResource( 2 )
text = "Table name: "
[node name="buttons" type="HBoxContainer" parent="v_layout"]
margin_top = 40.0
margin_right = 412.0
margin_bottom = 61.0
custom_constants/separation = 50
alignment = 1
[node name="ok_btn" type="Button" parent="v_layout/buttons"]
margin_left = 81.0
margin_right = 181.0
margin_bottom = 21.0
rect_min_size = Vector2( 100, 0 )
custom_fonts/font = ExtResource( 3 )
text = "OK"
[node name="cancel_btn" type="Button" parent="v_layout/buttons"]
margin_left = 231.0
margin_right = 331.0
margin_bottom = 21.0
rect_min_size = Vector2( 100, 0 )
custom_fonts/font = ExtResource( 3 )
text = "Cancel"
@@ -1,59 +0,0 @@
"""
class GDDBEditStringDlg
"""
class_name GDDBEditStringDlg
tool
extends WindowDialog
signal string_edited
var m_prop_id = gddb_constants.c_invalid_id
var m_row_idx = gddb_constants.c_invalid_id
var m_data_text = ""
# Called when the node enters the scene tree for the first time.
func _ready():
$v_layout/btns/ok_btn.connect("pressed", self, "on_ok_btn_pressed")
$v_layout/btns/cancel_btn.connect("pressed", self, "on_cancel_btn_pressed")
$v_layout/text.connect("text_changed", self, "on_text_changed")
# sets property id
func set_prop_id(prop_id : int) -> void:
m_prop_id = prop_id
# returns property id
func get_prop_id() -> int :
return m_prop_id
# sets row index
func set_row_idx(row_idx : int) -> void :
m_row_idx = row_idx
# returns row index
func get_row_idx() -> int :
return m_row_idx
# sets data text
func set_data_text(text : String) -> void :
m_data_text = text
$v_layout/text.set_text(text)
# returns data text
func get_data_text() -> String :
return m_data_text
# Called when the OK button is pressed
func on_ok_btn_pressed() -> void :
emit_signal("string_edited")
hide()
# Called when the Cancel button is pressed
func on_cancel_btn_pressed() -> void :
hide()
# Called when text is changed
func on_text_changed() -> void:
m_data_text = $v_layout/text.get_text()
@@ -1,60 +0,0 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://addons/godot_db_manager/dlgs/edit_string_dlg.gd" type="Script" id=1]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_14.tres" type="DynamicFont" id=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_12.tres" type="DynamicFont" id=3]
[node name="edit_string_dlg" type="WindowDialog"]
anchor_right = 0.430625
anchor_bottom = 0.423333
focus_next = NodePath("v_layout/text")
custom_fonts/title_font = ExtResource( 3 )
window_title = "Edit string"
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": true
}
[node name="v_layout" type="VBoxContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="edit_text_btns" type="HBoxContainer" parent="v_layout"]
margin_right = 689.0
margin_bottom = 30.0
rect_min_size = Vector2( 0, 30 )
[node name="text" type="TextEdit" parent="v_layout"]
margin_top = 34.0
margin_right = 689.0
margin_bottom = 334.0
rect_min_size = Vector2( 0, 300 )
custom_fonts/font = ExtResource( 2 )
caret_blink = true
[node name="btns" type="HBoxContainer" parent="v_layout"]
margin_top = 338.0
margin_right = 689.0
margin_bottom = 368.0
rect_min_size = Vector2( 0, 30 )
custom_constants/separation = 200
alignment = 1
[node name="ok_btn" type="Button" parent="v_layout/btns"]
margin_left = 144.0
margin_right = 244.0
margin_bottom = 30.0
rect_min_size = Vector2( 100, 0 )
custom_fonts/font = ExtResource( 3 )
text = "OK"
[node name="cancel_btn" type="Button" parent="v_layout/btns"]
margin_left = 444.0
margin_right = 544.0
margin_bottom = 30.0
rect_min_size = Vector2( 100, 0 )
custom_fonts/font = ExtResource( 3 )
text = "Cancel"
@@ -1,11 +0,0 @@
[gd_scene format=2]
[node name="error_dlg" type="AcceptDialog"]
visible = true
anchor_right = 0.139
anchor_bottom = 0.099
margin_right = 0.599976
margin_bottom = -0.100006
popup_exclusive = true
window_title = "Error"
dialog_autowrap = true
@@ -1,76 +0,0 @@
"""
class GDDBLoadResourcePathDlg
"""
class_name GDDBLoadResourcePathDlg
tool
extends FileDialog
# TODO: put this list in a config file
const file_filters = [
# Godot resource file types
"*.res, *.tres ; Godot resource file types",
# Godot scene files
"*.scn, *.tscn, *escn ; Godot scene file types",
# Code file types
"*.gd, *.cs, *.h, *.c, *.hpp, *.cpp ; Code file types",
# Shader file types
"*.shader ; Shader file types",
# material file types
"*.mat ; Material file types",
# mesh file types
"*.dae, *.gltf, *.obj, *.fbx ; Mesh file types",
# animation file types
"*.anim ; Animation file types",
# font file types
"*.ttf, *.otf ; Font file types",
# image file types
"*.png, *.jpg, *.jpeg, *.tiff, *.tga, *.bmp, *.webp, *.gif, *.hdr ; Images file types",
# soung file types
"*.snd, *.wav, *.ogg, *.mp3 ; Sound file types",
# video file types
"*.ogg, *.mpg, *.mpeg, *.avi, *.mov, *.mp4, *.webm ; Video file types",
# text file types
"*.txt, *.csv, *.json, *.xml, *.cfg, *.ini ; Text file types",
# document file types
"*.doc, *.docx, *.xls, *.xlsx, *.odt, *.ods, *.pdf ; Doc file types",
# binary data file types
"*.dat, *.raw ; Binary data file types"
]
var m_prop_id = gddb_constants.c_invalid_id
var m_row_idx = gddb_constants.c_invalid_id
# Called when the node enters the scene tree for the first time.
func _ready():
set_filters(PoolStringArray(file_filters))
# sets the property id
func set_prop_id(prop_id : int) -> void :
m_prop_id = prop_id
# returns the property id
func get_prop_id() -> int :
return m_prop_id
# sets the row index
func set_row_idx(row_idx : int) -> void :
m_row_idx = row_idx
# returns the row index
func get_row_idx() -> int :
return m_row_idx
@@ -1,16 +0,0 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/godot_db_manager/dlgs/load_res_path_dlg.gd" type="Script" id=1]
[node name="load_res_path_dlg" type="FileDialog"]
anchor_right = 0.404
anchor_bottom = 0.431
margin_right = -0.400024
margin_bottom = 0.0999756
window_title = "Open a File"
resizable = true
mode = 0
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
@@ -1,63 +0,0 @@
"""
class GDDBNewDBDlg
"""
class_name GDDBNewDBDlg
tool
extends WindowDialog
signal create_new_db
var m_current_db_name = ""
# Called when the node enters the scene tree for the first time.
func _ready() -> void :
$v_layout/buttons/ok_btn.connect("pressed", self, "on_ok_btn_pressed")
$v_layout/buttons/cancel_btn.connect("pressed", self, "on_cancel_btn_pressed")
connect("about_to_show", self, "on_about_to_show")
$v_layout/db_info/db_edt.connect("text_changed", self, "on_text_changed")
$v_layout/db_info/db_edt.connect("text_entered", self, "on_text_confirmed")
# Called when the node is about to be shown.
func on_about_to_show() -> void :
m_current_db_name = ""
$v_layout/db_info/db_edt.set_text(m_current_db_name)
# called everytime the text is changed
func on_text_changed(new_text: String) -> void :
var change_text = true
if(!gddb_globals.check_db_name(new_text)):
change_text = false
else:
if(new_text.length() > gddb_constants.c_max_db_name_len):
change_text = false
else:
change_text = true
if(change_text):
m_current_db_name = $v_layout/db_info/db_edt.get_text()
else:
$v_layout/db_info/db_edt.set_text(m_current_db_name)
$v_layout/db_info/db_edt.set_cursor_position(m_current_db_name.length())
# called when the user presses the ENTER key
func on_text_confirmed(text : String) -> void :
# print("GDDBNewDBDlg::on_text_confirmed(" + text + ")")
if(m_current_db_name.empty()):
return
handle_db_name()
hide()
# called when the OK button is pressed
func on_ok_btn_pressed() -> void :
if(!m_current_db_name.empty()):
handle_db_name()
# called when the Cancel button is pressed
func on_cancel_btn_pressed() -> void :
hide()
# handles the name of the database
func handle_db_name() -> void :
emit_signal("create_new_db", m_current_db_name)
@@ -1,82 +0,0 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_14.tres" type="DynamicFont" id=1]
[ext_resource path="res://addons/godot_db_manager/dlgs/new_db_dlg.gd" type="Script" id=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_12.tres" type="DynamicFont" id=3]
[node name="new_db_dlg" type="WindowDialog"]
visible = true
anchor_right = 0.257
anchor_bottom = 0.1
margin_right = 0.799988
focus_next = NodePath("v_layout/db_info/db_edt")
focus_mode = 2
custom_fonts/title_font = ExtResource( 1 )
popup_exclusive = true
window_title = "New database (max 16 characters)"
script = ExtResource( 2 )
__meta__ = {
"_edit_horizontal_guides_": [ 90.0781 ],
"_edit_use_anchors_": false
}
[node name="v_layout" type="VBoxContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
custom_constants/separation = 20
alignment = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="db_info" type="HBoxContainer" parent="v_layout"]
margin_top = 11.0
margin_right = 412.0
margin_bottom = 38.0
alignment = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="db_lbl" type="Label" parent="v_layout/db_info"]
margin_left = 18.0
margin_top = 5.0
margin_right = 89.0
margin_bottom = 22.0
custom_fonts/font = ExtResource( 1 )
text = "DB name: "
[node name="db_edt" type="LineEdit" parent="v_layout/db_info"]
margin_left = 93.0
margin_right = 393.0
margin_bottom = 27.0
rect_min_size = Vector2( 300, 20 )
custom_fonts/font = ExtResource( 1 )
caret_blink = true
caret_blink_speed = 0.5
[node name="buttons" type="HBoxContainer" parent="v_layout"]
margin_top = 58.0
margin_right = 412.0
margin_bottom = 79.0
custom_constants/separation = 80
alignment = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ok_btn" type="Button" parent="v_layout/buttons"]
margin_left = 66.0
margin_right = 166.0
margin_bottom = 21.0
rect_min_size = Vector2( 100, 0 )
custom_fonts/font = ExtResource( 3 )
text = "OK"
[node name="cancel_btn" type="Button" parent="v_layout/buttons"]
margin_left = 246.0
margin_right = 346.0
margin_bottom = 21.0
rect_min_size = Vector2( 100, 0 )
custom_fonts/font = ExtResource( 3 )
text = "Cancel"
@@ -1,83 +0,0 @@
"""
class GDDBNewDBDlg
"""
class_name GDDBNewTableDlg
tool
extends WindowDialog
signal create_new_table
signal cancel_dialog
var m_dlg_type : int = gddb_types.e_new_dlg_type_new
var m_table_id = gddb_constants.c_invalid_id
var m_current_table_name = ""
# Called when the node enters the scene tree for the first time.
func _ready():
$v_layout/buttons/ok_btn.connect("pressed", self, "on_ok_btn_pressed")
$v_layout/buttons/cancel_btn.connect("pressed", self, "on_cancel_btn_pressed")
$v_layout/table_info/table_edt.connect("text_changed", self, "on_text_changed")
$v_layout/table_info/table_edt.connect("text_entered", self, "on_text_confirmed")
m_current_table_name = ""
# sets the type of the dialog
func set_dld_type(dlg_type : int) -> void :
m_dlg_type = dlg_type
# returns the dialog type
func get_dlg_type() -> int :
return m_dlg_type
# sets the table id
func set_table_id(table_id : int) -> void:
m_table_id = table_id
# returns the table id
func get_table_id() -> int:
return m_table_id
# sets the table name
func set_init_name(table_name : String) -> void:
# print("cNewTableDlg::set_init_name(" + name + ")")
m_current_table_name = table_name
$v_layout/table_info/table_edt.set_text(m_current_table_name)
func on_text_changed(new_text: String) -> void:
var change_text = true
if(!gddb_globals.check_db_name(new_text)):
change_text = false
else:
if(new_text.length() > gddb_constants.c_max_db_name_len):
change_text = false
else:
change_text = true
if(change_text):
m_current_table_name = $v_layout/table_info/table_edt.get_text()
else:
$v_layout/table_info/table_edt.set_text(m_current_table_name)
$v_layout/table_info/table_edt.set_cursor_position(m_current_table_name.length())
# called when the user presses the ENTER key
func on_text_confirmed(text : String) -> void:
if(m_current_table_name.empty()):
return
handle_table_name()
hide()
# called when the OK button is pressed
func on_ok_btn_pressed() -> void:
if(!m_current_table_name.empty()):
handle_table_name()
hide()
# called when the Cancel button is pressed
func on_cancel_btn_pressed() -> void :
hide()
emit_signal("cancel_dialog")
# handles the text in the EditLine
func handle_table_name() -> void:
emit_signal("create_new_table", m_current_table_name)
@@ -1,73 +0,0 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_12.tres" type="DynamicFont" id=1]
[ext_resource path="res://addons/godot_db_manager/dlgs/new_table_dlg.gd" type="Script" id=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_14.tres" type="DynamicFont" id=3]
[node name="new_table_dlg" type="WindowDialog"]
visible = true
anchor_right = 0.257
anchor_bottom = 0.084
margin_right = 0.799988
margin_bottom = 0.399994
focus_next = NodePath("v_layout/table_info/table_edt")
focus_mode = 1
custom_fonts/title_font = ExtResource( 3 )
popup_exclusive = true
window_title = "New table (max 16 characters)"
script = ExtResource( 2 )
[node name="v_layout" type="VBoxContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
custom_constants/separation = 10
alignment = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="table_info" type="HBoxContainer" parent="v_layout"]
margin_top = 8.0
margin_right = 412.0
margin_bottom = 35.0
alignment = 1
[node name="table_lbl" type="Label" parent="v_layout/table_info"]
margin_left = 10.0
margin_top = 5.0
margin_right = 97.0
margin_bottom = 22.0
custom_fonts/font = ExtResource( 3 )
text = "Table name: "
[node name="table_edt" type="LineEdit" parent="v_layout/table_info"]
margin_left = 101.0
margin_right = 401.0
margin_bottom = 27.0
rect_min_size = Vector2( 300, 20 )
custom_fonts/font = ExtResource( 3 )
caret_blink = true
caret_blink_speed = 0.5
[node name="buttons" type="HBoxContainer" parent="v_layout"]
margin_top = 45.0
margin_right = 412.0
margin_bottom = 66.0
custom_constants/separation = 80
alignment = 1
[node name="ok_btn" type="Button" parent="v_layout/buttons"]
margin_left = 66.0
margin_right = 166.0
margin_bottom = 21.0
rect_min_size = Vector2( 100, 0 )
custom_fonts/font = ExtResource( 1 )
text = "OK"
[node name="cancel_btn" type="Button" parent="v_layout/buttons"]
margin_left = 246.0
margin_right = 346.0
margin_bottom = 21.0
rect_min_size = Vector2( 100, 0 )
custom_fonts/font = ExtResource( 1 )
text = "Cancel"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

@@ -1,34 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/icon.png-8476557a42180e1e377aacb0cfda943e.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/godot_db_manager/icon/icon.png"
dest_files=[ "res://.import/icon.png-8476557a42180e1e377aacb0cfda943e.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0
Binary file not shown.
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2020 Radu Bolovan
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.
-101
View File
@@ -1,101 +0,0 @@
"""
class GDDBMenu
"""
class_name GDDBMenu
tool
extends Control
signal new_database
signal load_database
signal save_database
signal save_database_as
enum {
e_file_new_id = 0,
e_file_load_id = 1
e_file_save_id = 2,
e_file_save_as_id = 3,
e_option_autosave_on_close_id = 4
}
var m_enable_new_db = true
var m_enable_load_db = true
var m_enable_save_db = false
var m_enable_save_as_db = false
var m_check_autosave_on_load = false
func _ready() -> void:
$layout/File.connect("about_to_show", self, "on_about_to_show_file_menu")
$layout/File.get_popup().clear()
$layout/File.get_popup().add_item("New DB", e_file_new_id)
$layout/File.get_popup().add_item("Load DB", e_file_load_id)
$layout/File.get_popup().add_item("Save DB", e_file_save_id)
$layout/File.get_popup().add_item("Save DB As ...", e_file_save_as_id)
$layout/File.get_popup().connect("id_pressed", self, "on_file_id_pressed")
$layout/Options.connect("about_to_show", self, "on_about_to_show_options_menu")
$layout/Options.get_popup().clear()
$layout/Options.get_popup().add_check_item("Autosave on close", e_option_autosave_on_close_id)
$layout/Options.get_popup().connect("id_pressed", self, "on_options_id_pressed")
# called before showing the file menu
func on_about_to_show_file_menu() -> void:
for idx in range(0, $layout/File.get_popup().get_item_count()):
var item_id = $layout/File.get_popup().get_item_id(idx)
if(item_id == e_file_new_id):
$layout/File.get_popup().set_item_disabled(idx, !m_enable_new_db)
elif(item_id == e_file_load_id):
$layout/File.get_popup().set_item_disabled(idx, !m_enable_load_db)
elif(item_id == e_file_save_id):
$layout/File.get_popup().set_item_disabled(idx, !m_enable_save_db)
elif(item_id == e_file_save_as_id):
$layout/File.get_popup().set_item_disabled(idx, !m_enable_save_as_db)
raise()
# enables / disables the possibility to create a new databbase
func enable_file_new(enable) -> void:
m_enable_new_db = enable
# enables / disables the possibility to load a databbase
func enable_file_load(enable) -> void:
m_enable_load_db = enable
# enables / disables the possibility to save a databbase
func enable_file_save(enable) -> void:
m_enable_save_db = enable
# enables / disables the possibility to save a databbase as another
func enable_file_save_as(enable) -> void:
m_enable_save_as_db = enable
# called when the user clicks on a file menu item
func on_file_id_pressed(id : int) -> void:
if(id == e_file_new_id):
emit_signal("new_database")
elif(id == e_file_load_id):
emit_signal("load_database")
elif(id == e_file_save_id):
emit_signal("save_database")
elif(id == e_file_save_as_id):
emit_signal("save_database_as")
# called before showing the option menu
func on_about_to_show_options_menu() -> void:
for idx in range(0, $layout/Options.get_popup().get_item_count()):
var item_id = $layout/Options.get_popup().get_item_id(idx)
if(item_id == e_option_autosave_on_close_id):
$layout/Options.get_popup().set_item_checked(idx, m_check_autosave_on_load)
raise()
# enables / disables the possibility to autosave all databases on close
func enable_autosave_on_close(enable) -> void:
m_check_autosave_on_load = enable
# called when the user clicks on a options menu item
func on_options_id_pressed(id : int) -> void:
if(id == e_option_autosave_on_close_id):
enable_autosave_on_close(!m_check_autosave_on_load)
-36
View File
@@ -1,36 +0,0 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://addons/godot_db_manager/menu.gd" type="Script" id=1]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=2]
[node name="menu" type="Control"]
anchor_right = 1.0
rect_min_size = Vector2( 0, 30 )
script = ExtResource( 1 )
__meta__ = {
"_edit_horizontal_guides_": [ 30.0 ],
"_edit_use_anchors_": false,
"_edit_vertical_guides_": [ 1024.0 ]
}
[node name="layout" type="HBoxContainer" parent="."]
margin_right = 1024.0
margin_bottom = 30.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="File" type="MenuButton" parent="layout"]
margin_right = 40.0
margin_bottom = 30.0
custom_fonts/font = ExtResource( 2 )
text = "File"
items = [ "New DB", null, 0, false, false, 0, 0, null, "", false, "Load DB", null, 0, false, false, 1, 0, null, "", false, "Save DB", null, 0, false, false, 2, 0, null, "", false, "Save DB As ...", null, 0, false, false, 3, 0, null, "", false ]
[node name="Options" type="MenuButton" parent="layout"]
margin_left = 44.0
margin_right = 117.0
margin_bottom = 30.0
custom_fonts/font = ExtResource( 2 )
text = "Options"
items = [ "Autosave on close", null, 1, false, false, 4, 0, null, "", false ]
-7
View File
@@ -1,7 +0,0 @@
[plugin]
name="Godot Database Manager"
description="A database manager plugin for Google Engine."
author="Radu Bolovan"
version="2.1.a"
script="db_manager.gd"
-221
View File
@@ -1,221 +0,0 @@
"""
class GDDBTableCell
"""
class_name GDDBTableCell
tool
extends Control
signal edit_data
signal choose_resource
signal choose_data
signal edit_string
const c_cell_min_width = 150
var m_prop_id : int = -1
var m_prop_type : int = gddb_constants.c_invalid_id
var m_row_idx : int = -1
var m_text : String = ""
func _ready() -> void :
$LineEdit.connect("text_changed", self, "on_text_changed")
$LineEdit/edit_btn.connect("pressed", self, "on_edit_string")
$Button.connect("pressed", self, "on_button_pressed")
$Button.set_clip_text(true)
$CheckBox.connect("toggled", self, "on_toggle_button")
func _exit_tree() -> void :
$LineEdit.disconnect("text_changed", self, "on_text_changed")
# sets the property id
func set_prop_id(id : int) -> void :
m_prop_id = id
# returns the property id
func get_prop_id() -> int :
return m_prop_id
# sets property type
func set_prop_type(data_type : int) -> void :
# print("GDDBTableCell::set_prop_type(" + str(data_type) + ")")
var data_type_changed = false
if(m_prop_type != data_type):
m_prop_type = data_type
data_type_changed = true
if(!data_type_changed):
return
if(m_prop_type == gddb_types.e_prop_type_bool):
$LineEdit.hide()
$Button.hide()
$CheckBox.show()
set_text("")
elif(m_prop_type == gddb_types.e_prop_type_int):
$LineEdit.show()
$LineEdit/edit_btn.hide()
$Button.hide()
$CheckBox.hide()
set_text("0")
elif(m_prop_type == gddb_types.e_prop_type_float):
$LineEdit.show()
$LineEdit/edit_btn.hide()
$Button.hide()
$CheckBox.hide()
set_text("0.0")
elif(m_prop_type == gddb_types.e_prop_type_string):
$LineEdit.show()
$LineEdit/edit_btn.show()
$Button.hide()
$CheckBox.hide()
set_text("")
elif(m_prop_type == gddb_types.e_prop_type_resource):
$LineEdit.hide()
$Button.show()
$CheckBox.hide()
set_text("res://")
elif(m_prop_type >= gddb_types.e_prop_types_count):
$LineEdit.hide()
$Button.show()
$CheckBox.hide()
set_text("{}")
func get_prop_type() -> int :
return m_prop_type
# sets the row index
func set_row_idx(idx : int) -> void :
m_row_idx = idx
# returns the property index
func get_row_idx() -> int :
return m_row_idx
# sets the text
func set_text(text : String) -> void :
# print("GDDBTableCell::set_text(" + text + ")")
m_text = text
$LineEdit.set_text(m_text)
$Button.set_text(m_text)
if(m_prop_type == gddb_types.e_prop_type_bool):
$CheckBox.set_pressed((text == "1"))
# sets autoincrement
func enable_autoincrement(enable : bool) -> void :
$LineEdit.set_editable(!enable)
# refreshes the width by the property name
func refresh_width(prop_name : String) -> void :
var size = get_custom_minimum_size()
size.x = max(c_cell_min_width, get_font("normal_font").get_string_size(prop_name).x + 10)
set_custom_minimum_size(size)
# called when the checkbox is toggled/untoggled
func on_toggle_button(enable : bool) -> void :
var data = "0"
if(enable):
data = "1"
emit_signal("edit_data", m_prop_id, m_row_idx, data)
# called when the button is pressed
func on_button_pressed() -> void :
if(m_prop_type == gddb_types.e_prop_type_resource):
# print("GDDBTableCell::on_button_pressed()")
emit_signal("choose_resource", m_prop_id, m_row_idx)
elif(m_prop_type >= gddb_types.e_prop_types_count):
emit_signal("choose_data", m_prop_id, m_row_idx, m_prop_type)
# called when the edit string button is pressed
func on_edit_string() -> void :
emit_signal("edit_string", m_prop_id, m_row_idx, m_text)
# called when edit the data
func on_text_changed(new_text : String) -> void :
if(new_text.empty()):
m_text = ""
$LineEdit.set_text(m_text)
$LineEdit.set_cursor_position(0)
return
if(m_prop_type == gddb_types.e_prop_type_int):
if(!check_integer(new_text)):
return
if(m_prop_type == gddb_types.e_prop_type_float):
if(!check_float(new_text)):
return
emit_signal("edit_data", m_prop_id, m_row_idx, new_text)
# checks if the text is integer
func check_integer(text : String) -> bool :
var is_negative = false
# check if the string is probably a number, but starts with "-"
if(text.begins_with("-")):
text.erase(0, 1)
is_negative = true
# check if the current string is only "-"
if(text.empty()):
m_text = "-"
$LineEdit.set_text(m_text)
$LineEdit.set_cursor_position(m_text.length())
return true
if(text.is_valid_integer()):
if(text.begins_with("0")):
# a negative integer cannot start with "0"
if(is_negative):
m_text = "-"
$LineEdit.set_text(m_text)
$LineEdit.set_cursor_position(1)
return true
# a positive number starting with "0" can be only "0"
m_text = "0"
$LineEdit.set_text(m_text)
$LineEdit.set_cursor_position(1)
return true
# don't add more "-" in front of the number
if(text.begins_with("-")):
text.erase(0, 1)
# add back the "-"
if(is_negative):
m_text = "-" + text
else:
m_text = text
$LineEdit.set_text(m_text)
$LineEdit.set_cursor_position(m_text.length())
return true
$LineEdit.set_text(m_text)
$LineEdit.set_cursor_position(m_text.length())
return false
func check_float(text : String) -> bool :
if(text.is_valid_float()):
if(text.begins_with("00") || text.begins_with("01") || text.begins_with("02")
|| text.begins_with("03") || text.begins_with("04") || text.begins_with("05")
|| text.begins_with("06") || text.begins_with("07") || text.begins_with("08")
|| text.begins_with("09")):
m_text = "0"
$LineEdit.set_text(m_text)
$LineEdit.set_cursor_position(1)
return true
m_text = text
return true
$LineEdit.set_text(m_text)
$LineEdit.set_cursor_position(m_text.length())
return false
-72
View File
@@ -1,72 +0,0 @@
[gd_scene load_steps=7 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=1]
[ext_resource path="res://addons/godot_db_manager/table_cell.gd" type="Script" id=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=3]
[sub_resource type="AtlasTexture" id=1]
atlas = ExtResource( 1 )
region = Rect2( 28, 1.86734, 24, 24.1327 )
[sub_resource type="AtlasTexture" id=2]
atlas = ExtResource( 1 )
region = Rect2( 28, 54, 24, 24 )
[sub_resource type="AtlasTexture" id=3]
atlas = ExtResource( 1 )
region = Rect2( 28, 28, 24, 24 )
[node name="table_cell" type="Control"]
anchor_right = 1.0
margin_bottom = 15.36
rect_min_size = Vector2( 150, 32 )
script = ExtResource( 2 )
__meta__ = {
"_edit_horizontal_guides_": [ 32.0 ],
"_edit_use_anchors_": true
}
[node name="LineEdit" type="LineEdit" parent="."]
anchor_right = 1.0
anchor_bottom = 0.914286
custom_fonts/font = ExtResource( 3 )
text = "TESTING WWW"
caret_blink = true
caret_blink_speed = 0.5
__meta__ = {
"_edit_use_anchors_": true
}
[node name="edit_btn" type="TextureButton" parent="LineEdit"]
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -29.0
margin_top = 4.0
margin_right = -5.0
margin_bottom = -4.0
texture_normal = SubResource( 1 )
texture_pressed = SubResource( 2 )
texture_hover = SubResource( 3 )
__meta__ = {
"_edit_use_anchors_": true
}
[node name="Button" type="Button" parent="."]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
custom_fonts/font = ExtResource( 3 )
clip_text = true
__meta__ = {
"_edit_use_anchors_": false
}
[node name="CheckBox" type="CheckBox" parent="."]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
custom_fonts/font = ExtResource( 3 )
__meta__ = {
"_edit_use_anchors_": false
}
-433
View File
@@ -1,433 +0,0 @@
"""
class GDDBTableEditor
"""
class_name GDDBTableEditor
tool
extends Control
signal set_dirty
var m_parent_table = null
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
$tabs/structure/header/new_property_btn.connect("pressed", self, "on_new_property_btn_pressed")
$tabs/data/add_data_btn.connect("pressed", self, "on_add_row_data_btn_pressed")
$tabs/data/add_data_btn.set_disabled(true)
$load_res_path_dlg.connect("file_selected", self, "on_select_res_path")
$data_dlg.connect("select_data", self, "on_select_data")
$edit_string_dlg.connect("string_edited", self, "on_text_edited")
$delete_prop_dlg.connect("delete_prop", self, "on_confirm_delete_property")
# called when resizing a property
func on_resize_property(prop_id : int, diff_x : float) -> void :
var current_prop = null
for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()):
var prop = $tabs/data/scroll/data_holder/data_header.get_child(idx)
if(prop.get_prop_id() == prop_id):
current_prop = prop
break
var prop_size : Vector2 = current_prop.get_child(0).get_size()
# print("diff_x: " + str(diff_x))
prop_size.x += diff_x
if(prop_size.x < gddb_constants.c_min_cell_width):
return
if(prop_size.x > gddb_constants.c_max_cell_width):
return
# print("prop_size.x = " + str(prop_size.x))
var prop_idx = -1
var data_size = $tabs/data/scroll.get_size()
data_size.x += diff_x
$tabs/data/scroll/data_holder/data_header.set_size(data_size)
for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()):
var prop = $tabs/data/scroll/data_holder/data_header.get_child(idx)
if(prop.get_prop_id() == prop_id):
var current_prop_size = prop.get_custom_minimum_size()
current_prop_size.x += diff_x
prop.set_custom_minimum_size(current_prop_size)
prop_idx = idx
if(prop_idx != -1 && idx > prop_idx):
var pos = prop.get_position()
pos.x += diff_x
prop.set_position(pos)
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
for jdx in range(0, row.get_child_count()):
var cell = row.get_child(jdx)
if(cell.get_prop_id() == prop_id):
cell.set_custom_minimum_size(prop_size)
if(jdx > prop_idx):
var pos = cell.get_position()
pos.x += diff_x
cell.set_position(pos)
# called when the new_property button is pressed
func on_new_property_btn_pressed() -> void:
# print("GDDBTableEditor::on_new_property_btn_pressed()")
if(null == m_parent_table):
print("ERROR: GDDBTableEditor::on_new_property_btn_pressed() - m_parent_table is null")
return
var prop_idx = m_parent_table.get_props_count()
var prop_type = gddb_types.e_prop_type_bool
var prop_name = "Property_" + str(prop_idx+1)
var prop_id = m_parent_table.add_prop(prop_type, prop_name)
add_prop_to_structure(prop_id, prop_type, prop_name)
add_prop_to_data(prop_id, prop_type, prop_name, false)
# enable add data btn
$tabs/data/add_data_btn.set_disabled(false)
emit_signal("set_dirty")
# adds a property to structure tab
func add_prop_to_structure(prop_id : int, prop_type : int, prop_name : String) -> void:
# print("GDDBTableEditor::add_prop_to_structure(" + str(prop_id) + ", " + str(prop_type) + ", " + prop_name + ")")
var prop = load(gddb_constants.c_addon_main_path + "table_property.tscn").instance()
$tabs/structure/scroll/properties.add_child(prop)
prop.set_parent_table(m_parent_table)
prop.setup(prop_id, prop_type, prop_name)
prop.connect("edit_property", self, "on_edit_property")
prop.connect("delete_property", self, "on_delete_property")
prop.connect("enable_autoincrement", self, "on_enable_prop_autoincrement")
# adds a property to data tab
func add_prop_to_data(prop_id : int, prop_type : int, prop_name : String, has_autoincrement : bool) -> void:
var prop = load(gddb_constants.c_addon_main_path + "data_label.tscn").instance()
$tabs/data/scroll/data_holder/data_header.add_child(prop)
prop.set_prop_id(prop_id)
prop.set_text(prop_name)
prop.connect("resize_property", self, "on_resize_property")
# add property to the existing rows
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
var cell = load(gddb_constants.c_addon_main_path + "table_cell.tscn").instance()
row.add_child(cell)
cell.set_prop_id(prop_id)
cell.set_row_idx(idx)
cell.set_prop_type(prop_type)
cell.set_text("")
cell.enable_autoincrement(has_autoincrement)
cell.connect("edit_data", self, "on_edit_data")
cell.connect("choose_resource", self, "on_choose_resource")
cell.connect("choose_data", self, "on_choose_data")
cell.connect("edit_string", self, "on_edit_string")
# called when the add data button is pressed
func on_add_row_data_btn_pressed() -> void:
# print("GDDBTableEditor::on_add_row_data_btn_pressed")
# add blank row in the table
var row_idx = m_parent_table.get_rows_count()
m_parent_table.add_blank_row()
# add row in the interface
var row = HBoxContainer.new()
$tabs/data/scroll/data_holder/data_container.add_child(row)
for idx in range(0, $tabs/structure/scroll/properties.get_child_count()):
var cell = load(gddb_constants.c_addon_main_path + "table_cell.tscn").instance()
var prop = $tabs/structure/scroll/properties.get_child(idx)
var db_prop = m_parent_table.get_prop_by_id(idx)
row.add_child(cell)
cell.set_prop_id(idx)
cell.set_row_idx(row_idx)
cell.set_prop_type(prop.get_prop_type())
var autoincrement = db_prop.has_autoincrement()
cell.enable_autoincrement(db_prop.has_autoincrement())
if(autoincrement):
cell.set_text(str(row_idx+1))
cell.connect("edit_data", self, "on_edit_data")
cell.connect("choose_resource", self, "on_choose_resource")
cell.connect("choose_data", self, "on_choose_data")
cell.connect("edit_string", self, "on_edit_string")
emit_signal("set_dirty")
# sets the table from database
func set_table(table : Object) -> void:
# print("GDDBTableEditor::set_table(" + table.get_table_name() + ")")
clear_current_layout()
m_parent_table = table
fill_properties()
fill_data()
# fills the interface with current table's properties
func fill_properties() -> void:
# print("GDDBTableEditor::fill_properties()")
var props_count = m_parent_table.get_props_count()
for idx in range(0, props_count):
var db_prop = m_parent_table.get_prop_at(idx)
add_prop_to_structure(db_prop.get_prop_id(), db_prop.get_prop_type(), db_prop.get_prop_name())
var prop = load(gddb_constants.c_addon_main_path + "data_label.tscn").instance()
$tabs/data/scroll/data_holder/data_header.add_child(prop)
prop.set_prop_id(db_prop.get_prop_id())
prop.set_prop_type(db_prop.get_prop_type())
prop.set_text(db_prop.get_prop_name())
prop.connect("resize_property", self, "on_resize_property")
if(props_count > 0):
$tabs/data/add_data_btn.set_disabled(false)
# fills the interface with current table's data
func fill_data() -> void:
#print("GDDBTableEditor::fill_data()")
var rows_count = m_parent_table.get_rows_count()
#print("Table name: " + m_parent_table.get_table_name())
#print("rows_count: " + str(rows_count))
for idx in range(0, rows_count):
var row = HBoxContainer.new()
$tabs/data/scroll/data_holder/data_container.add_child(row)
var data_row = m_parent_table.get_data_at_row_idx(idx)
for jdx in range(0, data_row.size()):
var db_prop = m_parent_table.get_prop_at(jdx)
#print("Prop id: " + str(db_prop.get_prop_id()))
#print("Prop type: " + str(db_prop.get_prop_type()))
#print("Prop name: " + str(db_prop.get_prop_name()))
var cell = load(gddb_constants.c_addon_main_path + "table_cell.tscn").instance()
var cell_data = data_row[jdx].get_data()
var prop_type = db_prop.get_prop_type()
if(prop_type >= gddb_types.e_prop_types_count):
var db = m_parent_table.get_parent_database()
var table = db.get_table_by_id(prop_type - gddb_types.e_prop_types_count)
var data_row_idx = cell_data.to_int()
cell_data = gddb_globals.get_json_from_row(table, data_row_idx)
row.add_child(cell)
cell.set_prop_id(data_row[jdx].get_prop_id())
cell.set_row_idx(idx)
cell.set_prop_type(prop_type)
cell.set_text(cell_data)
cell.enable_autoincrement(db_prop.has_autoincrement())
cell.connect("edit_data", self, "on_edit_data")
cell.connect("choose_resource", self, "on_choose_resource")
cell.connect("choose_data", self, "on_choose_data")
cell.connect("edit_string", self, "on_edit_string")
# links properties
func link_props() -> void :
# print("GDDBTableEditor::link_props() for table with name: " + m_parent_table.get_table_name())
for idx in range(0, $tabs/structure/scroll/properties.get_child_count()):
var prop = $tabs/structure/scroll/properties.get_child(idx)
prop.link()
# refreshes autoincrement props
func refresh_autoincrement_props(prop_id, enable) -> void:
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
for jdx in range(0, row.get_child_count()):
var cell = row.get_child(jdx)
if(cell.get_prop_id() == prop_id):
cell.enable_autoincrement(enable)
# cleares current layout
func clear_current_layout() -> void:
# clear structure tab
for idx in range(0, $tabs/structure/scroll/properties.get_child_count()):
$tabs/structure/scroll/properties.get_child(idx).queue_free()
# clear data from data tab
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
for jdx in range(0, row.get_child_count()):
row.get_child(jdx).queue_free()
row.queue_free()
# clear properties from data tab
for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()):
$tabs/data/scroll/data_holder/data_header.get_child(idx).queue_free()
$tabs/data/add_data_btn.set_disabled(true)
# called when a property is edited
func on_edit_property(prop_id : int, prop_type : int, prop_name : String) -> void:
"""
print("GDDBTableEditor::on_edit_property(" + str(prop_id) + ", " + str(prop_type) + ", " + prop_name + ")")
if(prop_type >= gddb_types.e_prop_types_count):
var db = m_parent_table.get_parent_database()
var selected_table = db.get_table_by_id(gddb_types.e_prop_types_count - prop_type)
print("GDDBTableEditor::on_edit_property(" + str(prop_id) + ", " + selected_table.get_table_name() + ", " + prop_name + ")")
else:
print("GDDBTableEditor::on_edit_property(" + str(prop_id) + ", " + gddb_globals.get_data_name(prop_type) + ", " + prop_name + ")")
#"""
# edit prop in the table
m_parent_table.edit_prop(prop_id, prop_type, prop_name)
# refresh the prop name in data tab
for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()):
var prop = $tabs/data/scroll/data_holder/data_header.get_child(idx)
if(prop.get_prop_id() == prop_id):
prop.set_text(prop_name)
# update data type
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
for jdx in range(0, row.get_child_count()):
var cell = row.get_child(jdx)
if(cell.get_prop_id() == prop_id):
"""
if(prop_type < gddb_types.e_prop_types_count):
print("Prop type: " + gddb_globals.get_data_name(prop_type))
else:
print("Prop type: custom")
"""
cell.set_prop_type(prop_type)
emit_signal("set_dirty")
# called when a property is deleted
func on_delete_property(prop_id : int) -> void:
# print("GDDBTableEditor::on_delete_property(" + str(prop_id) + ")")
var prop = m_parent_table.get_prop_by_id(prop_id)
$delete_prop_dlg.set_prop_id(prop_id)
$delete_prop_dlg.set_prop_name(prop.get_prop_name())
$delete_prop_dlg.popup_centered()
# called when a property is deleted
func on_confirm_delete_property() -> void:
var prop_id = $delete_prop_dlg.get_prop_id()
# deletes a property from table; also all data by this property
m_parent_table.delete_prop(prop_id)
# delete cells from data tab
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
for jdx in range(0, row.get_child_count()):
var cell = row.get_child(jdx)
if(cell.get_prop_id() == prop_id):
cell.disconnect("edit_data", self, "on_edit_data")
cell.queue_free()
break
# delete property from data tab
for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()):
var prop = $tabs/data/scroll/data_holder/data_header.get_child(idx)
if(prop.get_prop_id() == prop_id):
prop.queue_free()
break
# delete prop from structure
for idx in range(0, $tabs/structure/scroll/properties.get_child_count()):
var prop = $tabs/structure/scroll/properties.get_child(idx)
if(prop.get_prop_id() == prop_id):
prop.queue_free()
break
# refresh the add data button
var props_count = m_parent_table.get_props_count()
if(props_count == 0):
$tabs/data/add_data_btn.set_disabled(true)
emit_signal("set_dirty")
# called when the property has autoincrement or not
func on_enable_prop_autoincrement(prop_id : int, enable : bool) -> void :
m_parent_table.enable_prop_autoincrement(prop_id, enable)
emit_signal("set_dirty")
refresh_autoincrement_props(prop_id, enable)
# reindex all data
if(enable):
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
for jdx in range(0, row.get_child_count()):
var cell = row.get_child(jdx)
if(cell.get_prop_id() == prop_id):
cell.set_text(str(idx + 1))
# called when edit data
func on_edit_data(prop_id : int, row_idx : int, data : String) -> void:
m_parent_table.edit_data(prop_id, row_idx, data)
emit_signal("set_dirty")
# called when choosing a resource
func on_choose_resource(prop_id : int, row_idx : int) -> void:
# print("GDDBTableEditor::on_choose_resource(" + str(prop_id) + ", " + str(row_idx) + ")")
$load_res_path_dlg.set_prop_id(prop_id)
$load_res_path_dlg.set_row_idx(row_idx)
$load_res_path_dlg.popup_centered()
# called when choosing a data
func on_choose_data(prop_id : int, row_idx : int, prop_type : int) -> void:
# print("GDDBTableEditor::on_choose_data(" + str(prop_id) + ", " + str(row_idx) + ", " + str(prop_type) + ")")
$data_dlg.set_prop_id(prop_id)
$data_dlg.set_row_idx(row_idx)
var table_id = prop_type - gddb_types.e_prop_types_count
var db = m_parent_table.get_parent_database()
var tbl = db.get_table_by_id(table_id)
$data_dlg.set_table(tbl)
$data_dlg.popup_centered()
# called when choosing to edit string
func on_edit_string(prop_id : int, row_idx : int, text : String) -> void:
$edit_string_dlg.set_prop_id(prop_id)
$edit_string_dlg.set_row_idx(row_idx)
$edit_string_dlg.set_data_text(text)
$edit_string_dlg.popup_centered()
# called when selecting a resource filepath
func on_select_res_path(filepath : String) -> void:
# print("GDDBTableEditor::on_select_res_path(" + filepath + ")")
var prop_id = $load_res_path_dlg.get_prop_id()
var row_idx = $load_res_path_dlg.get_row_idx()
m_parent_table.edit_data(prop_id, row_idx, filepath)
var row = $tabs/data/scroll/data_holder/data_container.get_child(row_idx)
for idx in range(0, row.get_child_count()):
var cell = row.get_child(idx)
if(cell.get_prop_id() == prop_id):
cell.set_text(filepath)
emit_signal("set_dirty")
# called when data from a table is choosen
func on_select_data(prop_id : int, row_idx : int, data_row_idx : int, data : String) -> void:
# set the data in the databes / table
m_parent_table.edit_data(prop_id, row_idx, str(data_row_idx))
# fill in the interface cell with data
var row = $tabs/data/scroll/data_holder/data_container.get_child(row_idx)
for idx in range(0, row.get_child_count()):
var cell = row.get_child(idx)
if(cell.get_prop_id() == prop_id):
cell.set_text(data)
break
emit_signal("set_dirty")
# called when the text is edited
func on_text_edited():
var prop_id = $edit_string_dlg.get_prop_id()
var row_idx = $edit_string_dlg.get_row_idx()
var text_data = $edit_string_dlg.get_data_text()
var data = gddb_globals.handle_string(text_data)
# print("GDDBTableEditor::on_text_edited() - prop_id: " + str(prop_id) + ", row_idx: " + str(row_idx) + ", data: " + text_data)
m_parent_table.edit_data(prop_id, row_idx, data)
var row = $tabs/data/scroll/data_holder/data_container.get_child(row_idx)
for idx in range(0, row.get_child_count()):
var cell = row.get_child(idx)
if(cell.get_prop_id() == prop_id):
cell.set_text(text_data)
break
emit_signal("set_dirty")
-161
View File
@@ -1,161 +0,0 @@
[gd_scene load_steps=16 format=2]
[ext_resource path="res://addons/godot_db_manager/dlgs/error_dlg.tscn" type="PackedScene" id=1]
[ext_resource path="res://addons/godot_db_manager/dlgs/load_res_path_dlg.tscn" type="PackedScene" id=2]
[ext_resource path="res://addons/godot_db_manager/table_editor.gd" type="Script" id=3]
[ext_resource path="res://addons/godot_db_manager/dlgs/data_dlg.tscn" type="PackedScene" id=4]
[ext_resource path="res://addons/godot_db_manager/dlgs/edit_string_dlg.tscn" type="PackedScene" id=5]
[ext_resource path="res://addons/godot_db_manager/dlgs/delete_prop_dlg.tscn" type="PackedScene" id=6]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=7]
[ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=8]
[sub_resource type="AtlasTexture" id=1]
atlas = ExtResource( 8 )
region = Rect2( 2, 2, 24, 24 )
[sub_resource type="AtlasTexture" id=2]
atlas = ExtResource( 8 )
region = Rect2( 2, 54, 24, 24 )
[sub_resource type="AtlasTexture" id=3]
atlas = ExtResource( 8 )
region = Rect2( 2, 28, 24, 24 )
[sub_resource type="AtlasTexture" id=4]
atlas = ExtResource( 8 )
region = Rect2( 2, 2, 24, 24 )
[sub_resource type="AtlasTexture" id=5]
atlas = ExtResource( 8 )
region = Rect2( 2, 54, 24, 24 )
[sub_resource type="AtlasTexture" id=6]
atlas = ExtResource( 8 )
region = Rect2( 2, 28, 24, 24 )
[sub_resource type="AtlasTexture" id=7]
atlas = ExtResource( 8 )
region = Rect2( 132, 2, 24, 24 )
[node name="table" type="Control"]
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource( 3 )
__meta__ = {
"_edit_horizontal_guides_": [ 584.0, 64.0, 70.0 ],
"_edit_use_anchors_": false,
"_edit_vertical_guides_": [ 1000.47 ]
}
[node name="tabs" type="TabContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
custom_fonts/font = ExtResource( 7 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="structure" type="Tabs" parent="tabs"]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 40.0
margin_right = -4.0
margin_bottom = -4.0
tab_close_display_policy = 2
[node name="header" type="HBoxContainer" parent="tabs/structure"]
margin_right = 892.0
margin_bottom = 24.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="new_property_btn" type="TextureButton" parent="tabs/structure/header"]
margin_right = 24.0
margin_bottom = 24.0
texture_normal = SubResource( 1 )
texture_pressed = SubResource( 2 )
texture_hover = SubResource( 3 )
[node name="props_lbl" type="Label" parent="tabs/structure/header"]
margin_left = 28.0
margin_top = 1.0
margin_right = 114.0
margin_bottom = 23.0
custom_fonts/font = ExtResource( 7 )
text = "Properties:"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="scroll" type="ScrollContainer" parent="tabs/structure"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_top = 30.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="properties" type="VBoxContainer" parent="tabs/structure/scroll"]
__meta__ = {
"_edit_use_anchors_": false
}
[node name="data" type="Tabs" parent="tabs"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 40.0
margin_right = -4.0
margin_bottom = -4.0
tab_close_display_policy = 2
[node name="add_data_btn" type="TextureButton" parent="tabs/data"]
margin_right = 24.0
margin_bottom = 24.0
disabled = true
texture_normal = SubResource( 4 )
texture_pressed = SubResource( 5 )
texture_hover = SubResource( 6 )
texture_disabled = SubResource( 7 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="scroll" type="ScrollContainer" parent="tabs/data"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_top = 38.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="data_holder" type="VBoxContainer" parent="tabs/data/scroll"]
margin_bottom = 36.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="data_header" type="HBoxContainer" parent="tabs/data/scroll/data_holder"]
margin_bottom = 32.0
rect_min_size = Vector2( 0, 32 )
rect_clip_content = true
[node name="data_container" type="VBoxContainer" parent="tabs/data/scroll/data_holder"]
margin_top = 36.0
margin_bottom = 36.0
[node name="error_dlg" parent="." instance=ExtResource( 1 )]
visible = false
[node name="load_res_path_dlg" parent="." instance=ExtResource( 2 )]
filters = PoolStringArray( "*.res, *.tres ; Godot resource file types", "*.scn, *.tscn, *escn ; Godot scene file types", "*.gd, *.cs, *.h, *.c, *.hpp, *.cpp ; Code file types", "*.shader ; Shader file types", "*.mat ; Material file types", "*.dae, *.gltf, *.obj, *.fbx ; Mesh file types", "*.anim ; Animation file types", "*.ttf, *.otf ; Font file types", "*.png, *.jpg, *.jpeg, *.tiff, *.tga, *.bmp, *.webp, *.gif, *.hdr ; Images file types", "*.snd, *.wav, *.ogg, *.mp3 ; Sound file types", "*.ogg, *.mpg, *.mpeg, *.avi, *.mov, *.mp4, *.webm ; Video file types", "*.txt, *.csv, *.json, *.xml, *.cfg, *.ini ; Text file types", "*.doc, *.docx, *.xls, *.xlsx, *.odt, *.ods, *.pdf ; Doc file types", "*.dat, *.raw ; Binary data file types" )
[node name="data_dlg" parent="." instance=ExtResource( 4 )]
[node name="edit_string_dlg" parent="." instance=ExtResource( 5 )]
[node name="delete_prop_dlg" parent="." instance=ExtResource( 6 )]
visible = false
-67
View File
@@ -1,67 +0,0 @@
"""
class GDDBTableItem
"""
class_name GDDBTableItem
tool
extends Control
signal select_item
signal edit_table
signal delete_table
var m_table_id = gddb_constants.c_invalid_id
var m_table_name = ""
var m_is_selected = false
# Called when the node enters the scene tree for the first time.
func _ready():
$select_btn.connect("pressed", self, "on_select_btn_pressed")
$edit_table_btn.connect("pressed", self, "on_edit_table_btn_pressed")
$delete_table_btn.connect("pressed", self, "on_delete_table_btn_pressed")
$select.hide()
# sets the table id
func set_table_id(id : int) -> void:
m_table_id = id
# returns the table id
func get_table_id() -> int:
return m_table_id
func set_selected(select : bool) -> void :
m_is_selected = select
if(m_is_selected):
$select.show()
else:
$select.hide()
func is_selected():
return m_is_selected
# sets the table name
func set_table_name(name : String) -> void:
# print("GDDBTableItem::set_table_name(" + name + ")")
m_table_name = name
$table_name.set_text(m_table_name)
# returns the table name
func get_table_name() -> String:
return m_table_name
# called when the user presses the edit_table button
func on_edit_table_btn_pressed():
# print("GDDBTableItem::on_edit_table_btn_pressed")
emit_signal("edit_table", m_table_id, m_table_name)
# called when the user presses the delete_table button
func on_delete_table_btn_pressed():
# print("GDDBTableItem::on_delete_table_btn_pressed")
emit_signal("delete_table", m_table_id)
# called when select_btn is pressed
func on_select_btn_pressed() -> void:
# print("GDDBTableItem::on_select_btn_pressed()")
emit_signal("select_item", m_table_id)
-109
View File
@@ -1,109 +0,0 @@
[gd_scene load_steps=11 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=1]
[ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=2]
[ext_resource path="res://addons/godot_db_manager/table_item.gd" type="Script" id=3]
[ext_resource path="res://addons/godot_db_manager/assets/tex/debug.png" type="Texture" id=4]
[sub_resource type="AtlasTexture" id=1]
atlas = ExtResource( 2 )
region = Rect2( 28, 2, 24, 24 )
[sub_resource type="AtlasTexture" id=2]
atlas = ExtResource( 2 )
region = Rect2( 28, 54, 24, 24 )
[sub_resource type="AtlasTexture" id=3]
atlas = ExtResource( 2 )
region = Rect2( 28, 28, 24, 24 )
[sub_resource type="AtlasTexture" id=4]
atlas = ExtResource( 2 )
region = Rect2( 54, 2, 24, 24 )
[sub_resource type="AtlasTexture" id=5]
atlas = ExtResource( 2 )
region = Rect2( 54, 54, 24, 24 )
[sub_resource type="AtlasTexture" id=6]
atlas = ExtResource( 2 )
region = Rect2( 54, 28, 24, 24 )
[node name="table_item" type="Control"]
anchor_right = 1.0
anchor_bottom = 0.021
margin_bottom = 0.399998
rect_min_size = Vector2( 180, 34 )
script = ExtResource( 3 )
__meta__ = {
"_edit_horizontal_guides_": [ 34.0 ],
"_edit_use_anchors_": false,
"_edit_vertical_guides_": [ 170.0 ]
}
[node name="dbg" type="NinePatchRect" parent="."]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
texture = ExtResource( 4 )
region_rect = Rect2( 38, 38, 10, 10 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="select" type="NinePatchRect" parent="."]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
texture = ExtResource( 2 )
region_rect = Rect2( 80, 6, 24, 4 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="table_name" type="Label" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
margin_right = -6.10352e-05
margin_bottom = -4.0
rect_min_size = Vector2( 100, 0 )
custom_fonts/font = ExtResource( 1 )
text = "Table_999"
valign = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="select_btn" type="TextureButton" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="edit_table_btn" type="TextureButton" parent="."]
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -56.0
margin_top = 5.0
margin_right = -32.0
margin_bottom = -5.0
texture_normal = SubResource( 1 )
texture_pressed = SubResource( 2 )
texture_hover = SubResource( 3 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="delete_table_btn" type="TextureButton" parent="."]
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -28.0
margin_top = 5.0
margin_right = -4.0
margin_bottom = -5.0
texture_normal = SubResource( 4 )
texture_pressed = SubResource( 5 )
texture_hover = SubResource( 6 )
-195
View File
@@ -1,195 +0,0 @@
"""
class GDDBTableProperty
"""
class_name GDDBTableProperty
tool
extends Control
signal delete_property
signal edit_property
signal enable_autoincrement
var m_prop_id : int = -1
var m_prop_type : int = 0
var m_prop_name : String = ""
var m_parent_table = null
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
$prop_name.connect("text_changed", self, "on_name_changed")
$prop_type.clear()
for idx in range(0, gddb_types.e_prop_types_count):
$prop_type.add_item(gddb_globals.get_data_name(idx), gddb_types.e_prop_type_bool + idx)
$prop_type.select(0)
$prop_type.get_popup().connect("about_to_show", self, "on_about_to_show")
$prop_type.connect("item_selected", self, "on_type_changed")
$delete_button.connect("pressed", self, "on_delete_button_pressed")
$autoincrement_btn.hide()
$autoincrement_btn.connect("toggled", self, "on_set_autoincrement")
# setup property
func setup(prop_id : int, prop_type : int, prop_name : String) -> void:
"""
if(prop_type < gddb_types.e_prop_types_count):
print("GDDBTableProperty::setup(" + str(prop_id) + ", " + gddb_globals.get_data_name(prop_type) + ", " + prop_name + ")")
else:
var db = m_parent_table.get_parent_database()
var table = db.get_table_by_id(prop_type - gddb_types.e_prop_types_count)
print("GDDBTableProperty::setup(" + str(prop_id) + ", " + table.get_table_name() + ", " + prop_name + ")")
#"""
set_prop_id(prop_id)
set_prop_type(prop_type)
set_prop_name(prop_name)
# sets parent table
func set_parent_table(table):
#print("GDDBTableProperty::set_parent_table(" + str(table) + ")")
m_parent_table = table
var db = m_parent_table.get_parent_database()
for idx in range(0, db.get_tables_count()):
var tbl = db.get_table_at(idx)
if(tbl == m_parent_table):
continue
$prop_type.add_item(tbl.get_table_name(), gddb_types.e_prop_types_count + tbl.get_table_id())
# sets proprty id
func set_prop_id(prop_id : int) -> void:
# print("GDDBTableProperty::set_prop_id(" + str(prop_id) + ")")
m_prop_id = prop_id
# returns property id
func get_prop_id() -> int:
return m_prop_id
# sets property type
func set_prop_type(prop_type : int) -> void:
"""
print("GDDBTableProperty::set_prop_type(" + str(prop_type) + ")")
if(prop_type < gddb_types.e_prop_types_count):
print("GDDBTableProperty::set_prop_type(" + gddb_globals.get_data_name(prop_type) + ")")
else:
var db = m_parent_table.get_parent_database()
var table = db.get_table_by_id(prop_type - gddb_types.e_prop_types_count)
print("GDDBTableProperty::set_prop_type(" + table.get_table_name() + ")")
#"""
#if(prop_type >= gddb_types.e_prop_types_count):
# print("GDDBTableProperty::set_prop_type(" + str(prop_type) + ")")
m_prop_type = prop_type
select_current_prop()
if(m_prop_type == gddb_types.e_prop_type_int):
$autoincrement_btn.show()
var prop = m_parent_table.get_prop_by_id(m_prop_id)
if(prop.has_autoincrement()):
$autoincrement_btn.set_pressed(true)
else:
$autoincrement_btn.hide()
# selects current property
func select_current_prop() -> void:
if(m_prop_type < gddb_types.e_prop_types_count):
$prop_type.select(m_prop_type)
# links property type to other tables
func link():
# print("GDDBTableProperty::link()")
refill_list()
if(m_prop_type >= gddb_types.e_prop_types_count):
"""
print("m_prop_id : " + str(m_prop_id))
print("m_prop_type : " + str(m_prop_type))
print("m_prop_name : " + m_prop_name)
"""
set_selection_by_id(m_prop_type)
else:
$prop_type.select(m_prop_type)
# returns property type
func get_prop_type() -> int:
return m_prop_type
# sets property name
func set_prop_name(prop_name : String) -> void:
# print("GDDBTableProperty::set_prop_name(" + prop_name + ")")
m_prop_name = prop_name
$prop_name.set_text(m_prop_name)
# returns property name
func get_prop_name() -> String:
return m_prop_name
# called everytime the name of the property is changed
func on_name_changed(new_text : String) -> void:
m_prop_name = new_text
emit_signal("edit_property", m_prop_id, m_prop_type, m_prop_name)
# called when the popup from option button is about to be shown
func on_about_to_show():
var selected_id = $prop_type.get_selected_id()
# print("GDDBTableProperty::on_about_to_show() - " + str(selected_id))
refill_list()
set_selection_by_id(selected_id)
# refills the list
func refill_list() -> void :
$prop_type.clear()
for idx in range(0, gddb_types.e_prop_types_count):
$prop_type.add_item(gddb_globals.get_data_name(idx), gddb_types.e_prop_type_bool + idx)
if(null != m_parent_table):
var db = m_parent_table.get_parent_database()
for idx in range(0, db.get_tables_count()):
var table = db.get_table_at(idx)
if(table == m_parent_table):
continue
"""
print("GDDBTableProperty::refill_list - Add:")
print("table id: " + str(table.get_table_id()))
print("table name: " + table.get_table_name())
#"""
# print("GDDBTableProperty::prop_type.add_item(" + table.get_table_name() + ", " + str(gddb_types.e_prop_types_count + table.get_table_id()) + ")" )
$prop_type.add_item(table.get_table_name(), gddb_types.e_prop_types_count + table.get_table_id())
# $prop_type.select(selected_idx)
# sets selection
func set_selection_by_id(selected_id : int) -> void :
# print("GDDBTableProperty::set_selection_by_id(" + str(selected_id) + ")")
for idx in range(0, $prop_type.get_item_count()):
if($prop_type.get_item_id(idx) == selected_id):
$prop_type.select(idx)
break
func on_set_autoincrement(enable : bool) -> void:
# print("GDDBTableProperty::on_set_autoincrement(" + str(enable) + ") - " + str(m_prop_id))
emit_signal("enable_autoincrement", m_prop_id, enable)
# called everytime the type of the property is changed
func on_type_changed(option_idx : int) -> void:
var option_id = $prop_type.get_item_id(option_idx)
"""
print("GDDBTableProperty::on_type_changed(" + str(option_idx) + ")")
print("option_id = " + str(option_id))
if(option_id >= gddb_types.e_prop_types_count):
print("GDDBTableProperty::on_type_changed(" + str(option_id) + ")")
else:
print("GDDBTableProperty::on_type_changed(" + gddb_globals.get_data_name(option_id) + ")")
#"""
m_prop_type = option_id
$autoincrement_btn.set_pressed(false)
if(m_prop_type == gddb_types.e_prop_type_int):
$autoincrement_btn.show()
else:
$autoincrement_btn.hide()
emit_signal("edit_property", m_prop_id, m_prop_type, m_prop_name)
# called when the delete property button is pressed
func on_delete_button_pressed() -> void:
emit_signal("delete_property", m_prop_id)
@@ -1,89 +0,0 @@
[gd_scene load_steps=7 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=1]
[ext_resource path="res://addons/godot_db_manager/table_property.gd" type="Script" id=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_18.tres" type="DynamicFont" id=3]
[sub_resource type="AtlasTexture" id=1]
atlas = ExtResource( 1 )
region = Rect2( 54, 2, 24, 24 )
[sub_resource type="AtlasTexture" id=2]
atlas = ExtResource( 1 )
region = Rect2( 54, 54, 24, 24 )
[sub_resource type="AtlasTexture" id=3]
atlas = ExtResource( 1 )
region = Rect2( 54, 28, 24, 24 )
[node name="table_property" type="Control"]
anchor_right = 1.0
margin_bottom = 15.36
rect_min_size = Vector2( 900, 32 )
script = ExtResource( 2 )
__meta__ = {
"_edit_horizontal_guides_": [ 32.0 ],
"_edit_use_anchors_": true
}
[node name="delete_button" type="TextureButton" parent="."]
margin_left = 3.0
margin_top = 4.0
margin_right = 27.0
margin_bottom = 28.0
texture_normal = SubResource( 1 )
texture_pressed = SubResource( 2 )
texture_hover = SubResource( 3 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="prop_name_label" type="Label" parent="."]
margin_left = 28.0
margin_top = 2.0
margin_right = 97.0
margin_bottom = 24.0
custom_fonts/font = ExtResource( 3 )
text = " Name:"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="prop_name" type="LineEdit" parent="."]
margin_left = 109.0
margin_right = 409.0
margin_bottom = 32.0
rect_min_size = Vector2( 300, 0 )
custom_fonts/font = ExtResource( 3 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="type_label" type="Label" parent="."]
margin_left = 413.0
margin_top = 2.0
margin_right = 473.0
margin_bottom = 24.0
custom_fonts/font = ExtResource( 3 )
text = " Type:"
[node name="prop_type" type="OptionButton" parent="."]
margin_left = 485.0
margin_right = 735.0
margin_bottom = 32.0
rect_min_size = Vector2( 250, 0 )
custom_fonts/font = ExtResource( 3 )
text = "Bool"
items = [ "Bool", null, false, 0, null, "Integer", null, false, 1, null, "Float", null, false, 2, null, "String", null, false, 3, null, "Resource", null, false, 4, null ]
selected = 0
[node name="autoincrement_btn" type="CheckBox" parent="."]
visible = false
margin_left = 740.0
margin_right = 891.0
margin_bottom = 32.0
custom_fonts/font = ExtResource( 3 )
text = "Auto increment"
__meta__ = {
"_edit_use_anchors_": false
}
-17
View File
@@ -1,17 +0,0 @@
"""
class GDDBTablesHeader
"""
class_name GDDBTablesHeader
tool
extends Control
signal add_table
# Called when the node enters the scene tree for the first time.
func _ready():
$add_table_btn.connect("pressed", self, "on_add_table_btn_pressed")
func on_add_table_btn_pressed():
emit_signal("add_table")
@@ -1,65 +0,0 @@
[gd_scene load_steps=7 format=2]
[ext_resource path="res://addons/godot_db_manager/assets/fnt/roboto_20.tres" type="DynamicFont" id=1]
[ext_resource path="res://addons/godot_db_manager/tables_header.gd" type="Script" id=2]
[ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=3]
[sub_resource type="AtlasTexture" id=1]
atlas = ExtResource( 3 )
region = Rect2( 2, 2, 24, 24 )
[sub_resource type="AtlasTexture" id=2]
atlas = ExtResource( 3 )
region = Rect2( 2, 54, 24, 24 )
[sub_resource type="AtlasTexture" id=3]
atlas = ExtResource( 3 )
region = Rect2( 2, 28, 24, 24 )
[node name="tables_header" type="Control"]
anchor_right = 0.188889
anchor_bottom = 0.019
margin_right = 6.10352e-05
margin_bottom = -0.4
rect_min_size = Vector2( 170, 30 )
script = ExtResource( 2 )
__meta__ = {
"_edit_use_anchors_": true,
"_edit_vertical_guides_": [ 170.0 ]
}
[node name="add_table_btn" type="TextureButton" parent="."]
margin_left = 2.0
margin_top = 2.0
margin_right = 26.0
margin_bottom = 26.0
texture_normal = SubResource( 1 )
texture_pressed = SubResource( 2 )
texture_hover = SubResource( 3 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="tables_lbl" type="Label" parent="."]
anchor_left = 0.165
anchor_right = 1.0
anchor_bottom = 0.8
margin_left = -0.0500259
margin_right = -0.000152588
custom_fonts/font = ExtResource( 1 )
text = "Tables "
align = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="line" type="NinePatchRect" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
margin_top = 29.0
margin_right = -0.000152588
texture = ExtResource( 3 )
region_rect = Rect2( 80, 2, 24, 2 )
__meta__ = {
"_edit_use_anchors_": false
}
-129
View File
@@ -1,129 +0,0 @@
"""
class GDDBTablesList
"""
class_name GDDBTablesList
tool
extends Control
signal resize_tables_list
signal add_table
signal edit_table_name
signal delete_table
signal select_table
var m_tables = []
var m_mouse_pos_pressed : Vector2 = Vector2()
var m_mouse_pressed : bool = false
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
m_mouse_pos_pressed = Vector2()
m_mouse_pressed = false
$tables_header.connect("add_table", self, "on_add_table")
# called when the node gets an input
func _input(event : InputEvent) -> void :
if(!gddb_globals.is_interface_active()):
return
var evLocal = $resize_ctrl.make_input_local(event)
if event is InputEventMouseButton :
if(event.button_index == BUTTON_LEFT):
if(event.pressed):
var rect = Rect2(Vector2(0, 0), $resize_ctrl.get_size())
var inside = rect.has_point(evLocal.position)
if(inside):
m_mouse_pressed = true
m_mouse_pos_pressed = evLocal.position
else:
m_mouse_pressed = false
elif event is InputEventMouseMotion :
if(m_mouse_pressed):
var diff_x = evLocal.position.x - m_mouse_pos_pressed.x
emit_signal("resize_tables_list", diff_x)
# custom resizing the tables list
func resize_content(size : Vector2) -> void :
set_size(size)
# I have no idea why I need to do this; this should be done automatically
var content_size = $tables_container/tables.get_size()
content_size.x = size.x
$tables_container/tables.set_custom_minimum_size(content_size)
# Called when the user presses the "add_table" button from the tables_list/header
func on_add_table() -> void :
# print("GDDBTablesList::on_add_table()")
emit_signal("add_table")
# creates a table
func create_table(db_table : Object, select_table : bool = true) -> void:
# print("GDDBTablesList::create_table(" + str(db_table) + ")")
var table = load(gddb_constants.c_addon_main_path + "table_item.tscn").instance()
var table_id = db_table.get_table_id()
table.set_table_id(table_id)
table.set_table_name(db_table.get_table_name())
table.connect("select_item", self, "on_select_item")
table.connect("edit_table", self, "on_edit_table_name")
table.connect("delete_table", self, "on_delete_table")
m_tables.push_back(table)
$tables_container/tables.add_child(table)
if(select_table):
select_item_by_id(table_id)
# Called when the user presses the "edit_table" button from the tables_list/table
func on_edit_table_name(table_id : int, table_name : String) -> void:
# print("GDDBTablesList::on_edit_table_name(" + str(table_id) + ", " + table_name + ")")
emit_signal("edit_table_name", table_id, table_name)
# Called when the user presses the "delete_table" button from the tables_list/table
func on_delete_table(table_id : int) -> void:
# print("GDDBTablesList::on_delete_table(" + str(table_id) + ")")
emit_signal("delete_table", table_id)
# edits the table name
func edit_table_name(table_id: int, table_name : String) -> void:
for idx in range(0, m_tables.size()):
if(m_tables[idx].get_table_id() == table_id):
m_tables[idx].set_table_name(table_name)
break
# deletes a table from the list
func delete_table(table_id : int) -> void:
for idx in range(0, m_tables.size()):
if(m_tables[idx].get_table_id() == table_id):
$tables_container/tables.remove_child(m_tables[idx])
m_tables.remove(idx)
break
# called when the user presses an item
func on_select_item(table_id : int) -> void:
# print("GDDBTablesList::on_select_item(" + str(table_id) + ")")
select_item_by_id(table_id)
emit_signal("select_table", table_id)
# select an item by index
func select_item_at(table_idx : int) -> void:
for idx in range(0, m_tables.size()):
m_tables[idx].set_selected(idx == table_idx)
# select an item by id
func select_item_by_id(table_id : int) -> void:
# print("GDDBTablesList::select_item_by_id(" + str(table_id) + ")")
for idx in range(0, m_tables.size()):
m_tables[idx].set_selected(m_tables[idx].get_table_id() == table_id)
# returns the selected element
func get_selected_item():
for idx in range(0, m_tables.size()):
if(m_tables[idx].is_selected()):
return m_tables[idx]
print("ERROR: GDDBTablesList::get_selected_item() - there is no selected element")
return null
-60
View File
@@ -1,60 +0,0 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://addons/godot_db_manager/tables_list.gd" type="Script" id=1]
[ext_resource path="res://addons/godot_db_manager/tables_header.tscn" type="PackedScene" id=2]
[ext_resource path="res://addons/godot_db_manager/debug/dbg.tscn" type="PackedScene" id=3]
[ext_resource path="res://addons/godot_db_manager/assets/tex/gui.png" type="Texture" id=4]
[node name="tables_list" type="Control"]
anchor_right = 0.2
anchor_bottom = 1.0
margin_right = -9.99991
rect_min_size = Vector2( 180, 225 )
script = ExtResource( 1 )
__meta__ = {
"_edit_horizontal_guides_": [ 29.9686, 584.0 ],
"_edit_use_anchors_": false,
"_edit_vertical_guides_": [ 180.0 ]
}
[node name="tables_header" parent="." instance=ExtResource( 2 )]
anchor_right = 1.0
anchor_bottom = 0.0
margin_right = -9.15527e-05
margin_bottom = 30.0
rect_min_size = Vector2( 180, 30 )
[node name="tables_container" type="ScrollContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
margin_top = 32.0
rect_min_size = Vector2( 180, 0 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="tables" type="VBoxContainer" parent="tables_container"]
rect_clip_content = true
__meta__ = {
"_edit_use_anchors_": false
}
[node name="resize_ctrl" type="NinePatchRect" parent="."]
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -3.0
mouse_filter = 0
mouse_default_cursor_shape = 15
texture = ExtResource( 4 )
region_rect = Rect2( 80, 12, 24, 24 )
patch_margin_left = 1
patch_margin_top = 1
patch_margin_right = 1
patch_margin_bottom = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="dbg" parent="." instance=ExtResource( 3 )]
visible = false
+10 -9
View File
@@ -1,14 +1,15 @@
# Copyright © 2020 Hugo Locurcio and contributors - MIT License # Copyright © 2020 Hugo Locurcio and contributors - MIT License
# See `LICENSE.md` included in the source distribution for details. # See `LICENSE.md` included in the source distribution for details.
extends CPUParticles @icon("res://addons/lod/lod_cpu_particles.svg")
class_name LODCPUParticles, "lod_cpu_particles.svg" class_name LODCPUParticles
extends CPUParticles3D
# If `false`, LOD won't update anymore. This can be used for performance comparison # If `false`, LOD won't update anymore. This can be used for performance comparison
# purposes. # purposes.
export var enable_lod := true @export var enable_lod := true
# The maximum particle emitting distance in units. Past this distance, particles will no longer emit. # The maximum particle emitting distance in units. Past this distance, particles will no longer emit.
export(float, 0.0, 1000.0, 0.1) var max_emit_distance := 50 @export var max_emit_distance := 50 # (float, 0.0, 1000.0, 0.1)
# The rate at which LODs will be updated (in seconds). Lower values are more reactive # The rate at which LODs will be updated (in seconds). Lower values are more reactive
# but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes. # but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes.
@@ -22,7 +23,7 @@ var refresh_rate := 0.25
# Positive values will decrease the detail level and improve performance. # Positive values will decrease the detail level and improve performance.
# Negative values will improve visual appearance at the cost of performance. # Negative values will improve visual appearance at the cost of performance.
# This can overridden by setting the project setting `lod/bias`. # This can overridden by setting the project setting `lod/bias`.
var lod_bias := 0.0 var lod_distance_bias := 0.0
# The internal refresh timer. # The internal refresh timer.
var timer := 0.0 var timer := 0.0
@@ -30,13 +31,13 @@ var timer := 0.0
func _ready() -> void: func _ready() -> void:
if ProjectSettings.has_setting("lod/particle_bias"): if ProjectSettings.has_setting("lod/particle_bias"):
lod_bias = ProjectSettings.get_setting("lod/particle_bias") lod_distance_bias = ProjectSettings.get_setting("lod/particle_bias")
if ProjectSettings.has_setting("lod/refresh_rate"): if ProjectSettings.has_setting("lod/refresh_rate"):
refresh_rate = ProjectSettings.get_setting("lod/refresh_rate") refresh_rate = ProjectSettings.get_setting("lod/refresh_rate")
# Add random jitter to the timer to ensure LODs don't all swap at the same time. # Add random jitter to the timer to ensure LODs don't all swap at the same time.
randomize() randomize()
timer += rand_range(0, refresh_rate) timer += randf_range(0, refresh_rate)
# Despite LOD not being related to physics, we chose to run in `_physics_process()` # Despite LOD not being related to physics, we chose to run in `_physics_process()`
# to minimize the amount of method calls per second (and therefore decrease CPU usage). # to minimize the amount of method calls per second (and therefore decrease CPU usage).
@@ -45,7 +46,7 @@ func _physics_process(delta: float) -> void:
return return
# We need a camera to do the rest. # We need a camera to do the rest.
var camera := get_viewport().get_camera() var camera := get_viewport().get_camera_3d()
if camera == null: if camera == null:
return return
@@ -55,5 +56,5 @@ func _physics_process(delta: float) -> void:
timer = 0.0 timer = 0.0
var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_bias var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_distance_bias
emitting = distance < max_emit_distance emitting = distance < max_emit_distance
+1
View File
@@ -0,0 +1 @@
uid://bgn0l4r2ydecj
+24 -15
View File
@@ -1,8 +1,9 @@
[remap] [remap]
importer="texture" importer="texture"
type="StreamTexture" type="CompressedTexture2D"
path="res://.import/lod_cpu_particles.svg-b3ece84e0440c5d32851b9105345db21.stex" uid="uid://27ju1od2xllu"
path="res://.godot/imported/lod_cpu_particles.svg-b3ece84e0440c5d32851b9105345db21.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
@@ -10,25 +11,33 @@ metadata={
[deps] [deps]
source_file="res://addons/lod/lod_cpu_particles.svg" source_file="res://addons/lod/lod_cpu_particles.svg"
dest_files=[ "res://.import/lod_cpu_particles.svg-b3ece84e0440c5d32851b9105345db21.stex" ] dest_files=["res://.godot/imported/lod_cpu_particles.svg-b3ece84e0440c5d32851b9105345db21.ctex"]
[params] [params]
compress/mode=0 compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7 compress/lossy_quality=0.7
compress/hdr_mode=0 compress/uastc_level=0
compress/bptc_ldr=0 compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0 compress/normal_map=0
flags/repeat=0 compress/channel_pack=0
flags/filter=true mipmaps/generate=false
flags/mipmaps=false mipmaps/limit=-1
flags/anisotropic=false roughness/mode=0
flags/srgb=2 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/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/normal_map_invert_y=false
process/invert_color=false process/hdr_as_srgb=false
stream=false process/hdr_clamp_exposure=false
size_limit=0 process/size_limit=0
detect_3d=true detect_3d/compress_to=1
svg/scale=1.0 svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
+13 -20
View File
@@ -1,25 +1,26 @@
# Copyright © 2020 Hugo Locurcio and contributors - MIT License # Copyright © 2020 Hugo Locurcio and contributors - MIT License
# See `LICENSE.md` included in the source distribution for details. # See `LICENSE.md` included in the source distribution for details.
extends OmniLight @icon("res://addons/lod/lod_omni_light.svg")
class_name LODOmniLight, "lod_omni_light.svg" class_name LODOmniLight
extends OmniLight3D
# If `false`, LOD won't update anymore. This can be used for performance comparison # If `false`, LOD won't update anymore. This can be used for performance comparison
# purposes. # purposes.
export var enable_lod := true @export var enable_lod := true
# The maximum shadow distance in units. Past this distance, the shadow will be disabled. # The maximum shadow distance in units. Past this distance, the shadow will be disabled.
export(float, 0.0, 1000.0, 0.1) var shadow_max_distance := 25 @export var shadow_max_distance := 25 # (float, 0.0, 1000.0, 0.1)
# The distance factor at which the shadow starts fading. # The distance factor at which the shadow starts fading.
# A value of 0.0 will result in the smoothest transition whereas a value of 1.0 disables fading. # A value of 0.0 will result in the smoothest transition whereas a value of 1.0 disables fading.
export(float, 0.0, 1.0, 0.1) var shadow_fade_start := 0.8 @export var shadow_fade_start := 0.8 # (float, 0.0, 1.0, 0.1)
# The maximum shadow distance in units. Past this distance, the light will be hidden. # The maximum shadow distance in units. Past this distance, the light will be hidden.
export(float, 0.0, 1000.0, 0.1) var light_max_distance := 50 @export var light_max_distance := 50 # (float, 0.0, 1000.0, 0.1)
# The distance factor at which the light starts fading. # The distance factor at which the light starts fading.
# A value of 0.0 will result in the smoothest transition whereas a value of 1.0 disables fading. # A value of 0.0 will result in the smoothest transition whereas a value of 1.0 disables fading.
export(float, 0.0, 1.0, 0.1) var light_fade_start := 0.8 @export var light_fade_start := 0.8 # (float, 0.0, 1.0, 0.1)
# The rate at which LODs will be updated (in seconds). Lower values are more reactive # The rate at which LODs will be updated (in seconds). Lower values are more reactive
# but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes. # but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes.
@@ -35,7 +36,7 @@ var refresh_rate := 0.05
# Positive values will decrease the detail level and improve performance. # Positive values will decrease the detail level and improve performance.
# Negative values will improve visual appearance at the cost of performance. # Negative values will improve visual appearance at the cost of performance.
# This can overridden by setting the project setting `lod/bias`. # This can overridden by setting the project setting `lod/bias`.
var lod_bias := 0.0 var lod_distance_bias := 0.0
# The internal refresh timer. # The internal refresh timer.
var timer := 0.0 var timer := 0.0
@@ -46,13 +47,13 @@ var base_light_energy := light_energy
func _ready() -> void: func _ready() -> void:
if ProjectSettings.has_setting("lod/light_bias"): if ProjectSettings.has_setting("lod/light_bias"):
lod_bias = ProjectSettings.get_setting("lod/light_bias") lod_distance_bias = ProjectSettings.get_setting("lod/light_bias")
if ProjectSettings.has_setting("lod/light_refresh_rate"): if ProjectSettings.has_setting("lod/light_refresh_rate"):
refresh_rate = ProjectSettings.get_setting("lod/light_refresh_rate") refresh_rate = ProjectSettings.get_setting("lod/light_refresh_rate")
# Add random jitter to the timer to ensure LODs don't all swap at the same time. # Add random jitter to the timer to ensure LODs don't all swap at the same time.
randomize() randomize()
timer += rand_range(0, refresh_rate) timer += randf_range(0, refresh_rate)
# Despite LOD not being related to physics, we chose to run in `_physics_process()` # Despite LOD not being related to physics, we chose to run in `_physics_process()`
# to minimize the amount of method calls per second (and therefore decrease CPU usage). # to minimize the amount of method calls per second (and therefore decrease CPU usage).
@@ -61,7 +62,7 @@ func _physics_process(delta: float) -> void:
return return
# We need a camera to do the rest. # We need a camera to do the rest.
var camera := get_viewport().get_camera() var camera := get_viewport().get_camera_3d()
if camera == null: if camera == null:
return return
@@ -71,7 +72,7 @@ func _physics_process(delta: float) -> void:
timer = 0.0 timer = 0.0
var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_bias var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_distance_bias
visible = distance < light_max_distance visible = distance < light_max_distance
var light_fade_start_distance := light_max_distance * light_fade_start var light_fade_start_distance := light_max_distance * light_fade_start
@@ -82,11 +83,3 @@ func _physics_process(delta: float) -> void:
light_energy = base_light_energy light_energy = base_light_energy
shadow_enabled = distance < shadow_max_distance shadow_enabled = distance < shadow_max_distance
var shadow_fade_start_distance := shadow_max_distance * shadow_fade_start
var shadow_value: float
if distance > shadow_fade_start_distance:
shadow_value = min(1, (distance - shadow_fade_start_distance) / (shadow_max_distance - shadow_fade_start_distance))
else:
# We're close enough to the light to show its shadow at full darkness.
shadow_value = 0.0
shadow_color = Color(shadow_value, shadow_value, shadow_value)
+1
View File
@@ -0,0 +1 @@
uid://d30dj8px8hj0l
+24 -15
View File
@@ -1,8 +1,9 @@
[remap] [remap]
importer="texture" importer="texture"
type="StreamTexture" type="CompressedTexture2D"
path="res://.import/lod_omni_light.svg-72b7ec907b4f0e08e3154232a03aab77.stex" uid="uid://mx6063qws57r"
path="res://.godot/imported/lod_omni_light.svg-72b7ec907b4f0e08e3154232a03aab77.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
@@ -10,25 +11,33 @@ metadata={
[deps] [deps]
source_file="res://addons/lod/lod_omni_light.svg" source_file="res://addons/lod/lod_omni_light.svg"
dest_files=[ "res://.import/lod_omni_light.svg-72b7ec907b4f0e08e3154232a03aab77.stex" ] dest_files=["res://.godot/imported/lod_omni_light.svg-72b7ec907b4f0e08e3154232a03aab77.ctex"]
[params] [params]
compress/mode=0 compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7 compress/lossy_quality=0.7
compress/hdr_mode=0 compress/uastc_level=0
compress/bptc_ldr=0 compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0 compress/normal_map=0
flags/repeat=0 compress/channel_pack=0
flags/filter=true mipmaps/generate=false
flags/mipmaps=false mipmaps/limit=-1
flags/anisotropic=false roughness/mode=0
flags/srgb=2 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/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/normal_map_invert_y=false
process/invert_color=false process/hdr_as_srgb=false
stream=false process/hdr_clamp_exposure=false
size_limit=0 process/size_limit=0
detect_3d=true detect_3d/compress_to=1
svg/scale=1.0 svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
+10 -9
View File
@@ -1,14 +1,15 @@
# Copyright © 2020 Hugo Locurcio and contributors - MIT License # Copyright © 2020 Hugo Locurcio and contributors - MIT License
# See `LICENSE.md` included in the source distribution for details. # See `LICENSE.md` included in the source distribution for details.
extends Particles @icon("res://addons/lod/lod_particles.svg")
class_name LODParticles, "lod_particles.svg" class_name LODParticles
extends GPUParticles3D
# If `false`, LOD won't update anymore. This can be used for performance comparison # If `false`, LOD won't update anymore. This can be used for performance comparison
# purposes. # purposes.
export var enable_lod := true @export var enable_lod := true
# The maximum particle emitting distance in units. Past this distance, particles will no longer emit. # The maximum particle emitting distance in units. Past this distance, particles will no longer emit.
export(float, 0.0, 1000.0, 0.1) var max_emit_distance := 50 @export var max_emit_distance := 50 # (float, 0.0, 1000.0, 0.1)
# The rate at which LODs will be updated (in seconds). Lower values are more reactive # The rate at which LODs will be updated (in seconds). Lower values are more reactive
# but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes. # but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes.
@@ -22,7 +23,7 @@ var refresh_rate := 0.25
# Positive values will decrease the detail level and improve performance. # Positive values will decrease the detail level and improve performance.
# Negative values will improve visual appearance at the cost of performance. # Negative values will improve visual appearance at the cost of performance.
# This can overridden by setting the project setting `lod/bias`. # This can overridden by setting the project setting `lod/bias`.
var lod_bias := 0.0 var lod_distance_bias := 0.0
# The internal refresh timer. # The internal refresh timer.
var timer := 0.0 var timer := 0.0
@@ -30,13 +31,13 @@ var timer := 0.0
func _ready() -> void: func _ready() -> void:
if ProjectSettings.has_setting("lod/particle_bias"): if ProjectSettings.has_setting("lod/particle_bias"):
lod_bias = ProjectSettings.get_setting("lod/particle_bias") lod_distance_bias = ProjectSettings.get_setting("lod/particle_bias")
if ProjectSettings.has_setting("lod/refresh_rate"): if ProjectSettings.has_setting("lod/refresh_rate"):
refresh_rate = ProjectSettings.get_setting("lod/refresh_rate") refresh_rate = ProjectSettings.get_setting("lod/refresh_rate")
# Add random jitter to the timer to ensure LODs don't all swap at the same time. # Add random jitter to the timer to ensure LODs don't all swap at the same time.
randomize() randomize()
timer += rand_range(0, refresh_rate) timer += randf_range(0, refresh_rate)
# Despite LOD not being related to physics, we chose to run in `_physics_process()` # Despite LOD not being related to physics, we chose to run in `_physics_process()`
# to minimize the amount of method calls per second (and therefore decrease CPU usage). # to minimize the amount of method calls per second (and therefore decrease CPU usage).
@@ -45,7 +46,7 @@ func _physics_process(delta: float) -> void:
return return
# We need a camera to do the rest. # We need a camera to do the rest.
var camera := get_viewport().get_camera() var camera := get_viewport().get_camera_3d()
if camera == null: if camera == null:
return return
@@ -55,5 +56,5 @@ func _physics_process(delta: float) -> void:
timer = 0.0 timer = 0.0
var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_bias var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_distance_bias
emitting = distance < max_emit_distance emitting = distance < max_emit_distance
+1
View File
@@ -0,0 +1 @@
uid://165j0dlh8l4w
+24 -15
View File
@@ -1,8 +1,9 @@
[remap] [remap]
importer="texture" importer="texture"
type="StreamTexture" type="CompressedTexture2D"
path="res://.import/lod_particles.svg-86d5ee48cd8c5d9e3cfcd6fa66432a55.stex" uid="uid://c6x1ooubmx3ll"
path="res://.godot/imported/lod_particles.svg-86d5ee48cd8c5d9e3cfcd6fa66432a55.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
@@ -10,25 +11,33 @@ metadata={
[deps] [deps]
source_file="res://addons/lod/lod_particles.svg" source_file="res://addons/lod/lod_particles.svg"
dest_files=[ "res://.import/lod_particles.svg-86d5ee48cd8c5d9e3cfcd6fa66432a55.stex" ] dest_files=["res://.godot/imported/lod_particles.svg-86d5ee48cd8c5d9e3cfcd6fa66432a55.ctex"]
[params] [params]
compress/mode=0 compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7 compress/lossy_quality=0.7
compress/hdr_mode=0 compress/uastc_level=0
compress/bptc_ldr=0 compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0 compress/normal_map=0
flags/repeat=0 compress/channel_pack=0
flags/filter=true mipmaps/generate=false
flags/mipmaps=false mipmaps/limit=-1
flags/anisotropic=false roughness/mode=0
flags/srgb=2 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/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/normal_map_invert_y=false
process/invert_color=false process/hdr_as_srgb=false
stream=false process/hdr_clamp_exposure=false
size_limit=0 process/size_limit=0
detect_3d=true detect_3d/compress_to=1
svg/scale=1.0 svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
+12 -11
View File
@@ -1,21 +1,22 @@
# Copyright © 2020 Hugo Locurcio and contributors - MIT License # Copyright © 2020 Hugo Locurcio and contributors - MIT License
# See `LICENSE.md` included in the source distribution for details. # See `LICENSE.md` included in the source distribution for details.
extends Spatial @icon("res://addons/lod/lod_spatial.svg")
class_name LODSpatial, "lod_spatial.svg" class_name LODSpatial
extends Node3D
# If `false`, LOD won't update anymore. This can be used for performance comparison # If `false`, LOD won't update anymore. This can be used for performance comparison
# purposes. # purposes.
export var enable_lod := true @export var enable_lod := true
# The maximum LOD 0 (high quality) distance in units. # The maximum LOD 0 (high quality) distance in units.
export(float, 0.0, 1000.0, 0.1) var lod_0_max_distance := 10 @export var lod_0_max_distance := 10 # (float, 0.0, 1000.0, 0.1)
# The maximum LOD 1 (medium quality) distance in units. # The maximum LOD 1 (medium quality) distance in units.
export(float, 0.0, 1000.0, 0.1) var lod_1_max_distance := 25 @export var lod_1_max_distance := 25 # (float, 0.0, 1000.0, 0.1)
# The maximum LOD 2 (low quality) distance in units. # The maximum LOD 2 (low quality) distance in units.
# Past this distance, all LOD variants are hidden. # Past this distance, all LOD variants are hidden.
export(float, 0.0, 1000.0, 0.1) var lod_2_max_distance := 100 @export var lod_2_max_distance := 100 # (float, 0.0, 1000.0, 0.1)
# The rate at which LODs will be updated (in seconds). Lower values are more reactive # The rate at which LODs will be updated (in seconds). Lower values are more reactive
# but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes. # but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes.
@@ -29,7 +30,7 @@ var refresh_rate := 0.25
# Positive values will decrease the detail level and improve performance. # Positive values will decrease the detail level and improve performance.
# Negative values will improve visual appearance at the cost of performance. # Negative values will improve visual appearance at the cost of performance.
# This can overridden by setting the project setting `lod/bias`. # This can overridden by setting the project setting `lod/bias`.
var lod_bias := 0.0 var lod_distance_bias := 0.0
# The internal refresh timer. # The internal refresh timer.
var timer := 0.0 var timer := 0.0
@@ -37,13 +38,13 @@ var timer := 0.0
func _ready() -> void: func _ready() -> void:
if ProjectSettings.has_setting("lod/spatial_bias"): if ProjectSettings.has_setting("lod/spatial_bias"):
lod_bias = ProjectSettings.get_setting("lod/spatial_bias") lod_distance_bias = ProjectSettings.get_setting("lod/spatial_bias")
if ProjectSettings.has_setting("lod/refresh_rate"): if ProjectSettings.has_setting("lod/refresh_rate"):
refresh_rate = ProjectSettings.get_setting("lod/refresh_rate") refresh_rate = ProjectSettings.get_setting("lod/refresh_rate")
# Add random jitter to the timer to ensure LODs don't all swap at the same time. # Add random jitter to the timer to ensure LODs don't all swap at the same time.
randomize() randomize()
timer += rand_range(0, refresh_rate) timer += randf_range(0, refresh_rate)
# Despite LOD not being related to physics, we chose to run in `_physics_process()` # Despite LOD not being related to physics, we chose to run in `_physics_process()`
@@ -53,7 +54,7 @@ func _physics_process(delta: float) -> void:
return return
# We need a camera to do the rest. # We need a camera to do the rest.
var camera := get_viewport().get_camera() var camera := get_viewport().get_camera_3d()
if camera == null: if camera == null:
return return
@@ -63,7 +64,7 @@ func _physics_process(delta: float) -> void:
timer = 0.0 timer = 0.0
var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_bias var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_distance_bias
# The LOD level to choose (lower is more detailed). # The LOD level to choose (lower is more detailed).
var lod: int var lod: int
if distance < lod_0_max_distance: if distance < lod_0_max_distance:
+1
View File
@@ -0,0 +1 @@
uid://fnay4dhox0y7
+24 -15
View File
@@ -1,8 +1,9 @@
[remap] [remap]
importer="texture" importer="texture"
type="StreamTexture" type="CompressedTexture2D"
path="res://.import/lod_spatial.svg-0f291da571b0a5b87fdce289c6370d71.stex" uid="uid://drwqorwwfwjut"
path="res://.godot/imported/lod_spatial.svg-0f291da571b0a5b87fdce289c6370d71.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
@@ -10,25 +11,33 @@ metadata={
[deps] [deps]
source_file="res://addons/lod/lod_spatial.svg" source_file="res://addons/lod/lod_spatial.svg"
dest_files=[ "res://.import/lod_spatial.svg-0f291da571b0a5b87fdce289c6370d71.stex" ] dest_files=["res://.godot/imported/lod_spatial.svg-0f291da571b0a5b87fdce289c6370d71.ctex"]
[params] [params]
compress/mode=0 compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7 compress/lossy_quality=0.7
compress/hdr_mode=0 compress/uastc_level=0
compress/bptc_ldr=0 compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0 compress/normal_map=0
flags/repeat=0 compress/channel_pack=0
flags/filter=true mipmaps/generate=false
flags/mipmaps=false mipmaps/limit=-1
flags/anisotropic=false roughness/mode=0
flags/srgb=2 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/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/normal_map_invert_y=false
process/invert_color=false process/hdr_as_srgb=false
stream=false process/hdr_clamp_exposure=false
size_limit=0 process/size_limit=0
detect_3d=true detect_3d/compress_to=1
svg/scale=1.0 svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
+13 -20
View File
@@ -1,25 +1,26 @@
# Copyright © 2020 Hugo Locurcio and contributors - MIT License # Copyright © 2020 Hugo Locurcio and contributors - MIT License
# See `LICENSE.md` included in the source distribution for details. # See `LICENSE.md` included in the source distribution for details.
extends SpotLight @icon("res://addons/lod/lod_spot_light.svg")
class_name LODSpotLight, "lod_spot_light.svg" class_name LODSpotLight
extends SpotLight3D
# If `false`, LOD won't update anymore. This can be used for performance comparison # If `false`, LOD won't update anymore. This can be used for performance comparison
# purposes. # purposes.
export var enable_lod := true @export var enable_lod := true
# The maximum shadow distance in units. Past this distance, the shadow will be disabled. # The maximum shadow distance in units. Past this distance, the shadow will be disabled.
export(float, 0.0, 1000.0, 0.1) var shadow_max_distance := 25 @export var shadow_max_distance := 25 # (float, 0.0, 1000.0, 0.1)
# The distance factor at which the shadow starts fading. # The distance factor at which the shadow starts fading.
# A value of 0.0 will result in the smoothest transition whereas a value of 1.0 disables fading. # A value of 0.0 will result in the smoothest transition whereas a value of 1.0 disables fading.
export(float, 0.0, 1.0, 0.1) var shadow_fade_start := 0.8 @export var shadow_fade_start := 0.8 # (float, 0.0, 1.0, 0.1)
# The maximum shadow distance in units. Past this distance, the light will be hidden. # The maximum shadow distance in units. Past this distance, the light will be hidden.
export(float, 0.0, 1000.0, 0.1) var light_max_distance := 50 @export var light_max_distance := 50 # (float, 0.0, 1000.0, 0.1)
# The distance factor at which the light starts fading. # The distance factor at which the light starts fading.
# A value of 0.0 will result in the smoothest transition whereas a value of 1.0 disables fading. # A value of 0.0 will result in the smoothest transition whereas a value of 1.0 disables fading.
export(float, 0.0, 1.0, 0.1) var light_fade_start := 0.8 @export var light_fade_start := 0.8 # (float, 0.0, 1.0, 0.1)
# The rate at which LODs will be updated (in seconds). Lower values are more reactive # The rate at which LODs will be updated (in seconds). Lower values are more reactive
# but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes. # but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes.
@@ -35,7 +36,7 @@ var refresh_rate := 0.05
# Positive values will decrease the detail level and improve performance. # Positive values will decrease the detail level and improve performance.
# Negative values will improve visual appearance at the cost of performance. # Negative values will improve visual appearance at the cost of performance.
# This can overridden by setting the project setting `lod/bias`. # This can overridden by setting the project setting `lod/bias`.
var lod_bias := 0.0 var lod_distance_bias := 0.0
# The internal refresh timer. # The internal refresh timer.
var timer := 0.0 var timer := 0.0
@@ -46,13 +47,13 @@ var base_light_energy := light_energy
func _ready() -> void: func _ready() -> void:
if ProjectSettings.has_setting("lod/light_bias"): if ProjectSettings.has_setting("lod/light_bias"):
lod_bias = ProjectSettings.get_setting("lod/light_bias") lod_distance_bias = ProjectSettings.get_setting("lod/light_bias")
if ProjectSettings.has_setting("lod/light_refresh_rate"): if ProjectSettings.has_setting("lod/light_refresh_rate"):
refresh_rate = ProjectSettings.get_setting("lod/light_refresh_rate") refresh_rate = ProjectSettings.get_setting("lod/light_refresh_rate")
# Add random jitter to the timer to ensure LODs don't all swap at the same time. # Add random jitter to the timer to ensure LODs don't all swap at the same time.
randomize() randomize()
timer += rand_range(0, refresh_rate) timer += randf_range(0, refresh_rate)
# Despite LOD not being related to physics, we chose to run in `_physics_process()` # Despite LOD not being related to physics, we chose to run in `_physics_process()`
# to minimize the amount of method calls per second (and therefore decrease CPU usage). # to minimize the amount of method calls per second (and therefore decrease CPU usage).
@@ -61,7 +62,7 @@ func _physics_process(delta: float) -> void:
return return
# We need a camera to do the rest. # We need a camera to do the rest.
var camera := get_viewport().get_camera() var camera := get_viewport().get_camera_3d()
if camera == null: if camera == null:
return return
@@ -71,7 +72,7 @@ func _physics_process(delta: float) -> void:
timer = 0.0 timer = 0.0
var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_bias var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_distance_bias
visible = distance < light_max_distance visible = distance < light_max_distance
var light_fade_start_distance := light_max_distance * light_fade_start var light_fade_start_distance := light_max_distance * light_fade_start
@@ -82,11 +83,3 @@ func _physics_process(delta: float) -> void:
light_energy = base_light_energy light_energy = base_light_energy
shadow_enabled = distance < shadow_max_distance shadow_enabled = distance < shadow_max_distance
var shadow_fade_start_distance := shadow_max_distance * shadow_fade_start
var shadow_value: float
if distance > shadow_fade_start_distance:
shadow_value = min(1, (distance - shadow_fade_start_distance) / (shadow_max_distance - shadow_fade_start_distance))
else:
# We're close enough to the light to show its shadow at full darkness.
shadow_value = 0.0
shadow_color = Color(shadow_value, shadow_value, shadow_value)
+1
View File
@@ -0,0 +1 @@
uid://d3astipm6q338
+24 -15
View File
@@ -1,8 +1,9 @@
[remap] [remap]
importer="texture" importer="texture"
type="StreamTexture" type="CompressedTexture2D"
path="res://.import/lod_spot_light.svg-22de3bf1089e94662394255ca8159db9.stex" uid="uid://qc2optw5cldv"
path="res://.godot/imported/lod_spot_light.svg-22de3bf1089e94662394255ca8159db9.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
@@ -10,25 +11,33 @@ metadata={
[deps] [deps]
source_file="res://addons/lod/lod_spot_light.svg" source_file="res://addons/lod/lod_spot_light.svg"
dest_files=[ "res://.import/lod_spot_light.svg-22de3bf1089e94662394255ca8159db9.stex" ] dest_files=["res://.godot/imported/lod_spot_light.svg-22de3bf1089e94662394255ca8159db9.ctex"]
[params] [params]
compress/mode=0 compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7 compress/lossy_quality=0.7
compress/hdr_mode=0 compress/uastc_level=0
compress/bptc_ldr=0 compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0 compress/normal_map=0
flags/repeat=0 compress/channel_pack=0
flags/filter=true mipmaps/generate=false
flags/mipmaps=false mipmaps/limit=-1
flags/anisotropic=false roughness/mode=0
flags/srgb=2 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/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/normal_map_invert_y=false
process/invert_color=false process/hdr_as_srgb=false
stream=false process/hdr_clamp_exposure=false
size_limit=0 process/size_limit=0
detect_3d=true detect_3d/compress_to=1
svg/scale=1.0 svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
+1 -1
View File
@@ -1,7 +1,7 @@
@tool
# Copyright © 2020 Hugo Locurcio and contributors - MIT License # Copyright © 2020 Hugo Locurcio and contributors - MIT License
# See `LICENSE.md` included in the source distribution for details. # See `LICENSE.md` included in the source distribution for details.
# #
# This script is needed to make the `class_name` script visible in the Create New Node dialog # This script is needed to make the `class_name` script visible in the Create New Node dialog
# once the plugin is enabled. # once the plugin is enabled.
tool
extends EditorPlugin extends EditorPlugin
+1
View File
@@ -0,0 +1 @@
uid://btdo13snbx7nb
View File
+9 -20
View File
@@ -1,28 +1,17 @@
[gd_resource type="Environment" load_steps=3 format=2] [gd_resource type="Environment" format=3 uid="uid://cosbxx1qhfx35"]
[ext_resource path="res://assets/hdri/tx_night_place.hdr" type="Texture" id=1] [sub_resource type="Sky" id="2"]
[sub_resource type="PanoramaSky" id=2]
panorama = ExtResource( 1 )
[resource] [resource]
background_mode = 3 background_mode = 3
background_sky = SubResource( 2 ) background_color = Color(0.188235, 0.133333, 0.133333, 1)
background_color = Color( 0.188235, 0.133333, 0.133333, 1 ) sky = SubResource("2")
background_energy = 0.6 ambient_light_color = Color(0.694118, 0.168627, 0.67451, 1)
ambient_light_color = Color( 0.694118, 0.168627, 0.67451, 1 )
ambient_light_energy = 1.55
ambient_light_sky_contribution = 0.5 ambient_light_sky_contribution = 0.5
ambient_light_energy = 1.55
tonemap_mode = 2
glow_enabled = true
fog_enabled = true fog_enabled = true
fog_color = Color( 0.562167, 0.29, 1, 0.941176 ) fog_depth_curve = 1.10957
fog_depth_begin = 0.0 fog_depth_begin = 0.0
fog_depth_end = 60.0 fog_depth_end = 60.0
fog_depth_curve = 1.10957
fog_height_enabled = true
fog_height_min = 2.0
fog_height_max = -20.0
fog_height_curve = 0.965936
tonemap_mode = 2
ss_reflections_enabled = true
dof_blur_far_distance = 2.0
glow_enabled = true
+36
View File
@@ -0,0 +1,36 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://c7ps8q01ej5du"
path="res://.godot/imported/MKX Title.ttf-512f7a6aab4653a1f1f61ada9d68c77a.fontdata"
[deps]
source_file="res://assets/fonts/MKX Title.ttf"
dest_files=["res://.godot/imported/MKX Title.ttf-512f7a6aab4653a1f1f61ada9d68c77a.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=1
subpixel_positioning=4
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}
+3 -4
View File
@@ -1,7 +1,6 @@
[gd_resource type="DynamicFont" load_steps=2 format=2] [gd_resource type="FontVariation" format=3 uid="uid://ehvxks08bpr"]
[ext_resource path="res://assets/fonts/MKX Title.ttf" type="DynamicFontData" id=1] [ext_resource type="FontFile" uid="uid://c7ps8q01ej5du" path="res://assets/fonts/MKX Title.ttf" id="1"]
[resource] [resource]
size = 30 base_font = ExtResource("1")
font_data = ExtResource( 1 )
@@ -0,0 +1,36 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://c1wk0en7c3mpr"
path="res://.godot/imported/kirsty bd it.otf-bc7aa29ac3e576434d66f4370e7210d1.fontdata"
[deps]
source_file="res://assets/fonts/kirsty/kirsty bd it.otf"
dest_files=["res://.godot/imported/kirsty bd it.otf-bc7aa29ac3e576434d66f4370e7210d1.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=1
subpixel_positioning=4
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}
+36
View File
@@ -0,0 +1,36 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://bgrwp4g3d0ywx"
path="res://.godot/imported/kirsty bd.otf-ca5d4e790ddf12f0b6904680ae840b34.fontdata"
[deps]
source_file="res://assets/fonts/kirsty/kirsty bd.otf"
dest_files=["res://.godot/imported/kirsty bd.otf-ca5d4e790ddf12f0b6904680ae840b34.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=1
subpixel_positioning=4
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}
@@ -0,0 +1,36 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://dsixnafr172kk"
path="res://.godot/imported/kirsty rg it.otf-c12188a557bf88ecddef6b02df5b15ad.fontdata"
[deps]
source_file="res://assets/fonts/kirsty/kirsty rg it.otf"
dest_files=["res://.godot/imported/kirsty rg it.otf-c12188a557bf88ecddef6b02df5b15ad.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=1
subpixel_positioning=4
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}
+36
View File
@@ -0,0 +1,36 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://c0gq63h6u1c0f"
path="res://.godot/imported/kirsty rg.otf-3775cb67524e1b791919a65fd2a6e3a1.fontdata"
[deps]
source_file="res://assets/fonts/kirsty/kirsty rg.otf"
dest_files=["res://.godot/imported/kirsty rg.otf-3775cb67524e1b791919a65fd2a6e3a1.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=1
subpixel_positioning=4
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}
+3 -5
View File
@@ -1,8 +1,6 @@
[gd_resource type="DynamicFont" load_steps=2 format=2] [gd_resource type="FontVariation" format=3 uid="uid://inv1rofq17xy"]
[ext_resource path="res://assets/fonts/kirsty/kirsty rg.otf" type="DynamicFontData" id=1] [ext_resource type="FontFile" uid="uid://c0gq63h6u1c0f" path="res://assets/fonts/kirsty/kirsty rg.otf" id="1"]
[resource] [resource]
use_mipmaps = true base_font = ExtResource("1")
use_filter = true
font_data = ExtResource( 1 )
+3 -6
View File
@@ -1,9 +1,6 @@
[gd_resource type="DynamicFont" load_steps=2 format=2] [gd_resource type="FontVariation" format=3 uid="uid://dxs8032ya4bwr"]
[ext_resource path="res://assets/fonts/kirsty/kirsty rg.otf" type="DynamicFontData" id=1] [ext_resource type="FontFile" uid="uid://c0gq63h6u1c0f" path="res://assets/fonts/kirsty/kirsty rg.otf" id="1"]
[resource] [resource]
size = 24 base_font = ExtResource("1")
use_mipmaps = true
use_filter = true
font_data = ExtResource( 1 )
+3 -6
View File
@@ -1,9 +1,6 @@
[gd_resource type="DynamicFont" load_steps=2 format=2] [gd_resource type="FontVariation" format=3 uid="uid://bqx3uv23bwjul"]
[ext_resource path="res://assets/fonts/kirsty/kirsty bd.otf" type="DynamicFontData" id=1] [ext_resource type="FontFile" uid="uid://bgrwp4g3d0ywx" path="res://assets/fonts/kirsty/kirsty bd.otf" id="1"]
[resource] [resource]
size = 46 base_font = ExtResource("1")
use_mipmaps = true
use_filter = true
font_data = ExtResource( 1 )

Some files were not shown because too many files have changed in this diff Show More