Documentation & Travis & Refactoring
This commit is contained in:
parent
ec707ea776
commit
988b9e1f11
27 changed files with 772 additions and 123 deletions
159
docs/docbuild.nim
Normal file
159
docs/docbuild.nim
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
# Copyright 2017 Xored Software, Inc.
|
||||
|
||||
import threadpool, os, osproc, strutils, sequtils, pegs
|
||||
|
||||
import "../godot/godotapigen.nim"
|
||||
|
||||
const dirs = ["godot"/"core", "godot"/"internal", "godot"/"nim"]
|
||||
const files = ["godot"/"godotapigen.nim", "godot"/"godotinternal.nim",
|
||||
"godot"/"godot.nim"]
|
||||
const indexFile = "docs"/"index.rst"
|
||||
const gitHubUrl = "https://github.com/pragmagic/godot-nim"
|
||||
|
||||
proc outName(outDir, file: string): string =
|
||||
outDir / file.extractFilename().changeFileExt("html")
|
||||
|
||||
template quoted(s: string): string =
|
||||
('"' & s & '"')
|
||||
|
||||
proc execOrFail(cmd: string) =
|
||||
echo "[exec] " & cmd
|
||||
let ret = execShellCmd(cmd)
|
||||
if ret != 0:
|
||||
raise newException(
|
||||
Exception, "Command quit with exit code " & $ret & ": " & cmd)
|
||||
|
||||
template withDir(dir: string, body: typed) =
|
||||
let curDir = getCurrentDir()
|
||||
setCurrentDir(dir)
|
||||
try:
|
||||
body
|
||||
finally:
|
||||
setCurrentDir(curDir)
|
||||
|
||||
iterator walkDirRec(dir: string, filter: set[PathComponent],
|
||||
extensions: openarray[string]): string =
|
||||
for file in walkDirRec(dir, filter):
|
||||
if not extensions.anyIt(file.endsWith(it)): continue
|
||||
yield file
|
||||
|
||||
proc genApiFiles(targetDir, godotBin: string) =
|
||||
let jsonFile = targetDir / "api.json"
|
||||
try:
|
||||
execOrFail(quoted(godotBin) &
|
||||
" --gdnative-generate-json-api " & quoted(jsonFile))
|
||||
except:
|
||||
# this fails unstably even if api.json is created successfully
|
||||
discard
|
||||
if not fileExists(jsonFile):
|
||||
raise newException(Exception, "Failed to generate Godot API wrappers")
|
||||
|
||||
genApi(targetDir, jsonFile)
|
||||
|
||||
writeFile(targetDir / "nim.cfg", "path=\"$projectdir/../../godot\"")
|
||||
|
||||
proc extractVersion(nimbleFile: string): string =
|
||||
let contents = readFile(nimbleFile)
|
||||
var matches: array[1, string]
|
||||
doAssert match(contents, peg"""'version' \s* '=' \s* '"' {@} '"' """, matches)
|
||||
result = matches[0]
|
||||
|
||||
proc fixupHrefs(file: string) =
|
||||
var contents = readFile(file)
|
||||
contents = contents.replacef(
|
||||
peg"""'href="' ('internal'/'core'/'nim') '/' {@} '"' """,
|
||||
"href=\"$#\"")
|
||||
if file.contains("godotapi"):
|
||||
contents = contents.replacef(
|
||||
peg"""'href="' {('godotinternal' / 'godot') '.html"'} """,
|
||||
"href=\"../$#")
|
||||
writeFile(file, contents)
|
||||
|
||||
proc getGitHash(): string =
|
||||
result = execProcess("git rev-parse HEAD")
|
||||
if not result.isNil and result.len > 0:
|
||||
result = result.replace("\L", "").replace("\r", "")
|
||||
|
||||
proc buildDocs*(outDir, godotNimDir, godotBin: string) =
|
||||
removeDir(outDir)
|
||||
createDir(outDir)
|
||||
let outDirAbs = expandFilename(outDir)
|
||||
let godotBinAbs = expandFilename(godotBin)
|
||||
|
||||
setCurrentDir(godotNimDir)
|
||||
|
||||
let godotNimVersion = extractVersion("godot.nimble")
|
||||
putEnv("godotnimversion", godotNimVersion)
|
||||
putEnv("godotnimgithub", gitHubUrl)
|
||||
let gitCommit = getGitHash()
|
||||
|
||||
var allNimFiles = newSeq[string]()
|
||||
allNimFiles.add(files)
|
||||
for dir in dirs:
|
||||
for file in walkDirRec(dir, {pcFile, pcDir}, [".nim"]):
|
||||
allNimFiles.add(file)
|
||||
for file in allNimFiles:
|
||||
spawn execOrFail(
|
||||
"nim doc -o:" & quoted(outName(outDirAbs, file)) &
|
||||
" --git.url:" & quoted(gitHubUrl) &
|
||||
" --git.commit:" & quoted(gitCommit) &
|
||||
' ' & quoted(file))
|
||||
|
||||
let godotApiFolder = outDirAbs / "godotapi"
|
||||
createDir(godotApiFolder)
|
||||
genApiFiles(godotApiFolder, godotBinAbs)
|
||||
for file in walkDirRec(godotApiFolder, {pcFile, pcDir}, [".nim"]):
|
||||
spawn execOrFail("nim doc " & quoted(file))
|
||||
|
||||
sync()
|
||||
|
||||
var gitHash: string
|
||||
withDir(godotBinAbs.parentDir()):
|
||||
gitHash = getGitHash()
|
||||
if gitHash.isNil or gitHash.len == 0:
|
||||
raise newException(Exception,
|
||||
"Godot executable is not under Git repository")
|
||||
|
||||
var indexContent = readFile(indexFile)
|
||||
var apiList = newStringOfCap(4096)
|
||||
for file in walkDirRec(godotApiFolder, {pcFile, pcDir}):
|
||||
if not file.endsWith(".html"):
|
||||
removeFile(file)
|
||||
else:
|
||||
let moduleHtml = file.extractFileName()
|
||||
let moduleName = moduleHtml.changeFileExt("")
|
||||
apiList.add("* `" & moduleName & " <godotapi/" & moduleHtml & ">`_\L")
|
||||
indexContent = indexContent.replace("$GODOTAPI_CHANGESET_HASH", gitHash).
|
||||
replace("$AUTO_GENERATED_GODOTAPI_LIST", apiList).
|
||||
replace("$GODOTNIM_GITHUB_URL", gitHubUrl)
|
||||
|
||||
let tmpRst = outDirAbs/"index.rst"
|
||||
writeFile(tmpRst, indexContent)
|
||||
try:
|
||||
execOrFail("nim rst2html -o:" & quoted(outName(outDirAbs, tmpRst)) &
|
||||
' ' & quoted(tmpRst))
|
||||
finally:
|
||||
removeFile(tmpRst)
|
||||
|
||||
for file in walkDirRec(outDir, {pcFile, pcDir}, [".html"]):
|
||||
spawn fixupHrefs(file)
|
||||
|
||||
sync()
|
||||
|
||||
when isMainModule:
|
||||
const outDir = "docgen"
|
||||
|
||||
if not fileExists("godot.nimble"):
|
||||
echo "Must be executed from godot-nim root dir"
|
||||
quit(-1)
|
||||
|
||||
let godotBin = getEnv("GODOT_BIN")
|
||||
if godotBin.len == 0:
|
||||
echo "GODOT_BIN environment variable must point to Godot executable"
|
||||
quit(-1)
|
||||
|
||||
try:
|
||||
buildDocs(outDir, getCurrentDir(), godotBin)
|
||||
except:
|
||||
echo getCurrentExceptionMsg()
|
||||
quit(-1)
|
||||
94
docs/docpublish.nim
Normal file
94
docs/docpublish.nim
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
# Copyright 2017 Xored Software, Inc.
|
||||
|
||||
import os, pegs, strutils
|
||||
import docbuild
|
||||
|
||||
const indexTemplate = """<html>
|
||||
<head><title>godot-nim docs index</title></head>
|
||||
<body>
|
||||
<h1>Documentation of Nim bindings for Godot Engine (<a href="https://github.com/$REPO_SLUG">GitHub</a>)</h1><br/>
|
||||
$VERSION_LIST
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
proc execOrQuit(cmd: string) =
|
||||
let ret = execShellCmd(cmd)
|
||||
if ret != 0:
|
||||
quit(ret)
|
||||
|
||||
proc walkDirRecRelative(dir: string, cb: proc (file: string), start = "") =
|
||||
for kind, path in walkDir(dir, relative = true):
|
||||
if kind in {pcFile, pcLinkToFile}:
|
||||
cb(if start.len > 0: start / path else: path)
|
||||
elif kind in {pcDir, pcLinkToDir}:
|
||||
let fullPath = if start.len > 0: start / path else: path
|
||||
walkDirRecRelative(dir / fullPath, cb, fullPath)
|
||||
|
||||
proc publish(docDir, gitHubToken, repoSlug, branch, tag, changeset: string) =
|
||||
let release = if branch == "master": branch else: tag
|
||||
let commitComment = if release == "master":
|
||||
"Update master documentation for changeset " & changeset
|
||||
else:
|
||||
"Update documentation for " & tag
|
||||
|
||||
const repoDir = "gh-pages"
|
||||
execOrQuit(
|
||||
"git clone --depth=1 --branch=gh-pages https://github.com/$#.git $#" %
|
||||
[repoSlug, repoDir])
|
||||
try:
|
||||
removeDir(repoDir/release)
|
||||
createDir(repoDir/release)
|
||||
var versionList = newStringOfCap(4096)
|
||||
for kind, path in walkDir(repoDir, relative = true):
|
||||
if kind == pcDir and not path.startsWith("."):
|
||||
versionList.add("<a href='$1/index.html'>$1</a><br/>" % path)
|
||||
let index = indexTemplate.replace("$REPO_SLUG", repoSlug).
|
||||
replace("$VERSION_LIST", versionList)
|
||||
writeFile(repoDir/"index.html", index)
|
||||
|
||||
walkDirRecRelative(docDir) do (file: string):
|
||||
createDir(parentDir(repoDir/release/file))
|
||||
copyFile(docDir/file, repoDir/release/file)
|
||||
|
||||
setCurrentDir(repoDir)
|
||||
try:
|
||||
execOrQuit("git add --all")
|
||||
execOrQuit("git commit -m \"$#\"" % commitComment)
|
||||
execOrQuit("git push -fq \"https://$#@github.com/$#.git\" gh-pages" %
|
||||
[gitHubToken, repoSlug])
|
||||
finally:
|
||||
setCurrentDir("..")
|
||||
finally:
|
||||
removeDir(repoDir)
|
||||
|
||||
when isMainModule:
|
||||
proc getEnvOrQuit(key: string): string =
|
||||
result = getEnv(key)
|
||||
if result.len == 0:
|
||||
echo "Expected environment variable: " & key
|
||||
quit(1)
|
||||
|
||||
if getEnv("TRAVIS_PULL_REQUEST").len > 0:
|
||||
quit(0)
|
||||
|
||||
let repoSlug = getEnvOrQuit("TRAVIS_REPO_SLUG")
|
||||
let branch = getEnvOrQuit("TRAVIS_BRANCH")
|
||||
let changeset = getEnvOrQuit("TRAVIS_COMMIT")
|
||||
let tag = getEnv("TRAVIS_TAG")
|
||||
|
||||
# let repoSlug = "pragmagic/godot-nim"
|
||||
# let branch = "master"
|
||||
# let changeset = "0fd0101432c1fed1004f50b035fcf74f75f004a8"
|
||||
# let tag = ""
|
||||
|
||||
let gitHubToken = getEnvOrQuit("GITHUB_TOKEN")
|
||||
|
||||
if branch != "master" and not (tag =~ peg"^ 'v' \d+ '.' \d+ '.' \d+ $"):
|
||||
quit(0)
|
||||
|
||||
let godotBin = getEnvOrQuit("GODOT_BIN")
|
||||
|
||||
const docDir = "docgen"
|
||||
buildDocs(docDir, getCurrentDir(), godotBin)
|
||||
publish(docDir, gitHubToken, repoSlug, branch, tag, changeset)
|
||||
12
docs/godotapi.rst
Normal file
12
docs/godotapi.rst
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
===============
|
||||
Godot API (Nim)
|
||||
===============
|
||||
|
||||
:Godot Git Hash: |godothash|
|
||||
|
||||
.. contents::
|
||||
|
||||
This is an auto-generated index of Godot API. It's built from Git changeset
|
||||
$GODOTAPI_CHANGESET_HASH.
|
||||
|
||||
$AUTO_GENERATED_GODOTAPI_LIST
|
||||
198
docs/index.rst
Normal file
198
docs/index.rst
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
=============================
|
||||
Nim bindings for Godot Engine
|
||||
=============================
|
||||
|
||||
:Author: Ruslan Mustakov
|
||||
:Version: |godotnimversion|
|
||||
:GitHub: `$GODOTNIM_GITHUB_URL <$GODOTNIM_GITHUB_URL>`_
|
||||
|
||||
.. contents::
|
||||
|
||||
``godot-nim`` library allows to create games on
|
||||
`Godot Engine <https://godotengine.org/>`_ with
|
||||
`Nim programming language <https://nim-lang.org/>`_. Nim is a statically typed
|
||||
language with an elegant Python-like syntax that compiles to native code.
|
||||
It is garbage-collected, but its GC supports real-time mode which this library
|
||||
makes use of. It means the GC will never run during game frames and will use
|
||||
fixed amount of frame idle time to collect garbage. This leads to no stalls
|
||||
and close to zero compromise on performance comparing to native languages with
|
||||
manual memory management.
|
||||
|
||||
If you are not familiar with Nim yet, it is recommended to go through the
|
||||
`official tutorial <https://nim-lang.org/docs/tut1.html>`_.
|
||||
|
||||
`VSCode <https://code.visualstudio.com/>`_ is the recommended editor for
|
||||
working with Nim code. It is cross-platform and has the excellent
|
||||
`nim plugin <https://marketplace.visualstudio.com/items?itemName=kosz78.nim>`_
|
||||
that supports most of the features you would expect from an IDE.
|
||||
It also has `godot-tools plugin <https://marketplace.visualstudio.com/items?itemName=geequlim.godot-tools>`_
|
||||
which adds features for editing GDScript and Godot resource files.
|
||||
|
||||
|
||||
Getting Started
|
||||
===============
|
||||
|
||||
Building Godot
|
||||
--------------
|
||||
|
||||
The library requires a not yet released Godot version 3.0, which you can
|
||||
build yourself by running the commands below (requires
|
||||
`Git <https://git-scm.com/downloads>`_,
|
||||
`Python 2.7 <https://www.python.org/downloads/>`_,
|
||||
`SCons <http://www.scons.org/>`_):
|
||||
|
||||
.. code-block:: bash
|
||||
git clone https://github.com/godotengine/godot.git
|
||||
cd godot
|
||||
scons platform=<your_platform>
|
||||
|
||||
where ``<your_platform>`` can be ``windows``, ``osx``, ``x11``. After build
|
||||
is finished, Godot binaries will be under the ``bin`` folder. More details
|
||||
about compiling Godot can be found in `Godot documentation
|
||||
<https://godot.readthedocs.io/en/stable/development/compiling/index.html>`_.
|
||||
|
||||
|
||||
Building Nim
|
||||
-------------
|
||||
|
||||
The library requires a not yet released Nim version 0.17.1, which you can
|
||||
build yourself by following instructions in the
|
||||
`Nim repository <https://github.com/nim-lang/Nim>`_. Make sure to also run
|
||||
``./koch tools -d:release`` after the steps described there to build ``nimble``
|
||||
(package manager) and ``nimsuggest`` (IDE helper tool,
|
||||
used by VSCode Nim plugin)
|
||||
|
||||
|
||||
Creating Project
|
||||
----------------
|
||||
|
||||
The fastest way to set up a Godot-Nim project is to use an existing stub:
|
||||
|
||||
.. code-block:: bash
|
||||
git clone --depth=1 https://github.com/pragmagic/godot-nim-stub.git myproject
|
||||
|
||||
(you can then delete the .git directory within to untie the project from the
|
||||
stub repository)
|
||||
|
||||
The stub contains the necessary build configuration to compile your code for
|
||||
desktop and mobile platforms, as well as a couple of very simple scenes to
|
||||
help you get started. Consult the stub's `README
|
||||
<https://github.com/pragmagic/godot-nim-stub>`_ for information about
|
||||
compiling the project.
|
||||
|
||||
|
||||
Adding Nim to Existing Project
|
||||
------------------------------
|
||||
|
||||
If you would like to use Nim in an existing project:
|
||||
|
||||
1. Copy ``nakefile.nim`` file and ``src`` directory from the stub described
|
||||
in the previous section above your Godot project folder. Adjust paths in
|
||||
build scripts (``nakefile.nim``, ``src/stub.nimble``) according to your
|
||||
own project structure.
|
||||
|
||||
2. Copy ``project/nimlib.tres`` to your Godot project folder. It is a
|
||||
GDNative library resource that contains paths to dynamic libraries
|
||||
compiled by Nim.
|
||||
|
||||
3. Add ``NimRuntime`` as an `AutoLoad singleton <https://godot.readthedocs.io/en/stable/learning/step_by_step/singletons_autoload.html>`_
|
||||
to your project. To do this, copy ``project/scripts/NimRuntime.gdns`` into
|
||||
your project and add these lines to ``project.godot``, adjusting path to
|
||||
``NimRuntime.gdns`` as necessary:
|
||||
.. code-block:: cfg
|
||||
[autoload]
|
||||
NimRuntime="*res://scripts/NimRuntime.gdns"
|
||||
|
||||
|
||||
Next Steps
|
||||
----------
|
||||
|
||||
Once you are familiarized with the build process (it's as simple as running
|
||||
``nake build`` after you are set up), it is recommended to go through
|
||||
`godotmacros <godotmacros.html>`_ and `godotnim <godotnim.html>`_ module
|
||||
documentations. They describe special macros and procedures needed to define
|
||||
or instantiate Godot objects. After you learned that, the rest is similar to
|
||||
using any Nim library. These bindings do not limit any of Nim's capabilities,
|
||||
and you can use any Nim types as fields or parameters of Godot objects and
|
||||
their procedures (but, obviously, you may not be able to export some of them
|
||||
to Godot editor or GDScript, unless you define your own converters).
|
||||
|
||||
|
||||
Modules
|
||||
=======
|
||||
|
||||
The binding library consists of three major modules:
|
||||
|
||||
* `godot <#modules-godot-module>`_ - Contains core types and macro definitions.
|
||||
You need to import this in any module that defines or makes use of Godot
|
||||
types.
|
||||
|
||||
* `godotinternal <#modules-godotinternal-module>`_ - Contains raw wrappers over
|
||||
few core types, such as ``GodotVariant``, ``GodotString``, ``GodotNodePath``,
|
||||
``GodotDictionary``, pool arrays. These are used by ``godotapigen`` and macro
|
||||
implementations, and you don't have to use them at all in your code, unless
|
||||
you want to go into low-level details for some reason. Each of those types
|
||||
needs to be destructed manually with ``deinit`` procedure.
|
||||
|
||||
* `godotapigen <godotapigen.html>`_ - Wrapper generator based on data from
|
||||
Godot's ``ClassDB``. You only need to use it as a part of the build process.
|
||||
|
||||
|
||||
godot Module
|
||||
------------
|
||||
|
||||
Contains core types and macro definitions. You need to import this in any
|
||||
module that defines or makes use of Godot types. The sumbodules below are
|
||||
exported and you don't have to import any of them directly.
|
||||
|
||||
* `godotnim <godotnim.html>`_ Defines ``NimGodotObject`` and Varaint converters
|
||||
for standard Nim types.
|
||||
* `godotmacros <godotmacros.html>`_ Defines ``gdobj`` macro for defining
|
||||
Godot objects.
|
||||
* `variants <variants.html>`_ ``Variant`` type represents a "dynamic object"
|
||||
that many Godot procedures make use of.
|
||||
* `arrays <arrays.html>`_ Defines ``Array`` of Variants.
|
||||
* `basis <basis.html>`_ Defines 3D ``Basis``.
|
||||
* `colors <colors.html>`_ Defines ARGB ``Color``.
|
||||
* `dictionaries <dictionaries.html>`_ Defines ``Variant`` -> ``Variant``
|
||||
``Dictionary``.
|
||||
* `nodepaths <nodepaths.html>`_ Defines ``NodePath`` - a path to a ``Node``.
|
||||
* `planes <planes.html>`_ Defines 3D ``Plane``.
|
||||
* `poolarrays <poolarrays.html>`_ Defines pooled arrays: ``PoolByteArray``,
|
||||
``PoolIntArray``, ``PoolRealArray``, ``PoolVector2Array``,
|
||||
``PoolVector3Array``, ``PoolColorArray``, ``PoolStringArray``.
|
||||
* `quats <quats.html>`_ Defines ``Quat`` (quaternion) describing object
|
||||
rotation in 3D space.
|
||||
* `rect2 <rect2.html>`_ Defines ``Rect2`` - a 2D rectangle.
|
||||
* `rect3 <rect3.html>`_ Defines ``Rect3`` - a 3D box.
|
||||
* `rids <rids.html>`_ Defines ``RID`` - a resource identifier.
|
||||
* `transform2d <transform2d.html>`_ Defines ``Transform2D``.
|
||||
* `transforms <transforms.html>`_ Defines ``Transform``.
|
||||
* `vector2 <vector2.html>`_ Defines ``Vector2``.
|
||||
* `vector3 <vector3.html>`_ Defines ``Vector3``.
|
||||
* `godotbase <godotbase.html>`_ Defines ``Error`` type and few common math
|
||||
procedures missing in Nim's standard library.
|
||||
|
||||
|
||||
Godot API
|
||||
---------
|
||||
|
||||
This is an auto-generated list of Godot API modules. It's built from Godot
|
||||
changeset `$GODOTAPI_CHANGESET_HASH
|
||||
<https://github.com/godotengine/godot/commit/$GODOTAPI_CHANGESET_HASH>`_.
|
||||
|
||||
$AUTO_GENERATED_GODOTAPI_LIST
|
||||
|
||||
|
||||
godotinternal Module
|
||||
--------------------
|
||||
|
||||
Contains low-level wrappers over Godot types that require manual memory
|
||||
management. This module is used within ``godot-nim`` implementation and you
|
||||
don't need to import it unless you know what you are doing.
|
||||
|
||||
* `godotdictionaries <godotdictionaries.html>`_
|
||||
* `godotnodepaths <godotnodepaths.html>`_
|
||||
* `godotpoolarrays <godotpoolarrays.html>`_
|
||||
* `godotstrings <godotstrings.html>`_
|
||||
* `godotvariants <godotvariants.html>`_
|
||||
1
docs/nim.cfg
Normal file
1
docs/nim.cfg
Normal file
|
|
@ -0,0 +1 @@
|
|||
--threads:on
|
||||
Loading…
Add table
Add a link
Reference in a new issue