Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial

  • Loading branch information...
commit 0efaf9ac238375f7f90c5e7a73c43d33fc24ed88 0 parents
Stephen Moore authored
Showing with 25,132 additions and 0 deletions.
  1. +15 −0 .gitignore
  2. +105 −0 docs/Makefile
  3. +212 −0 docs/_ext/gmadocs.py
  4. +38 −0 docs/_ext/jsapi.py
  5. +13 −0 docs/_templates/classes/gma/constants.rst
  6. +33 −0 docs/_templates/modules/gma/class.rst
  7. +11 −0 docs/_templates/modules/gma/module.rst
  8. +42 −0 docs/_theme/nature/layout.html
  9. +18 −0 docs/_theme/nature/searchbox.html
  10. 0  docs/_theme/nature/start.html
  11. +330 −0 docs/_theme/nature/static/nature.css_t
  12. +526 −0 docs/_theme/nature/static/searchtools.js
  13. +4 −0 docs/_theme/nature/theme.conf
  14. +178 −0 docs/advanced/architecture.txt
  15. +184 −0 docs/advanced/collisionFunctions.txt
  16. +18 −0 docs/advanced/index.txt
  17. +41 −0 docs/advanced/install.txt
  18. +153 −0 docs/advanced/levelParser.txt
  19. +37 −0 docs/advanced/templates.txt
  20. +117 −0 docs/api/docs/gma.txt
  21. +181 −0 docs/api/docs/gma/backgroundMaker.txt
  22. +306 −0 docs/api/docs/gma/baseTemplate.txt
  23. +207 −0 docs/api/docs/gma/character.txt
  24. +73 −0 docs/api/docs/gma/colladaTemplate.txt
  25. +80 −0 docs/api/docs/gma/collectable.txt
  26. +224 −0 docs/api/docs/gma/collisions.txt
  27. +235 −0 docs/api/docs/gma/constants.txt
  28. +63 −0 docs/api/docs/gma/deathPlatform.txt
  29. +124 −0 docs/api/docs/gma/door.txt
  30. +311 −0 docs/api/docs/gma/enemy.txt
  31. +73 −0 docs/api/docs/gma/glgeIDTemplate.txt
  32. +248 −0 docs/api/docs/gma/gma.txt
  33. +276 −0 docs/api/docs/gma/hud.txt
  34. +71 −0 docs/api/docs/gma/jumpingEnemy.txt
  35. +168 −0 docs/api/docs/gma/keyHandler.txt
  36. +1,140 −0 docs/api/docs/gma/levelParser.txt
  37. +770 −0 docs/api/docs/gma/manager.txt
  38. +75 −0 docs/api/docs/gma/meshTemplate.txt
  39. +319 −0 docs/api/docs/gma/moveable.txt
  40. +71 −0 docs/api/docs/gma/patrolEnemy.txt
  41. +93 −0 docs/api/docs/gma/platform.txt
  42. +71 −0 docs/api/docs/gma/platformEnemy.txt
  43. +234 −0 docs/api/docs/gma/renderHelper.txt
  44. +534 −0 docs/api/docs/gma/sceneHelper.txt
  45. +63 −0 docs/api/docs/gma/scoreCollectable.txt
  46. +613 −0 docs/api/docs/gma/shapes.rectangle.txt
  47. +74 −0 docs/api/docs/gma/shapes.txt
  48. +65 −0 docs/api/docs/gma/utils.txt
  49. +275 −0 docs/conf.py
  50. +71 −0 docs/glossary.txt
  51. +73 −0 docs/index.txt
  52. +9 −0 docs/intro/index.txt
  53. +69 −0 docs/intro/install.txt
  54. +22 −0 docs/intro/tutorials.txt
  55. +11 −0 docs/sphinx-build.py
  56. +171 −0 docs/topics/appearance.txt
  57. +79 −0 docs/topics/character.txt
  58. +163 −0 docs/topics/enemy.txt
  59. +241 −0 docs/topics/hud.txt
  60. +36 −0 docs/topics/index.txt
  61. +129 −0 docs/topics/keyHandling.txt
  62. +406 −0 docs/topics/levels.txt
  63. +50 −0 docs/topics/messages.txt
  64. +60 −0 docs/topics/moveables.txt
  65. +77 −0 docs/topics/platform.txt
  66. +88 −0 docs/topics/shapes.txt
  67. +82 −0 docs/topics/tags.txt
  68. +33 −0 docs/tutorials/camera.txt
  69. +79 −0 docs/tutorials/character.txt
  70. +164 −0 docs/tutorials/collada.txt
  71. +173 −0 docs/tutorials/enemies.txt
  72. +218 −0 docs/tutorials/extraLevels.txt
  73. +71 −0 docs/tutorials/gettingStarted.txt
  74. +238 −0 docs/tutorials/hud.txt
  75. +37 −0 docs/tutorials/lights.txt
  76. +106 −0 docs/tutorials/moving.txt
  77. +64 −0 docs/tutorials/platforms.txt
  78. +167 −0 docs/tutorials/polish.txt
  79. +141 −0 docs/tutorials/textures.txt
  80. +21 −0 examples/fancy/_levels/common.js
  81. +32 −0 examples/fancy/_levels/level.template.js
  82. +72 −0 examples/fancy/_levels/level1.js
  83. +79 −0 examples/fancy/_levels/level2.js
  84. +44 −0 examples/fancy/_levels/level3.js
  85. +62 −0 examples/fancy/_levels/level4.js
  86. +59 −0 examples/fancy/_levels/level5.js
  87. +57 −0 examples/fancy/_levels/level6.js
  88. +60 −0 examples/fancy/_levels/level7.js
  89. +62 −0 examples/fancy/_levels/templates.js
  90. +53 −0 examples/fancy/_levels/types.js
  91. +221 −0 examples/fancy/enemy.js
  92. +83 −0 examples/fancy/hud.css
  93. +7 −0 examples/fancy/view.html
  94. BIN  examples/feedbackSession/0/bricks.jpg
  95. BIN  examples/feedbackSession/0/dirt.jpg
  96. +25 −0 examples/feedbackSession/0/game.html
  97. +128 −0 examples/feedbackSession/0/game.js
  98. +192 −0 examples/feedbackSession/0/gamma.css
  99. BIN  examples/feedbackSession/1/bricks.jpg
  100. +25 −0 examples/feedbackSession/1/game.html
  101. +135 −0 examples/feedbackSession/1/game.js
  102. +192 −0 examples/feedbackSession/1/gamma.css
  103. +192 −0 examples/feedbackSession/1/gorilla.dae
  104. BIN  examples/feedbackSession/1/skin.jpg
  105. BIN  examples/feedbackSession/best/bricks.jpg
  106. BIN  examples/feedbackSession/best/cloud.jpg
  107. BIN  examples/feedbackSession/best/dirt.jpg
  108. +25 −0 examples/feedbackSession/best/game.html
  109. +157 −0 examples/feedbackSession/best/game.js
  110. +192 −0 examples/feedbackSession/best/gamma.css
  111. +192 −0 examples/feedbackSession/best/gorilla.dae
  112. BIN  examples/feedbackSession/best/jungle.png
  113. BIN  examples/feedbackSession/best/side-rock.jpg
  114. BIN  examples/feedbackSession/best/skin.jpg
  115. BIN  examples/glge/cloud.jpg
  116. BIN  examples/glge/earth-specular.gif
  117. BIN  examples/glge/earth.jpg
  118. +80 −0 examples/glge/example.js
  119. BIN  examples/glge/moon.jpg
  120. BIN  examples/glge/smiley.jpg
  121. +67 −0 examples/glge/view.html
  122. BIN  examples/glge/waternormal.jpg
  123. +277 −0 examples/hud/example.js
  124. +75 −0 examples/hud/hud.css
  125. BIN  examples/hud/star.png
  126. +25 −0 examples/noNav/demo.css
  127. +65 −0 examples/noNav/demo.js
  128. +6 −0 examples/noNav/view.html
  129. +79 −0 examples/simple/hud.css
  130. +55 −0 examples/simple/infinite-jump.js
  131. +53 −0 examples/simple/simple.js
  132. +49 −0 examples/simple/steps.js
  133. +79 −0 examples/tests/hud.css
  134. +82 −0 examples/tests/textures.js
  135. +238 −0 examples/tests/toggle.js
  136. BIN  examples/tutorial/bricks.jpg
  137. +57 −0 examples/tutorial/camera.js
  138. +83 −0 examples/tutorial/collada.js
  139. +55 −0 examples/tutorial/enemy.js
  140. +192 −0 examples/tutorial/gorilla/gorilla.txt
  141. +114 −0 examples/tutorial/hud.js
  142. +64 −0 examples/tutorial/lights.js
  143. +33 −0 examples/tutorial/moving.js
  144. +107 −0 examples/tutorial/mulitpleLevel.js
  145. +119 −0 examples/tutorial/polish.js
  146. BIN  examples/tutorial/skin.jpg
  147. +73 −0 examples/tutorial/texture.js
  148. +95 −0 gma/base.js
  149. +90 −0 gma/constants.js
  150. +257 −0 gma/convenience.js
  151. +7 −0 gma/entities/base.js
  152. +108 −0 gma/entities/character.js
  153. +56 −0 gma/entities/collectable.js
  154. +51 −0 gma/entities/door.js
  155. +254 −0 gma/entities/enemy.js
  156. +228 −0 gma/entities/moveable.js
  157. +60 −0 gma/entities/platform.js
  158. +505 −0 gma/entities/shapes.js
  159. +191 −0 gma/entities/spec/character_spec.js
  160. +66 −0 gma/entities/spec/collectable_spec.js
  161. +52 −0 gma/entities/spec/door_spec.js
  162. +448 −0 gma/entities/spec/enemy_spec.js
  163. +25 −0 gma/entities/spec/moveable_spec.js
  164. +237 −0 gma/entities/spec/moveable_spec_helpers.js
  165. +50 −0 gma/entities/spec/platform_spec.js
  166. +279 −0 gma/entities/spec/shapes_spec.js
  167. +11 −0 gma/entities/tests/test1.xml
  168. +5 −0 gma/entities/tests/test2.xml
  169. +101 −0 gma/events.js
  170. +614 −0 gma/manager.js
  171. BIN  gma/spec/collision_specs/Adjoining.png
  172. BIN  gma/spec/collision_specs/HitCornerDiagonally.png
  173. BIN  gma/spec/collision_specs/MoveAndStop.png
  174. BIN  gma/spec/collision_specs/MultipleInCorner.png
  175. BIN  gma/spec/collision_specs/SkimDiagonally.png
  176. BIN  gma/spec/collision_specs/SlidePast.png
  177. BIN  gma/spec/collision_specs/SlidingDiagonally.png
  178. BIN  gma/spec/collision_specs/SmallerDiagonally.png
  179. BIN  gma/spec/collision_specs/WeirdDiaganolly.png
  180. +23 −0 gma/spec/collision_specs/adjoining.js
  181. +17 −0 gma/spec/collision_specs/hitCornerDiagonally.js
  182. +17 −0 gma/spec/collision_specs/moveAndStop.js
  183. +14 −0 gma/spec/collision_specs/multipleInCorner.js
  184. +27 −0 gma/spec/collision_specs/skimDiagonally.js
  185. +40 −0 gma/spec/collision_specs/slidePast.js
  186. +25 −0 gma/spec/collision_specs/slidingDiagonally.js
  187. +17 −0 gma/spec/collision_specs/smallerDiagonally.js
  188. +17 −0 gma/spec/collision_specs/weirdDiagonally.js
  189. +64 −0 gma/spec/collisions_spec.js
  190. +113 −0 gma/spec/collisions_spec_helper.js
  191. +76 −0 gma/spec/constants_spec.js
  192. +81 −0 gma/spec/events_spec.js
  193. +903 −0 gma/spec/manager_spec.js
  194. +72 −0 gma/spec/spec.helper.js
  195. +129 −0 gma/support/base64.js
  196. +247 −0 gma/support/canvas2image.js
  197. +107 −0 gma/utils/background.js
  198. +9 −0 gma/utils/base.js
  199. +391 −0 gma/utils/collisions.js
  200. +256 −0 gma/utils/hud.js
  201. +42 −0 gma/utils/image.js
  202. +766 −0 gma/utils/parser.js
  203. +729 −0 gma/utils/render.js
  204. +226 −0 gma/utils/spec/background_spec.js
