Showing preview only (730K chars total). Download the full file or copy to clipboard to get everything.
Repository: cloudwu/soluna
Branch: master
Commit: 59f5d0dc69a7
Files: 218
Total size: 673.5 KB
Directory structure:
gitextract_o983gujm/
├── .editorconfig
├── .github/
│ ├── actions/
│ │ ├── sample/
│ │ │ └── action.yml
│ │ └── soluna/
│ │ └── action.yml
│ └── workflows/
│ ├── nightly.yml
│ └── pages.yml
├── .gitignore
├── .gitmodules
├── LICENSE
├── Makefile
├── README.md
├── asset/
│ ├── sounds.dl
│ └── sprites.dl
├── clibs/
│ ├── datalist/
│ │ └── make.lua
│ ├── ltask/
│ │ └── make.lua
│ ├── lua/
│ │ └── make.lua
│ ├── sample/
│ │ └── make.lua
│ ├── soluna/
│ │ ├── compile_lua.lua
│ │ ├── compile_shader.lua
│ │ ├── make.lua
│ │ ├── runlua.lua
│ │ └── shader2c.lua
│ ├── yoga/
│ │ └── make.lua
│ └── zip/
│ └── make.lua
├── docs/
│ ├── app.lua
│ ├── args.lua
│ ├── callback.lua
│ ├── coroutine.lua
│ ├── crypt.lua
│ ├── datalist.lua
│ ├── file.lua
│ ├── font.lua
│ ├── font_system.lua
│ ├── image.lua
│ ├── layout.lua
│ ├── lfs.lua
│ ├── material_mask.lua
│ ├── material_quad.lua
│ ├── material_text.lua
│ ├── soluna.lua
│ ├── text.lua
│ ├── url.lua
│ └── zip.lua
├── extlua/
│ ├── extlua.c
│ ├── extlua.temp.c
│ ├── extlua_impl.c
│ ├── extlua_impl.temp.c
│ ├── extlua_sample.c
│ ├── gen.lua
│ ├── gen_sokol.lua
│ ├── gen_soluna.lua
│ ├── perspective_quad.glsl
│ ├── sokolapi.c
│ ├── sokolapi.temp.c
│ ├── sokolapi_impl.c
│ ├── sokolapi_impl.temp.c
│ ├── solunaapi.c
│ ├── solunaapi.h
│ ├── solunaapi.h.temp
│ ├── solunaapi.temp.c
│ ├── solunaapi_impl.c
│ └── solunaapi_impl.temp.c
├── make.lua
├── script/
│ ├── act.lua
│ ├── act_targets.lua
│ ├── compile_commands.lua
│ ├── datalist2c.lua
│ ├── hashversion.lua
│ └── lua2c.lua
├── src/
│ ├── appevent.h
│ ├── audio.c
│ ├── batch.c
│ ├── batch.h
│ ├── blit.glsl
│ ├── colorquad.glsl
│ ├── data/
│ │ └── settingdefault.dl
│ ├── drawmgr.c
│ ├── embedlua.c
│ ├── entry.c
│ ├── extapi.c
│ ├── extapi_types.h
│ ├── extapi_types.temp.h
│ ├── external.c
│ ├── file.c
│ ├── font.c
│ ├── font_define.h
│ ├── font_manager.c
│ ├── font_manager.h
│ ├── font_system.c
│ ├── gamepad.c
│ ├── image.c
│ ├── ime_char_filter.h
│ ├── ime_state.h
│ ├── lcrypt.c
│ ├── lfs.c
│ ├── loginfo.h
│ ├── lsha1.c
│ ├── luabuffer.h
│ ├── lualib/
│ │ ├── coroutine.lua
│ │ ├── fontmgr.lua
│ │ ├── icon.lua
│ │ ├── initsetting.lua
│ │ ├── layout.lua
│ │ ├── main.lua
│ │ ├── packageloader.lua
│ │ ├── print_r.lua
│ │ ├── soluna.lua
│ │ ├── spritebundle.lua
│ │ ├── text.lua
│ │ └── util.lua
│ ├── luamods.c
│ ├── luayoga.c
│ ├── luazip.c
│ ├── maskquad.glsl
│ ├── material/
│ │ ├── matdefault.lua
│ │ ├── matmask.lua
│ │ ├── matquad.lua
│ │ └── mattext.lua
│ ├── material_blit.c
│ ├── material_default.c
│ ├── material_mask.c
│ ├── material_quad.c
│ ├── material_text.c
│ ├── material_util.c
│ ├── material_util.h
│ ├── mutex.h
│ ├── openlibs.c
│ ├── openurl.c
│ ├── platform/
│ │ ├── linux/
│ │ │ ├── soluna_linux_ime.c
│ │ │ └── soluna_linux_ime.h
│ │ ├── macos/
│ │ │ ├── soluna_macos_ime.h
│ │ │ └── soluna_macos_ime.m
│ │ ├── wasm/
│ │ │ ├── soluna_ime.js
│ │ │ ├── soluna_openurl.js
│ │ │ └── soluna_wasm_ime.h
│ │ └── windows/
│ │ ├── soluna_windows_ime.c
│ │ └── soluna_windows_ime.h
│ ├── render.c
│ ├── render_bindings.c
│ ├── render_bindings.h
│ ├── render_uniform.c
│ ├── sdfimage.c
│ ├── sdftext.glsl
│ ├── service/
│ │ ├── audio.lua
│ │ ├── gamepad.lua
│ │ ├── loader.lua
│ │ ├── log.lua
│ │ ├── render.lua
│ │ ├── settings.lua
│ │ └── start.lua
│ ├── sprite_submit.h
│ ├── spritemgr.c
│ ├── spritemgr.h
│ ├── srbuffer.c
│ ├── srbuffer.h
│ ├── texquad.glsl
│ ├── tmpbuffer.h
│ ├── transform.c
│ ├── transform.h
│ ├── truetype.c
│ ├── truetype.h
│ ├── version.h
│ ├── winfile.c
│ ├── writelog.c
│ ├── yogaone.cpp
│ └── zipreader.h
├── test/
│ ├── audio.game
│ ├── audio.lua
│ ├── bundle.lua
│ ├── extlua/
│ │ └── material/
│ │ └── perspective_quad.lua
│ ├── extlua.game
│ ├── extlua.lua
│ ├── file.lua
│ ├── hello.game
│ ├── hello.lua
│ ├── icon.lua
│ ├── image.lua
│ ├── ime.lua
│ ├── intersect.lua
│ ├── layout.lua
│ ├── mask.lua
│ ├── mtex.game
│ ├── mtex.lua
│ ├── setting.lua
│ ├── sprite.lua
│ ├── spritepack.lua
│ ├── test.lua
│ ├── text.lua
│ ├── version.lua
│ ├── window.game
│ └── window.lua
└── website/
├── README.md
├── README.zh-CN.md
├── astro.config.mjs
├── eslint.config.mjs
├── package.json
├── packages/
│ └── astro-theme-soluna/
│ ├── package.json
│ └── src/
│ ├── client/
│ │ └── play.ts
│ ├── components/
│ │ ├── Footer.astro
│ │ ├── Hero.astro
│ │ ├── Menubar.astro
│ │ ├── Nav.astro
│ │ ├── PlainList.astro
│ │ ├── Section.astro
│ │ ├── docs/
│ │ │ └── DocsPage.astro
│ │ └── examples/
│ │ ├── ExampleListPage.astro
│ │ └── ExamplePlayPage.astro
│ ├── layouts/
│ │ └── BaseLayout.astro
│ └── styles/
│ └── theme.css
├── pnpm-workspace.yaml
├── scripts/
│ └── prepare-runtime.mjs
├── src/
│ ├── content.config.ts
│ ├── lib/
│ │ ├── content.ts
│ │ └── readme.ts
│ └── pages/
│ ├── docs/
│ │ └── index.astro
│ ├── examples/
│ │ ├── [id].astro
│ │ └── index.astro
│ └── index.astro
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# see https://github.com/CppCXY/EmmyLuaCodeStyle
[*.lua]
max_line_length = 120
end_of_line = lf
indent_style = tab
indent_size = 4
quote_style = double
call_arg_parentheses = remove
auto_collapse_lines = false
================================================
FILE: .github/actions/sample/action.yml
================================================
name: Build Sample WASM
description: Build sample.wasm side module for Soluna web runtime
inputs:
soluna_path:
description: "The path to the Soluna repository. Defaults to ."
required: false
default: "."
luamake_version:
description: "LuaMake commit SHA used to build."
required: false
default: "5bedfce66f075a9f68b1475747738b81b3b41c25"
emsdk_version:
description: "Emscripten SDK version."
required: false
default: "4.0.17"
outputs:
SAMPLE_WASM_PATH:
description: "The path to built sample.wasm side module."
value: ${{ steps.set-output.outputs.SAMPLE_WASM_PATH }}
runs:
using: "composite"
steps:
- name: Get the soluna commit
id: refs
working-directory: ${{ inputs.soluna_path }}
shell: bash
run: |
echo "commit=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
- name: Cache sample wasm build
uses: actions/cache@v4
id: cache
with:
path: |
${{ inputs.soluna_path }}/bin
${{ inputs.soluna_path }}/build
key: ${{ runner.os }}-sample-wasm-${{ steps.refs.outputs.commit }}-${{ inputs.luamake_version }}-${{ inputs.emsdk_version }}
- name: Checkout all submodules
if: steps.cache.outputs.cache-hit != 'true'
working-directory: ${{ inputs.soluna_path }}
shell: bash
run: |
git submodule update --init --recursive
- name: Setup LuaMake
if: steps.cache.outputs.cache-hit != 'true'
uses: yuchanns/actions-luamake@v1
with:
luamake-version: ${{ inputs.luamake_version }}
- name: Setup Emscripten
if: runner.os == 'Linux' && steps.cache.outputs.cache-hit != 'true'
uses: mymindstorm/setup-emsdk@v14
with:
version: ${{ inputs.emsdk_version }}
actions-cache-folder: 'emsdk-cache'
- name: Build sample side module
if: runner.os == 'Linux' && steps.cache.outputs.cache-hit != 'true'
shell: bash
working-directory: ${{ inputs.soluna_path }}
run: |
luamake -compiler emcc sample
- name: Set output
id: set-output
shell: bash
working-directory: ${{ inputs.soluna_path }}
run: |
soluna_root=$(pwd -P)
SAMPLE_WASM_PATH=$(find "$soluna_root/bin" -name "sample.wasm" | head -n 1)
if [ -z "$SAMPLE_WASM_PATH" ]; then
echo "sample.wasm not found" >&2
exit 1
fi
echo "SAMPLE_WASM_PATH=$SAMPLE_WASM_PATH" >> "$GITHUB_OUTPUT"
================================================
FILE: .github/actions/soluna/action.yml
================================================
name: Build Soluna
description: Build Soluna for different operating systems
inputs:
soluna_path:
description: 'The path to the Soluna repository. Defaults to .'
required: false
default: '.'
debug:
description: 'Whether to build Soluna in debug mode. Defaults to false.'
required: false
default: 'false'
outputs:
SOLUNA_BINARY:
description: 'The name of the built Soluna binary.'
value: ${{ steps.set-output.outputs.SOLUNA_BINARY }}
SOLUNA_PATH:
description: 'The path to the built Soluna binary.'
value: ${{ steps.set-output.outputs.SOLUNA_PATH }}
SOLUNA_WASM_PATH:
description: 'The path to the built Soluna WebAssembly binary.'
value: ${{ steps.set-output.outputs.SOLUNA_WASM_PATH }}
SOLUNA_JS_PATH:
description: 'The path to the Soluna JavaScript glue code for WebAssembly.'
value: ${{ steps.set-output.outputs.SOLUNA_JS_PATH }}
SOLUNA_WASM_MAP_PATH:
description: 'The path to the built Soluna WebAssembly map if debug is true.'
value: ${{ steps.set-output.outputs.SOLUNA_WASM_MAP_PATH }}
runs:
using: "composite"
steps:
- name: Get the soluna commit
id: refs
working-directory: ${{ inputs.soluna_path }}
run: |
echo "commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
shell: bash
- name: Cache soluna build
uses: actions/cache@v4
id: cache
with:
path: ${{ inputs.soluna_path }}/bin
key: ${{ runner.os }}-soluna-build-${{ steps.refs.outputs.commit }}-${{ inputs.debug }}
- name: Checkout all submodules
if: steps.cache.outputs.cache-hit != 'true'
working-directory: ${{ inputs.soluna_path }}
run: |
git submodule update --init --recursive
shell: bash
- uses: yuchanns/actions-luamake@v1
if: steps.cache.outputs.cache-hit != 'true'
with:
luamake-version: "5bedfce66f075a9f68b1475747738b81b3b41c25"
- name: Install Dependencies (Linux)
shell: bash
if: runner.os == 'Linux' && steps.cache.outputs.cache-hit != 'true'
run: |
sudo apt-get update
sudo apt-get install -y build-essential \
libgl1-mesa-dev libglu1-mesa-dev libx11-dev \
libxrandr-dev libxi-dev libxxf86vm-dev libxcursor-dev \
libasound2-dev libfontconfig1-dev
- name: Build (Windows)
if: runner.os == 'Windows' && steps.cache.outputs.cache-hit != 'true'
shell: powershell
working-directory: ${{ inputs.soluna_path }}
run: |
if (${{ inputs.debug }} -eq 'true') {
$env:LUAMAKE_BUILD_TYPE = 'debug'
} else {
$env:LUAMAKE_BUILD_TYPE = 'release'
}
luamake -mode $env:LUAMAKE_BUILD_TYPE soluna
- name: Build (Unix)
if: runner.os != 'Windows' && steps.cache.outputs.cache-hit != 'true'
shell: bash
working-directory: ${{ inputs.soluna_path }}
run: |
if [ "${{ inputs.debug }}" == "true" ]; then
export LUAMAKE_BUILD_TYPE=debug
else
export LUAMAKE_BUILD_TYPE=release
fi
luamake -mode $LUAMAKE_BUILD_TYPE soluna
- uses: mymindstorm/setup-emsdk@v14
if: runner.os == 'Linux' && steps.cache.outputs.cache-hit != 'true'
with:
version: 4.0.17
actions-cache-folder: 'emsdk-cache'
- name: Build Emscripten
if: runner.os == 'Linux' && steps.cache.outputs.cache-hit != 'true'
working-directory: ${{ inputs.soluna_path }}
shell: bash
run: |
if [ "${{ inputs.debug }}" == "true" ]; then
export LUAMAKE_BUILD_TYPE=debug
else
export LUAMAKE_BUILD_TYPE=release
fi
luamake -mode $LUAMAKE_BUILD_TYPE -compiler emcc
SOLUNA_JS="soluna.js"
SOLUNA_JS_PATH=$(find bin -name $SOLUNA_JS | head -n 1)
sed -i 's/setBindGroup(groupIndex,group,(growMemViews(),HEAPU32),dynamicOffsetsPtr>>2,dynamicOffsetCount)/setBindGroup(groupIndex,group,(growMemViews(),HEAPU32).subarray(dynamicOffsetsPtr>>2,(dynamicOffsetsPtr>>2)+dynamicOffsetCount))/g' "$SOLUNA_JS_PATH"
sed -i 's/setBindGroup(groupIndex, group, (growMemViews(), HEAPU32), ((dynamicOffsetsPtr) >> 2), dynamicOffsetCount)/setBindGroup(groupIndex, group, (growMemViews(), HEAPU32).subarray(((dynamicOffsetsPtr) >> 2), ((dynamicOffsetsPtr) >> 2) + dynamicOffsetCount))/g' "$SOLUNA_JS_PATH"
perl -0pi -e 's/var group=WebGPU\.getJsObject\(groupPtr\);if\(dynamicOffsetCount==0\)\{pass\.setBindGroup\(groupIndex,group\)\}else\{pass\.setBindGroup\(groupIndex,group,\(growMemViews\(\),HEAPU32\)\.subarray\(dynamicOffsetsPtr>>2,\(dynamicOffsetsPtr>>2\)\+dynamicOffsetCount\)\)\}/var group=WebGPU.getJsObject(groupPtr);if(!group){return}if(dynamicOffsetCount==0){pass.setBindGroup(groupIndex,group)}else{pass.setBindGroup(groupIndex,group,(growMemViews(),HEAPU32).subarray(dynamicOffsetsPtr>>2,(dynamicOffsetsPtr>>2)+dynamicOffsetCount))}/g' "$SOLUNA_JS_PATH"
perl -0pi -e 's/var group = WebGPU\.getJsObject\(groupPtr\);\n if \(dynamicOffsetCount == 0\) \{\n pass\.setBindGroup\(groupIndex, group\);\n \} else \{\n pass\.setBindGroup\(groupIndex, group, \(growMemViews\(\), HEAPU32\)\.subarray\(\(\(dynamicOffsetsPtr\) >> 2\), \(\(dynamicOffsetsPtr\) >> 2\) \+ dynamicOffsetCount\)\);\n \}/var group = WebGPU.getJsObject(groupPtr);\n if (!group) {\n return;\n }\n if (dynamicOffsetCount == 0) {\n pass.setBindGroup(groupIndex, group);\n } else {\n pass.setBindGroup(groupIndex, group, (growMemViews(), HEAPU32).subarray(((dynamicOffsetsPtr) >> 2), ((dynamicOffsetsPtr) >> 2) + dynamicOffsetCount));\n }/g' "$SOLUNA_JS_PATH"
if grep -Fq 'setBindGroup(groupIndex,group,(growMemViews(),HEAPU32),dynamicOffsetsPtr>>2,dynamicOffsetCount)' "$SOLUNA_JS_PATH" || \
grep -Fq 'setBindGroup(groupIndex, group, (growMemViews(), HEAPU32), ((dynamicOffsetsPtr) >> 2), dynamicOffsetCount)' "$SOLUNA_JS_PATH"; then
echo "Unpatched WebGPU setBindGroup glue remains in $SOLUNA_JS_PATH" >&2
exit 1
fi
- name: Set Output Build Path
id: set-output
run: |
soluna_root=$(cd "${{ inputs.soluna_path }}" && pwd -P)
if [ "${{ runner.os }}" == "Windows" ]; then
soluna_root_output=$(cd "${{ inputs.soluna_path }}" && pwd -W | sed 's#\\#/#g')
else
soluna_root_output="$soluna_root"
fi
bin_dir="$soluna_root/bin"
bin_dir_output="$soluna_root_output/bin"
if [ "${{ runner.os }}" == "Windows" ]; then
SOLUNA_BINARY="soluna.exe"
RENAME_BINARY="soluna-windows-amd64.exe"
elif [ "${{ runner.os }}" == "macOS" ]; then
SOLUNA_BINARY="soluna"
RENAME_BINARY="soluna-macos-arm64"
else
SOLUNA_BINARY="soluna"
RENAME_BINARY="soluna-linux-amd64"
fi
SOLUNA_PATH=$(find "$bin_dir" -name "$SOLUNA_BINARY" | head -n 1)
cp "$SOLUNA_PATH" "$bin_dir/$RENAME_BINARY"
echo "SOLUNA_PATH=$bin_dir_output/$RENAME_BINARY" >> $GITHUB_OUTPUT
echo "SOLUNA_BINARY=$RENAME_BINARY" >> $GITHUB_OUTPUT
if [ "${{ runner.os }}" == "Linux" ]; then
SOLUNA_WASM_PATH=$(find "$bin_dir" -name "soluna.wasm" | head -n 1)
SOLUNA_JS_PATH=$(find "$bin_dir" -name "soluna.js" | head -n 1)
echo "SOLUNA_WASM_PATH=$SOLUNA_WASM_PATH" >> $GITHUB_OUTPUT
echo "SOLUNA_JS_PATH=$SOLUNA_JS_PATH" >> $GITHUB_OUTPUT
if [ "${{ inputs.debug }}" == "true" ]; then
SOLUNA_WASM_MAP_PATH=$(find "$bin_dir" -name "soluna.wasm.map" | head -n 1)
echo "SOLUNA_WASM_MAP_PATH=$SOLUNA_WASM_MAP_PATH" >> $GITHUB_OUTPUT
fi
fi
shell: bash
================================================
FILE: .github/workflows/nightly.yml
================================================
name: Nightly Build
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_dispatch:
schedule:
- cron: '0 0 * * *' # Runs every day at midnight UTC
jobs:
check:
name: Determine Build Necessity
runs-on: ubuntu-latest
outputs:
proceed: ${{ steps.check.outputs.proceed }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Get the last nightly commit
id: last_nightly
uses: actions/github-script@v7
with:
script: |
const releases = await github.rest.repos.listReleases({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100
});
const nightlyRelease = releases.data.find(release => release.tag_name.includes('nightly') || release.name.includes('Nightly'));
if (nightlyRelease) {
const tagName = nightlyRelease.tag_name;
const tag = await github.rest.git.getRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `tags/${tagName}`
});
const commitSha = tag.data.object.sha;
return commitSha;
} else {
return null;
}
- name: Check the proceed condition
id: check
run: |
LAST_NIGHTLY_COMMIT="${{ steps.last_nightly.outputs.result }}"
CURRENT_COMMIT="${GITHUB_SHA}"
echo "Last nightly commit: $LAST_NIGHTLY_COMMIT"
echo "Current commit: $CURRENT_COMMIT"
if [ -z "$LAST_NIGHTLY_COMMIT" ]; then
echo "No previous nightly release found. Proceeding with build."
echo "proceed=true" >> $GITHUB_OUTPUT
elif [ "$LAST_NIGHTLY_COMMIT" != "$CURRENT_COMMIT" ]; then
echo "New commits found since last nightly release. Proceeding with build."
echo "proceed=true" >> $GITHUB_OUTPUT
else
echo "No new commits since last nightly release. Skipping build."
echo "proceed=false" >> $GITHUB_OUTPUT
fi
build:
name: Nightly Build on ${{ matrix.os }}
needs: check
if: needs.check.outputs.proceed == 'true'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-latest, macos-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- uses: ./.github/actions/soluna
name: Build
id: build
with:
soluna_path: "."
- uses: actions/upload-artifact@v4
name: Upload
if: github.event_name == 'workflow_dispatch' || github.event_name == 'schedule'
with:
name: "soluna-${{ runner.os }}-${{ steps.build.outputs.SOLUNA_BINARY }}"
if-no-files-found: "error"
path: "${{ steps.build.outputs.SOLUNA_PATH }}"
overwrite: "true"
- uses: actions/upload-artifact@v4
name: Upload Emscripten
if: (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule') && runner.os == 'Linux'
with:
name: "soluna-emscripten"
if-no-files-found: "error"
overwrite: "true"
path: |
${{ steps.build.outputs.SOLUNA_WASM_PATH }}
${{ steps.build.outputs.SOLUNA_JS_PATH }}
release:
name: Create Nightly Release
needs: [check, build]
runs-on: ubuntu-latest
if: (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule') && github.actor != 'nektos/act'
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- name: Download all artifacts
uses: actions/download-artifact@v5
with:
path: artifacts
- name: Prepare release assets
run: |
mkdir -p release-assets
find artifacts -type f -name "soluna*" -exec cp {} release-assets/ \;
ls -la release-assets/
- name: Delete existing nightly releases
uses: actions/github-script@v7
with:
script: |
const releases = await github.rest.repos.listReleases({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100
});
for (const release of releases.data) {
if (release.tag_name.includes('nightly') || release.name.includes('Nightly')) {
console.log(`Deleting release: ${release.tag_name}`);
try {
await github.rest.repos.deleteRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: release.id
});
try {
await github.rest.git.deleteRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `tags/${release.tag_name}`
});
} catch (error) {
console.log(`Tag ${release.tag_name} might not exist or already deleted`);
}
} catch (error) {
console.log(`Failed to delete release ${release.tag_name}: ${error.message}`);
}
}
}
- name: Create nightly release
id: create-release
uses: actions/github-script@v7
with:
script: |
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
const commitSha = context.sha.substring(0, 7);
const tagName = 'nightly';
const releaseNotes = `🌙 **Nightly Build**
**Build Information:**
- **Commit:** \`${context.sha}\`
- **Branch:** \`${context.ref.replace('refs/heads/', '')}\`
- **Build Time:** \`${new Date().toISOString()}\`
- **Workflow:** [${context.runId}](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})
> ⚠️ **Note:** This is an automated nightly build. It may contain unstable features and bugs.
>
> 📦 **Previous nightly releases are automatically removed to keep the repository clean.**`;
const { data } = await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name: tagName,
name: `Nightly Build (${timestamp})`,
body: releaseNotes,
prerelease: true,
make_latest: 'true',
draft: false,
});
console.log(`Created release: ${data.html_url}`);
return data.id;
- name: Upload release assets
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
const releaseId = ${{ steps.create-release.outputs.result }};
const assetsDir = 'release-assets';
const files = fs.readdirSync(assetsDir);
for (const file of files) {
const filePath = path.join(assetsDir, file);
const stats = fs.statSync(filePath);
if (stats.isFile()) {
console.log(`Uploading ${file}...`);
const content = fs.readFileSync(filePath);
await github.rest.repos.uploadReleaseAsset({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: releaseId,
name: file,
data: content
});
console.log(`Uploaded ${file}`);
}
}
================================================
FILE: .github/workflows/pages.yml
================================================
name: GitHub Pages
on:
workflow_run:
workflows:
- Nightly Build
types:
- completed
branches:
- master
workflow_dispatch:
inputs:
debug:
description: 'Whether to build in debug mode'
required: false
default: 'false'
jobs:
build:
name: Build Web Site
if: |
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
runs-on: ubuntu-latest
concurrency:
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.ref }}
permissions:
contents: read
pages: write
id-token: write
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
fetch-depth: 0
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
- name: Build Soluna
uses: ./.github/actions/soluna
id: build
with:
soluna_path: "."
debug: ${{ github.event.inputs.debug }}
- name: Build Sample
uses: ./.github/actions/sample
id: sample
with:
soluna_path: "."
- name: Build Astro
uses: withastro/action@v6
env:
SITE_BASE: /soluna/
SOLUNA_JS_PATH: ${{ steps.build.outputs.SOLUNA_JS_PATH }}
SOLUNA_WASM_PATH: ${{ steps.build.outputs.SOLUNA_WASM_PATH }}
SOLUNA_WASM_MAP_PATH: ${{ steps.build.outputs.SOLUNA_WASM_MAP_PATH }}
SAMPLE_WASM_PATH: ${{ steps.sample.outputs.SAMPLE_WASM_PATH }}
with:
path: website
node-version: 24
package-manager: pnpm@10.28.2
build-cmd: pnpm run build
out-dir: dist
deploy:
name: Deploy to GitHub Pages
if: |
(github.event_name == 'workflow_dispatch' ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')) &&
github.actor != 'nektos/act'
needs: [build]
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
================================================
FILE: .gitignore
================================================
bin
build
compile_commands.json
.cache
node_modules
.pnpm-store
pnpm-debug.log*
website/node_modules
website/packages/*/node_modules
website/dist
website/.astro
website/public/runtime/
================================================
FILE: .gitmodules
================================================
[submodule "3rd/ltask"]
path = 3rd/ltask
url = https://github.com/cloudwu/ltask.git
[submodule "3rd/sokol"]
path = 3rd/sokol
url = https://github.com/floooh/sokol.git
[submodule "3rd/lua"]
path = 3rd/lua
url = https://github.com/lua/lua.git
[submodule "3rd/stb"]
path = 3rd/stb
url = https://github.com/nothings/stb.git
[submodule "3rd/datalist"]
path = 3rd/datalist
url = https://github.com/cloudwu/datalist.git
[submodule "3rd/yoga"]
path = 3rd/yoga
url = https://github.com/facebook/yoga.git
[submodule "3rd/zlib"]
path = 3rd/zlib
url = https://github.com/madler/zlib.git
[submodule "bin/sokol-tools-bin"]
path = bin/sokol-tools-bin
url = https://github.com/floooh/sokol-tools-bin.git
[submodule "3rd/miniaudio"]
path = 3rd/miniaudio
url = https://github.com/mackron/miniaudio.git
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2025 codingnow.com
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.
================================================
FILE: Makefile
================================================
.PHONY : all clean shader extlua_sample
BUILD=build
BIN=bin
APPNAME=soluna.exe
CC?=gcc
# msvc support
#CC=cl
LD=$(CC)
LUA_EXE=$(BUILD)/lua.exe
SHDC=$(BIN)/sokol-tools-bin/bin/win32/sokol-shdc.exe
VERSION=$(shell git rev-parse HEAD)
#for msvc
ifeq ($(CC),cl)
CCPP=cl
CFLAGS=-utf-8 -W3 -O2
OUTPUT_O=-c -Fo:
OUTPUT_EXE=-Fe:
STDC=-std:c11 -experimental:c11atomics
STDCPP=-std:c++20
SUBSYSTEM=-LINK -SUBSYSTEM:WINDOWS -ENTRY:"mainCRTStartup"
LDFLAGS=$(SUBSYSTEM) xinput.lib Ws2_32.lib ntdll.lib Imm32.lib
SHARED=-LD
else
CCPP=g++
CFLAGS=-Wall -O2
OUTPUT_O=-c -o
OUTPUT_EXE=-o
STDC=-std=c99 -lm
STDCPP=-std=c++20
SUBSYSTEM=-Wl,-subsystem,windows
LDFLAGS=-lkernel32 -luser32 -lshell32 -lgdi32 -ldxgi -ld3d11 -lwinmm -lws2_32 -lntdll -lxinput -limm32 -lstdc++ $(SUBSYSTEM)
SHARED=--shared
endif
all : $(BIN)/$(APPNAME)
3RDINC=-I3rd
YOGAINC=-I3rd/yoga
MINIAUDIOINC=-I3rd/miniaudio
LUAINC=-I3rd/lua
LUASRC:=$(wildcard 3rd/lua/*.c 3rd/lua/*.h)
WINFILE:=src/winfile.c
$(LUA_EXE) : $(LUASRC) $(WINFILE)
$(CC) $(CFLAGS) -o $@ 3rd/lua/onelua.c $(WINFILE) -DMAKE_LUA -Dfopen=fopen_utf8
COMPILE_C=$(CC) $(CFLAGS) $(STDC) $(OUTPUT_O) $@ $<
COMPILE_LUA=$(LUA_EXE) script/lua2c.lua $< $@
COMPILE_DATALIST=$(LUA_EXE) script/datalist2c.lua $< $@
LUA_O=$(BUILD)/onelua.o
$(LUA_O) : $(LUASRC)
$(CC) $(CFLAGS) $(OUTPUT_O) $@ 3rd/lua/onelua.c -DMAKE_LIB -Dfopen=fopen_utf8
SHADER_SRC=$(wildcard src/*.glsl)
SHADER_O=$(patsubst src/%.glsl,$(BUILD)/%.glsl.h,$(SHADER_SRC))
EXTLUA_SHADER_SRC=$(wildcard extlua/*.glsl)
EXTLUA_SHADER_O=$(patsubst extlua/%.glsl,$(BUILD)/%.glsl.h,$(EXTLUA_SHADER_SRC))
SHADERINC=-I$(BUILD)
$(BUILD)/%.glsl.h : src/%.glsl
$(SHDC) --input $< --output $@ --slang hlsl4 --format sokol
$(BUILD)/%.glsl.h : extlua/%.glsl
$(SHDC) --input $< --output $@ --slang hlsl4 --format sokol
shader : $(SHADER_O) $(EXTLUA_SHADER_O)
MAIN_FULL=$(wildcard src/*.c)
PLATFORM_FULL=$(wildcard src/platform/windows/*.c)
MAIN_C=$(notdir $(MAIN_FULL))
MAIN_O=$(patsubst %.c,$(BUILD)/soluna_%.o,$(MAIN_C))
PLATFORM_C=$(notdir $(PLATFORM_FULL))
PLATFORM_O=$(patsubst %.c,$(BUILD)/platform_%.o,$(PLATFORM_C))
EXTLUA_O=$(BUILD)/extlua_impl.o $(BUILD)/sokolapi_impl.o $(BUILD)/solunaapi_impl.o
$(MAIN_O) : $(SHADER_O)
LTASK_FULL=$(wildcard 3rd/ltask/src/*.c)
LTASK_C=$(notdir $(LTASK_FULL))
LTASK_O=$(patsubst %.c,$(BUILD)/ltask_%.o,$(LTASK_C))
LTASK_LUASRC=\
3rd/ltask/service/root.lua\
3rd/ltask/service/timer.lua\
$(wildcard 3rd/ltask/lualib/*.lua src/lualib/*.lua src/service/*.lua src/material/*.lua)
LTASK_LUACODE=$(patsubst %.lua, $(BUILD)/%.lua.h, $(notdir $(LTASK_LUASRC)))
DATALIST_SRC=$(wildcard src/data/*.dl)
DATALIST_CODE=$(patsubst %.dl, $(BUILD)/%.dl.h, $(notdir $(DATALIST_SRC)))
ZLIBINC=-I3rd/zlib
ZLIB_FULL=$(wildcard 3rd/zlib/*.c)
ZLIB_C = $(notdir $(ZLIB_FULL))
ZLIB_O = $(patsubst %.c,$(BUILD)/zlib_%.o,$(ZLIB_C))
MINIZIP_FULL=\
3rd\zlib\contrib/minizip/ioapi.c\
3rd\zlib\contrib/minizip/unzip.c\
3rd\zlib\contrib/minizip/zip.c\
3rd\zlib\contrib/minizip/iowin32.c
MINIZIP_C = $(notdir $(MINIZIP_FULL))
MINIZIP_O = $(patsubst %.c,$(BUILD)/minizip_%.o,$(MINIZIP_C))
$(LTASK_LUACODE) $(DATALIST_CODE) : | $(LUA_EXE)
$(BUILD)/%.lua.h : 3rd/ltask/service/%.lua
$(COMPILE_LUA)
$(BUILD)/%.lua.h : 3rd/ltask/lualib/%.lua
$(COMPILE_LUA)
$(BUILD)/%.lua.h : src/lualib/%.lua
$(COMPILE_LUA)
$(BUILD)/%.lua.h : src/service/%.lua
$(COMPILE_LUA)
$(BUILD)/%.lua.h : src/material/%.lua
$(COMPILE_LUA)
$(BUILD)/%.dl.h : src/data/%.dl
$(COMPILE_DATALIST)
$(BUILD)/soluna_embedlua.o : src/embedlua.c $(LTASK_LUACODE) $(DATALIST_CODE)
$(COMPILE_C) -I$(BUILD) $(LUAINC)
$(BUILD)/soluna_entry.o : src/entry.c src/version.h
$(COMPILE_C) $(LUAINC) $(3RDINC) -DSOLUNA_HASH_VERSION=\"$(VERSION)\"
$(BUILD)/soluna_%.o : src/%.c
$(COMPILE_C) $(LUAINC) $(3RDINC) $(SHADERINC) $(YOGAINC) $(ZLIBINC) $(MINIAUDIOINC)
$(BUILD)/platform_%.o : src/platform/windows/%.c
$(COMPILE_C) $(LUAINC) $(3RDINC) $(SHADERINC) $(YOGAINC) $(ZLIBINC) -Isrc
$(BUILD)/ltask_%.o : 3rd/ltask/src/%.c
$(COMPILE_C) $(LUAINC) -D_WIN32_WINNT=0x0601 -DLTASK_EXTERNAL_OPENLIBS=soluna_openlibs
DATALIST_O=$(BUILD)/datalist.o
$(DATALIST_O) : 3rd/datalist/datalist.c
$(COMPILE_C) $(LUAINC)
YOGASRC:=$(wildcard 3rd/yoga/yoga/*.cpp $(addsuffix *.cpp,$(wildcard 3rd/yoga/yoga/*/)))
$(BUILD)/yoga.o : src/yogaone.cpp $(YOGASRC)
$(CCPP) $(STDCPP) $(OUTPUT_O) $@ $< $(YOGAINC) $(CFLAGS)
$(BUILD)/zlib_%.o : 3rd/zlib/%.c
$(COMPILE_C) $(ZLIBINC)
$(BUILD)/minizip_%.o : 3rd/zlib/contrib/minizip/%.c
$(COMPILE_C) $(ZLIBINC)
$(BUILD)/extlua_impl.o : extlua/extlua_impl.c
$(COMPILE_C) $(LUAINC)
$(BUILD)/sokolapi_impl.o : extlua/sokolapi_impl.c
$(COMPILE_C) $(3RDINC)
$(BUILD)/solunaapi_impl.o : extlua/solunaapi_impl.c
$(COMPILE_C) $(LUAINC) $(3RDINC)
$(BIN)/$(APPNAME): $(MAIN_O) $(PLATFORM_O) $(EXTLUA_O) $(LTASK_O) $(LUA_O) $(DATALIST_O) $(BUILD)/yoga.o $(ZLIB_O) $(MINIZIP_O)
$(LD) $(OUTPUT_EXE) $@ $^ $(LDFLAGS)
$(BIN)/sample.dll : extlua/extlua.c extlua/sokolapi.c extlua/solunaapi.c extlua/extlua_sample.c | $(EXTLUA_SHADER_O)
$(CC) $(CFLAGS) $(SHARED) $(OUTPUT_EXE) $@ $^ $(LUAINC) $(3RDINC) $(SHADERINC) -Iextlua
extlua_sample: $(BIN)/sample.dll
clean :
rm -f $(BIN)/*.exe $(BIN)/*.dll $(BUILD)/*.o $(BUILD)/*.h
================================================
FILE: README.md
================================================
<div align="center">
Sokol + Lua = Soluna
</div>
# Soluna
[Live Examples / 在线示例](https://cloudwu.github.io/soluna/)
Soluna is a 2D game framework for Lua. It is built on top of [sokol](https://github.com/floooh/sokol), integrates ltask for multithreading, and runs on Windows, Linux, macOS, and modern browsers through WebAssembly.
Soluna 是一个 Lua 2D 游戏框架。它基于 [sokol](https://github.com/floooh/sokol),整合 ltask 作为多线程框架,可运行在 Windows、Linux、macOS 以及通过 WebAssembly 支持的现代浏览器中。
[](/../../actions/workflows/nightly.yml)
## Documentation / 文档
- [API Reference / API 参考](./docs)
- [Examples / 示例](./test)
- [Wiki](https://github.com/cloudwu/soluna/wiki)
## Precompiled Binaries / 预编译二进制文件
Precompiled binaries for Windows, Linux, macOS, and WebAssembly are available from [Nightly Releases](/../../releases/tag/nightly).
Windows、Linux、macOS 和 WebAssembly 的预编译二进制文件可从 [Nightly Releases](/../../releases/tag/nightly) 下载。
## Building from Source / 从源码构建
Soluna can be built with `make` on Windows and with `luamake` on all supported platforms. The GitHub Action in [`.github/actions/soluna`](./.github/actions/soluna) shows the exact CI build flow.
Soluna 可在 Windows 上通过 `make` 构建,也可在所有支持平台上通过 `luamake` 构建。[`.github/actions/soluna`](./.github/actions/soluna) 展示了 CI 使用的完整构建流程。
### GitHub Actions Integration / GitHub Actions 集成
```yaml
- uses: actions/checkout@v6
with:
repository: cloudwu/soluna
ref: <a fixed commit hash to avoid breaking changes>
path: soluna
submodules: recursive
- uses: ./soluna/.github/actions/soluna
id: soluna
with:
soluna_path: soluna
- run: |
echo "Soluna binary is at ${{ steps.soluna.outputs.SOLUNA_PATH }}"
echo "Soluna WASM binary is at ${{ steps.soluna.outputs.SOLUNA_WASM_PATH }}"
echo "Soluna js glue is at ${{ steps.soluna.outputs.SOLUNA_JS_PATH }}"
```
## Local Website Build / 本地构建与运行网站
The website is an Astro app in `website/`. It renders the homepage from this README, generates API pages from `docs/`, and builds live example pages from `test/`.
网站是位于 `website/` 目录的 Astro 应用。它使用本 README 生成首页,从 `docs/` 生成 API 页面,并从 `test/` 生成在线示例页面。
Build the WebAssembly runtime from the repository root first:
先在仓库根目录构建 WebAssembly runtime:
```bash
luamake -compiler emcc
luamake -compiler emcc sample
```
Then install dependencies and start the local dev server:
然后安装依赖并启动本地开发服务器:
```bash
cd website
pnpm install
pnpm run dev
```
## Projects Made with Soluna / 使用 Soluna 制作的项目
- [Deep Future](https://github.com/cloudwu/deepfuture), a digital version of the board game Deep Future. / 电子版桌游《深远未来》。
## License / 许可证
Soluna is licensed under the MIT License. See [LICENSE](./LICENSE) for details.
Soluna 使用 MIT 许可证。详情见 [LICENSE](./LICENSE)。
================================================
FILE: asset/sounds.dl
================================================
--
name : bloop
filename : asset/sounds/bloop_x.wav
--
name : bloop_loop
filename : asset/sounds/bloop_x.wav
group : music
volume : 0.6
pitch : 0.8
loop : true
stream : true
================================================
FILE: asset/sprites.dl
================================================
--
name : avatar
filename : avatar.png
x : -0.5
y : -1
--
name : avatar2
filename : avatar.png
x : -0.5
y : -0.5
================================================
FILE: clibs/datalist/make.lua
================================================
local lm = require "luamake"
lm.rootdir = lm.basedir .. "/3rd/datalist"
lm:source_set "datalist_src" {
sources = {
"datalist.c",
},
includes = {
lm.basedir .. "/3rd/lua",
},
}
================================================
FILE: clibs/ltask/make.lua
================================================
local lm = require "luamake"
lm.rootdir = lm.basedir .. "/3rd/ltask"
lm:source_set "ltask_src" {
sources = {
"src/*.c",
},
includes = {
lm.basedir .. "/3rd/lua",
},
defines = {
"LTASK_EXTERNAL_OPENLIBS=soluna_openlibs",
},
}
================================================
FILE: clibs/lua/make.lua
================================================
local lm = require "luamake"
lm.rootdir = lm.basedir .. "/3rd/lua"
if lm.os == "windows" then
lm:source_set "winfile" {
sources = {
lm.basedir .. "/src/winfile.c",
},
}
end
lm:source_set "lua_src" {
sources = {
"onelua.c",
},
defines = {
"MAKE_LIB",
lm.os == "windows" and "LUA_DL_DLL" or "LUA_USE_DLOPEN",
},
}
lm:exe "lua" {
deps = {
lm.os == "windows" and "winfile",
},
sources = {
"onelua.c",
},
defines = {
"MAKE_LUA",
},
windows = {
defines = {
"fopen=fopen_utf8",
},
},
}
================================================
FILE: clibs/sample/make.lua
================================================
local lm = require "luamake"
local platform = require "bee.platform"
lm.rootdir = lm.basedir
local function shdc_plat()
if lm.os == "windows" then
return "win32"
end
if lm.os == "linux" then
return "linux"
end
if lm.os == "macos" then
return platform.Arch == "arm64" and "osx_arm64" or "osx"
end
return "unknown"
end
local paths = {
windows = "$PATH/$NAME.exe",
macos = "$PATH/$NAME",
linux = "$PATH/$NAME",
}
local shdc = assert(paths[lm.os]):gsub("%$(%u+)", {
PATH = tostring(lm.basedir / "bin/sokol-tools-bin/bin" / shdc_plat()),
NAME = "sokol-shdc",
})
local function shader_lang()
local plat = lm.platform
if plat == "msvc" or plat == "clang-cl" or plat == "mingw" then
return "hlsl4"
end
if plat == "macos" then
return "metal_macos"
end
if plat == "emcc" then
return "wgsl"
end
if plat == "linux" then
return "glsl430"
end
return "unknown"
end
local function compile_shader(src, name)
local dep = name .. "_shader"
local target = lm.builddir .. "/" .. name
lm:runlua(dep) {
script = lm.basedir .. "/clibs/soluna/shader2c.lua",
inputs = lm.basedir .. "/" .. src,
outputs = lm.basedir .. "/" .. target,
args = {
shdc,
"$in",
"$out",
shader_lang(),
},
}
return dep
end
local sample_shader = compile_shader("extlua/perspective_quad.glsl", "perspective_quad.glsl.h")
lm:dll "sample" {
sources = {
"extlua/extlua.c",
"extlua/sokolapi.c",
"extlua/solunaapi.c",
"extlua/extlua_sample.c",
},
objdeps = {
sample_shader,
},
includes = {
"3rd/lua",
"3rd",
"build",
"extlua",
},
}
================================================
FILE: clibs/soluna/compile_lua.lua
================================================
local lm = require "luamake"
local fs = require "bee.filesystem"
local function compile_lua_code(script, src, name)
local dep = name .. "_lua_code"
local target = lm.builddir .. "/" .. name
local bindir = lm.bindir
if lm.platform == "emcc" then
bindir = lm.osbindir
end
lm:runlua(dep) {
script = lm.basedir .. "/clibs/soluna/runlua.lua",
deps = {
"lua",
},
inputs = lm.basedir .. "/" .. src,
outputs = lm.basedir .. "/" .. target,
args = {
bindir,
lm.basedir .. "/" .. script,
"$in",
"$out",
},
}
return dep
end
local lua_code_src = {
"3rd/ltask/service",
"3rd/ltask/lualib",
"src/service",
"src/lualib",
"src/material",
}
return function(objdeps)
for _, dir in ipairs(lua_code_src) do
for path in fs.pairs(lm.basedir .. "/" .. dir) do
if path:extension() == ".lua" then
local base = path:stem():string()
local dep = compile_lua_code("script/lua2c.lua", path:string(), base .. ".lua.h")
objdeps[#objdeps + 1] = dep
end
end
end
for path in fs.pairs "src/data" do
if path:extension() == ".dl" then
local base = path:stem():string()
local dep = compile_lua_code("script/datalist2c.lua", path:string(), base .. ".dl.h")
objdeps[#objdeps + 1] = dep
end
end
end
================================================
FILE: clibs/soluna/compile_shader.lua
================================================
local lm = require "luamake"
local fs = require "bee.filesystem"
local platform = require "bee.platform"
local function shdc_plat()
if lm.os == "windows" then
return "win32"
end
if lm.os == "linux" then
return "linux"
end
if lm.os == "macos" then
return platform.Arch == "arm64" and "osx_arm64" or "osx"
end
return "unknown"
end
local paths = {
windows = "$PATH/$NAME.exe",
macos = "$PATH/$NAME",
linux = "$PATH/$NAME",
}
local shdc = assert(paths[lm.os]):gsub("%$(%u+)", {
PATH = tostring(lm.basedir / "bin/sokol-tools-bin/bin" / shdc_plat()),
NAME = "sokol-shdc",
})
local function compile_shader(src, name, lang)
local dep = name .. "_shader"
local target = lm.builddir .. "/" .. name
lm:runlua(dep) {
script = lm.basedir .. "/clibs/soluna/shader2c.lua",
inputs = lm.basedir .. "/" .. src,
outputs = lm.basedir .. "/" .. target,
args = {
shdc,
"$in",
"$out",
lang,
},
}
return dep
end
local function shader_lang()
local plat = lm.platform
if plat == "msvc" or plat == "clang-cl" or plat == "mingw" then
return "hlsl4"
end
if plat == "macos" then
return "metal_macos"
end
if plat == "emcc" then
return "wgsl"
end
if plat == "linux" then
return "glsl430"
end
return "unknown"
end
return function(objdeps)
for path in fs.pairs "src" do
local lang = shader_lang()
if path:extension() == ".glsl" then
local base = path:stem():string()
local dep = compile_shader(path:string(), base .. ".glsl.h", lang)
objdeps[#objdeps + 1] = dep
end
end
end
================================================
FILE: clibs/soluna/make.lua
================================================
local lm = require "luamake"
local subprocess = require "bee.subprocess"
local compile_lua = require "compile_lua"
local compile_shader = require "compile_shader"
lm.rootdir = lm.basedir
local ok, process, errMsg = pcall(subprocess.spawn, {
lm.os ~= "windows" and "git" or "C:\\Program Files\\Git\\cmd\\git.exe",
"rev-parse",
"HEAD",
stdout = true,
})
local commit
if ok then
if errMsg then
print("Failed to start git process: " .. errMsg)
else
local output = process.stdout:read "a"
commit = output:match "^%s*(.-)%s*$"
process:wait()
end
end
local objdeps = {}
compile_lua(objdeps)
compile_shader(objdeps)
lm:source_set "soluna_src" {
sources = {
"src/*.c",
"extlua/extlua_impl.c",
"extlua/sokolapi_impl.c",
"extlua/solunaapi_impl.c",
},
objdeps = objdeps,
defines = {
commit and string.format('SOLUNA_HASH_VERSION=\\"%s\\"', commit),
},
includes = {
"build",
"src",
"3rd",
"3rd/lua",
"3rd/yoga",
"3rd/zlib",
"3rd/miniaudio",
},
clang = {
sources = lm.os == "macos" and {
"src/platform/macos/*.m",
},
flags = lm.os == "macos" and {
"-x objective-c",
},
frameworks = lm.os == "macos" and {
"AudioToolbox",
"IOKit",
"CoreText",
"CoreFoundation",
"Foundation",
"Cocoa",
"Metal",
"MetalKit",
"QuartzCore",
},
},
windows = {
sources = {
"src/platform/windows/*.c",
},
includes = {
"3rd/zlib/contrib/minizip",
}
},
gcc = {
sources = lm.os == "linux" and {
"src/platform/linux/*.c",
} or nil,
links = lm.os == "linux" and {
"pthread",
"dl",
"GL",
"X11",
"Xrandr",
"Xi",
"Xxf86vm",
"Xcursor",
"GLU",
"asound",
},
},
msvc = {
ldflags = {
"-SUBSYSTEM:WINDOWS",
"xinput.lib",
"Ws2_32.lib",
"ntdll.lib",
"Imm32.lib",
},
},
mingw = {
links = {
"kernel32",
"user32",
"shell32",
"gdi32",
"dxgi",
"d3d11",
"winmm",
"ws2_32",
"ntdll",
"xinput",
"imm32",
},
flags = {
"-Wl,subsystem,windows",
},
},
}
================================================
FILE: clibs/soluna/runlua.lua
================================================
local subprocess = require "bee.subprocess"
local platform = require "bee.platform"
local bindir, script, src, target = ...
local luaexe = platform.os == "windows" and bindir .. "/lua.exe" or bindir .. "/lua"
local process = assert(subprocess.spawn {
luaexe, script, src, target,
})
local code = process:wait()
if code ~= 0 then
os.exit(code, true)
end
================================================
FILE: clibs/soluna/shader2c.lua
================================================
local subprocess = require "bee.subprocess"
local shdcexe, src, target, lang = ...
local process = assert(subprocess.spawn {
shdcexe,
"--input",
src,
"--output",
target,
"--slang",
lang,
"--format",
"sokol",
})
local code = process:wait()
if code ~= 0 then
os.exit(code, true)
end
================================================
FILE: clibs/yoga/make.lua
================================================
local lm = require "luamake"
lm.rootdir = lm.basedir .. "/3rd/yoga"
lm:source_set "yoga_src" {
sources = {
"yoga/*.cpp",
"yoga/*/*.cpp",
},
includes = {
lm.rootdir,
}
}
================================================
FILE: clibs/zip/make.lua
================================================
local lm = require "luamake"
lm.rootdir = lm.basedir .. "/3rd/zlib"
lm:source_set "minizip" {
sources = {
"contrib/minizip/ioapi.c",
"contrib/minizip/unzip.c",
"contrib/minizip/zip.c",
},
windows = {
sources = {
"contrib/minizip/iowin32.c",
},
includes = {
"contrib/minizip",
},
},
includes = {
lm.rootdir,
},
}
lm:source_set "zlib" {
sources = {
"*.c",
"!gz*.c",
},
}
lm:source_set "zip_src" {
deps = {
"minizip",
"zlib",
}
}
================================================
FILE: docs/app.lua
================================================
---@meta soluna.app
---输入法候选窗口矩形
---IME candidate window rectangle.
---@class soluna.app.ImeRect
---@field x number 左上角 X / Left coordinate
---@field y number 左上角 Y / Top coordinate
---@field width number 宽度 / Width
---@field height number 高度 / Height
---@field text_color? integer 文本 ARGB 颜色;alpha 为 0 时补为 0xff / Text color in ARGB; alpha 0 is promoted to 0xff
---应用控制模块
---Application control module.
---@class soluna.app
local app = {}
---请求应用优雅退出
---Requests graceful application quit.
function app.quit()
end
---设置输入法字体
---Sets the IME font face and pixel size.
---@overload fun()
---@overload fun(font_size: number)
---@param font_name? string 字体名;nil 表示平台默认字体 / Font face; nil uses platform default
---@param font_size number 字体像素大小 / Font size in pixels
function app.set_ime_font(font_name, font_size)
end
---设置输入法候选窗口矩形
---Sets the IME candidate window rectangle.
---@param rect? soluna.app.ImeRect nil 会清除矩形 / nil clears the rectangle
function app.set_ime_rect(rect)
end
return app
================================================
FILE: docs/args.lua
================================================
---@meta
---可提交给 batch 的绘制对象
---Drawable object accepted by `Batch:add`.
---@alias soluna.Drawable integer|string|userdata
---绘制批次
---Render batch object.
---@class Batch
local batch = {}
---向批次添加 sprite、material 对象或 packed stream
---Adds a sprite id, material userdata, or packed command stream.
---@param sprite soluna.Drawable sprite ID、material userdata 或 packed string / Sprite id, material userdata, or packed string
---@param x? number X 坐标,默认 0 / X position, default 0
---@param y? number Y 坐标,默认 0 / Y position, default 0
function batch:add(sprite, x, y)
end
---打开或关闭变换层
---Opens or closes a transform layer.
---@overload fun(self: Batch)
---@overload fun(self: Batch, rotation: number)
---@overload fun(self: Batch, x: number, y: number)
---@overload fun(self: Batch, scale: number, x: number, y: number)
---@param scale number 缩放倍率,不能为 0 / Scale factor, cannot be 0
---@param rotation number 旋转弧度 / Rotation in radians
---@param x number X 平移 / X translation
---@param y number Y 平移 / Y translation
function batch:layer(scale, rotation, x, y)
end
---把屏幕点转换到当前 layer 坐标
---Transforms a screen point into the current layer space.
---@param x number 屏幕 X / Screen X
---@param y number 屏幕 Y / Screen Y
---@return number x 转换后的 X / Transformed X
---@return number y 转换后的 Y / Transformed Y
function batch:point(x, y)
end
---入口参数表
---Entry argument table passed to the game script.
---@class Args
---@field width integer 当前窗口宽度 / Current window width
---@field height integer 当前窗口高度 / Current window height
---@field batch Batch 绘制批次 / Render batch
---@field [integer] string 启动参数 / Startup argument
local args = {}
return args
================================================
FILE: docs/callback.lua
================================================
---@meta
---游戏入口返回的 callback 表
---Callback table returned by the game entry script.
---@class Callback
local callback = {}
---每帧调用
---Called once per frame.
---@param count integer frame 计数 / Frame counter
function callback.frame(count)
end
---键盘事件
---Keyboard event.
---@param keycode integer Sokol key code / Sokol key code
---@param state integer 1 为按下,0 为释放 / 1 for key down, 0 for key up
function callback.key(keycode, state)
end
---字符输入事件
---Text input event.
---@param codepoint integer Unicode codepoint / Unicode codepoint
function callback.char(codepoint)
end
---鼠标按钮事件
---Mouse button event.
---@param button integer 0 左键,1 右键,2 中键 / 0 left, 1 right, 2 middle
---@param state integer 1 为按下,0 为释放 / 1 for down, 0 for up
function callback.mouse_button(button, state)
end
---鼠标移动事件
---Mouse move event.
---@param x integer 逻辑像素 X / Logical pixel X
---@param y integer 逻辑像素 Y / Logical pixel Y
function callback.mouse_move(x, y)
end
---鼠标滚轮事件
---Mouse scroll event.
---@param y integer 垂直滚动量 / Vertical scroll delta
---@param x integer 水平滚动量 / Horizontal scroll delta
function callback.mouse_scroll(y, x)
end
---其它鼠标事件
---Other mouse event.
---@param event_type integer Sokol event type / Sokol event type
function callback.mouse(event_type)
end
---触摸开始
---Touch begin event.
---@param x integer 逻辑像素 X / Logical pixel X
---@param y integer 逻辑像素 Y / Logical pixel Y
function callback.touch_begin(x, y)
end
---触摸移动
---Touch move event.
---@param x integer 逻辑像素 X / Logical pixel X
---@param y integer 逻辑像素 Y / Logical pixel Y
function callback.touch_moved(x, y)
end
---触摸结束
---Touch end event.
---@param x integer 逻辑像素 X / Logical pixel X
---@param y integer 逻辑像素 Y / Logical pixel Y
function callback.touch_end(x, y)
end
---触摸取消
---Touch cancelled event.
---@param x integer 逻辑像素 X / Logical pixel X
---@param y integer 逻辑像素 Y / Logical pixel Y
function callback.touch_cancelled(x, y)
end
---窗口尺寸变化
---Window resize event.
---@param width integer 新窗口宽度 / New window width
---@param height integer 新窗口高度 / New window height
function callback.window_resize(width, height)
end
return callback
================================================
FILE: docs/coroutine.lua
================================================
---@meta soluna.coroutine
---ltask 兼容 coroutine 模块
---ltask-compatible coroutine module.
---@class soluna.coroutine
local coroutine = {}
---创建受 ltask 跟踪的 coroutine
---Creates a coroutine tracked by the ltask bridge.
---@param f function coroutine 函数 / Coroutine function
---@return thread co coroutine 线程 / Coroutine thread
function coroutine.create(f)
end
---恢复 coroutine
---Resumes a tracked coroutine.
---@param co thread coroutine 线程 / Coroutine thread
---@param ... any 传入参数 / Arguments
---@return boolean ok 是否成功 / Whether resume succeeded
---@return any ... 返回值或错误 / Return values or error
function coroutine.resume(co, ...)
end
---挂起当前 coroutine
---Yields from the current coroutine.
---@param ... any 返回给 resume 的值 / Values returned to resume
---@return any ... 下次 resume 传入的值 / Values passed by the next resume
function coroutine.yield(...)
end
return coroutine
================================================
FILE: docs/crypt.lua
================================================
---@meta soluna.crypt
---密码辅助模块
---Cryptography helper module.
---@class soluna.crypt
local crypt = {}
---编码为小写十六进制字符串
---Encodes binary data as lower-case hex.
---@param data string 二进制数据 / Binary data
---@return string hex 十六进制字符串 / Hex string
function crypt.hexencode(data)
end
---计算 SHA-1 摘要
---Calculates SHA-1 digest.
---@param data string 输入数据 / Input data
---@return string hash 20 字节摘要 / 20-byte digest
function crypt.sha1(data)
end
return crypt
================================================
FILE: docs/datalist.lua
================================================
---@meta soluna.datalist
---datalist 解析模块
---Datalist parser module.
---@class soluna.datalist
local datalist = {}
---解析 datalist 文本
---Parses datalist text.
---@param data string datalist 文本 / Datalist text
---@return table parsed 解析结果 / Parsed result
function datalist.parse(data)
end
---为 datalist 格式引用字符串
---Quotes a string for datalist syntax.
---@param str string 原始字符串 / Raw string
---@return string quoted quoted 字符串 / Quoted string
function datalist.quote(str)
end
return datalist
================================================
FILE: docs/file.lua
================================================
---@meta soluna.file
---文件属性表
---File attribute table.
---@class soluna.file.Attributes
---@field mode "file"|"directory"|"link"|"socket"|"named pipe"|"char device"|"block device"|"other" 文件类型 / File type
---@field dev integer 设备号 / Device id
---@field ino integer inode / Inode
---@field nlink integer 硬链接数 / Hard link count
---@field uid integer owner user id / Owner user id
---@field gid integer owner group id / Owner group id
---@field rdev integer special file device id / Special file device id
---@field access integer 最后访问时间 / Last access time
---@field modification integer 最后修改时间 / Last modification time
---@field change integer 最后状态变化时间 / Last status change time
---@field size integer 文件大小 / File size
---@field permissions string 权限字符串 / Permission string
---文件加载模块
---File loading module.
---@class soluna.file
local file = {}
---加载文件内容
---Loads file contents.
---@param filename string 文件路径 / File path
---@param mode? string 本地文件打开模式,默认 `"rb"` / Local file open mode, default `"rb"`
---@return string? content 文件内容;失败返回 nil / File contents, nil on failure
function file.load(filename, mode)
end
---获取文件属性
---Gets file attributes.
---@param filename string 文件路径 / File path
---@return soluna.file.Attributes|string? attributes 本地文件返回属性表,zip 文件可返回 `"file"` 或 `"directory"` / Local files return attributes; zip files may return `"file"` or `"directory"`
function file.attributes(filename)
end
---判断文件是否存在
---Checks whether a file exists.
---@param filename string 文件路径 / File path
---@return boolean? exists 存在时为 true,否则为 nil / true when found, nil otherwise
function file.exist(filename)
end
---判断本地文件是否存在
---Checks whether a local file exists.
---@param filename string 文件路径 / File path
---@return boolean? exists 存在时为 true,否则为 nil / true when found, nil otherwise
function file.local_exist(filename)
end
---加载本地文件内容
---Loads local file contents.
---@param filename string 文件路径 / File path
---@param mode? string 打开模式,默认 `"rb"` / Open mode, default `"rb"`
---@return string? content 文件内容;失败返回 nil / File contents, nil on failure
function file.local_load(filename, mode)
end
---遍历目录条目
---Iterates directory entries.
---@param path string 目录路径 / Directory path
---@return fun(): string? iterator 迭代器 / Iterator
---@return userdata? state 本地目录句柄 / Local directory handle
function file.dir(path)
end
return file
================================================
FILE: docs/font.lua
================================================
---@meta soluna.font
---字体模块
---Font module.
---@class soluna.font
local font = {}
---导入 TrueType 字体数据
---Imports TrueType font data.
---@param data string TTF/TTC 字体数据 / TTF/TTC font data
function font.import(data)
end
---按字体族名获取 font id
---Gets a font id by family name.
---@param name string 字体族名 / Font family name
---@return integer? fontid 字体 id;找不到时为 nil / Font id, nil when not found
function font.name(name)
end
---返回字体管理器 C 指针
---Returns the native font manager pointer.
---@return lightuserdata fontcobj 字体管理器指针 / Font manager pointer
function font.cobj()
end
return font
================================================
FILE: docs/font_system.lua
================================================
---@meta soluna.font.system
---系统字体模块
---System font module.
---@class soluna.font.system
local font_system = {}
---按字体族名读取系统 TTF/TTC 数据
---Reads system TTF/TTC data by family name.
---@param name string 字体族名 / Font family name
---@return string? data 字体数据;wasm 或失败时可能为 nil / Font data, nil on wasm or failure
function font_system.ttfdata(name)
end
return font_system
================================================
FILE: docs/image.lua
================================================
---@meta soluna.image
---图片模块
---Image module.
---@class soluna.image
local image = {}
---从 PNG 数据加载 RGBA 图片
---Loads RGBA image data from PNG bytes.
---@param data string PNG 数据 / PNG bytes
---@return string? data RGBA 像素数据,失败时为 nil / RGBA pixels, nil on failure
---@return integer|string width_or_error 成功时为宽度,失败时为错误信息 / Width on success, error message on failure
---@return integer? height 高度 / Height
function image.load(data)
end
---按比例缩放 RGBA 或灰度图片
---Resizes RGBA or grayscale image data by scale factors.
---@param data string RGBA 或灰度像素数据 / RGBA or grayscale pixels
---@param width integer 原始宽度 / Source width
---@param height integer 原始高度 / Source height
---@param scale_x number X 缩放倍率 / X scale factor
---@param scale_y? number Y 缩放倍率,默认等于 `scale_x` / Y scale factor, default is `scale_x`
---@return string data 缩放后的像素数据 / Resized pixels
---@return integer width 新宽度 / New width
---@return integer height 新高度 / New height
function image.resize(data, width, height, scale_x, scale_y)
end
return image
================================================
FILE: docs/layout.lua
================================================
---@meta soluna.layout
---layout 元素对象
---Layout element object.
---@class soluna.layout.Element
local element = {}
---更新元素 Yoga 属性
---Updates Yoga attributes on the element.
---@param attr table 属性表 / Attribute table
function element:update(attr)
end
---读取元素布局结果
---Reads calculated element layout.
---@return number x X 坐标 / X coordinate
---@return number y Y 坐标 / Y coordinate
---@return number w 宽度 / Width
---@return number h 高度 / Height
function element:get()
end
---返回元素属性表
---Returns the element attribute table.
---@return table attrs 属性表 / Attribute table
function element:attribs()
end
---layout 文档对象
---Layout document object.
---@class soluna.layout.Document
---@field [string] soluna.layout.Element 按 id 访问元素 / Element access by id
---layout 绘制条目
---Calculated drawable layout item.
---@class soluna.layout.Item
---@field x number X 坐标 / X coordinate
---@field y number Y 坐标 / Y coordinate
---@field w number 宽度 / Width
---@field h number 高度 / Height
---@field [string] any datalist 属性 / Datalist attributes
---layout 计算结果
---Calculated layout item list.
---@class soluna.layout.Result
---@field [integer] soluna.layout.Item 绘制条目 / Drawable item
---@field width number 根节点宽度 / Root width
---@field height number 根节点高度 / Root height
---Yoga layout 模块
---Yoga layout module.
---@class soluna.layout
local layout = {}
---加载 layout 定义
---Loads a layout definition.
---@param filename_or_list string|table layout 文件路径或已解析 datalist / Layout file path or parsed datalist
---@param scripts? fun(name: string): table children 动态 children resolver / Dynamic children resolver
---@return soluna.layout.Document document layout 文档 / Layout document
function layout.load(filename_or_list, scripts)
end
---计算 layout 并返回绘制条目
---Calculates layout and returns drawable items.
---@param document soluna.layout.Document layout 文档 / Layout document
---@return soluna.layout.Result items 绘制条目列表 / Drawable item list
function layout.calc(document)
end
return layout
================================================
FILE: docs/lfs.lua
================================================
---@meta soluna.lfs
---本地文件属性表
---Local file attribute table.
---@class soluna.lfs.Attributes
---@field mode "file"|"directory"|"link"|"socket"|"named pipe"|"char device"|"block device"|"other" 文件类型 / File type
---@field size integer 文件大小 / File size
---@field access integer 最后访问时间 / Last access time
---@field modification integer 最后修改时间 / Last modification time
---@field change integer 最后状态变化时间 / Last status change time
---@field permissions string 权限字符串 / Permission string
---本地文件系统模块
---Local filesystem module.
---@class soluna.lfs
local lfs = {}
---获取文件属性
---Gets file attributes.
---@param filename string 文件路径 / File path
---@param member? string 可选属性名 / Optional attribute name
---@return soluna.lfs.Attributes|integer|string|nil attributes 属性表或指定属性 / Attribute table or selected attribute
---@return string? err 错误信息 / Error message
---@return integer? errno 系统错误码 / System errno
function lfs.attributes(filename, member)
end
---遍历目录条目
---Iterates directory entries.
---@param path string 目录路径 / Directory path
---@return fun(): string? iterator 迭代器 / Iterator
---@return userdata state 目录句柄 / Directory handle
function lfs.dir(path)
end
return lfs
================================================
FILE: docs/material_mask.lua
================================================
---@meta soluna.material.mask
---mask material 模块
---Mask material module.
---@class soluna.material.mask
local matmask = {}
---创建带颜色遮罩的 sprite command stream
---Creates a colored mask sprite command stream.
---@param sprite integer 1-based sprite id / 1-based sprite id
---@param color integer ARGB 颜色,alpha 为 0 时补为 0xff / ARGB color; alpha 0 is promoted to 0xff
---@return string stream 可传给 `batch:add` 的 packed stream / Packed stream for `batch:add`
function matmask.mask(sprite, color)
end
return matmask
================================================
FILE: docs/material_quad.lua
================================================
---@meta soluna.material.quad
---quad material 模块
---Quad material module.
---@class soluna.material.quad
local matquad = {}
---创建纯色矩形 command stream
---Creates a solid rectangle command stream.
---@param width integer 宽度 / Width
---@param height integer 高度 / Height
---@param color integer ARGB 颜色,alpha 为 0 时补为 0xff / ARGB color; alpha 0 is promoted to 0xff
---@return string stream 可传给 `batch:add` 的 packed stream / Packed stream for `batch:add`
function matquad.quad(width, height, color)
end
return matquad
================================================
FILE: docs/material_text.lua
================================================
---@meta soluna.material.text
---文本块创建函数
---Text block builder function.
---@alias soluna.material.text.Block fun(text: string, width?: integer, height?: integer): string, integer
---光标位置查询函数
---Text cursor query function.
---@alias soluna.material.text.Cursor fun(text: string, position: integer, width?: integer, height?: integer): integer, integer, integer, integer, integer, integer
---text material 模块
---Text material module.
---@class soluna.material.text
local mattext = {}
---创建文本块和光标查询函数
---Creates text block and cursor query functions.
---@param fontcobj lightuserdata `font.cobj()` 返回的字体管理器指针 / Font manager pointer returned by `font.cobj()`
---@param fontid integer `font.name()` 返回的字体 id / Font id returned by `font.name()`
---@param size? integer 字体像素大小,默认 16 / Font pixel size, default 16
---@param color? integer ARGB 颜色,默认 `0xff000000` / ARGB color, default `0xff000000`
---@param alignment? string 对齐代码,如 `"LT"`、`"CV"`、`"RB"` / Alignment code such as `"LT"`, `"CV"`, `"RB"`
---@return soluna.material.text.Block block 创建 packed text stream / Creates packed text stream
---@return soluna.material.text.Cursor cursor 查询光标矩形 / Queries cursor rectangle
function mattext.block(fontcobj, fontid, size, color, alignment)
end
return mattext
================================================
FILE: docs/soluna.lua
================================================
---@meta
---单个 sprite id 或动画帧 id 列表
---Single sprite id or animation frame id list.
---@alias Sprite integer|integer[]
---sprite bundle 名称到 id 的映射
---Sprite bundle name-to-id mapping.
---@alias SpriteBundle table<string, Sprite?>
---窗口图标图片描述
---Window icon image descriptor.
---@class soluna.IconImage
---@field data string|userdata|lightuserdata RGBA 像素数据 / RGBA pixel buffer
---@field w? integer 宽度;也可使用 `width` / Width; `width` is also accepted
---@field h? integer 高度;也可使用 `height` / Height; `height` is also accepted
---@field width? integer 宽度;`w` 的别名 / Width alias for `w`
---@field height? integer 高度;`h` 的别名 / Height alias for `h`
---@field stride? integer 每行字节数,默认 `width * 4` / Row stride in bytes, default `width * 4`
---@field size? integer `lightuserdata` 数据大小 / Buffer size for `lightuserdata`
---运行时预加载 sprite 图片
---Runtime preloaded sprite image.
---@class soluna.PreloadSprite
---@field filename string 虚拟文件名 / Virtual filename
---@field content string RGBA 像素数据 / RGBA pixel data
---@field w integer 宽度 / Width
---@field h integer 高度 / Height
---音频播放选项
---Audio playback options.
---@class soluna.AudioPlayOptions
---@field group? string audio bus 名称 / Audio bus name
---@field volume? number 线性音量倍率 / Linear volume multiplier
---@field pan? number 声像,范围通常为 `[-1.0, 1.0]` / Stereo pan, usually in `[-1.0, 1.0]`
---@field pitch? number pitch 倍率 / Pitch multiplier
---@field loop? boolean 是否循环播放 / Whether playback loops
---@field stream? boolean 是否流式播放 / Whether to stream instead of preloading
---音频播放实例
---Audio playback instance.
---@class soluna.AudioVoice
local AudioVoice = {}
---停止播放
---Stops playback.
---@param fade_seconds? number fade out 秒数 / Fade-out seconds
---@return boolean ok voice 有效且请求成功时为 true / true when the voice is valid and the request succeeds
function AudioVoice:stop(fade_seconds)
end
---返回是否仍在播放
---Returns whether the voice is still playing.
---@return boolean playing 是否播放中 / Whether it is playing
function AudioVoice:playing()
end
---设置 voice 音量
---Sets voice volume.
---@param volume number 线性音量倍率 / Linear volume multiplier
---@return boolean ok voice 有效时为 true / true when the voice is valid
function AudioVoice:set_volume(volume)
end
---设置 voice 声像
---Sets voice pan.
---@param pan number 声像 / Stereo pan
---@return boolean ok voice 有效时为 true / true when the voice is valid
function AudioVoice:set_pan(pan)
end
---设置 voice pitch
---Sets voice pitch.
---@param pitch number pitch 倍率 / Pitch multiplier
---@return boolean ok voice 有效时为 true / true when the voice is valid
function AudioVoice:set_pitch(pitch)
end
---设置 voice 是否循环
---Sets whether the voice loops.
---@param loop boolean 是否循环 / Whether to loop
---@return boolean ok voice 有效时为 true / true when the voice is valid
function AudioVoice:set_loop(loop)
end
---跳转播放位置
---Seeks to a playback position.
---@param seconds number 目标秒数 / Target seconds
---@return boolean ok voice 有效且 seek 成功时为 true / true when valid and seek succeeds
function AudioVoice:seek(seconds)
end
---返回当前播放位置
---Returns the current playback position.
---@return number? seconds 当前秒数 / Current seconds
---@return string? err 错误信息 / Error message
function AudioVoice:tell()
end
---音频 bus 句柄
---Audio bus handle.
---@class soluna.AudioBus
local AudioBus = {}
---设置 bus 音量
---Sets bus volume.
---@param volume number 线性音量倍率 / Linear volume multiplier
---@return boolean ok bus 存在时为 true / true when the bus exists
function AudioBus:set_volume(volume)
end
---Soluna 主模块
---Soluna root module.
---@class soluna
---@field platform "windows"|"macos"|"linux"|"wasm" 当前平台 / Current platform
---@field version string 运行时版本字符串 / Runtime version string
---@field version_api integer API 版本号 / API version number
local soluna = {}
---返回 `.game` 设置表
---Returns the `.game` settings table.
---@return table settings 游戏设置 / Game settings
function soluna.settings()
end
---设置窗口标题
---Sets the window title.
---@param text string 标题文字 / Window title
function soluna.set_window_title(text)
end
---设置窗口图标
---Sets one icon image or an icon image list.
---@param data soluna.IconImage|soluna.IconImage[] 图标数据 / Icon data
function soluna.set_icon(data)
end
---返回并创建游戏数据目录
---Returns and creates the game data directory.
---@param name? string 项目名,默认来自 `settings.project` / Project name, default from `settings.project`
---@return string path 绝对路径,结尾带 `/` / Absolute path ending with `/`
function soluna.gamedir(name)
end
---加载 sprite bundle
---Loads a sprite bundle.
---@param filename string|table `.dl` 文件路径或已解析 bundle 表 / `.dl` path or parsed bundle table
---@return SpriteBundle sprites sprite 名称映射 / Sprite name mapping
function soluna.load_sprites(filename)
end
---预加载运行时生成的 RGBA sprite 图片
---Preloads runtime-generated RGBA sprite images.
---@param sprites soluna.PreloadSprite|soluna.PreloadSprite[] 单个 sprite 或列表 / One sprite or a list
function soluna.preload(sprites)
end
---加载音频定义 bundle
---Loads an audio definition bundle.
---@param filename string `sounds.dl` 文件路径 / `sounds.dl` path
function soluna.load_sounds(filename)
end
---播放音频并返回 voice
---Plays a sound and returns a voice handle.
---@param name string `sounds.dl` 中的音频名 / Sound name from `sounds.dl`
---@param opts? soluna.AudioPlayOptions 播放选项覆盖 / Playback option overrides
---@return soluna.AudioVoice? voice voice 句柄 / Voice handle
---@return string? err 错误信息 / Error message
function soluna.play_sound(name, opts)
end
---返回 audio bus 句柄
---Returns an audio bus handle.
---@param name string bus 名称 / Bus name
---@return soluna.AudioBus? bus bus 句柄 / Bus handle
---@return string? err 错误信息 / Error message
function soluna.audio_bus(name)
end
return soluna
================================================
FILE: docs/text.lua
================================================
---@meta soluna.text
---文本预处理模块
---Text preprocessing module.
---@class soluna.text
---@field convert table<string, string> 文本转换缓存表 / Text conversion cache table
local text = {}
---初始化内嵌 icon bundle
---Initializes the embedded icon bundle.
---@param bundle_file string icon bundle `.dl` 文件路径 / Icon bundle `.dl` path
function text.init(bundle_file)
end
return text
================================================
FILE: docs/url.lua
================================================
---@meta soluna.url
---URL 模块
---URL module.
---@class soluna.url
local url = {}
---用系统默认浏览器打开 URL
---Opens a URL with the system default browser.
---@param link string URL / URL
function url.open(link)
end
return url
================================================
FILE: docs/zip.lua
================================================
---@meta soluna.zip
---ZIP 模块
---ZIP module.
---@class soluna.zip
local zip = {}
---打开 ZIP 文件
---Opens a ZIP archive.
---@param filename string ZIP 文件路径 / ZIP file path
---@param mode "r"|"w"|"a" 打开模式:读、写、追加 / Open mode: read, write, append
---@return userdata? zipfile ZIP 句柄;失败时为 nil / ZIP handle, nil on failure
function zip.open(filename, mode)
end
return zip
================================================
FILE: extlua/extlua.c
================================================
// AUTO GENERATED by extlua.temp.c, DONT EDIT
#include <lua.h>
#include <lauxlib.h>
#include <stdarg.h>
#include <assert.h>
#include <stdio.h>
struct lua_api {
int version;
lua_State * (*lua_newstate) (lua_Alloc f, void *ud, unsigned seed);
void (*lua_close) (lua_State *L);
lua_State * (*lua_newthread) (lua_State *L);
int (*lua_closethread) (lua_State *L, lua_State *from);
lua_CFunction (*lua_atpanic) (lua_State *L, lua_CFunction panicf);
lua_Number (*lua_version) (lua_State *L);
int (*lua_absindex) (lua_State *L, int idx);
int (*lua_gettop) (lua_State *L);
void (*lua_settop) (lua_State *L, int idx);
void (*lua_pushvalue) (lua_State *L, int idx);
void (*lua_rotate) (lua_State *L, int idx, int n);
void (*lua_copy) (lua_State *L, int fromidx, int toidx);
int (*lua_checkstack) (lua_State *L, int n);
void (*lua_xmove) (lua_State *from, lua_State *to, int n);
int (*lua_isnumber) (lua_State *L, int idx);
int (*lua_isstring) (lua_State *L, int idx);
int (*lua_iscfunction) (lua_State *L, int idx);
int (*lua_isinteger) (lua_State *L, int idx);
int (*lua_isuserdata) (lua_State *L, int idx);
int (*lua_type) (lua_State *L, int idx);
const char * (*lua_typename) (lua_State *L, int tp);
lua_Number (*lua_tonumberx) (lua_State *L, int idx, int *isnum);
lua_Integer (*lua_tointegerx) (lua_State *L, int idx, int *isnum);
int (*lua_toboolean) (lua_State *L, int idx);
const char * (*lua_tolstring) (lua_State *L, int idx, size_t *len);
lua_Unsigned (*lua_rawlen) (lua_State *L, int idx);
lua_CFunction (*lua_tocfunction) (lua_State *L, int idx);
void * (*lua_touserdata) (lua_State *L, int idx);
lua_State * (*lua_tothread) (lua_State *L, int idx);
const void * (*lua_topointer) (lua_State *L, int idx);
void (*lua_arith) (lua_State *L, int op);
int (*lua_rawequal) (lua_State *L, int idx1, int idx2);
int (*lua_compare) (lua_State *L, int idx1, int idx2, int op);
void (*lua_pushnil) (lua_State *L);
void (*lua_pushnumber) (lua_State *L, lua_Number n);
void (*lua_pushinteger) (lua_State *L, lua_Integer n);
const char * (*lua_pushlstring) (lua_State *L, const char *s, size_t len);
const char * (*lua_pushexternalstring) (lua_State *L,
const char *s, size_t len, lua_Alloc falloc, void *ud);
const char * (*lua_pushstring) (lua_State *L, const char *s);
const char * (*lua_pushvfstring) (lua_State *L, const char *fmt,
va_list argp);
void (*lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
void (*lua_pushboolean) (lua_State *L, int b);
void (*lua_pushlightuserdata) (lua_State *L, void *p);
int (*lua_pushthread) (lua_State *L);
int (*lua_getglobal) (lua_State *L, const char *name);
int (*lua_gettable) (lua_State *L, int idx);
int (*lua_getfield) (lua_State *L, int idx, const char *k);
int (*lua_geti) (lua_State *L, int idx, lua_Integer n);
int (*lua_rawget) (lua_State *L, int idx);
int (*lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
int (*lua_rawgetp) (lua_State *L, int idx, const void *p);
void (*lua_createtable) (lua_State *L, int narr, int nrec);
void * (*lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
int (*lua_getmetatable) (lua_State *L, int objindex);
int (*lua_getiuservalue) (lua_State *L, int idx, int n);
void (*lua_setglobal) (lua_State *L, const char *name);
void (*lua_settable) (lua_State *L, int idx);
void (*lua_setfield) (lua_State *L, int idx, const char *k);
void (*lua_seti) (lua_State *L, int idx, lua_Integer n);
void (*lua_rawset) (lua_State *L, int idx);
void (*lua_rawseti) (lua_State *L, int idx, lua_Integer n);
void (*lua_rawsetp) (lua_State *L, int idx, const void *p);
int (*lua_setmetatable) (lua_State *L, int objindex);
int (*lua_setiuservalue) (lua_State *L, int idx, int n);
void (*lua_callk) (lua_State *L, int nargs, int nresults,
lua_KContext ctx, lua_KFunction k);
int (*lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
lua_KContext ctx, lua_KFunction k);
int (*lua_load) (lua_State *L, lua_Reader reader, void *dt,
const char *chunkname, const char *mode);
int (*lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip);
int (*lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx,
lua_KFunction k);
int (*lua_resume) (lua_State *L, lua_State *from, int narg,
int *nres);
int (*lua_status) (lua_State *L);
int (*lua_isyieldable) (lua_State *L);
void (*lua_setwarnf) (lua_State *L, lua_WarnFunction f, void *ud);
void (*lua_warning) (lua_State *L, const char *msg, int tocont);
int (*lua_error) (lua_State *L);
int (*lua_next) (lua_State *L, int idx);
void (*lua_concat) (lua_State *L, int n);
void (*lua_len) (lua_State *L, int idx);
unsigned (*lua_numbertocstring) (lua_State *L, int idx, char *buff);
size_t (*lua_stringtonumber) (lua_State *L, const char *s);
lua_Alloc (*lua_getallocf) (lua_State *L, void **ud);
void (*lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
void (*lua_toclose) (lua_State *L, int idx);
void (*lua_closeslot) (lua_State *L, int idx);
int (*lua_getstack) (lua_State *L, int level, lua_Debug *ar);
int (*lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar);
const char * (*lua_getlocal) (lua_State *L, const lua_Debug *ar, int n);
const char * (*lua_setlocal) (lua_State *L, const lua_Debug *ar, int n);
const char * (*lua_getupvalue) (lua_State *L, int funcindex, int n);
const char * (*lua_setupvalue) (lua_State *L, int funcindex, int n);
void * (*lua_upvalueid) (lua_State *L, int fidx, int n);
void (*lua_upvaluejoin) (lua_State *L, int fidx1, int n1,
int fidx2, int n2);
void (*lua_sethook) (lua_State *L, lua_Hook func, int mask, int count);
lua_Hook (*lua_gethook) (lua_State *L);
int (*lua_gethookmask) (lua_State *L);
int (*lua_gethookcount) (lua_State *L);
void (*luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz);
int (*luaL_getmetafield) (lua_State *L, int obj, const char *e);
int (*luaL_callmeta) (lua_State *L, int obj, const char *e);
const char * (*luaL_tolstring) (lua_State *L, int idx, size_t *len);
int (*luaL_argerror) (lua_State *L, int arg, const char *extramsg);
int (*luaL_typeerror) (lua_State *L, int arg, const char *tname);
const char * (*luaL_checklstring) (lua_State *L, int arg,
size_t *l);
const char * (*luaL_optlstring) (lua_State *L, int arg,
const char *def, size_t *l);
lua_Number (*luaL_checknumber) (lua_State *L, int arg);
lua_Number (*luaL_optnumber) (lua_State *L, int arg, lua_Number def);
lua_Integer (*luaL_checkinteger) (lua_State *L, int arg);
lua_Integer (*luaL_optinteger) (lua_State *L, int arg,
lua_Integer def);
void (*luaL_checkstack) (lua_State *L, int sz, const char *msg);
void (*luaL_checktype) (lua_State *L, int arg, int t);
void (*luaL_checkany) (lua_State *L, int arg);
int (*luaL_newmetatable) (lua_State *L, const char *tname);
void (*luaL_setmetatable) (lua_State *L, const char *tname);
void * (*luaL_testudata) (lua_State *L, int ud, const char *tname);
void * (*luaL_checkudata) (lua_State *L, int ud, const char *tname);
void (*luaL_where) (lua_State *L, int lvl);
int (*luaL_checkoption) (lua_State *L, int arg, const char *def,
const char *const lst[]);
int (*luaL_fileresult) (lua_State *L, int stat, const char *fname);
int (*luaL_execresult) (lua_State *L, int stat);
void * (*luaL_alloc) (void *ud, void *ptr, size_t osize,
size_t nsize);
int (*luaL_ref) (lua_State *L, int t);
void (*luaL_unref) (lua_State *L, int t, int ref);
int (*luaL_loadfilex) (lua_State *L, const char *filename,
const char *mode);
int (*luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
const char *name, const char *mode);
int (*luaL_loadstring) (lua_State *L, const char *s);
lua_State * (*luaL_newstate) (void);
unsigned (*luaL_makeseed) (lua_State *L);
lua_Integer (*luaL_len) (lua_State *L, int idx);
void (*luaL_addgsub) (luaL_Buffer *b, const char *s,
const char *p, const char *r);
const char * (*luaL_gsub) (lua_State *L, const char *s,
const char *p, const char *r);
void (*luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
int (*luaL_getsubtable) (lua_State *L, int idx, const char *fname);
void (*luaL_traceback) (lua_State *L, lua_State *L1,
const char *msg, int level);
void (*luaL_requiref) (lua_State *L, const char *modname,
lua_CFunction openf, int glb);
void (*luaL_buffinit) (lua_State *L, luaL_Buffer *B);
char * (*luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
void (*luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
void (*luaL_addstring) (luaL_Buffer *B, const char *s);
void (*luaL_addvalue) (luaL_Buffer *B);
void (*luaL_pushresult) (luaL_Buffer *B);
void (*luaL_pushresultsize) (luaL_Buffer *B, size_t sz);
char * (*luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz);
int (*lua_gc) (lua_State *L, int what, ...);
};
static struct lua_api API;
LUA_API lua_State *
lua_newstate(lua_Alloc f, void *ud, unsigned seed) {
return API.lua_newstate(f,ud,seed);
}
LUA_API void
lua_close(lua_State *L) {
API.lua_close(L);
}
LUA_API lua_State *
lua_newthread(lua_State *L) {
return API.lua_newthread(L);
}
LUA_API int
lua_closethread(lua_State *L, lua_State *from) {
return API.lua_closethread(L,from);
}
LUA_API lua_CFunction
lua_atpanic(lua_State *L, lua_CFunction panicf) {
return API.lua_atpanic(L,panicf);
}
LUA_API lua_Number
lua_version(lua_State *L) {
return API.lua_version(L);
}
LUA_API int
lua_absindex(lua_State *L, int idx) {
return API.lua_absindex(L,idx);
}
LUA_API int
lua_gettop(lua_State *L) {
return API.lua_gettop(L);
}
LUA_API void
lua_settop(lua_State *L, int idx) {
API.lua_settop(L,idx);
}
LUA_API void
lua_pushvalue(lua_State *L, int idx) {
API.lua_pushvalue(L,idx);
}
LUA_API void
lua_rotate(lua_State *L, int idx, int n) {
API.lua_rotate(L,idx,n);
}
LUA_API void
lua_copy(lua_State *L, int fromidx, int toidx) {
API.lua_copy(L,fromidx,toidx);
}
LUA_API int
lua_checkstack(lua_State *L, int n) {
return API.lua_checkstack(L,n);
}
LUA_API void
lua_xmove(lua_State *from, lua_State *to, int n) {
API.lua_xmove(from,to,n);
}
LUA_API int
lua_isnumber(lua_State *L, int idx) {
return API.lua_isnumber(L,idx);
}
LUA_API int
lua_isstring(lua_State *L, int idx) {
return API.lua_isstring(L,idx);
}
LUA_API int
lua_iscfunction(lua_State *L, int idx) {
return API.lua_iscfunction(L,idx);
}
LUA_API int
lua_isinteger(lua_State *L, int idx) {
return API.lua_isinteger(L,idx);
}
LUA_API int
lua_isuserdata(lua_State *L, int idx) {
return API.lua_isuserdata(L,idx);
}
LUA_API int
lua_type(lua_State *L, int idx) {
return API.lua_type(L,idx);
}
LUA_API const char *
lua_typename(lua_State *L, int tp) {
return API.lua_typename(L,tp);
}
LUA_API lua_Number
lua_tonumberx(lua_State *L, int idx, int *isnum) {
return API.lua_tonumberx(L,idx,isnum);
}
LUA_API lua_Integer
lua_tointegerx(lua_State *L, int idx, int *isnum) {
return API.lua_tointegerx(L,idx,isnum);
}
LUA_API int
lua_toboolean(lua_State *L, int idx) {
return API.lua_toboolean(L,idx);
}
LUA_API const char *
lua_tolstring(lua_State *L, int idx, size_t *len) {
return API.lua_tolstring(L,idx,len);
}
LUA_API lua_Unsigned
lua_rawlen(lua_State *L, int idx) {
return API.lua_rawlen(L,idx);
}
LUA_API lua_CFunction
lua_tocfunction(lua_State *L, int idx) {
return API.lua_tocfunction(L,idx);
}
LUA_API void *
lua_touserdata(lua_State *L, int idx) {
return API.lua_touserdata(L,idx);
}
LUA_API lua_State *
lua_tothread(lua_State *L, int idx) {
return API.lua_tothread(L,idx);
}
LUA_API const void *
lua_topointer(lua_State *L, int idx) {
return API.lua_topointer(L,idx);
}
LUA_API void
lua_arith(lua_State *L, int op) {
API.lua_arith(L,op);
}
LUA_API int
lua_rawequal(lua_State *L, int idx1, int idx2) {
return API.lua_rawequal(L,idx1,idx2);
}
LUA_API int
lua_compare(lua_State *L, int idx1, int idx2, int op) {
return API.lua_compare(L,idx1,idx2,op);
}
LUA_API void
lua_pushnil(lua_State *L) {
API.lua_pushnil(L);
}
LUA_API void
lua_pushnumber(lua_State *L, lua_Number n) {
API.lua_pushnumber(L,n);
}
LUA_API void
lua_pushinteger(lua_State *L, lua_Integer n) {
API.lua_pushinteger(L,n);
}
LUA_API const char *
lua_pushlstring(lua_State *L, const char *s, size_t len) {
return API.lua_pushlstring(L,s,len);
}
LUA_API const char *
lua_pushexternalstring(lua_State *L,
const char *s, size_t len, lua_Alloc falloc, void *ud) {
return API.lua_pushexternalstring(L,s,len,falloc,ud);
}
LUA_API const char *
lua_pushstring(lua_State *L, const char *s) {
return API.lua_pushstring(L,s);
}
LUA_API const char *
lua_pushvfstring(lua_State *L, const char *fmt,
va_list argp) {
return API.lua_pushvfstring(L,fmt,argp);
}
LUA_API void
lua_pushcclosure(lua_State *L, lua_CFunction fn, int n) {
API.lua_pushcclosure(L,fn,n);
}
LUA_API void
lua_pushboolean(lua_State *L, int b) {
API.lua_pushboolean(L,b);
}
LUA_API void
lua_pushlightuserdata(lua_State *L, void *p) {
API.lua_pushlightuserdata(L,p);
}
LUA_API int
lua_pushthread(lua_State *L) {
return API.lua_pushthread(L);
}
LUA_API int
lua_getglobal(lua_State *L, const char *name) {
return API.lua_getglobal(L,name);
}
LUA_API int
lua_gettable(lua_State *L, int idx) {
return API.lua_gettable(L,idx);
}
LUA_API int
lua_getfield(lua_State *L, int idx, const char *k) {
return API.lua_getfield(L,idx,k);
}
LUA_API int
lua_geti(lua_State *L, int idx, lua_Integer n) {
return API.lua_geti(L,idx,n);
}
LUA_API int
lua_rawget(lua_State *L, int idx) {
return API.lua_rawget(L,idx);
}
LUA_API int
lua_rawgeti(lua_State *L, int idx, lua_Integer n) {
return API.lua_rawgeti(L,idx,n);
}
LUA_API int
lua_rawgetp(lua_State *L, int idx, const void *p) {
return API.lua_rawgetp(L,idx,p);
}
LUA_API void
lua_createtable(lua_State *L, int narr, int nrec) {
API.lua_createtable(L,narr,nrec);
}
LUA_API void *
lua_newuserdatauv(lua_State *L, size_t sz, int nuvalue) {
return API.lua_newuserdatauv(L,sz,nuvalue);
}
LUA_API int
lua_getmetatable(lua_State *L, int objindex) {
return API.lua_getmetatable(L,objindex);
}
LUA_API int
lua_getiuservalue(lua_State *L, int idx, int n) {
return API.lua_getiuservalue(L,idx,n);
}
LUA_API void
lua_setglobal(lua_State *L, const char *name) {
API.lua_setglobal(L,name);
}
LUA_API void
lua_settable(lua_State *L, int idx) {
API.lua_settable(L,idx);
}
LUA_API void
lua_setfield(lua_State *L, int idx, const char *k) {
API.lua_setfield(L,idx,k);
}
LUA_API void
lua_seti(lua_State *L, int idx, lua_Integer n) {
API.lua_seti(L,idx,n);
}
LUA_API void
lua_rawset(lua_State *L, int idx) {
API.lua_rawset(L,idx);
}
LUA_API void
lua_rawseti(lua_State *L, int idx, lua_Integer n) {
API.lua_rawseti(L,idx,n);
}
LUA_API void
lua_rawsetp(lua_State *L, int idx, const void *p) {
API.lua_rawsetp(L,idx,p);
}
LUA_API int
lua_setmetatable(lua_State *L, int objindex) {
return API.lua_setmetatable(L,objindex);
}
LUA_API int
lua_setiuservalue(lua_State *L, int idx, int n) {
return API.lua_setiuservalue(L,idx,n);
}
LUA_API void
lua_callk(lua_State *L, int nargs, int nresults,
lua_KContext ctx, lua_KFunction k) {
API.lua_callk(L,nargs,nresults,ctx,k);
}
LUA_API int
lua_pcallk(lua_State *L, int nargs, int nresults, int errfunc,
lua_KContext ctx, lua_KFunction k) {
return API.lua_pcallk(L,nargs,nresults,errfunc,ctx,k);
}
LUA_API int
lua_load(lua_State *L, lua_Reader reader, void *dt,
const char *chunkname, const char *mode) {
return API.lua_load(L,reader,dt,chunkname,mode);
}
LUA_API int
lua_dump(lua_State *L, lua_Writer writer, void *data, int strip) {
return API.lua_dump(L,writer,data,strip);
}
LUA_API int
lua_yieldk(lua_State *L, int nresults, lua_KContext ctx,
lua_KFunction k) {
return API.lua_yieldk(L,nresults,ctx,k);
}
LUA_API int
lua_resume(lua_State *L, lua_State *from, int narg,
int *nres) {
return API.lua_resume(L,from,narg,nres);
}
LUA_API int
lua_status(lua_State *L) {
return API.lua_status(L);
}
LUA_API int
lua_isyieldable(lua_State *L) {
return API.lua_isyieldable(L);
}
LUA_API void
lua_setwarnf(lua_State *L, lua_WarnFunction f, void *ud) {
API.lua_setwarnf(L,f,ud);
}
LUA_API void
lua_warning(lua_State *L, const char *msg, int tocont) {
API.lua_warning(L,msg,tocont);
}
LUA_API int
lua_error(lua_State *L) {
return API.lua_error(L);
}
LUA_API int
lua_next(lua_State *L, int idx) {
return API.lua_next(L,idx);
}
LUA_API void
lua_concat(lua_State *L, int n) {
API.lua_concat(L,n);
}
LUA_API void
lua_len(lua_State *L, int idx) {
API.lua_len(L,idx);
}
LUA_API unsigned
lua_numbertocstring(lua_State *L, int idx, char *buff) {
return API.lua_numbertocstring(L,idx,buff);
}
LUA_API size_t
lua_stringtonumber(lua_State *L, const char *s) {
return API.lua_stringtonumber(L,s);
}
LUA_API lua_Alloc
lua_getallocf(lua_State *L, void **ud) {
return API.lua_getallocf(L,ud);
}
LUA_API void
lua_setallocf(lua_State *L, lua_Alloc f, void *ud) {
API.lua_setallocf(L,f,ud);
}
LUA_API void
lua_toclose(lua_State *L, int idx) {
API.lua_toclose(L,idx);
}
LUA_API void
lua_closeslot(lua_State *L, int idx) {
API.lua_closeslot(L,idx);
}
LUA_API int
lua_getstack(lua_State *L, int level, lua_Debug *ar) {
return API.lua_getstack(L,level,ar);
}
LUA_API int
lua_getinfo(lua_State *L, const char *what, lua_Debug *ar) {
return API.lua_getinfo(L,what,ar);
}
LUA_API const char *
lua_getlocal(lua_State *L, const lua_Debug *ar, int n) {
return API.lua_getlocal(L,ar,n);
}
LUA_API const char *
lua_setlocal(lua_State *L, const lua_Debug *ar, int n) {
return API.lua_setlocal(L,ar,n);
}
LUA_API const char *
lua_getupvalue(lua_State *L, int funcindex, int n) {
return API.lua_getupvalue(L,funcindex,n);
}
LUA_API const char *
lua_setupvalue(lua_State *L, int funcindex, int n) {
return API.lua_setupvalue(L,funcindex,n);
}
LUA_API void *
lua_upvalueid(lua_State *L, int fidx, int n) {
return API.lua_upvalueid(L,fidx,n);
}
LUA_API void
lua_upvaluejoin(lua_State *L, int fidx1, int n1,
int fidx2, int n2) {
API.lua_upvaluejoin(L,fidx1,n1,fidx2,n2);
}
LUA_API void
lua_sethook(lua_State *L, lua_Hook func, int mask, int count) {
API.lua_sethook(L,func,mask,count);
}
LUA_API lua_Hook
lua_gethook(lua_State *L) {
return API.lua_gethook(L);
}
LUA_API int
lua_gethookmask(lua_State *L) {
return API.lua_gethookmask(L);
}
LUA_API int
lua_gethookcount(lua_State *L) {
return API.lua_gethookcount(L);
}
LUA_API void
luaL_checkversion_(lua_State *L, lua_Number ver, size_t sz) {
API.luaL_checkversion_(L,ver,sz);
}
LUA_API int
luaL_getmetafield(lua_State *L, int obj, const char *e) {
return API.luaL_getmetafield(L,obj,e);
}
LUA_API int
luaL_callmeta(lua_State *L, int obj, const char *e) {
return API.luaL_callmeta(L,obj,e);
}
LUA_API const char *
luaL_tolstring(lua_State *L, int idx, size_t *len) {
return API.luaL_tolstring(L,idx,len);
}
LUA_API int
luaL_argerror(lua_State *L, int arg, const char *extramsg) {
return API.luaL_argerror(L,arg,extramsg);
}
LUA_API int
luaL_typeerror(lua_State *L, int arg, const char *tname) {
return API.luaL_typeerror(L,arg,tname);
}
LUA_API const char *
luaL_checklstring(lua_State *L, int arg,
size_t *l) {
return API.luaL_checklstring(L,arg,l);
}
LUA_API const char *
luaL_optlstring(lua_State *L, int arg,
const char *def, size_t *l) {
return API.luaL_optlstring(L,arg,def,l);
}
LUA_API lua_Number
luaL_checknumber(lua_State *L, int arg) {
return API.luaL_checknumber(L,arg);
}
LUA_API lua_Number
luaL_optnumber(lua_State *L, int arg, lua_Number def) {
return API.luaL_optnumber(L,arg,def);
}
LUA_API lua_Integer
luaL_checkinteger(lua_State *L, int arg) {
return API.luaL_checkinteger(L,arg);
}
LUA_API lua_Integer
luaL_optinteger(lua_State *L, int arg,
lua_Integer def) {
return API.luaL_optinteger(L,arg,def);
}
LUA_API void
luaL_checkstack(lua_State *L, int sz, const char *msg) {
API.luaL_checkstack(L,sz,msg);
}
LUA_API void
luaL_checktype(lua_State *L, int arg, int t) {
API.luaL_checktype(L,arg,t);
}
LUA_API void
luaL_checkany(lua_State *L, int arg) {
API.luaL_checkany(L,arg);
}
LUA_API int
luaL_newmetatable(lua_State *L, const char *tname) {
return API.luaL_newmetatable(L,tname);
}
LUA_API void
luaL_setmetatable(lua_State *L, const char *tname) {
API.luaL_setmetatable(L,tname);
}
LUA_API void *
luaL_testudata(lua_State *L, int ud, const char *tname) {
return API.luaL_testudata(L,ud,tname);
}
LUA_API void *
luaL_checkudata(lua_State *L, int ud, const char *tname) {
return API.luaL_checkudata(L,ud,tname);
}
LUA_API void
luaL_where(lua_State *L, int lvl) {
API.luaL_where(L,lvl);
}
LUA_API int
luaL_checkoption(lua_State *L, int arg, const char *def,
const char *const lst[]) {
return API.luaL_checkoption(L,arg,def,lst);
}
LUA_API int
luaL_fileresult(lua_State *L, int stat, const char *fname) {
return API.luaL_fileresult(L,stat,fname);
}
LUA_API int
luaL_execresult(lua_State *L, int stat) {
return API.luaL_execresult(L,stat);
}
LUA_API void *
luaL_alloc(void *ud, void *ptr, size_t osize,
size_t nsize) {
return API.luaL_alloc(ud,ptr,osize,nsize);
}
LUA_API int
luaL_ref(lua_State *L, int t) {
return API.luaL_ref(L,t);
}
LUA_API void
luaL_unref(lua_State *L, int t, int ref) {
API.luaL_unref(L,t,ref);
}
LUA_API int
luaL_loadfilex(lua_State *L, const char *filename,
const char *mode) {
return API.luaL_loadfilex(L,filename,mode);
}
LUA_API int
luaL_loadbufferx(lua_State *L, const char *buff, size_t sz,
const char *name, const char *mode) {
return API.luaL_loadbufferx(L,buff,sz,name,mode);
}
LUA_API int
luaL_loadstring(lua_State *L, const char *s) {
return API.luaL_loadstring(L,s);
}
LUA_API lua_State *
luaL_newstate(void) {
return API.luaL_newstate();
}
LUA_API unsigned
luaL_makeseed(lua_State *L) {
return API.luaL_makeseed(L);
}
LUA_API lua_Integer
luaL_len(lua_State *L, int idx) {
return API.luaL_len(L,idx);
}
LUA_API void
luaL_addgsub(luaL_Buffer *b, const char *s,
const char *p, const char *r) {
API.luaL_addgsub(b,s,p,r);
}
LUA_API const char *
luaL_gsub(lua_State *L, const char *s,
const char *p, const char *r) {
return API.luaL_gsub(L,s,p,r);
}
LUA_API void
luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) {
API.luaL_setfuncs(L,l,nup);
}
LUA_API int
luaL_getsubtable(lua_State *L, int idx, const char *fname) {
return API.luaL_getsubtable(L,idx,fname);
}
LUA_API void
luaL_traceback(lua_State *L, lua_State *L1,
const char *msg, int level) {
API.luaL_traceback(L,L1,msg,level);
}
LUA_API void
luaL_requiref(lua_State *L, const char *modname,
lua_CFunction openf, int glb) {
API.luaL_requiref(L,modname,openf,glb);
}
LUA_API void
luaL_buffinit(lua_State *L, luaL_Buffer *B) {
API.luaL_buffinit(L,B);
}
LUA_API char *
luaL_prepbuffsize(luaL_Buffer *B, size_t sz) {
return API.luaL_prepbuffsize(B,sz);
}
LUA_API void
luaL_addlstring(luaL_Buffer *B, const char *s, size_t l) {
API.luaL_addlstring(B,s,l);
}
LUA_API void
luaL_addstring(luaL_Buffer *B, const char *s) {
API.luaL_addstring(B,s);
}
LUA_API void
luaL_addvalue(luaL_Buffer *B) {
API.luaL_addvalue(B);
}
LUA_API void
luaL_pushresult(luaL_Buffer *B) {
API.luaL_pushresult(B);
}
LUA_API void
luaL_pushresultsize(luaL_Buffer *B, size_t sz) {
API.luaL_pushresultsize(B,sz);
}
LUA_API char *
luaL_buffinitsize(lua_State *L, luaL_Buffer *B, size_t sz) {
return API.luaL_buffinitsize(L,B,sz);
}
LUA_API
const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
const char *ret;
va_list argp;
va_start(argp, fmt);
ret = API.lua_pushvfstring(L, fmt, argp);
va_end(argp);
return ret;
}
LUA_API int
lua_gc (lua_State *L, int what, ...) {
va_list argp;
va_start(argp, what);
int p1 = va_arg(argp, int);
int p2 = va_arg(argp, int);
int p3 = va_arg(argp, int);
va_end(argp);
return API.lua_gc(L, what, p1, p2, p3);
}
LUA_API int
luaL_error(lua_State *L, const char *fmt, ...) {
va_list argp;
va_start(argp, fmt);
luaL_where(L, 1);
lua_pushvfstring(L, fmt, argp);
va_end(argp);
lua_concat(L, 2);
return lua_error(L);
}
static void
stub_luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
}
static void stub_lua_createtable (lua_State *L, int narr, int nrec) {
}
static void stub_luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
}
struct sokol_api;
struct soluna_api;
struct extlua_apis {
struct lua_api * lua;
struct sokol_api * sokol;
struct soluna_api * soluna;
};
LUA_API void
luaapi_init(lua_State *L) {
struct extlua_apis *apis = *(struct extlua_apis **)lua_getextraspace(L);
struct lua_api * api = apis->lua;
if (api->version == LUA_VERSION_NUM) {
API = *api;
return;
}
// stub for luaL_newlib
API.luaL_checkversion_ = stub_luaL_checkversion_;
API.lua_createtable = stub_lua_createtable;
API.luaL_setfuncs = stub_luaL_setfuncs;
}
================================================
FILE: extlua/extlua.temp.c
================================================
#include <lua.h>
#include <lauxlib.h>
#include <stdarg.h>
#include <assert.h>
#include <stdio.h>
struct lua_api {
int version;
$API_DECL$
};
static struct lua_api API;
$API_IMPL$
LUA_API
const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
const char *ret;
va_list argp;
va_start(argp, fmt);
ret = API.lua_pushvfstring(L, fmt, argp);
va_end(argp);
return ret;
}
LUA_API int
lua_gc (lua_State *L, int what, ...) {
va_list argp;
va_start(argp, what);
int p1 = va_arg(argp, int);
int p2 = va_arg(argp, int);
int p3 = va_arg(argp, int);
va_end(argp);
return API.lua_gc(L, what, p1, p2, p3);
}
LUA_API int
luaL_error(lua_State *L, const char *fmt, ...) {
va_list argp;
va_start(argp, fmt);
luaL_where(L, 1);
lua_pushvfstring(L, fmt, argp);
va_end(argp);
lua_concat(L, 2);
return lua_error(L);
}
static void
stub_luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
}
static void stub_lua_createtable (lua_State *L, int narr, int nrec) {
}
static void stub_luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
}
struct sokol_api;
struct soluna_api;
struct extlua_apis {
struct lua_api * lua;
struct sokol_api * sokol;
struct soluna_api * soluna;
};
LUA_API void
luaapi_init(lua_State *L) {
struct extlua_apis *apis = *(struct extlua_apis **)lua_getextraspace(L);
struct lua_api * api = apis->lua;
if (api->version == LUA_VERSION_NUM) {
API = *api;
return;
}
// stub for luaL_newlib
API.luaL_checkversion_ = stub_luaL_checkversion_;
API.lua_createtable = stub_lua_createtable;
API.luaL_setfuncs = stub_luaL_setfuncs;
}
================================================
FILE: extlua/extlua_impl.c
================================================
// AUTO GENERATED by extlua_impl.temp.c, DONT EDIT
#include <lua.h>
#include <lauxlib.h>
struct lua_api {
int version;
lua_State * (*lua_newstate) (lua_Alloc f, void *ud, unsigned seed);
void (*lua_close) (lua_State *L);
lua_State * (*lua_newthread) (lua_State *L);
int (*lua_closethread) (lua_State *L, lua_State *from);
lua_CFunction (*lua_atpanic) (lua_State *L, lua_CFunction panicf);
lua_Number (*lua_version) (lua_State *L);
int (*lua_absindex) (lua_State *L, int idx);
int (*lua_gettop) (lua_State *L);
void (*lua_settop) (lua_State *L, int idx);
void (*lua_pushvalue) (lua_State *L, int idx);
void (*lua_rotate) (lua_State *L, int idx, int n);
void (*lua_copy) (lua_State *L, int fromidx, int toidx);
int (*lua_checkstack) (lua_State *L, int n);
void (*lua_xmove) (lua_State *from, lua_State *to, int n);
int (*lua_isnumber) (lua_State *L, int idx);
int (*lua_isstring) (lua_State *L, int idx);
int (*lua_iscfunction) (lua_State *L, int idx);
int (*lua_isinteger) (lua_State *L, int idx);
int (*lua_isuserdata) (lua_State *L, int idx);
int (*lua_type) (lua_State *L, int idx);
const char * (*lua_typename) (lua_State *L, int tp);
lua_Number (*lua_tonumberx) (lua_State *L, int idx, int *isnum);
lua_Integer (*lua_tointegerx) (lua_State *L, int idx, int *isnum);
int (*lua_toboolean) (lua_State *L, int idx);
const char * (*lua_tolstring) (lua_State *L, int idx, size_t *len);
lua_Unsigned (*lua_rawlen) (lua_State *L, int idx);
lua_CFunction (*lua_tocfunction) (lua_State *L, int idx);
void * (*lua_touserdata) (lua_State *L, int idx);
lua_State * (*lua_tothread) (lua_State *L, int idx);
const void * (*lua_topointer) (lua_State *L, int idx);
void (*lua_arith) (lua_State *L, int op);
int (*lua_rawequal) (lua_State *L, int idx1, int idx2);
int (*lua_compare) (lua_State *L, int idx1, int idx2, int op);
void (*lua_pushnil) (lua_State *L);
void (*lua_pushnumber) (lua_State *L, lua_Number n);
void (*lua_pushinteger) (lua_State *L, lua_Integer n);
const char * (*lua_pushlstring) (lua_State *L, const char *s, size_t len);
const char * (*lua_pushexternalstring) (lua_State *L,
const char *s, size_t len, lua_Alloc falloc, void *ud);
const char * (*lua_pushstring) (lua_State *L, const char *s);
const char * (*lua_pushvfstring) (lua_State *L, const char *fmt,
va_list argp);
void (*lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
void (*lua_pushboolean) (lua_State *L, int b);
void (*lua_pushlightuserdata) (lua_State *L, void *p);
int (*lua_pushthread) (lua_State *L);
int (*lua_getglobal) (lua_State *L, const char *name);
int (*lua_gettable) (lua_State *L, int idx);
int (*lua_getfield) (lua_State *L, int idx, const char *k);
int (*lua_geti) (lua_State *L, int idx, lua_Integer n);
int (*lua_rawget) (lua_State *L, int idx);
int (*lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
int (*lua_rawgetp) (lua_State *L, int idx, const void *p);
void (*lua_createtable) (lua_State *L, int narr, int nrec);
void * (*lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
int (*lua_getmetatable) (lua_State *L, int objindex);
int (*lua_getiuservalue) (lua_State *L, int idx, int n);
void (*lua_setglobal) (lua_State *L, const char *name);
void (*lua_settable) (lua_State *L, int idx);
void (*lua_setfield) (lua_State *L, int idx, const char *k);
void (*lua_seti) (lua_State *L, int idx, lua_Integer n);
void (*lua_rawset) (lua_State *L, int idx);
void (*lua_rawseti) (lua_State *L, int idx, lua_Integer n);
void (*lua_rawsetp) (lua_State *L, int idx, const void *p);
int (*lua_setmetatable) (lua_State *L, int objindex);
int (*lua_setiuservalue) (lua_State *L, int idx, int n);
void (*lua_callk) (lua_State *L, int nargs, int nresults,
lua_KContext ctx, lua_KFunction k);
int (*lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
lua_KContext ctx, lua_KFunction k);
int (*lua_load) (lua_State *L, lua_Reader reader, void *dt,
const char *chunkname, const char *mode);
int (*lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip);
int (*lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx,
lua_KFunction k);
int (*lua_resume) (lua_State *L, lua_State *from, int narg,
int *nres);
int (*lua_status) (lua_State *L);
int (*lua_isyieldable) (lua_State *L);
void (*lua_setwarnf) (lua_State *L, lua_WarnFunction f, void *ud);
void (*lua_warning) (lua_State *L, const char *msg, int tocont);
int (*lua_error) (lua_State *L);
int (*lua_next) (lua_State *L, int idx);
void (*lua_concat) (lua_State *L, int n);
void (*lua_len) (lua_State *L, int idx);
unsigned (*lua_numbertocstring) (lua_State *L, int idx, char *buff);
size_t (*lua_stringtonumber) (lua_State *L, const char *s);
lua_Alloc (*lua_getallocf) (lua_State *L, void **ud);
void (*lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
void (*lua_toclose) (lua_State *L, int idx);
void (*lua_closeslot) (lua_State *L, int idx);
int (*lua_getstack) (lua_State *L, int level, lua_Debug *ar);
int (*lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar);
const char * (*lua_getlocal) (lua_State *L, const lua_Debug *ar, int n);
const char * (*lua_setlocal) (lua_State *L, const lua_Debug *ar, int n);
const char * (*lua_getupvalue) (lua_State *L, int funcindex, int n);
const char * (*lua_setupvalue) (lua_State *L, int funcindex, int n);
void * (*lua_upvalueid) (lua_State *L, int fidx, int n);
void (*lua_upvaluejoin) (lua_State *L, int fidx1, int n1,
int fidx2, int n2);
void (*lua_sethook) (lua_State *L, lua_Hook func, int mask, int count);
lua_Hook (*lua_gethook) (lua_State *L);
int (*lua_gethookmask) (lua_State *L);
int (*lua_gethookcount) (lua_State *L);
void (*luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz);
int (*luaL_getmetafield) (lua_State *L, int obj, const char *e);
int (*luaL_callmeta) (lua_State *L, int obj, const char *e);
const char * (*luaL_tolstring) (lua_State *L, int idx, size_t *len);
int (*luaL_argerror) (lua_State *L, int arg, const char *extramsg);
int (*luaL_typeerror) (lua_State *L, int arg, const char *tname);
const char * (*luaL_checklstring) (lua_State *L, int arg,
size_t *l);
const char * (*luaL_optlstring) (lua_State *L, int arg,
const char *def, size_t *l);
lua_Number (*luaL_checknumber) (lua_State *L, int arg);
lua_Number (*luaL_optnumber) (lua_State *L, int arg, lua_Number def);
lua_Integer (*luaL_checkinteger) (lua_State *L, int arg);
lua_Integer (*luaL_optinteger) (lua_State *L, int arg,
lua_Integer def);
void (*luaL_checkstack) (lua_State *L, int sz, const char *msg);
void (*luaL_checktype) (lua_State *L, int arg, int t);
void (*luaL_checkany) (lua_State *L, int arg);
int (*luaL_newmetatable) (lua_State *L, const char *tname);
void (*luaL_setmetatable) (lua_State *L, const char *tname);
void * (*luaL_testudata) (lua_State *L, int ud, const char *tname);
void * (*luaL_checkudata) (lua_State *L, int ud, const char *tname);
void (*luaL_where) (lua_State *L, int lvl);
int (*luaL_checkoption) (lua_State *L, int arg, const char *def,
const char *const lst[]);
int (*luaL_fileresult) (lua_State *L, int stat, const char *fname);
int (*luaL_execresult) (lua_State *L, int stat);
void * (*luaL_alloc) (void *ud, void *ptr, size_t osize,
size_t nsize);
int (*luaL_ref) (lua_State *L, int t);
void (*luaL_unref) (lua_State *L, int t, int ref);
int (*luaL_loadfilex) (lua_State *L, const char *filename,
const char *mode);
int (*luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
const char *name, const char *mode);
int (*luaL_loadstring) (lua_State *L, const char *s);
lua_State * (*luaL_newstate) (void);
unsigned (*luaL_makeseed) (lua_State *L);
lua_Integer (*luaL_len) (lua_State *L, int idx);
void (*luaL_addgsub) (luaL_Buffer *b, const char *s,
const char *p, const char *r);
const char * (*luaL_gsub) (lua_State *L, const char *s,
const char *p, const char *r);
void (*luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
int (*luaL_getsubtable) (lua_State *L, int idx, const char *fname);
void (*luaL_traceback) (lua_State *L, lua_State *L1,
const char *msg, int level);
void (*luaL_requiref) (lua_State *L, const char *modname,
lua_CFunction openf, int glb);
void (*luaL_buffinit) (lua_State *L, luaL_Buffer *B);
char * (*luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
void (*luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
void (*luaL_addstring) (luaL_Buffer *B, const char *s);
void (*luaL_addvalue) (luaL_Buffer *B);
void (*luaL_pushresult) (luaL_Buffer *B);
void (*luaL_pushresultsize) (luaL_Buffer *B, size_t sz);
char * (*luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz);
int (*lua_gc) (lua_State *L, int what, ...);
};
struct lua_api *
extlua_api() {
static struct lua_api api = {
LUA_VERSION_NUM,
lua_newstate,
lua_close,
lua_newthread,
lua_closethread,
lua_atpanic,
lua_version,
lua_absindex,
lua_gettop,
lua_settop,
lua_pushvalue,
lua_rotate,
lua_copy,
lua_checkstack,
lua_xmove,
lua_isnumber,
lua_isstring,
lua_iscfunction,
lua_isinteger,
lua_isuserdata,
lua_type,
lua_typename,
lua_tonumberx,
lua_tointegerx,
lua_toboolean,
lua_tolstring,
lua_rawlen,
lua_tocfunction,
lua_touserdata,
lua_tothread,
lua_topointer,
lua_arith,
lua_rawequal,
lua_compare,
lua_pushnil,
lua_pushnumber,
lua_pushinteger,
lua_pushlstring,
lua_pushexternalstring,
lua_pushstring,
lua_pushvfstring,
lua_pushcclosure,
lua_pushboolean,
lua_pushlightuserdata,
lua_pushthread,
lua_getglobal,
lua_gettable,
lua_getfield,
lua_geti,
lua_rawget,
lua_rawgeti,
lua_rawgetp,
lua_createtable,
lua_newuserdatauv,
lua_getmetatable,
lua_getiuservalue,
lua_setglobal,
lua_settable,
lua_setfield,
lua_seti,
lua_rawset,
lua_rawseti,
lua_rawsetp,
lua_setmetatable,
lua_setiuservalue,
lua_callk,
lua_pcallk,
lua_load,
lua_dump,
lua_yieldk,
lua_resume,
lua_status,
lua_isyieldable,
lua_setwarnf,
lua_warning,
lua_error,
lua_next,
lua_concat,
lua_len,
lua_numbertocstring,
lua_stringtonumber,
lua_getallocf,
lua_setallocf,
lua_toclose,
lua_closeslot,
lua_getstack,
lua_getinfo,
lua_getlocal,
lua_setlocal,
lua_getupvalue,
lua_setupvalue,
lua_upvalueid,
lua_upvaluejoin,
lua_sethook,
lua_gethook,
lua_gethookmask,
lua_gethookcount,
luaL_checkversion_,
luaL_getmetafield,
luaL_callmeta,
luaL_tolstring,
luaL_argerror,
luaL_typeerror,
luaL_checklstring,
luaL_optlstring,
luaL_checknumber,
luaL_optnumber,
luaL_checkinteger,
luaL_optinteger,
luaL_checkstack,
luaL_checktype,
luaL_checkany,
luaL_newmetatable,
luaL_setmetatable,
luaL_testudata,
luaL_checkudata,
luaL_where,
luaL_checkoption,
luaL_fileresult,
luaL_execresult,
luaL_alloc,
luaL_ref,
luaL_unref,
luaL_loadfilex,
luaL_loadbufferx,
luaL_loadstring,
luaL_newstate,
luaL_makeseed,
luaL_len,
luaL_addgsub,
luaL_gsub,
luaL_setfuncs,
luaL_getsubtable,
luaL_traceback,
luaL_requiref,
luaL_buffinit,
luaL_prepbuffsize,
luaL_addlstring,
luaL_addstring,
luaL_addvalue,
luaL_pushresult,
luaL_pushresultsize,
luaL_buffinitsize,
lua_gc,
};
return &api;
}
================================================
FILE: extlua/extlua_impl.temp.c
================================================
#include <lua.h>
#include <lauxlib.h>
struct lua_api {
int version;
$API_DECL$
};
struct lua_api *
extlua_api() {
static struct lua_api api = {
LUA_VERSION_NUM,
$API_STRUCT$
};
return &api;
}
================================================
FILE: extlua/extlua_sample.c
================================================
#include <lua.h>
#include <lauxlib.h>
#include <stdint.h>
#include <stddef.h>
#include "sokol/sokol_gfx.h"
#include "perspective_quad.glsl.h"
#include "solunaapi.h"
LUA_API void luaapi_init(lua_State *L);
void sokolapi_init(lua_State *L);
#if defined(_WIN32)
#define EXTLUA_EXPORT __declspec(dllexport)
#else
#define EXTLUA_EXPORT __attribute__((visibility("default")))
#endif
#define PQUAD_CORNER_N 4
#define PQUAD_INFO_CORNER_MASK 0x3u
#define PQUAD_INFO_USE_SPRITE_RECT 0x4u
#define PQUAD_EPSILON 0.000001f
struct color {
unsigned char channel[4];
};
struct pquad_payload {
uint32_t info;
float q;
struct color color;
};
struct pquad_inst {
float pos_h0[3];
float pos_h1[3];
float pos_h2[3];
float uv_rect[4];
float q[4];
struct color color;
};
struct material_perspective_quad {
sg_pipeline pip;
sg_buffer inst;
struct soluna_render_bindings bind;
int base;
vs_params_t *uniform;
struct soluna_sprite_bank bank;
void *tmp_ptr;
size_t tmp_size;
};
struct sprite_rect_basis {
float scale_x;
float scale_y;
float shear_x;
float shear_y;
float tx;
float ty;
};
static int material_id = 0;
static void *
free_material_stream(void *ud, void *ptr, size_t osize, size_t nsize) {
(void)ud;
(void)osize;
if (nsize == 0) {
soluna_material_stream_free(ptr);
}
return NULL;
}
static sg_pipeline
make_pipeline(sg_pipeline_desc *desc) {
sg_shader shd = sg_make_shader(perspective_quad_shader_desc(sg_query_backend()));
desc->shader = shd;
desc->primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP;
desc->label = "extlua-perspective-quad-pipeline";
desc->layout.buffers[0].step_func = SG_VERTEXSTEP_PER_INSTANCE;
desc->colors[0].blend = (sg_blend_state) {
.enabled = true,
.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA,
.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
.src_factor_alpha = SG_BLENDFACTOR_ONE,
.dst_factor_alpha = SG_BLENDFACTOR_ZERO,
};
return sg_make_pipeline(desc);
}
static void
set_position_homography(const float pos[PQUAD_CORNER_N][2], struct pquad_inst *inst) {
const float x0 = pos[0][0], y0 = pos[0][1];
const float x1 = pos[1][0], y1 = pos[1][1];
const float x2 = pos[2][0], y2 = pos[2][1];
const float x3 = pos[3][0], y3 = pos[3][1];
const float sx = x0 - x1 + x3 - x2;
const float sy = y0 - y1 + y3 - y2;
const float dx1 = x1 - x3;
const float dx2 = x2 - x3;
const float dy1 = y1 - y3;
const float dy2 = y2 - y3;
const float det = dx1 * dy2 - dx2 * dy1;
float m31 = 0.0f;
float m32 = 0.0f;
float abs_det = det < 0.0f ? -det : det;
if (abs_det > PQUAD_EPSILON) {
m31 = (sx * dy2 - sy * dx2) / det;
m32 = (sy * dx1 - sx * dy1) / det;
}
const float m11 = x1 - x0 + m31 * x1;
const float m12 = x2 - x0 + m32 * x2;
const float m13 = x0;
const float m21 = y1 - y0 + m31 * y1;
const float m22 = y2 - y0 + m32 * y2;
const float m23 = y0;
inst->pos_h0[0] = m11;
inst->pos_h0[1] = m21;
inst->pos_h0[2] = m31;
inst->pos_h1[0] = m12;
inst->pos_h1[1] = m22;
inst->pos_h1[2] = m32;
inst->pos_h2[0] = m13;
inst->pos_h2[1] = m23;
inst->pos_h2[2] = 1.0f;
}
static inline soluna_material_error
perspective_quad_count(int prim_n, int *out) {
if (prim_n % PQUAD_CORNER_N != 0) {
return "Invalid perspective quad primitive count";
}
*out = prim_n / PQUAD_CORNER_N;
return NULL;
}
static inline void
decode_sprite_rect_basis(struct sprite_rect_basis *basis, uint32_t corner, const struct soluna_material_stream_data *item) {
float x = item->x;
float y = item->y;
switch (corner) {
case 0:
basis->scale_x = x;
basis->scale_y = y;
break;
case 1:
basis->shear_x = x;
basis->shear_y = y;
break;
case 2:
basis->tx = x;
basis->ty = y;
break;
}
}
static inline void
build_quad_from_rect(const struct sprite_rect_basis *basis, const struct soluna_sprite_rect *rect, float pos[PQUAD_CORNER_N][2]) {
float scale_x = basis->scale_x - basis->tx;
float scale_y = basis->scale_y - basis->ty;
float shear_x = basis->shear_x - basis->tx;
float shear_y = basis->shear_y - basis->ty;
int corner;
for (corner=0; corner<PQUAD_CORNER_N; corner++) {
float x = (corner & 1) ? (rect->w - rect->ox) : -rect->ox;
float y = (corner >> 1) ? (rect->h - rect->oy) : -rect->oy;
pos[corner][0] = x * scale_x + y * shear_x + basis->tx;
pos[corner][1] = x * shear_y + y * scale_y + basis->ty;
}
}
static void
submit(void *m_, struct soluna_material_stream_context ctx, int n) {
struct material_perspective_quad *m = (struct material_perspective_quad *)m_;
struct pquad_inst *tmp = (struct pquad_inst *)m->tmp_ptr;
int out_n;
soluna_material_error err = perspective_quad_count(n, &out_n);
if (err != NULL) {
soluna_material_stream_error(ctx, err);
return;
}
int i;
for (i=0; i<out_n; i++) {
struct pquad_inst *inst = &tmp[i];
int base = i * PQUAD_CORNER_N;
int j;
int sprite = -1;
uint32_t stream_flags = 0;
struct sprite_rect_basis sprite_rect_basis = { 0 };
float pos[PQUAD_CORNER_N][2];
for (j=0; j<PQUAD_CORNER_N; j++) {
struct soluna_material_stream_data item;
struct pquad_payload payload;
if (!soluna_material_stream_read(ctx, base + j, sizeof(payload), &payload, &item)) {
return;
}
uint32_t flags = payload.info & PQUAD_INFO_USE_SPRITE_RECT;
if (j == 0) {
sprite = item.sprite;
stream_flags = flags;
inst->color = payload.color;
} else if (item.sprite != sprite || flags != stream_flags) {
soluna_material_stream_error(ctx, "Invalid perspective quad stream");
return;
}
uint32_t corner = payload.info & PQUAD_INFO_CORNER_MASK;
if (corner >= PQUAD_CORNER_N) {
soluna_material_stream_error(ctx, "Invalid perspective quad corner");
return;
}
if (stream_flags & PQUAD_INFO_USE_SPRITE_RECT) {
decode_sprite_rect_basis(&sprite_rect_basis, corner, &item);
} else {
pos[corner][0] = item.x;
pos[corner][1] = item.y;
}
float q = payload.q;
if (q <= PQUAD_EPSILON) {
q = PQUAD_EPSILON;
}
inst->q[corner] = q;
}
struct soluna_sprite_rect sprite_rect;
if (!soluna_material_sprite_rect(m->bank, sprite, &sprite_rect)) {
soluna_material_stream_error(ctx, "Invalid perspective quad sprite");
return;
}
if (stream_flags & PQUAD_INFO_USE_SPRITE_RECT) {
build_quad_from_rect(&sprite_rect_basis, &sprite_rect, pos);
}
set_position_homography(pos, inst);
inst->uv_rect[0] = sprite_rect.u;
inst->uv_rect[1] = sprite_rect.v;
inst->uv_rect[2] = sprite_rect.w;
inst->uv_rect[3] = sprite_rect.h;
}
sg_append_buffer(m->inst, &(sg_range) { tmp, out_n * sizeof(tmp[0]) });
}
static int
lmaterial_perspective_quad_submit(lua_State *L) {
struct material_perspective_quad *m = (struct material_perspective_quad *)luaL_checkudata(L, 1, "EXTLUA_MATERIAL_PERSPECTIVE_QUAD");
int inst_batch_n = (int)(m->tmp_size / sizeof(struct pquad_inst));
if (inst_batch_n < 1) {
return luaL_error(L, "Perspective quad tmp buffer is too small");
}
const void *stream = lua_touserdata(L, 2);
int prim_n = luaL_checkinteger(L, 3);
soluna_material_error err = soluna_material_submit(stream, prim_n, material_id, inst_batch_n * PQUAD_CORNER_N, m, submit);
if (err != NULL) {
return luaL_error(L, "%s", err);
}
return 0;
}
static int
lmaterial_perspective_quad_draw(lua_State *L) {
struct material_perspective_quad *m = (struct material_perspective_quad *)luaL_checkudata(L, 1, "EXTLUA_MATERIAL_PERSPECTIVE_QUAD");
int prim_n = luaL_checkinteger(L, 3);
if (prim_n <= 0) {
return 0;
}
int quad_n;
soluna_material_error err = perspective_quad_count(prim_n, &quad_n);
if (err != NULL) {
return luaL_error(L, "%s", err);
}
sg_apply_pipeline(m->pip);
sg_apply_uniforms(UB_vs_params, &(sg_range) { m->uniform, sizeof(vs_params_t) });
sg_bindings bindings = soluna_material_bindings(m->bind);
bindings.vertex_buffer_offsets[0] += (size_t)m->base * sizeof(struct pquad_inst);
sg_apply_bindings(&bindings);
sg_draw(0, 4, quad_n);
m->base += quad_n;
return 0;
}
static int
lmaterial_perspective_quad_reset(lua_State *L) {
struct material_perspective_quad *m = (struct material_perspective_quad *)luaL_checkudata(L, 1, "EXTLUA_MATERIAL_PERSPECTIVE_QUAD");
m->base = 0;
return 0;
}
static int
lset_material_id(lua_State *L) {
int id = luaL_checkinteger(L, 1);
if (id <= 0) {
return luaL_error(L, "Invalid perspective quad material id %d", id);
}
material_id = id;
return 0;
}
static void
init_pipeline(struct material_perspective_quad *p) {
sg_pipeline_desc desc = {
.layout.attrs = {
[ATTR_perspective_quad_pos_h0].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_perspective_quad_pos_h1].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_perspective_quad_pos_h2].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_perspective_quad_uv_rect].format = SG_VERTEXFORMAT_FLOAT4,
[ATTR_perspective_quad_q].format = SG_VERTEXFORMAT_FLOAT4,
[ATTR_perspective_quad_color].format = SG_VERTEXFORMAT_UBYTE4N,
},
};
p->pip = make_pipeline(&desc);
}
static int
lnew_material_perspective_quad(lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
struct material_perspective_quad *m = (struct material_perspective_quad *)lua_newuserdatauv(L, sizeof(*m), 4);
int material_index = lua_gettop(L);
init_pipeline(m);
m->base = 0;
if (lua_getfield(L, 1, "inst_buffer") != LUA_TUSERDATA) {
return luaL_error(L, "Invalid key .inst_buffer");
}
luaL_checkudata(L, -1, "SOKOL_BUFFER");
lua_pushvalue(L, -1);
lua_setiuservalue(L, material_index, 1);
lua_pushlightuserdata(L, &m->inst);
lua_call(L, 1, 0);
if (lua_getfield(L, 1, "bindings") != LUA_TUSERDATA) {
return luaL_error(L, "Invalid key .bindings");
}
m->bind = (struct soluna_render_bindings) {
.ctx = luaL_checkudata(L, -1, "SOKOL_BINDINGS"),
};
lua_pushvalue(L, -1);
lua_setiuservalue(L, material_index, 2);
lua_pop(L, 1);
if (lua_getfield(L, 1, "uniform") != LUA_TUSERDATA) {
return luaL_error(L, "Invalid key .uniform");
}
m->uniform = (vs_params_t *)luaL_checkudata(L, -1, "SOKOL_UNIFORM");
lua_pushvalue(L, -1);
lua_setiuservalue(L, material_index, 3);
lua_pop(L, 1);
if (lua_getfield(L, 1, "sprite_bank") != LUA_TLIGHTUSERDATA) {
return luaL_error(L, "Invalid key .sprite_bank");
}
m->bank = (struct soluna_sprite_bank) {
.ctx = lua_touserdata(L, -1),
};
lua_pop(L, 1);
if (lua_getfield(L, 1, "tmp_buffer") != LUA_TUSERDATA) {
return luaL_error(L, "Invalid key .tmp_buffer");
}
if (lua_getmetatable(L, -1)) {
return luaL_error(L, "Not an userdata without metatable");
}
m->tmp_ptr = lua_touserdata(L, -1);
m->tmp_size = lua_rawlen(L, -1);
lua_setiuservalue(L, material_index, 4);
if (luaL_newmetatable(L, "EXTLUA_MATERIAL_PERSPECTIVE_QUAD")) {
luaL_Reg l[] = {
{ "__index", NULL },
{ "reset", lmaterial_perspective_quad_reset },
{ "submit", lmaterial_perspective_quad_submit },
{ "draw", lmaterial_perspective_quad_draw },
{ NULL, NULL },
};
luaL_setfuncs(L, l, 0);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
}
lua_setmetatable(L, -2);
return 1;
}
static inline float
get_number_field(lua_State *L, int index, const char *field, float defv) {
float v;
lua_getfield(L, index, field);
v = luaL_optnumber(L, -1, defv);
lua_pop(L, 1);
return v;
}
static int
get_quad(lua_State *L, int index, float quad[8]) {
if (lua_getfield(L, index, "quad") == LUA_TTABLE) {
int i;
for (i=0; i<8; i++) {
lua_geti(L, -1, i + 1);
quad[i] = luaL_checknumber(L, -1);
lua_pop(L, 1);
}
lua_pop(L, 1);
return 0;
}
lua_pop(L, 1);
return 1;
}
static void
get_q(lua_State *L, int index, float q[4]) {
int i;
if (lua_getfield(L, index, "q") != LUA_TTABLE) {
for (i=0; i<4; i++) {
q[i] = 1.0f;
}
lua_pop(L, 1);
return;
}
for (i=0; i<4; i++) {
lua_geti(L, -1, i + 1);
q[i] = luaL_optnumber(L, -1, 1.0f);
lua_pop(L, 1);
}
lua_pop(L, 1);
}
static struct color
get_color(lua_State *L, int index) {
uint32_t color;
struct color c;
lua_getfield(L, index, "color");
color = (uint32_t)luaL_optinteger(L, -1, 0xffffffff);
if (!(color & 0xff000000)) {
color |= 0xff000000;
}
c.channel[0] = (color >> 16) & 0xff;
c.channel[1] = (color >> 8) & 0xff;
c.channel[2] = color & 0xff;
c.channel[3] = (color >> 24) & 0xff;
lua_pop(L, 1);
return c;
}
struct pquad_stream_context {
int sprite;
int use_sprite_rect;
float scale_x;
float scale_y;
float shear_x;
float shear_y;
float quad[8];
float q[4];
struct color color;
struct pquad_payload payload[PQUAD_CORNER_N];
};
static void
write_perspective_quad_stream(void *ud, int index, struct soluna_material_stream_item *item) {
struct pquad_stream_context *ctx = (struct pquad_stream_context *)ud;
item->sprite = ctx->sprite;
if (ctx->use_sprite_rect) {
switch (index) {
case 0:
item->x = ctx->scale_x;
item->y = ctx->scale_y;
break;
case 1:
item->x = ctx->shear_x;
item->y = ctx->shear_y;
break;
default:
item->x = 0.0f;
item->y = 0.0f;
break;
}
} else {
float x = ctx->quad[index * 2];
float y = ctx->quad[index * 2 + 1];
item->x = x * ctx->scale_x + y * ctx->shear_x;
item->y = x * ctx->shear_y + y * ctx->scale_y;
}
struct pquad_payload *payload = &ctx->payload[index];
uint32_t info = (uint32_t)index;
if (ctx->use_sprite_rect) {
info |= PQUAD_INFO_USE_SPRITE_RECT;
}
payload->info = info;
payload->q = ctx->q[index];
payload->color = ctx->color;
item->payload = payload;
}
static int
lperspective_quad_sprite(lua_State *L) {
if (material_id <= 0) {
return luaL_error(L, "Perspective quad material is not registered");
}
luaL_checktype(L, 2, LUA_TTABLE);
struct pquad_stream_context ctx;
ctx.sprite = luaL_checkinteger(L, 1) - 1;
ctx.use_sprite_rect = get_quad(L, 2, ctx.quad);
ctx.scale_x = get_number_field(L, 2, "scale_x", 1.0f);
ctx.scale_y = get_number_field(L, 2, "scale_y", 1.0f);
ctx.shear_x = get_number_field(L, 2, "shear_x", 0.0f);
ctx.shear_y = get_number_field(L, 2, "shear_y", 0.0f);
get_q(L, 2, ctx.q);
ctx.color = get_color(L, 2);
struct soluna_material_stream stream;
soluna_material_error err = soluna_material_push_stream(material_id, PQUAD_CORNER_N, sizeof(struct pquad_payload), write_perspective_quad_stream, &ctx, &stream);
if (err != NULL) {
return luaL_error(L, "%s", err);
}
lua_pushexternalstring(L, stream.data, stream.size, free_material_stream, NULL);
return 1;
}
static int
luaopen_ext_material_perspective_quad(lua_State *L) {
luaL_checkversion(L);
luaL_Reg l[] = {
{ "set_material_id", lset_material_id },
{ "new", lnew_material_perspective_quad },
{ "sprite", lperspective_quad_sprite },
{ "instance_size", NULL },
{ NULL, NULL },
};
luaL_newlib(L, l);
lua_pushinteger(L, sizeof(struct pquad_inst));
lua_setfield(L, -2, "instance_size");
return 1;
}
static int
lhello(lua_State *L) {
lua_pushstring(L, "Hello World From Sample");
return 1;
}
static int
luaopen_foobar(lua_State *L) {
luaL_Reg l[] = {
{ "hello", lhello },
{ NULL, NULL },
};
luaL_newlib(L, l);
return 1;
}
EXTLUA_EXPORT int
extlua_init(lua_State *L) {
luaapi_init(L);
sokolapi_init(L);
solunaapi_init(L);
luaL_Reg l[] = {
{ "ext.foobar", luaopen_foobar },
{ "ext.material.perspective_quad", luaopen_ext_material_perspective_quad },
{ NULL, NULL },
};
luaL_newlib(L, l);
return 1;
}
================================================
FILE: extlua/gen.lua
================================================
-- extlua.h[/.c] generator
local luapath = "../3rd/lua/"
local function parse_params(params)
local p = {}
if params == "(void)" then
return p
end
local pn = 1
for t, n in params:gmatch ("(.-)([%w_.%[%]]+)[,)]", 2) do
local is_array
if n:sub(-2) == "[]" then
is_array = true
n = n:sub(1, -3)
end
p[pn] = { type = t, name = n, is_array = is_array }
pn = pn + 1
end
return p
end
local function get_apis(result, filename, prefix)
local f = assert(io.open(luapath .. filename))
local src = f:read "*a"
f:close()
local n = #result + 1
for line in src:gmatch( prefix .. "%s*(.-;)%s*\n" ) do
if not line:find("...", 1, true) then
local retv, funcname, params = line:match "([%s%w_*]+)%(([%s%w_]+)%)%s*(%b());$"
if retv == nil then
if line:match "%S" then
error("Invalid function " .. line)
end
end
retv = retv:gsub("%s+$", "")
if retv:match "%s*void%s*$" then
retv = "void"
end
result[n] = {
ret = retv,
name = funcname,
params = parse_params(params),
}
n = n + 1
end
end
end
local function decls(params)
if #params == 0 then
return "void"
end
local r = {}
for idx, p in ipairs(params) do
local d = p.type .. p.name
if p.is_array then
d = d .. "[]"
end
r[idx] = d
end
return table.concat(r, ",")
end
local function gen_decl(apis)
local d = {}
for idx, item in ipairs(apis) do
d[idx] = ("\t%s (*%s) (%s);"):format(item.ret, item.name, decls(item.params))
end
d[#d+1] = "\tint (*lua_gc) (lua_State *L, int what, ...);"
return table.concat(d, "\n")
end
local function gen_struct(apis)
local d = {}
for idx, item in ipairs(apis) do
d[idx] = ("\t\t%s,"):format(item.name)
end
d[#d+1] = "\t\tlua_gc,"
return table.concat(d, "\n")
end
local function args(params)
local args = {}
for idx, p in ipairs(params) do
args[idx] = p.name
end
return table.concat(args, ",")
end
local impl_fmt = [[
LUA_API %s
%s(%s) {
%sAPI.%s(%s);
}
]]
local function gen_impl(apis)
local d = {}
local n = 1
for idx, item in ipairs(apis) do
if item.name ~= "lua_gc" then
local ret
if item.ret == "void" then
ret = ""
else
ret = "return "
end
local impl = impl_fmt:format(item.ret, item.name, decls(item.params),
ret, item.name, args(item.params))
d[n] = impl; n = n + 1
end
end
return table.concat(d)
end
local function readfile(filename)
local f = assert(io.open(filename))
local content = f:read "a"
f:close()
return content
end
local function genfile(filename, temp)
local t = readfile(filename)
local output_filename = filename:gsub("%.temp", "")
local output_f = assert(io.open(output_filename, "w"))
output_f:write("// AUTO GENERATED by " .. filename .. ", DONT EDIT\n\n")
output_f:write((t:gsub("%$([%w_]+)%$", temp)))
output_f:close()
end
local apis = {}
get_apis(apis, "lua.h", "LUA_API")
get_apis(apis, "lauxlib.h", "LUALIB_API")
local convert = {
API_DECL = gen_decl(apis),
API_STRUCT = gen_struct(apis),
API_IMPL = gen_impl(apis),
}
genfile("extlua.temp.c", convert)
genfile("extlua_impl.temp.c", convert)
================================================
FILE: extlua/gen_sokol.lua
================================================
-- sokolapi.c generator
local header = "../3rd/sokol/sokol_gfx.h"
local allowlist = {
sg_make_buffer = true,
sg_destroy_buffer = true,
sg_update_buffer = true,
sg_append_buffer = true,
sg_make_shader = true,
sg_destroy_shader = true,
sg_make_pipeline = true,
sg_destroy_pipeline = true,
sg_apply_pipeline = true,
sg_apply_bindings = true,
sg_apply_uniforms = true,
sg_draw = true,
sg_draw_ex = true,
sg_query_backend = true,
sg_query_buffer_state = true,
sg_query_shader_state = true,
sg_query_pipeline_state = true,
}
local function parse_params(params)
local p = {}
if params == "(void)" then
return p
end
local body = params:sub(2, -2)
local n = 1
for decl in body:gmatch "[^,]+" do
local t, name = decl:match "^(.-)([%w_]+)%s*$"
if not t then
error("Invalid param " .. decl)
end
p[n] = { type = t, name = name }
n = n + 1
end
return p
end
local function readfile(filename)
local f = assert(io.open(filename))
local content = f:read "a"
f:close()
return content
end
local function get_apis()
local src = readfile(header)
local apis = {}
for line in src:gmatch "SOKOL_GFX_API_DECL%s*(.-;)%s*\n" do
local retv, name, params = line:match "([%s%w_*]+)%s+(sg_[%w_]+)%s*(%b());$"
if name and allowlist[name] then
apis[#apis + 1] = {
ret = retv:gsub("%s+$", ""),
name = name,
params = parse_params(params),
}
end
end
return apis
end
local function decls(params)
if #params == 0 then
return "void"
end
local r = {}
for i, p in ipairs(params) do
r[i] = p.type .. p.name
end
return table.concat(r, ", ")
end
local function args(params)
local r = {}
for i, p in ipairs(params) do
r[i] = p.name
end
return table.concat(r, ", ")
end
local function gen_decl(apis)
local r = {}
for i, api in ipairs(apis) do
r[i] = ("\t%s (*%s) (%s);"):format(api.ret, api.name, decls(api.params))
end
return table.concat(r, "\n")
end
local function gen_struct(apis)
local r = {}
for i, api in ipairs(apis) do
r[i] = ("\t\t%s,"):format(api.name)
end
return table.concat(r, "\n")
end
local function gen_impl(apis)
local r = {}
for i, api in ipairs(apis) do
local ret = api.ret == "void" and "" or "return "
r[i] = ("SOKOL_GFX_API_DECL %s\n%s(%s) {\n\t%sAPI.%s(%s);\n}\n\n"):format(
api.ret,
api.name,
decls(api.params),
ret,
api.name,
args(api.params)
)
end
return table.concat(r)
end
local function genfile(filename, temp)
local t = readfile(filename)
local output = filename:gsub("%.temp", "")
local f = assert(io.open(output, "w"))
f:write("// AUTO GENERATED by " .. filename .. ", DONT EDIT\n\n")
f:write((t:gsub("%$([%w_]+)%$", temp)))
f:close()
end
local apis = get_apis()
local convert = {
API_DECL = gen_decl(apis),
API_STRUCT = gen_struct(apis),
API_IMPL = gen_impl(apis),
}
genfile("sokolapi.temp.c", convert)
genfile("sokolapi_impl.temp.c", convert)
================================================
FILE: extlua/gen_soluna.lua
================================================
-- solunaapi.c generator
local apis = {
{
ret = "soluna_material_error",
name = "soluna_material_submit",
params = {
{ type = "const void *", name = "stream" },
{ type = "int ", name = "prim_n" },
{ type = "int ", name = "material_id" },
{ type = "int ", name = "batch_n" },
{ type = "void *", name = "ud" },
{ type = "soluna_material_submit_func ", name = "submit" },
},
},
{
ret = "int",
name = "soluna_material_sprite_rect",
params = {
{ type = "struct soluna_sprite_bank ", name = "bank" },
{ type = "int ", name = "sprite" },
{ type = "struct soluna_sprite_rect *", name = "out" },
},
},
{
ret = "sg_bindings",
name = "soluna_material_bindings",
params = {
{ type = "struct soluna_render_bindings ", name = "bindings" },
},
},
{
ret = "soluna_material_error",
name = "soluna_material_push_stream",
params = {
{ type = "int ", name = "material_id" },
{ type = "int ", name = "count" },
{ type = "size_t ", name = "payload_size" },
{ type = "soluna_material_stream_write_func ", name = "write" },
{ type = "void *", name = "ud" },
{ type = "struct soluna_material_stream *", name = "out" },
},
},
{
ret = "void",
name = "soluna_material_stream_free",
params = {
{ type = "void *", name = "ptr" },
},
},
{
ret = "int",
name = "soluna_material_stream_read",
params = {
{ type = "struct soluna_material_stream_context ", name = "ctx" },
{ type = "int ", name = "index" },
{ type = "size_t ", name = "payload_size" },
{ type = "void *", name = "payload" },
{ type = "struct soluna_material_stream_data *", name = "out" },
},
},
{
ret = "void",
name = "soluna_material_stream_error",
params = {
{ type = "struct soluna_material_stream_context ", name = "ctx" },
{ type = "const char *", name = "error" },
},
},
{
ret = "int",
name = "soluna_material_stream_failed",
params = {
{ type = "struct soluna_material_stream_context ", name = "ctx" },
},
},
}
local type_decl = [[
#define SOLUNA_EXT_API_VERSION 1
struct soluna_sprite_rect {
int texture;
float u;
float v;
float w;
float h;
float ox;
float oy;
};
struct soluna_material_stream_item {
float x;
float y;
int sprite;
const void *payload;
};
struct soluna_material_stream_data {
float x;
float y;
int sprite;
};
struct soluna_material_stream {
char *data;
size_t size;
};
typedef const char *soluna_material_error;
struct soluna_material_stream_context {
void *ctx;
};
struct soluna_render_bindings {
void *ctx;
};
struct soluna_sprite_bank {
void *ctx;
};
typedef void (*soluna_material_submit_func)(void *ud, struct soluna_material_stream_context ctx, int n);
typedef void (*soluna_material_stream_write_func)(void *ud, int index, struct soluna_material_stream_item *item);
]]
local host_type_decl = [[
#include <stddef.h>
#include "sokol/sokol_gfx.h"
]] .. type_decl
local function readfile(filename)
local f = assert(io.open(filename))
local content = f:read "a"
f:close()
return content
end
local function genfile(filename, temp)
local t = readfile(filename)
local output = filename:gsub("%.temp", "")
local f = assert(io.open(output, "w"))
f:write("// AUTO GENERATED by " .. filename .. ", DONT EDIT\n\n")
f:write((t:gsub("%$([%w_]+)%$", temp)))
f:close()
end
local function decls(params)
if #params == 0 then
return "void"
end
local r = {}
for i, p in ipairs(params) do
r[i] = p.type .. p.name
end
return table.concat(r, ", ")
end
local function args(params)
local r = {}
for i, p in ipairs(params) do
r[i] = p.name
end
return table.concat(r, ", ")
end
local function field_name(api)
return api.field or api.name:gsub("^soluna_", "")
end
local function impl_name(api)
return api.impl or field_name(api)
end
local function gen_header_decl()
local r = { "void solunaapi_init(lua_State *L);" }
for _, api in ipairs(apis) do
r[#r + 1] = ("%s %s(%s);"):format(api.ret, api.name, decls(api.params))
end
return table.concat(r, "\n")
end
local function gen_api_decl()
local r = {}
for i, api in ipairs(apis) do
r[i] = ("\t%s (*%s) (%s);"):format(api.ret, field_name(api), decls(api.params))
end
return table.concat(r, "\n")
end
local function gen_api_struct()
local r = {}
for i, api in ipairs(apis) do
r[i] = ("\t\t%s,"):format(impl_name(api))
end
return table.concat(r, "\n")
end
local function gen_api_extern()
local r = {}
for i, api in ipairs(apis) do
r[i] = ("extern %s %s(%s);"):format(api.ret, impl_name(api), decls(api.params))
end
return table.concat(r, "\n")
end
local function gen_api_impl()
local r = {}
for i, api in ipairs(apis) do
local ret = api.ret == "void" and "" or "return "
r[i] = ("%s\n%s(%s) {\n\t%sAPI.%s(%s);\n}\n\n"):format(
api.ret,
api.name,
decls(api.params),
ret,
field_name(api),
args(api.params)
)
end
return table.concat(r)
end
local convert = {
TYPE_DECL = type_decl,
HEADER_DECL = gen_header_decl(),
API_DECL = gen_api_decl(),
API_STRUCT = gen_api_struct(),
API_EXTERN = gen_api_extern(),
API_IMPL = gen_api_impl(),
HOST_TYPE_DECL = host_type_decl,
}
genfile("solunaapi.h.temp", convert)
genfile("solunaapi.temp.c", convert)
genfile("solunaapi_impl.temp.c", convert)
genfile("../src/extapi_types.temp.h", convert)
================================================
FILE: extlua/perspective_quad.glsl
================================================
@vs vs
layout(binding=0) uniform vs_params {
vec2 framesize;
float texsize;
};
in vec3 pos_h0;
in vec3 pos_h1;
in vec3 pos_h2;
in vec4 uv_rect;
in vec4 q;
in vec4 color;
out vec3 uvq;
out vec4 frag_color;
out flat float tex_scale;
void main() {
vec2 corner = vec2(float(gl_VertexIndex & 1), float(gl_VertexIndex >> 1));
mat3 pos_h = mat3(pos_h0, pos_h1, pos_h2);
vec3 pos_hv = pos_h * vec3(corner, 1.0);
float pos_w = max(pos_hv.z, 1e-6);
vec2 pos = pos_hv.xy / pos_w;
vec2 uv = uv_rect.xy + uv_rect.zw * corner;
float qx0 = mix(q.x, q.y, corner.x);
float qx1 = mix(q.z, q.w, corner.x);
float qv = max(mix(qx0, qx1, corner.y), 1e-6);
uvq = vec3(uv * qv, qv);
vec2 clip = pos * framesize;
gl_Position = vec4(clip.x - 1.0, clip.y + 1.0, 0.0, 1.0);
frag_color = color;
tex_scale = texsize;
}
@end
@fs fs
layout(binding=1) uniform texture2D tex;
layout(binding=0) uniform sampler smp;
in vec3 uvq;
in vec4 frag_color;
in flat float tex_scale;
out vec4 out_color;
void main() {
vec3 proj_uv = vec3(uvq.xy * tex_scale, uvq.z);
out_color = textureProj(sampler2D(tex, smp), proj_uv) * frag_color;
}
@end
@program perspective_quad vs fs
================================================
FILE: extlua/sokolapi.c
================================================
// AUTO GENERATED by sokolapi.temp.c, DONT EDIT
#include <lua.h>
#include "sokol/sokol_gfx.h"
struct sokol_api {
int version;
sg_buffer (*sg_make_buffer) (const sg_buffer_desc* desc);
sg_shader (*sg_make_shader) (const sg_shader_desc* desc);
sg_pipeline (*sg_make_pipeline) (const sg_pipeline_desc* desc);
void (*sg_destroy_buffer) (sg_buffer buf);
void (*sg_destroy_shader) (sg_shader shd);
void (*sg_destroy_pipeline) (sg_pipeline pip);
void (*sg_update_buffer) (sg_buffer buf, const sg_range* data);
int (*sg_append_buffer) (sg_buffer buf, const sg_range* data);
void (*sg_apply_pipeline) (sg_pipeline pip);
void (*sg_apply_bindings) (const sg_bindings* bindings);
void (*sg_apply_uniforms) (int ub_slot, const sg_range* data);
void (*sg_draw) (int base_element, int num_elements, int num_instances);
void (*sg_draw_ex) (int base_element, int num_elements, int num_instances, int base_vertex, int base_instance);
sg_backend (*sg_query_backend) (void);
sg_resource_state (*sg_query_buffer_state) (sg_buffer buf);
sg_resource_state (*sg_query_shader_state) (sg_shader shd);
sg_resource_state (*sg_query_pipeline_state) (sg_pipeline pip);
};
static struct sokol_api API;
SOKOL_GFX_API_DECL sg_buffer
sg_make_buffer(const sg_buffer_desc* desc) {
return API.sg_make_buffer(desc);
}
SOKOL_GFX_API_DECL sg_shader
sg_make_shader(const sg_shader_desc* desc) {
return API.sg_make_shader(desc);
}
SOKOL_GFX_API_DECL sg_pipeline
sg_make_pipeline(const sg_pipeline_desc* desc) {
return API.sg_make_pipeline(desc);
}
SOKOL_GFX_API_DECL void
sg_destroy_buffer(sg_buffer buf) {
API.sg_destroy_buffer(buf);
}
SOKOL_GFX_API_DECL void
sg_destroy_shader(sg_shader shd) {
API.sg_destroy_shader(shd);
}
SOKOL_GFX_API_DECL void
sg_destroy_pipeline(sg_pipeline pip) {
API.sg_destroy_pipeline(pip);
}
SOKOL_GFX_API_DECL void
sg_update_buffer(sg_buffer buf, const sg_range* data) {
API.sg_update_buffer(buf, data);
}
SOKOL_GFX_API_DECL int
sg_append_buffer(sg_buffer buf, const sg_range* data) {
return API.sg_append_buffer(buf, data);
}
SOKOL_GFX_API_DECL void
sg_apply_pipeline(sg_pipeline pip) {
API.sg_apply_pipeline(pip);
}
SOKOL_GFX_API_DECL void
sg_apply_bindings(const sg_bindings* bindings) {
API.sg_apply_bindings(bindings);
}
SOKOL_GFX_API_DECL void
sg_apply_uniforms(int ub_slot, const sg_range* data) {
API.sg_apply_uniforms(ub_slot, data);
}
SOKOL_GFX_API_DECL void
sg_draw(int base_element, int num_elements, int num_instances) {
API.sg_draw(base_element, num_elements, num_instances);
}
SOKOL_GFX_API_DECL void
sg_draw_ex(int base_element, int num_elements, int num_instances, int base_vertex, int base_instance) {
API.sg_draw_ex(base_element, num_elements, num_instances, base_vertex, base_instance);
}
SOKOL_GFX_API_DECL sg_backend
sg_query_backend(void) {
return API.sg_query_backend();
}
SOKOL_GFX_API_DECL sg_resource_state
sg_query_buffer_state(sg_buffer buf) {
return API.sg_query_buffer_state(buf);
}
SOKOL_GFX_API_DECL sg_resource_state
sg_query_shader_state(sg_shader shd) {
return API.sg_query_shader_state(shd);
}
SOKOL_GFX_API_DECL sg_resource_state
sg_query_pipeline_state(sg_pipeline pip) {
return API.sg_query_pipeline_state(pip);
}
struct lua_api;
struct soluna_api;
struct extlua_apis {
struct lua_api * lua;
struct sokol_api * sokol;
struct soluna_api * soluna;
};
void
sokolapi_init(lua_State *L) {
struct extlua_apis *apis = *(struct extlua_apis **)lua_getextraspace(L);
API = *apis->sokol;
}
================================================
FILE: extlua/sokolapi.temp.c
================================================
#include <lua.h>
#include "sokol/sokol_gfx.h"
struct sokol_api {
int version;
$API_DECL$
};
static struct sokol_api API;
$API_IMPL$
struct lua_api;
struct soluna_api;
struct extlua_apis {
struct lua_api * lua;
struct sokol_api * sokol;
struct soluna_api * soluna;
};
void
sokolapi_init(lua_State *L) {
struct extlua_apis *apis = *(struct extlua_apis **)lua_getextraspace(L);
API = *apis->sokol;
}
================================================
FILE: extlua/sokolapi_impl.c
================================================
// AUTO GENERATED by sokolapi_impl.temp.c, DONT EDIT
#include "sokol/sokol_gfx.h"
struct sokol_api {
int version;
sg_buffer (*sg_make_buffer) (const sg_buffer_desc* desc);
sg_shader (*sg_make_shader) (const sg_shader_desc* desc);
sg_pipeline (*sg_make_pipeline) (const sg_pipeline_desc* desc);
void (*sg_destroy_buffer) (sg_buffer buf);
void (*sg_destroy_shader) (sg_shader shd);
void (*sg_destroy_pipeline) (sg_pipeline pip);
void (*sg_update_buffer) (sg_buffer buf, const sg_range* data);
int (*sg_append_buffer) (sg_buffer buf, const sg_range* data);
void (*sg_apply_pipeline) (sg_pipeline pip);
void (*sg_apply_bindings) (const sg_bindings* bindings);
void (*sg_apply_uniforms) (int ub_slot, const sg_range* data);
void (*sg_draw) (int base_element, int num_elements, int num_instances);
void (*sg_draw_ex) (int base_element, int num_elements, int num_instances, int base_vertex, int base_instance);
sg_backend (*sg_query_backend) (void);
sg_resource_state (*sg_query_buffer_state) (sg_buffer buf);
sg_resource_state (*sg_query_shader_state) (sg_shader shd);
sg_resource_state (*sg_query_pipeline_state) (sg_pipeline pip);
};
struct sokol_api *
extlua_sokol_api() {
static struct sokol_api api = {
SOKOL_GFX_INCLUDED,
sg_make_buffer,
sg_make_shader,
sg_make_pipeline,
sg_destroy_buffer,
sg_destroy_shader,
sg_destroy_pipeline,
sg_update_buffer,
sg_append_buffer,
sg_apply_pipeline,
sg_apply_bindings,
sg_apply_uniforms,
sg_draw,
sg_draw_ex,
sg_query_backend,
sg_query_buffer_state,
sg_query_shader_state,
sg_query_pipeline_state,
};
return &api;
}
================================================
FILE: extlua/sokolapi_impl.temp.c
================================================
#include "sokol/sokol_gfx.h"
struct sokol_api {
int version;
$API_DECL$
};
struct sokol_api *
extlua_sokol_api() {
static struct sokol_api api = {
SOKOL_GFX_INCLUDED,
$API_STRUCT$
};
return &api;
}
================================================
FILE: extlua/solunaapi.c
================================================
// AUTO GENERATED by solunaapi.temp.c, DONT EDIT
#include "solunaapi.h"
#include <lauxlib.h>
struct soluna_api {
int version;
soluna_material_error (*material_submit) (const void *stream, int prim_n, int material_id, int batch_n, void *ud, soluna_material_submit_func submit);
int (*material_sprite_rect) (struct soluna_sprite_bank bank, int sprite, struct soluna_sprite_rect *out);
sg_bindings (*material_bindings) (struct soluna_render_bindings bindings);
soluna_material_error (*material_push_stream) (int material_id, int count, size_t payload_size, soluna_material_stream_write_func write, void *ud, struct soluna_material_stream *out);
void (*material_stream_free) (void *ptr);
int (*material_stream_read) (struct soluna_material_stream_context ctx, int index, size_t payload_size, void *payload, struct soluna_material_stream_data *out);
void (*material_stream_error) (struct soluna_material_stream_context ctx, const char *error);
int (*material_stream_failed) (struct soluna_material_stream_context ctx);
};
static struct soluna_api API;
soluna_material_error
soluna_material_submit(const void *stream, int prim_n, int material_id, int batch_n, void *ud, soluna_material_submit_func submit) {
return API.material_submit(stream, prim_n, material_id, batch_n, ud, submit);
}
int
soluna_material_sprite_rect(struct soluna_sprite_bank bank, int sprite, struct soluna_sprite_rect *out) {
return API.material_sprite_rect(bank, sprite, out);
}
sg_bindings
soluna_material_bindings(struct soluna_render_bindings bindings) {
return API.material_bindings(bindings);
}
soluna_material_error
soluna_material_push_stream(int material_id, int count, size_t payload_size, soluna_material_stream_write_func write, void *ud, struct soluna_material_stream *out) {
return API.material_push_stream(material_id, count, payload_size, write, ud, out);
}
void
soluna_material_stream_free(void *ptr) {
API.material_stream_free(ptr);
}
int
soluna_material_stream_read(struct soluna_material_stream_context ctx, int index, size_t payload_size, void *payload, struct soluna_material_stream_data *out) {
return API.material_stream_read(ctx, index, payload_size, payload, out);
}
void
soluna_material_stream_error(struct soluna_material_stream_context ctx, const char *error) {
API.material_stream_error(ctx, error);
}
int
soluna_material_stream_failed(struct soluna_material_stream_context ctx) {
return API.material_stream_failed(ctx);
}
struct lua_api;
struct sokol_api;
struct extlua_apis {
struct lua_api * lua;
struct sokol_api * sokol;
struct soluna_api * soluna;
};
void
solunaapi_init(lua_State *L) {
struct extlua_apis *apis = *(struct extlua_apis **)lua_getextraspace(L);
if (apis == NULL || apis->soluna == NULL || apis->soluna->version != SOLUNA_EXT_API_VERSION) {
int version = (apis != NULL && apis->soluna != NULL) ? apis->soluna->version : 0;
luaL_error(L, "soluna ext api version mismatch, expected %d got %d", SOLUNA_EXT_API_VERSION, version);
}
API = *apis->soluna;
}
================================================
FILE: extlua/solunaapi.h
================================================
// AUTO GENERATED by solunaapi.h.temp, DONT EDIT
#ifndef SOLUNAAPI_H
#define SOLUNAAPI_H
#include <stddef.h>
#include <lua.h>
#include "sokol/sokol_gfx.h"
#define SOLUNA_EXT_API_VERSION 1
struct soluna_sprite_rect {
int texture;
float u;
float v;
float w;
float h;
float ox;
float oy;
};
struct soluna_material_stream_item {
float x;
float y;
int sprite;
const void *payload;
};
struct soluna_material_stream_data {
float x;
float y;
int sprite;
};
struct soluna_material_stream {
char *data;
size_t size;
};
typedef const char *soluna_material_error;
struct soluna_material_stream_context {
void *ctx;
};
struct soluna_render_bindings {
void *ctx;
};
struct soluna_sprite_bank {
void *ctx;
};
typedef void (*soluna_material_submit_func)(void *ud, struct soluna_material_stream_context ctx, int n);
typedef void (*soluna_material_stream_write_func)(void *ud, int index, struct soluna_material_stream_item *item);
void solunaapi_init(lua_State *L);
soluna_material_error soluna_material_submit(const void *stream, int prim_n, int material_id, int batch_n, void *ud, soluna_material_submit_func submit);
int soluna_material_sprite_rect(struct soluna_sprite_bank bank, int sprite, struct soluna_sprite_rect *out);
sg_bindings soluna_material_bindings(struct soluna_render_bindings bindings);
soluna_material_error soluna_material_push_stream(int material_id, int count, size_t payload_size, soluna_material_stream_write_func write, void *ud, struct soluna_material_stream *out);
void soluna_material_stream_free(void *ptr);
int soluna_material_stream_read(struct soluna_material_stream_context ctx, int index, size_t payload_size, void *payload, struct soluna_material_stream_data *out);
void soluna_material_stream_error(struct soluna_material_stream_context ctx, const char *error);
int soluna_material_stream_failed(struct soluna_material_stream_context ctx);
#endif
================================================
FILE: extlua/solunaapi.h.temp
================================================
#ifndef SOLUNAAPI_H
#define SOLUNAAPI_H
#include <stddef.h>
#include <lua.h>
#include "sokol/sokol_gfx.h"
$TYPE_DECL$
$HEADER_DECL$
#endif
================================================
FILE: extlua/solunaapi.temp.c
================================================
#include "solunaapi.h"
#include <lauxlib.h>
struct soluna_api {
int version;
$API_DECL$
};
static struct soluna_api API;
$API_IMPL$
struct lua_api;
struct sokol_api;
struct extlua_apis {
struct lua_api * lua;
struct sokol_api * sokol;
struct soluna_api * soluna;
};
void
solunaapi_init(lua_State *L) {
struct extlua_apis *apis = *(struct extlua_apis **)lua_getextraspace(L);
if (apis == NULL || apis->soluna == NULL || apis->soluna->version != SOLUNA_EXT_API_VERSION) {
int version = (apis != NULL && apis->soluna != NULL) ? apis->soluna->version : 0;
luaL_error(L, "soluna ext api version mismatch, expected %d got %d", SOLUNA_EXT_API_VERSION, version);
}
API = *apis->soluna;
}
================================================
FILE: extlua/solunaapi_impl.c
================================================
// AUTO GENERATED by solunaapi_impl.temp.c, DONT EDIT
#include <stddef.h>
#include "sokol/sokol_gfx.h"
#define SOLUNA_EXT_API_VERSION 1
struct soluna_sprite_rect {
int texture;
float u;
float v;
float w;
float h;
float ox;
float oy;
};
struct soluna_material_stream_item {
float x;
float y;
int sprite;
const void *payload;
};
struct soluna_material_stream_data {
float x;
float y;
int sprite;
};
struct soluna_material_stream {
char *data;
size_t size;
};
typedef const char *soluna_material_error;
struct soluna_material_stream_context {
void *ctx;
};
struct soluna_render_bindings {
void *ctx;
};
struct soluna_sprite_bank {
void *ctx;
};
typedef void (*soluna_material_submit_func)(void *ud, struct soluna_material_stream_context ctx, int n);
typedef void (*soluna_material_stream_write_func)(void *ud, int index, struct soluna_material_stream_item *item);
extern soluna_material_error material_submit(const void *stream, int prim_n, int material_id, int batch_n, void *ud, soluna_material_submit_func submit);
extern int material_sprite_rect(struct soluna_sprite_bank bank, int sprite, struct soluna_sprite_rect *out);
extern sg_bindings material_bindings(struct soluna_render_bindings bindings);
extern soluna_material_error material_push_stream(int material_id, int count, size_t payload_size, soluna_material_stream_write_func write, void *ud, struct soluna_material_stream *out);
extern void material_stream_free(void *ptr);
extern int material_stream_read(struct soluna_material_stream_context ctx, int index, size_t payload_size, void *payload, struct soluna_material_stream_data *out);
extern void material_stream_error(struct soluna_material_stream_context ctx, const char *error);
extern int material_stream_failed(struct soluna_material_stream_context ctx);
struct soluna_api {
int version;
soluna_material_error (*material_submit) (const void *stream, int prim_n, int material_id, int batch_n, void *ud, soluna_material_submit_func submit);
int (*material_sprite_rect) (struct soluna_sprite_bank bank, int sprite, struct soluna_sprite_rect *out);
sg_bindings (*material_bindings) (struct soluna_render_bindings bindings);
soluna_material_error (*material_push_stream) (int material_id, int count, size_t payload_size, soluna_material_stream_write_func write, void *ud, struct soluna_material_stream *out);
void (*material_stream_free) (void *ptr);
int (*material_stream_read) (struct soluna_material_stream_context ctx, int index, size_t payload_size, void *payload, struct soluna_material_stream_data *out);
void (*material_stream_error) (struct soluna_material_stream_context ctx, const char *error);
int (*material_stream_failed) (struct soluna_material_stream_context ctx);
};
struct soluna_api *
extlua_soluna_api() {
static struct soluna_api api = {
SOLUNA_EXT_API_VERSION,
material_submit,
material_sprite_rect,
material_bindings,
material_push_stream,
material_stream_free,
material_stream_read,
material_stream_error,
material_stream_failed,
};
return &api;
}
================================================
FILE: extlua/solunaapi_impl.temp.c
================================================
$HOST_TYPE_DECL$
$API_EXTERN$
struct soluna_api {
int version;
$API_DECL$
};
struct soluna_api *
extlua_soluna_api() {
static struct soluna_api api = {
SOLUNA_EXT_API_VERSION,
$API_STRUCT$
};
return &api;
}
================================================
FILE: make.lua
================================================
local lm = require "luamake"
local fs = require "bee.filesystem"
local function detect_emcc()
if lm.compiler == "emcc" then
return true
end
if type(lm.cc) == "string" and lm.cc:find("emcc", 1, true) then
return true
end
return false
end
local osplat = (function()
if lm.os == "windows" then
if lm.compiler == "gcc" then
return "mingw"
end
if lm.cc == "clang-cl" then
return "clang-cl"
end
return "msvc"
end
return lm.os
end)()
local plat = (function()
if detect_emcc() then
return "emcc"
end
return osplat
end)()
lm.platform = plat
lm.basedir = lm:path "."
lm.bindir = ("bin/%s/%s"):format(plat, lm.mode)
lm.osbindir = ("bin/%s/%s"):format(osplat, lm.mode)
lm:conf {
cxx = "c++20",
clang = {
c = "c11",
},
flags = {
lm.mode ~= "debug" and "-O2",
},
msvc = {
c = "c11",
flags = {
"-W3",
"-utf-8",
"-experimental:c11atomics",
"/wd4244",
"/wd4267",
"/wd4305",
"/wd4996",
"/wd4018",
"/wd4113",
},
defines = {
"_CRT_SECURE_NO_WARNINGS",
"_CRT_NONSTDC_NO_DEPRECATE",
"_CRT_SECURE_NO_DEPRECATE"
},
},
mingw = {
c = "c99",
},
gcc = {
c = "c11",
flags = {
"-Wall",
},
defines = {
"_POSIX_C_SOURCE=199309L",
"_GNU_SOURCE",
},
links = {
"m",
(lm.os ~= "windows" and lm.platform ~= "emcc") and "fontconfig",
},
},
emcc = {
c = "gnu11",
flags = {
"-Wall",
"-pthread",
"-fPIC",
"--use-port=emdawnwebgpu",
"-fwasm-exceptions",
},
links = {
"idbfs.js",
},
ldflags = {
"--use-port=emdawnwebgpu",
"-s ALLOW_MEMORY_GROWTH",
"-s FORCE_FILESYSTEM=1",
"-s USE_PTHREADS=1",
"-fwasm-exceptions",
lm.mode == "debug" and "-gsource-map",
lm.mode == "debug" and "-s EXCEPTION_STACK_TRACES=1",
lm.mode == "debug" and "-s ASSERTIONS=2",
-- lm.mode == "debug" and "-s SAFE_HEAP=1",
lm.mode == "debug" and "-s STACK_OVERFLOW_CHECK=1",
lm.mode == "debug" and "-s PTHREADS_DEBUG=1",
},
defines = {
"_POSIX_C_SOURCE=200809L",
"_GNU_SOURCE",
},
},
defines = {
-- lm.mode == "debug" and "DEBUGLOG",
lm.mode == "debug" and "SOKOL_DEBUG",
}
}
local deps = { "soluna_src" }
for path in fs.pairs(lm.basedir .. "/clibs") do
local name = path:stem():string()
if name ~= "soluna" and name ~= "sample" and fs.exists(path / "make.lua") then
local makefile = ("clibs/%s/make.lua"):format(name)
lm:import(makefile)
deps[#deps + 1] = name .. "_src"
end
end
lm:import "clibs/soluna/make.lua"
lm:import "clibs/sample/make.lua"
lm:exe "soluna" {
deps = deps,
emcc = {
ldflags = {
"--js-library=src/platform/wasm/soluna_ime.js",
"--js-library=src/platform/wasm/soluna_openurl.js",
"-s MODULARIZE=1",
"-s EXPORT_ES6=1",
"-s EXPORT_NAME=createApp",
'-s EXPORTED_FUNCTIONS=\'["_main"]\'',
'-s EXPORTED_RUNTIME_METHODS=\'["FS","FS_createPath","FS_createDataFile","IDBFS"]\'',
"-s PTHREAD_POOL_SIZE='Math.max(2,navigator.hardwareConcurrency)'",
"-s PTHREAD_POOL_SIZE_STRICT=2",
"-s MAIN_MODULE=2",
"-Wl,-u,emscripten_builtin_memalign",
"-Wl,--export=emscripten_builtin_memalign",
},
},
}
lm:import "script/act_targets.lua"
lm:runlua "cc" {
script = "script/compile_commands.lua",
args = {
"build/build.ninja",
"compile_commands.json",
},
inputs = {
"build/build.ninja",
"script/compile_commands.lua",
},
outputs = {
"compile_commands.json",
},
}
lm:default "soluna"
================================================
FILE: script/act.lua
================================================
local platform = require "bee.platform"
local fs = require "bee.filesystem"
local subprocess = require "bee.subprocess"
local is_windows = platform.os == "windows"
local function quote_ps(value)
return "'" .. value:gsub("'", "''") .. "'"
end
local function cmdline(args)
local out = {}
for i = 1, #args do
local v = args[i]
if v:find("[%s\"]") then
out[#out + 1] = '"' .. v:gsub('"', '\\"') .. '"'
else
out[#out + 1] = v
end
end
return table.concat(out, " ")
end
local function run(args, option)
option = option or {}
print("> " .. cmdline(args))
local process, errmsg = subprocess.spawn {
args,
searchPath = true,
stdout = option.stdout ~= nil and option.stdout or io.stdout,
stderr = option.stderr ~= nil and option.stderr or "stdout",
}
assert(process, errmsg)
local code = process:wait()
process:detach()
if code ~= 0 then
error(("command failed (%d): %s"):format(code, cmdline(args)))
end
end
local function run_code(args)
local process = assert(subprocess.spawn {
args,
searchPath = true,
stdout = true,
stderr = true,
})
local code = process:wait()
process:detach()
return code
end
local function exists(path)
return fs.exists(path)
end
local function getenv(name, default)
local value = os.getenv(name)
if value == nil or value == "" then
return default
end
return value
end
local function reset_dir(path)
pcall(fs.remove_all, path)
if not exists(path) then
fs.create_directories(path)
end
end
local function get_home()
if is_windows then
local userprofile = os.getenv("USERPROFILE")
if userprofile and userprofile ~= "" then
return fs.path(userprofile)
end
local home_drive = os.getenv("HOMEDRIVE") or ""
local home_path = os.getenv("HOMEPATH") or ""
local combined = home_drive .. home_path
if combined ~= "" then
return fs.path(combined)
end
return nil
end
local home = os.getenv("HOME")
if home and home ~= "" then
return fs.path(home)
end
return nil
end
local function detect_python()
if is_windows then
if run_code { "where", "py" } == 0 then
return { "py", "-3" }
end
if run_code { "where", "python" } == 0 then
return { "python" }
end
else
if run_code { "which", "python3" } == 0 then
return { "python3" }
end
if run_code { "which", "python" } == 0 then
return { "python" }
end
end
error "python interpreter not found"
end
local function find_file(root, filename)
for path, status in fs.pairs_r(root) do
if status and status:is_regular_file() and path:filename():string() == filename then
return path
end
end
return nil
end
local function collect_files(root)
local files = {}
if not exists(root) then
return files
end
for path, status in fs.pairs_r(root) do
if status and status:is_regular_file() then
files[#files + 1] = path
end
end
table.sort(files, function(a, b)
return a:string() < b:string()
end)
return files
end
local workflow = (arg[1] or "pages"):lower()
local workflow_file = ({
pages = ".github/workflows/pages.yml",
nightly = ".github/workflows/nightly.yml",
})[workflow]
if not workflow_file then
error(("unknown workflow: %s (expected: pages or nightly)"):format(workflow))
end
local function parse_options(argv)
local options = {
port = tonumber(getenv("PORT", "8080")) or 8080,
host_os = platform.os,
}
for i = 2, #argv do
local value = argv[i]
local port_num = tonumber(value)
local kv_key, kv_value = value:match("^([%w_]+)=(.+)$")
if kv_key == "port" then
local p = tonumber(kv_value)
if p then
options.port = p
end
elseif kv_key == "host_os" then
options.host_os = kv_value:lower()
elseif port_num then
options.port = port_num
end
end
return options
end
local options = parse_options(arg)
local port = options.port
local home = assert(get_home(), "home directory is not set")
local root = fs.path(getenv("ACT_ROOT", (home / ".act/soluna"):string()))
local artifact_root = root / "artifacts"
local unpack_dir = root / "unpack"
local serve_root = root / "serve"
local preview_dir = serve_root / "soluna"
reset_dir(artifact_root)
reset_dir(unpack_dir)
reset_dir(preview_dir)
local act_args = {
"act",
"workflow_dispatch",
"-W",
workflow_file,
"--container-architecture",
"linux/amd64",
"--artifact-server-path",
artifact_root:string(),
}
if workflow == "nightly" then
local matrix_os = ({
windows = "windows-latest",
macos = "macos-latest",
})[options.host_os] or "ubuntu-latest"
act_args[#act_args + 1] = "--matrix"
act_args[#act_args + 1] = "os:" .. matrix_os
if matrix_os == "windows-latest" or matrix_os == "macos-latest" then
act_args[#act_args + 1] = "-P"
act_args[#act_args + 1] = matrix_os .. "=-self-hosted"
end
print(("Nightly matrix selected: %s (host_os=%s)"):format(matrix_os, options.host_os))
end
run(act_args)
if workflow ~= "pages" then
print("Workflow completed: " .. workflow)
print("Artifacts root: " .. artifact_root:string())
local files = collect_files(artifact_root)
if #files == 0 then
print("No artifact files were found under artifacts root.")
else
print("Artifact files:")
for i = 1, #files do
local rel = files[i]:string():sub(#artifact_root:string() + 2)
print(" - " .. rel)
end
end
return
end
local zip_path = find_file(artifact_root, "github-pages.zip")
if not zip_path then
error(table.concat({
"missing github-pages.zip under: " .. artifact_root:string(),
"The workflow build job was likely skipped (for example, unsupported runner image).",
"You can inspect with: act -l ; act -n -W .github/workflows/pages.yml",
"If needed, pass platform mapping manually, for example:",
" act workflow_dispatch -W .github/workflows/pages.yml -P ubuntu-latest=ghcr.io/catthehacker/ubuntu:act-latest",
}, "\n"))
end
if is_windows then
run {
"powershell",
"-NoProfile",
"-Command",
"Expand-Archive -LiteralPath "
.. quote_ps(zip_path:string())
.. " -DestinationPath "
.. quote_ps(unpack_dir:string())
.. " -Force",
}
else
run {
"unzip",
"-o",
zip_path:string(),
"-d",
unpack_dir:string(),
}
end
local artifact_tar = find_file(unpack_dir, "artifact.tar")
if not artifact_tar then
error("missing artifact.tar under: " .. unpack_dir:string())
end
run {
"tar",
"-xf",
artifact_tar:string(),
"-C",
preview_dir:string(),
}
print("Preview files are ready at: " .. preview_dir:string())
print("Serving http://127.0.0.1:" .. port .. "/soluna/")
print "If the page loads before the service worker takes control, refresh once."
local python = detect_python()
python[#python + 1] = "-m"
python[#python + 1] = "http.server"
python[#python + 1] = tostring(port)
python[#python + 1] = "--directory"
python[#python + 1] = serve_root:string()
run(python)
================================================
FILE: script/act_targets.lua
================================================
local lm = require "luamake"
lm:rule "act_lua" {
args = { "$luamake", "lua", "$args" },
description = "$args",
pool = "console",
}
lm:build "pages" {
rule = "act_lua",
args = { "@act.lua", "pages" },
inputs = { "act.lua" },
}
lm:build "nightly" {
rule = "act_lua",
args = { "@act.lua", "nightly", "host_os=" .. lm.os },
inputs = { "act.lua" },
}
lm:phony "act" {
inputs = "act.lua",
}
================================================
FILE: script/compile_commands.lua
================================================
local subprocess = require "bee.subprocess"
local ninja_file, output = ...
assert(ninja_file, "missing ninja file path")
assert(output, "missing output path")
local process = assert(subprocess.spawn {
"ninja",
"-f",
ninja_file,
"-t",
"compdb",
"-x",
searchPath = true,
stdout = true,
})
local content = process.stdout:read "a"
local code = process:wait()
if code ~= 0 then
os.exit(code, true)
end
local file <close> = assert(io.open(output, "wb"))
file:write(content)
================================================
FILE: script/datalist2c.lua
================================================
local dlsrc, cname = ...
local f = assert(io.open(dlsrc,"rb"))
local bin = f:read "a"
f:close()
local code = [[
static const unsigned char dl_$name[] = {
$bytes
};
]]
local count = 0
local function tohex(c)
local b = string.format("0x%02x,", c:byte())
count = count + 1
if count == 16 then
b = b .. "\n\t"
count = 0
end
return b
end
local p = {
name = cname:match "([^/]+)%.dl%.h$",
bytes = string.gsub(bin .. "\0", ".", tohex),
}
local source = string.gsub(code, "$(%w+)", p)
local f = assert(io.open(cname, "w"))
f:write(source)
f:close()
================================================
FILE: script/hashversion.lua
================================================
local function get_rev()
local f = io.popen "git rev-parse HEAD"
local rev = f:read "a"
f:close()
return rev:match "[%da-f]*"
end
local version = get_rev()
print("SOLUNA_HASH_VERSION", version)
local f = assert(io.open "src/version.h")
local text = f:read "a"
text = text:gsub('(SOLUNA_HASH_VERSION%s+")([%da-f]*)(")', "%1".. version .. "%3")
f:close()
local f = assert(io.open("src/version.h", "wb"))
f:write(text)
f:close()
================================================
FILE: script/lua2c.lua
================================================
local luasrc, cname = ...
local s = assert(loadfile(luasrc))
local bin = string.dump(s)
local code = [[
static const unsigned char luasrc_$name[] = {
$bytes
};
]]
local count = 0
local function tohex(c)
local b = string.format("0x%02x,", c:byte())
count = count + 1
if count == 16 then
b = b .. "\n\t"
count = 0
end
return b
end
local p = {
name = cname:match "([^/]+)%.lua%.h$",
bytes = string.gsub(bin .. "\0" , ".", tohex),
}
local source = string.gsub(code, "$(%w+)", p)
local f = assert(io.open(cname, "w"))
f:write(source)
f:close()
================================================
FILE: src/appevent.h
================================================
#ifndef soluna_app_event_h
#define soluna_app_event_h
struct event_message {
const char *typestr;
int p1;
int p2;
int p3;
};
static inline void
get_xy(struct event_message *em, float x, float y) {
float dpi_scale = sapp_dpi_scale();
float inv;
if (dpi_scale <= 0.0f) {
dpi_scale = 1.0f;
inv = 1.0f;
} else {
inv = 1.0f / dpi_scale;
}
float logical_x = x * inv;
float logical_y = y * inv;
if (logical_x >= 0.0f)
em->p1 = (int)(logical_x + 0.5f);
else
em->p1 = (int)(logical_x - 0.5f);
if (logical_y >= 0.0f)
em->p2 = (int)(logical_y + 0.5f);
else
em->p2 = (int)(logical_y - 0.5f);
}
static inline void
mouse_message(struct event_message *em, const sapp_event* ev) {
switch (ev->type) {
case SAPP_EVENTTYPE_MOUSE_MOVE:
em->typestr = "mouse_move";
get_xy(em, ev->mouse_x, ev->mouse_y);
break;
case SAPP_EVENTTYPE_MOUSE_DOWN:
case SAPP_EVENTTYPE_MOUSE_UP:
em->typestr = "mouse_button";
em->p1 = ev->mouse_button;
em->p2 = ev->type == SAPP_EVENTTYPE_MOUSE_DOWN;
break;
case SAPP_EVENTTYPE_MOUSE_SCROLL:
em->typestr = "mouse_scroll";
em->p1 = ev->scroll_y;
em->p2 = ev->scroll_x;
break;
default:
em->typestr = "mouse";
em->p1 = ev->type;
break;
}
}
static inline void
touch_message(struct event_message *em, const sapp_event* ev) {
// todo : support multi touch points
// get 1st touch point now
const sapp_touchpoint *t = &ev->touches[0];
get_xy(em, t->pos_x, t->pos_y);
em->p3 = t->changed;
switch (ev->type) {
case SAPP_EVENTTYPE_TOUCHES_BEGAN:
em->typestr = "touch_begin";
break;
case SAPP_EVENTTYPE_TOUCHES_MOVED:
em->typestr = "touch_moved";
break;
case SAPP_EVENTTYPE_TOUCHES_ENDED:
em->typestr = "touch_end";
break;
case SAPP_EVENTTYPE_TOUCHES_CANCELLED:
em->typestr = "touch_cancelled";
break;
default:
em->typestr = "touch";
break;
}
}
static inline void
window_message(struct event_message *em, const sapp_event *ev) {
switch (ev->type) {
case SAPP_EVENTTYPE_RESIZED:
em->typestr = "window_resize";
em->p1 = ev->window_width;
em->p2 = ev->window_height;
break;
default:
em->typestr = "window";
em->p1 = ev->type;
break;
}
}
static inline void
key_message(struct event_message *em, const sapp_event *ev) {
switch (ev->type) {
case SAPP_EVENTTYPE_CHAR:
em->typestr = "char";
em->p1 = (int)ev->char_code;
em->p2 = 0;
break;
default:
em->typestr = "key";
em->p1 = (int)ev->key_code;
em->p2 = ev->type == SAPP_EVENTTYPE_KEY_DOWN;
break;
}
}
static inline void
app_event_unpack(struct event_message *em, const sapp_event* ev) {
em->typestr = NULL;
em->p1 = 0;
em->p2 = 0;
em->p3 = 0;
switch (ev->type) {
case SAPP_EVENTTYPE_MOUSE_MOVE:
case SAPP_EVENTTYPE_MOUSE_DOWN:
case SAPP_EVENTTYPE_MOUSE_UP:
case SAPP_EVENTTYPE_MOUSE_SCROLL:
case SAPP_EVENTTYPE_MOUSE_ENTER:
case SAPP_EVENTTYPE_MOUSE_LEAVE:
mouse_message(em, ev);
break;
case SAPP_EVENTTYPE_TOUCHES_BEGAN:
case SAPP_EVENTTYPE_TOUCHES_MOVED:
case SAPP_EVENTTYPE_TOUCHES_ENDED:
case SAPP_EVENTTYPE_TOUCHES_CANCELLED:
touch_message(em, ev);
break;
case SAPP_EVENTTYPE_RESIZED:
window_message(em, ev);
break;
case SAPP_EVENTTYPE_CHAR:
case SAPP_EVENTTYPE_KEY_DOWN:
case SAPP_EVENTTYPE_KEY_UP:
key_message(em, ev);
break;
default:
em->typestr = "message";
em->p1 = ev->type;
break;
}
}
#endif
================================================
FILE: src/audio.c
================================================
#include <lua.h>
#include <lauxlib.h>
#include "zipreader.h"
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#define MA_NO_WIN32_FILEIO
#define MA_NO_MP3
#define MA_NO_FLAC
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
FILE * fopen_utf8(const char *filename, const char *mode);
static ma_result
vfs_open_local(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile) {
FILE* pFileStd;
const char* pOpenModeStr;
MA_ASSERT(pFilePath != NULL);
MA_ASSERT(openMode != 0);
MA_ASSERT(pFile != NULL);
(void)pVFS;
if ((openMode & MA_OPEN_MODE_READ) != 0) {
if ((openMode & MA_OPEN_MODE_WRITE) != 0) {
pOpenModeStr = "r+";
} else {
pOpenModeStr = "rb";
}
} else {
pOpenModeStr = "wb";
}
pFileStd = fopen_utf8(pFilePath, pOpenModeStr);
if (pFileStd == NULL) {
return MA_ERROR;
}
*pFile = pFileStd;
return MA_SUCCESS;
}
struct custom_vfs {
ma_default_vfs base;
struct zipreader_name *zipnames;
};
struct custom_engine {
struct ma_engine engine;
struct ma_resource_manager rm;
struct custom_vfs vfs;
};
struct audio_group {
ma_sound_group group;
int alive;
};
struct audio_sound {
ma_sound sound;
int alive;
};
#define AUDIO_GROUP_METATABLE "SOLUNA_AUDIO_GROUP"
#define AUDIO_SOUND_METATABLE "SOLUNA_AUDIO_SOUND"
static struct custom_engine *
check_engine(lua_State *L, int index) {
luaL_checktype(L, index, LUA_TLIGHTUSERDATA);
return (struct custom_engine *)lua_touserdata(L, index);
}
static struct audio_group *
check_group(lua_State *L, int index) {
struct audio_group *group = (struct audio_group *)luaL_checkudata(L, index, AUDIO_GROUP_METATABLE);
luaL_argcheck(L, group->alive, index, "closed audio group");
return group;
}
static struct audio_sound *
check_sound(lua_State *L, int index) {
struct audio_sound *sound = (struct audio_sound *)luaL_checkudata(L, index, AUDIO_SOUND_METATABLE);
luaL_argcheck(L, sound->alive, index, "closed audio sound");
return sound;
}
static int
push_error(lua_State *L, ma_result r) {
lua_pushnil(L);
lua_pushstring(L, ma_result_description(r));
return 2;
}
static int
laudio_group_uninit(lua_State *L) {
struct audio_group *group = (struct audio_group *)luaL_checkudata(L, 1, AUDIO_GROUP_METATABLE);
if (group->alive) {
ma_sound_group_uninit(&group->group);
group->alive = 0;
}
return 0;
}
static int
laudio_sound_uninit(lua_State *L) {
struct audio_sound *sound = (struct audio_sound *)luaL_checkudata(L, 1, AUDIO_SOUND_METATABLE);
if (sound->alive) {
ma_sound_uninit(&sound->sound);
sound->alive = 0;
}
return 0;
}
static ma_result
zr_open(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile) {
struct custom_vfs *vfs = (struct custom_vfs *)pVFS;
if (openMode != MA_OPEN_MODE_READ)
return MA_NOT_IMPLEMENTED;
zipreader_file zf = zipreader_open(vfs->zipnames, pFilePath);
if (zf == NULL) {
return MA_ERROR;
}
*pFile = (ma_vfs_file)zf;
return MA_SUCCESS;
}
static ma_result
zr_close(ma_vfs* pVFS, ma_vfs_file file) {
(void)pVFS;
zipreader_close((zipreader_file)file);
return MA_SUCCESS;
}
static ma_result
zr_read(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead) {
(void)pVFS;
int bytes = (int)sizeInBytes;
if (bytes!= sizeInBytes || bytes < 0)
return MA_OUT_OF_RANGE;
int rd = zipreader_read((zipreader_file)file, pDst, bytes);
if (rd < 0)
return MA_IO_ERROR;
*pBytesRead = rd;
return MA_SUCCESS;
}
static ma_result
zr_seek(ma_vfs* pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin) {
(void)pVFS;
int whence;
switch (origin) {
case ma_seek_origin_start :
whence = SEEK_SET;
break;
case ma_seek_origin_current :
whence = SEEK_CUR;
break;
case ma_seek_origin_end :
whence = SEEK_END;
break;
default :
return MA_INVALID_ARGS;
}
if (zipreader_seek((zipreader_file)file, offset, whence) != 0) {
return MA_ERROR;
}
return MA_SUCCESS;
}
static ma_result
zr_tell(ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor) {
(void)pVFS;
*pCursor = zipreader_tell((zipreader_file)file);
if (*pCursor < 0)
return MA_ERROR;
return MA_SUCCESS;
}
static ma_result
zr_info(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo) {
(void)pVFS;
pInfo->sizeInBytes = zipreader_size((zipreader_file)file);
return MA_SUCCESS;
}
static int
laudio_init_vfs(lua_State *L) {
struct custom_engine *e = (struct custom_engine *)lua_touserdata(L, 1);
luaL_checktype(L, 2, LUA_TUSERDATA);
e->vfs.zipnames = lua_touserdata(L, 2);
e->vfs.base.cb.onOpen = zr_open;
e->vfs.base.cb.onOpenW = NULL;
e->vfs.base.cb.onClose = zr_close;
e->vfs.base.cb.onRead = zr_read;
e->vfs.base.cb.onWrite = NULL;
e->vfs.base.cb.onSeek = zr_seek;
e->vfs.base.cb.onTell = zr_tell;
e->vfs.base.cb.onInfo = zr_info;
return 0;
}
static int
laudio_init(lua_State *L) {
struct custom_engine *e = (struct custom_engine *)lua_newuserdatauv(L, sizeof(*e), 0);
ma_default_vfs_init(&e->vfs.base, NULL);
e->vfs.base.cb.onOpen = vfs_open_local;
e->vfs.zipnames = NULL;
ma_resource_manager_config config = ma_resource_manager_config_init();
config.pVFS = &e->vfs;
ma_result r = ma_resource_manager_init(&config, &e->rm);
if (r != MA_SUCCESS) {
return luaL_error(L, "ma_resource_manager_init() error : %s", ma_result_description(r));
}
ma_engine_config ec = ma_engine_config_init();
ec.pResourceManager = &e->rm;
r = ma_engine_init(&ec, &e->engine);
if (r != MA_SUCCESS) {
return luaL_error(L, "ma_engine_init() error : %s", ma_result_description(r));
}
e->rm.config.decodedFormat = ma_format_f32;
e->rm.config.decodedSampleRate = ma_engine_get_sample_rate(&e->engine);
lua_pushlightuserdata(L, (void *)e);
return 2;
}
static int
laudio_deinit(lua_State *L) {
struct custom_engine *e = check_engine(L, 1);
ma_engine_uninit(&e->engine);
ma_resource_manager_uninit(&e->rm);
return 0;
}
static int
laudio_group_init(lua_State *L) {
struct custom_engine *e = check_engine(L, 1);
struct audio_group *group = (struct audio_group *)lua_newuserdatauv(L, sizeof(*group), 0);
group->alive = 0;
ma_result r = ma_sound_group_init(&e->engine, 0, NULL, &group->group);
if (r != MA_SUCCESS) {
lua_pop(L, 1);
return push_error(L, r);
}
group->alive = 1;
luaL_setmetatable(L, AUDIO_GROUP_METATABLE);
return 1;
}
static int
laudio_group_set_volume(lua_State *L) {
struct audio_group *group = check_group(L, 1);
float volume = (float)luaL_checknumber(L, 2);
ma_sound_group_set_volume(&group->group, volume);
return 0;
}
static int
laudio_sound_init(lua_State *L) {
struct custom_engine *e = check_engine(L, 1);
const char *filename = luaL_checkstring(L, 2);
ma_uint32 flags = (ma_uint32)luaL_optinteger(L, 3, 0);
struct audio_group *group = NULL;
if (!lua_isnoneornil(L, 4)) {
group = check_group(L, 4);
}
struct audio_sound *sound = (struct audio_sound *)lua_newuserdatauv(L, sizeof(*sound), 0);
sound->alive = 0;
ma_result r = ma_sound_init_from_file(&e->engine, filename, flags, group ? &group->group : NULL, NULL, &sound->sound);
if (r != MA_SUCCESS) {
lua_pop(L, 1);
return push_error(L, r);
}
sound->alive = 1;
luaL_setmetatable(L, AUDIO_SOUND_METATABLE);
return 1;
}
static int
laudio_sound_start(lua_State *L) {
struct audio_sound *sound = check_sound(L, 1);
ma_result r = ma_sound_start(&sound->sound);
if (r != MA_SUCCESS) {
return push_error(L, r);
}
lua_pushboolean(L, 1);
return 1;
}
static int
laudio_sound_stop(lua_State *L) {
struct audio_sound *sound = check_sound(L, 1);
ma_result r;
if (lua_isnoneornil(L, 2)) {
r = ma_sound_stop(&sound->sound);
} else {
ma_uint64 fade_ms = (ma_uint64)luaL_checkinteger(L, 2);
if (fade_ms == 0) {
r = ma_sound_stop(&sound->sound);
} else {
r = ma_sound_stop_with_fade_in_milliseconds(&sound->sound, fade_ms);
}
}
if (r != MA_SUCCESS) {
return push_error(L, r);
}
lua_pushboolean(L, 1);
return 1;
}
static int
laudio_sound_playing(lua_State *L) {
struct audio_sound *sound = check_sound(L, 1);
lua_pushboolean(L, ma_sound_is_playing(&sound->sound));
return 1;
}
static int
laudio_sound_set_volume(lua_State *L) {
struct audio_sound *sound = check_sound(L, 1);
float volume = (float)luaL_checknumber(L, 2);
ma_sound_set_volume(&sound->sound, volume);
return 0;
}
static int
laudio_sound_set_pan(lua_State *L) {
struct audio_sound *sound = check_sound(L, 1);
float pan = (float)luaL_checknumber(L, 2);
ma_sound_set_pan(&sound->sound, pan);
return 0;
}
static int
laudio_sound_set_pitch(lua_State *L) {
struct audio_sound *sound = check_sound(L, 1);
float pitch = (float)luaL_checknumber(L, 2);
ma_sound_set_pitch(&sound->sound, pitch);
return 0;
}
static int
laudio_sound_set_looping(lua_State *L) {
struct audio_sound *sound = check_sound(L, 1);
int looping = lua_toboolean(L, 2);
ma_sound_set_looping(&sound->sound, looping);
return 0;
}
static int
laudio_sound_seek(lua_State *L) {
struct audio_sound *sound = check_sound(L, 1);
float seconds = (float)luaL_checknumber(L, 2);
ma_result r = ma_sound_seek_to_second(&sound->sound, seconds);
if (r != MA_SUCCESS) {
return push_error(L, r);
}
lua_pushboolean(L, 1);
return 1;
}
static int
laudio_sound_tell(lua_State *L) {
struct audio_sound *sound = check_sound(L, 1);
float seconds = 0.0f;
ma_result r = ma_sound_get_cursor_in_seconds(&sound->sound, &seconds);
if (r != MA_SUCCESS) {
return push_error(L, r);
}
lua_pushnumber(L, seconds);
return 1;
}
int
luaopen_soluna_audio(lua_State *L) {
luaL_checkversion(L);
if (luaL_newmetatable(L, AUDIO_GROUP_METATABLE)) {
lua_pushcfunction(L, laudio_group_uninit);
lua_setfield(L, -2, "__gc");
}
lua_pop(L, 1);
if (luaL_newmetatable(L, AUDIO_SOUND_METATABLE)) {
lua_pushcfunction(L, laudio_sound_uninit);
lua_setfield(L, -2, "__gc");
}
lua_pop(L, 1);
luaL_Reg l[] = {
{ "init", laudio_init },
{ "init_vfs", laudio_init_vfs },
{ "deinit", laudio_deinit },
{ "group_init", laudio_group_init },
{ "group_uninit", laudio_group_uninit },
{ "group_set_volume", laudio_group_set_volume },
{ "sound_init", laudio_sound_init },
{ "sound_uninit", laudio_sound_uninit },
{ "sound_start", laudio_sound_start },
{ "sound_stop", laudio_sound_stop },
{ "sound_playing", laudio_sound_playing },
{ "sound_set_volume", laudio_sound_set_volume },
{ "sound_set_pan", laudio_sound_set_pan },
{ "sound_set_pitch", laudio_sound_set_pitch },
{ "sound_set_looping", laudio_sound_set_looping },
{ "sound_seek", laudio_sound_seek },
{ "sound_tell", laudio_sound_tell },
{ NULL, NULL },
};
luaL_newlib(L, l);
return 1;
}
================================================
FILE: src/batch.c
================================================
#include "batch.h"
#include <stdlib.h>
#include <assert.h>
#include <stdatomic.h>
#define DEFAULT_SIZE 1024
struct draw_batch {
int cap;
struct draw_primitive * stream;
};
struct draw_batch *
batch_new(int size) {
if (size < DEFAULT_SIZE)
size = DEFAULT_SIZE;
struct draw_batch * batch = (struct draw_batch *)malloc(sizeof(*batch));
if (batch == NULL)
return NULL;
batch->cap = size;
batch->stream = (struct draw_primitive *)malloc(sizeof(struct draw_primitive) * size);
if (batch->stream == NULL) {
free(batch);
return NULL;
}
return batch;
}
void
batch_delete(struct draw_batch *B) {
if (B == NULL)
return;
free(B->stream);
free(B);
}
struct draw_primitive *
batch_reserve(struct draw_batch *B, int size) {
if (size <= B->cap)
return B->stream;
int cap = B->cap;
do {
cap = cap * 3/2;
} while (cap < size);
struct draw_primitive * stream = realloc(B->stream, cap * sizeof(struct draw_primitive));
if (stream == NULL)
return NULL;
B->stream = stream;
B->cap = cap;
return stream;
}
================================================
FILE: src/batch.h
================================================
#ifndef soluna_batch_h
#define soluna_batch_h
#include <stdint.h>
struct draw_primitive {
int32_t x; // sign bit + 23 + 8 fix number
int32_t y;
uint32_t sr; // scale + rot
int32_t sprite; // negative : material
};
struct draw_primitive_external {
int sprite;
};
struct draw_batch;
struct draw_batch * batch_new(int size);
struct draw_primitive * batch_reserve(struct draw_batch *, int size);
void batch_delete(struct draw_batch *);
#endif
================================================
FILE: src/blit.glsl
================================================
@vs vs
out vec2 uv;
void main() {
vec2 position = vec2(gl_VertexIndex & 1, gl_VertexIndex >> 1);
vec2 screen = position * 2.0 - 1.0;
gl_Position = vec4(screen.x, -screen.y, 0.0, 1.0);
uv = position;
}
@end
@fs fs
layout(binding=0) uniform texture2D tex;
layout(binding=0) uniform sampler smp;
in vec2 uv;
out vec4 frag_color;
void main() {
frag_color = texture(sampler2D(tex, smp), uv);
}
@end
@program blit vs fs
================================================
FILE: src/colorquad.glsl
================================================
@vs vs
layout(binding=0) uniform vs_params {
vec2 framesize;
};
struct sr_mat {
mat2 m;
};
layout(binding=0) readonly buffer sr_lut {
sr_mat sr[];
};
in vec4 position;
in uint idx;
in vec4 c;
out vec4 color;
void main() {
ivec2 u2 = ivec2(0 , position.z);
ivec2 v2 = ivec2(0 , position.w);
vec2 uv_offset = vec2(u2[gl_VertexIndex & 1] , v2[gl_VertexIndex >> 1]);
vec2 pos = (uv_offset * sr[idx].m + position.xy) * framesize;
gl_Position = vec4(pos.x - 1.0f, pos.y + 1.0f, 0, 1);
color = c;
}
@end
@fs fs
in vec4 color;
out vec4 frag_color;
void main() {
frag_color = color;
}
@end
@program colorquad vs fs
================================================
FILE: src/data/settingdefault.dl
================================================
sprite_max : 0x40000
texture_size : 2048
srbuffer_size : 0x10000
batch_size : 65536
draw_instance : 65536
entry : main.lua
project : soluna
service_path : "./?.lua"
width : 1024
height : 768
high_dpi : false
window_title : soluna
background : 0x4080c0
tmpbuffer_size : 0x20000
================================================
FILE: src/drawmgr.c
================================================
#include <lua.h>
#include <lauxlib.h>
#include <stdint.h>
#include "batch.h"
#include "spritemgr.h"
struct draw_element {
struct draw_primitive * base;
int n;
int material;
int texture;
};
struct drawmgr {
struct sprite_bank *bank;
int cap;
int n;
int bank_n;
struct draw_element data[1];
};
static int
ldrawmgr_len(lua_State *L) {
struct drawmgr * d = lua_touserdata(L, 1);
lua_pushinteger(L, d->n);
return 1;
}
static int
ldrawmgr_index(lua_State *L) {
struct drawmgr * d = lua_touserdata(L, 1);
int idx = luaL_checkinteger(L, 2) - 1;
if (idx < 0 || idx >= d->n) {
return 0;
}
struct draw_element *e = &(d->data[idx]);
lua_pushinteger(L, e->material);
lua_pushlightuserdata(L, e->base);
lua_pushinteger(L, e->n);
if (e->texture >= 0) {
lua_pushinteger(L, e->texture);
return 4;
} else {
return 3;
}
}
static int
ldrawmgr_reset(lua_State *L) {
struct drawmgr * d = (struct drawmgr *)luaL_checkudata(L, 1, "SOLUNA_DRAWMGR");
d->n = 0;
d->bank_n = d->bank->n;
return 0;
}
static int
append_external_material(struct drawmgr * d, struct draw_primitive *base, int n, int matid, int texid) {
int i;
struct sprite_rect * rect = d->bank->rect;
for (i=1;i<n;i++) {
if (base[i*2].sprite != matid) {
break;
}
struct draw_primitive_external * ext = (struct draw_primitive_external *)&base[i*2+1];
int sprite = ext->sprite;
if (sprite >= 0 && rect[sprite].texid != texid) {
break;
}
}
struct draw_element *e = &d->data[d->n++];
e->base = base;
e->n = i;
e->material = -matid;
e->texture = texid;
return i;
}
static int
append_default_material(struct drawmgr * d, struct draw_primitive *base, int n, int texid) {
int i;
struct sprite_rect * rect = d->bank->rect;
int rect_n = d->bank_n;
for (i=1;i<n;i++) {
int sprite = base[i].sprite;
if (sprite <= 0 || sprite > rect_n)
break;
--sprite;
if (texid != rect[sprite].texid)
break;
}
struct draw_element *e = &d->data[d->n++];
e->base = base;
e->n = i;
e->material = 0;
e->texture = texid;
return i;
}
static int
ldrawmgr_append(lua_State *L) {
struct drawmgr * d = (struct drawmgr *)luaL_checkudata(L, 1, "SOLUNA_DRAWMGR");
struct draw_primitive *prim = (struct draw_primitive *)lua_touserdata(L, 2);
int prim_n = luaL_checkinteger(L, 3);
struct sprite_rect * rect = d->bank->rect;
int rect_n = d->bank_n;
int i;
struct draw_primitive *end_ptr = &prim[prim_n];
for (i=0;i<prim_n;) {
struct draw_primitive *p = &prim[i];
int index = p->sprite;
if (d->n >= d->cap) {
return luaL_error(L, "Too many draw");
}
if (index <= 0) {
if (i == prim_n || index == 0) {
return luaL_error(L, "Invalid batch stream");
}
struct draw_primitive_external * ext = (struct draw_primitive_external *)&prim[i+1];
int sprite = ext->sprite;
int texid = -1;
if (sprite >= 0) {
texid = rect[sprite].texid;
}
i += append_external_material(d, p, (end_ptr - p)/2, index, texid) * 2;
} else {
--index;
if (index >= rect_n)
return luaL_error(L, "Invalid sprite id %d", index);
int texid = rect[index].texid;
i += append_default_material(d, p, end_ptr - p, texid);
}
}
return 0;
}
static int
ldrawmgr_new(lua_State *L) {
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
void * bank = lua_touserdata(L, 1);
int cap = luaL_checkinteger(L, 2);
struct drawmgr * d = (struct drawmgr *)lua_newuserdatauv(L, sizeof(*d) + (cap-1)*sizeof(d->data[0]), 0);
d->bank = (struct sprite_bank *)bank;
d->cap = cap;
d->n = 0;
if (luaL_newmetatable(L, "SOLUNA_DRAWMGR")) {
luaL_Reg l[] = {
{ "__index", NULL },
{ "__len", ldrawmgr_len },
{ "__call", ldrawmgr_index },
{ "reset", ldrawmgr_reset },
{ "append", ldrawmgr_append },
{ NULL, NULL },
};
luaL_setfuncs(L, l, 0);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
}
lua_setmetatable(L, -2);
return 1;
}
int
luaopen_drawmgr(lua_State *L) {
luaL_checkversion(L);
luaL_Reg l[] = {
{ "new", ldrawmgr_new },
{ NULL, NULL },
};
luaL_newlib(L, l);
return 1;
}
================================================
FILE: src/embedlua.c
================================================
#include "bootstrap.lua.h"
#include "service.lua.h"
#include "log.lua.h"
#include "timer.lua.h"
#include "root.lua.h"
#include "main.lua.h"
#include "start.lua.h"
#include "print_r.lua.h"
#include "loader.lua.h"
#include "spritebundle.lua.h"
#include "render.lua.h"
#include "settingdefault.dl.h"
#include "settings.lua.h"
#include "initsetting.lua.h"
#include "fontmgr.lua.h"
#include "gamepad.lua.h"
#include "soluna.lua.h"
#include "icon.lua.h"
#include "layout.lua.h"
#include "text.lua.h"
#include "util.lua.h"
#include "coroutine.lua.h"
#include "packageloader.lua.h"
#include "audio.lua.h"
#include "matdefault.lua.h"
#include "mattext.lua.h"
#include "matquad.lua.h"
#include "matmask.lua.h"
#include "lua.h"
#include "lauxlib.h"
#define REG_SOURCE(name) \
lua_pushlightuserdata(L, (void *)luasrc_##name); \
lua_pushinteger(L, sizeof(luasrc_##name) - 1); \
lua_pushcclosure(L, get_string, 2); \
lua_setfield(L, -2, #name);
#define REG_MATERIAL(name) \
lua_pushstring(L, #name); \
lua_rawseti(L, -2, luaL_len(L, -2) + 1); \
REG_SOURCE(name)
#define REG_DATALIST(name) \
lua_pushlightuserdata(L, (void *)dl_##name); \
lua_pushinteger(L, sizeof(dl_##name) - 1); \
lua_pushcclosure(L, get_stringloader, 2); \
lua_setfield(L, -2, #name);
static int
get_string(lua_State *L) {
const char * s = (const char *)lua_touserdata(L, lua_upvalueindex(1));
size_t sz = (size_t)lua_tointeger(L, lua_upvalueindex(2));
lua_pushexternalstring(L, s, sz, NULL, NULL);
return 1;
}
static int
get_stringloader(lua_State *L) {
lua_pushvalue(L, lua_upvalueindex(1));
lua_pushvalue(L, lua_upvalueindex(2));
return 2;
}
int
luaopen_embedsource(lua_State *L) {
lua_newtable(L);
lua_newtable(L); // runtime
REG_SOURCE(bootstrap)
REG_SOURCE(service)
REG_SOURCE(main)
REG_SOURCE(print_r)
REG_SOURCE(fontmgr)
REG_SOURCE(packageloader)
lua_setfield(L, -2, "runtime");
lua_newtable(L); // runtime
REG_SOURCE(spritebundle)
REG_SOURCE(icon)
REG_SOURCE(layout)
REG_SOURCE(text)
REG_SOURCE(soluna)
REG_SOURCE(util)
REG_SOURCE(coroutine)
REG_SOURCE(initsetting)
lua_setfield(L, -2, "lib");
lua_newtable(L); // service
REG_SOURCE(log)
REG_SOURCE(root)
REG_SOURCE(timer)
REG_SOURCE(start)
REG_SOURCE(loader)
REG_SOURCE(render)
REG_SOURCE(gamepad)
REG_SOURCE(settings)
REG_SOURCE(audio)
lua_setfield(L, -2, "service");
lua_newtable(L); // material
REG_MATERIAL(matdefault)
REG_MATERIAL(mattext)
REG_MATERIAL(matquad)
REG_MATERIAL(matmask)
lua_setfield(L, -2, "material");
lua_newtable(L); // data list
REG_DATALIST(settingdefault)
lua_setfield(L, -2, "data");
return 1;
}
================================================
FILE: src/entry.c
================================================
#define SOKOL_IMPL
#include <lua.h>
#include <lauxlib.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <locale.h>
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
#define SOKOL_D3D11
#elif defined(__APPLE__)
#define SOKOL_METAL
#elif defined(__EMSCRIPTEN__)
#define SOKOL_WGPU
#elif defined(__linux__)
#define SOKOL_GLCORE
#else
#error Unsupport platform
#endif
#include "version.h"
#define FRAME_CALLBACK 1
#define CLEANUP_CALLBACK 2
#define EVENT_CALLBACK 3
#define CALLBACK_COUNT 3
#include "sokol/sokol_app.h"
#include "sokol/sokol_gfx.h"
#include "sokol/sokol_glue.h"
#include "sokol/sokol_log.h"
#include "sokol/sokol_args.h"
#include "loginfo.h"
#include "appevent.h"
#include "ime_state.h"
#if defined(__APPLE__)
#include "platform/macos/soluna_macos_ime.h"
#endif
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
#include "platform/windows/soluna_windows_ime.h"
#endif
#if defined(__linux__)
#include "platform/linux/soluna_linux_ime.h"
#endif
#if defined(__EMSCRIPTEN__)
#include "platform/wasm/soluna_wasm_ime.h"
#endif
static void app_event(const sapp_event* ev);
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
#define PLATFORM "windows"
#elif defined(__APPLE__)
#define PLATFORM "macos"
#elif defined(__EMSCRIPTEN__)
#define PLATFORM "wasm"
#elif defined(__linux__)
#define PLATFORM "linux"
#else
#define PLATFORM "unknown"
#endif
struct app_context {
lua_State *L;
lua_State *quitL;
int (*send_log)(void *ud, unsigned int id, void *data, uint32_t sz);
void *send_log_ud;
void *mqueue;
};
static struct app_context *CTX = NULL;
struct soluna_ime_rect_state g_soluna_ime_rect = { 0.0f, 0.0f, 0.0f, 0.0f, 0, false };
void soluna_emit_char(uint32_t codepoint, uint32_t modifiers, bool repeat);
struct soluna_message {
const char *type;
union {
int p[2];
uint64_t u64;
} v;
};
static inline struct soluna_message *
message_create(const char *type, int p1, int p2) {
struct soluna_message *msg = (struct soluna_message *)malloc(sizeof(*msg));
msg->type = type;
msg->v.p[0] = p1;
msg->v.p[1] = p2;
return msg;
}
static inline struct soluna_message *
message_create64(const char *type, uint64_t p) {
struct soluna_message *msg = (struct soluna_message *)malloc(sizeof(*msg));
msg->type = type;
msg->v.u64 = p;
return msg;
}
static inline void
message_release(struct soluna_message *msg) {
free(msg);
}
void
soluna_emit_char(uint32_t codepoint, uint32_t modifiers, bool repeat) {
sapp_event ev;
memset(&ev, 0, sizeof(ev));
ev.type = SAPP_EVENTTYPE_CHAR;
ev.frame_count = sapp_frame_count();
ev.char_code = codepoint;
ev.modifiers = modifiers;
ev.key_repeat = repeat;
app_event(&ev);
}
static int
lmessage_send(lua_State *L) {
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
luaL_checktype(L, 2, LUA_TLIGHTUSERDATA);
int (*send_message)(void *ud, void *p) = lua_touserdata(L, 1);
void *send_message_ud = lua_touserdata(L, 2);
const char * what = NULL;
if (lua_type(L, 3) == LUA_TSTRING) {
what = lua_tostring(L, 3);
} else {
luaL_checktype(L, 3, LUA_TLIGHTUSERDATA);
what = (const char *)lua_touserdata(L, 3);
}
int64_t p1 = luaL_optinteger(L, 4, 0);
struct soluna_message * msg = NULL;
if (lua_isnoneornil(L, 5)) {
msg = message_create64(what, p1);
} else {
int p2 = luaL_checkinteger(L, 5);
msg = message_create(what, (int)p1, p2);
}
int fail = send_message(send_message_ud, msg);
if (fail) {
message_release(msg);
}
lua_pushboolean(L, !fail);
return 1;
}
static int
lmessage_unpack(lua_State *L) {
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
struct soluna_message *m = (struct soluna_message *)lua_touserdata(L,1);
lua_pushstring(L, m->type);
lua_pushinteger(L, m->v.p[0]);
lua_pushinteger(L, m->v.p[1]);
lua_pushinteger(L, m->v.u64);
message_release(m);
return 4;
}
static void
request_app_quit(void) {
if (CTX) {
CTX->quitL = CTX->L;
CTX->L = NULL;
}
}
static int
lquit_signal(lua_State *L) {
request_app_quit();
return 0;
}
#if defined(__EMSCRIPTEN__)
EMSCRIPTEN_KEEPALIVE
void
soluna_runtime_quit(void) {
request_app_quit();
}
#endif
static int
levent_unpack(lua_State *L) {
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
struct event_message em;
app_event_unpack(&em, lua_touserdata(L, 1));
lua_pushlightuserdata(L, (void *)em.typestr);
lua_pushinteger(L, em.p1);
lua_pushinteger(L, em.p2);
lua_pushinteger(L, em.p3);
return 4;
}
static int
lset_window_title(lua_State *L) {
if (CTX == NULL || lua_type(L, 1) != LUA_TSTRING)
return 0;
const char * text = lua_tostring(L, 1);
sapp_set_window_title(text);
return 0;
}
struct icon_pixels {
uint8_t *ptr;
};
static void
icon_free_pixels(struct icon_pixels *payloads, int count) {
for (int i = 0; i < count; ++i) {
free(payloads[i].ptr);
}
}
static int
icon_get_int(lua_State *L, int index, const char *field, const char *fallback) {
int abs_index = lua_absindex(L, index);
int value = 0;
int type = lua_getfield(L, abs_index, field);
if (type == LUA_TNUMBER) {
value = (int)lua_tointeger(L, -1);
lua_pop(L, 1);
return value;
}
lua_pop(L, 1);
if (fallback) {
type = lua_getfield(L, abs_index, fallback);
if (type == LUA_TNUMBER) {
value = (int)lua_tointeger(L, -1);
lua_pop(L, 1);
return value;
}
lua_pop(L, 1);
}
luaL_error(L, "icon missing %s", field);
return 0;
}
static void
icon_copy_image(lua_State *L, int index, sapp_image_desc *dst, struct icon_pixels *payload) {
int abs_index = lua_absindex(L, index);
int width = icon_get_int(L, abs_index, "w", "width");
int height = icon_get_int(L, abs_index, "h", "height");
if (width <= 0 || height <= 0) {
luaL_error(L, "icon size (%d * %d) must be positive", width, height);
}
size_t stride = 0;
if (lua_getfield(L, abs_index, "stride") == LUA_TNUMBER) {
stride = (size_t)lua_tointeger(L, -1);
}
lua_pop(L, 1);
size_t explicit_size = 0;
if (lua_getfield(L, abs_index, "size") == LUA_TNUMBER) {
explicit_size = (size_t)lua_tointeger(L, -1);
}
lua_pop(L, 1);
int type = lua_getfield(L, abs_index, "data");
const uint8_t *src = NULL;
size_t src_size = 0;
if (type == LUA_TSTRING) {
src = (const uint8_t *)lua_tolstring(L, -1, &src_size);
} else if (type == LUA_TUSERDATA) {
src = (const uint8_t *)lua_touserdata(L, -1);
src_size = lua_rawlen(L, -1);
} else if (type == LUA_TLIGHTUSERDATA) {
src = (const uint8_t *)lua_touserdata(L, -1);
src_size = explicit_size;
} else {
lua_pop(L, 1);
luaL_error(L, "icon.data must be buffer");
}
lua_pop(L, 1);
if (src == NULL) {
luaL_error(L, "icon data missing");
}
size_t row_bytes = (size_t)width * 4;
if (stride == 0) {
stride = row_bytes;
}
if (stride < row_bytes) {
luaL_error(L, "icon stride < width");
}
if (!(type == LUA_TLIGHTUSERDATA && explicit_size == 0)) {
size_t required = stride * (size_t)height;
if (src_size < required) {
luaL_error(L, "icon buffer too small");
}
}
size_t copy_size = row_bytes * (size_t)height;
uint8_t *copy = (uint8_t *)malloc(copy_size);
if (copy == NULL) {
luaL_error(L, "icon alloc fail");
}
if (stride == row_bytes) {
memcpy(copy, src, copy_size);
} else {
const uint8_t *s = src;
uint8_t *d = copy;
int y;
for (y = 0; y < height; ++y) {
memcpy(d, s, row_bytes);
s += stride;
d += row_bytes;
}
}
dst->width = width;
dst->height = height;
dst->pixels.ptr = copy;
dst->pixels.size = copy_size;
payload->ptr = copy;
}
static float
get_field_float(lua_State *L, int index, const char *field) {
lua_getfield(L, index, field);
if (lua_getfield(L, index, field) != LUA_TNUMBER) {
return luaL_error(L, "Invalid .%s type (%s is not a number)",
field, lua_typename(L, lua_type(L, -1)));
}
float value = (float)lua_tonumber(L, -1);
lua_pop(L, 1);
return value;
}
static int
lset_icon(lua_State *L) {
if (lua_isnoneornil(L, 1))
return 0;
luaL_checktype(L, 1, LUA_TTABLE);
sapp_icon_desc desc;
memset(&desc, 0, sizeof(desc));
struct icon_pixels payloads[SAPP_MAX_ICONIMAGES];
memset(payloads, 0, sizeof(payloads));
int count = 0;
int abs_index = lua_absindex(L, 1);
if (lua_getfield(L, abs_index, "data") != LUA_TNIL) {
lua_pop(L, 1);
icon_copy_image(L, abs_index, &desc.images[count], &payloads[count]);
++count;
} else {
lua_pop(L, 1);
int len = (int)lua_rawlen(L, abs_index);
for (int i = 1; i <= len; ++i) {
if (count >= SAPP_MAX_ICONIMAGES) {
icon_free_pixels(payloads, count);
luaL_error(L, "too many icon images");
}
lua_rawgeti(L, abs_index, i);
luaL_checktype(L, -1, LUA_TTABLE);
icon_copy_image(L, -1, &desc.images[count], &payloads[count]);
++count;
lua_pop(L, 1);
}
}
i
gitextract_o983gujm/
├── .editorconfig
├── .github/
│ ├── actions/
│ │ ├── sample/
│ │ │ └── action.yml
│ │ └── soluna/
│ │ └── action.yml
│ └── workflows/
│ ├── nightly.yml
│ └── pages.yml
├── .gitignore
├── .gitmodules
├── LICENSE
├── Makefile
├── README.md
├── asset/
│ ├── sounds.dl
│ └── sprites.dl
├── clibs/
│ ├── datalist/
│ │ └── make.lua
│ ├── ltask/
│ │ └── make.lua
│ ├── lua/
│ │ └── make.lua
│ ├── sample/
│ │ └── make.lua
│ ├── soluna/
│ │ ├── compile_lua.lua
│ │ ├── compile_shader.lua
│ │ ├── make.lua
│ │ ├── runlua.lua
│ │ └── shader2c.lua
│ ├── yoga/
│ │ └── make.lua
│ └── zip/
│ └── make.lua
├── docs/
│ ├── app.lua
│ ├── args.lua
│ ├── callback.lua
│ ├── coroutine.lua
│ ├── crypt.lua
│ ├── datalist.lua
│ ├── file.lua
│ ├── font.lua
│ ├── font_system.lua
│ ├── image.lua
│ ├── layout.lua
│ ├── lfs.lua
│ ├── material_mask.lua
│ ├── material_quad.lua
│ ├── material_text.lua
│ ├── soluna.lua
│ ├── text.lua
│ ├── url.lua
│ └── zip.lua
├── extlua/
│ ├── extlua.c
│ ├── extlua.temp.c
│ ├── extlua_impl.c
│ ├── extlua_impl.temp.c
│ ├── extlua_sample.c
│ ├── gen.lua
│ ├── gen_sokol.lua
│ ├── gen_soluna.lua
│ ├── perspective_quad.glsl
│ ├── sokolapi.c
│ ├── sokolapi.temp.c
│ ├── sokolapi_impl.c
│ ├── sokolapi_impl.temp.c
│ ├── solunaapi.c
│ ├── solunaapi.h
│ ├── solunaapi.h.temp
│ ├── solunaapi.temp.c
│ ├── solunaapi_impl.c
│ └── solunaapi_impl.temp.c
├── make.lua
├── script/
│ ├── act.lua
│ ├── act_targets.lua
│ ├── compile_commands.lua
│ ├── datalist2c.lua
│ ├── hashversion.lua
│ └── lua2c.lua
├── src/
│ ├── appevent.h
│ ├── audio.c
│ ├── batch.c
│ ├── batch.h
│ ├── blit.glsl
│ ├── colorquad.glsl
│ ├── data/
│ │ └── settingdefault.dl
│ ├── drawmgr.c
│ ├── embedlua.c
│ ├── entry.c
│ ├── extapi.c
│ ├── extapi_types.h
│ ├── extapi_types.temp.h
│ ├── external.c
│ ├── file.c
│ ├── font.c
│ ├── font_define.h
│ ├── font_manager.c
│ ├── font_manager.h
│ ├── font_system.c
│ ├── gamepad.c
│ ├── image.c
│ ├── ime_char_filter.h
│ ├── ime_state.h
│ ├── lcrypt.c
│ ├── lfs.c
│ ├── loginfo.h
│ ├── lsha1.c
│ ├── luabuffer.h
│ ├── lualib/
│ │ ├── coroutine.lua
│ │ ├── fontmgr.lua
│ │ ├── icon.lua
│ │ ├── initsetting.lua
│ │ ├── layout.lua
│ │ ├── main.lua
│ │ ├── packageloader.lua
│ │ ├── print_r.lua
│ │ ├── soluna.lua
│ │ ├── spritebundle.lua
│ │ ├── text.lua
│ │ └── util.lua
│ ├── luamods.c
│ ├── luayoga.c
│ ├── luazip.c
│ ├── maskquad.glsl
│ ├── material/
│ │ ├── matdefault.lua
│ │ ├── matmask.lua
│ │ ├── matquad.lua
│ │ └── mattext.lua
│ ├── material_blit.c
│ ├── material_default.c
│ ├── material_mask.c
│ ├── material_quad.c
│ ├── material_text.c
│ ├── material_util.c
│ ├── material_util.h
│ ├── mutex.h
│ ├── openlibs.c
│ ├── openurl.c
│ ├── platform/
│ │ ├── linux/
│ │ │ ├── soluna_linux_ime.c
│ │ │ └── soluna_linux_ime.h
│ │ ├── macos/
│ │ │ ├── soluna_macos_ime.h
│ │ │ └── soluna_macos_ime.m
│ │ ├── wasm/
│ │ │ ├── soluna_ime.js
│ │ │ ├── soluna_openurl.js
│ │ │ └── soluna_wasm_ime.h
│ │ └── windows/
│ │ ├── soluna_windows_ime.c
│ │ └── soluna_windows_ime.h
│ ├── render.c
│ ├── render_bindings.c
│ ├── render_bindings.h
│ ├── render_uniform.c
│ ├── sdfimage.c
│ ├── sdftext.glsl
│ ├── service/
│ │ ├── audio.lua
│ │ ├── gamepad.lua
│ │ ├── loader.lua
│ │ ├── log.lua
│ │ ├── render.lua
│ │ ├── settings.lua
│ │ └── start.lua
│ ├── sprite_submit.h
│ ├── spritemgr.c
│ ├── spritemgr.h
│ ├── srbuffer.c
│ ├── srbuffer.h
│ ├── texquad.glsl
│ ├── tmpbuffer.h
│ ├── transform.c
│ ├── transform.h
│ ├── truetype.c
│ ├── truetype.h
│ ├── version.h
│ ├── winfile.c
│ ├── writelog.c
│ ├── yogaone.cpp
│ └── zipreader.h
├── test/
│ ├── audio.game
│ ├── audio.lua
│ ├── bundle.lua
│ ├── extlua/
│ │ └── material/
│ │ └── perspective_quad.lua
│ ├── extlua.game
│ ├── extlua.lua
│ ├── file.lua
│ ├── hello.game
│ ├── hello.lua
│ ├── icon.lua
│ ├── image.lua
│ ├── ime.lua
│ ├── intersect.lua
│ ├── layout.lua
│ ├── mask.lua
│ ├── mtex.game
│ ├── mtex.lua
│ ├── setting.lua
│ ├── sprite.lua
│ ├── spritepack.lua
│ ├── test.lua
│ ├── text.lua
│ ├── version.lua
│ ├── window.game
│ └── window.lua
└── website/
├── README.md
├── README.zh-CN.md
├── astro.config.mjs
├── eslint.config.mjs
├── package.json
├── packages/
│ └── astro-theme-soluna/
│ ├── package.json
│ └── src/
│ ├── client/
│ │ └── play.ts
│ ├── components/
│ │ ├── Footer.astro
│ │ ├── Hero.astro
│ │ ├── Menubar.astro
│ │ ├── Nav.astro
│ │ ├── PlainList.astro
│ │ ├── Section.astro
│ │ ├── docs/
│ │ │ └── DocsPage.astro
│ │ └── examples/
│ │ ├── ExampleListPage.astro
│ │ └── ExamplePlayPage.astro
│ ├── layouts/
│ │ └── BaseLayout.astro
│ └── styles/
│ └── theme.css
├── pnpm-workspace.yaml
├── scripts/
│ └── prepare-runtime.mjs
├── src/
│ ├── content.config.ts
│ ├── lib/
│ │ ├── content.ts
│ │ └── readme.ts
│ └── pages/
│ ├── docs/
│ │ └── index.astro
│ ├── examples/
│ │ ├── [id].astro
│ │ └── index.astro
│ └── index.astro
└── tsconfig.json
SYMBOL INDEX (1184 symbols across 75 files)
FILE: extlua/extlua.c
type lua_api (line 9) | struct lua_api {
type lua_api (line 176) | struct lua_api
function LUA_API (line 178) | LUA_API lua_State *
function LUA_API (line 183) | LUA_API void
function LUA_API (line 188) | LUA_API lua_State *
function LUA_API (line 193) | LUA_API int
function LUA_API (line 198) | LUA_API lua_CFunction
function LUA_API (line 203) | LUA_API lua_Number
function LUA_API (line 208) | LUA_API int
function LUA_API (line 213) | LUA_API int
function LUA_API (line 218) | LUA_API void
function LUA_API (line 223) | LUA_API void
function LUA_API (line 228) | LUA_API void
function LUA_API (line 233) | LUA_API void
function LUA_API (line 238) | LUA_API int
function LUA_API (line 243) | LUA_API void
function LUA_API (line 248) | LUA_API int
function LUA_API (line 253) | LUA_API int
function LUA_API (line 258) | LUA_API int
function LUA_API (line 263) | LUA_API int
function LUA_API (line 268) | LUA_API int
function LUA_API (line 273) | LUA_API int
function LUA_API (line 278) | LUA_API const char *
function LUA_API (line 283) | LUA_API lua_Number
function LUA_API (line 288) | LUA_API lua_Integer
function LUA_API (line 293) | LUA_API int
function LUA_API (line 298) | LUA_API const char *
function LUA_API (line 303) | LUA_API lua_Unsigned
function LUA_API (line 308) | LUA_API lua_CFunction
function LUA_API (line 313) | LUA_API void *
function LUA_API (line 318) | LUA_API lua_State *
function LUA_API (line 323) | LUA_API const void *
function LUA_API (line 328) | LUA_API void
function LUA_API (line 333) | LUA_API int
function LUA_API (line 338) | LUA_API int
function LUA_API (line 343) | LUA_API void
function LUA_API (line 348) | LUA_API void
function LUA_API (line 353) | LUA_API void
function LUA_API (line 358) | LUA_API const char *
function LUA_API (line 363) | LUA_API const char *
function LUA_API (line 369) | LUA_API const char *
function LUA_API (line 374) | LUA_API const char *
function LUA_API (line 380) | LUA_API void
function LUA_API (line 385) | LUA_API void
function LUA_API (line 390) | LUA_API void
function LUA_API (line 395) | LUA_API int
function LUA_API (line 400) | LUA_API int
function LUA_API (line 405) | LUA_API int
function LUA_API (line 410) | LUA_API int
function LUA_API (line 415) | LUA_API int
function LUA_API (line 420) | LUA_API int
function LUA_API (line 425) | LUA_API int
function LUA_API (line 430) | LUA_API int
function LUA_API (line 435) | LUA_API void
function LUA_API (line 440) | LUA_API void *
function LUA_API (line 445) | LUA_API int
function LUA_API (line 450) | LUA_API int
function LUA_API (line 455) | LUA_API void
function LUA_API (line 460) | LUA_API void
function LUA_API (line 465) | LUA_API void
function LUA_API (line 470) | LUA_API void
function LUA_API (line 475) | LUA_API void
function LUA_API (line 480) | LUA_API void
function LUA_API (line 485) | LUA_API void
function LUA_API (line 490) | LUA_API int
function LUA_API (line 495) | LUA_API int
function LUA_API (line 500) | LUA_API void
function LUA_API (line 506) | LUA_API int
function LUA_API (line 512) | LUA_API int
function LUA_API (line 518) | LUA_API int
function LUA_API (line 523) | LUA_API int
function LUA_API (line 529) | LUA_API int
function LUA_API (line 535) | LUA_API int
function LUA_API (line 540) | LUA_API int
function LUA_API (line 545) | LUA_API void
function LUA_API (line 550) | LUA_API void
function LUA_API (line 555) | LUA_API int
function LUA_API (line 560) | LUA_API int
function LUA_API (line 565) | LUA_API void
function LUA_API (line 570) | LUA_API void
function lua_numbertocstring (line 575) | LUA_API unsigned
function LUA_API (line 580) | LUA_API size_t
function LUA_API (line 585) | LUA_API lua_Alloc
function LUA_API (line 590) | LUA_API void
function LUA_API (line 595) | LUA_API void
function LUA_API (line 600) | LUA_API void
function LUA_API (line 605) | LUA_API int
function LUA_API (line 610) | LUA_API int
function LUA_API (line 615) | LUA_API const char *
function LUA_API (line 620) | LUA_API const char *
function LUA_API (line 625) | LUA_API const char *
function LUA_API (line 630) | LUA_API const char *
function LUA_API (line 635) | LUA_API void *
function LUA_API (line 640) | LUA_API void
function LUA_API (line 646) | LUA_API void
function LUA_API (line 651) | LUA_API lua_Hook
function LUA_API (line 656) | LUA_API int
function LUA_API (line 661) | LUA_API int
function LUA_API (line 666) | LUA_API void
function LUA_API (line 671) | LUA_API int
function LUA_API (line 676) | LUA_API int
function LUA_API (line 681) | LUA_API const char *
function LUA_API (line 686) | LUA_API int
function LUA_API (line 691) | LUA_API int
function LUA_API (line 696) | LUA_API const char *
function LUA_API (line 702) | LUA_API const char *
function LUA_API (line 708) | LUA_API lua_Number
function LUA_API (line 713) | LUA_API lua_Number
function LUA_API (line 718) | LUA_API lua_Integer
function LUA_API (line 723) | LUA_API lua_Integer
function LUA_API (line 729) | LUA_API void
function LUA_API (line 734) | LUA_API void
function LUA_API (line 739) | LUA_API void
function LUA_API (line 744) | LUA_API int
function LUA_API (line 749) | LUA_API void
function LUA_API (line 754) | LUA_API void *
function LUA_API (line 759) | LUA_API void *
function LUA_API (line 764) | LUA_API void
function LUA_API (line 769) | LUA_API int
function LUA_API (line 775) | LUA_API int
function LUA_API (line 780) | LUA_API int
function LUA_API (line 785) | LUA_API void *
function LUA_API (line 791) | LUA_API int
function LUA_API (line 796) | LUA_API void
function LUA_API (line 801) | LUA_API int
function LUA_API (line 807) | LUA_API int
function LUA_API (line 813) | LUA_API int
function LUA_API (line 818) | LUA_API lua_State *
function luaL_makeseed (line 823) | LUA_API unsigned
function LUA_API (line 828) | LUA_API lua_Integer
function LUA_API (line 833) | LUA_API void
function LUA_API (line 839) | LUA_API const char *
function LUA_API (line 845) | LUA_API void
function LUA_API (line 850) | LUA_API int
function LUA_API (line 855) | LUA_API void
function LUA_API (line 861) | LUA_API void
function LUA_API (line 867) | LUA_API void
function LUA_API (line 872) | LUA_API char *
function LUA_API (line 877) | LUA_API void
function LUA_API (line 882) | LUA_API void
function LUA_API (line 887) | LUA_API void
function LUA_API (line 892) | LUA_API void
function LUA_API (line 897) | LUA_API void
function LUA_API (line 902) | LUA_API char *
function LUA_API (line 909) | LUA_API
function LUA_API (line 919) | LUA_API int
function LUA_API (line 930) | LUA_API int
function stub_luaL_checkversion_ (line 941) | static void
function stub_lua_createtable (line 945) | static void stub_lua_createtable (lua_State *L, int narr, int nrec) {
function stub_luaL_setfuncs (line 948) | static void stub_luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
type sokol_api (line 951) | struct sokol_api
type soluna_api (line 952) | struct soluna_api
type extlua_apis (line 954) | struct extlua_apis {
function LUA_API (line 960) | LUA_API void
FILE: extlua/extlua.temp.c
type lua_api (line 7) | struct lua_api {
function lua_gc (line 27) | int
function LUA_API (line 38) | LUA_API int
function stub_luaL_checkversion_ (line 49) | static void
function stub_lua_createtable (line 53) | static void stub_lua_createtable (lua_State *L, int narr, int nrec) {
function stub_luaL_setfuncs (line 56) | static void stub_luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
type sokol_api (line 59) | struct sokol_api
type soluna_api (line 60) | struct soluna_api
type extlua_apis (line 62) | struct extlua_apis {
function LUA_API (line 68) | LUA_API void
FILE: extlua/extlua_impl.c
type lua_api (line 6) | struct lua_api {
type lua_api (line 173) | struct lua_api
type lua_api (line 175) | struct lua_api
FILE: extlua/extlua_impl.temp.c
type lua_api (line 4) | struct lua_api {
type lua_api (line 10) | struct lua_api
type lua_api (line 12) | struct lua_api
FILE: extlua/extlua_sample.c
type color (line 24) | struct color {
type pquad_payload (line 28) | struct pquad_payload {
type pquad_inst (line 34) | struct pquad_inst {
type material_perspective_quad (line 43) | struct material_perspective_quad {
type sprite_rect_basis (line 54) | struct sprite_rect_basis {
function sg_pipeline (line 75) | static sg_pipeline
function set_position_homography (line 92) | static void
function soluna_material_error (line 129) | static inline soluna_material_error
function decode_sprite_rect_basis (line 138) | static inline void
function build_quad_from_rect (line 158) | static inline void
function submit (line 173) | static void
function lmaterial_perspective_quad_submit (line 241) | static int
function lmaterial_perspective_quad_draw (line 257) | static int
function lmaterial_perspective_quad_reset (line 279) | static int
function lset_material_id (line 286) | static int
function init_pipeline (line 296) | static void
function lnew_material_perspective_quad (line 311) | static int
function get_number_field (line 380) | static inline float
function get_quad (line 389) | static int
function get_q (line 405) | static void
function get_color (line 423) | static struct color
type pquad_stream_context (line 440) | struct pquad_stream_context {
function write_perspective_quad_stream (line 453) | static void
function lperspective_quad_sprite (line 489) | static int
function luaopen_ext_material_perspective_quad (line 513) | static int
function lhello (line 529) | static int
function luaopen_foobar (line 535) | static int
function EXTLUA_EXPORT (line 545) | EXTLUA_EXPORT int
FILE: extlua/sokolapi.c
type sokol_api (line 7) | struct sokol_api {
type sokol_api (line 29) | struct sokol_api
function SOKOL_GFX_API_DECL (line 31) | SOKOL_GFX_API_DECL sg_buffer
function SOKOL_GFX_API_DECL (line 36) | SOKOL_GFX_API_DECL sg_shader
function SOKOL_GFX_API_DECL (line 41) | SOKOL_GFX_API_DECL sg_pipeline
function SOKOL_GFX_API_DECL (line 46) | SOKOL_GFX_API_DECL void
function SOKOL_GFX_API_DECL (line 51) | SOKOL_GFX_API_DECL void
function SOKOL_GFX_API_DECL (line 56) | SOKOL_GFX_API_DECL void
function SOKOL_GFX_API_DECL (line 61) | SOKOL_GFX_API_DECL void
function SOKOL_GFX_API_DECL (line 66) | SOKOL_GFX_API_DECL int
function SOKOL_GFX_API_DECL (line 71) | SOKOL_GFX_API_DECL void
function SOKOL_GFX_API_DECL (line 76) | SOKOL_GFX_API_DECL void
function SOKOL_GFX_API_DECL (line 81) | SOKOL_GFX_API_DECL void
function SOKOL_GFX_API_DECL (line 86) | SOKOL_GFX_API_DECL void
function SOKOL_GFX_API_DECL (line 91) | SOKOL_GFX_API_DECL void
function SOKOL_GFX_API_DECL (line 96) | SOKOL_GFX_API_DECL sg_backend
function SOKOL_GFX_API_DECL (line 101) | SOKOL_GFX_API_DECL sg_resource_state
function SOKOL_GFX_API_DECL (line 106) | SOKOL_GFX_API_DECL sg_resource_state
function SOKOL_GFX_API_DECL (line 111) | SOKOL_GFX_API_DECL sg_resource_state
type lua_api (line 118) | struct lua_api
type soluna_api (line 119) | struct soluna_api
type extlua_apis (line 121) | struct extlua_apis {
function sokolapi_init (line 127) | void
FILE: extlua/sokolapi.temp.c
type sokol_api (line 5) | struct sokol_api {
FILE: extlua/sokolapi_impl.c
type sokol_api (line 5) | struct sokol_api {
type sokol_api (line 27) | struct sokol_api
type sokol_api (line 29) | struct sokol_api
FILE: extlua/sokolapi_impl.temp.c
type sokol_api (line 3) | struct sokol_api {
type sokol_api (line 9) | struct sokol_api
type sokol_api (line 11) | struct sokol_api
FILE: extlua/solunaapi.c
type soluna_api (line 7) | struct soluna_api {
type soluna_api (line 20) | struct soluna_api
function soluna_material_error (line 22) | soluna_material_error
function soluna_material_sprite_rect (line 27) | int
function sg_bindings (line 32) | sg_bindings
function soluna_material_error (line 37) | soluna_material_error
function soluna_material_stream_free (line 42) | void
function soluna_material_stream_read (line 47) | int
function soluna_material_stream_error (line 52) | void
function soluna_material_stream_failed (line 57) | int
type lua_api (line 64) | struct lua_api
type sokol_api (line 65) | struct sokol_api
type extlua_apis (line 67) | struct extlua_apis {
function solunaapi_init (line 73) | void
FILE: extlua/solunaapi.h
type soluna_sprite_rect (line 14) | struct soluna_sprite_rect {
type soluna_material_stream_item (line 24) | struct soluna_material_stream_item {
type soluna_material_stream_data (line 31) | struct soluna_material_stream_data {
type soluna_material_stream (line 37) | struct soluna_material_stream {
type soluna_material_stream_context (line 44) | struct soluna_material_stream_context {
type soluna_render_bindings (line 48) | struct soluna_render_bindings {
type soluna_sprite_bank (line 52) | struct soluna_sprite_bank {
type soluna_material_stream_context (line 56) | struct soluna_material_stream_context
type soluna_material_stream_item (line 57) | struct soluna_material_stream_item
type soluna_sprite_bank (line 62) | struct soluna_sprite_bank
type soluna_sprite_rect (line 62) | struct soluna_sprite_rect
type soluna_render_bindings (line 63) | struct soluna_render_bindings
type soluna_material_stream (line 64) | struct soluna_material_stream
type soluna_material_stream_context (line 66) | struct soluna_material_stream_context
type soluna_material_stream_data (line 66) | struct soluna_material_stream_data
type soluna_material_stream_context (line 67) | struct soluna_material_stream_context
type soluna_material_stream_context (line 68) | struct soluna_material_stream_context
FILE: extlua/solunaapi.temp.c
type soluna_api (line 11) | struct soluna_api
type sokol_api (line 16) | struct sokol_api
type extlua_apis (line 18) | struct extlua_apis {
type extlua_apis (line 26) | struct extlua_apis
FILE: extlua/solunaapi_impl.c
type soluna_sprite_rect (line 9) | struct soluna_sprite_rect {
type soluna_material_stream_item (line 19) | struct soluna_material_stream_item {
type soluna_material_stream_data (line 26) | struct soluna_material_stream_data {
type soluna_material_stream (line 32) | struct soluna_material_stream {
type soluna_material_stream_context (line 39) | struct soluna_material_stream_context {
type soluna_render_bindings (line 43) | struct soluna_render_bindings {
type soluna_sprite_bank (line 47) | struct soluna_sprite_bank {
type soluna_material_stream_context (line 51) | struct soluna_material_stream_context
type soluna_material_stream_item (line 52) | struct soluna_material_stream_item
type soluna_sprite_bank (line 56) | struct soluna_sprite_bank
type soluna_sprite_rect (line 56) | struct soluna_sprite_rect
type soluna_render_bindings (line 57) | struct soluna_render_bindings
type soluna_material_stream (line 58) | struct soluna_material_stream
type soluna_material_stream_context (line 60) | struct soluna_material_stream_context
type soluna_material_stream_data (line 60) | struct soluna_material_stream_data
type soluna_material_stream_context (line 61) | struct soluna_material_stream_context
type soluna_material_stream_context (line 62) | struct soluna_material_stream_context
type soluna_api (line 64) | struct soluna_api {
type soluna_api (line 77) | struct soluna_api
type soluna_api (line 79) | struct soluna_api
FILE: extlua/solunaapi_impl.temp.c
type soluna_api (line 5) | struct soluna_api {
type soluna_api (line 11) | struct soluna_api
type soluna_api (line 13) | struct soluna_api
FILE: src/appevent.h
type event_message (line 4) | struct event_message {
function get_xy (line 11) | static inline void
function mouse_message (line 33) | static inline void
function touch_message (line 58) | static inline void
function window_message (line 84) | static inline void
function key_message (line 99) | static inline void
function app_event_unpack (line 115) | static inline void
FILE: src/audio.c
function ma_result (line 18) | static ma_result
type custom_vfs (line 50) | struct custom_vfs {
type custom_engine (line 55) | struct custom_engine {
type audio_group (line 61) | struct audio_group {
type audio_sound (line 66) | struct audio_sound {
type custom_engine (line 74) | struct custom_engine
type custom_engine (line 77) | struct custom_engine
type audio_group (line 80) | struct audio_group
type audio_group (line 82) | struct audio_group
type audio_group (line 82) | struct audio_group
type audio_sound (line 87) | struct audio_sound
type audio_sound (line 89) | struct audio_sound
type audio_sound (line 89) | struct audio_sound
function push_error (line 94) | static int
function laudio_group_uninit (line 101) | static int
function laudio_sound_uninit (line 111) | static int
function ma_result (line 121) | static ma_result
function ma_result (line 134) | static ma_result
function ma_result (line 141) | static ma_result
function ma_result (line 154) | static ma_result
function ma_result (line 177) | static ma_result
function ma_result (line 186) | static ma_result
function laudio_init_vfs (line 193) | static int
function laudio_init (line 209) | static int
function laudio_deinit (line 238) | static int
function laudio_group_init (line 247) | static int
function laudio_group_set_volume (line 262) | static int
function laudio_sound_init (line 270) | static int
function laudio_sound_start (line 292) | static int
function laudio_sound_stop (line 303) | static int
function laudio_sound_playing (line 324) | static int
function laudio_sound_set_volume (line 331) | static int
function laudio_sound_set_pan (line 339) | static int
function laudio_sound_set_pitch (line 347) | static int
function laudio_sound_set_looping (line 355) | static int
function laudio_sound_seek (line 363) | static int
function laudio_sound_tell (line 375) | static int
function luaopen_soluna_audio (line 387) | int
FILE: src/batch.c
type draw_batch (line 8) | struct draw_batch {
type draw_batch (line 13) | struct draw_batch
type draw_batch (line 17) | struct draw_batch
type draw_batch (line 17) | struct draw_batch
type draw_primitive (line 21) | struct draw_primitive
type draw_primitive (line 21) | struct draw_primitive
function batch_delete (line 29) | void
type draw_primitive (line 37) | struct draw_primitive
type draw_batch (line 38) | struct draw_batch
type draw_primitive (line 45) | struct draw_primitive
type draw_primitive (line 45) | struct draw_primitive
FILE: src/batch.h
type draw_primitive (line 6) | struct draw_primitive {
type draw_primitive_external (line 13) | struct draw_primitive_external {
type draw_batch (line 17) | struct draw_batch
type draw_batch (line 19) | struct draw_batch
type draw_primitive (line 20) | struct draw_primitive
type draw_batch (line 20) | struct draw_batch
type draw_batch (line 21) | struct draw_batch
FILE: src/drawmgr.c
type draw_element (line 8) | struct draw_element {
type drawmgr (line 15) | struct drawmgr {
function ldrawmgr_len (line 23) | static int
function ldrawmgr_index (line 30) | static int
function ldrawmgr_reset (line 49) | static int
function append_external_material (line 57) | static int
function append_default_material (line 80) | static int
function ldrawmgr_append (line 102) | static int
function ldrawmgr_new (line 143) | static int
function luaopen_drawmgr (line 171) | int
FILE: src/embedlua.c
function get_string (line 50) | static int
function get_stringloader (line 58) | static int
function luaopen_embedsource (line 65) | int
FILE: src/entry.c
type app_context (line 89) | struct app_context {
type app_context (line 97) | struct app_context
type soluna_ime_rect_state (line 99) | struct soluna_ime_rect_state
type soluna_message (line 103) | struct soluna_message {
type soluna_message (line 111) | struct soluna_message
type soluna_message (line 113) | struct soluna_message
type soluna_message (line 113) | struct soluna_message
type soluna_message (line 120) | struct soluna_message
type soluna_message (line 122) | struct soluna_message
type soluna_message (line 122) | struct soluna_message
function message_release (line 128) | static inline void
function soluna_emit_char (line 133) | void
function lmessage_send (line 145) | static int
function lmessage_unpack (line 174) | static int
function request_app_quit (line 186) | static void
function lquit_signal (line 194) | static int
function EMSCRIPTEN_KEEPALIVE (line 201) | EMSCRIPTEN_KEEPALIVE
function levent_unpack (line 208) | static int
function lset_window_title (line 220) | static int
type icon_pixels (line 229) | struct icon_pixels {
function icon_free_pixels (line 233) | static void
function icon_get_int (line 240) | static int
function icon_copy_image (line 264) | static void
function get_field_float (line 345) | static float
function lset_icon (line 357) | static int
function lset_ime_rect (line 399) | static int
function lset_ime_font (line 446) | static int
function lclose_window (line 489) | static int
function lmqueue (line 495) | static int
function lversion (line 504) | static int
function desc_get_boolean (line 511) | static void
function desc_get_int (line 521) | static void
function desc_get_string (line 531) | static void
function linit_desc (line 541) | static int
function luaopen_soluna_app (line 555) | int
function log_func (line 581) | static void
function pmain (line 611) | static int
function get_function (line 650) | static int
function init_callback (line 660) | static int
function msghandler (line 679) | static int
function get_app_info (line 686) | static void
function start_app (line 701) | static int
function app_init (line 731) | static void
function lua_State (line 758) | static lua_State *
function invoke_callback (line 771) | static void
function app_frame (line 783) | static void
function app_cleanup (line 792) | static void
function app_event (line 815) | static void
function init_settings (line 857) | static int
function sapp_desc (line 877) | sapp_desc
FILE: src/extapi.c
type soluna_material_stream_context (line 25) | struct soluna_material_stream_context
type material_stream_context_impl (line 27) | struct material_stream_context_impl {
type material_stream_context_impl (line 37) | struct material_stream_context_impl
type soluna_material_stream_context (line 38) | struct soluna_material_stream_context
type material_stream_context_impl (line 39) | struct material_stream_context_impl
function soluna_material_error (line 42) | static soluna_material_error
function material_stream_error (line 54) | void
function material_stream_failed (line 62) | int
function soluna_material_error (line 68) | static soluna_material_error
function soluna_material_error (line 120) | soluna_material_error
function material_sprite_rect (line 125) | int
function sg_bindings (line 142) | sg_bindings
function stream_payload_max (line 149) | static size_t
function material_stream_free (line 154) | void
function soluna_material_error (line 159) | soluna_material_error
function clear_stream_read (line 221) | static void
function fail_stream_read (line 231) | static int
function material_stream_read (line 238) | int
FILE: src/extapi_types.h
type soluna_sprite_rect (line 12) | struct soluna_sprite_rect {
type soluna_material_stream_item (line 22) | struct soluna_material_stream_item {
type soluna_material_stream_data (line 29) | struct soluna_material_stream_data {
type soluna_material_stream (line 35) | struct soluna_material_stream {
type soluna_material_stream_context (line 42) | struct soluna_material_stream_context {
type soluna_render_bindings (line 46) | struct soluna_render_bindings {
type soluna_sprite_bank (line 50) | struct soluna_sprite_bank {
type soluna_material_stream_context (line 54) | struct soluna_material_stream_context
type soluna_material_stream_item (line 55) | struct soluna_material_stream_item
FILE: src/external.c
type lua_api (line 6) | struct lua_api
type sokol_api (line 7) | struct sokol_api
type soluna_api (line 8) | struct soluna_api
type lua_api (line 9) | struct lua_api
type sokol_api (line 10) | struct sokol_api
type soluna_api (line 11) | struct soluna_api
type extlua_apis (line 13) | struct extlua_apis {
type extlua_apis (line 19) | struct extlua_apis
type extlua_apis (line 21) | struct extlua_apis
function init_extraspace (line 28) | static void
function get_reg (line 34) | static int
function count_table (line 51) | static int
function register_libs (line 63) | static void
function register_libs_ (line 93) | static int
function load_libs (line 103) | static int
type preload_extlib (line 122) | struct preload_extlib {
type preload_extlib (line 127) | struct preload_extlib
function preload_lib (line 129) | static void
function cmpreg (line 145) | static int
function preload_libs (line 152) | static int
function lua_CFunction (line 191) | static lua_CFunction
function searcher (line 209) | static int
function luaopen_extlua (line 228) | int
FILE: src/file.c
function lfile_exist (line 8) | static int
function lfile_load (line 26) | static int
function luaopen_soluna_file (line 53) | int
FILE: src/font.c
type font_manager (line 17) | struct font_manager
type font_manager (line 20) | struct font_manager
function lsubmit (line 27) | static int
function limport (line 35) | static int
function lname (line 44) | static int
function ltexture (line 56) | static int
function ltexture_write (line 66) | static int
function ltouch (line 78) | static int
function lcobj (line 88) | static int
function limport_icon (line 95) | static int
function lsize (line 108) | static int
function llist (line 135) | static int
function luaopen_font (line 159) | int
function luavm_init (line 188) | static int
function fontm_init (line 201) | static int
function fontm_shutdown (line 234) | static int
function luaopen_font_manager (line 248) | int
FILE: src/font_define.h
type font_glyph (line 11) | struct font_glyph {
function codepoint_key (line 26) | static inline uint32_t
function font_index (line 31) | static inline int
FILE: src/font_manager.c
type font_slot (line 48) | struct font_slot {
type priority_list (line 58) | struct priority_list {
type truetype_font (line 64) | struct truetype_font
type font_manager (line 66) | struct font_manager {
type font_manager (line 84) | struct font_manager
function is_space_codepoint (line 104) | static inline int
function lock (line 114) | static inline void
function unlock (line 119) | static inline void
function stbtt_fontinfo (line 124) | static inline const stbtt_fontinfo*
function stbtt_fontinfo (line 129) | static inline const stbtt_fontinfo *
function ttf_with_family (line 137) | static inline int
function hash (line 142) | static inline int
function hash_lookup (line 147) | static int
type font_manager (line 160) | struct font_manager
function hash_insert (line 162) | static void
function rehash (line 182) | static void
function remove_node (line 200) | static void
function touch_slot (line 208) | static void
function get_icon (line 227) | static int
function font_manager_touch_unsafe (line 245) | static int
function font_manager_touch (line 309) | static int
function scale_font (line 317) | static inline int
function fscale_font (line 322) | static inline float
function font_manager_fontheight (line 327) | void
function font_manager_underline (line 345) | int
function font_manager_pixelsize (line 361) | int
function scale (line 369) | static inline void
function uscale (line 374) | static inline void
function font_manager_scale (line 379) | void
function icon_scale (line 390) | static void
type font_manager (line 401) | struct font_manager
type font_glyph (line 401) | struct font_glyph
type priority_list (line 412) | struct priority_list
type font_slot (line 426) | struct font_slot
type stbtt_fontinfo (line 456) | struct stbtt_fontinfo
type font_manager (line 499) | struct font_manager
type font_glyph (line 499) | struct font_glyph
type font_glyph (line 499) | struct font_glyph
function font_manager_flush (line 520) | int
function font_manager_import_unsafe (line 531) | static void
function font_manager_import (line 536) | void
function font_manager_addfont_with_family_unsafe (line 543) | static int
function font_manager_addfont_with_family (line 548) | int
function font_manager_enum_fontname (line 556) | int
function font_manager_sdf_mask (line 564) | float
function font_manager_sdf_distance (line 569) | float
function font_manager_sizeof (line 574) | size_t
function font_manager_icon_init (line 579) | void
function font_manager_init (line 587) | void
type font_manager (line 621) | struct font_manager
FILE: src/font_manager.h
type font_manager (line 9) | struct font_manager
type font_manager (line 12) | struct font_manager
type font_manager (line 13) | struct font_manager
type font_manager (line 14) | struct font_manager
type font_manager (line 16) | struct font_manager
type font_manager (line 17) | struct font_manager
type font_manager (line 18) | struct font_manager
type font_manager (line 19) | struct font_manager
type font_glyph (line 19) | struct font_glyph
type font_glyph (line 19) | struct font_glyph
type font_manager (line 22) | struct font_manager
type font_manager (line 23) | struct font_manager
type font_glyph (line 23) | struct font_glyph
type font_manager (line 24) | struct font_manager
type font_manager (line 25) | struct font_manager
type font_manager (line 26) | struct font_manager
type font_manager (line 27) | struct font_manager
type font_manager (line 28) | struct font_manager
type font_manager (line 31) | struct font_manager
FILE: src/font_system.c
function lttfdata (line 16) | static int
function CFDataRef (line 78) | static CFDataRef read_font_file_data(CFURLRef url) {
function lttfdata (line 108) | static int
function lttfdata (line 183) | static int
function lttfdata (line 201) | static int
function lttfdata (line 279) | static int
function luaopen_font_system (line 287) | int
FILE: src/gamepad.c
type gamepad_state (line 29) | struct gamepad_state {
function gamepad_getstate (line 45) | static int
function gamepad_init (line 64) | static void gamepad_init() {
function gamepad_getstate (line 104) | static int
function gamepad_getstate (line 192) | static int
function gamepad_getstate (line 251) | static int
type gamepad_global (line 267) | struct gamepad_global {
type gamepad_local (line 274) | struct gamepad_local {
function lgamepad_update (line 279) | static int
function luaopen_gamepad (line 390) | int
function lgamepad_device_init (line 401) | static int
function lgamepad_device_deinit (line 412) | static int
function lgamepad_device_update (line 418) | static int
function luaopen_gamepad_device (line 449) | int
FILE: src/image.c
function load_image (line 60) | static int
function image_load (line 75) | static int
function image_load_alpha (line 88) | static int
function image_info (line 112) | static int
type rect (line 128) | struct rect {
function rect_init (line 135) | static int
function remove_top (line 166) | static int
function remove_bottom (line 185) | static int
function remove_left (line 203) | static int
function remove_right (line 226) | static int
function image_crop (line 249) | static int
function limage_write_png (line 308) | static int
type canvas (line 321) | struct canvas {
function limage_tocanvas (line 328) | static int
function image_new (line 343) | static int
function image_canvas (line 405) | static int
function check_canvas (line 448) | static int
function image_canvas_size (line 460) | static int
function canvas_blit (line 473) | static int
function image_makeindex (line 517) | static int
function image_resize (line 539) | static int
function luaopen_image (line 577) | int
FILE: src/ime_char_filter.h
type soluna_ime_char_filter_state (line 8) | struct soluna_ime_char_filter_state {
function soluna_ime_char_queue_push (line 16) | static inline void
function soluna_ime_char_queue_consume (line 27) | static inline bool
function soluna_ime_char_filter_reset (line 41) | static inline void
function soluna_ime_char_filter_push_expected (line 47) | static inline void
function soluna_ime_char_filter_should_skip (line 52) | static inline bool
FILE: src/ime_state.h
type soluna_ime_rect_state (line 7) | struct soluna_ime_rect_state {
type soluna_ime_rect_state (line 16) | struct soluna_ime_rect_state
FILE: src/lcrypt.c
function des_main_ks (line 248) | static void
function des_crypt (line 317) | static void
function lrandomkey (line 341) | static int
function padding_mode_table (line 357) | static void
function padding_add_iso7816_4 (line 376) | static void
function padding_remove_iso7816_4 (line 382) | static int
function padding_add_pkcs7 (line 399) | static void
function padding_remove_pkcs7 (line 405) | static int
function check_padding_mode (line 427) | static inline void
function add_padding (line 433) | static void
function remove_padding (line 442) | static int
function des_key (line 448) | static void
function ldesencode (line 458) | static int
function ldesdecode (line 484) | static int
function Hash (line 517) | static void
function lhashkey (line 540) | static int
function ltohex (line 550) | static int
function lfromhex (line 571) | static int
function digest_md5 (line 625) | static void
function hmac (line 664) | static void
function hmac_md5 (line 682) | static void
function read64 (line 705) | static void
function pushqword (line 722) | static int
function lhmac64 (line 738) | static int
function lhmac64_md5 (line 753) | static int
function lhmac_hash (line 766) | static int
function mul_mod_p (line 792) | static inline uint64_t
function pow_mod_p (line 814) | static inline uint64_t
function powmodp (line 828) | static uint64_t
function push64 (line 835) | static void
function ldhsecret (line 850) | static int
function ldhexchange (line 867) | static int
function lb64encode (line 889) | static int
function b64index (line 932) | static inline int
function lb64decode (line 945) | static int
function lxor_str (line 1011) | static int
function luaopen_skynet_crypt (line 1035) | int
FILE: src/lfs.c
function utf8_filename (line 39) | static int
type dir_data (line 54) | struct dir_data {
function windows_filename (line 59) | static int
function system_error (line 72) | static void
function error_return (line 98) | static int
function push_filename (line 105) | static void
function dir_iter (line 112) | static int
function dir_close (line 145) | static int
function ldir (line 156) | static int
function lpersonaldir (line 201) | static int
function lcurrentdir (line 214) | static int
function lchdir (line 227) | static int
function push_st_mode (line 261) | static void push_st_mode (lua_State *L, STAT_STRUCT *info) {
function push_st_dev (line 265) | static void push_st_dev (lua_State *L, STAT_STRUCT *info) {
function push_st_ino (line 269) | static void push_st_ino (lua_State *L, STAT_STRUCT *info) {
function push_st_nlink (line 273) | static void push_st_nlink (lua_State *L, STAT_STRUCT *info) {
function push_st_uid (line 277) | static void push_st_uid (lua_State *L, STAT_STRUCT *info) {
function push_st_gid (line 281) | static void push_st_gid (lua_State *L, STAT_STRUCT *info) {
function push_st_rdev (line 285) | static void push_st_rdev (lua_State *L, STAT_STRUCT *info) {
function push_st_atime (line 289) | static void push_st_atime (lua_State *L, STAT_STRUCT *info) {
function push_st_mtime (line 293) | static void push_st_mtime (lua_State *L, STAT_STRUCT *info) {
function push_st_ctime (line 297) | static void push_st_ctime (lua_State *L, STAT_STRUCT *info) {
function push_st_size (line 301) | static void push_st_size (lua_State *L, STAT_STRUCT *info) {
function push_st_perm (line 319) | static void push_st_perm (lua_State *L, STAT_STRUCT *info) {
type _stat_members (line 325) | struct _stat_members {
type _stat_members (line 330) | struct _stat_members
function file_info (line 349) | static int
function lrealpath (line 390) | static int
function create_dir_wchar_ (line 410) | static inline int
function mkdir_utf8 (line 431) | static int
function pusherror (line 440) | static int
type dir_data (line 487) | struct dir_data {
function system_error (line 492) | static void
function error_return (line 497) | static int
function dir_iter (line 504) | static int
function dir_close (line 532) | static int
function ldir (line 543) | static int
function lpersonaldir (line 586) | static int
function lcurrentdir (line 602) | static int
function lchdir (line 612) | static int
function push_st_mode (line 644) | static void push_st_mode(lua_State *L, STAT_STRUCT *info) {
function push_st_dev (line 648) | static void push_st_dev(lua_State *L, STAT_STRUCT *info) {
function push_st_ino (line 652) | static void push_st_ino(lua_State *L, STAT_STRUCT *info) {
function push_st_nlink (line 656) | static void push_st_nlink(lua_State *L, STAT_STRUCT *info) {
function push_st_uid (line 660) | static void push_st_uid(lua_State *L, STAT_STRUCT *info) {
function push_st_gid (line 664) | static void push_st_gid(lua_State *L, STAT_STRUCT *info) {
function push_st_rdev (line 668) | static void push_st_rdev(lua_State *L, STAT_STRUCT *info) {
function push_st_atime (line 672) | static void push_st_atime(lua_State *L, STAT_STRUCT *info) {
function push_st_mtime (line 676) | static void push_st_mtime(lua_State *L, STAT_STRUCT *info) {
function push_st_ctime (line 680) | static void push_st_ctime(lua_State *L, STAT_STRUCT *info) {
function push_st_size (line 684) | static void push_st_size(lua_State *L, STAT_STRUCT *info) {
function push_st_perm (line 707) | static void push_st_perm(lua_State *L, STAT_STRUCT *info) {
type _stat_members (line 713) | struct _stat_members {
type _stat_members (line 718) | struct _stat_members
function file_info (line 737) | static int
function lrealpath (line 776) | static int
function pusherror (line 795) | static int
function pushresult (line 805) | static int
function lmkdir (line 819) | static int
function luaopen_localfs (line 825) | int
FILE: src/loginfo.h
type log_info (line 6) | struct log_info {
FILE: src/lsha1.c
type SHA1_CTX (line 89) | typedef struct {
function SHA1_Transform (line 122) | static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
function sat_SHA1_Init (line 175) | static void sat_SHA1_Init(SHA1_CTX* context)
function sat_SHA1_Update (line 188) | static void sat_SHA1_Update(SHA1_CTX* context, const uint8_t* data, cons...
function sat_SHA1_Final (line 217) | static void sat_SHA1_Final(SHA1_CTX* context, uint8_t digest[SHA1_DIGEST...
function lsha1 (line 247) | int
function xor_key (line 263) | static inline void
function lhmac_sha1 (line 272) | int
FILE: src/luamods.c
function soluna_embed (line 38) | void soluna_embed(lua_State* L) {
FILE: src/luayoga.c
type enum_string (line 18) | struct enum_string {
type set_number (line 23) | struct set_number {
type set_edge_number (line 32) | struct set_edge_number {
type set_two_number (line 38) | struct set_two_number {
function lnodeNew (line 43) | static int
function lnodeFree (line 55) | static int
function lnodeCalc (line 62) | static int
type pos (line 69) | struct pos {
function get_pos (line 74) | static void
function lnodeGet (line 86) | static int
function is_whitespace (line 106) | static inline int
function setNumberString (line 111) | static void
function setNumber (line 132) | static void
function lsetWidth (line 143) | static void
function lsetMinWidth (line 155) | static void
function lsetMaxWidth (line 167) | static void
function lsetHeight (line 179) | static void
function lsetMinHeight (line 191) | static void
function lsetMaxHeight (line 203) | static void
function count_words (line 223) | static int
type set_edge_number (line 238) | struct set_edge_number
function setFourNumber (line 259) | static void
type set_two_number (line 292) | struct set_two_number
function setTwoNumber (line 308) | static void
function setFlexBasis (line 338) | static void
function lsetFlex (line 351) | static void
function lsetMargin (line 403) | static void
function lsetPadding (line 413) | static void
function lsetBorder (line 423) | static void
function lsetGap (line 433) | static void
function getEnum (line 442) | static int
function getEnumHigh (line 455) | static int
function getEnumLow (line 461) | static int
function lsetFlexDirection (line 467) | static void
function lsetJustifyContent (line 472) | static void
function lsetAlignItems (line 477) | static void
function lsetAlignContent (line 482) | static void
function lsetAlignSelf (line 487) | static void
function lsetWrap (line 492) | static void
function lsetDisplay (line 497) | static void
function lsetPosition (line 502) | static void
function setPosition (line 507) | static void
function lsetTop (line 524) | static void
function lsetBottom (line 529) | static void
function lsetLeft (line 534) | static void
function lsetRight (line 539) | static void
function lsetAspectRatio (line 544) | static void
function set_array (line 550) | static void
function set_one (line 565) | static void
function lnodeSet (line 578) | static int
function LUAMOD_API (line 594) | LUAMOD_API int
FILE: src/luazip.c
function lcompress (line 22) | static int
function luncompress (line 49) | static int
type filename_convert (line 80) | struct filename_convert {
function zipFile (line 84) | static zipFile
function unzFile (line 97) | static unzFile
function FILE (line 110) | static FILE *
type filename_convert (line 133) | struct filename_convert {}
function zipFile (line 135) | static zipFile
function unzFile (line 140) | static unzFile
function FILE (line 145) | static FILE *
type ziphandle (line 152) | struct ziphandle {
type zipraw (line 156) | struct zipraw {
function zipFile (line 161) | static zipFile
function close_inzip (line 192) | static inline void
function zipwrite_add (line 199) | static int
function zipwrite_addfile (line 213) | static int
function zipwrite_open (line 243) | static int
function zipwrite_close (line 250) | static int
function zipwrite_closezip (line 259) | static int
function zipwrite_write (line 271) | static int
type unzhandle (line 285) | struct unzhandle {
function zipread_closezip (line 289) | static int
function lua_Integer (line 301) | static inline lua_Integer
function unz_file_pos (line 308) | static inline unz_file_pos *
function get_filelist (line 315) | static void
function zipread_list (line 339) | static int
function locate_file (line 361) | static void
function zipread_exist (line 369) | static int
function unzFile (line 380) | static unzFile
function close_file (line 409) | static void
function zipread_readfile (line 420) | static int
function zipread_size (line 448) | static int
function zipread_extract (line 461) | static int
function zipread_openfile (line 491) | static int
function zipread_closefile (line 497) | static int
function zipread_read (line 506) | static int
function zipwrite_copyfrom (line 529) | static int
function zipread_filename (line 573) | static int
function unzip (line 595) | static int
function zip (line 630) | static int
function lzip (line 669) | static int
function lziplist (line 685) | static int
function luaopen_zip (line 730) | int
function unzFile (line 749) | static unzFile
function zipreader_file (line 768) | zipreader_file
function zipreader_close (line 779) | void
function zipreader_read (line 784) | int
function zipreader_tell (line 789) | int64_t
function zipreader_size (line 794) | size_t
function reopen_file (line 804) | static void
function skip_bytes (line 815) | static int
function zipreader_seek (line 828) | int
function lziptest (line 862) | static int
FILE: src/material_blit.c
type material_blit (line 9) | struct material_blit {
function lmaterial_blit_draw (line 14) | static int
function init_pipeline (line 23) | static void
function lnew_material_blit (line 31) | static int
function luaopen_material_blit (line 53) | int
FILE: src/material_default.c
type inst_object (line 15) | struct inst_object {
type material_default (line 23) | struct material_default {
function submit (line 33) | static void
function lmaterial_default_submit (line 62) | static int
function lmaterial_default_draw_ (line 70) | static inline int
function lmaterial_default_draw (line 95) | static int
function lmaterial_default_draw_ex (line 100) | static int
function init_pipeline (line 105) | static void
function lnew_material_default (line 118) | static int
function luaopen_material_default (line 150) | int
FILE: src/material_mask.c
type color (line 15) | struct color {
type inst_object (line 19) | struct inst_object {
type mask (line 28) | struct mask {
type material_mask (line 33) | struct material_mask {
function submit (line 45) | static void
function lmaterial_mask_submit (line 78) | static int
function lmaterial_mask_draw_ (line 86) | static inline int
function lmaterial_mask_draw (line 112) | static int
function lmaterial_mask_draw_ex (line 117) | static int
function lset_material_id (line 122) | static int
function init_pipeline (line 132) | static void
function lnew_material_mask (line 146) | static int
type mask_primitive (line 178) | struct mask_primitive {
function lmask (line 186) | static int
function luaopen_material_mask (line 208) | int
FILE: src/material_quad.c
type color (line 15) | struct color {
type quad (line 19) | struct quad {
type inst_object (line 26) | struct inst_object {
type material_quad (line 33) | struct material_quad {
function submit (line 44) | static void
function lmateraial_quad_submit (line 72) | static int
function lmateraial_quad_draw_ (line 80) | static inline int
function lmateraial_quad_draw (line 106) | static int
function lmateraial_quad_draw_ex (line 111) | static int
function lset_material_id (line 116) | static int
function init_pipeline (line 126) | static void
function lnew_material_quad (line 138) | static int
type quad_primitive (line 165) | struct quad_primitive {
function lquad (line 173) | static int
function luaopen_material_quad (line 197) | int
FILE: src/material_text.c
type text (line 20) | struct text {
type inst_object (line 28) | struct inst_object {
type material_text (line 36) | struct material_text {
function submit (line 49) | static void
function lmateraial_text_submit (line 86) | static int
function draw_text (line 94) | static inline void
function lmateraial_text_draw_ (line 113) | static inline int
function lmateraial_text_draw (line 150) | static int
function lmateraial_text_draw_ex (line 155) | static int
function init_pipeline (line 160) | static void
function lnew_material_text_normal (line 173) | static int
function lchar_for_batch (line 213) | static int
function lset_material_id (line 230) | static int
type text_primitive (line 244) | struct text_primitive {
function count_string (line 301) | static int
type block_context (line 349) | struct block_context {
function advance (line 363) | static inline int
type position (line 371) | struct position {
function newline (line 382) | static inline int
function tohex (line 419) | static inline int
type block_context (line 429) | struct block_context
function advance_position (line 460) | static inline void
function ltext_ (line 472) | static int
function ltext (line 631) | static int
function ltext_position (line 636) | static int
function parse_alignment (line 655) | static uint32_t
function ltext_block (line 692) | static int
function luaopen_material_text (line 723) | int
FILE: src/material_util.c
function util_ref_object (line 6) | void
function util_submit_material (line 24) | void
function sg_pipeline (line 43) | sg_pipeline
FILE: src/material_util.h
type draw_primitive (line 10) | struct draw_primitive
type sg_shader_desc (line 13) | typedef const sg_shader_desc* (*util_shader_desc_func)(sg_backend backend);
FILE: src/openlibs.c
function soluna_openlibs (line 11) | void
FILE: src/openurl.c
function open_url (line 8) | static void
function soluna_wasm_call_open_url (line 26) | static void
function open_url (line 37) | static void
function open_url (line 49) | static void
function open_url (line 75) | static void
function lurl_open (line 81) | static int
function luaopen_url (line 88) | int
FILE: src/platform/linux/soluna_linux_ime.c
function soluna_linux_char_filter_state (line 32) | static inline struct soluna_ime_char_filter_state
function soluna_linux_reset_char_queues (line 43) | static void
function Display (line 48) | static Display *
function Window (line 53) | static Window
function soluna_linux_ensure_locale (line 58) | static void
function soluna_linux_set_spot (line 73) | static void
function soluna_linux_ensure_im (line 88) | bool
function soluna_linux_update_spot (line 123) | void
function soluna_linux_emit_utf8 (line 148) | static void
function soluna_linux_handle_keypress (line 176) | static bool
function soluna_linux_filter_event (line 218) | static bool
function soluna_linux_XNextEvent (line 242) | static int
function XNextEvent (line 261) | int
function soluna_linux_focus_reset (line 266) | static void
function soluna_linux_focus_in (line 271) | void
function soluna_linux_focus_out (line 284) | void
function soluna_linux_shutdown_ime (line 296) | void
function soluna_linux_on_rect_cleared (line 311) | void
function soluna_linux_should_skip_event (line 319) | bool
function soluna_linux_handle_event (line 327) | void
FILE: src/platform/wasm/soluna_wasm_ime.h
function soluna_wasm_char_filter_state (line 38) | static inline struct soluna_ime_char_filter_state
function soluna_wasm_call_setup (line 49) | static void
function soluna_wasm_call_show (line 60) | static void
function soluna_wasm_call_hide (line 71) | static void
function soluna_wasm_call_set_font (line 82) | static void
function soluna_wasm_call_set_color (line 93) | static void
function soluna_wasm_reset_queues (line 104) | static void
function soluna_wasm_set_font (line 109) | void
function soluna_wasm_ensure_locale (line 115) | static void
function soluna_wasm_emit_utf8 (line 128) | static void
function soluna_wasm_is_composing (line 154) | static inline bool
function soluna_wasm_hide (line 159) | void
function soluna_wasm_apply_rect (line 166) | void
function soluna_wasm_should_block_key_event (line 177) | static inline bool
function soluna_wasm_filter_char_event (line 193) | static inline bool
function soluna_wasm_handle_event (line 201) | static inline void
function EMSCRIPTEN_KEEPALIVE (line 221) | EMSCRIPTEN_KEEPALIVE void
function EMSCRIPTEN_KEEPALIVE (line 226) | EMSCRIPTEN_KEEPALIVE void
function EMSCRIPTEN_KEEPALIVE (line 231) | EMSCRIPTEN_KEEPALIVE void
FILE: src/platform/windows/soluna_windows_ime.c
function soluna_win32_set_candidate_position (line 21) | static void
function soluna_win32_apply_ime_rect (line 41) | void
function LRESULT (line 97) | static LRESULT CALLBACK
function soluna_win32_install_wndproc (line 133) | void
function soluna_win32_set_ime_font (line 149) | void
function soluna_win32_reset_ime_font (line 172) | void
FILE: src/render.c
type buffer (line 18) | struct buffer {
type image (line 23) | struct image {
type sampler (line 28) | struct sampler {
function get_buffer_type (line 32) | static struct sg_buffer_usage
function get_buffer_usage (line 52) | static void
function lbuffer_update (line 124) | static int
function lbuffer_ref (line 156) | static int
function lbuffer_tostring (line 165) | static int
function lbuffer (line 180) | static int
type pass (line 223) | struct pass {
function read_color_action (line 228) | static int
function lpass_begin (line 263) | static int
function lpass_end (line 273) | static int
function read_attachments (line 279) | static void
function lpass_new (line 310) | static int
function lsubmit (line 369) | static int
function limage_update (line 375) | static int
function get_pixel_format (line 390) | static int
function limage_ref (line 405) | static int
function limage (line 414) | static int
function lsampler_ref (line 473) | static int
type enum_string (line 482) | struct enum_string {
function convert_enum (line 487) | static int
function read_enum (line 498) | static int
function lsampler (line 515) | static int
function ldraw (line 557) | static int
function lsrbuffer_add (line 566) | static int
function lsrbuffer_ptr (line 581) | static int
function lsrbuffer (line 593) | static int
type inst_object (line 615) | struct inst_object {
type sprite_object (line 620) | struct sprite_object {
function lbuffer_size (line 626) | static int
function ltmp_buffer (line 644) | static int
function luaopen_render (line 655) | int
FILE: src/render_bindings.c
function sg_bindings (line 7) | static inline sg_bindings *
function lbindings_set_base (line 13) | static int
function lbindings_set_vb (line 21) | static int
function lbindings_set_voff (line 34) | static int
function lbindings_set_ib (line 44) | static int
function lbindings_set_ioff (line 54) | static int
type view (line 61) | struct view {
function lbindings_set_view (line 66) | static int
function lbindings_set_sampler (line 77) | static int
function lbindings_apply (line 90) | static int
function check_view_type (line 114) | static inline void
function lview_tostring (line 120) | static int
function lview_release (line 128) | static int
function lview_getptr (line 138) | static int
function lview_new (line 148) | int
function lbindings_new (line 221) | int
FILE: src/render_bindings.h
type render_bindings (line 6) | struct render_bindings {
FILE: src/render_uniform.c
function set_uniform_float (line 10) | static void
function set_uniform_int (line 34) | static void
function luniform_set (line 58) | static int
function set_key (line 85) | static void
function check_uniform (line 138) | static void
function get_typeinfo (line 147) | static void
function luniform_apply (line 175) | static int
function luniform_new (line 184) | int
FILE: src/sdfimage.c
function edt1d (line 26) | static void
function edt (line 54) | static void
type sdf_context (line 77) | struct sdf_context {
function sdf_convert (line 84) | static void
function image_loadsdf (line 149) | static int
function image_savesdf (line 189) | static int
function icon_bundle (line 205) | static int
function luaopen_image_sdf (line 229) | int
FILE: src/sprite_submit.h
function to_fixpoint_ (line 9) | static inline int32_t
function sprite_set_xy (line 15) | static inline void
function sprite_apply_xy (line 21) | static inline void
function convert_scale_ (line 27) | static inline int
function convert_scale_part_ (line 43) | static inline uint32_t
function convert_rot_ (line 56) | static inline int
function sprite_set_scale (line 66) | static inline void
function sprite_set_rot (line 71) | static inline void
function sprite_set_sr (line 76) | static inline void
function sprite_apply_scale (line 81) | static inline void
FILE: src/spritemgr.c
function lbank_add (line 19) | static int
function pack_sprite (line 42) | static int
type tmp_context (line 98) | struct tmp_context {
type tmp_context (line 104) | struct tmp_context
type tmp_context (line 106) | struct tmp_context
type tmp_context (line 106) | struct tmp_context
function free_context (line 110) | static inline void
function lbank_pack (line 115) | static int
function lbank_altas (line 141) | static int
function lbank_ptr (line 160) | static int
function lsprite_newbank (line 167) | static int
type layer (line 196) | struct layer {
type batch (line 203) | struct batch {
function lbatch_reset (line 212) | static int
function lbatch_release (line 221) | static int
type draw_primitive (line 231) | struct draw_primitive
type batch (line 232) | struct batch
type draw_primitive (line 234) | struct draw_primitive
type draw_primitive (line 253) | struct draw_primitive
type batch (line 254) | struct batch
type draw_primitive (line 256) | struct draw_primitive
type draw_primitive (line 275) | struct draw_primitive
type draw_primitive (line 276) | struct draw_primitive
type draw_primitive (line 285) | struct draw_primitive
type batch (line 286) | struct batch
type draw_primitive (line 292) | struct draw_primitive
type draw_primitive (line 293) | struct draw_primitive
type draw_primitive (line 295) | struct draw_primitive
type draw_primitive (line 301) | struct draw_primitive
function lbatch_add (line 305) | static int
function lbatch_ptr (line 338) | static int
function layer_close (line 352) | static void
type layer (line 366) | struct layer
type batch (line 367) | struct batch
type layer (line 370) | struct layer
type layer (line 370) | struct layer
type layer (line 370) | struct layer
type layer (line 371) | struct layer
type layer (line 376) | struct layer
function layer_merge (line 381) | static void
function lbatch_layer (line 403) | static int
function lbatch_point (line 453) | static int
function lsprite_newbatch (line 474) | static int
function luaopen_spritemgr (line 507) | int
FILE: src/spritemgr.h
type sprite_rect (line 9) | struct sprite_rect {
type sprite_bank (line 16) | struct sprite_bank {
FILE: src/srbuffer.c
function pow2 (line 5) | static inline int
function srbuffer_size (line 14) | size_t
function srbuffer_init (line 25) | void
function srbuffer_add (line 50) | int
type sr_buffer (line 123) | struct sr_buffer
function test (line 142) | static void
function test_rot (line 160) | static void
function test_sr (line 168) | static void
function main (line 176) | int
FILE: src/srbuffer.h
type sr_mat (line 7) | struct sr_mat {
type sr_buffer (line 11) | struct sr_buffer {
type sr_buffer (line 24) | struct sr_buffer
type sr_buffer (line 25) | struct sr_buffer
type sr_buffer (line 26) | struct sr_buffer
FILE: src/tmpbuffer.h
type tmp_buffer (line 7) | struct tmp_buffer {
function tmp_buffer_init (line 15) | static inline void
FILE: src/transform.c
function sprite_transform_init (line 9) | void
function sincos_lut (line 24) | static inline void
function sprite_transform_apply (line 31) | void
function sprite_transform_set (line 66) | void
function sprite_transform_point (line 76) | void
FILE: src/transform.h
type transform (line 6) | struct transform {
type draw_primitive (line 14) | struct draw_primitive
function sprite_transform_identity (line 16) | static inline void
type transform (line 25) | struct transform
type draw_primitive (line 26) | struct draw_primitive
type transform (line 26) | struct transform
type transform (line 27) | struct transform
FILE: src/truetype.c
function lupdate_cstruct (line 23) | static int
function lunload_cstruct (line 55) | static int
function lnamestring (line 72) | static int
function init_cstruct (line 103) | static void
function ltestname (line 110) | static int
function ltestinfo (line 118) | static int
function luaopen_font_truetype (line 127) | int
FILE: src/truetype.h
type truetype_font (line 17) | struct truetype_font {
type truetype_font (line 23) | struct truetype_font
type truetype_font (line 29) | struct truetype_font
type truetype_font (line 29) | struct truetype_font
function lget_fontdata (line 34) | static inline int
function stbtt_fontinfo (line 44) | static inline const stbtt_fontinfo *
function stbtt_fontinfo (line 52) | static inline const stbtt_fontinfo *
function lget_fontid (line 83) | static inline int
function truetype_name (line 94) | static inline int
function lenum_fontname (line 111) | static inline int
function truetype_enum (line 123) | static inline int
function import_font (line 147) | static inline int
function truetype_import (line 160) | static inline void
FILE: src/winfile.c
function FILE (line 7) | FILE *
function FILE (line 22) | FILE *
FILE: src/writelog.c
function write_timestamp (line 11) | static void
function log_write_sokol (line 21) | static int
function log_write_ltask (line 43) | static int
function luaopen_applog (line 76) | int
FILE: src/zipreader.h
type zipreader_name (line 6) | struct zipreader_name {
type zipreader_name (line 14) | struct zipreader_name
FILE: website/packages/astro-theme-soluna/src/client/play.ts
type RuntimeModule (line 3) | interface RuntimeModule {
type PlayAppOptions (line 11) | interface PlayAppOptions {
type StartOptions (line 20) | interface StartOptions {
type PlayOptions (line 29) | interface PlayOptions {
type RuntimeHandle (line 35) | interface RuntimeHandle {
type RuntimeFile (line 39) | interface RuntimeFile {
type Window (line 45) | interface Window {
function qs (line 50) | function qs<T extends Element>(selector: string, root: ParentNode = docu...
function normalizeBaseUrl (line 54) | function normalizeBaseUrl(baseUrl: string): URL {
function normalizeFileData (line 59) | function normalizeFileData(data: Uint8Array | ArrayBuffer | ArrayBufferV...
function ensureAbsolutePath (line 69) | function ensureAbsolutePath(path: string): string {
function dirname (line 76) | function dirname(path: string): string {
function ensureParentDirectory (line 85) | function ensureParentDirectory(runtimeModule: RuntimeModule, path: strin...
function fetchArrayBuffer (line 93) | async function fetchArrayBuffer(url: string): Promise<ArrayBuffer> {
function ensureCrossOriginIsolation (line 101) | async function ensureCrossOriginIsolation(serviceWorkerUrl: string): Pro...
function installRuntimeFiles (line 117) | function installRuntimeFiles(runtimeModule: RuntimeModule, files: StartO...
function resolveQuitApp (line 124) | function resolveQuitApp(instance: RuntimeModule): (() => void) | undefin...
function createRuntimeHandle (line 132) | async function createRuntimeHandle(
function setStatus (line 177) | function setStatus(text: string): void {
function setNote (line 184) | function setNote(text: string): void {
function setOverlayVisible (line 191) | function setOverlayVisible(visible: boolean): void {
function resetConsole (line 198) | function resetConsole(): void {
function appendConsole (line 205) | function appendConsole(text: string, isError: boolean): void {
function createCanvas (line 220) | function createCanvas(): HTMLCanvasElement {
function setupCanvasResize (line 233) | function setupCanvasResize(canvas: HTMLCanvasElement): () => void {
function buildMainGame (line 244) | function buildMainGame(exampleGameSettings = ''): string {
function normalizeRuntimeFilePath (line 262) | function normalizeRuntimeFilePath(path: string): string {
function buildMainZip (line 273) | function buildMainZip(exampleSource: string, exampleGameSettings: string...
function destroyActiveRuntime (line 288) | async function destroyActiveRuntime(): Promise<void> {
function loadAppFactory (line 294) | async function loadAppFactory(basePath: string): Promise<PlayAppOptions[...
function ensureIsolation (line 303) | async function ensureIsolation(basePath: string): Promise<boolean> {
function loadRuntimeAssets (line 327) | async function loadRuntimeAssets(
function startRuntime (line 354) | async function startRuntime(
function initPlay (line 393) | async function initPlay(options: PlayOptions): Promise<void> {
FILE: website/scripts/prepare-runtime.mjs
function resolveMode (line 14) | function resolveMode() {
function resolveRuntimePath (line 18) | function resolveRuntimePath(name, fallback) {
function exists (line 29) | function exists(filePath) {
function ensureFile (line 33) | async function ensureFile(sourcePath, label) {
function createAssetZip (line 39) | async function createAssetZip(outputPath) {
function main (line 45) | async function main() {
FILE: website/src/lib/content.ts
type ExampleRuntimeFile (line 5) | interface ExampleRuntimeFile {
type ExampleEntry (line 10) | interface ExampleEntry {
type DocBlock (line 19) | interface DocBlock {
type DocEntry (line 25) | interface DocEntry {
function trim (line 36) | function trim(value: string): string {
function titleize (line 40) | function titleize(name: string): string {
function exists (line 48) | async function exists(filePath: string): Promise<boolean> {
function normalizeGameSettings (line 52) | function normalizeGameSettings(source: string): string {
function loadGameSettings (line 64) | async function loadGameSettings(id: string): Promise<string> {
function loadRuntimeFiles (line 72) | async function loadRuntimeFiles(root: string, prefix: string): Promise<E...
function loadExamples (line 96) | async function loadExamples(): Promise<ExampleEntry[]> {
function loadDocs (line 121) | async function loadDocs(): Promise<DocEntry[]> {
function parseDocFile (line 142) | function parseDocFile(content: string): DocBlock[] {
function annotationSignature (line 189) | function annotationSignature(annos: string[]): string | null {
FILE: website/src/lib/readme.ts
function normalizeGithubPath (line 7) | function normalizeGithubPath(pathname: string): string {
function resolveReadmeHref (line 17) | function resolveReadmeHref(href: string, basePath: string): string {
function rewriteReadmeLinks (line 48) | function rewriteReadmeLinks(markdown: string, basePath: string): string {
function renderReadme (line 54) | async function renderReadme(basePath: string): Promise<string> {
Condensed preview — 218 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (761K chars).
[
{
"path": ".editorconfig",
"chars": 211,
"preview": "# see https://github.com/CppCXY/EmmyLuaCodeStyle\n[*.lua]\n\nmax_line_length = 120\nend_of_line = lf\nindent_style = tab\ninde"
},
{
"path": ".github/actions/sample/action.yml",
"chars": 2482,
"preview": "name: Build Sample WASM\ndescription: Build sample.wasm side module for Soluna web runtime\n\ninputs:\n soluna_path:\n de"
},
{
"path": ".github/actions/soluna/action.yml",
"chars": 7697,
"preview": "name: Build Soluna\ndescription: Build Soluna for different operating systems\n\ninputs:\n soluna_path:\n description: 'T"
},
{
"path": ".github/workflows/nightly.yml",
"chars": 7959,
"preview": "name: Nightly Build\n\non:\n push:\n branches:\n - master\n pull_request:\n branches:\n - master\n workflow_di"
},
{
"path": ".github/workflows/pages.yml",
"chars": 2300,
"preview": "name: GitHub Pages\n\non:\n workflow_run:\n workflows:\n - Nightly Build\n types:\n - completed\n branches:\n"
},
{
"path": ".gitignore",
"chars": 185,
"preview": "bin\nbuild\ncompile_commands.json\n.cache\nnode_modules\n.pnpm-store\npnpm-debug.log*\nwebsite/node_modules\nwebsite/packages/*/"
},
{
"path": ".gitmodules",
"chars": 802,
"preview": "[submodule \"3rd/ltask\"]\n\tpath = 3rd/ltask\n\turl = https://github.com/cloudwu/ltask.git\n[submodule \"3rd/sokol\"]\n\tpath = 3r"
},
{
"path": "LICENSE",
"chars": 1080,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2025 codingnow.com\n\nPermission is hereby granted, free of charge, to any person obt"
},
{
"path": "Makefile",
"chars": 5246,
"preview": ".PHONY : all clean shader extlua_sample\n\nBUILD=build\nBIN=bin\nAPPNAME=soluna.exe\nCC?=gcc\n# msvc support\n#CC=cl\nLD=$(CC)\nL"
},
{
"path": "README.md",
"chars": 2781,
"preview": "<div align=\"center\">\n\nSokol + Lua = Soluna\n\n</div>\n\n# Soluna\n\n[Live Examples / 在线示例](https://cloudwu.github.io/soluna/)\n"
},
{
"path": "asset/sounds.dl",
"chars": 175,
"preview": "--\nname : bloop\nfilename : asset/sounds/bloop_x.wav\n\n--\nname : bloop_loop\nfilename : asset/sounds/bloop_x.wav\ngroup : mu"
},
{
"path": "asset/sprites.dl",
"chars": 114,
"preview": "--\nname : avatar\nfilename : avatar.png\nx : -0.5\ny : -1\n\n--\nname : avatar2\nfilename : avatar.png\nx : -0.5\ny : -0.5\n"
},
{
"path": "clibs/datalist/make.lua",
"chars": 186,
"preview": "local lm = require \"luamake\"\n\nlm.rootdir = lm.basedir .. \"/3rd/datalist\"\n\nlm:source_set \"datalist_src\" {\n\tsources = {\n\t\t"
},
{
"path": "clibs/ltask/make.lua",
"chars": 239,
"preview": "local lm = require \"luamake\"\n\nlm.rootdir = lm.basedir .. \"/3rd/ltask\"\n\nlm:source_set \"ltask_src\" {\n\tsources = {\n\t\t\"src/*"
},
{
"path": "clibs/lua/make.lua",
"chars": 523,
"preview": "local lm = require \"luamake\"\n\nlm.rootdir = lm.basedir .. \"/3rd/lua\"\n\nif lm.os == \"windows\" then\n\tlm:source_set \"winfile\""
},
{
"path": "clibs/sample/make.lua",
"chars": 1569,
"preview": "local lm = require \"luamake\"\nlocal platform = require \"bee.platform\"\n\nlm.rootdir = lm.basedir\n\nlocal function shdc_plat("
},
{
"path": "clibs/soluna/compile_lua.lua",
"chars": 1243,
"preview": "local lm = require \"luamake\"\nlocal fs = require \"bee.filesystem\"\n\nlocal function compile_lua_code(script, src, name)\n\tlo"
},
{
"path": "clibs/soluna/compile_shader.lua",
"chars": 1524,
"preview": "local lm = require \"luamake\"\nlocal fs = require \"bee.filesystem\"\nlocal platform = require \"bee.platform\"\n\nlocal function"
},
{
"path": "clibs/soluna/make.lua",
"chars": 2009,
"preview": "local lm = require \"luamake\"\nlocal subprocess = require \"bee.subprocess\"\nlocal compile_lua = require \"compile_lua\"\nlocal"
},
{
"path": "clibs/soluna/runlua.lua",
"chars": 359,
"preview": "local subprocess = require \"bee.subprocess\"\nlocal platform = require \"bee.platform\"\n\nlocal bindir, script, src, target ="
},
{
"path": "clibs/soluna/shader2c.lua",
"chars": 293,
"preview": "local subprocess = require \"bee.subprocess\"\nlocal shdcexe, src, target, lang = ...\n\nlocal process = assert(subprocess.sp"
},
{
"path": "clibs/yoga/make.lua",
"chars": 181,
"preview": "local lm = require \"luamake\"\n\nlm.rootdir = lm.basedir .. \"/3rd/yoga\"\n\nlm:source_set \"yoga_src\" {\n\tsources = {\n\t\t\"yoga/*."
},
{
"path": "clibs/zip/make.lua",
"chars": 472,
"preview": "local lm = require \"luamake\"\n\nlm.rootdir = lm.basedir .. \"/3rd/zlib\"\n\nlm:source_set \"minizip\" {\n\tsources = {\n\t\t\"contrib/"
},
{
"path": "docs/app.lua",
"chars": 998,
"preview": "---@meta soluna.app\n\n---输入法候选窗口矩形\n---IME candidate window rectangle.\n---@class soluna.app.ImeRect\n---@field x number 左上角"
},
{
"path": "docs/args.lua",
"chars": 1639,
"preview": "---@meta\n\n---可提交给 batch 的绘制对象\n---Drawable object accepted by `Batch:add`.\n---@alias soluna.Drawable integer|string|userd"
},
{
"path": "docs/callback.lua",
"chars": 2111,
"preview": "---@meta\n\n---游戏入口返回的 callback 表\n---Callback table returned by the game entry script.\n---@class Callback\nlocal callback ="
},
{
"path": "docs/coroutine.lua",
"chars": 877,
"preview": "---@meta soluna.coroutine\n\n---ltask 兼容 coroutine 模块\n---ltask-compatible coroutine module.\n---@class soluna.coroutine\nloc"
},
{
"path": "docs/crypt.lua",
"chars": 459,
"preview": "---@meta soluna.crypt\n\n---密码辅助模块\n---Cryptography helper module.\n---@class soluna.crypt\nlocal crypt = {}\n\n---编码为小写十六进制字符串"
},
{
"path": "docs/datalist.lua",
"chars": 494,
"preview": "---@meta soluna.datalist\n\n---datalist 解析模块\n---Datalist parser module.\n---@class soluna.datalist\nlocal datalist = {}\n\n---"
},
{
"path": "docs/file.lua",
"chars": 2335,
"preview": "---@meta soluna.file\n\n---文件属性表\n---File attribute table.\n---@class soluna.file.Attributes\n---@field mode \"file\"|\"director"
},
{
"path": "docs/font.lua",
"chars": 588,
"preview": "---@meta soluna.font\n\n---字体模块\n---Font module.\n---@class soluna.font\nlocal font = {}\n\n---导入 TrueType 字体数据\n---Imports True"
},
{
"path": "docs/font_system.lua",
"chars": 371,
"preview": "---@meta soluna.font.system\n\n---系统字体模块\n---System font module.\n---@class soluna.font.system\nlocal font_system = {}\n\n---按字"
},
{
"path": "docs/image.lua",
"chars": 1016,
"preview": "---@meta soluna.image\n\n---图片模块\n---Image module.\n---@class soluna.image\nlocal image = {}\n\n---从 PNG 数据加载 RGBA 图片\n---Loads "
},
{
"path": "docs/layout.lua",
"chars": 1968,
"preview": "---@meta soluna.layout\n\n---layout 元素对象\n---Layout element object.\n---@class soluna.layout.Element\nlocal element = {}\n\n---"
},
{
"path": "docs/lfs.lua",
"chars": 1168,
"preview": "---@meta soluna.lfs\n\n---本地文件属性表\n---Local file attribute table.\n---@class soluna.lfs.Attributes\n---@field mode \"file\"|\"di"
},
{
"path": "docs/material_mask.lua",
"chars": 512,
"preview": "---@meta soluna.material.mask\n\n---mask material 模块\n---Mask material module.\n---@class soluna.material.mask\nlocal matmask"
},
{
"path": "docs/material_quad.lua",
"chars": 515,
"preview": "---@meta soluna.material.quad\n\n---quad material 模块\n---Quad material module.\n---@class soluna.material.quad\nlocal matquad"
},
{
"path": "docs/material_text.lua",
"chars": 1258,
"preview": "---@meta soluna.material.text\n\n---文本块创建函数\n---Text block builder function.\n---@alias soluna.material.text.Block fun(text:"
},
{
"path": "docs/soluna.lua",
"chars": 5617,
"preview": "---@meta\n\n---单个 sprite id 或动画帧 id 列表\n---Single sprite id or animation frame id list.\n---@alias Sprite integer|integer[]\n"
},
{
"path": "docs/text.lua",
"chars": 368,
"preview": "---@meta soluna.text\n\n---文本预处理模块\n---Text preprocessing module.\n---@class soluna.text\n---@field convert table<string, str"
},
{
"path": "docs/url.lua",
"chars": 221,
"preview": "---@meta soluna.url\n\n---URL 模块\n---URL module.\n---@class soluna.url\nlocal url = {}\n\n---用系统默认浏览器打开 URL\n---Opens a URL with"
},
{
"path": "docs/zip.lua",
"chars": 367,
"preview": "---@meta soluna.zip\n\n---ZIP 模块\n---ZIP module.\n---@class soluna.zip\nlocal zip = {}\n\n---打开 ZIP 文件\n---Opens a ZIP archive.\n"
},
{
"path": "extlua/extlua.c",
"chars": 25998,
"preview": "// AUTO GENERATED by extlua.temp.c, DONT EDIT\n\n#include <lua.h>\n#include <lauxlib.h>\n#include <stdarg.h>\n#include <asser"
},
{
"path": "extlua/extlua.temp.c",
"chars": 1591,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <stdarg.h>\n#include <assert.h>\n#include <stdio.h>\n\nstruct lua_api {\n\tint "
},
{
"path": "extlua/extlua_impl.c",
"chars": 11952,
"preview": "// AUTO GENERATED by extlua_impl.temp.c, DONT EDIT\n\n#include <lua.h>\n#include <lauxlib.h>\n\nstruct lua_api {\n\tint version"
},
{
"path": "extlua/extlua_impl.temp.c",
"chars": 202,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n\nstruct lua_api {\n\tint version;\n\n$API_DECL$\n};\n\nstruct lua_api *\nextlua_api() {\n\ts"
},
{
"path": "extlua/extlua_sample.c",
"chars": 15182,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <stdint.h>\n#include <stddef.h>\n\n#include \"sokol/sokol_gfx.h\"\n#include \"pe"
},
{
"path": "extlua/gen.lua",
"chars": 3076,
"preview": "-- extlua.h[/.c] generator\n\nlocal luapath = \"../3rd/lua/\"\n\nlocal function parse_params(params)\n\tlocal p = {}\n\tif params "
},
{
"path": "extlua/gen_sokol.lua",
"chars": 2882,
"preview": "-- sokolapi.c generator\n\nlocal header = \"../3rd/sokol/sokol_gfx.h\"\n\nlocal allowlist = {\n\tsg_make_buffer = true,\n\tsg_dest"
},
{
"path": "extlua/gen_soluna.lua",
"chars": 5291,
"preview": "-- solunaapi.c generator\n\nlocal apis = {\n\t{\n\t\tret = \"soluna_material_error\",\n\t\tname = \"soluna_material_submit\",\n\t\tparams"
},
{
"path": "extlua/perspective_quad.glsl",
"chars": 1155,
"preview": "@vs vs\nlayout(binding=0) uniform vs_params {\n\tvec2 framesize;\n\tfloat texsize;\n};\n\nin vec3 pos_h0;\nin vec3 pos_h1;\nin vec"
},
{
"path": "extlua/sokolapi.c",
"chars": 3492,
"preview": "// AUTO GENERATED by sokolapi.temp.c, DONT EDIT\n\n#include <lua.h>\n\n#include \"sokol/sokol_gfx.h\"\n\nstruct sokol_api {\n\tint"
},
{
"path": "extlua/sokolapi.temp.c",
"chars": 411,
"preview": "#include <lua.h>\n\n#include \"sokol/sokol_gfx.h\"\n\nstruct sokol_api {\n\tint version;\n\n$API_DECL$\n};\n\nstatic struct sokol_api"
},
{
"path": "extlua/sokolapi_impl.c",
"chars": 1623,
"preview": "// AUTO GENERATED by sokolapi_impl.temp.c, DONT EDIT\n\n#include \"sokol/sokol_gfx.h\"\n\nstruct sokol_api {\n\tint version;\n\n\ts"
},
{
"path": "extlua/sokolapi_impl.temp.c",
"chars": 208,
"preview": "#include \"sokol/sokol_gfx.h\"\n\nstruct sokol_api {\n\tint version;\n\n$API_DECL$\n};\n\nstruct sokol_api *\nextlua_sokol_api() {\n\t"
},
{
"path": "extlua/solunaapi.c",
"chars": 3013,
"preview": "// AUTO GENERATED by solunaapi.temp.c, DONT EDIT\n\n#include \"solunaapi.h\"\n\n#include <lauxlib.h>\n\nstruct soluna_api {\n\tint"
},
{
"path": "extlua/solunaapi.h",
"chars": 1903,
"preview": "// AUTO GENERATED by solunaapi.h.temp, DONT EDIT\n\n#ifndef SOLUNAAPI_H\n#define SOLUNAAPI_H\n\n#include <stddef.h>\n\n#include"
},
{
"path": "extlua/solunaapi.h.temp",
"chars": 145,
"preview": "#ifndef SOLUNAAPI_H\n#define SOLUNAAPI_H\n\n#include <stddef.h>\n\n#include <lua.h>\n\n#include \"sokol/sokol_gfx.h\"\n\n$TYPE_DECL"
},
{
"path": "extlua/solunaapi.temp.c",
"chars": 700,
"preview": "#include \"solunaapi.h\"\n\n#include <lauxlib.h>\n\nstruct soluna_api {\n\tint version;\n\n$API_DECL$\n};\n\nstatic struct soluna_api"
},
{
"path": "extlua/solunaapi_impl.c",
"chars": 3052,
"preview": "// AUTO GENERATED by solunaapi_impl.temp.c, DONT EDIT\n\n#include <stddef.h>\n\n#include \"sokol/sokol_gfx.h\"\n\n#define SOLUNA"
},
{
"path": "extlua/solunaapi_impl.temp.c",
"chars": 218,
"preview": "$HOST_TYPE_DECL$\n\n$API_EXTERN$\n\nstruct soluna_api {\n\tint version;\n\n$API_DECL$\n};\n\nstruct soluna_api *\nextlua_soluna_api("
},
{
"path": "make.lua",
"chars": 3398,
"preview": "local lm = require \"luamake\"\nlocal fs = require \"bee.filesystem\"\n\nlocal function detect_emcc()\n\tif lm.compiler == \"emcc\""
},
{
"path": "script/act.lua",
"chars": 7604,
"preview": "local platform = require \"bee.platform\"\nlocal fs = require \"bee.filesystem\"\nlocal subprocess = require \"bee.subprocess\"\n"
},
{
"path": "script/act_targets.lua",
"chars": 429,
"preview": "local lm = require \"luamake\"\n\nlm:rule \"act_lua\" {\n args = { \"$luamake\", \"lua\", \"$args\" },\n description = \"$args\",\n"
},
{
"path": "script/compile_commands.lua",
"chars": 482,
"preview": "local subprocess = require \"bee.subprocess\"\n\nlocal ninja_file, output = ...\n\nassert(ninja_file, \"missing ninja file path"
},
{
"path": "script/datalist2c.lua",
"chars": 559,
"preview": "local dlsrc, cname = ...\n\nlocal f = assert(io.open(dlsrc,\"rb\"))\nlocal bin = f:read \"a\"\nf:close()\n\nlocal code = [[\nstatic"
},
{
"path": "script/hashversion.lua",
"chars": 432,
"preview": "local function get_rev()\n\tlocal f = io.popen \"git rev-parse HEAD\"\n\tlocal rev = f:read \"a\"\n\tf:close()\n\treturn rev:match \""
},
{
"path": "script/lua2c.lua",
"chars": 557,
"preview": "local luasrc, cname = ...\n\nlocal s = assert(loadfile(luasrc))\nlocal bin = string.dump(s)\n\nlocal code = [[\nstatic const u"
},
{
"path": "src/appevent.h",
"chars": 3332,
"preview": "#ifndef soluna_app_event_h\n#define soluna_app_event_h\n\nstruct event_message {\n\tconst char *typestr;\n\tint p1;\n\tint p2;\n\ti"
},
{
"path": "src/audio.c",
"chars": 10581,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n\n#include \"zipreader.h\"\n\n#ifdef __EMSCRIPTEN__\n#include <emscripten.h>\n#endif\n\n#de"
},
{
"path": "src/batch.c",
"chars": 1026,
"preview": "#include \"batch.h\"\n#include <stdlib.h>\n#include <assert.h>\n#include <stdatomic.h>\n\n#define DEFAULT_SIZE 1024\n\nstruct dra"
},
{
"path": "src/batch.h",
"chars": 455,
"preview": "#ifndef soluna_batch_h\n#define soluna_batch_h\n\n#include <stdint.h>\n\nstruct draw_primitive {\n\tint32_t x;\t\t// sign bit + 2"
},
{
"path": "src/blit.glsl",
"chars": 424,
"preview": "@vs vs\n\nout vec2 uv;\n\nvoid main() {\n\tvec2 position = vec2(gl_VertexIndex & 1, gl_VertexIndex >> 1);\n\tvec2 screen = posit"
},
{
"path": "src/colorquad.glsl",
"chars": 625,
"preview": "@vs vs\nlayout(binding=0) uniform vs_params {\n\tvec2 framesize;\n};\n\nstruct sr_mat {\n\tmat2 m;\n};\n\nlayout(binding=0) readonl"
},
{
"path": "src/data/settingdefault.dl",
"chars": 277,
"preview": "sprite_max : 0x40000\ntexture_size : 2048\nsrbuffer_size : 0x10000\nbatch_size : 65536\ndraw_instance : 65536\nentry : main.l"
},
{
"path": "src/drawmgr.c",
"chars": 4023,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <stdint.h>\n\n#include \"batch.h\"\n#include \"spritemgr.h\"\n\nstruct draw_elemen"
},
{
"path": "src/embedlua.c",
"chars": 2673,
"preview": "#include \"bootstrap.lua.h\"\n#include \"service.lua.h\"\n#include \"log.lua.h\"\n#include \"timer.lua.h\"\n#include \"root.lua.h\"\n#i"
},
{
"path": "src/entry.c",
"chars": 21182,
"preview": "#define SOKOL_IMPL\n\n#include <lua.h>\n#include <lauxlib.h>\n#include <string.h>\n#include <stdio.h>\n#include <stdlib.h>\n#in"
},
{
"path": "src/extapi.c",
"chars": 8691,
"preview": "#include <assert.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"sokol/sok"
},
{
"path": "src/extapi_types.h",
"chars": 967,
"preview": "// AUTO GENERATED by ../src/extapi_types.temp.h, DONT EDIT\n\n#ifndef SOLUNA_EXTAPI_TYPES_H\n#define SOLUNA_EXTAPI_TYPES_H\n"
},
{
"path": "src/extapi_types.temp.h",
"chars": 86,
"preview": "#ifndef SOLUNA_EXTAPI_TYPES_H\n#define SOLUNA_EXTAPI_TYPES_H\n\n$HOST_TYPE_DECL$\n\n#endif\n"
},
{
"path": "src/external.c",
"chars": 5147,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <stdlib.h>\n#include <string.h>\n\nstruct lua_api;\nstruct sokol_api;\nstruct "
},
{
"path": "src/file.c",
"chars": 1308,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <stdlib.h>\n#include <string.h>\n\nFILE * fopen_utf8(const char *filename, c"
},
{
"path": "src/font.c",
"chars": 5691,
"preview": "#include \"font_manager.h\"\n#include \"truetype.h\"\n\n#include <lua.h>\n#include <lauxlib.h>\n\n#include <string.h>\n#include <st"
},
{
"path": "src/font_define.h",
"chars": 682,
"preview": "#ifndef soluna_font_define_h\n#define soluna_font_define_h\n\n#define FONT_MANAGER_TEXSIZE 2048\n#define FONT_MANAGER_GLYPHS"
},
{
"path": "src/font_manager.c",
"chars": 17026,
"preview": "#include \"font_manager.h\"\n#include \"mutex.h\"\n#include \"truetype.h\"\n\n#include <string.h>\n#include <stdio.h>\n#include <ass"
},
{
"path": "src/font_manager.h",
"chars": 1686,
"preview": "#ifndef font_manager_h\n#define font_manager_h\n\n#include <stb/stb_truetype.h>\n#include <stdint.h>\n#include <stddef.h>\n#in"
},
{
"path": "src/font_system.c",
"chars": 6708,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <stdint.h>\n\n#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MI"
},
{
"path": "src/gamepad.c",
"chars": 12361,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <stdint.h>\n#include <string.h>\n#include \"mutex.h\"\n\n// It's the same with "
},
{
"path": "src/image.c",
"chars": 12636,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n\n#include <stdint.h>\n#include <string.h>\n#include <stdlib.h>\n\nstatic void *\nmalloc"
},
{
"path": "src/ime_char_filter.h",
"chars": 2120,
"preview": "#ifndef SOLUNA_IME_CHAR_FILTER_H\n#define SOLUNA_IME_CHAR_FILTER_H\n\n#include <stdbool.h>\n#include <stdint.h>\n#include <st"
},
{
"path": "src/ime_state.h",
"chars": 313,
"preview": "#ifndef SOLUNA_IME_STATE_H\n#define SOLUNA_IME_STATE_H\n\n#include <stdbool.h>\n#include <stdint.h>\n\nstruct soluna_ime_rect_"
},
{
"path": "src/lcrypt.c",
"chars": 28899,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n\n#include <time.h>\n#include <stdint.h>\n#include <string.h>\n#include <stdlib.h>\n\n#d"
},
{
"path": "src/lfs.c",
"chars": 20335,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <assert.h>\n\n#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MI"
},
{
"path": "src/loginfo.h",
"chars": 219,
"preview": "#ifndef soluna_loginfo_h\n#define soluna_loginfo_h\n\n#include <stdint.h>\n\nstruct log_info {\n\tchar tag[64];\n\tuint32_t log_l"
},
{
"path": "src/lsha1.c",
"chars": 9379,
"preview": "/*\nSHA-1 in C\nBy Steve Reid <sreid@sea-to-sky.net>\n100% Public\tDomain\n\n-----------------\nModified 7/98\nBy James H.\tBrown"
},
{
"path": "src/luabuffer.h",
"chars": 737,
"preview": "#ifndef soluna_luabuffer_h\n#define soluna_luabuffer_h\n\n#include <stdint.h>\n#include <lua.h>\n#include <lauxlib.h>\n\nstatic"
},
{
"path": "src/lualib/coroutine.lua",
"chars": 2544,
"preview": "local co = require \"coroutine\"\n\nglobal assert, setmetatable, error\n\nlocal coroutine_create = co.create\nlocal coroutine_r"
},
{
"path": "src/lualib/fontmgr.lua",
"chars": 5785,
"preview": "local ttf = require \"soluna.font.truetype\"\nlocal string = string\nlocal utf8 = utf8\nlocal table = table\nlocal debug = deb"
},
{
"path": "src/lualib/icon.lua",
"chars": 809,
"preview": "local sdf = require \"soluna.image.sdf\"\nlocal datalist = require \"soluna.datalist\"\nlocal file = require \"soluna.file\"\nloc"
},
{
"path": "src/lualib/initsetting.lua",
"chars": 1855,
"preview": "local datalist = require \"soluna.datalist\"\nlocal source = require \"soluna.embedsource\"\nlocal lfs = require \"soluna.lfs\"\n"
},
{
"path": "src/lualib/layout.lua",
"chars": 3835,
"preview": "local yoga = require \"soluna.layout.yoga\"\nlocal datalist = require \"soluna.datalist\"\nlocal file = require \"soluna.file\"\n"
},
{
"path": "src/lualib/main.lua",
"chars": 5797,
"preview": "local package = package\nlocal table = table\n\nglobal load, require, assert, select, error, tostring, print, type\n\nlocal i"
},
{
"path": "src/lualib/packageloader.lua",
"chars": 4171,
"preview": "local file = require \"soluna.file\"\nlocal zip = require \"soluna.zip\"\nlocal lfs = require \"soluna.lfs\"\n\nlocal package = pa"
},
{
"path": "src/lualib/print_r.lua",
"chars": 3084,
"preview": "local ltask = require \"ltask\"\nlocal log_info = ltask.log.info\nlocal table = table\nlocal math = math\n\nglobal pairs, tostr"
},
{
"path": "src/lualib/soluna.lua",
"chars": 4024,
"preview": "local ltask = require \"ltask\"\nlocal app = require \"soluna.app\"\nlocal mqueue = require \"ltask.mqueue\"\n\nglobal require, er"
},
{
"path": "src/lualib/spritebundle.lua",
"chars": 3001,
"preview": "local image = require \"soluna.image\"\nlocal file = require \"soluna.file\"\nlocal datalist = require \"soluna.datalist\"\n\nglob"
},
{
"path": "src/lualib/text.lua",
"chars": 1370,
"preview": "local font = require \"soluna.font\"\nlocal icon = require \"soluna.icon\"\nglobal setmetatable, print, tonumber\n\nlocal text ="
},
{
"path": "src/lualib/util.lua",
"chars": 337,
"preview": "local table = table\n\nglobal setmetatable\n\nlocal util = {}\n\nlocal func_chain = {}; func_chain.__index = func_chain\n\nfunct"
},
{
"path": "src/luamods.c",
"chars": 3031,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n\nint luaopen_ltask(lua_State *L);\nint luaopen_ltask_root(lua_State *L);\nint luaope"
},
{
"path": "src/luayoga.c",
"chars": 16409,
"preview": "#define LUA_LIB\n\n#include <lua.h>\n#include <lauxlib.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"yoga/Yoga.h\"\n\n#"
},
{
"path": "src/luazip.c",
"chars": 21390,
"preview": "#include \"lua.h\"\n#include \"lauxlib.h\"\n#include \"zipreader.h\"\n#include \"zlib/zlib.h\"\n#include \"zlib/contrib/minizip/zip.h"
},
{
"path": "src/maskquad.glsl",
"chars": 1044,
"preview": "@vs vs\nlayout(binding=0) uniform vs_params {\n\tvec2 framesize;\n\tfloat texsize;\n};\n\nstruct sr_mat {\n\tmat2 m;\n};\n\nlayout(bi"
},
{
"path": "src/material/matdefault.lua",
"chars": 1005,
"preview": "local render = require \"soluna.render\"\nlocal defmat = require \"soluna.material.default\"\n\nlocal ctx = ...\nlocal state = c"
},
{
"path": "src/material/matmask.lua",
"chars": 1046,
"preview": "local render = require \"soluna.render\"\nlocal maskmat = require \"soluna.material.mask\"\n\nlocal ctx = ...\nlocal state = ctx"
},
{
"path": "src/material/matquad.lua",
"chars": 910,
"preview": "local render = require \"soluna.render\"\nlocal quadmat = require \"soluna.material.quad\"\n\nlocal ctx = ...\nlocal state = ctx"
},
{
"path": "src/material/mattext.lua",
"chars": 1345,
"preview": "local render = require \"soluna.render\"\nlocal textmat = require \"soluna.material.text\"\n\nlocal ctx = ...\nlocal state = ctx"
},
{
"path": "src/material_blit.c",
"chars": 1406,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n\n#include \"sokol/sokol_gfx.h\"\n#include \"blit.glsl.h\"\n#include \"render_bindings.h\"\n"
},
{
"path": "src/material_default.c",
"chars": 4443,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <assert.h>\n#include <stdint.h>\n\n#include \"sokol/sokol_gfx.h\"\n#include \"te"
},
{
"path": "src/material_mask.c",
"chars": 5744,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <assert.h>\n#include <stdint.h>\n\n#include \"sokol/sokol_gfx.h\"\n#include \"ma"
},
{
"path": "src/material_quad.c",
"chars": 5324,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <assert.h>\n#include <string.h>\n\n#include \"sokol/sokol_gfx.h\"\n#include \"co"
},
{
"path": "src/material_text.c",
"chars": 17712,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <assert.h>\n#include <string.h>\n#include <stdio.h>\n#include <stdint.h>\n#in"
},
{
"path": "src/material_util.c",
"chars": 1951,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n\n#include \"material_util.h\"\n\nvoid\nutil_ref_object(lua_State *L, void *ptr, int uv_"
},
{
"path": "src/material_util.h",
"chars": 623,
"preview": "#ifndef soluna_material_util_h\n#define soluna_material_util_h\n\n#include <lua.h>\n#include \"sokol/sokol_gfx.h\"\n#include \"b"
},
{
"path": "src/mutex.h",
"chars": 526,
"preview": "#ifndef __fontmutex_h_\n#define __fontmutex_h_\n\n#if defined(_WIN32)\n #include <windows.h>\n #define mutex_t SRWLOCK\n"
},
{
"path": "src/openlibs.c",
"chars": 327,
"preview": "#define linit_c\n#define LUA_LIB\n\n#include <stddef.h>\n#include \"lua.h\"\n#include \"lualib.h\"\n#include \"lauxlib.h\"\n\nvoid sol"
},
{
"path": "src/openurl.c",
"chars": 2111,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n\n#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)\n\n#include <"
},
{
"path": "src/platform/linux/soluna_linux_ime.c",
"chars": 9139,
"preview": "#include <X11/Xlib.h>\n#include <X11/Xutil.h>\n#include <X11/Xatom.h>\n#include <wchar.h>\n#include <uchar.h>\n#include <dlfc"
},
{
"path": "src/platform/linux/soluna_linux_ime.h",
"chars": 443,
"preview": "#ifndef SOLUNA_LINUX_IME_H\n#define SOLUNA_LINUX_IME_H\n\n#include <stdbool.h>\n\nbool soluna_linux_ensure_im(void);\nvoid sol"
},
{
"path": "src/platform/macos/soluna_macos_ime.h",
"chars": 346,
"preview": "#ifndef SOLUNA_MACOS_IME_H\n#define SOLUNA_MACOS_IME_H\n\n#include <stdbool.h>\n\nvoid soluna_macos_install_ime(void);\nvoid s"
},
{
"path": "src/platform/macos/soluna_macos_ime.m",
"chars": 17113,
"preview": "#import <Cocoa/Cocoa.h>\n#import <objc/runtime.h>\n\n#include <stdint.h>\n\n#include \"ime_state.h\"\n#include \"soluna_macos_ime"
},
{
"path": "src/platform/wasm/soluna_ime.js",
"chars": 19927,
"preview": "mergeInto(LibraryManager.library, {\n soluna_wasm_setup_ime__deps: ['$withStackSave', '$lengthBytesUTF8', '$stringToUTF8"
},
{
"path": "src/platform/wasm/soluna_openurl.js",
"chars": 531,
"preview": "mergeInto(LibraryManager.library, {\n soluna_wasm_open_url__deps: ['$UTF8ToString'],\n soluna_wasm_open_url__sig: 'vi',\n"
},
{
"path": "src/platform/wasm/soluna_wasm_ime.h",
"chars": 6476,
"preview": "#ifndef SOLUNA_WASM_IME_H\n#define SOLUNA_WASM_IME_H\n\n#if defined(__EMSCRIPTEN__)\n\n#include <emscripten/emscripten.h>\n#in"
},
{
"path": "src/platform/windows/soluna_windows_ime.c",
"chars": 5143,
"preview": "#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#include <imm.h>\n#include <windowsx.h>\n#include <winnls.h>\n\n\n#include <"
},
{
"path": "src/platform/windows/soluna_windows_ime.h",
"chars": 287,
"preview": "#ifndef SOLUNA_WINDOWS_IME_H\n#define SOLUNA_WINDOWS_IME_H\n\nvoid soluna_win32_install_wndproc(void);\nvoid soluna_win32_ap"
},
{
"path": "src/render.c",
"chars": 16874,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <string.h>\n#include <stdint.h>\n\n#include \"sokol/sokol_gfx.h\"\n#include \"so"
},
{
"path": "src/render_bindings.c",
"chars": 6331,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <string.h>\n\n#include \"render_bindings.h\"\n\nstatic inline sg_bindings *\nget"
},
{
"path": "src/render_bindings.h",
"chars": 251,
"preview": "#ifndef soluna_render_bindings_h\n#define soluna_render_bindings_h\n\n#include \"sokol/sokol_gfx.h\"\n\nstruct render_bindings "
},
{
"path": "src/render_uniform.c",
"chars": 5617,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <string.h>\n\n#include \"sokol/sokol_gfx.h\"\n\n#define UNIFORM_TYPE_FLOAT 1\n#d"
},
{
"path": "src/sdfimage.c",
"chars": 5970,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <math.h>\n#include <string.h>\n\n#include \"font_define.h\"\n\n// implement from"
},
{
"path": "src/sdftext.glsl",
"chars": 1367,
"preview": "@vs vs\nlayout(binding=0) uniform vs_params {\n\tvec2 framesize;\n\tfloat texsize;\n};\n\nstruct sr_mat {\n\tmat2 m;\n};\n\nlayout(bi"
},
{
"path": "src/service/audio.lua",
"chars": 5920,
"preview": "local ltask = require \"ltask\"\nlocal audio = require \"soluna.audio\"\nlocal file = require \"soluna.file\"\nlocal datalist = r"
},
{
"path": "src/service/gamepad.lua",
"chars": 364,
"preview": "local ltask = require \"ltask\"\nlocal device = require \"soluna.gamepad.device\"\n\nglobal pairs\n\nlocal S = {}\n\nlocal listener"
},
{
"path": "src/service/loader.lua",
"chars": 2501,
"preview": "local image = require \"soluna.image\"\nlocal spritemgr = require \"soluna.spritemgr\"\nlocal spritebundle = require \"soluna.s"
},
{
"path": "src/service/log.lua",
"chars": 594,
"preview": "local ltask = require \"ltask\"\nlocal writelog = require \"soluna.log\"\nlocal io = io\n\nglobal none\n\nlocal S = {}\n\nlocal soko"
},
{
"path": "src/service/render.lua",
"chars": 7425,
"preview": "local ltask = require \"ltask\"\nlocal render = require \"soluna.render\"\nlocal image = require \"soluna.image\"\nlocal embedsou"
},
{
"path": "src/service/settings.lua",
"chars": 232,
"preview": "local initsetting = require \"soluna.initsetting\"\n\nglobal assert\n\nlocal S = {}\n\nlocal setting\n\nfunction S.init(args)\n\tass"
},
{
"path": "src/service/start.lua",
"chars": 3947,
"preview": "local ltask = require \"ltask\"\nlocal file = require \"soluna.file\"\nlocal spritemgr = require \"soluna.spritemgr\"\nlocal solu"
},
{
"path": "src/sprite_submit.h",
"chars": 2113,
"preview": "#ifndef soluna_sprite_submit_h\n#define soluna_sprite_submit_h\n\n#include \"batch.h\"\n#include <stdint.h>\n#include <assert.h"
},
{
"path": "src/spritemgr.c",
"chars": 12133,
"preview": "#include \"spritemgr.h\"\n#include \"sprite_submit.h\"\n#include \"batch.h\"\n#include \"transform.h\"\n\n#include <stdint.h>\n#includ"
},
{
"path": "src/spritemgr.h",
"chars": 393,
"preview": "#ifndef soluna_spritemgr_h\n#define soluna_spritemgr_h\n\n#include <stdint.h>\n#include <assert.h>\n\n#define INVALID_TEXTUREI"
},
{
"path": "src/srbuffer.c",
"chars": 3908,
"preview": "#include \"srbuffer.h\"\n#include <math.h>\n#include <stdlib.h>\n\nstatic inline int\npow2(int n) {\n\tint m = 1 << 5;\n\twhile (m "
},
{
"path": "src/srbuffer.h",
"chars": 491,
"preview": "#ifndef soluna_srbuffer_h\n#define soluna_srbuffer_h\n\n#include <stdint.h>\n#include <stdlib.h>\n\nstruct sr_mat {\n\tfloat v[4"
},
{
"path": "src/texquad.glsl",
"chars": 903,
"preview": "@vs vs\nlayout(binding=0) uniform vs_params {\n\tvec2 framesize;\n\tfloat texsize;\n};\n\nstruct sr_mat {\n\tmat2 m;\n};\n\nlayout(bi"
},
{
"path": "src/tmpbuffer.h",
"chars": 706,
"preview": "#ifndef soluna_tmp_buffer_h\n#define soluna_tmp_buffer_h\n\n#include <lua.h>\n#include <lauxlib.h>\n\nstruct tmp_buffer {\n\tvoi"
},
{
"path": "src/transform.c",
"chars": 2047,
"preview": "#include <math.h>\n#include \"batch.h\"\n#include \"transform.h\"\n#include \"sprite_submit.h\"\n\n// sin(0 ~ 2 * pi) * 2^24\nstatic"
},
{
"path": "src/transform.h",
"chars": 653,
"preview": "#ifndef soluna_transform_h\n#define soluna_transform_h\n\n#include <stdint.h>\n\nstruct transform {\n\t// ix, iy : sign bit + 2"
},
{
"path": "src/truetype.c",
"chars": 4393,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <string.h>\n\n#include \"font_define.h\"\n#include \"truetype.h\"\n\nstatic const "
},
{
"path": "src/truetype.h",
"chars": 3880,
"preview": "#ifndef ant_truetype_h\n#define ant_truetype_h\n\n#include <lua.h>\n#include <lauxlib.h>\n#include <stdint.h>\n#include <strin"
},
{
"path": "src/version.h",
"chars": 157,
"preview": "#ifndef soluna_version_h\n#define soluna_version_h\n\n#define SOLUNA_API_VERSION 3\n#ifndef SOLUNA_HASH_VERSION\n#define SOLU"
},
{
"path": "src/winfile.c",
"chars": 603,
"preview": "#include <stdio.h>\n\n#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)\n\n#include <windows.h>\n\nFILE *\n"
},
{
"path": "src/writelog.c",
"chars": 1763,
"preview": "#include <lua.h>\n#include <lauxlib.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <time.h>\n#incl"
},
{
"path": "src/yogaone.cpp",
"chars": 694,
"preview": "#include \"yoga/YGConfig.cpp\"\n#include \"yoga/YGEnums.cpp\"\n#include \"yoga/YGNode.cpp\"\n#include \"yoga/YGNodeLayout.cpp\"\n#in"
},
{
"path": "src/zipreader.h",
"chars": 541,
"preview": "#ifndef soluna_zip_reader_h\n#define soluna_zip_reader_h\n\n#include <stdint.h>\n\nstruct zipreader_name {\n\tconst char * zipf"
},
{
"path": "test/audio.game",
"chars": 23,
"preview": "entry : test/audio.lua\n"
},
{
"path": "test/audio.lua",
"chars": 8076,
"preview": "local soluna = require \"soluna\"\nlocal matquad = require \"soluna.material.quad\"\nlocal mattext = require \"soluna.material."
},
{
"path": "test/bundle.lua",
"chars": 377,
"preview": "local sb = require \"soluna.spritebundle\"\n\nlocal filecache = setmetatable({ __missing = {} }, { __index = sb.loadimage })"
},
{
"path": "test/extlua/material/perspective_quad.lua",
"chars": 870,
"preview": "local render = require \"soluna.render\"\nlocal pqmat = require \"ext.material.perspective_quad\"\n\nlocal ctx = ...\nlocal stat"
},
{
"path": "test/extlua.game",
"chars": 150,
"preview": "entry : extlua.lua\nextlua_entry : extlua_init\nextlua_preload : sample\nextlua_material : perspective_quad\nextlua_material"
},
{
"path": "test/extlua.lua",
"chars": 2719,
"preview": "-- bin/soluna.exe test/extlua.game\n\nlocal soluna = require \"soluna\"\nlocal foobar = require \"ext.foobar\"\nlocal matpq = re"
},
{
"path": "test/file.lua",
"chars": 249,
"preview": "local file = require \"soluna.file\"\nlocal image = require \"soluna.image\"\nlocal lfs = require \"soluna.lfs\"\n\nprint_r(image."
},
{
"path": "test/hello.game",
"chars": 34,
"preview": "entry : hello.lua\na.b : 1\na.c : 2\n"
},
{
"path": "test/hello.lua",
"chars": 19,
"preview": "print \"Hello World\""
},
{
"path": "test/icon.lua",
"chars": 306,
"preview": "local image = require \"soluna.image\"\nlocal file = require \"soluna.file\"\nlocal soluna = require \"soluna\"\n\nlocal c = file."
},
{
"path": "test/image.lua",
"chars": 364,
"preview": "local image = require \"soluna.image\"\nlocal file = require \"soluna.file\"\n\nlocal c = file.load \"asset/avatar.png\"\nprint(im"
},
{
"path": "test/ime.lua",
"chars": 9511,
"preview": "-- To run this sample:\n-- bin/soluna.exe entry=test/ime.lua\n\nlocal soluna = require \"soluna\"\nlocal app = require \"soluna"
},
{
"path": "test/intersect.lua",
"chars": 766,
"preview": "local soluna = require \"soluna\"\nlocal quad = require \"soluna.material.quad\"\n\nlocal args = ...\nlocal batch = args.batch\n\n"
},
{
"path": "test/layout.lua",
"chars": 935,
"preview": "local layout = require \"soluna.layout\"\nlocal datalist = require \"soluna.datalist\"\nlocal matquad = require \"soluna.materi"
},
{
"path": "test/mask.lua",
"chars": 478,
"preview": "-- To run this sample :\n-- bin/soluna.exe entry=test/sprite.lua\nlocal soluna = require \"soluna\"\nlocal ltask = require \"l"
},
{
"path": "test/mtex.game",
"chars": 70,
"preview": "# a small texture size for testing\ntexture_size : 64\nentry : mtex.lua\n"
},
{
"path": "test/mtex.lua",
"chars": 972,
"preview": "-- To run this sample :\n-- bin/soluna.exe test/mtex.game\nlocal soluna = require \"soluna\"\nlocal ltask = require \"ltask\"\n\n"
},
{
"path": "test/setting.lua",
"chars": 60,
"preview": "local soluna = require \"soluna\"\n\nprint_r(soluna.settings())\n"
},
{
"path": "test/sprite.lua",
"chars": 939,
"preview": "-- To run this sample :\n-- bin/soluna.exe entry=test/sprite.lua\nlocal soluna = require \"soluna\"\nlocal ltask = require \"l"
},
{
"path": "test/spritepack.lua",
"chars": 387,
"preview": "local spritemgr = require \"soluna.spritemgr\"\n\n-- texture size = 128\nlocal bank = spritemgr.newbank(65536, 128)\n\nbank:add"
},
{
"path": "test/test.lua",
"chars": 24,
"preview": "print_r {\"Hello World\"}\n"
},
{
"path": "test/text.lua",
"chars": 2229,
"preview": "local soluna = require \"soluna\"\nlocal ltask = require \"ltask\"\nlocal mattext = require \"soluna.material.text\"\nlocal matqu"
},
{
"path": "test/version.lua",
"chars": 54,
"preview": "local soluna = require \"soluna\"\nprint (soluna.version)"
},
{
"path": "test/window.game",
"chars": 19,
"preview": "entry : window.lua\n"
},
{
"path": "test/window.lua",
"chars": 247,
"preview": "-- To run this sample :\n-- bin/soluna.exe entry=test/window.lua\n-- bin/soluna.exe test/window.game\nlocal soluna = requir"
},
{
"path": "website/README.md",
"chars": 738,
"preview": "# Website\n\n[中文](./README.zh-CN.md)\n\nThis directory contains the Astro-based website for Soluna Live Examples.\n\nIt is res"
},
{
"path": "website/README.zh-CN.md",
"chars": 448,
"preview": "# Website\n\n[English](./README.md)\n\n这个目录包含 Soluna 在线示例网站的 Astro 源码。\n\n它负责:\n\n- 渲染网站页面\n- 从 `../docs/` 生成 API 文档页面\n- 从 `../te"
},
{
"path": "website/astro.config.mjs",
"chars": 349,
"preview": "import process from 'node:process'\nimport { defineConfig } from 'astro/config'\n\nconst site = process.env.SITE_URL || 'ht"
},
{
"path": "website/eslint.config.mjs",
"chars": 226,
"preview": "import antfu from '@antfu/eslint-config'\n\nexport default antfu(\n {\n astro: true,\n typescript: true,\n stylistic"
},
{
"path": "website/package.json",
"chars": 789,
"preview": "{\n \"name\": \"website\",\n \"type\": \"module\",\n \"private\": true,\n \"packageManager\": \"pnpm@10.28.2\",\n \"scripts\": {\n \"pr"
},
{
"path": "website/packages/astro-theme-soluna/package.json",
"chars": 989,
"preview": "{\n \"name\": \"astro-theme-soluna\",\n \"type\": \"module\",\n \"version\": \"0.1.0\",\n \"exports\": {\n \"./layouts/BaseLayout.ast"
},
{
"path": "website/packages/astro-theme-soluna/src/client/play.ts",
"chars": 12614,
"preview": "import { strToU8, zipSync } from 'fflate'\n\ninterface RuntimeModule {\n FS: {\n writeFile: (path: string, data: Uint8Ar"
},
{
"path": "website/packages/astro-theme-soluna/src/components/Footer.astro",
"chars": 86,
"preview": "<footer class=\"footer\">\n <div>Soluna Web Lab / Live Engine Reference</div>\n</footer>\n"
},
{
"path": "website/packages/astro-theme-soluna/src/components/Hero.astro",
"chars": 290,
"preview": "---\ninterface Props {\n eyebrow: string\n title: string\n subtitle: string\n}\n\nconst { eyebrow, title, subtitle } = Astro"
},
{
"path": "website/packages/astro-theme-soluna/src/components/Menubar.astro",
"chars": 40,
"preview": "<div class=\"menubar\">\n <slot />\n</div>\n"
}
]
// ... and 18 more files (download for full content)
About this extraction
This page contains the full source code of the cloudwu/soluna GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 218 files (673.5 KB), approximately 221.0k tokens, and a symbol index with 1184 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.