Sorry, we could not display the entire diff because too many files (325) changed.
15 .gitignore
@@ -0,0 +1,15 @@
+*.pyc
+*~
+.DS_Store
+*.graffle
+docs/_build/*
+built/*
+app-build.js
+support/web/info
+support/web/results
+support/info
+support/messages.log
+support/APIgen/src/docs/*
+support/APIgen/src/temp/*
+support/built/*
+
105 docs/Makefile
@@ -0,0 +1,105 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = python sphinx-build.py
+PAPER =
+BUILDDIR = _build
+TEMPDIR = _temp
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp epub latex latexpdf text changes linkcheck doctest
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/* $(TEMPDIR)/*
+
+html:
+ $(SPHINXBUILD) -b gmahtml $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ make -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
212 docs/_ext/gmadocs.py
@@ -0,0 +1,212 @@
+from sphinx.writers.html import SmartyPantsHTMLTranslator
+from sphinx.builders.html import StandaloneHTMLBuilder
+from sphinx.domains.std import StandardDomain
+from sphinx.roles import XRefRole
+
+from docutils import nodes, transforms
+import os
+
+class BaseRole(XRefRole):
+ isFunction = False
+
+ def process_link(self, env, refnode, has_explicit_title, title, target):
+ if not has_explicit_title:
+ title = title.lstrip('.')
+ title = title[1:]
+ dot = title.rfind('.')
+ if dot != -1:
+ title = title[dot+1:]
+
+ #I dislike this for references
+ #if self.isFunction:
+ # title = '%s()' % title
+
+ parts = target.split('.')
+ if len(parts) > 2:
+ last = parts[-1]
+ kls = '.'.join(parts[:-1])
+ classes = env.jsapi['modules'][parts[0]]['classes']
+ if kls in classes:
+ kls = classes[kls]
+ else:
+ kls = '.'.join(parts[:-2])
+ last = '.'.join(parts[-2:])
+ if kls not in classes:
+ raise Exception, "Trying and failing to find kls '%s' from '%s'" % (kls, '.'.join(parts))
+ kls = classes[kls]
+
+ typ = 'property'
+ if self.isFunction:
+ typ = 'method'
+ inherited = kls.findInherited(typ, last)
+ if inherited:
+ target = '%s.%s.%s' % (parts[0], inherited, last)
+
+ return title, target
+
+class MethodRole(BaseRole):
+ isFunction = True
+
+class PropertyRole(BaseRole): pass
+
+def moreContext(app, pagename, templatename, context, doctree):
+ def p(url):
+ parts = pagename.split('/')[:-1]
+ if len(parts) == 0:
+ return url[1:]
+ return os.path.relpath(url, '/%s' % '/'.join(parts))
+
+ context['toplinks'] = [
+ ('Overview', p('/index.html'), pagename=='index')
+ , ('Tutorial', p('/intro/tutorials.html'),
+ pagename.startswith("intro/tutorials")
+ or pagename.startswith("tutorials"))
+ , ('Topics', p('/topics/index.html'),
+ pagename.startswith("topics/")
+ or pagename.startswith("advanced/"))
+ , ('API', p('/api/docs/gma.html'), pagename.startswith("api/docs/gma"))
+ , ('Download', p('/intro/install.html'), pagename == 'intro/install')
+ ]
+
+def setup(app):
+ app.add_crossref_type(
+ directivename = "entity",
+ rolename = "entity",
+ indextemplate = "pair: %s; entity",
+ )
+
+ app.add_crossref_type(
+ directivename = "rhelper",
+ rolename = "rhelper",
+ indextemplate = "pair: %s; Render Helper",
+ )
+
+ app.add_crossref_type(
+ directivename = "api",
+ rolename = "api",
+ indextemplate = "single: %s",
+ )
+
+ app.add_crossref_type(
+ directivename = "constant",
+ rolename = "constant",
+ indextemplate = "pair: %s; constant",
+ )
+
+ app.add_crossref_type(
+ directivename = "metho",
+ rolename = "metho",
+ )
+
+ app.add_crossref_type(
+ directivename = "prop",
+ rolename = "prop",
+ )
+
+ StandardDomain.roles["metho"] = MethodRole()
+ StandardDomain.roles["prop"] = PropertyRole()
+
+
+ app.add_builder(GMA_HTML_Builder)
+ app.add_transform(SuppressBlockquotes)
+
+ app.connect("html-page-context", moreContext)
+
+
+class SuppressBlockquotes(transforms.Transform):
+ """
+ Remove the default blockquotes that encase indented list, tables, etc.
+ """
+ default_priority = 300
+
+ suppress_blockquote_child_nodes = (
+ nodes.bullet_list,
+ nodes.enumerated_list,
+ nodes.definition_list,
+ nodes.literal_block,
+ nodes.doctest_block,
+ nodes.line_block,
+ nodes.table
+ )
+
+ def apply(self):
+ for node in self.document.traverse(nodes.block_quote):
+ if len(node.children) == 1 and isinstance(node.children[0], self.suppress_blockquote_child_nodes):
+ node.replace_self(node.children[0])
+
+class GmaHTMLTranslator(SmartyPantsHTMLTranslator):
+ """
+ Django-specific reST to HTML tweaks.
+ """
+
+ # Don't use border=1, which docutils does by default.
+ def visit_table(self, node):
+ self.body.append(self.starttag(node, 'table', CLASS='docutils'))
+
+ # <big>? Really?
+ def visit_desc_parameterlist(self, node):
+ self.body.append('(')
+ self.first_param = 1
+
+ def depart_desc_parameterlist(self, node):
+ self.body.append(')')
+
+ #
+ # Don't apply smartypants to literal blocks
+ #
+ def visit_literal_block(self, node):
+ self.no_smarty += 1
+ SmartyPantsHTMLTranslator.visit_literal_block(self, node)
+
+ def depart_literal_block(self, node):
+ SmartyPantsHTMLTranslator.depart_literal_block(self, node)
+ self.no_smarty -= 1
+
+ # Give each section a unique ID -- nice for custom CSS hooks
+ def visit_section(self, node):
+ old_ids = node.get('ids', [])
+ node['ids'] = ['s-' + i for i in old_ids]
+ node['ids'].extend(old_ids)
+ SmartyPantsHTMLTranslator.visit_section(self, node)
+ node['ids'] = old_ids
+
+class GMA_HTML_Builder(StandaloneHTMLBuilder):
+
+ name = 'gmahtml'
+
+ def write_genindex(self):
+ # the total count of lines for each index letter, used to distribute
+ # the entries into two columns
+ genindex = self.env.create_index(self)
+
+ for key, entries in genindex:
+ for index, (name, (links, subitems)) in enumerate(entries):
+ if len(subitems) == 1 and not links:
+ entries[index] = ('%s (%s)' % (name, subitems[0][0]), [subitems[0][1], []])
+
+ indexcounts = []
+ for _, entries in genindex:
+ indexcounts.append(sum(1 + len(subitems)
+ for _, (_, subitems) in entries))
+
+ genindexcontext = dict(
+ genindexentries = genindex,
+ genindexcounts = indexcounts,
+ split_index = self.config.html_split_index,
+ )
+ self.info(' genindex', nonl=1)
+ #import pdb
+ #pdb.set_trace()
+ if self.config.html_split_index:
+ self.handle_page('genindex', genindexcontext,
+ 'genindex-split.html')
+ self.handle_page('genindex-all', genindexcontext,
+ 'genindex.html')
+
+ for (key, entries), count in zip(genindex, indexcounts):
+ ctx = {'key': key, 'entries': entries, 'count': count,
+ 'genindexentries': genindex}
+ self.handle_page('genindex-' + key, ctx,
+ 'genindex-single.html')
+ else:
+ self.handle_page('genindex', genindexcontext, 'genindex.html')
38 docs/_ext/jsapi.py
@@ -0,0 +1,38 @@
+from APIgen.main import main as genApi
+
+import subprocess
+import os
+
+def runBash(cmd):
+ """Runs a bash command and returns the output"""
+ process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
+ out = process.stdout.read().strip()
+ return out
+
+def createAPI(app):
+ buildir = app.env.srcdir
+ outdir = os.path.join(buildir, os.sep.join(["_temp", "jsapi", "docs"]))
+ resultdir = os.path.join(buildir, "api")
+ tempdir = os.path.join(buildir, os.sep.join(["_temp", "jsapi", "temp"]))
+ templatedirs = [os.path.join(buildir, "_templates")]
+
+ for path in (outdir, resultdir, tempdir) + tuple(templatedirs):
+ if not os.path.exists(path):
+ os.makedirs(path)
+
+ information = genApi(os.environ['GMA_SRC']), outDir=outdir, tempDir=tempdir, templateDirs=templatedirs)
+
+ app.jsapi = information
+ rsync = "rsync %s %s -r --delete -c" % (outdir, resultdir)
+ print runBash(rsync)
+
+def removeInfo(app, doctree):
+ app.env.jsapi = None
+
+def addInfo(app, env, docname):
+ app.env.jsapi = app.jsapi
+
+def setup(app):
+ app.connect('builder-inited', createAPI)
+ app.connect('doctree-read', removeInfo)
+ app.connect("env-purge-doc", addInfo)
13 docs/_templates/classes/gma/constants.rst
@@ -0,0 +1,13 @@
+{% extends "modules/gma/class.rst" %}
+
+{% block ref %}
+{{block.super}}
+
+.. api:: gma.constant
+{% endblock %}
+
+{% block propertyRef %}
+{{block.super}}
+
+.. constant:: {{property.getName}}
+{% endblock %}
33 docs/_templates/modules/gma/class.rst
@@ -0,0 +1,33 @@
+{% extends 'class.rst' %}
+{% load gma %}
+
+{% block ref %}
+.. api:: {{fullname}}
+
+{% if fullname != current.name %}
+.. api:: {{current.name}}
+{% endif %}
+{% endblock %}
+
+
+{% block afterInfo %}
+{% if current.hasTags %}
+{% underline "-" %}Tags{% endunderline %}
+
+{% block tags %}
+{{current.tagString}}
+{% endblock %}
+{% endif %}
+{% endblock %}
+
+{% block propertyRef %}
+{{ block.super }}
+
+.. prop:: {{module.name}}.{{current.name}}.{{property.getName}}
+{% endblock %}
+
+{% block methodRef %}
+{{ block.super }}
+
+.. metho:: {{module.name}}.{{current.name}}.{{method.name}}
+{% endblock %}
11 docs/_templates/modules/gma/module.rst
@@ -0,0 +1,11 @@
+{% extends "module.rst" %}
+{% load edit %}
+{% load gma %}
+
+{% block top %}
+.. _gmaApi:
+{% endblock %}
+
+{% block links %}
+{{module.links|safe}}
+{% endblock %}
42 docs/_theme/nature/layout.html
@@ -0,0 +1,42 @@
+{% extends "basic/layout.html" %}
+{%- block header %}
+ <div id="header">
+ <div class="inner">
+ <p id="site_title">
+ <a href="/">GammaJS: A WebGL platformer game engine</a>
+ </p>
+ <ul class="menu">
+ {%- for name, link, selected in toplinks %}
+ <li><a href="{{link}}" {%- if selected %}class="selected"{% endif %}>{{name}}</a></li>
+ {% endfor %}
+ <li>
+ {%- include "searchbox.html" %}
+ </li>
+ </ul>
+ </div>
+ </div>
+{% endblock %}
+{%- block document %}
+ <div class="documentwrapper">
+ {%- if display_toc %}
+ <div class="bodywrapper">
+ {%- endif %}
+ <div class="body">
+ {% block body %} {% endblock %}
+ </div>
+ {%- if display_toc %}
+ </div>
+ {%- endif %}
+ <div class="sphinxsidebar">
+ {%- if display_toc %}
+ <h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
+ {{ toc }}
+ {%- endif %}
+ </div>
+ </div>
+{%- endblock %}
+
+{%- block relbar1 %}{% endblock %}
+{%- block relbar2 %}{% endblock %}
+{%- block relbaritems %}{% endblock %}
+
18 docs/_theme/nature/searchbox.html
@@ -0,0 +1,18 @@
+{#
+ basic/searchbox.html
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx sidebar template: quick search box.
+
+ :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- if pagename != "search" %}
+ <form class="search" id="searchbox" action="{{ pathto('search') }}" method="get">
+ <input type="text" name="q" size="18" />
+ <input type="submit" value="{{ _('Search') }}" />
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+ </form>
+ <script type="text/javascript">$('#searchbox').show(0);</script>
+{%- endif %}
0  docs/_theme/nature/start.html
No changes.
330 docs/_theme/nature/static/nature.css_t
@@ -0,0 +1,330 @@
+/*
+ * nature.css_t
+ * ~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- nature theme.
+ *
+ * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+@import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+html {
+ font-family: Arial, sans-serif;
+ font-size: 76%;
+ height: 100%;
+ width: 100%;
+}
+body {
+ margin: 0;
+ padding: 0;
+ color: #111;
+ background-color: #fff;
+ height: 100%;
+ width: 100%;
+}
+div.header {
+ width: 100%;
+ color: #111;
+ background-color: #fff;
+}
+.inner, .footer {
+ width: 960px;
+ margin: 0 auto;
+ position: relative;
+}
+div.header .inner {
+ height: auto !important;
+ height: 180px;
+ min-height: 180px;
+}
+p#site_title {
+ color: #111;
+ font-size: 2.7em;
+ line-height: 1em;
+ margin: 0;
+ padding: 1em 0;
+}
+p#site_title a {
+ color: #111;
+ font-weight: bold;
+ text-decoration: none;
+}
+ul.menu {
+ display: inline;
+ height: 25px;
+ font-size: 1.6em;
+ color: #fff;
+ background-color: #6BA81E;
+ margin: 0;
+ padding: 5px 10px;
+}
+ul.menu li {
+ display: inline;
+ color: #fff;
+}
+ul.menu a {
+ color: #fff;
+ padding: 10px;
+ text-decoration: none;
+}
+ul.menu a.selected {
+ background-color: #000;
+}
+ul.menu a:hover {
+ color: #000;
+ background-color: #ccc;
+}
+form#searchbox {
+ display:inline;
+ margin: 0;
+ position: relative;
+ bottom: 0.15em;
+}
+
+div.documentwrapper {
+ width: 960px;
+ margin: 0 auto;
+ position: relative;
+}
+
+div.bodywrapper {
+ margin: 0 0 0 230px;
+}
+
+hr {
+ border: 1px solid #B1B4B6;
+}
+
+div.document {
+ margin-top: 10px;
+}
+
+div.body {
+ background-color: #ffffff;
+ color: #3E4349;
+ padding: 0 0 30px 30px;
+ font-size: 1.3em;
+}
+
+div.footer {
+ color: #555;
+ background-color: #eee;
+ width: 100%;
+ padding: 13px 0;
+ text-align: center;
+}
+
+div.footer a {
+ color: #444;
+ text-decoration: underline;
+}
+
+div.related {
+ background-color: #6BA81E;
+ line-height: 32px;
+ color: #fff;
+ text-shadow: 0px 1px 0 #444;
+ font-size: 0.9em;
+}
+
+div.related a {
+ color: #E2F3CC;
+}
+
+div.sphinxsidebar {
+ font-size: 1.1em;
+ line-height: 1.5em;
+ margin: 0;
+ position:absolute;
+ left: 0;
+ top: 100px;
+ width: 240px;
+ float: none;
+ background-color: #eee;
+}
+
+div.sphinxsidebar h3,
+div.sphinxsidebar h4 {
+ font-family: Arial, sans-serif;
+ color: #222;
+ font-size: 1.2em;
+ font-weight: normal;
+ margin: 0;
+ padding: 5px 10px;
+ background-color: #ddd;
+ text-shadow: 1px 1px 0 white
+}
+
+div.sphinxsidebar h4{
+ font-size: 1.1em;
+}
+
+div.sphinxsidebar h3 a {
+ color: #444;
+}
+
+
+div.sphinxsidebar p {
+ color: #888;
+ padding: 5px 20px;
+}
+
+div.sphinxsidebar p.topless {
+}
+
+div.sphinxsidebar ul {
+ margin: 10px 20px;
+ padding: 0;
+ color: #000;
+}
+
+div.sphinxsidebar a {
+ color: #444;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #ccc;
+ font-family: sans-serif;
+ font-size: 1em;
+}
+
+div.sphinxsidebar input[type=text]{
+ margin-left: 20px;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+
+a {
+ color: #005B81;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #E32E00;
+ text-decoration: underline;
+}
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+ font-family: Arial, sans-serif;
+ background-color: #BED4EB;
+ font-weight: normal;
+ color: #212224;
+ margin: 30px 0px 10px 0px;
+ padding: 5px 0 5px 10px;
+ text-shadow: 0px 1px 0 white
+}
+
+div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
+div.body h2 { font-size: 150%; background-color: #C8D5E3; }
+div.body h3 { font-size: 120%; background-color: #D8DEE3; }
+div.body h4 { font-size: 100%; background-color: #eeeeee; margin-top: 20px;}
+div.body h5 { font-size: 100%; background-color: #eeeeee; margin-top: 20px;}
+div.body h6 { font-size: 100%; background-color: #eeeeee; margin-top: 20px;}
+
+a.headerlink {
+ color: #c60f0f;
+ font-size: 0.8em;
+ padding: 0 4px 0 4px;
+ text-decoration: none;
+}
+
+a.headerlink:hover {
+ background-color: #c60f0f;
+ color: white;
+}
+
+div.body p, div.body dd, div.body li {
+ line-height: 1.5em;
+}
+
+div.admonition p.admonition-title + p {
+ display: inline;
+}
+
+div.highlight{
+ background-color: white;
+}
+
+div.note {
+ background-color: #FCFFDD;
+ margin-left: 3em !important;
+ border: 1px solid #F5F5A1 !important;
+}
+div.note p.admonition-title {
+ position: absolute;
+ left: -3em;
+}
+
+div.seealso {
+ background-color: #ffc;
+ border: 1px solid #ff6;
+}
+
+div.topic {
+ background-color: #eee;
+}
+
+div.warning {
+ background-color: #ffe4e4;
+ border: 1px solid #f66;
+}
+
+div.admonition {
+ padding: .3em .8em;
+ margin: 1em 0;
+ border:1px solid #94da3a;
+ position: relative;
+}
+
+p:target, dl:target dt, dl:target h3, span:target+dt, span:target+h3 {
+ background-color : #FBE54E;
+}
+
+pre {
+ padding: 10px;
+ background-color: White;
+ color: #222;
+ line-height: 1.2em;
+ border: 1px solid #C6C9CB;
+ font-size: 1.1em;
+ margin: 1.5em 0 1.5em 0;
+ -webkit-box-shadow: 1px 1px 1px #d8d8d8;
+ -moz-box-shadow: 1px 1px 1px #d8d8d8;
+}
+
+tt {
+ background-color: #ecf0f3;
+ color: #222;
+ /* padding: 1px 2px; */
+ font-size: 1.1em;
+ font-family: monospace;
+}
+
+a tt {
+ color: #005B81;
+}
+
+a tt:hover {
+ color: #E32E00;
+ text-decoration: underline;
+}
+
+.viewcode-back {
+ font-family: Arial, sans-serif;
+}
+
+div.viewcode-block:target {
+ background-color: #f4debf;
+ border-top: 1px solid #ac9;
+ border-bottom: 1px solid #ac9;
+}
526 docs/_theme/nature/static/searchtools.js
@@ -0,0 +1,526 @@
+/*
+ * searchtools.js
+ * ~~~~~~~~~~~~~~
+ *
+ * Sphinx JavaScript utilties for the full-text search.
+ *
+ * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/**
+ * helper function to return a node containing the
+ * search summary for a given text. keywords is a list
+ * of stemmed words, hlwords is the list of normal, unstemmed
+ * words. the first one is used to find the occurance, the
+ * latter for highlighting it.
+ */
+
+jQuery.makeSearchSummary = function(text, keywords, hlwords) {
+ var textLower = text.toLowerCase();
+ var start = 0;
+ $.each(keywords, function() {
+ var i = textLower.indexOf(this.toLowerCase());
+ if (i > -1)
+ start = i;
+ });
+ start = Math.max(start - 120, 0);
+ var excerpt = ((start > 0) ? '...' : '') +
+ $.trim(text.substr(start, 240)) +
+ ((start + 240 - text.length) ? '....' : '');
+ excerpt = excerpt.replace(/\.\.\s_?.*::?/g, '');
+ excerpt = excerpt.replace(/[-=+*]{2,}/g, '');
+ excerpt = excerpt.replace(/`_?/g, "'");
+ excerpt = excerpt.replace(/\s?<.*?(>|\.\.)/g, '');
+ excerpt = excerpt.replace(/:(maxdepth|ref|doc|metho|api|term):/g, '');
+ var rv = $('<div class="context"></div>').text(excerpt);
+ $.each(hlwords, function() {
+ rv = rv.highlightText(this, 'highlighted');
+ });
+ return rv;
+}
+
+/**
+ * Porter Stemmer
+ */
+var PorterStemmer = function() {
+
+ var step2list = {
+ ational: 'ate',
+ tional: 'tion',
+ enci: 'ence',
+ anci: 'ance',
+ izer: 'ize',
+ bli: 'ble',
+ alli: 'al',
+ entli: 'ent',
+ eli: 'e',
+ ousli: 'ous',
+ ization: 'ize',
+ ation: 'ate',
+ ator: 'ate',
+ alism: 'al',
+ iveness: 'ive',
+ fulness: 'ful',
+ ousness: 'ous',
+ aliti: 'al',
+ iviti: 'ive',
+ biliti: 'ble',
+ logi: 'log'
+ };
+
+ var step3list = {
+ icate: 'ic',
+ ative: '',
+ alize: 'al',
+ iciti: 'ic',
+ ical: 'ic',
+ ful: '',
+ ness: ''
+ };
+
+ var c = "[^aeiou]"; // consonant
+ var v = "[aeiouy]"; // vowel
+ var C = c + "[^aeiouy]*"; // consonant sequence
+ var V = v + "[aeiou]*"; // vowel sequence
+
+ var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
+ var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
+ var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
+ var s_v = "^(" + C + ")?" + v; // vowel in stem
+
+ this.stemWord = function (w) {
+ var stem;
+ var suffix;
+ var firstch;
+ var origword = w;
+
+ if (w.length < 3)
+ return w;
+
+ var re;
+ var re2;
+ var re3;
+ var re4;
+
+ firstch = w.substr(0,1);
+ if (firstch == "y")
+ w = firstch.toUpperCase() + w.substr(1);
+
+ // Step 1a
+ re = /^(.+?)(ss|i)es$/;
+ re2 = /^(.+?)([^s])s$/;
+
+ if (re.test(w))
+ w = w.replace(re,"$1$2");
+ else if (re2.test(w))
+ w = w.replace(re2,"$1$2");
+
+ // Step 1b
+ re = /^(.+?)eed$/;
+ re2 = /^(.+?)(ed|ing)$/;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ re = new RegExp(mgr0);
+ if (re.test(fp[1])) {
+ re = /.$/;
+ w = w.replace(re,"");
+ }
+ }
+ else if (re2.test(w)) {
+ var fp = re2.exec(w);
+ stem = fp[1];
+ re2 = new RegExp(s_v);
+ if (re2.test(stem)) {
+ w = stem;
+ re2 = /(at|bl|iz)$/;
+ re3 = new RegExp("([^aeiouylsz])\\1$");
+ re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+ if (re2.test(w))
+ w = w + "e";
+ else if (re3.test(w)) {
+ re = /.$/;
+ w = w.replace(re,"");
+ }
+ else if (re4.test(w))
+ w = w + "e";
+ }
+ }
+
+ // Step 1c
+ re = /^(.+?)y$/;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ re = new RegExp(s_v);
+ if (re.test(stem))
+ w = stem + "i";
+ }
+
+ // Step 2
+ re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ suffix = fp[2];
+ re = new RegExp(mgr0);
+ if (re.test(stem))
+ w = stem + step2list[suffix];
+ }
+
+ // Step 3
+ re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ suffix = fp[2];
+ re = new RegExp(mgr0);
+ if (re.test(stem))
+ w = stem + step3list[suffix];
+ }
+
+ // Step 4
+ re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
+ re2 = /^(.+?)(s|t)(ion)$/;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ re = new RegExp(mgr1);
+ if (re.test(stem))
+ w = stem;
+ }
+ else if (re2.test(w)) {
+ var fp = re2.exec(w);
+ stem = fp[1] + fp[2];
+ re2 = new RegExp(mgr1);
+ if (re2.test(stem))
+ w = stem;
+ }
+
+ // Step 5
+ re = /^(.+?)e$/;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ re = new RegExp(mgr1);
+ re2 = new RegExp(meq1);
+ re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+ if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
+ w = stem;
+ }
+ re = /ll$/;
+ re2 = new RegExp(mgr1);
+ if (re.test(w) && re2.test(w)) {
+ re = /.$/;
+ w = w.replace(re,"");
+ }
+
+ // and turn initial Y back to y
+ if (firstch == "y")
+ w = firstch.toLowerCase() + w.substr(1);
+ return w;
+ }
+}
+
+
+/**
+ * Search Module
+ */
+var Search = {
+
+ _index : null,
+ _queued_query : null,
+ _pulse_status : -1,
+
+ init : function() {
+ var params = $.getQueryParameters();
+ if (params.q) {
+ var query = params.q[0];
+ $('input[name="q"]')[0].value = query;
+ this.performSearch(query);
+ }
+ },
+
+ loadIndex : function(url) {
+ $.ajax({type: "GET", url: url, data: null, success: null,
+ dataType: "script", cache: true});
+ },
+
+ setIndex : function(index) {
+ var q;
+ this._index = index;
+ if ((q = this._queued_query) !== null) {
+ this._queued_query = null;
+ Search.query(q);
+ }
+ },
+
+ hasIndex : function() {
+ return this._index !== null;
+ },
+
+ deferQuery : function(query) {
+ this._queued_query = query;
+ },
+
+ stopPulse : function() {
+ this._pulse_status = 0;
+ },
+
+ startPulse : function() {
+ if (this._pulse_status >= 0)
+ return;
+ function pulse() {
+ Search._pulse_status = (Search._pulse_status + 1) % 4;
+ var dotString = '';
+ for (var i = 0; i < Search._pulse_status; i++)
+ dotString += '.';
+ Search.dots.text(dotString);
+ if (Search._pulse_status > -1)
+ window.setTimeout(pulse, 500);
+ };
+ pulse();
+ },
+
+ /**
+ * perform a search for something
+ */
+ performSearch : function(query) {
+ // create the required interface elements
+ this.out = $('#search-results');
+ this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
+ this.dots = $('<span></span>').appendTo(this.title);
+ this.status = $('<p style="display: none"></p>').appendTo(this.out);
+ this.output = $('<ul class="search"/>').appendTo(this.out);
+
+ $('#search-progress').text(_('Preparing search...'));
+ this.startPulse();
+
+ // index already loaded, the browser was quick!
+ if (this.hasIndex())
+ this.query(query);
+ else
+ this.deferQuery(query);
+ },
+
+ query : function(query) {
+ var stopwords = ['and', 'then', 'into', 'it', 'as', 'are', 'in',
+ 'if', 'for', 'no', 'there', 'their', 'was', 'is',
+ 'be', 'to', 'that', 'but', 'they', 'not', 'such',
+ 'with', 'by', 'a', 'on', 'these', 'of', 'will',
+ 'this', 'near', 'the', 'or', 'at'];
+
+ // stem the searchterms and add them to the correct list
+ var stemmer = new PorterStemmer();
+ var searchterms = [];
+ var excluded = [];
+ var hlterms = [];
+ var tmp = query.split(/\s+/);
+ var object = (tmp.length == 1) ? tmp[0].toLowerCase() : null;
+ for (var i = 0; i < tmp.length; i++) {
+ if ($u.indexOf(stopwords, tmp[i]) != -1 || tmp[i].match(/^\d+$/) ||
+ tmp[i] == "") {
+ // skip this "word"
+ continue;
+ }
+ // stem the word
+ var word = stemmer.stemWord(tmp[i]).toLowerCase();
+ // select the correct list
+ if (word[0] == '-') {
+ var toAppend = excluded;
+ word = word.substr(1);
+ }
+ else {
+ var toAppend = searchterms;
+ hlterms.push(tmp[i].toLowerCase());
+ }
+ // only add if not already in the list
+ if (!$.contains(toAppend, word))
+ toAppend.push(word);
+ };
+ var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
+
+ // console.debug('SEARCH: searching for:');
+ // console.info('required: ', searchterms);
+ // console.info('excluded: ', excluded);
+
+ // prepare search
+ var filenames = this._index.filenames;
+ var titles = this._index.titles;
+ var terms = this._index.terms;
+ var objects = this._index.objects;
+ var objtypes = this._index.objtypes;
+ var objnames = this._index.objnames;
+ var fileMap = {};
+ var files = null;
+ // different result priorities
+ var importantResults = [];
+ var objectResults = [];
+ var regularResults = [];
+ var unimportantResults = [];
+ $('#search-progress').empty();
+
+ // lookup as object
+ if (object != null) {
+ for (var prefix in objects) {
+ for (var name in objects[prefix]) {
+ var fullname = (prefix ? prefix + '.' : '') + name;
+ if (fullname.toLowerCase().indexOf(object) > -1) {
+ match = objects[prefix][name];
+ descr = objnames[match[1]] + _(', in ') + titles[match[0]];
+ // XXX the generated anchors are not generally correct
+ // XXX there may be custom prefixes
+ result = [filenames[match[0]], fullname, '#'+fullname, descr];
+ switch (match[2]) {
+ case 1: objectResults.push(result); break;
+ case 0: importantResults.push(result); break;
+ case 2: unimportantResults.push(result); break;
+ }
+ }
+ }
+ }
+ }
+
+ // sort results descending
+ objectResults.sort(function(a, b) {
+ return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
+ });
+
+ importantResults.sort(function(a, b) {
+ return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
+ });
+
+ unimportantResults.sort(function(a, b) {
+ return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
+ });
+
+
+ // perform the search on the required terms
+ for (var i = 0; i < searchterms.length; i++) {
+ var word = searchterms[i];
+ // no match but word was a required one
+ if ((files = terms[word]) == null)
+ break;
+ if (files.length == undefined) {
+ files = [files];
+ }
+ // create the mapping
+ for (var j = 0; j < files.length; j++) {
+ var file = files[j];
+ if (file in fileMap)
+ fileMap[file].push(word);
+ else
+ fileMap[file] = [word];
+ }
+ }
+
+ // now check if the files don't contain excluded terms
+ for (var file in fileMap) {
+ var valid = true;
+
+ // check if all requirements are matched
+ if (fileMap[file].length != searchterms.length)
+ continue;
+
+ // ensure that none of the excluded terms is in the
+ // search result.
+ for (var i = 0; i < excluded.length; i++) {
+ if (terms[excluded[i]] == file ||
+ $.contains(terms[excluded[i]] || [], file)) {
+ valid = false;
+ break;
+ }
+ }
+
+ // if we have still a valid result we can add it
+ // to the result list
+ if (valid)
+ regularResults.push([filenames[file], titles[file], '', null]);
+ }
+
+ // delete unused variables in order to not waste
+ // memory until list is retrieved completely
+ delete filenames, titles, terms;
+
+ // now sort the regular results descending by title
+ regularResults.sort(function(a, b) {
+ var left = a[1].toLowerCase();
+ var right = b[1].toLowerCase();
+ return (left > right) ? -1 : ((left < right) ? 1 : 0);
+ });
+
+ // combine all results
+ var results = unimportantResults.concat(regularResults)
+ .concat(objectResults).concat(importantResults);
+
+ // print the results
+ var resultCount = results.length;
+ function displayNextItem() {
+ // results left, load the summary and display it
+ if (results.length) {
+ var item = results.pop();
+ var listItem = $('<li style="display:none"></li>');
+ if (DOCUMENTATION_OPTIONS.FILE_SUFFIX == '') {
+ // dirhtml builder
+ var dirname = item[0] + '/';
+ if (dirname.match(/\/index\/$/)) {
+ dirname = dirname.substring(0, dirname.length-6);
+ } else if (dirname == 'index/') {
+ dirname = '';
+ }
+ listItem.append($('<a/>').attr('href',
+ DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
+ highlightstring + item[2]).html(item[1]));
+ } else {
+ // normal html builders
+ listItem.append($('<a/>').attr('href',
+ item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
+ highlightstring + item[2]).html(item[1]));
+ }
+ if (item[3]) {
+ item[3] = item[3].replace('api,', 'module,');
+ item[3] = item[3].replace('prop,', 'property,');
+ item[3] = item[3].replace('metho,', 'method,');
+ listItem.append($('<span> (' + item[3] + ')</span>'));
+ Search.output.append(listItem);
+ listItem.slideDown(5, function() {
+ displayNextItem();
+ });
+ } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
+ $.get(DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' +
+ item[0] + '.txt', function(data) {
+ if (data != '') {
+ listItem.append($.makeSearchSummary(data, searchterms, hlterms));
+ Search.output.append(listItem);
+ }
+ listItem.slideDown(5, function() {
+ displayNextItem();
+ });
+ });
+ } else {
+ // no source available, just display title
+ Search.output.append(listItem);
+ listItem.slideDown(5, function() {
+ displayNextItem();
+ });
+ }
+ }
+ // search finished, update title and status message
+ else {
+ Search.stopPulse();
+ Search.title.text(_('Search Results'));
+ if (!resultCount)
+ Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
+ else
+ Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
+ Search.status.fadeIn(500);
+ }
+ }
+ displayNextItem();
+ }
+}
+
+$(document).ready(function() {
+ Search.init();
+});
4 docs/_theme/nature/theme.conf
@@ -0,0 +1,4 @@
+[theme]
+inherit = basic
+stylesheet = nature.css
+pygments_style = tango
178 docs/advanced/architecture.txt
@@ -0,0 +1,178 @@
+Architecture
+============
+
+If you are planning to extend or modify the Gamma framework -- or are, perhaps, simply curious -- it is desirable to understand the various patterns that were used whilst constructing the framework.
+
+Reading this section, you will learn:
+
+ - how to use `RequireJS <http://requirejs.org/>`_;
+ - how each module is put in the gma namespace;
+ - how we've constructed the building blocks in Gamma to allow inheritance;
+ - how we've allowed private variables through closures; and
+ - the limitations we imposed on the game engine for simplicity.
+
+
+.. _requireJSNS:
+
+Namespace and RequireJS
+------------------------
+
+Eveything in Gamma exists under the ``gma`` namespace, which has been achieved using `RequireJS <http://requirejs.org/>`_.
+
+Whether defining a new module with ``require.def`` or simply loading dependencies with ``require``, you need to supply a list of dependencies that will be loaded before executing the supplied callback. RequireJS will then pass in all these dependencies into callback function when it loads. When defining a module, this callback function is expected to return the module and is called the `Module's function`.
+
+.. code-block:: javascript
+
+ require.def('newModule',
+ [
+ 'dependency1',
+ 'dependency2'
+ ],
+ function(dependency1, dependency2) {
+ // Module's function
+
+ return the_module;
+ }
+ );
+
+Gamma uses the convention that each module has ``gma/base`` as the first dependency, then the gma namespace will be the first argument to the module's function. Then, each module will append it's contents straight onto the gma namespace. Therefore only the gma base object will return a module.
+
+For example, :api:`gma.character` is added to the gma namespace with the following code:
+
+.. code-block:: javascript
+
+ require.def('gma/entities/character',
+ [ 'gma/base', // Provides the gma namespace which
+ 'gma/entities/moveable', // is passed into the function
+ 'gma/utils/collisions' // below.
+ ],
+ function(gma) {
+ // Add gma.character
+ gma.character = function(spec) {
+ // character class goes here
+ };
+ }
+ );
+
+
+Factory Pattern
+---------------
+
+Gamma was designed so that `classes` behave like building blocks, allowing objects to be created by applying many such "building blocks" to a JavaScript object.
+
+This was achieved using the factory pattern. In this pattern, an object is created by a factory function that accepts an object and simply add more properties/methods to it.
+
+We have designed all our building blocks to "respect" properties/methods already existing on any input object, by only setting such properties and methods if the object doesn't already have such a property. The building blocks ensure that a default set of properties/methods exist on objects, so that they may be "complete".
+
+For example,
+
+.. code-block:: javascript
+
+ var myClass = function(spec) {
+ var self = spec || {};
+
+ // add properties and methods to self
+ self.y = self.y || 6
+
+ self.someFunction = self.someFunction || function() {
+ return 'hi there';
+ };
+
+ return self;
+ };
+
+ // Defaults to a new object if one isn't passed in
+ var myNewObject = myClass();
+
+ // Or we can apply the building block with some object
+ var myOtherNewObject = myClass({x:5});
+ myOtherNewObject.y; // <= 6
+
+ // Or just by calling the function on an existing object
+ var yetAnotherObject = {y:2};
+ myClass(yetAnotherObject);
+ yetAnotherObject.y; // <= 2
+
+This allows the Gamma framework to imitate inheritance -- in the previous example ``yetAnotherObject`` inherits from ``myClass`` -- but it is possible to create an object that is built using a combination of unrelated blocks.
+
+For example,
+
+.. code-block:: javascript
+
+ var myObject = {};
+ // There are no building blocks as shape, animateable or
+ // armed, but for example's sake
+ shape(myObject);
+ animateable(myObject);
+ armed(myObject);
+
+.. note:: For all these examples to work, the factory must return the object it creates/edits at the bottom
+
+The factory pattern also chosen because it allows our classes to have a :term:`closure`, which allows us to imitate private variables.
+
+.. code-block:: javascript
+
+ var myClass = function(spec) {
+ var self = spec || {};
+
+ // Anything else that is var'd is private
+ var secret = "Lalala";
+
+ // Private variable is only exposed through an accessor
+ self.someFunction = self.someFunction || function() {
+ return 'My secret is ' + secret;
+ };
+
+ return self;
+ };
+
+
+Factories in collision detection
+++++++++++++++++++++++++++++++++
+
+We have also used factories for our collision detection for caching purposes, as you can see on the page that :ref:`explains our collision detection <collisionDetection>`
+
+
+Separating Concerns
+-------------------
+
+The Gamma framework aims to disconnect the game logic from the visual logic. We have achieved this by making an interface that sits between Gamma and an arbitary rendering engine. This interface is collectively referred to as the ``Render Helpers``. Theoretically we can define rendering helpers for many rendering engines, and perhaps even non-webgl engines. At this point we only have Render Helpers that use GLGE. You can find more about these :ref:`here <renderingEngines>`.
+
+
+Limitations for Simplicity
+--------------------------
+
+Gamma was designed to be with two main limitations to keep the code simple
+
+* Entities can only move in 2D space
+* Everything is a square
+
+Below is the list of places in the Gamma codebase that makes these assumptions
+
+* The entire collision detection assumes we don't need to look at the ``z`` axis, and that everything is a square
+
+ * :metho:`gma.collisions.detectCollisions`, :metho:`gma.collisions.factories.findCollisions`, :metho:`gma.collisions.factories.findGround`, :metho:`gma.collisions.factories.findBlockers`
+
+* We only supply directional :api:`constants <gma.constants>` that represent 2D directions, (:constant:`LEFT`, :constant:`RIGHT`, :constant:`FALLING`, :constant:`JUMPING`)
+
+* :metho:`gma.renderHelper.setLocation` assumes entities don't have a ``z`` property.
+
+* :api:`gma.moveable` assumes it only needs to keep track of vertical and horizontal state (:prop:`gma.moveable.xState` and :prop:`gma.moveable.yState`)
+
+* :api:`gma.moveable` also has functions that change the position of an entity, and they all assume we only need to update it's :prop:`gma.moveable.x` and :prop:`gma.moveable.y` properties
+
+ * :metho:`gma.moveable.updatePositions`, :metho:`gma.moveable.animate`, :metho:`gma.moveable.getMovement`
+ * This also means everything that inherits from :api:`gma.moveable` have the same limitations.
+
+* :api:`gma.shapes.rectangle` has a couple of functions that don't care about the ``z`` axis.
+
+ * :metho:`gma.shapes.rectangle.setBottomLeft` and :metho:`gma.shapes.rectangle.setPointsAndEdges`
+
+* :api:`gma.shapes.rectangle` is the only object that provides any "shape" functionality.
+
+
+Functionality through tags
+--------------------------
+
+Gamma uses a very simple tags system to provide the ability to specify particular functionality on entities. This is explained in further detail on :ref:`this page <tags>`.
+
184 docs/advanced/collisionFunctions.txt
@@ -0,0 +1,184 @@
+.. _collisionFunctions:
+
+Defining collision behaviour
+============================
+
+Each entity in Gamma defines what happens when a collision with another entity occurs via their :metho:`gma.shapes.rectangle.collided` method. When Gamma :ref:`detects that a collision has occurred <collisionDetection>`, this function is invoked on the entities that have collided.
+
+An understanding of this function is helpful if you wish to extend the functionality of the character or enemies, or create new entities.
+
+The *collided* method
+*********************
+
+For the following explanation, ``self`` refers to the entity defining the behaviour, and ``focus`` refers to the entity that is being collided with.
+
+The :metho:`gma.shapes.rectangle.collided` method accepts four arguments:
+
+* ``where`` -- The side of ``self`` that was collided with as a :api:`gma.constant`
+* ``focus`` -- The entity that was collided with
+* ``focusSide`` -- The side of the ``focus`` that was collided with
+* ``focusVector`` -- The movement vector [x, y] that the ``focus`` was trying to move by before it collided
+
+To make configuring and customising behaviour flexible, we have implemented this function so that it looks at the :ref:`tags <tags>` on the entity. If a particular tag exists, then an internal method (with the same method signature) is called to carry out the functionality.
+
+In this example the function to pick up a collectable (eg. coin) is called if the focus has a collectable tag:
+
+.. code-block:: javascript
+
+ var oldCollided = self.collided;
+ self.collided = function(where, focus, focusSide, focusVector) {
+ oldCollided.apply(this, arguments);
+ if (focus.tags.collectable) {
+ self.collided__pickupCollectable.apply(this, arguments);
+ }
+ };
+
+In this extract from :api:`gma.enemy`, the focus (character) is killed if the enemy is alive and has the ``deathtouch`` tag:
+
+.. code-block:: javascript
+
+ var oldCollided = self.collided;
+ self.collided = function() {
+ oldCollided.apply(this, arguments);
+ ...
+
+ if (self.alive && self.tags.deathtouch) {
+ self.collided__deathtouch.apply(this, arguments);
+ }
+ };
+
+ // Defined elsewhere
+ self.collided__deathtouch || function(w, focus, fs, fv) {
+ if (focus.tags.character) {
+ focus.kill();
+ }
+ };
+
+As a convention, these internal methods are named by prepending the tag name with "collided\_\_". See :metho:`gma.enemy.collided__deathtouch`, :metho:`gma.enemy.collided__weakhead`, :metho:`gma.enemy.collided__rebound` and :metho:`gma.character.collided__pickupCollectable`
+
+
+Writing custom collision behaviour
+**********************************
+
+Let's say we want to make a `cryer` that yells in pain every time something hits it.
+
+To create a `cryer` we can create a rectangle and define a custom ``collided`` function on that rectangle. We create a reference of the old ``collided`` function before we define the new one. Then, inside the new ``collided`` function we invoke the old function:
+
+.. code-block:: javascript
+
+ myRectangle = gma.shapes.rectangle({x:0, y:0, width:1, height:1});
+
+ oldCollided = myRectangle.collided;
+ myRectangle.collided = function() {
+ oldCollided.apply(this, arguments);
+ manager.hud.message("OOOOWWWW", 20)
+ }
+
+
+Alternatively, we can create a function that can be used to add this functionality to any entity.
+
+.. code-block:: javascript
+
+ cryerFunctionality = function(entity) {
+ var self = entity || gma.shapes.rectangle({x:0, y:0, width:1, height:1});
+
+ var oldCollided = self.collided;
+ self.collided = function() {
+ oldCollided && oldCollided.apply(this, arguments);
+ manager.hud.message("OOOOWWWW", 20)
+ }
+
+ return self;
+ }
+
+If we follow the convention that this logic should be defined in an internal function, would would write the function as:
+
+.. code-block:: javascript
+
+ cryerFunctionality = function(entity) {
+ var self = entity || gma.shapes.rectangle({x:0, y:0, width:1, height:1});
+
+ var oldCollided = self.collided;
+ self.collided = function() {
+ oldCollided && oldCollided.apply(this, arguments);
+ self.collided__announce.apply(this, arguments);
+ }
+
+ self.collided__announce = function() {
+ manager.hud.message("OOOOWWWW", 20)
+ }
+
+ return self;
+ }
+
+We could take this further and use the functions arguments to change the message:
+
+.. code-block:: javascript
+
+ cryerFunctionality = function(entity) {
+ var self = entity || gma.shapes.rectangle({x:0, y:0, width:1, height:1});
+
+ self.sides = {}
+ self.sides[gma.constants.TOP] = 'top'
+ self.sides[gma.constants.LEFT] = 'left'
+ self.sides[gma.constants.RIGHT] = 'right'
+ self.sides[gma.constants.BOTTOM] = 'bottom'
+
+ oldCollided = self.collided;
+ self.collided = function() {
+ oldCollided.apply(this, arguments);
+ self.collided__announce.apply(this, arguments);
+ }
+
+ self.collided__announce = function(where, focus, focusSide) {
+ manager.hud.message("OWWWWWW, damnit!, something hit my " + sides[where] + " with their " + sides[focusSide], 20);
+ }
+
+ return self;
+ };
+
+We could also change the message based on the entity's tags:
+
+.. code-block:: javascript
+
+ cryerFunctionality = function(entity) {
+ var self = entity || gma.shapes.rectangle({x:0, y:0, width:1, height:1});
+
+ self.sides = {}
+ self.sides[gma.constants.TOP] = 'top'
+ self.sides[gma.constants.LEFT] = 'left'
+ self.sides[gma.constants.RIGHT] = 'right'
+ self.sides[gma.constants.BOTTOM] = 'bottom'
+
+ oldCollided = self.collided;
+ self.collided = function() {
+ oldCollided.apply(this, arguments);
+ if (self.tags.angry) {
+ self.collided__anger.apply(this, arguements);
+ }
+ else {
+ self.collided__announce.apply(this, arguments);
+ }
+ }
+
+ self.collided__announce = function(where, environ, environSide) {
+ manager.hud.message("OWWWWWW, damnit!, something hit my " + sides[where] + " with their " + sides[environSide], 20);
+ }
+
+ self.collided__anger = function(where, environ, environSide) {
+ manager.hud.message("GO AWAY, ANNOYING THING", 20);
+ }
+
+ return self;
+ };
+
+We can then use it as follows:
+
+.. code-block:: javascript
+
+ captainObvious = gma.jumpingEnemy({x:0, y:0, width:2, height:5});
+ cryerFunctionality(captainObvious);
+
+ anAngryEnemy = gma.enemy({x:0, y:0, width:2, height:4, tags=['angry']});
+ cryerFunctionality(anAngryEnemy);
+
18 docs/advanced/index.txt
@@ -0,0 +1,18 @@
+.. _advancedTopics:
+
+Advanced Topics
+=================================
+
+More advanced information providing the knowledge required to understand and/or customise the behaviour of the Gamma engine.
+
+Table of Contents
+-----------------
+
+.. toctree::
+ :maxdepth: 1
+
+ install
+ architecture
+ collisionFunctions
+ levelParser
+ templates
41 docs/advanced/install.txt
@@ -0,0 +1,41 @@
+.. _advancedInstall:
+
+Developing with Gamma
+=====================
+
+Gamma is a modular library that is split into many files. Whilst you can use a combined and :term:`minified` version of the library, as shown in the :ref:`getting started section <install>`, it's a lot easier to develop and debug you game if you can view the full source code. This allows you to see the code where errors originate from and set breakpoints in the Gamma library.
+
+To install the non-minified version, you must download a few files and modify your HTML page to tell RequireJS where to find the Gamma library:
+
+* Follow the :ref:`getting started section <install>`.
+
+* Download all the `Gamma files <http://lodle.dyndns.org:8/code/gma.tar.bz2>`_ and untar it so you have the ``gma`` folder next to your other files.
+
+* Download :ref:`RequireJS <requireJSNS>` and the other libraries that Gamma uses, which you can find in a `single, minifed file <http://lodle.dyndns.org:8/code/libs-min.js>`_.
+
+* Inside ``game.html``, replace the ``head`` element with the following:
+
+ .. code-block:: html
+
+ <head>
+
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>My Awesome Game</title>
+
+ <!-- Include any style sheets here -->
+
+ <!-- Tell requirejs where to find your code -->
+ <script type="text/javascript">
+ var require = {
+ baseUrl: "",
+ waitSeconds: 15,
+ context: "gma"
+ };
+ </script>
+
+ <!-- Include the necessary libraries -->
+ <script type="text/javascript" src="libs-min.js"></script>
+
+ </head>
+
+* That's it!
153 docs/advanced/levelParser.txt
@@ -0,0 +1,153 @@
+.. _levelParsers:
+
+Level Parser
+============
+
+If you need to extend or modify the level parser -- or are, perhaps, simply curious -- this section describes how the level parser works.
+
+When a Gamma :api:`manager <gma.manager>` loads a level, it parses the level specifications with it's :prop:`gma.manager.levelParser` object. The :api:`gma.levelParser` is designed to **create gamma objects from the level specification object**. By default the level parser object will be an instance of :api:`gma.levelParser`.
+
+Level parsing begins with the :metho:`processLevel(level) <gma.levelParser.processLevel>` method which does the following:
+
+* Check to see if the level has been previously processed
+
+ * If it has, then return the level, parsing the level stops here
+
+* Set any defaults on the level using :metho:`gma.levelParser.preProcess`
+
+* Process the level
+
+Determining if a level is already processed
+-------------------------------------------
+
+The level parser will consider a level as already processed if it has a property on it called ``processed``, which is set to ``true``.
+
+The levelParser will ensure this property is set to ``true`` on the level once it has been processed.
+
+Pre-Processing the level
+------------------------
+
+The :metho:`gma.levelParser.preProcess` function serves two purposes :
+
+Expand Replicate With
++++++++++++++++++++++++++++++++
+
+Firstly, the :metho:`gma.utils.expandReplicateWith` method is used to expand the level specification where the ``replicateWith`` key has been used. See :ref:`ReplicateWith <replicateWith>` in the level creation topic.
+
+Set up all necessary defaults on the level
++++++++++++++++++++++++++++++++++++++++++++++
+
+Secondly set up defaults for a level's light, camera, entities and spawn location. This is done using :metho:`gma.levelParser.default_light`, :metho:`gma.levelParser.default_camera`, :metho:`gma.levelParser.default_entities` and :metho:`gma.levelParser.default_spawn` to get defaults for these particular properties.
+
+This function will also initialise the following properties:
+
+level.removed
+*******************
+
+This list is used by :metho:`gma.manager.twitch` when it calls :metho:`gma.manager.removeDead`, which then uses it to store references to any entities that have died with a ``reincarnate`` tag.
+
+:metho:`gma.manager.loadLevel` uses this list of `reincarnatable` enemies to set their status back to ``alive`` if when the level is reloaded.
+
+level.following
+***************
+
+This is a :term:`dictionary` that holds any item that specifies it follows another item. Currently only the light and camera may specify this, and they are limited to following the character.
+
+The dictionary is then used by :metho:`gma.manager.loadLevel`, which uses the information in calls to :metho:`gma.sceneHelper.attach` on the manager's :prop:`gma.manager.sceneHelper`.
+
+level.levelExtras
+*****************
+
+References to any level specific items (currently, just lights and camera) that have been added the the rendered scene. This list is maintained so that when :metho:`gma.manager.clearLevel` is called, it knows what extra items in the current scene belong to the current level and must be removed. (This allows lights and other objects to be permanently added to the scene, regardless of the currently level.)
+
+Processing a level
+------------------
+
+The levelParser is designed such that processing each item in the level is done independently of other items. This is accomplished by a suite of ``validate_*`` and ``process_*`` functions (the star represents the property on the level that these functions will operate on). Gamma provides processing functions for entities, light, camera, other, utility, following, template, removed and levelExtras.
+
+For example to process entities in a level specification,
+
+.. code-block:: javascript
+
+ var myLevel = {
+ entities : [
+ {left:19, right:30, top:9, height:3}
+ ]
+ };
+
+Gamma provides the following functions in :api:`gma.levelParser`:
+
+.. code-block:: javascript
+
+ self.validate_entities = function(manager, key, value, level) {
+ ...
+ };
+
+ self.process_entities = function(manager, key, value, level) {
+ ...
+ }
+
+ self.default_entities = function(manager, key, value, level) {
+ ...
+ }
+
+Arguments to validate and process functions
++++++++++++++++++++++++++++++++++++++++++++
+
+Each validate and process function will receive, in this order, a ``manager`` object, the ``key`` of the property being processed, the ``value`` of the property being processed, and the ``level`` object being processed.
+
+Changes made to the level object are permanent and cannot be reversed.
+
+Validate function
++++++++++++++++++++++
+
+The validate function checks whether it is possible to create a gamma object with the properties specified. These functions will simply return a Boolean saying whether the information is valid or not.
+
+This function is allowed to transform the data to be valid for processing.
+
+Process function
++++++++++++++++++++++
+
+The process function will turn each object specification into an actual gamma object. This way :metho:`gma.manager.loadLevel` does not need to worry about whether the objects in the level are gamma objects or just specifications.
+
+.. _levelParserPreProcess:
+
+Default function
++++++++++++++++++++
+
+The default function is optional. It is used by :metho:`gma.levelParser.preProcess` to set up a default for the level where one is not specified.
+
+
+Processing a Custom Type
+--------------------------
+
+You can create you own type of object in the level parser. For example, say we want to make the levelParser aware of a ``skybox`` property on the level, then all we need to do is create ``validate_skybox`` and ``process_skybox`` functions. Then optionally create a ``default_skybox`` function and override :metho:`gma.levelParser.preProcess` such that it is used.
+
+.. code-block:: javascript
+
+ var myLevelParser = (function() {
+ var self = gma.levelParser();
+
+ var oldPreProcess = self.preProcess;
+ self.preProcess = function(level) {
+ level = oldPreProcess(level);
+
+ level.skybox = level.skybox || self.default_skybox();
+ };
+
+ self.validate_skybox(manager, key, value, level) {
+ //validate the information given for the skybox property here
+ };
+
+ self.process_skybox(manager, key, value, level) {
+ //Do any necessary processing/transformation to the information given for the skybox here
+ };
+ })();
+
+Then we just set this new levelParser on the manager, and then when we use :metho:`gma.manager.loadLevel`, it will be aware of the skybox property and handle it as you have specified.
+
+.. note :: If the levelparser can't find an associated validate and/or process function for a property, it will use the generic :metho:`gma.levelParser.validate_other` and :metho:`gma.levelParser.process_other` methods.
+
+
+
+
37 docs/advanced/templates.txt
@@ -0,0 +1,37 @@
+.. _renderHelpers:
+
+Render Helpers and Templates
+============================
+
+This page explains how Gamma uses :api:`gma.renderHelper` to provide the link between Gamma entities and the rendering engine.
+
+Everything that is rendered in Gamma is found inside the ``entities`` or ``levelExtras`` property of the current level. The content of the ``entities`` list doesn't matter, as long as each `entity` has a ``helper`` property that is an instance of :api:`gma.renderHelper`, and that the `render helper` has a :prop:`gma.renderHelper.template` property set to a descendant of :api:`gma.baseTemplate`. These `render helpers` are used to provide the visual representation to the `scene helper`.
+
+.. note:: See :ref:`appearance` for more information on templates
+
+As a part of processing a level, in the :metho:`gma.levelParser.process_entities` method, the :prop:`gma.manager.levelParser` will go through all the entities in the level and use :metho:`gma.manager.prepareEntity` to give them each a :api:`gma.renderHelper`.
+
+These render helper objects are responsible for ensuring that the visual representation of the entity it belongs to has the correct size and position and is added to the current :prop:`gma.manager.sceneHelper`. The render helper also maintains a cache of the object specifying this representation.
+
+Registering with the SceneHelper
+++++++++++++++++++++++++++++++++
+
+As a part of loading a level, :metho:`gma.manager.loadLevel` will go through the ``entities`` list on the current level and ask the :prop:`gma.manager.sceneHelper` to add each entity's ``helper`` object.
+
+This will cause the :api:`gma.sceneHelper` to call the render helper's :metho:`gma.renderHelper.addTo` method with a container that it can add the visual representation to.
+
+Maintaining size and position
++++++++++++++++++++++++++++++
+
+As part of the :term:`Game Loop`, the manager's :prop:`gma.manager.sceneHelper` is asked to render the scene using it's :metho:`gma.sceneHelper.render` method. This method will first update all the objects specific to the rendering engine using :metho:`gma.sceneHelper.setRenderedLocations` and then use ask the rendering engine to render everything.
+
+The :metho:`gma.sceneHelper.setRenderedLocations` method will go through each entity on the current level and call :metho:`gma.renderHelper.setLocation` on each entity's render helper. This method will get the object that represents the entity and make sure it accurately represents the size and position of the entity.
+
+.. note:: The :metho:`gma.sceneHelper.setRenderedLocations` method is also responsible for ensuring anything registered as being :ref:`attached <attached>` to something else is moved when that entity is moved.
+
+Providing a cache
++++++++++++++++++
+
+To get the rendering specific object from a render helper, we call it's :metho:`gma.renderHelper.getRenderedObj` method. This method will look for an ``_instance`` attribute on the render helper. If it does not have one, then it will ask it's template (one is added as part of :metho:`gma.manager.prepareEntity`) to give it an instance to work with by calling it's :metho:`gma.baseTemplate.getInstance` method.
+
+.. note:: You can override the template on the render helper just by setting it's ``_instance`` property.
117 docs/api/docs/gma.txt
@@ -0,0 +1,117 @@
+
+
+
+
+.. _gmaApi:
+
+
+
+
+
+
+gma
+===
+
+Everything resides under the gma namespace
+
+.. toctree::
+ :hidden:
+ :titlesonly:
+
+
+ gma/gma
+
+ gma/constants
+
+ gma/keyHandler
+
+ gma/manager
+
+ gma/character
+
+ gma/collectable
+
+ gma/scoreCollectable
+
+ gma/door
+
+ gma/enemy
+
+ gma/platformEnemy
+
+ gma/jumpingEnemy
+
+ gma/patrolEnemy
+
+ gma/moveable
+
+ gma/platform
+
+ gma/deathPlatform
+
+ gma/shapes
+
+ gma/shapes.rectangle
+
+ gma/backgroundMaker
+
+ gma/utils
+
+ gma/collisions
+
+ gma/hud
+
+ gma/levelParser
+
+ gma/sceneHelper
+
+ gma/renderHelper
+
+ gma/baseTemplate
+
+ gma/colladaTemplate
+
+ gma/glgeIDTemplate
+
+ gma/meshTemplate
+
+
+Available classes
+-----------------
+
+
+* Top Level
+
+ * :doc:`gma <gma/gma>`
+ * :doc:`constants <gma/constants>`
+ * :doc:`keyHandler <gma/keyHandler>`
+ * :doc:`manager <gma/manager>`
+* entities
+
+ * :doc:`character <gma/character>`
+ * :doc:`collectable <gma/collectable>`
+ * :doc:`scoreCollectable <gma/scoreCollectable>`
+ * :doc:`door <gma/door>`
+ * :doc:`enemy <gma/enemy>`
+ * :doc:`platformEnemy <gma/platformEnemy>`
+ * :doc:`jumpingEnemy <gma/jumpingEnemy>`
+ * :doc:`patrolEnemy <gma/patrolEnemy>`
+ * :doc:`moveable <gma/moveable>`
+ * :doc:`platform <gma/platform>`
+ * :doc:`deathPlatform <gma/deathPlatform>`
+ * :doc:`shapes <gma/shapes>`
+ * :doc:`shapes.rectangle <gma/shapes.rectangle>`
+* utils
+
+ * :doc:`backgroundMaker <gma/backgroundMaker>`
+ * :doc:`utils <gma/utils>`
+ * :doc:`collisions <gma/collisions>`
+ * :doc:`hud <gma/hud>`
+ * :doc:`levelParser <gma/levelParser>`
+ * :doc:`sceneHelper <gma/sceneHelper>`
+ * :doc:`renderHelper <gma/renderHelper>`
+ * :doc:`baseTemplate <gma/baseTemplate>`
+ * :doc:`colladaTemplate <gma/colladaTemplate>`
+ * :doc:`glgeIDTemplate <gma/glgeIDTemplate>`
+ * :doc:`meshTemplate <gma/meshTemplate>`
+
181 docs/api/docs/gma/backgroundMaker.txt
@@ -0,0 +1,181 @@
+
+
+.. api:: gma.backgroundMaker
+
+
+.. api:: backgroundMaker
+
+
+
+gma.backgroundMaker
+===================
+
+
+ Provides some functions to transform specification into background
+
+
+
+ ========= ======================
+ Package gma/utils/background
+ ========= ======================
+
+
+
+
+
+
+
+Properties
+----------
+
+
+
+
+
+
+
+
+.. _gma.backgroundMaker.z:
+
+
+.. prop:: gma.backgroundMaker.z
+
+
+**z**
+
+ The z co-ordinate given to all background items
+
+ +------+--------+
+ | Type | Number |
+ +------+--------+
+
+
+