diff --git a/indigo/build.sbt b/indigo/build.sbt index 278202875..a0f3bf0fb 100644 --- a/indigo/build.sbt +++ b/indigo/build.sbt @@ -11,12 +11,12 @@ ThisBuild / scalaVersion := scala3Version lazy val indigoVersion = IndigoVersion.getVersion // For the docs site -lazy val indigoDocsVersion = "0.14.0" -lazy val tyrianDocsVersion = "0.6.0" +lazy val indigoDocsVersion = "0.15.0-RC3" +lazy val tyrianDocsVersion = "0.7.1" lazy val scalaJsDocsVersion = "1.13.1" lazy val scalaDocsVersion = "3.3.0" -lazy val sbtDocsVersion = "1.9.0" -lazy val millDocsVersion = "0.10.12" +lazy val sbtDocsVersion = "1.9.2" +lazy val millDocsVersion = "0.11.0" lazy val commonSettings: Seq[sbt.Def.Setting[_]] = Seq( version := indigoVersion, @@ -194,8 +194,8 @@ lazy val jsdocs = project "io.indigoengine" %%% "indigo-json-circe" % indigoDocsVersion, "io.indigoengine" %%% "indigo" % indigoDocsVersion, "io.indigoengine" %%% "indigo-extras" % indigoDocsVersion, - "io.indigoengine" %%% "tyrian-io" % tyrianDocsVersion, - "io.indigoengine" %%% "tyrian-indigo-bridge" % tyrianDocsVersion + "io.indigoengine" %%% "tyrian-io" % tyrianDocsVersion//, + // "io.indigoengine" %%% "tyrian-indigo-bridge" % tyrianDocsVersion ) ) .enablePlugins(ScalaJSPlugin) diff --git a/indigo/docs/01-quickstart/directory.conf b/indigo/docs/01-quickstart/directory.conf new file mode 100644 index 000000000..9b0e1f665 --- /dev/null +++ b/indigo/docs/01-quickstart/directory.conf @@ -0,0 +1 @@ +laika.title = "Setup & Configuration" diff --git a/indigo/docs/quickstart/examples.md b/indigo/docs/01-quickstart/examples.md similarity index 61% rename from indigo/docs/quickstart/examples.md rename to indigo/docs/01-quickstart/examples.md index 37ae43dbd..7777774b2 100644 --- a/indigo/docs/quickstart/examples.md +++ b/indigo/docs/01-quickstart/examples.md @@ -1,16 +1,11 @@ ---- -id: examples -title: Examples ---- +# Examples At various points in Indigo's development, little games and examples have been made. These help drive out requirements, test the feel of the engine against real examples and help ensure the build is stable. They are not always very polished, but they are small and reasonably easy to follow. -> The examples have moved. They now track the latest public release! - They can all be found in the [indigo-examples](https://github.com/PurpleKingdomGames/indigo-examples) repo. Please visit the [repo](https://github.com/PurpleKingdomGames/indigo-examples) for more information. -You can play a game of [Snake](/snake.html) and try the [The Cursed Pirate](/pirate.html) demo on this site. Please note that The Cursed Pirate is not a game, just a little demo of how you might build a platformer. +You can play a game of Snake and try the The Cursed Pirate Demo demo on this site. Please note that The Cursed Pirate is not a game, just a little demo of how you might build a platformer. diff --git a/indigo/docs/quickstart/hello-indigo.md b/indigo/docs/01-quickstart/hello-indigo.md similarity index 98% rename from indigo/docs/quickstart/hello-indigo.md rename to indigo/docs/01-quickstart/hello-indigo.md index 9b34ca021..16f2d9d7d 100644 --- a/indigo/docs/quickstart/hello-indigo.md +++ b/indigo/docs/01-quickstart/hello-indigo.md @@ -1,7 +1,4 @@ ---- -id: hello-indigo -title: Hello, Indigo! ---- +# Hello, Indigo! This is a quick start tutorial to help you build something with Indigo. @@ -23,7 +20,7 @@ In this guide, we'll be using `IndigoSandbox` for brevity and our "game" will be ## "Hello, Indigo!" -We'll skip over the initial project set up and assume that you followed the [set up guide](setup-and-configuration.md), or have [checked out the repo](https://github.com/PurpleKingdomGames/hello-indigo) for reference. +We'll skip over the initial project set up and assume that you followed the [set up guide](quickstart.md), or have [checked out the repo](https://github.com/PurpleKingdomGames/hello-indigo) for reference. Here is our starting point: @@ -31,7 +28,7 @@ Here is our starting point: import indigo.* import scala.scalajs.js.annotation.JSExportTopLevel -@JSExportTopLevel("IndigoGame") +// @JSExportTopLevel("IndigoGame") // Pandering to mdoc object HelloIndigo extends IndigoSandbox[Unit, Unit] { val config: GameConfig = @@ -100,7 +97,7 @@ One small thing to note is that most types in Indigo try to provide sensible def We're going to follow the Mill version of the project below, but the SBT version is almost identical, substituting `sbt runGame` in place of `mill helloindigo.runGame`. -So assuming you have followed the [set up guide](setup-and-configuration.md), to run the demo enter the following from your command line: +So assuming you have followed the [set up guide](quickstart.md), to run the demo enter the following from your command line: ```bash mill helloindigo.runGame diff --git a/indigo/docs/quickstart/project-templates.md b/indigo/docs/01-quickstart/project-templates.md similarity index 88% rename from indigo/docs/quickstart/project-templates.md rename to indigo/docs/01-quickstart/project-templates.md index 2dd2099f8..509e65670 100644 --- a/indigo/docs/quickstart/project-templates.md +++ b/indigo/docs/01-quickstart/project-templates.md @@ -1,7 +1,4 @@ ---- -id: project-templates -title: Mill & SBT Game Templates ---- +# Mill & SBT Templates To help you get started quickly, we've put together a minimal project template for both [Mill](http://www.lihaoyi.com/mill/) and [SBT](https://www.scala-sbt.org/). diff --git a/indigo/docs/quickstart/setup-and-configuration.md b/indigo/docs/01-quickstart/quickstart.md similarity index 99% rename from indigo/docs/quickstart/setup-and-configuration.md rename to indigo/docs/01-quickstart/quickstart.md index 555db1573..4a041aef4 100644 --- a/indigo/docs/quickstart/setup-and-configuration.md +++ b/indigo/docs/01-quickstart/quickstart.md @@ -1,9 +1,4 @@ ---- -id: setup-and-configuration -title: Setup & Configuration ---- - -## Quick setup +# Quick start ### Using giter8 / sbt new diff --git a/indigo/docs/02-guides/directory.conf b/indigo/docs/02-guides/directory.conf new file mode 100644 index 000000000..0b2125941 --- /dev/null +++ b/indigo/docs/02-guides/directory.conf @@ -0,0 +1 @@ +laika.title = Guides diff --git a/indigo/docs/guides/howto-custom-entity.md b/indigo/docs/02-guides/howto-custom-entity.md similarity index 99% rename from indigo/docs/guides/howto-custom-entity.md rename to indigo/docs/02-guides/howto-custom-entity.md index 63bae16ad..90da4d895 100644 --- a/indigo/docs/guides/howto-custom-entity.md +++ b/indigo/docs/02-guides/howto-custom-entity.md @@ -1,7 +1,4 @@ ---- -id: howto-custom-entity -title: How to make a custom entity ---- +# How to make a custom entity ## What are custom entities? diff --git a/indigo/docs/guides/howto-fire-shader.md b/indigo/docs/02-guides/howto-fire-shader.md similarity index 99% rename from indigo/docs/guides/howto-fire-shader.md rename to indigo/docs/02-guides/howto-fire-shader.md index 99e8cf9ad..ef5909ac1 100644 --- a/indigo/docs/guides/howto-fire-shader.md +++ b/indigo/docs/02-guides/howto-fire-shader.md @@ -1,7 +1,4 @@ ---- -id: howto-fire-shader -title: How to write a fire shader ---- +# How to write a fire shader In this how-to guide, we're going to look at one approach to writing a little shader that produces procedural flames. Here's one I made earlier: @@ -48,7 +45,7 @@ final case class Fire( ShaderData( Fire.shaderId, UniformBlock( - "FireData", + UniformBlockName("FireData"), Batch( Uniform("OFFSET") -> float(offset), Uniform("COLOR_OUTER") -> vec3(outer.r, outer.g, outer.b), @@ -172,7 +169,7 @@ def toShaderData: ShaderData = ShaderData( Fire.shaderId, UniformBlock( - "FireData", + UniformBlockName("FireData"), Batch( Uniform("OFFSET") -> float(offset), Uniform("COLOR_OUTER") -> vec3(outer.r, outer.g, outer.b), @@ -194,7 +191,7 @@ layout (std140) uniform FireData { }; ``` -At some point in the future it would be good to improve the type safety around the relationship across this interface, but for now, please take care. More information on how this works including the **all important packing rules** can be found in the [Shaders Overview](shaders/shader-overview.md). +At some point in the future it would be good to improve the type safety around the relationship across this interface, but for now, please take care. More information on how this works including the **all important packing rules** can be found in the [Shaders Overview](/07-shaders/shaders-overview.md). ### UVs diff --git a/indigo/docs/guides/howto-hello-indigo-tyrian.md b/indigo/docs/02-guides/howto-hello-indigo-tyrian.md similarity index 98% rename from indigo/docs/guides/howto-hello-indigo-tyrian.md rename to indigo/docs/02-guides/howto-hello-indigo-tyrian.md index 75fe32b0d..348520dd7 100644 --- a/indigo/docs/guides/howto-hello-indigo-tyrian.md +++ b/indigo/docs/02-guides/howto-hello-indigo-tyrian.md @@ -1,7 +1,4 @@ ---- -id: howto-responsive-ui-with-tyrian -title: How to make a responsive UI using Tyrian ---- +# How to make a responsive UI using Tyrian ## Responsive UI Using Tyrian @@ -36,7 +33,7 @@ These are the steps we're going to take: * [Set up the environment](#setting-up-the-environment) - e.g. clone `hello-indigo` and set up ParcelJS * [Modify our build files](#setting-up-the-build) - e.g. update our `build.sbt` or `build.sc` files * [Create our static files](#setting-up-the-html-and-parceljs) - e.ge create our html, js, css and other static content -* [Update Indigo with a new subsystem](#update-helloindigoscala) and [Initialise our Tyrian app](#create-a-tyrian-app) +* [Update Indigo with a new subsystem](#update-helloindigo-scala) and [Initialise our Tyrian app](#create-a-tyrian-app) * [Get Tyrian publishing messages to Indigo](#tyrian-to-indigo-communication) (and Indigo to subscribe to them) * [Get Indigo publishing messages to Tyrian](#indigo-to-tyrian-communication) (and Tyrian to subscribe to them) * And finally [creating a responsive UI in CSS](#responsive-ui) @@ -57,7 +54,7 @@ follow [this guide](howto-indigo-game.md) or replace `HelloIndigo.scala` with [this](https://gist.github.com/hobnob/c24f00936e91a7b7e5d644d19e4f1b32) -```scala mdoc:js:shared:invisible +```scala import indigo.* import indigo.scenes.* import tyrian.TyrianSubSystem @@ -373,7 +370,7 @@ Create a new file called `HelloTyrian.scala` inside the `helloindigo/src` folder and add the following contents found below, or [here](https://gist.github.com/hobnob/436318b3ae5eed5891ba2b18bb8c264b). -```scala mdoc:js +```scala import cats.effect.IO import tyrian.* import tyrian.Html.* diff --git a/indigo/docs/guides/howto-indigo-game.md b/indigo/docs/02-guides/howto-indigo-game.md similarity index 98% rename from indigo/docs/guides/howto-indigo-game.md rename to indigo/docs/02-guides/howto-indigo-game.md index 219c485d8..b82a811d3 100644 --- a/indigo/docs/guides/howto-indigo-game.md +++ b/indigo/docs/02-guides/howto-indigo-game.md @@ -1,7 +1,4 @@ ---- -id: howto-indigo-game -title: Converting `IndigoSandbox` to `IndigoGame` ---- +# Converting `IndigoSandbox` to `IndigoGame` ## Basic Concepts diff --git a/indigo/docs/03-gameloop/directory.conf b/indigo/docs/03-gameloop/directory.conf new file mode 100644 index 000000000..880502913 --- /dev/null +++ b/indigo/docs/03-gameloop/directory.conf @@ -0,0 +1 @@ +laika.title = Gameloop diff --git a/indigo/docs/gameloop/events.md b/indigo/docs/03-gameloop/events.md similarity index 97% rename from indigo/docs/gameloop/events.md rename to indigo/docs/03-gameloop/events.md index da39a15c7..34838e4fc 100644 --- a/indigo/docs/gameloop/events.md +++ b/indigo/docs/03-gameloop/events.md @@ -1,7 +1,4 @@ ---- -id: events -title: Events ---- +# Events ## The event loop @@ -71,7 +68,7 @@ of the site, and will also fire when the application loses or gains focus. ### `InputEvent`s -Handling `InputEvent`s can be a bit tricky in some situations, so Indigo includes `Mouse` and `Keyboard` classes that can be accessed from the [frame context](gameloop/frame-context.md), providing a rich interface to gather more complex information from those input devices. +Handling `InputEvent`s can be a bit tricky in some situations, so Indigo includes `Mouse` and `Keyboard` classes that can be accessed from the [frame context](/03-gameloop/frame-context.md), providing a rich interface to gather more complex information from those input devices. #### `MouseEvent`s @@ -137,7 +134,7 @@ the internet or indeed a single resource on the internet is available. - `HttpError` - Unspecified error - `HttpResponse(status, headers, body)` -### `StorageEvent`s +### StorageEvents Used to load and save data from local storage. @@ -155,7 +152,7 @@ be raised as a separate event. - `FeatureNotAvailable(key, actionType)` - The storage feature is not available - `Unspecified(key, actionType, message)` - An unknown error -### `AssetEvent`s +### AssetEvents These are the low level events used to load additional assets at runtime. If you want a slightly more sophisticated loading experience, please look at the asset bundle loader sub system. diff --git a/indigo/docs/gameloop/frame-context.md b/indigo/docs/03-gameloop/frame-context.md similarity index 91% rename from indigo/docs/gameloop/frame-context.md rename to indigo/docs/03-gameloop/frame-context.md index 141b40e34..be1a3e9c4 100644 --- a/indigo/docs/gameloop/frame-context.md +++ b/indigo/docs/03-gameloop/frame-context.md @@ -1,7 +1,4 @@ ---- -id: frame-context -title: Frame context ---- +# Frame context Updating a frame in Indigo is principally about doing two things: @@ -39,7 +36,7 @@ The problem is that `Random` goes against our referential transparency principle > Side note: Testing this kind of behavior with property based testing techniques works very well and often neatly side steps the issue of unknown values. -Similar problems occur if you attempt to implement [frame independence](/docs/information/glossary#frame-independence) based on the elapsed time. You could add a last updated field to Bob's model and use `System.currentTimeMillis` to get the delta, but again, how would you write a test for that. +Similar problems occur if you attempt to implement [frame independence](/10-information/glossary.md) based on the elapsed time. You could add a last updated field to Bob's model and use `System.currentTimeMillis` to get the delta, but again, how would you write a test for that. The problem is that `Random` and `System.currentTimeMillis` are side effecting and that makes them hard to test. diff --git a/indigo/docs/gameloop/outcome.md b/indigo/docs/03-gameloop/outcome.md similarity index 99% rename from indigo/docs/gameloop/outcome.md rename to indigo/docs/03-gameloop/outcome.md index 604b35660..4453a81a0 100644 --- a/indigo/docs/gameloop/outcome.md +++ b/indigo/docs/03-gameloop/outcome.md @@ -1,7 +1,4 @@ ---- -id: outcome -title: Outcome Type ---- +# Outcome Type ## What is an Outcome? diff --git a/indigo/docs/organisation/boot-and-start-up.md b/indigo/docs/04-organisation/boot-and-start-up.md similarity index 98% rename from indigo/docs/organisation/boot-and-start-up.md rename to indigo/docs/04-organisation/boot-and-start-up.md index 58f58dd63..ec33ed045 100644 --- a/indigo/docs/organisation/boot-and-start-up.md +++ b/indigo/docs/04-organisation/boot-and-start-up.md @@ -1,7 +1,4 @@ ---- -id: boot-and-start-up -title: Boot & Start Up ---- +# Boot & Start Up > Please note that the terms "start up" and "setup" are used interchangeably here. "Startup" is the name of the data type, while "setup" is the name of the method. This naming should probably be revisited... @@ -10,7 +7,7 @@ In order to get your game up and running, it needs to go through an initializati 1. Boot - which only ever happens once; 2. Start up - which occurs on first run, and then whenever new assets are loaded dynamically. -A lot of what this process relates to is the loading and processing of assets, so it's worth [reading up on that too](platform/assets.md). +A lot of what this process relates to is the loading and processing of assets, so it's worth [reading up on that too](/05-platform/assets.md). ## Booting your game @@ -83,7 +80,7 @@ IndigoGame.halt(); Calling `halt` does not clean up your page in any way, the assumption is that you will remove the relevant HTML dom nodes. -#### BootResult[_] +#### BootResult In a simple game, all of your animations, fonts, subsystems, shaders, and assets can be declared during the boot stage. For more complex games, such as ones that have a pre-loader, you should only include the elements you need for the preloader scene here. diff --git a/indigo/docs/04-organisation/directory.conf b/indigo/docs/04-organisation/directory.conf new file mode 100644 index 000000000..2b1bc5a51 --- /dev/null +++ b/indigo/docs/04-organisation/directory.conf @@ -0,0 +1 @@ +laika.title = Organisation diff --git a/indigo/docs/organisation/game-entry-points.md b/indigo/docs/04-organisation/game-entry-points.md similarity index 97% rename from indigo/docs/organisation/game-entry-points.md rename to indigo/docs/04-organisation/game-entry-points.md index 97d527304..74189fab6 100644 --- a/indigo/docs/organisation/game-entry-points.md +++ b/indigo/docs/04-organisation/game-entry-points.md @@ -1,7 +1,4 @@ ---- -id: game-entry-points -title: Game Entry Points ---- +# Game Entry Points Entry points are typically traits that you extend in order to write your game, and they provide the basic structure that you need to adhere to, to make a game that Indigo understands. What they actually do underneath is provide a user friendly way to build the frame processor and start the engine that does all of the work. diff --git a/indigo/docs/organisation/scene-management.md b/indigo/docs/04-organisation/scene-management.md similarity index 100% rename from indigo/docs/organisation/scene-management.md rename to indigo/docs/04-organisation/scene-management.md diff --git a/indigo/docs/organisation/subsystems.md b/indigo/docs/04-organisation/subsystems.md similarity index 98% rename from indigo/docs/organisation/subsystems.md rename to indigo/docs/04-organisation/subsystems.md index e815703e4..790d3d87c 100644 --- a/indigo/docs/organisation/subsystems.md +++ b/indigo/docs/04-organisation/subsystems.md @@ -23,8 +23,8 @@ final case class PointsTrackerExample(startingPoints: Int) extends SubSystem: val id: SubSystemId = SubSystemId("points tracker") val eventFilter: GlobalEvent => Option[PointsTrackerEvent] = { - case e: PointsTrackerEvent => Option(e) - case _ => None + case e: PointsTrackerEvent @unchecked => Option(e) + case _ => None } def initialModel: Outcome[Int] = diff --git a/indigo/docs/platform/assets.md b/indigo/docs/05-platform/assets.md similarity index 99% rename from indigo/docs/platform/assets.md rename to indigo/docs/05-platform/assets.md index ec6fabee8..e35352b90 100644 --- a/indigo/docs/platform/assets.md +++ b/indigo/docs/05-platform/assets.md @@ -1,7 +1,4 @@ ---- -id: assets -title: Assets & Asset Loading ---- +# Assets & Asset Loading ## Asset Types diff --git a/indigo/docs/platform/cross-platform-publishing.md b/indigo/docs/05-platform/cross-platform-publishing.md similarity index 98% rename from indigo/docs/platform/cross-platform-publishing.md rename to indigo/docs/05-platform/cross-platform-publishing.md index e0500487b..8c9d41db3 100644 --- a/indigo/docs/platform/cross-platform-publishing.md +++ b/indigo/docs/05-platform/cross-platform-publishing.md @@ -1,7 +1,4 @@ ---- -id: cross-platform-publishing -title: Cross Platform Publishing ---- +# Cross Platform Publishing Indigo supports basic publishing to/building for the following platforms: diff --git a/indigo/docs/05-platform/directory.conf b/indigo/docs/05-platform/directory.conf new file mode 100644 index 000000000..fc37445bb --- /dev/null +++ b/indigo/docs/05-platform/directory.conf @@ -0,0 +1 @@ +laika.title = "Platform & IO" diff --git a/indigo/docs/platform/importers.md b/indigo/docs/05-platform/importers.md similarity index 98% rename from indigo/docs/platform/importers.md rename to indigo/docs/05-platform/importers.md index 1b1d05702..04d906252 100644 --- a/indigo/docs/platform/importers.md +++ b/indigo/docs/05-platform/importers.md @@ -1,7 +1,4 @@ ---- -id: importers -title: File Format Importers ---- +# File Importers At the time of writing, Indigo has limited support for importing data from Aseprite and Tiled. The support that has been added was built on an "as needed" basis, and is far from complete. diff --git a/indigo/docs/platform/input-handling.md b/indigo/docs/05-platform/input-handling.md similarity index 96% rename from indigo/docs/platform/input-handling.md rename to indigo/docs/05-platform/input-handling.md index 8691f4fdb..3cad7dbe7 100644 --- a/indigo/docs/platform/input-handling.md +++ b/indigo/docs/05-platform/input-handling.md @@ -1,7 +1,4 @@ ---- -id: input-handling -title: User Input Handling ---- +# Input Handling At the time of writing, Indigo understands three input device types: Mouse, Keyboard, and Gamepad. @@ -20,7 +17,7 @@ There are input actions that are best represented as events, a mouse click for e Input events only (currently) cover Mouse and Keyboard events, _not gamepads_, and can be detected during the model or view model update functions as you would any other event. -For more information, please see the [events](gameloop/events.md) page. +For more information, please see the [events](/03-gameloop/events.md) page. ## InputState (Continuous signals) @@ -28,7 +25,7 @@ There are other types of input that don't make as much sense as events. It is possible in Indigo to listen to every distinct mouse move event for example, but that is almost certainly not what you actually want to do. Most likely, what you really want is the cumulative position at the point that this frame is being processed. -Indigo does this by sampling the input states of the mouse, keyboard and gamepad and allowing you to access it through the [frame context](gameloop/frame-context.md). +Indigo does this by sampling the input states of the mouse, keyboard and gamepad and allowing you to access it through the [frame context](/03-gameloop/frame-context.md). > Note that this is how gamepads are usually modeled and at the moment Indigo is no exception. Adding discrete events for specific button presses to emulate mouse-like behavior is under consideration. diff --git a/indigo/docs/platform/loading-and-saving-data.md b/indigo/docs/05-platform/loading-and-saving-data.md similarity index 79% rename from indigo/docs/platform/loading-and-saving-data.md rename to indigo/docs/05-platform/loading-and-saving-data.md index 0a09def64..32c54c804 100644 --- a/indigo/docs/platform/loading-and-saving-data.md +++ b/indigo/docs/05-platform/loading-and-saving-data.md @@ -1,7 +1,4 @@ ---- -id: loading-and-saving-data -title: Loading & Saving Data ---- +# Loading & Saving Data Sooner or later, you're probably going to need to load data into your game or save user data. @@ -9,7 +6,7 @@ Sooner or later, you're probably going to need to load data into your game or sa When you think of loading and saving, probably the first thing that comes to mind is save games. -Currently Indigo's local storage options are a bit limited, but what you can do is [storage events](/docs/gameloop/events#storageevents). +Currently Indigo's local storage options are a bit limited, but what you can do is [storage events](/03-gameloop/events.md#storageevents). Storage events use your browsers local storage, which you can think of like a key value store. You process might be: @@ -22,11 +19,11 @@ Storage events use your browsers local storage, which you can think of like a ke ### Loading local data -You can always load data in plain text format (that could be JSON or CSV for example), by using making use of the [asset loading](/docs/platform/assets#asset-loading) functionality. This allows you to dynamically load a data file at any time, process it, and apply it to you model. +You can always load data in plain text format (that could be JSON or CSV for example), by using making use of the [asset loading](/05-platform/assets.md#asset-loading) functionality. This allows you to dynamically load a data file at any time, process it, and apply it to you model. ### Loading and saving over a network -The other way to load and save data might be over a network, please see the [networking page for details](platform/networking.md). +The other way to load and save data might be over a network, please see the [networking page for details](/05-platform/networking.md). Similar to the save game flow, you might do something like: diff --git a/indigo/docs/platform/logging.md b/indigo/docs/05-platform/logging.md similarity index 97% rename from indigo/docs/platform/logging.md rename to indigo/docs/05-platform/logging.md index 1ba4e9deb..866b5a3ca 100644 --- a/indigo/docs/platform/logging.md +++ b/indigo/docs/05-platform/logging.md @@ -1,7 +1,4 @@ ---- -id: logging -title: Logging ---- +# Logging Sometimes you need a log message to help you debug something, and to help you do that Indigo comes with a very simple / border-line dumb logger. diff --git a/indigo/docs/platform/networking.md b/indigo/docs/05-platform/networking.md similarity index 92% rename from indigo/docs/platform/networking.md rename to indigo/docs/05-platform/networking.md index 6d079385d..170992d9e 100644 --- a/indigo/docs/platform/networking.md +++ b/indigo/docs/05-platform/networking.md @@ -1,7 +1,4 @@ ---- -id: networking -title: Networking ---- +# Networking Indigo supports basic networking via HTTP or WebSockets. You can also get a rudimentary indication as to whether the local machine has an active network @@ -16,8 +13,8 @@ JavaScript handles network calls via callbacks and promises, but that doesn't fi Therefore, what we have is a side-effecting networking system inside Indigo which you communicate with via the normal event loop. If you want to send an HTTP request you emit a `GET(url, params, headers)` event, and at the beginning of some future frame, hopefully you'll get an `HttpResponse(status, headers, body)`. WebSockets work in a similar way but are complicated by having more states. -For a complete list of network events, please head over the the [events documentation](gameloop/events.md). +For a complete list of network events, please head over the the [events documentation](/03-gameloop/events.md). We have examples of networking in our indigo-examples repo, of both [HTTP](https://github.com/PurpleKingdomGames/indigo-examples/blob/master/examples/http/src/main/scala/indigoexamples/HttpExample.scala) and [WebSockets](https://github.com/PurpleKingdomGames/indigo-examples/blob/master/examples/websocket/src/main/scala/indigoexamples/WebSocketExample.scala). -The examples make use of buttons which you can find out about on the [UI Components](presentation/ui-components.md) page. +The examples make use of buttons which you can find out about on the [UI Components](/09-uicomponents/ui-components.md) page. diff --git a/indigo/docs/presentation/animation.md b/indigo/docs/06-presentation/animation.md similarity index 99% rename from indigo/docs/presentation/animation.md rename to indigo/docs/06-presentation/animation.md index 5bdd6f819..0f3841bc7 100644 --- a/indigo/docs/presentation/animation.md +++ b/indigo/docs/06-presentation/animation.md @@ -1,7 +1,4 @@ ---- -id: animation -title: Animation ---- +# Animation There are two types of animations found in Indigo. diff --git a/indigo/docs/presentation/audio.md b/indigo/docs/06-presentation/audio.md similarity index 96% rename from indigo/docs/presentation/audio.md rename to indigo/docs/06-presentation/audio.md index 4b9e0abb1..2de1fbeff 100644 --- a/indigo/docs/presentation/audio.md +++ b/indigo/docs/06-presentation/audio.md @@ -1,7 +1,4 @@ ---- -id: audio -title: Audio ---- +# Audio Indigo's audio support is fairly unsophisticated, but probably good enough for the kind of games Indigo was designed for. The authors are not audio experts, please feel free to raise issues if you have any suggestions for improvements. @@ -14,7 +11,7 @@ There are two kinds of audio support in Indigo: Indigo uses web technologies, so you should refer to current recommended practices for audio formats. That being said, anything a browser will play Indigo will play, and most of the existing demos and examples just use MP3 files, but that is a fairly dated format these days. -Please refer to the assets documentation for information on [how to load audio files](platform/assets.md). +Please refer to the assets documentation for information on [how to load audio files](/05-platform/assets.md). ## Sound effects diff --git a/indigo/docs/presentation/boundaries.md b/indigo/docs/06-presentation/boundaries.md similarity index 98% rename from indigo/docs/presentation/boundaries.md rename to indigo/docs/06-presentation/boundaries.md index b45d167a8..a6e12b726 100644 --- a/indigo/docs/presentation/boundaries.md +++ b/indigo/docs/06-presentation/boundaries.md @@ -1,7 +1,4 @@ ---- -id: boundaries -title: Boundaries ---- +# Boundaries A curious quirk of the way Indigo works is that it seems unusual to need to find the boundary / bounding box of a rendered element. Usually you are telling something how big it needs to be rather than asking it how big or small it actually is. diff --git a/indigo/docs/presentation/cameras.md b/indigo/docs/06-presentation/cameras.md similarity index 99% rename from indigo/docs/presentation/cameras.md rename to indigo/docs/06-presentation/cameras.md index 73552e631..5535a5f5e 100644 --- a/indigo/docs/presentation/cameras.md +++ b/indigo/docs/06-presentation/cameras.md @@ -1,7 +1,4 @@ ---- -id: cameras -title: Cameras ---- +# Cameras When you look at a scene rendered by Indigo, you are looking through a default camera. diff --git a/indigo/docs/presentation/clones-and-mutants.md b/indigo/docs/06-presentation/clones-and-mutants.md similarity index 94% rename from indigo/docs/presentation/clones-and-mutants.md rename to indigo/docs/06-presentation/clones-and-mutants.md index 6816525f7..166312996 100644 --- a/indigo/docs/presentation/clones-and-mutants.md +++ b/indigo/docs/06-presentation/clones-and-mutants.md @@ -1,9 +1,4 @@ ---- -id: clones-and-mutants -title: Clones & Mutants ---- - -> Available in the forthcoming Indigo 0.10.0 only. There were earlier versions of Clones but they were never documented properly and they've all been superseded. +# Clones & Mutants Sometimes you really need to draw a lot of things. Thousands and thousands of things. @@ -127,7 +122,7 @@ Mutants( Array( Batch( UniformBlock( - "MutantData", + UniformBlockName("MutantData"), Batch( Uniform("MOVE_TO") -> vec2(10.0, 10.0), Uniform("SCALE_TO") -> vec2(2.0, 2.0), @@ -139,7 +134,7 @@ Mutants( ) ``` -The idea here is that you have [created a custom entity](guides/howto-custom-entity.md) and for each instance, you want to set it's UBO data, which here contains a position, a scale and an alpha value. +The idea here is that you have [created a custom entity](/02-guides/howto-custom-entity.md) and for each instance, you want to set it's UBO data, which here contains a position, a scale and an alpha value. In many ways the important part of this example is the alpha. If you only wanted to position the entities you be far better off with one of the clone types. The whole point is that you also plan to programmatically influence the visual rendering of the entity in some way. @@ -197,4 +192,4 @@ void fragment(){ // ``` -The fragment shader takes the default texture channel and applies the supplied alpha to it. Note the use of [premultiplied alpha](shaders/premultiplied-alpha.md). +The fragment shader takes the default texture channel and applies the supplied alpha to it. Note the use of [premultiplied alpha](/07-shaders/premultiplied-alpha.md). diff --git a/indigo/docs/presentation/depth.md b/indigo/docs/06-presentation/depth.md similarity index 97% rename from indigo/docs/presentation/depth.md rename to indigo/docs/06-presentation/depth.md index 93483b9b7..e5e15e466 100644 --- a/indigo/docs/presentation/depth.md +++ b/indigo/docs/06-presentation/depth.md @@ -1,12 +1,7 @@ ---- -id: depth -title: Depth ---- +# Depth One thing you will need to consider when building your game, is the order that visual elements are drawn in. -## Depth - Depth is quite straight forward. All visual elements can be given a `Depth`, which is just a number. Zero is right in front of the camera, and bigger numbers are further away. It makes sense if you think in terms of "I am the camera and it's further away from me, so it's a bigger number". diff --git a/indigo/docs/06-presentation/directory.conf b/indigo/docs/06-presentation/directory.conf new file mode 100644 index 000000000..86f651ed3 --- /dev/null +++ b/indigo/docs/06-presentation/directory.conf @@ -0,0 +1 @@ +laika.title = Presentation diff --git a/indigo/docs/presentation/layers.md b/indigo/docs/06-presentation/layers.md similarity index 97% rename from indigo/docs/presentation/layers.md rename to indigo/docs/06-presentation/layers.md index c7c804e08..103952d31 100644 --- a/indigo/docs/presentation/layers.md +++ b/indigo/docs/06-presentation/layers.md @@ -1,7 +1,4 @@ ---- -id: layers -title: Layers ---- +# Layers Layers are used to help "layer up" and group the visual elements of your scene. @@ -132,7 +129,7 @@ There are some properties that layers have that can be used to override game or If you've ever used a photo editing software you're probably aware that layers can be used to alter the appearance of the image, say by sucking the colour out and turning it black and white. Indigo layers can do the same sorts of thing, however there are only a few built in Blending options currently, and for anything more advanced you'll need to roll up your sleeves and write your own blending functions! -You can read more about this subject in the [blending section of the docs](shaders/blending.md), but in a nutshell a `Blending` instance is comprised of two things: +You can read more about this subject in the [blending section of the docs](/07-shaders/blending.md), but in a nutshell a `Blending` instance is comprised of two things: 1. `BlendMode` - this is the hardware blend function 2. `BlendMaterial` - which is a material backed by a special shader specifically for blending. diff --git a/indigo/docs/presentation/lighting.md b/indigo/docs/06-presentation/lighting.md similarity index 93% rename from indigo/docs/presentation/lighting.md rename to indigo/docs/06-presentation/lighting.md index 50cbd41f6..a42d25e1a 100644 --- a/indigo/docs/presentation/lighting.md +++ b/indigo/docs/06-presentation/lighting.md @@ -1,7 +1,4 @@ ---- -id: lighting -title: Lighting ---- +# Lighting Lighting in Indigo is in every sense of the word, fake. It was not designed to try and mimic real light, but to be useful and understandable to 2D game builders who were trying to add some interest to their games through lighting. @@ -30,7 +27,7 @@ This sort of effect is very useful for drawing things like the light from a stre Indigo comes bundled with shaders you can use to produce image based lighting. These shaders do not make use of any special machinery, and so you can always write your own versions if you like! -Imaged based lighting in Indigo is all about the [blending](shaders/blending.md). +Imaged based lighting in Indigo is all about the [blending](/07-shaders/blending.md). There are two blending jobs to do: @@ -109,7 +106,7 @@ AmbientLight(RGBA.White.withAlpha(0.2)) ### Materials for Dynamic Lighting -Dynamic lighting only affects [materials](presentation/materials.md) that can be lit, i.e. have a lighting model, and the material properties affect what happens when the light hits them. +Dynamic lighting only affects [materials](/06-presentation/materials.md) that can be lit, i.e. have a lighting model, and the material properties affect what happens when the light hits them. Lighting models are either: `Unlit` or `Lit`, and if they are either textured or 'flat'. For example a `Shape` can be lit, but is always flat since there are no textures. @@ -127,4 +124,4 @@ A note on emissive materials: 1. In a real 3D engine, an emissive material might also affect the colors of surrounding surfaces. Indigo does not do that. 2. Emissive materials are ignored by image based lighting. -More information on the main [materials](presentation/materials.md) page. +More information on the main [materials](/06-presentation/materials.md) page. diff --git a/indigo/docs/presentation/materials.md b/indigo/docs/06-presentation/materials.md similarity index 99% rename from indigo/docs/presentation/materials.md rename to indigo/docs/06-presentation/materials.md index 3b60b8473..84c0cb6cb 100644 --- a/indigo/docs/presentation/materials.md +++ b/indigo/docs/06-presentation/materials.md @@ -1,7 +1,4 @@ ---- -id: materials -title: Materials ---- +# Materials Indigo is intended to be a pixel art based game engine, and that means drawing pixels! diff --git a/indigo/docs/presentation/primitives.md b/indigo/docs/06-presentation/primitives.md similarity index 98% rename from indigo/docs/presentation/primitives.md rename to indigo/docs/06-presentation/primitives.md index dc35c746d..c14fc01f3 100644 --- a/indigo/docs/presentation/primitives.md +++ b/indigo/docs/06-presentation/primitives.md @@ -1,7 +1,4 @@ ---- -id: primitives -title: Primitives & Building Blocks ---- +# Primitives & Building Blocks Indigo is made of several projects, but two of particular note are Indigo itself, and "Indigo Extras". diff --git a/indigo/docs/presentation/scene-update-fragment.md b/indigo/docs/06-presentation/scene-update-fragment.md similarity index 94% rename from indigo/docs/presentation/scene-update-fragment.md rename to indigo/docs/06-presentation/scene-update-fragment.md index e465142dc..8d113b178 100644 --- a/indigo/docs/presentation/scene-update-fragment.md +++ b/indigo/docs/06-presentation/scene-update-fragment.md @@ -1,7 +1,4 @@ ---- -id: scene-update-fragment -title: SceneUpdateFragment ---- +# SceneUpdateFragment The `SceneUpdateFragment` is one of the most important types in Indigo, as it is the type that describes everything you want your player to experience. @@ -90,6 +87,6 @@ The `SceneUpdateFragment` has a fairly rich API that you can explore, but at a h - **Layers**: A list of [layers](layers.md) to help structure your visuals and how they are presented. - **Lights**: A list of dynamic [lights](lighting.md) that affect nodes with the right materials. - **Audio**: Background [audio](audio.md) tracks and volume mixing. -- **A scene blend material**: Used in [blending](shaders/blending.md), unlike layers you cannot change the blend mode, only the blend material. +- **A scene blend material**: Used in [blending](/07-shaders/blending.md), unlike layers you cannot change the blend mode, only the blend material. - **Clone blanks**: A list of nodes used as look up reference for Cloning. -- **Scene Camera**: A default [camera](camera.md). +- **Scene Camera**: A default [camera](cameras.md). diff --git a/indigo/docs/presentation/shapes.md b/indigo/docs/06-presentation/shapes.md similarity index 88% rename from indigo/docs/presentation/shapes.md rename to indigo/docs/06-presentation/shapes.md index 841e03b32..a59ddbbea 100644 --- a/indigo/docs/presentation/shapes.md +++ b/indigo/docs/06-presentation/shapes.md @@ -1,16 +1,13 @@ ---- -id: shapes -title: Shapes ---- +# Shapes Shapes allow you to draw simple graphics without needing images. There are four `Shape` types that come shipped with Indigo at the time of writing, although we may add more in the future: 1. `Shape.Box` - Any rectangle -1. `Shape.Circle` - A circle centered around a point -1. `Shape.Line` - A straight line made of two points -1. `Shape.Polygon` - An arbitrary shape with up to 16 vertices. +2. `Shape.Circle` - A circle centered around a point +3. `Shape.Line` - A straight line made of two points +4. `Shape.Polygon` - An arbitrary shape with up to 16 vertices. They all share similar properties: diff --git a/indigo/docs/presentation/text-and-fonts.md b/indigo/docs/06-presentation/text-and-fonts.md similarity index 98% rename from indigo/docs/presentation/text-and-fonts.md rename to indigo/docs/06-presentation/text-and-fonts.md index 6ed1c1541..2d343c729 100644 --- a/indigo/docs/presentation/text-and-fonts.md +++ b/indigo/docs/06-presentation/text-and-fonts.md @@ -1,12 +1,9 @@ ---- -id: text-and-fonts -title: Text & Fonts ---- +# Text & Fonts There are two way to add text in Indigo, each with their own set of trade offs. 1. `TextBox` - is text as you'd expect it, easy to use and with full font support, but is generally lower quality. -1. `Text` - is a graphical primitive that gives high rendering fidelity but requires a lot of set up. +2. `Text` - is a graphical primitive that gives high rendering fidelity but requires a lot of set up. If you're new to Indigo and just want to get some text on the screen quickly, you are strongly advised to use a `TextBox`. diff --git a/indigo/docs/shaders/blending.md b/indigo/docs/07-shaders/blending.md similarity index 96% rename from indigo/docs/shaders/blending.md rename to indigo/docs/07-shaders/blending.md index 682ee40cd..17a137f72 100644 --- a/indigo/docs/shaders/blending.md +++ b/indigo/docs/07-shaders/blending.md @@ -1,7 +1,4 @@ ---- -id: blending -title: Blending ---- +# Blending Once you've told Indigo what you'd like your entity to look like, perhaps with a standard material or a custom shader, you then need to tell Indigo how to blend it into you game's scene. This allows you to describe scene level effects. @@ -20,7 +17,7 @@ The two main building blocks of the blending process are: Blend modes are hardware level functions with limited but important options. They instruct the graphics card on fundamentally how to combine two pixels together. -Explaining blend modes is beyond the scope of this guide, and there are many tutorials available, but as an example, we can compare Indigo's standard entity blend mode with it's entity lighting blend mode (used in image based [lighting](presentation/lighting.md)): +Explaining blend modes is beyond the scope of this guide, and there are many tutorials available, but as an example, we can compare Indigo's standard entity blend mode with it's entity lighting blend mode (used in image based [lighting](/06-presentation/lighting.md)): ```scala mdoc:js:shared import indigo.* @@ -67,7 +64,7 @@ Blending the final scene is less fine grained, and a `SceneUpdateFragment` can o ## Example: Lighting -Here is the `Blending` description for Indigo's image based [lighting](presentation/lighting.md). +Here is the `Blending` description for Indigo's image based [lighting](/06-presentation/lighting.md). ```scala mdoc:js val ambientLightColor = RGBA.White.withAlpha(0.25) diff --git a/indigo/docs/shaders/constants.md b/indigo/docs/07-shaders/constants.md similarity index 99% rename from indigo/docs/shaders/constants.md rename to indigo/docs/07-shaders/constants.md index 53958bbc3..6ce748278 100644 --- a/indigo/docs/shaders/constants.md +++ b/indigo/docs/07-shaders/constants.md @@ -1,7 +1,4 @@ ---- -id: constants -title: Shader Constants, Variables, and Outputs ---- +# Shader Constants, Variables, and Outputs Below are tables of shader constants and variables that are available to you, provided by Indigo, when writing shaders for the WebGL 2.0 renderer. diff --git a/indigo/docs/07-shaders/directory.conf b/indigo/docs/07-shaders/directory.conf new file mode 100644 index 000000000..a32e4d6a8 --- /dev/null +++ b/indigo/docs/07-shaders/directory.conf @@ -0,0 +1 @@ +laika.title = Shaders diff --git a/indigo/docs/shaders/premultiplied-alpha.md b/indigo/docs/07-shaders/premultiplied-alpha.md similarity index 95% rename from indigo/docs/shaders/premultiplied-alpha.md rename to indigo/docs/07-shaders/premultiplied-alpha.md index 64c59cbc5..62df47550 100644 --- a/indigo/docs/shaders/premultiplied-alpha.md +++ b/indigo/docs/07-shaders/premultiplied-alpha.md @@ -1,7 +1,4 @@ ---- -id: premultiplied-alpha -title: Premultiplied Alpha ---- +# Premultiplied Alpha A small but essential piece of information to know when writing shaders in Indigo, is that Indigo uses premultiplied alpha almost everywhere, with the notable exception of Shapes. diff --git a/indigo/docs/shaders/shader-overview.md b/indigo/docs/07-shaders/shaders-overview.md similarity index 81% rename from indigo/docs/shaders/shader-overview.md rename to indigo/docs/07-shaders/shaders-overview.md index f740cd8bf..246873ea1 100644 --- a/indigo/docs/shaders/shader-overview.md +++ b/indigo/docs/07-shaders/shaders-overview.md @@ -1,7 +1,6 @@ ---- -id: shader-overview -title: Shaders Overview ---- +# Shaders Overview + +> Please be aware that these docs are out of date, as they do not yet include information about Ultraviolet, our shader library. ## What is a shader? @@ -15,15 +14,15 @@ Shaders are a big subject and beyond the scope of this documentation site, the a ## How to get started with Shaders -There is a brief introduction to using shaders in your project as part of the ["how to create a custom entity"](guides/howto-custom-entity.md) guide that we recommend you read first, which also has an accompanying [example repo](https://github.com/PurpleKingdomGames/indigo-examples/tree/master/howto/custom-entity). +There is a brief introduction to using shaders in your project as part of the ["how to create a custom entity"](/02-guides/howto-custom-entity.md) guide that we recommend you read first, which also has an accompanying [example repo](https://github.com/PurpleKingdomGames/indigo-examples/tree/master/howto/custom-entity). -There is a follow on tutorial to the one above than explains [how to make a fire shader](guides/howto-fire-shader.md) that you may also find useful. +There is a follow on tutorial to the one above than explains [how to make a fire shader](/02-guides/howto-fire-shader.md) that you may also find useful. ## Entity vs Blend Shaders Indigo has two distinct flavours of shader. -1. [Entity shaders](entity-shaders.md) are used to draw individual items / entities on the screen. +1. `Entity shaders` are used to draw individual items / entities on the screen. 2. Blend shaders are used in the [blending process](blending.md) to tell Indigo how to merge layers together. They both work in a similar way, but there are differences. @@ -53,13 +52,13 @@ void fragment(){} **Function uses** -Name|Sequential order|description ----|---|--- -`vertex`|1|Used to modify the space on the screen the entity occupies, and to pass data to the fragment shader. -`fragment`|2|Tells Indigo what color each pixel needs to be. -`prepare`|3|Called before `light`, prepare gives you an opportunity to set up any data or functions needed for the lighting process. -`light`|4..4n|Called before `composite`, `light` is called once per light in the scene, and is used to build up per pixel lighting data separate from the colour data that results from `fragment`. -`composite`|5|Called last, `composite` is used to override how lighting information is combined with unlit pixel color data. +| Name | Sequential order | description | +| ----------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `vertex` | 1 | Used to modify the space on the screen the entity occupies, and to pass data to the fragment shader. | +| `fragment` | 2 | Tells Indigo what color each pixel needs to be. | +| `prepare` | 3 | Called before `light`, prepare gives you an opportunity to set up any data or functions needed for the lighting process. | +| `light` | 4..4n | Called before `composite`, `light` is called once per light in the scene, and is used to build up per pixel lighting data separate from the colour data that results from `fragment`. | +| `composite` | 5 | Called last, `composite` is used to override how lighting information is combined with unlit pixel color data. | To override a function you simply need to declare it. In an `Source` shader type, this could be done as follows: @@ -168,7 +167,7 @@ Finally we need to tell Indigo about these shaders, or we won't be able to use t ## Using shaders in your scene -Custom shaders are generally expected to be used in conjunction with custom entities, please see the [guide](guides/howto-custom-entity.md) for examples. +Custom shaders are generally expected to be used in conjunction with custom entities, please see the [guide](/02-guides/howto-custom-entity.md) for examples. You can also use custom shaders to override the behavior of built-in materials. Technically this is as easy as replacing the `shaderId: Option[ShaderId]` field on the material with the id of your own shader, but you will need to look into the source code to determine data that material provides to the shader. @@ -176,7 +175,7 @@ You can also use custom shaders to override the behavior of built-in materials. Shaders without any data can still be useful if you have a known effect, and not sending data is less costly than sending it! However, sometimes you need to tell your shader about what you need it to do, and for that we use `UniformBlock`s (know as UBO's technically, Uniform Buffer Objects). -In the [guide](guides/howto-custom-entity.md), we create a custom entity that fills it's self with a solid color: +In the [guide](/02-guides/howto-custom-entity.md), we create a custom entity that fills it's self with a solid color: ```scala mdoc:js final case class MyColoredEntity(position: Point, depth: Depth) extends EntityNode[MyColoredEntity]: @@ -230,7 +229,7 @@ final case class MyColoredEntity(position: Point, depth: Depth, color: RGBA) ext ShaderData( MyColoredEntity.shader.id, UniformBlock( - "MyCustomData", + UniformBlockName("MyCustomData"), Batch(Uniform("MY_COLOR") -> vec4(color.r, color.g, color.b, color.a)) ) ) @@ -290,3 +289,4 @@ You also can't straddle byte boundries. So if you're trying to pack this: Float- This is valid: F0VV But this isn't: FVV0 ``` + diff --git a/indigo/docs/08-time/directory.conf b/indigo/docs/08-time/directory.conf new file mode 100644 index 000000000..c86c4567d --- /dev/null +++ b/indigo/docs/08-time/directory.conf @@ -0,0 +1 @@ +laika.title = Time diff --git a/indigo/docs/08-time/gametime.md b/indigo/docs/08-time/gametime.md new file mode 100644 index 000000000..eb42554b7 --- /dev/null +++ b/indigo/docs/08-time/gametime.md @@ -0,0 +1,11 @@ +# GameTime + +The most important thing to know is what time it is now! This can by found on the [frame context](/03-gameloop/frame-context.md), which provides two important different time representations: + +1. `running` - which is the time the game has been running for in total. +2. `delta` - which is how long has passed since the last update, which is important for smooth updates and animations. + +Both are represented as `Second`s. + +The `Scene` version of frame context objects additionally provide information about the running time of the particular scene you are in, and when the scene was last changed. + diff --git a/indigo/docs/time/signals.md b/indigo/docs/08-time/signals.md similarity index 99% rename from indigo/docs/time/signals.md rename to indigo/docs/08-time/signals.md index c27dad765..5854afd0a 100644 --- a/indigo/docs/time/signals.md +++ b/indigo/docs/08-time/signals.md @@ -1,7 +1,4 @@ ---- -id: signals -title: Signals & Signal Functions ---- +# Signals & Signal Functions ## Motivation diff --git a/indigo/docs/time/time-varying-values.md b/indigo/docs/08-time/time-varying-values.md similarity index 97% rename from indigo/docs/time/time-varying-values.md rename to indigo/docs/08-time/time-varying-values.md index e4f5cb9e5..89993ef64 100644 --- a/indigo/docs/time/time-varying-values.md +++ b/indigo/docs/08-time/time-varying-values.md @@ -1,7 +1,4 @@ ---- -id: time-varying-values -title: Time Varying Values ---- +# Time Varying Values Time varying values describe numeric values (`Double`s) that will change over time. They are supposed to live in your game model to help you do simple time based updates. diff --git a/indigo/docs/uicomponents/button.md b/indigo/docs/09-uicomponents/button.md similarity index 89% rename from indigo/docs/uicomponents/button.md rename to indigo/docs/09-uicomponents/button.md index 418d629d9..2905cf90f 100644 --- a/indigo/docs/uicomponents/button.md +++ b/indigo/docs/09-uicomponents/button.md @@ -1,7 +1,4 @@ ---- -id: button -title: Buttons ---- +# Buttons The out-of-the-box button is created out of three graphics that represent the up, over, and down states. Aside from handling the button's state, the main advantage of using the button component is that it's easier to to define interactions. Rather than pattern matching on a click event at the top of your update function, and then deciding whether the click happened inside the button or not, you can just define you button as follows and it will do the rest for you, once it has been wired in: @@ -72,7 +69,7 @@ for { } yield updatedViewModel ``` -First we have to update the button, which is done by calling the buttons's built in update method and supplying the current state of the mouse on this frame. The button update returns an [`Outcome`](gameloop/outcome.md) because as well as containing a freshly updated button, it can also return events that will need to be collected at the end of the frame. Since we need to return an outcome containing an updated view model at the end of the frame, we then need to map over the outcome, and insert the button in the view model. +First we have to update the button, which is done by calling the buttons's built in update method and supplying the current state of the mouse on this frame. The button update returns an [`Outcome`](/03-gameloop/outcome.md) because as well as containing a freshly updated button, it can also return events that will need to be collected at the end of the frame. Since we need to return an outcome containing an updated view model at the end of the frame, we then need to map over the outcome, and insert the button in the view model. ***A word of caution***, you might be tempted to do this instead, which appears to work and compiles just fine: diff --git a/indigo/docs/09-uicomponents/directory.conf b/indigo/docs/09-uicomponents/directory.conf new file mode 100644 index 000000000..69ad03a57 --- /dev/null +++ b/indigo/docs/09-uicomponents/directory.conf @@ -0,0 +1 @@ +laika.title = UI Components diff --git a/indigo/docs/uicomponents/hit-area.md b/indigo/docs/09-uicomponents/hit-area.md similarity index 97% rename from indigo/docs/uicomponents/hit-area.md rename to indigo/docs/09-uicomponents/hit-area.md index 011b837f0..3157a3ab1 100644 --- a/indigo/docs/uicomponents/hit-area.md +++ b/indigo/docs/09-uicomponents/hit-area.md @@ -1,7 +1,4 @@ ---- -id: hit-area -title: Hit Area ---- +# Hit Areas Hit areas are different to the other UI components. diff --git a/indigo/docs/uicomponents/input-field.md b/indigo/docs/09-uicomponents/input-field.md similarity index 97% rename from indigo/docs/uicomponents/input-field.md rename to indigo/docs/09-uicomponents/input-field.md index 23035ac55..1019acb91 100644 --- a/indigo/docs/uicomponents/input-field.md +++ b/indigo/docs/09-uicomponents/input-field.md @@ -1,7 +1,4 @@ ---- -id: input-field -title: Input Field ---- +# Input Fields Input fields are text boxes that all users to type values into them. As with button, you need to provide some assets, specifically font information and a graphic to use as the cursor while a user is inputing values. Indigo's input field is quite basic, but input fields are a bit fiddly to implement. Hopefully it will either save someone some time or be useful as a reference to someone who'd like to do make something more sophisticated. diff --git a/indigo/docs/uicomponents/radio-button.md b/indigo/docs/09-uicomponents/radio-button.md similarity index 98% rename from indigo/docs/uicomponents/radio-button.md rename to indigo/docs/09-uicomponents/radio-button.md index 7dae06041..89fbd30dd 100644 --- a/indigo/docs/uicomponents/radio-button.md +++ b/indigo/docs/09-uicomponents/radio-button.md @@ -1,7 +1,4 @@ ---- -id: radio-button -title: Radio Button ---- +# Radio Buttons Radio buttons are a collection of buttons where only one of them can be in a selected state at any given time, and one must always be selected once an initial selection has been made. No doubt you've seen them on multiple choice forms. diff --git a/indigo/docs/uicomponents/ui-components.md b/indigo/docs/09-uicomponents/ui-components.md similarity index 95% rename from indigo/docs/uicomponents/ui-components.md rename to indigo/docs/09-uicomponents/ui-components.md index 9fca244aa..75c69865c 100644 --- a/indigo/docs/uicomponents/ui-components.md +++ b/indigo/docs/09-uicomponents/ui-components.md @@ -1,7 +1,4 @@ ---- -id: ui-components -title: Overview ---- +# UI Components > UI Components live in the "Indigo Extras" library, since they are built on top of Indigo itself and require no special machinery to work. @@ -9,7 +6,7 @@ UI components are generally the kinds of elements your expect to see in any web Indigo does not provide a large suite of UI Components out of the box although we hope to expand, [see issue for progress](https://github.com/PurpleKingdomGames/indigo/issues/41). This is because _basic_ UI components are not terribly complicated to build on top of Indigo by aspiring game devs, and so have been pushed down the priority list in favor of more fundamental / specialized pieces of functionality. Help is welcome! -> A word of caution about UI components depending on mouse actions: currently, only the left mouse button is supported for the sake of simplicity. But you can always create another UI component allowing the usage of other mouse actions like the right mouse button up or down, as Indigo supports it, along with other mouse buttons actions, as you can see at the [events](gamelooop/events.md) page. +> A word of caution about UI components depending on mouse actions: currently, only the left mouse button is supported for the sake of simplicity. But you can always create another UI component allowing the usage of other mouse actions like the right mouse button up or down, as Indigo supports it, along with other mouse buttons actions, as you can see at the [events](/03-gameloop/events.md) page. ## The Pattern diff --git a/indigo/docs/information/alternatives.md b/indigo/docs/10-information/alternatives.md similarity index 95% rename from indigo/docs/information/alternatives.md rename to indigo/docs/10-information/alternatives.md index d64a7297e..0dfaff533 100644 --- a/indigo/docs/information/alternatives.md +++ b/indigo/docs/10-information/alternatives.md @@ -1,7 +1,4 @@ ---- -id: alternatives -title: Alternatives to Indigo ---- +# Alternatives to Indigo If Indigo isn't quite working out for you - we quite understand! Here are some possible alternatives to help you get your game dev fix. Each of these suggestions has something in common with Indigo, there are of course lots of other engines out there! diff --git a/indigo/docs/information/antipatterns.md b/indigo/docs/10-information/antipatterns.md similarity index 99% rename from indigo/docs/information/antipatterns.md rename to indigo/docs/10-information/antipatterns.md index ab5c11b4e..e0ad1e6d0 100644 --- a/indigo/docs/information/antipatterns.md +++ b/indigo/docs/10-information/antipatterns.md @@ -1,7 +1,4 @@ ---- -id: antipatterns -title: Anti-Patterns ---- +# Anti-Patterns This page is an attempt to flag any anti-patterns, bad practices or traps that the authors have seen in the wild or have themselves fallen into! The hope is that but not repeating these mistakes your game dev'ving will be more fun and fruitful. diff --git a/indigo/docs/10-information/directory.conf b/indigo/docs/10-information/directory.conf new file mode 100644 index 000000000..6b08ee4b4 --- /dev/null +++ b/indigo/docs/10-information/directory.conf @@ -0,0 +1 @@ +laika.title = Misc diff --git a/indigo/docs/information/glossary.md b/indigo/docs/10-information/glossary.md similarity index 93% rename from indigo/docs/information/glossary.md rename to indigo/docs/10-information/glossary.md index 1e2559aa9..8f88517c7 100644 --- a/indigo/docs/information/glossary.md +++ b/indigo/docs/10-information/glossary.md @@ -1,25 +1,22 @@ ---- -id: glossary -title: Glossary ---- +# Glossary -# A +## A ### Automata A type of subsystem used to manage simple autonomous particles. -# B +## B -# C +## C -# D +## D ### Dice A pseudo-random number generator seeded on the current frames running time to facilitate testing and issue reproduction. -# E +## E ### Entry point @@ -29,53 +26,53 @@ The main interface an Indigo game developer is exposed to when trying to write a A description of an action that is emitted during a frame and made available to the subsequent frame, such as a keyboard event. -# F +## F ### Frame Independence Movement that is adjusted to account for the time elapsed between frames in order to proceed at a consistent rate. -# G +## G ### GameTime A sample of the current time provided to every frame. All computations are assumed to happen instantly at the time given. -# H +## H -# I +## I ### InputState The current state of input devices like the keyboard, mouse or game pad. -# J +## J -# K +## K -# L +## L -# M +## M -# N +## N -# O +## O ### Outcome Used to gather state and events that were the result of a frame update. -# P +## P -# Q +## Q -# R +## R ### Referential Transparency The ability to reliably replace a function call and arguments, with the result type and observe no change. -# S +## S ### Scene @@ -101,20 +98,20 @@ A combinator used to manipulate, process, and compose Signals. A small, well encapsulated game that can be combined with the main game. Used to organise sections of you game and to manages tasks and processes in the background. -# T +## T ### Time Varying Value A value that is updated automatically based on some behavior and the time delta between frames. -# U +## U -# V +## V -# W +## W -# X +## X -# Y +## Y -# Z +## Z diff --git a/indigo/docs/information/key-concepts.md b/indigo/docs/10-information/key-concepts.md similarity index 99% rename from indigo/docs/information/key-concepts.md rename to indigo/docs/10-information/key-concepts.md index 77c5f1508..06d1030fe 100644 --- a/indigo/docs/information/key-concepts.md +++ b/indigo/docs/10-information/key-concepts.md @@ -1,7 +1,4 @@ ---- -id: key-concepts -title: Key Concepts ---- +# Key Concepts ## Making a game testable diff --git a/indigo/docs/information/model-viewmodel-view.md b/indigo/docs/10-information/model-viewmodel-view.md similarity index 98% rename from indigo/docs/information/model-viewmodel-view.md rename to indigo/docs/10-information/model-viewmodel-view.md index 013b1cb04..cc5f4fa92 100644 --- a/indigo/docs/information/model-viewmodel-view.md +++ b/indigo/docs/10-information/model-viewmodel-view.md @@ -1,7 +1,4 @@ ---- -id: model-viewmodel-view -title: Model, ViewModel, & View ---- +# Model, ViewModel, & View The standard entry point traits define functions that talk about a `Model`, a `ViewModel`, and a "view" (in the form of a `present` function that returns a `SceneUpdateFragment`). diff --git a/indigo/docs/information/motivation-and-constraints.md b/indigo/docs/10-information/motivation-and-constraints.md similarity index 98% rename from indigo/docs/information/motivation-and-constraints.md rename to indigo/docs/10-information/motivation-and-constraints.md index ff5bb88df..f504efd9d 100644 --- a/indigo/docs/information/motivation-and-constraints.md +++ b/indigo/docs/10-information/motivation-and-constraints.md @@ -1,7 +1,4 @@ ---- -id: motivation-and-constraints -title: Motivation & Constraints ---- +# Motivation & Constraints ## Motivation diff --git a/indigo/docs/information/performance.md b/indigo/docs/10-information/performance.md similarity index 99% rename from indigo/docs/information/performance.md rename to indigo/docs/10-information/performance.md index 6ecb4301a..5fdd2e064 100644 --- a/indigo/docs/information/performance.md +++ b/indigo/docs/10-information/performance.md @@ -1,7 +1,4 @@ ---- -id: performance -title: Performance ---- +# Performance ## What is performance? diff --git a/indigo/docs/information/prior-art.md b/indigo/docs/10-information/prior-art.md similarity index 99% rename from indigo/docs/information/prior-art.md rename to indigo/docs/10-information/prior-art.md index 94a333d1e..9b5c1a148 100644 --- a/indigo/docs/information/prior-art.md +++ b/indigo/docs/10-information/prior-art.md @@ -1,7 +1,4 @@ ---- -id: prior-art -title: Prior Art ---- +# Prior Art Indigo was not built in a vacuum, it's the conflation of lots of different borrowed ideas, mostly from the places listed below. There are lots of good references on each of these subjects, but here they are briefly enumerated as areas you can dig into if you're interested. diff --git a/indigo/docs/information/rendering-technology.md b/indigo/docs/10-information/rendering-technology.md similarity index 96% rename from indigo/docs/information/rendering-technology.md rename to indigo/docs/10-information/rendering-technology.md index 81182719d..c48e840d8 100644 --- a/indigo/docs/information/rendering-technology.md +++ b/indigo/docs/10-information/rendering-technology.md @@ -1,7 +1,4 @@ ---- -id: rendering-technology -title: Rendering Technology ---- +# Rendering Technology At the time of writing, there are five options for rendering 2D graphics into a browser page, if you are so inclined: diff --git a/website/static/CNAME b/indigo/docs/CNAME similarity index 100% rename from website/static/CNAME rename to indigo/docs/CNAME diff --git a/indigo/docs/development-status.md b/indigo/docs/README.md similarity index 76% rename from indigo/docs/development-status.md rename to indigo/docs/README.md index 9361adb3f..26c6398b7 100644 --- a/indigo/docs/development-status.md +++ b/indigo/docs/README.md @@ -1,11 +1,10 @@ ---- -id: development-status -title: Indigo's Development Status ---- +# Indigo -## Indigo's Status is Alpha +Indigo is a pixel art Scala 2D game engine that encourages functional programming, and broadly follows the Elm architecture. -Indigo will be consider in an alpha release state until a game of any significant depth is shown to have been built using it. The implication being that by successfully building at releasing a game - web or desktop - enough features and structure must have been written in order to have made that happen. +## Indigo's Development Status + +Indigo is pretty stable, but will be consider in an alpha release state until a game of any significant depth is shown to have been built using it. The implication being that by successfully building and releasing a game - web or desktop - enough features and structure must have been written in order to have made that happen. If you have a game you are building and plan to release, or are building for a game jam or something, get in touch on Discord or Gitter and we _will_ help you with any technical problems if we possibly can! @@ -19,7 +18,7 @@ We'd love you to try building your game in Indigo and let us know how you get on What we know that we don't know yet, are Indigo's limits. -We have a fair idea about things like general graphics [performance and how to squeeze more rendering juice out of it](information/performance.md), but we don't yet have a full view on what issues will emerge on titles that aren't necessarily graphically complex, but include a serious amount of gameplay logic or content. +We have a fair idea about things like general graphics [performance and how to squeeze more rendering juice out of it](10-information/performance.md), but we don't yet have a full view on what issues will emerge on titles that aren't necessarily graphically complex, but include a serious amount of gameplay logic or content. A gentle word of caution then: We expect that things will need to change as people start to use it in anger. No doubt we've missed things, and the APIs are not as clear or consistent as we'd like them to be. Certainly the documentation needs expansion. There's bound to be the odd quirk we haven't noticed yet, or performance issues in scenarios we haven't considered. diff --git a/indigo/docs/css/custom.css b/indigo/docs/css/custom.css new file mode 100644 index 000000000..b5e35e3ac --- /dev/null +++ b/indigo/docs/css/custom.css @@ -0,0 +1,12 @@ +header { + height: 50px; + background-color: #29016a; +} + +header .row a { + color: #ffffff; +} + +#sidebar { + padding-top: 1em; +} diff --git a/indigo/docs/guides.md b/indigo/docs/guides.md deleted file mode 100644 index f4abd639d..000000000 --- a/indigo/docs/guides.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: guides -title: About these guides ---- - -In contrast to the docs, these guides are intended to be practical "how to" examples that work through specific use cases. - -As with all of Indigo's documentation, this section is a work in progress! diff --git a/website/static/img/aseprite_export.png b/indigo/docs/img/aseprite_export.png similarity index 100% rename from website/static/img/aseprite_export.png rename to indigo/docs/img/aseprite_export.png diff --git a/website/static/img/favicon.ico b/indigo/docs/img/favicon.ico similarity index 100% rename from website/static/img/favicon.ico rename to indigo/docs/img/favicon.ico diff --git a/website/static/img/font-example.png b/indigo/docs/img/font-example.png similarity index 100% rename from website/static/img/font-example.png rename to indigo/docs/img/font-example.png diff --git a/website/static/img/howtos/animated-noise-circle.gif b/indigo/docs/img/howtos/animated-noise-circle.gif similarity index 100% rename from website/static/img/howtos/animated-noise-circle.gif rename to indigo/docs/img/howtos/animated-noise-circle.gif diff --git a/website/static/img/howtos/animated-noise-circle2.gif b/indigo/docs/img/howtos/animated-noise-circle2.gif similarity index 100% rename from website/static/img/howtos/animated-noise-circle2.gif rename to indigo/docs/img/howtos/animated-noise-circle2.gif diff --git a/website/static/img/howtos/animated-noise.gif b/indigo/docs/img/howtos/animated-noise.gif similarity index 100% rename from website/static/img/howtos/animated-noise.gif rename to indigo/docs/img/howtos/animated-noise.gif diff --git a/website/static/img/howtos/campfire.gif b/indigo/docs/img/howtos/campfire.gif similarity index 100% rename from website/static/img/howtos/campfire.gif rename to indigo/docs/img/howtos/campfire.gif diff --git a/website/static/img/howtos/colours.gif b/indigo/docs/img/howtos/colours.gif similarity index 100% rename from website/static/img/howtos/colours.gif rename to indigo/docs/img/howtos/colours.gif diff --git a/website/static/img/howtos/fire.gif b/indigo/docs/img/howtos/fire.gif similarity index 100% rename from website/static/img/howtos/fire.gif rename to indigo/docs/img/howtos/fire.gif diff --git a/website/static/img/howtos/flame-colors.png b/indigo/docs/img/howtos/flame-colors.png similarity index 100% rename from website/static/img/howtos/flame-colors.png rename to indigo/docs/img/howtos/flame-colors.png diff --git a/website/static/img/howtos/flame.gif b/indigo/docs/img/howtos/flame.gif similarity index 100% rename from website/static/img/howtos/flame.gif rename to indigo/docs/img/howtos/flame.gif diff --git a/website/static/img/howtos/flames.gif b/indigo/docs/img/howtos/flames.gif similarity index 100% rename from website/static/img/howtos/flames.gif rename to indigo/docs/img/howtos/flames.gif diff --git a/website/static/img/howtos/gradient.png b/indigo/docs/img/howtos/gradient.png similarity index 100% rename from website/static/img/howtos/gradient.png rename to indigo/docs/img/howtos/gradient.png diff --git a/website/static/img/howtos/green-square.png b/indigo/docs/img/howtos/green-square.png similarity index 100% rename from website/static/img/howtos/green-square.png rename to indigo/docs/img/howtos/green-square.png diff --git a/website/static/img/howtos/sdf-circle.png b/indigo/docs/img/howtos/sdf-circle.png similarity index 100% rename from website/static/img/howtos/sdf-circle.png rename to indigo/docs/img/howtos/sdf-circle.png diff --git a/website/static/img/howtos/sdf.png b/indigo/docs/img/howtos/sdf.png similarity index 100% rename from website/static/img/howtos/sdf.png rename to indigo/docs/img/howtos/sdf.png diff --git a/website/static/img/howtos/shader_uvs.png b/indigo/docs/img/howtos/shader_uvs.png similarity index 100% rename from website/static/img/howtos/shader_uvs.png rename to indigo/docs/img/howtos/shader_uvs.png diff --git a/website/static/img/howtos/slow-flame.gif b/indigo/docs/img/howtos/slow-flame.gif similarity index 100% rename from website/static/img/howtos/slow-flame.gif rename to indigo/docs/img/howtos/slow-flame.gif diff --git a/website/static/img/howtos/uv-square.png b/indigo/docs/img/howtos/uv-square.png similarity index 100% rename from website/static/img/howtos/uv-square.png rename to indigo/docs/img/howtos/uv-square.png diff --git a/website/static/img/indigo_logo.svg b/indigo/docs/img/indigo_logo.svg similarity index 100% rename from website/static/img/indigo_logo.svg rename to indigo/docs/img/indigo_logo.svg diff --git a/website/static/img/indigo_logo_bg.svg b/indigo/docs/img/indigo_logo_bg.svg similarity index 100% rename from website/static/img/indigo_logo_bg.svg rename to indigo/docs/img/indigo_logo_bg.svg diff --git a/website/static/img/indigo_logo_full.svg b/indigo/docs/img/indigo_logo_full.svg similarity index 100% rename from website/static/img/indigo_logo_full.svg rename to indigo/docs/img/indigo_logo_full.svg diff --git a/website/static/img/indigo_logo_solid.svg b/indigo/docs/img/indigo_logo_solid.svg similarity index 100% rename from website/static/img/indigo_logo_solid.svg rename to indigo/docs/img/indigo_logo_solid.svg diff --git a/website/static/img/indigo_logo_solid_text.svg b/indigo/docs/img/indigo_logo_solid_text.svg similarity index 100% rename from website/static/img/indigo_logo_solid_text.svg rename to indigo/docs/img/indigo_logo_solid_text.svg diff --git a/website/static/img/oss_logo.png b/indigo/docs/img/oss_logo.png similarity index 100% rename from website/static/img/oss_logo.png rename to indigo/docs/img/oss_logo.png diff --git a/website/static/img/refractions.png b/indigo/docs/img/refractions.png similarity index 100% rename from website/static/img/refractions.png rename to indigo/docs/img/refractions.png diff --git a/website/static/img/renderer-comparison.png b/indigo/docs/img/renderer-comparison.png similarity index 100% rename from website/static/img/renderer-comparison.png rename to indigo/docs/img/renderer-comparison.png diff --git a/website/static/img/scala-lang.svg b/indigo/docs/img/scala-lang.svg similarity index 100% rename from website/static/img/scala-lang.svg rename to indigo/docs/img/scala-lang.svg diff --git a/website/static/img/site_consoles.png b/indigo/docs/img/site_consoles.png similarity index 100% rename from website/static/img/site_consoles.png rename to indigo/docs/img/site_consoles.png diff --git a/website/static/img/site_pirate.png b/indigo/docs/img/site_pirate.png similarity index 100% rename from website/static/img/site_pirate.png rename to indigo/docs/img/site_pirate.png diff --git a/website/static/img/site_scala_logo.png b/indigo/docs/img/site_scala_logo.png similarity index 100% rename from website/static/img/site_scala_logo.png rename to indigo/docs/img/site_scala_logo.png diff --git a/website/static/img/snake_bg.gif b/indigo/docs/img/snake_bg.gif similarity index 100% rename from website/static/img/snake_bg.gif rename to indigo/docs/img/snake_bg.gif diff --git a/website/static/img/undraw_code_review.svg b/indigo/docs/img/undraw_code_review.svg similarity index 100% rename from website/static/img/undraw_code_review.svg rename to indigo/docs/img/undraw_code_review.svg diff --git a/website/static/img/undraw_monitor.svg b/indigo/docs/img/undraw_monitor.svg similarity index 100% rename from website/static/img/undraw_monitor.svg rename to indigo/docs/img/undraw_monitor.svg diff --git a/website/static/img/undraw_note_list.svg b/indigo/docs/img/undraw_note_list.svg similarity index 100% rename from website/static/img/undraw_note_list.svg rename to indigo/docs/img/undraw_note_list.svg diff --git a/website/static/img/undraw_online.svg b/indigo/docs/img/undraw_online.svg similarity index 100% rename from website/static/img/undraw_online.svg rename to indigo/docs/img/undraw_online.svg diff --git a/website/static/img/undraw_open_source.svg b/indigo/docs/img/undraw_open_source.svg similarity index 100% rename from website/static/img/undraw_open_source.svg rename to indigo/docs/img/undraw_open_source.svg diff --git a/website/static/img/undraw_operating_system.svg b/indigo/docs/img/undraw_operating_system.svg similarity index 100% rename from website/static/img/undraw_operating_system.svg rename to indigo/docs/img/undraw_operating_system.svg diff --git a/website/static/img/undraw_react.svg b/indigo/docs/img/undraw_react.svg similarity index 100% rename from website/static/img/undraw_react.svg rename to indigo/docs/img/undraw_react.svg diff --git a/website/static/img/undraw_tweetstorm.svg b/indigo/docs/img/undraw_tweetstorm.svg similarity index 100% rename from website/static/img/undraw_tweetstorm.svg rename to indigo/docs/img/undraw_tweetstorm.svg diff --git a/website/static/img/undraw_youtube_tutorial.svg b/indigo/docs/img/undraw_youtube_tutorial.svg similarity index 100% rename from website/static/img/undraw_youtube_tutorial.svg rename to indigo/docs/img/undraw_youtube_tutorial.svg diff --git a/indigo/docs/unused/computations.md b/indigo/docs/unused/computations.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/indigo/docs/unused/jobs.md b/indigo/docs/unused/jobs.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/indigo/project/plugins.sbt b/indigo/project/plugins.sbt index 0cb5f69fb..075181de0 100644 --- a/indigo/project/plugins.sbt +++ b/indigo/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("org.xerial.sbt" %% "sbt-sonatype" % "3.9.7") addSbtPlugin("com.jsuereth" %% "sbt-pgp" % "2.0.1") addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.3.0") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.31") -addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.4") +addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.7") addSbtPlugin("com.github.sbt" % "sbt-unidoc" % "0.5.0") addSbtPlugin("org.scala-js" % "sbt-jsdependencies" % "1.0.2") addSbtPlugin("com.github.reibitto" % "sbt-welcome" % "0.3.1") diff --git a/website/README.md b/website/README.md deleted file mode 100644 index 6477a55a5..000000000 --- a/website/README.md +++ /dev/null @@ -1,198 +0,0 @@ -This website was created with [Docusaurus](https://docusaurus.io/). - -# What's In This Document - -- [Get Started in 5 Minutes](#get-started-in-5-minutes) -- [Directory Structure](#directory-structure) -- [Editing Content](#editing-content) -- [Adding Content](#adding-content) -- [Full Documentation](#full-documentation) - -# Get Started in 5 Minutes - -1. Make sure all the dependencies for the website are installed: - -```sh -# Install dependencies -$ yarn -``` - -2. Run your dev server: - -```sh -# Start the site -$ yarn start -``` - -## Directory Structure - -Your project file structure should look something like this - -``` -my-docusaurus/ - docs/ - doc-1.md - doc-2.md - doc-3.md - website/ - blog/ - 2016-3-11-oldest-post.md - 2017-10-24-newest-post.md - core/ - node_modules/ - pages/ - static/ - css/ - img/ - package.json - sidebars.json - siteConfig.js -``` - -# Editing Content - -## Editing an existing docs page - -Edit docs by navigating to `docs/` and editing the corresponding document: - -`docs/doc-to-be-edited.md` - -```markdown ---- -id: page-needs-edit -title: This Doc Needs To Be Edited ---- - -Edit me... -``` - -For more information about docs, click [here](https://docusaurus.io/docs/en/navigation) - -## Editing an existing blog post - -Edit blog posts by navigating to `website/blog` and editing the corresponding post: - -`website/blog/post-to-be-edited.md` - -```markdown ---- -id: post-needs-edit -title: This Blog Post Needs To Be Edited ---- - -Edit me... -``` - -For more information about blog posts, click [here](https://docusaurus.io/docs/en/adding-blog) - -# Adding Content - -## Adding a new docs page to an existing sidebar - -1. Create the doc as a new markdown file in `/docs`, example `docs/newly-created-doc.md`: - -```md ---- -id: newly-created-doc -title: This Doc Needs To Be Edited ---- - -My new content here.. -``` - -1. Refer to that doc's ID in an existing sidebar in `website/sidebars.json`: - -```javascript -// Add newly-created-doc to the Getting Started category of docs -{ - "docs": { - "Getting Started": [ - "quick-start", - "newly-created-doc" // new doc here - ], - ... - }, - ... -} -``` - -For more information about adding new docs, click [here](https://docusaurus.io/docs/en/navigation) - -## Adding a new blog post - -1. Make sure there is a header link to your blog in `website/siteConfig.js`: - -`website/siteConfig.js` - -```javascript -headerLinks: [ - ... - { blog: true, label: 'Blog' }, - ... -] -``` - -2. Create the blog post with the format `YYYY-MM-DD-My-Blog-Post-Title.md` in `website/blog`: - -`website/blog/2018-05-21-New-Blog-Post.md` - -```markdown ---- -author: Frank Li -authorURL: https://twitter.com/foobarbaz -authorFBID: 503283835 -title: New Blog Post ---- - -Lorem Ipsum... -``` - -For more information about blog posts, click [here](https://docusaurus.io/docs/en/adding-blog) - -## Adding items to your site's top navigation bar - -1. Add links to docs, custom pages or external links by editing the headerLinks field of `website/siteConfig.js`: - -`website/siteConfig.js` - -```javascript -{ - headerLinks: [ - ... - /* you can add docs */ - { doc: 'my-examples', label: 'Examples' }, - /* you can add custom pages */ - { page: 'help', label: 'Help' }, - /* you can add external links */ - { href: 'https://github.com/facebook/docusaurus', label: 'GitHub' }, - ... - ], - ... -} -``` - -For more information about the navigation bar, click [here](https://docusaurus.io/docs/en/navigation) - -## Adding custom pages - -1. Docusaurus uses React components to build pages. The components are saved as .js files in `website/pages/en`: -1. If you want your page to show up in your navigation header, you will need to update `website/siteConfig.js` to add to the `headerLinks` element: - -`website/siteConfig.js` - -```javascript -{ - headerLinks: [ - ... - { page: 'my-new-custom-page', label: 'My New Custom Page' }, - ... - ], - ... -} -``` - -For more information about custom pages, click [here](https://docusaurus.io/docs/en/custom-pages). - -# Full Documentation - -Full documentation can be found on the [website](https://docusaurus.io/). diff --git a/website/blog/2021-02-18-devlog-1.md b/website/blog/2021-02-18-devlog-1.md deleted file mode 100644 index df6026b02..000000000 --- a/website/blog/2021-02-18-devlog-1.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: Indigo Dev Log 1: Rethinking Indigo's Renderer -author: Dave Smith -authorURL: http://twitter.com/davidjamessmith ---- - -The current work in progress is to re-think Indigo’s rendering pipeline. This isn’t the first time I’ve gone back to the drawing board, but it is the first time since Indigo’s launch. Since this is going to mean a bit of a longer wait between releases than usual, I thought I ought to explain what’s happening and report on my progress so far.. - - - -## A brief history of Indigo’s renderer - -I don’t know how interesting this is but I feel like the context is important. - -Back in 2016 I wasn’t even sure if it was possible to make a usable game engine in Scala, but I was confident that there was a minimal feature set that I would enjoy that might be achievable, as long as I kept it small. Really small. - -Pixel-art only, something that approximated [blitting](https://en.wikipedia.org/wiki/Bit_blit) operations. No arbitrary shapes, scenes, real fonts, special effects or shaders or anything, not even rotation. Something you could just about build the original Mario with. - -Graphics rendering is complicated, but the great thing about a super minimal set of rendering requirements is that the pipeline can be specialised and focused, which is easier than building something more general purpose. Indigo was not as fast as it could have been I’m sure, but it was/is able to draw decent numbers of on screen elements while retaining a pretty solid performance profile. - -Reliable performance for low effort felt important to me because, I reasoned, most people coming from Scala were likely to be new to game building, and I didn’t want them to be too worried about performance tuning. - -The problem is that at the point of Indigo’s initial launch, this renderer design was basically maxed out in terms of how many graphical features I had the ability (as an amateur) to push through such a constrained pipeline. - -## Indigo’s roadmap - -I don’t like to nail down roadmaps too firmly as a rule. I work on the principle of having a mirage on the horizon that I can use to give me a bearing in case I think I’m losing my way, but I don’t worry too much about the exact destination or the route I‘m going to take to get there. The only real detail in the plan is of the work I’m doing right now, the next step on the journey. - -I try not to look up from my feet too often in case I find the length of the road ahead off-putting. - -What does the vague impression in the distance look like at the moment? Well, I think it looks a bit like a GUI editor for Indigo. What kind of editor? What features will it have? How will it work? Will we ever reach that goal? Who knows! ...and it doesn’t matter, it’s just a direction to head in. - -To move in the direction of that goal there are a few obvious and chunky things that Indigo needs, like the ability to draw arbitrary shapes, a more flexible layers system, and possibly better/real font support to name but a few. - -To do any of those things means having a more sophisticated rendering pipeline that can cope with things like custom shaders, and that in turn means a rethink of the renderer. - -So that’s what I’m doing. - -## Progress report - -What I have already is the foundations: - -- An infinite number of non-specialised layers (no more fixed named layers) -- New syntax to describe layer blend modes -- The ability to write completely custom scene entities -- The ability to write custom shaders -- Some prebuilt entities and shaders that work similarly to the existing primitives -- The tentative beginnings of work on shape primitives - -Safe to say that the next release will feature many breaking changes, but I’m planning to write migration notes of some kind. - -One of the major philosophical differences that the next release will introduce, is that the game developer will be much more in control of performance. Fewer rendering requirements will result in faster performance, but if you wish, you’ll also be able to trade off raw speed for much more sophisticated rendering. - -My aim is to keep the new renderer as beginner friendly as I can, but also to allow people to explore more advanced rendering techniques. - -## Questions without answers (yet) - -1. The next release will include new features Indigo has never had before, will it also have all of the features of the previous versions? - -Undecided. I think I shall aim for feature parity but some things may not make the cut. - -2. Will Indigo continue to support Scala 2? - -Scala 2 is still important because the dev tooling around Scala 3 hasn’t (unsurprisingly since it hasn’t been released yet) caught up with the Scala 2 experience yet. But once the tooling is better, could Scala 2 just be dropped? Since there is no-one depending on Indigo for their business or livelihood, the usual library support / backwards compatibility considerations don’t really apply here, so it might be reasonable. - -However unless Scala 3’s tooling is much better before the next release (possible...), it’s likely that the next release will support Scala 2, just not guaranteed. - -3. Will Indigo continue to support WebGL 1.0? - -Maintaining WebGL 1.0 and 2.0 is effectively maintaining two completely different renderers, which is a lot of work for one person. Also worth noting that sooner or later I’ll need to look into supporting WebGPU too. - -At the time of writing all the new work is happening in the WebGL 2.0 renderer, and I don’t know how feasible back porting it will be. - -The performance of WebGL 1.0 is far worse than WebGL 2.0, but it’s market/browser penetration is near 100%, where WebGL 2.0 is closer to 75% with big names like Safari conspicuously missing (Safari tech preview version does add support). However, WebGL 2.0 is probably available everywhere that you’re likely to find a gamer that wants to play your game, so does the other 25% matter? Hard to say. - -One option, rather than removing WebGL 1.0 support altogether is to reduce it to a bare minimum, so that it’s just about good enough to inform your players to try a different browser or platform. Would that be acceptable? Your guess is as good as mine. - -## Thanks! - -Thanks for taking the time to read this update. If you have any questions or would like to discuss any of it I can usually be found on our Discord channel. - -Dave diff --git a/website/blog/2021-03-24-devlog-2.md b/website/blog/2021-03-24-devlog-2.md deleted file mode 100644 index f9eabbe45..000000000 --- a/website/blog/2021-03-24-devlog-2.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Indigo Dev Log 2: It's all about the shaders... -author: Dave Smith -authorURL: http://twitter.com/davidjamessmith ---- - -!["pixel art being refracted through a normal map to give the illusion of a lens."](/img/refractions.png) - -Thought I’d try a different format this time to see if I can make it easier to write these things. Hopefully it will encourage me to do it more often. Aiming for a sort of agile / stand-up / update format. - -## TL;DR - -Next version is coming along nicely, lots of new exciting stuff going into it. The only technical hurdle ahead of me is to reimplement dynamic lighting, and hopefully make it better! After that I’ll begin prepping the next release. - - - -### What has happened since the last update? - -**Scala 3.0.0-RC1 & Scala 2.13.5** - Many thanks to [auman](https://github.com/aumann) for upgrading Indigo to the latest Scala 3 version! - -**Shapes!** - A first version of shapes is now included as standard. There’s A LOT you can do with shapes conceptually, this first version is a limited functionality release to test the water. It contains Circles, Boxes, and Polygon’s that support borders of arbitrary thickness and can be filled with solid colours or linear / radial gradients. Worth noting that these shapes were initially implemented with the new custom shader mechanism - so if you know GLSL there’s nothing stopping you going the [full Freya](https://acegikmo.com/shapes/)! (Note: If you do, I’d love a PR!! :-)) - -**Custom Shader Data** - Ability to supply custom data to your shaders. - -**Blending and BlendMaterials** - As well as entity shaders, you can now write shaders that control how layers blend together, enabling things like simple post processing effects. You can also control hardware blend functions. This arrangement has been used in combination with entity shaders to re-implement the old image based lighting layer functionality, but now you can have as many lighting layers as you like. - -**Reimplemented screen effects as layer effects** - The current Indigo version allows you some basic fixed post-processing effects. This has been reimplemented and expanded using the BlendMaterials mentioned above. One big difference is that the effects are layer level, as opposed to screen level, and you can optionally apply the effects to only the current layer or to the merged layer stack (below the current layer). - -**Reimplemented legacy effects** - The old border and glow effects, which are quite cheap and I suspect of limited use, have been reimplemented just in case anyone is depending on them. However they aren’t built into Indigo by default any more, you need to add them from the extras library. - -**Reimplemented Distortion layers as Refractions** - Not only reimplemented but also slightly improved. In the same vein as effects, I’m not convinced this is up to scratch quality wise and so I’ve moved it into the extras project. The implementation is achieved using entity and blend materials. - -### What is being worked on at the moment? - -The current work in progress is to reimplement and improve dynamic lighting. The two improvements specifically are (hopefully): - -1. Rethink how specular lighting is handled, a mistake was made during the original implementation that I’d like to correct. - -2. Ambient lighting will no longer rely on image based ambient lighting. - -There is also an unresolved question about whether lights will be global, layer based, or both. As it’s a forward renderer, there will be a light count limit in the next version (which shouldn’t be a problem for most use cases), so if you had global + layer lights that went over the limit, which should take priority? I’m sure I’ll think of something. - -It’s unclear how much effort this will be as Indigo has moved from being an inflexible [deferred renderer](https://en.wikipedia.org/wiki/Deferred_shading) to a programmable forward renderer. But I’m hopeful it will be in the order of days rather than weeks. - -### What is expected to happen next? - -Essentially release prep, however, a lot has changed in terms of the APIs and how Indigo works. So the plan is the work through the various demos and example projects, and while I upgrade them, take down migration notes, and re-assess the API choices I’ve made to see if I can make them clearer or reduce the impact of change. - -## Thanks! - -Thanks for taking the time to read this little update. Looking forward to getting the next version out and seeing what people make of it. I'd also like to say thank you the expanding cast of people supporting the project. Whether you are helping financially, contributing code and documentation improvements, or just being around to help discuss ideas: It's all very much appreciated! - -Dave diff --git a/website/blog/2021-04-11-indigo-0-7-0-released.md b/website/blog/2021-04-11-indigo-0-7-0-released.md deleted file mode 100644 index f8caddc0b..000000000 --- a/website/blog/2021-04-11-indigo-0-7-0-released.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Indigo 0.7.0 Released -author: Dave Smith -authorURL: http://twitter.com/davidjamessmith ---- - -This release is a total rewrite of Indigo’s rendering process to make it flexible and customisable. - -[Full details of this release with migration notes can be found on github.](https://github.com/PurpleKingdomGames/indigo/releases/tag/v0.7.0) - -!["Comparison of the old and new rendering pipelines."](/img/renderer-comparison.png) - -*(The diagram above attempts to show how this release has changed the rendering process.)* diff --git a/website/blog/2021-05-17-indigo-0-8-0-released.md b/website/blog/2021-05-17-indigo-0-8-0-released.md deleted file mode 100644 index 687339058..000000000 --- a/website/blog/2021-05-17-indigo-0-8-0-released.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Indigo 0.8.0 Released -author: Dave Smith -authorURL: http://twitter.com/davidjamessmith ---- - -This release is the first Scala 3.0.0 release, and drops support for Scala 2. - -Aside from a number of important bug fixes, this release also includes an early version of a new `TextBox` primitive and support for font assets. - -[Full details of this release can be found on github.](https://github.com/PurpleKingdomGames/indigo/releases/tag/v0.8.0) diff --git a/website/blog/2021-05-20-indigo-0-8-1-released.md b/website/blog/2021-05-20-indigo-0-8-1-released.md deleted file mode 100644 index 9dc7308d8..000000000 --- a/website/blog/2021-05-20-indigo-0-8-1-released.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Indigo 0.8.1 Released -author: Dave Smith -authorURL: http://twitter.com/davidjamessmith ---- - -This is an important bug fix release that resolves rendering problems on Windows machines (including browsers on Windows). - -[Full details of this release can be found on github.](https://github.com/PurpleKingdomGames/indigo/releases/tag/v0.8.1) diff --git a/website/blog/2021-05-30-indigo-0-8-2-released.md b/website/blog/2021-05-30-indigo-0-8-2-released.md deleted file mode 100644 index 16c125199..000000000 --- a/website/blog/2021-05-30-indigo-0-8-2-released.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Indigo 0.8.2 Released -author: Dave Smith -authorURL: http://twitter.com/davidjamessmith ---- - -This is a bug fix release that resolves an issue with entity nodes incorrectly rendering textures. - -[Full details of this release can be found on github.](https://github.com/PurpleKingdomGames/indigo/releases/tag/v0.8.2) diff --git a/website/blog/2021-07-06-indigo-0-9-0-released.md b/website/blog/2021-07-06-indigo-0-9-0-released.md deleted file mode 100644 index 79217685d..000000000 --- a/website/blog/2021-07-06-indigo-0-9-0-released.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Indigo 0.9.0 Released -author: Dave Smith -authorURL: http://twitter.com/davidjamessmith ---- - -Details of the major changes found in Indigo 0.9.0: - -- New! Scene Camera (Early preview, feedback welcome) -- Dynamic shader loading -- Improved texture support in shaders -- Built-in primitives have Material type parameter -- Caching of custom packed UBO data - -[Full details of this release can be found on github.](https://github.com/PurpleKingdomGames/indigo/releases/tag/v0.9.0) diff --git a/website/blog/2021-08-17-roguelike-post-mortem.md b/website/blog/2021-08-17-roguelike-post-mortem.md deleted file mode 100644 index 3a9db33d1..000000000 --- a/website/blog/2021-08-17-roguelike-post-mortem.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: Post-Mortem: "RoguelikeDev Does The Complete Roguelike Tutorial" in Scala -author: Dave Smith -authorURL: http://twitter.com/davidjamessmith ---- - -!["A early screenshot of a roguelike made with Indigo"](https://raw.githubusercontent.com/davesmith00000/roguelike-tutorial/main/part3/roguelike-part3_2.gif) - -**This is a brief post-mortem of my attempt to do the ["RoguelikeDev Does The Complete Roguelike Tutorial"](https://www.reddit.com/r/roguelikedev/comments/o5x585/roguelikedev_does_the_complete_roguelike_tutorial/) in Scala.** - -I've been asked on several occasions if it would be possible to build a roguelike using Indigo? - -My answer has always been that it should be possible, but that it would probably be challenging because Indigo isn't built for rendering lots of text. - -About a month before this year's annual "RoguelikeDev Does The Complete Roguelike Tutorial" I was asked again, and decided it was time to find out if it really was possible or not! - - - -## What are roguelikes? - -[Roguelike](https://en.wikipedia.org/wiki/Roguelike)'s are a type of game that get their name because they are ...wait for it ..._like_ an 80s game called _Rogue_! - -They typically use ASCII art for graphics, generated levels / dungeons and feature things like perma-death. - -## Starting at the finish - -### Where can I play it? - -[All completed parts of the roguelike tutorials](http://rogueliketutorials.com/tutorials/tcod/v2/) can be found in the following repo, along with playable links so that you can try out it's progression for yourself: - -[https://github.com/davesmith00000/roguelike-tutorial](https://github.com/davesmith00000/roguelike-tutorial) - -### What should I expect? - -[The final playable version of the "game"](https://davesmith00000.github.io/roguelike-tutorial/part13/) is surprisingly playable.. for a while at least. :-) - -Sure, the lack of game balance is quickly apparent and after about level 6 or 7 you'll run out of new things to do, but I'm really quite pleased with it. There's exploration, discovery, spells, potions, equipment, monsters, levels, an inventory, and menus - all the things in the tutorial, in fact! And considering I spent _no time at all_ selecting colors or which tileset to go with, it actually looks quite nice! - -The code quality is ok. - -When I began the project I had some lofty ideas about writing lovely clean code that would be easy to follow, but as you can see if you look at the later stages of the code base, by the end I was just pleased to be crossing the finishing line at the end of the marathon. - -Maybe I'll refactor it next year.. - -## The tutorial - -The tutorial is very well written and the "RoguelikeDev Does The Complete Roguelike Tutorial" follow-along is well paced, taking me two to three evenings a week. - -The difficulty with the tutorial is that it is aimed at Python developers, and as they say in the follow-along's description, if you're not using Python the expectation is that you'll blaze your own trail. - -There are two problems with not using Python. - -The first is simply distilling the tutorial parts into the intended deliverables. The tutorials are written for Python developers, and they have a lovely conversational style, building a narrative as they go along. The authors take great care to go over code from previous chapters - refactoring code to be ready for the next section. Of course, if you're not a Python developer then the result is - in places - _a lot_ of text / code to sift through to find the information you need. Luckily, the screenshots the authors included were a massive help. In the chapter on saving and loading I basically just looked at the screenshots and reverse engineered suitable requirements. This was because most of the tutorial chapter was involved in disk IO while my solution ran in a browser, and is side effect free! - -The second problem is the lack of ready-made tooling. - -## DIY Tooling - -The Python version uses a library called [tcod](https://python-tcod.readthedocs.io/en/latest/) which essentially gives you all of the functionality you need to build a roguelike, and your job in the tutorial is to build the game logic and data structures. - -Choosing to follow along in another language means that you need to fend for yourself. In my case I ended up building a [roguelike starter kit](https://github.com/PurpleKingdomGames/indigo-roguelike-starterkit) to fill in some of the critical gaps. - -The [README](https://github.com/PurpleKingdomGames/indigo-roguelike-starterkit/blob/main/README.md) on the starter kit's repo explains most of the functionality that the starter kit provides in a fair amount of detail, but the main things it does is: - -1. Give you easy access to Dwarf Fortress assets. -2. Provide two ways of rendering coloured terminal-like text. - -Dwarf Fortress is a very famous roguelike with [many different tilesets available](https://dwarffortresswiki.org/Tileset_repository). They are all based on the "IBM Code Page 437" or "Extended ASCII" table, and what you get is an image of a grid of characters and symbols. The starter kit uses a little compile time script to convert the tileset of your choice, into pre-baked classes containing all of the character information for use with either Indigo's `Text` primitive using the `TerminalText` material, or the `TerminalEntity`/`TerminalEmulator`. - -It wasn't terribly difficult, but this little bit of tool sharpening was very satisfying to do and made the rest of the build much more fun. - -## Lessons Learned - -### What went well? - -Taking the time to build the starter kit paid itself back many times over. Once I got into the game building proper, I basically never had to think about how to do the rendering again. - -Converting the tutorial to pure functions and Indigo's uni-directional data flow was challenging at times, but made following the code easy, and in the few places where I really needed tests it was easy to set them up. I didn't write very many tests however, because most of the game was just plumbing that required little checking beyond making the compiler happy. Testing came into it's own wherever something non-trivial needed to be verified, such as the path finding code. - -The tutorial descriptions of topics like procedural dungeon generation were really great and easy to follow. - -### Where did I get lucky? - -For reasons best known to someone else, early in the development of the starter kit I set it up to work with [Parcel.js](https://parceljs.org/). This turned out to be a great idea because it made publishing the playable tutorial parts to github pages a piece of cake! - -### What went wrong? - -I repeatedly underestimated the size of the tutorial! - -Each chapter often does more than one thing and I was regularly halfway through a section when I realised I was going to have to do something much more complicated than I anticipated, or that I was fundamentally missing some piece of functionality / tooling. - -Another unexpected problem was that the tutorials rely on a feature of game engines that Indigo considers a defect, and fixes by default. In Indigo you cannot (easily / idiomatically) modify the state of another actor / entity during the current frame. To put it another way, there is no "first mover" advantage to having the good fortune of being the first entity updated. Consider the following: - -1. The Player attacks an Orc -2. The Orc is killed -3. The Orc cannot attack the Player because it is dead. - -Seems reasonable. - -In Python this translates easily: - -1. On update, the Player attacks an Orc, directly calling it's damage method. -2. The Orc's health is reduced below zero and it is killed. -3. ... that's it. - -This works because the Player's actions are always evaluated first and carried out immediately. In a fair fight with two evenly matched players, the first player would always win. - -In Indigo things are not so simple because Indigo hugely discourages first-mover advantage by decoupling action from outcome. In reality the combatants effectively both attacked at the same time in the same instant! Like this: - -1. On update, the Player attacks the Orc, _emitting an event with the amount of damage to be inflicted_. -2. The Orc's health has not yet been reduced, so the Orc is still alive during this update. -3. The Orc attacks! It doesn't know it's dead yet! It gets one last gasping attempt at killing the Player! _The Orc also emits an event saying the Player has been damaged_. -4. On the next frame, the relevant damage is inflicted on both parties. -5. The Orc is killed as before... but the Player has been unexpectedly injured or killed too! - -The solution is to separate the players turn from the enemies turn, creating a turn based game. This effectively mimics the original behavior but it's now part of the game's design rather than a happy accident. - -### What would I do differently next time? - -My main regret is that the terminal emulator is rather heavy and can't be refreshed at 60 fps. For the purposes of the tutorial this isn't a problem since you only have to update on key press, but if you wanted to do any smoother effects it wouldn't be able to keep up. The other way this problem rears it's head is if someone is running a low power system of some kind, since it requires the ability to allocate some fairly chunky arrays on to the GPU as UBO data (uniform buffer object). - -There are lots of ways to resolve this problem, I would have liked to have had the time to make it better, maybe next time. - -Additionally I'd like to have wrapped up the starter kit into a library of some sort for ease of use by others. - -Finally, a small thing, but I wish I'd spent a little bit longer on the build process. When you build for web you have to emit a different module kind than if you're running locally, and that's a manual change in the `build.sbt` file. It would have been nice to do that properly. ([The process is described in the starter kit's README.](https://github.com/PurpleKingdomGames/indigo-roguelike-starterkit#how-to-run-and-package-up-this-game)) - -## Final thoughts - -Following the tutorial in a language other than Python added a lot of complexity. Converting the tutorial to a purely functional language / approach on top of that often meant completely ignoring what the tutorial was saying, and trying to achieve the same outcome by totally different means. This would be very difficult if you didn't know your engine well in advance. - -That said, following the tutorial was great fun and I would highly recommend it. Hopefully I'll be able to have another crack at it next year! In the meantime, perhaps the version I've pulled together (along with the starter kit) will help the next adventurous Scala soul that decides to delve into the depths of a roguelike! diff --git a/website/blog/2021-09-07-indigo-0-9-1-released.md b/website/blog/2021-09-07-indigo-0-9-1-released.md deleted file mode 100644 index fb0bed443..000000000 --- a/website/blog/2021-09-07-indigo-0-9-1-released.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Indigo 0.9.1 Released -author: Dave Smith -authorURL: http://twitter.com/davidjamessmith ---- - -Details of the major changes found in Indigo 0.9.1: - -- Updated! Cameras... -- New `HitArea` UI Component -- Standard Materials can tile and stretch to fit -- `ShaderPrimitive` Improvements - -[Full details of this release can be found on github.](https://github.com/PurpleKingdomGames/indigo/releases/tag/v0.9.1) diff --git a/website/blog/2021-09-09-indigo-0-9-2-released.md b/website/blog/2021-09-09-indigo-0-9-2-released.md deleted file mode 100644 index f4877439b..000000000 --- a/website/blog/2021-09-09-indigo-0-9-2-released.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Indigo 0.9.2 Released -author: Dave Smith -authorURL: http://twitter.com/davidjamessmith ---- - -This release contains two seemingly small bug fixes / corrections that could significantly change the look of your game. As luck would have it, they have been around for several versions and have gone unnoticed until the day _after_ the previous release. - -- Loaded images are now correctly unpacked with premultiplied alpha. -- Shape fill colours have had premultiplication removed. - -[Full details of this release can be found on github.](https://github.com/PurpleKingdomGames/indigo/releases/tag/v0.9.2) diff --git a/website/build.sbt b/website/build.sbt index f6de46289..b4d0c3d1d 100644 --- a/website/build.sbt +++ b/website/build.sbt @@ -1,21 +1,128 @@ +import laika.markdown.github.GitHubFlavor +import laika.parse.code.SyntaxHighlighting +import laika.rewrite.nav.PrettyURLs +import laika.helium.Helium +import laika.theme.config.Color +import laika.theme.config.Color._ +import laika.helium.config.ColorQuintet +import laika.helium.config._ +import laika.ast.Path.Root +import laika.ast.Image +import laika.ast.Length +import laika.ast.LengthUnit +import com.comcast.ip4s._ +import scala.concurrent.duration.DurationInt +import laika.sbt.LaikaPreviewConfig + +ThisBuild / scalaVersion := "3.3.0" + +enablePlugins(LaikaPlugin, GhpagesPlugin) + Global / onChangedBuildSource := ReloadOnSourceChanges -val scala3Version = "3.3.0" - -lazy val indigoSite = - (project in file(".")) - .enablePlugins(GhpagesPlugin) - .settings( - name := "indigo site publisher", - version := "0.0.1", - scalaVersion := scala3Version, - organization := "io.indigo", - siteSourceDirectory := target.value / ".." / "build" / "indigo-site", - makeSite / includeFilter := "*", - makeSite / excludeFilter := ".DS_Store", - git.remoteRepo := "git@github.com:PurpleKingdomGames/indigo.git", - ghpagesNoJekyll := true +Laika / sourceDirectories := Seq( + baseDirectory.value / "../indigo/indigo-docs/target/mdoc" +) + +laikaExtensions := Seq(GitHubFlavor, SyntaxHighlighting, PrettyURLs) + +/* +Dark purple - #29016a +hot pink - #ae2be2 / less hot: 9003c8 +light pink - #efc6ff +Purpleish - 6237a7 +Light grey - e4e4e4 +Light purple - a888db + */ + +laikaTheme := + Helium.defaults.all + .metadata( + title = Some("Indigo"), + language = Some("en") + ) + .all + .themeColors( + primary = Color.hex("29016a"), + secondary = Color.hex("9003c8"), + primaryMedium = Color.hex("a888db"), + primaryLight = Color.hex("e4e4e4"), + text = Color.hex("5f5f5f"), + background = Color.hex("ffffff"), + bgGradient = (Color.hex("095269"), Color.hex("007c99")) ) + .site + .darkMode + .themeColors( + primary = Color.hex("29016a"), + secondary = Color.hex("9003c8"), + primaryMedium = Color.hex("a888db"), + primaryLight = Color.hex("e4e4e4"), + text = Color.hex("5f5f5f"), + background = Color.hex("ffffff"), + bgGradient = (Color.hex("29016a"), Color.hex("ffffff")) + ) + .all + .syntaxHighlightingColors( + base = ColorQuintet( + hex("2a3236"), + hex("8c878e"), + hex("b2adb4"), + hex("bddcee"), + hex("e8e8e8") + ), + wheel = ColorQuintet( + hex("e28e93"), + hex("ef9725"), + hex("ffc66d"), + hex("7fb971"), + hex("4dbed4") + ) + ) + .site + .topNavigationBar( + homeLink = ImageLink.internal( + Root / "README.md", + Image.internal( + Root / "img" / "indigo_logo_solid_text.svg", + alt = Some("Homepage"), + title = Some("Indigo"), + width = Some(Length(150.0, LengthUnit.px)), + height = Some(Length(50.0, LengthUnit.px)) + ) + ), + navLinks = Seq( + ButtonLink.external("https://discord.gg/b5CD47g", "Discord"), + ButtonLink.external("/api", "API"), + ButtonLink.external( + "https://github.com/PurpleKingdomGames/indigo", + "Github" + ) + ) + ) + .site + .tableOfContent(title = "Contents", depth = 2) + .site + .autoLinkCSS(Root / "css" / "custom.css") + .site.favIcons( + Favicon.internal(Root / "img" / "indigo_logo_solid.svg", sizes = "32x32"), + Favicon.internal(Root / "img" / "indigo_logo_solid.svg", sizes = "64x64") + ) + .build + +// Helium.defaults + +laikaPreviewConfig := + LaikaPreviewConfig.defaults + .withPort(port"8080") + +// Make site + +siteSourceDirectory := target.value / "docs" / "site" +makeSite / includeFilter := "*" +makeSite / excludeFilter := ".DS_Store" +git.remoteRepo := "git@github.com:PurpleKingdomGames/indigo.git" +ghpagesNoJekyll := true addCommandAlias( "publishIndigoSite", diff --git a/website/build.sh b/website/build.sh index afbb4a14a..6b98f35ec 100644 --- a/website/build.sh +++ b/website/build.sh @@ -1,8 +1,5 @@ #!/bin/bash -# TODO -# Auto update the demos? - set -e WEBSITE_DIR=$(pwd) @@ -18,10 +15,11 @@ sbt gendocs cd $WEBSITE_DIR # ----- -# build the site -yarn run build +# build the site // $WEBSITE_DIR/target/docs/site +sbt clean laikaSite # ----- # Publish -cp -R $INDIGO_ENGINE_DIR/target/scala-3.*/unidoc/. $WEBSITE_DIR/build/indigo-site/api/ -sbt clean makeSite ghpagesPushSite +mkdir -p target/docs/site/api/ +cp -R $INDIGO_ENGINE_DIR/target/scala-3.*/unidoc/. $WEBSITE_DIR/target/docs/site/api/ +sbt makeSite ghpagesPushSite diff --git a/website/core/Copyright.js b/website/core/Copyright.js deleted file mode 100644 index 91b4e5b90..000000000 --- a/website/core/Copyright.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -const React = require('react'); - -class Copyright extends React.Component { - docUrl(doc, language) { - const baseUrl = this.props.config.baseUrl; - const docsUrl = this.props.config.docsUrl; - const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`; - const langPart = `${language ? `${language}/` : ''}`; - return `${baseUrl}${docsPart}${langPart}${doc}`; - } - - pageUrl(doc, language) { - const baseUrl = this.props.config.baseUrl; - return baseUrl + (language ? `${language}/` : '') + doc; - } - - render() { - return ( - - ); - } -} - -module.exports = Copyright; diff --git a/website/core/Footer.js b/website/core/Footer.js deleted file mode 100644 index 4e9c9d4e5..000000000 --- a/website/core/Footer.js +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -const React = require('react'); - -class Footer extends React.Component { - docUrl(doc, language) { - const baseUrl = this.props.config.baseUrl; - const docsUrl = this.props.config.docsUrl; - const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`; - const langPart = `${language ? `${language}/` : ''}`; - return `${baseUrl}${docsPart}${langPart}${doc}`; - } - - pageUrl(doc, language) { - const baseUrl = this.props.config.baseUrl; - return baseUrl + (language ? `${language}/` : '') + doc; - } - - render() { - return ( - - ); - } -} - -module.exports = Footer; diff --git a/website/i18n/en.json b/website/i18n/en.json deleted file mode 100644 index 7ad2cee78..000000000 --- a/website/i18n/en.json +++ /dev/null @@ -1,214 +0,0 @@ -{ - "_comment": "This file is auto-generated by write-translations.js", - "localized-strings": { - "next": "Next", - "previous": "Previous", - "tagline": "A game engine for functional programmers.", - "docs": { - "development-status": { - "title": "Indigo's Development Status" - }, - "gameloop/events": { - "title": "Events" - }, - "gameloop/frame-context": { - "title": "Frame context" - }, - "gameloop/outcome": { - "title": "Outcome Type" - }, - "guides": { - "title": "About these guides" - }, - "guides/howto-custom-entity": { - "title": "How to make a custom entity" - }, - "guides/howto-fire-shader": { - "title": "How to write a fire shader" - }, - "guides/howto-responsive-ui-with-tyrian": { - "title": "How to make a responsive UI using Tyrian" - }, - "guides/howto-indigo-game": { - "title": "Converting `IndigoSandbox` to `IndigoGame`" - }, - "information/alternatives": { - "title": "Alternatives to Indigo" - }, - "information/antipatterns": { - "title": "Anti-Patterns" - }, - "information/glossary": { - "title": "Glossary" - }, - "information/key-concepts": { - "title": "Key Concepts" - }, - "information/model-viewmodel-view": { - "title": "Model, ViewModel, & View" - }, - "information/motivation-and-constraints": { - "title": "Motivation & Constraints" - }, - "information/performance": { - "title": "Performance" - }, - "information/prior-art": { - "title": "Prior Art" - }, - "information/rendering-technology": { - "title": "Rendering Technology" - }, - "organisation/boot-and-start-up": { - "title": "Boot & Start Up" - }, - "organisation/game-entry-points": { - "title": "Game Entry Points" - }, - "organisation/scene-management": { - "title": "Scenes & Scene Management" - }, - "organisation/subsystems": { - "title": "SubSystems" - }, - "platform/assets": { - "title": "Assets & Asset Loading" - }, - "platform/cross-platform-publishing": { - "title": "Cross Platform Publishing" - }, - "platform/importers": { - "title": "File Format Importers" - }, - "platform/input-handling": { - "title": "User Input Handling" - }, - "platform/loading-and-saving-data": { - "title": "Loading & Saving Data" - }, - "platform/logging": { - "title": "Logging" - }, - "platform/networking": { - "title": "Networking" - }, - "presentation/animation": { - "title": "Animation" - }, - "presentation/audio": { - "title": "Audio" - }, - "presentation/boundaries": { - "title": "Boundaries" - }, - "presentation/cameras": { - "title": "Cameras" - }, - "presentation/clones-and-mutants": { - "title": "Clones & Mutants" - }, - "presentation/depth": { - "title": "Depth" - }, - "presentation/layers": { - "title": "Layers" - }, - "presentation/lighting": { - "title": "Lighting" - }, - "presentation/materials": { - "title": "Materials" - }, - "presentation/primitives": { - "title": "Primitives & Building Blocks" - }, - "presentation/scene-update-fragment": { - "title": "SceneUpdateFragment" - }, - "presentation/shapes": { - "title": "Shapes" - }, - "presentation/text-and-fonts": { - "title": "Text & Fonts" - }, - "quickstart/examples": { - "title": "Examples" - }, - "quickstart/hello-indigo": { - "title": "Hello, Indigo!" - }, - "quickstart/project-templates": { - "title": "Mill & SBT Game Templates" - }, - "quickstart/setup-and-configuration": { - "title": "Setup & Configuration" - }, - "shaders/blending": { - "title": "Blending" - }, - "shaders/constants": { - "title": "Shader Constants, Variables, and Outputs" - }, - "shaders/premultiplied-alpha": { - "title": "Premultiplied Alpha" - }, - "shaders/shader-overview": { - "title": "Shaders Overview" - }, - "time/signals": { - "title": "Signals & Signal Functions" - }, - "time/time-varying-values": { - "title": "Time Varying Values" - }, - "uicomponents/button": { - "title": "Buttons" - }, - "uicomponents/hit-area": { - "title": "Hit Area" - }, - "uicomponents/input-field": { - "title": "Input Field" - }, - "uicomponents/radio-button": { - "title": "Radio Button" - }, - "uicomponents/ui-components": { - "title": "Overview" - }, - "unused/computations": { - "title": "unused/computations" - }, - "unused/jobs": { - "title": "unused/jobs" - } - }, - "links": { - "Blog": "Blog", - "Guides": "Guides", - "Docs": "Docs", - "APIs": "APIs", - "Tools": "Tools", - "GitHub": "GitHub" - }, - "categories": { - "How To's": "How To's", - "Gamedev": "Gamedev", - "Indigo": "Indigo", - "Getting started": "Getting started", - "Organising your game": "Organising your game", - "The game loop": "The game loop", - "Presentation": "Presentation", - "UI Components": "UI Components", - "Shaders": "Shaders", - "Working with Time": "Working with Time", - "Platform & Publishing": "Platform & Publishing", - "Other information": "Other information" - } - }, - "pages-strings": { - "Help Translate|recruit community translators for your project": "Help Translate", - "Edit this Doc|recruitment message asking to edit the doc source": "Edit", - "Translate this Doc|recruitment message asking to translate the docs": "Translate" - } -} diff --git a/website/package.json b/website/package.json deleted file mode 100644 index 28c38e758..000000000 --- a/website/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "scripts": { - "examples": "docusaurus-examples", - "start": "docusaurus-start", - "build": "docusaurus-build", - "publish-gh-pages": "docusaurus-publish", - "write-translations": "docusaurus-write-translations", - "version": "docusaurus-version", - "rename-version": "docusaurus-rename-version" - }, - "devDependencies": { - "docusaurus": "^1.14.7" - } -} diff --git a/website/pages/en/index.js b/website/pages/en/index.js deleted file mode 100644 index c941ebe33..000000000 --- a/website/pages/en/index.js +++ /dev/null @@ -1,205 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -const React = require('react'); - -const CompLibrary = require('../../core/CompLibrary.js'); - -const MarkdownBlock = CompLibrary.MarkdownBlock; /* Used to read markdown */ -const Container = CompLibrary.Container; -const GridBlock = CompLibrary.GridBlock; - -class HomeSplash extends React.Component { - render() { - const {siteConfig, language = ''} = this.props; - const {baseUrl, docsUrl} = siteConfig; - const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`; - const langPart = `${language ? `${language}/` : ''}`; - const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}`; - - const SplashContainer = props => ( -
-
-
{props.children}
-
-
- ); - - const Logo = props => ( -
- Indigo Logo -
- ); - - const ProjectTitle = props => ( -

- {props.tagline} -

- ); - - const PromoSection = props => ( -
-
-
{props.children}
-
-
- ); - - const Button = props => ( -
- - {props.children} - -
- ); - - const pageUrl = page => baseUrl + (language ? `${language}/` : '') + page; - - return ( - - -
- - - - - - -
-
- ); - } -} - -class Index extends React.Component { - render() { - const {config: siteConfig, language = ''} = this.props; - const {baseUrl} = siteConfig; - - const Block = props => ( - - - - ); - - const Features = () => ( - - {[ - { - content: 'If you can write Scala, you can make games. Indigo is powered by Scala.js, and builds with sbt & Mill.', - image: `${baseUrl}img/site_scala_logo.png`, - imageAlign: 'top', - title: 'Nothing but Scala.', - }, - { - content: 'Confident development using Scala\'s advanced type system, purely functional APIs, and a deterministic game loop.', - image: `${baseUrl}img/site_pirate.png`, - imageAlign: 'top', - title: 'Easy to Type. Easy to Test.', - }, - { - content: 'Indigo was designed for crisp, modern, beautiful pixel art. You can make non-pixel art games too!', - image: `${baseUrl}img/site_consoles.png`, - imageAlign: 'top', - title: 'Big Beautiful Pixels.', - }, - ]} - - ); - - // const Description = () => ( - //
- //
- //
- //
- //

Let's have some fun!

- // - // Indigo is a game engine for functional programmers. People who know how to code and want to make games _by writing code_. Just for the fun of it! - // - // - // The engine has been designed specifically with programmers in mind. It focuses on developer productivity and ease of testing. - // - // - // Indigo is written in [**Scala**](https://www.scala-lang.org/) (powered by [**Scala.js**](https://www.scala-js.org/)), as are the amazing games you'll make. It's intended for the people who _really_ like pure functions, but being Scala, allows you too flip back to a more procedural or object oriented styles if that suits you or your game better. - // - //
- //
- //

 

- // - // Building games in Indigo is just like working any other Scala project, we've worked hard to keep the surprises to a minimum. You can even use all your favourite Scala.js compatible libraries and build tools, with extra support for SBT and Mill built in. - // - // - // Indigo is free to use and the engine is open source. There are no limits on its use, or fees or royalties to pay, ever. - // - // - // We can't wait to see what you're going to build! - // - //
- //
- //
- //
- // ); - - // const GetInvolved = () => ( - //
- //
- //
- //
- //

Who makes this?

- // - // Purple Kingdom Games is made up of two long time collaborators that like building software together. They are both called Dave. - // - // - // Although the bulk of the early work on Indigo came from the Dave's, since launch we've also gratefully recieved a number of wonderful community contributions too! - // - //
- //
- //

You can contribute!

- // - // We'd love you to get involved! You could... - // - //
    - //
  • Build a new [feature](https://github.com/PurpleKingdomGames/indigo/blob/master/CONTRIBUTING.md)
  • - //
  • Report an [issue](https://github.com/PurpleKingdomGames/indigo/issues)
  • - //
  • Help with the [documentation](https://github.com/PurpleKingdomGames/indigo-website)
  • - //
- // If you're not sure where to start or would like to discuss your ideas, come and say hello on [Discord](https://discord.gg/b5CD47g), or post a question on [GitHub Discussions](https://github.com/PurpleKingdomGames/indigo/discussions). - //
- //
- //

Please sponsor our work!

- // - // Indigo is a passion project, and in software, passion projects come from coffee and biscuits and ...from the ability to cover some less exciting running costs. - // - // - // If you like what we're doing and would like to help fuel Indigo's development, please consider sponsoring us on either [GitHub](https://github.com/sponsors/PurpleKingdomGames) or [Patreon](https://www.patreon.com/indigoengine). - // - //
- //
- //
- //
- // ); - - return ( -
- -
- - {/* - */} -
-
- ); - } -} - -module.exports = Index; diff --git a/website/pages/en/pirate.js b/website/pages/en/pirate.js deleted file mode 100644 index cc51c4e54..000000000 --- a/website/pages/en/pirate.js +++ /dev/null @@ -1,41 +0,0 @@ - -const React = require('react'); - -const CompLibrary = require('../../core/CompLibrary.js'); - -const Container = CompLibrary.Container; - - -class Snake extends React.Component { - render() { - const {config: siteConfig, language = ''} = this.props; - const {baseUrl} = siteConfig; - - const Game = props => ( -
-
- - - -
- ); - - return ( -
- - -
- For more information, please visit the examples repo.
- Requirements: Keyboard or PS4 controller, runs at fixed resolution of 1280x720.
- Keyboard: Left & right arrow keys to move. Up arrow or Spacebar to jump.
- PS4 Controllor: Left analog to move and 'X' button to jump. -
-
-
- ); - } -}; - -module.exports = Snake; diff --git a/website/pages/en/snake.js b/website/pages/en/snake.js deleted file mode 100644 index 7583c8bab..000000000 --- a/website/pages/en/snake.js +++ /dev/null @@ -1,40 +0,0 @@ - -const React = require('react'); - -const CompLibrary = require('../../core/CompLibrary.js'); - -const Container = CompLibrary.Container; - - -class Snake extends React.Component { - render() { - const {config: siteConfig, language = ''} = this.props; - const {baseUrl} = siteConfig; - - const Game = props => ( -
-
- - - -
- ); - - return ( -
- - -
- For more information, please visit the examples repo.
- Keyboard controls: Use Space bar and arrows keys to navigate and accept menus.
- Game controls are either left and right arrow keys to tunr left and right relative to the snake,
or press the arrow to change to the corresponding direction.
-
-
-
- ); - } -}; - -module.exports = Snake; diff --git a/website/project/plugins.sbt b/website/project/plugins.sbt index 12499a721..b8a8dc4d3 100644 --- a/website/project/plugins.sbt +++ b/website/project/plugins.sbt @@ -1,2 +1,3 @@ +addSbtPlugin("org.planet42" % "laika-sbt" % "0.19.3") addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.4.1") addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.3") diff --git a/website/reference/help.js b/website/reference/help.js deleted file mode 100644 index 1b17334e7..000000000 --- a/website/reference/help.js +++ /dev/null @@ -1,54 +0,0 @@ -// /** -// * Copyright (c) 2017-present, Facebook, Inc. -// * -// * This source code is licensed under the MIT license found in the -// * LICENSE file in the root directory of this source tree. -// */ - -// const React = require('react'); - -// const CompLibrary = require('../../core/CompLibrary.js'); - -// const Container = CompLibrary.Container; -// const GridBlock = CompLibrary.GridBlock; - -// function Help(props) { -// const {config: siteConfig, language = ''} = props; -// const {baseUrl, docsUrl} = siteConfig; -// const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`; -// const langPart = `${language ? `${language}/` : ''}`; -// const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}`; - -// const supportLinks = [ -// { -// content: `Learn more using the [documentation on this site.](${docUrl( -// 'doc1.html', -// )})`, -// title: 'Browse Docs', -// }, -// { -// content: 'Ask questions about the documentation and project', -// title: 'Join the community', -// }, -// { -// content: "Find out what's new with this project", -// title: 'Stay up to date', -// }, -// ]; - -// return ( -//
-// -//
-//
-//

Need help?

-//
-//

This project is maintained by a dedicated group of people.

-// -//
-//
-//
-// ); -// } - -// module.exports = Help; diff --git a/website/reference/users.js b/website/reference/users.js deleted file mode 100644 index b22523fd5..000000000 --- a/website/reference/users.js +++ /dev/null @@ -1,48 +0,0 @@ -// /** -// * Copyright (c) 2017-present, Facebook, Inc. -// * -// * This source code is licensed under the MIT license found in the -// * LICENSE file in the root directory of this source tree. -// */ - -// const React = require('react'); - -// const CompLibrary = require('../../core/CompLibrary.js'); - -// const Container = CompLibrary.Container; - -// class Users extends React.Component { -// render() { -// const {config: siteConfig} = this.props; -// if ((siteConfig.users || []).length === 0) { -// return null; -// } - -// const editUrl = `${siteConfig.repoUrl}/edit/master/website/siteConfig.js`; -// const showcase = siteConfig.users.map(user => ( -// -// {user.caption} -// -// )); - -// return ( -//
-// -//
-//
-//

Who is Using This?

-//

This project is used by many folks

-//
-//
{showcase}
-//

Are you using this project?

-// -// Add your company -// -//
-//
-//
-// ); -// } -// } - -// module.exports = Users; diff --git a/website/sidebars.json b/website/sidebars.json deleted file mode 100644 index 17383d475..000000000 --- a/website/sidebars.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "guides": { - "How To's": [ - "guides" - ], - "Gamedev": [ - "guides/howto-custom-entity", - "guides/howto-fire-shader", - "guides/howto-indigo-game", - "guides/howto-responsive-ui-with-tyrian" - ] - }, - "docs": { - "Indigo": [ - "development-status" - ], - "Getting started": [ - "quickstart/setup-and-configuration", - "quickstart/hello-indigo", - "quickstart/examples", - "quickstart/project-templates" - ], - "Organising your game": [ - "organisation/boot-and-start-up", - "organisation/game-entry-points", - "organisation/scene-management", - "organisation/subsystems" - ], - "The game loop": [ - "gameloop/events", - "gameloop/frame-context", - "gameloop/outcome" - ], - "Presentation": [ - "presentation/animation", - "presentation/audio", - "presentation/boundaries", - "presentation/cameras", - "presentation/clones-and-mutants", - "presentation/depth", - "presentation/layers", - "presentation/lighting", - "presentation/materials", - "presentation/primitives", - "presentation/scene-update-fragment", - "presentation/shapes", - "presentation/text-and-fonts" - ], - "UI Components": [ - "uicomponents/ui-components", - "uicomponents/button", - "uicomponents/hit-area", - "uicomponents/input-field", - "uicomponents/radio-button" - ], - "Shaders": [ - "shaders/shader-overview", - "shaders/constants", - "shaders/blending", - "shaders/premultiplied-alpha" - ], - "Working with Time": [ - "time/signals", - "time/time-varying-values" - ], - "Platform & Publishing": [ - "platform/assets", - "platform/cross-platform-publishing", - "platform/importers", - "platform/input-handling", - "platform/loading-and-saving-data", - "platform/logging", - "platform/networking" - ], - "Other information": [ - "information/alternatives", - "information/glossary", - "information/key-concepts", - "information/model-viewmodel-view", - "information/antipatterns", - "information/motivation-and-constraints", - "information/performance", - "information/prior-art", - "information/rendering-technology" - ] - } -} diff --git a/website/siteConfig.js b/website/siteConfig.js deleted file mode 100644 index 9aadef782..000000000 --- a/website/siteConfig.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -// See https://docusaurus.io/docs/site-config for all the possible -// site configuration options. - -// List of projects/orgs using your project for the users page. -// const users = [ -// { -// caption: 'User1', -// // You will need to prepend the image path with your baseUrl -// // if it is not '/', like: '/test-site/img/image.jpg'. -// image: '/img/undraw_open_source.svg', -// infoLink: 'https://www.facebook.com', -// pinned: true, -// }, -// ]; - -const siteConfig = { - title: 'Indigo', // Title for your website. - tagline: 'A game engine for functional programmers.', - url: 'https://your-docusaurus-test-site.com', // Your website URL - baseUrl: '/', // Base URL for your project */ - // For github.io type URLs, you would set the url and baseUrl like: - // url: 'https://facebook.github.io', - // baseUrl: '/test-site/', - - customDocsPath: '../indigo/indigo/indigo-docs/target/mdoc', - - // Used for publishing and more - projectName: 'indigo-site', - organizationName: 'purplekingdomgames', - // For top-level user or org sites, the organization is still the same. - // e.g., for the https://JoelMarcey.github.io site, it would be set like... - // organizationName: 'JoelMarcey' - - // For no header links in the top nav bar -> headerLinks: [], - headerLinks: [ - { blog: true, label: 'Blog' }, - { doc: 'guides', label: 'Guides' }, - { doc: 'development-status', label: 'Docs' }, - { href: "/api/", label: "APIs", external: false }, - { page: 'tools', label: 'Tools' }, - { href: "https://github.com/PurpleKingdomGames/indigo", label: "GitHub", external: true }, - ], - - blogSidebarTitle: { default: 'News & Updates', all: 'All posts' }, - blogSidebarCount: 'ALL', - - // If you have users set above, you add it here: - // users, - - /* path to images for header/footer */ - headerIcon: 'img/indigo_logo_solid_text.svg', - footerIcon: 'img/indigo_logo.svg', - favicon: 'img/indigo_logo_solid.svg', - - /* Colors for website */ - colors: { - primaryColor: '#29016A', - secondaryColor: '#29016A', - }, - - /* Custom fonts for website */ - /* - fonts: { - myFont: [ - "Times New Roman", - "Serif" - ], - myOtherFont: [ - "-apple-system", - "system-ui" - ] - }, - */ - - //GA - gaTrackingId: "UA-169190516-1", - gaGtag: true, - - // This copyright info is used in /core/Footer.js and blog RSS/Atom feeds. - copyright: `Copyright © ${new Date().getFullYear()} Purple Kingdom Games Limited`, - - highlight: { - // Highlight.js theme to use for syntax highlighting in code blocks. - theme: 'default', - }, - - // Add custom scripts here that would be placed in - - - - - diff --git a/website/static/tools/js/elm.compiled.min.js b/website/static/tools/js/elm.compiled.min.js deleted file mode 100644 index 6c3080622..000000000 --- a/website/static/tools/js/elm.compiled.min.js +++ /dev/null @@ -1,17733 +0,0 @@ -(function(scope){ -'use strict'; - -function F(arity, fun, wrapper) { - wrapper.a = arity; - wrapper.f = fun; - return wrapper; -} - -function F2(fun) { - return F(2, fun, function(a) { return function(b) { return fun(a,b); }; }) -} -function F3(fun) { - return F(3, fun, function(a) { - return function(b) { return function(c) { return fun(a, b, c); }; }; - }); -} -function F4(fun) { - return F(4, fun, function(a) { return function(b) { return function(c) { - return function(d) { return fun(a, b, c, d); }; }; }; - }); -} -function F5(fun) { - return F(5, fun, function(a) { return function(b) { return function(c) { - return function(d) { return function(e) { return fun(a, b, c, d, e); }; }; }; }; - }); -} -function F6(fun) { - return F(6, fun, function(a) { return function(b) { return function(c) { - return function(d) { return function(e) { return function(f) { - return fun(a, b, c, d, e, f); }; }; }; }; }; - }); -} -function F7(fun) { - return F(7, fun, function(a) { return function(b) { return function(c) { - return function(d) { return function(e) { return function(f) { - return function(g) { return fun(a, b, c, d, e, f, g); }; }; }; }; }; }; - }); -} -function F8(fun) { - return F(8, fun, function(a) { return function(b) { return function(c) { - return function(d) { return function(e) { return function(f) { - return function(g) { return function(h) { - return fun(a, b, c, d, e, f, g, h); }; }; }; }; }; }; }; - }); -} -function F9(fun) { - return F(9, fun, function(a) { return function(b) { return function(c) { - return function(d) { return function(e) { return function(f) { - return function(g) { return function(h) { return function(i) { - return fun(a, b, c, d, e, f, g, h, i); }; }; }; }; }; }; }; }; - }); -} - -function A2(fun, a, b) { - return fun.a === 2 ? fun.f(a, b) : fun(a)(b); -} -function A3(fun, a, b, c) { - return fun.a === 3 ? fun.f(a, b, c) : fun(a)(b)(c); -} -function A4(fun, a, b, c, d) { - return fun.a === 4 ? fun.f(a, b, c, d) : fun(a)(b)(c)(d); -} -function A5(fun, a, b, c, d, e) { - return fun.a === 5 ? fun.f(a, b, c, d, e) : fun(a)(b)(c)(d)(e); -} -function A6(fun, a, b, c, d, e, f) { - return fun.a === 6 ? fun.f(a, b, c, d, e, f) : fun(a)(b)(c)(d)(e)(f); -} -function A7(fun, a, b, c, d, e, f, g) { - return fun.a === 7 ? fun.f(a, b, c, d, e, f, g) : fun(a)(b)(c)(d)(e)(f)(g); -} -function A8(fun, a, b, c, d, e, f, g, h) { - return fun.a === 8 ? fun.f(a, b, c, d, e, f, g, h) : fun(a)(b)(c)(d)(e)(f)(g)(h); -} -function A9(fun, a, b, c, d, e, f, g, h, i) { - return fun.a === 9 ? fun.f(a, b, c, d, e, f, g, h, i) : fun(a)(b)(c)(d)(e)(f)(g)(h)(i); -} - -console.warn('Compiled in DEV mode. Follow the advice at https://elm-lang.org/0.19.1/optimize for better performance and smaller assets.'); - - -// EQUALITY - -function _Utils_eq(x, y) -{ - for ( - var pair, stack = [], isEqual = _Utils_eqHelp(x, y, 0, stack); - isEqual && (pair = stack.pop()); - isEqual = _Utils_eqHelp(pair.a, pair.b, 0, stack) - ) - {} - - return isEqual; -} - -function _Utils_eqHelp(x, y, depth, stack) -{ - if (depth > 100) - { - stack.push(_Utils_Tuple2(x,y)); - return true; - } - - if (x === y) - { - return true; - } - - if (typeof x !== 'object' || x === null || y === null) - { - typeof x === 'function' && _Debug_crash(5); - return false; - } - - /**/ - if (x.$ === 'Set_elm_builtin') - { - x = $elm$core$Set$toList(x); - y = $elm$core$Set$toList(y); - } - if (x.$ === 'RBNode_elm_builtin' || x.$ === 'RBEmpty_elm_builtin') - { - x = $elm$core$Dict$toList(x); - y = $elm$core$Dict$toList(y); - } - //*/ - - /**_UNUSED/ - if (x.$ < 0) - { - x = $elm$core$Dict$toList(x); - y = $elm$core$Dict$toList(y); - } - //*/ - - for (var key in x) - { - if (!_Utils_eqHelp(x[key], y[key], depth + 1, stack)) - { - return false; - } - } - return true; -} - -var _Utils_equal = F2(_Utils_eq); -var _Utils_notEqual = F2(function(a, b) { return !_Utils_eq(a,b); }); - - - -// COMPARISONS - -// Code in Generate/JavaScript.hs, Basics.js, and List.js depends on -// the particular integer values assigned to LT, EQ, and GT. - -function _Utils_cmp(x, y, ord) -{ - if (typeof x !== 'object') - { - return x === y ? /*EQ*/ 0 : x < y ? /*LT*/ -1 : /*GT*/ 1; - } - - /**/ - if (x instanceof String) - { - var a = x.valueOf(); - var b = y.valueOf(); - return a === b ? 0 : a < b ? -1 : 1; - } - //*/ - - /**_UNUSED/ - if (typeof x.$ === 'undefined') - //*/ - /**/ - if (x.$[0] === '#') - //*/ - { - return (ord = _Utils_cmp(x.a, y.a)) - ? ord - : (ord = _Utils_cmp(x.b, y.b)) - ? ord - : _Utils_cmp(x.c, y.c); - } - - // traverse conses until end of a list or a mismatch - for (; x.b && y.b && !(ord = _Utils_cmp(x.a, y.a)); x = x.b, y = y.b) {} // WHILE_CONSES - return ord || (x.b ? /*GT*/ 1 : y.b ? /*LT*/ -1 : /*EQ*/ 0); -} - -var _Utils_lt = F2(function(a, b) { return _Utils_cmp(a, b) < 0; }); -var _Utils_le = F2(function(a, b) { return _Utils_cmp(a, b) < 1; }); -var _Utils_gt = F2(function(a, b) { return _Utils_cmp(a, b) > 0; }); -var _Utils_ge = F2(function(a, b) { return _Utils_cmp(a, b) >= 0; }); - -var _Utils_compare = F2(function(x, y) -{ - var n = _Utils_cmp(x, y); - return n < 0 ? $elm$core$Basics$LT : n ? $elm$core$Basics$GT : $elm$core$Basics$EQ; -}); - - -// COMMON VALUES - -var _Utils_Tuple0_UNUSED = 0; -var _Utils_Tuple0 = { $: '#0' }; - -function _Utils_Tuple2_UNUSED(a, b) { return { a: a, b: b }; } -function _Utils_Tuple2(a, b) { return { $: '#2', a: a, b: b }; } - -function _Utils_Tuple3_UNUSED(a, b, c) { return { a: a, b: b, c: c }; } -function _Utils_Tuple3(a, b, c) { return { $: '#3', a: a, b: b, c: c }; } - -function _Utils_chr_UNUSED(c) { return c; } -function _Utils_chr(c) { return new String(c); } - - -// RECORDS - -function _Utils_update(oldRecord, updatedFields) -{ - var newRecord = {}; - - for (var key in oldRecord) - { - newRecord[key] = oldRecord[key]; - } - - for (var key in updatedFields) - { - newRecord[key] = updatedFields[key]; - } - - return newRecord; -} - - -// APPEND - -var _Utils_append = F2(_Utils_ap); - -function _Utils_ap(xs, ys) -{ - // append Strings - if (typeof xs === 'string') - { - return xs + ys; - } - - // append Lists - if (!xs.b) - { - return ys; - } - var root = _List_Cons(xs.a, ys); - xs = xs.b - for (var curr = root; xs.b; xs = xs.b) // WHILE_CONS - { - curr = curr.b = _List_Cons(xs.a, ys); - } - return root; -} - - - -var _List_Nil_UNUSED = { $: 0 }; -var _List_Nil = { $: '[]' }; - -function _List_Cons_UNUSED(hd, tl) { return { $: 1, a: hd, b: tl }; } -function _List_Cons(hd, tl) { return { $: '::', a: hd, b: tl }; } - - -var _List_cons = F2(_List_Cons); - -function _List_fromArray(arr) -{ - var out = _List_Nil; - for (var i = arr.length; i--; ) - { - out = _List_Cons(arr[i], out); - } - return out; -} - -function _List_toArray(xs) -{ - for (var out = []; xs.b; xs = xs.b) // WHILE_CONS - { - out.push(xs.a); - } - return out; -} - -var _List_map2 = F3(function(f, xs, ys) -{ - for (var arr = []; xs.b && ys.b; xs = xs.b, ys = ys.b) // WHILE_CONSES - { - arr.push(A2(f, xs.a, ys.a)); - } - return _List_fromArray(arr); -}); - -var _List_map3 = F4(function(f, xs, ys, zs) -{ - for (var arr = []; xs.b && ys.b && zs.b; xs = xs.b, ys = ys.b, zs = zs.b) // WHILE_CONSES - { - arr.push(A3(f, xs.a, ys.a, zs.a)); - } - return _List_fromArray(arr); -}); - -var _List_map4 = F5(function(f, ws, xs, ys, zs) -{ - for (var arr = []; ws.b && xs.b && ys.b && zs.b; ws = ws.b, xs = xs.b, ys = ys.b, zs = zs.b) // WHILE_CONSES - { - arr.push(A4(f, ws.a, xs.a, ys.a, zs.a)); - } - return _List_fromArray(arr); -}); - -var _List_map5 = F6(function(f, vs, ws, xs, ys, zs) -{ - for (var arr = []; vs.b && ws.b && xs.b && ys.b && zs.b; vs = vs.b, ws = ws.b, xs = xs.b, ys = ys.b, zs = zs.b) // WHILE_CONSES - { - arr.push(A5(f, vs.a, ws.a, xs.a, ys.a, zs.a)); - } - return _List_fromArray(arr); -}); - -var _List_sortBy = F2(function(f, xs) -{ - return _List_fromArray(_List_toArray(xs).sort(function(a, b) { - return _Utils_cmp(f(a), f(b)); - })); -}); - -var _List_sortWith = F2(function(f, xs) -{ - return _List_fromArray(_List_toArray(xs).sort(function(a, b) { - var ord = A2(f, a, b); - return ord === $elm$core$Basics$EQ ? 0 : ord === $elm$core$Basics$LT ? -1 : 1; - })); -}); - - - -var _JsArray_empty = []; - -function _JsArray_singleton(value) -{ - return [value]; -} - -function _JsArray_length(array) -{ - return array.length; -} - -var _JsArray_initialize = F3(function(size, offset, func) -{ - var result = new Array(size); - - for (var i = 0; i < size; i++) - { - result[i] = func(offset + i); - } - - return result; -}); - -var _JsArray_initializeFromList = F2(function (max, ls) -{ - var result = new Array(max); - - for (var i = 0; i < max && ls.b; i++) - { - result[i] = ls.a; - ls = ls.b; - } - - result.length = i; - return _Utils_Tuple2(result, ls); -}); - -var _JsArray_unsafeGet = F2(function(index, array) -{ - return array[index]; -}); - -var _JsArray_unsafeSet = F3(function(index, value, array) -{ - var length = array.length; - var result = new Array(length); - - for (var i = 0; i < length; i++) - { - result[i] = array[i]; - } - - result[index] = value; - return result; -}); - -var _JsArray_push = F2(function(value, array) -{ - var length = array.length; - var result = new Array(length + 1); - - for (var i = 0; i < length; i++) - { - result[i] = array[i]; - } - - result[length] = value; - return result; -}); - -var _JsArray_foldl = F3(function(func, acc, array) -{ - var length = array.length; - - for (var i = 0; i < length; i++) - { - acc = A2(func, array[i], acc); - } - - return acc; -}); - -var _JsArray_foldr = F3(function(func, acc, array) -{ - for (var i = array.length - 1; i >= 0; i--) - { - acc = A2(func, array[i], acc); - } - - return acc; -}); - -var _JsArray_map = F2(function(func, array) -{ - var length = array.length; - var result = new Array(length); - - for (var i = 0; i < length; i++) - { - result[i] = func(array[i]); - } - - return result; -}); - -var _JsArray_indexedMap = F3(function(func, offset, array) -{ - var length = array.length; - var result = new Array(length); - - for (var i = 0; i < length; i++) - { - result[i] = A2(func, offset + i, array[i]); - } - - return result; -}); - -var _JsArray_slice = F3(function(from, to, array) -{ - return array.slice(from, to); -}); - -var _JsArray_appendN = F3(function(n, dest, source) -{ - var destLen = dest.length; - var itemsToCopy = n - destLen; - - if (itemsToCopy > source.length) - { - itemsToCopy = source.length; - } - - var size = destLen + itemsToCopy; - var result = new Array(size); - - for (var i = 0; i < destLen; i++) - { - result[i] = dest[i]; - } - - for (var i = 0; i < itemsToCopy; i++) - { - result[i + destLen] = source[i]; - } - - return result; -}); - - - -// LOG - -var _Debug_log_UNUSED = F2(function(tag, value) -{ - return value; -}); - -var _Debug_log = F2(function(tag, value) -{ - console.log(tag + ': ' + _Debug_toString(value)); - return value; -}); - - -// TODOS - -function _Debug_todo(moduleName, region) -{ - return function(message) { - _Debug_crash(8, moduleName, region, message); - }; -} - -function _Debug_todoCase(moduleName, region, value) -{ - return function(message) { - _Debug_crash(9, moduleName, region, value, message); - }; -} - - -// TO STRING - -function _Debug_toString_UNUSED(value) -{ - return ''; -} - -function _Debug_toString(value) -{ - return _Debug_toAnsiString(false, value); -} - -function _Debug_toAnsiString(ansi, value) -{ - if (typeof value === 'function') - { - return _Debug_internalColor(ansi, ''); - } - - if (typeof value === 'boolean') - { - return _Debug_ctorColor(ansi, value ? 'True' : 'False'); - } - - if (typeof value === 'number') - { - return _Debug_numberColor(ansi, value + ''); - } - - if (value instanceof String) - { - return _Debug_charColor(ansi, "'" + _Debug_addSlashes(value, true) + "'"); - } - - if (typeof value === 'string') - { - return _Debug_stringColor(ansi, '"' + _Debug_addSlashes(value, false) + '"'); - } - - if (typeof value === 'object' && '$' in value) - { - var tag = value.$; - - if (typeof tag === 'number') - { - return _Debug_internalColor(ansi, ''); - } - - if (tag[0] === '#') - { - var output = []; - for (var k in value) - { - if (k === '$') continue; - output.push(_Debug_toAnsiString(ansi, value[k])); - } - return '(' + output.join(',') + ')'; - } - - if (tag === 'Set_elm_builtin') - { - return _Debug_ctorColor(ansi, 'Set') - + _Debug_fadeColor(ansi, '.fromList') + ' ' - + _Debug_toAnsiString(ansi, $elm$core$Set$toList(value)); - } - - if (tag === 'RBNode_elm_builtin' || tag === 'RBEmpty_elm_builtin') - { - return _Debug_ctorColor(ansi, 'Dict') - + _Debug_fadeColor(ansi, '.fromList') + ' ' - + _Debug_toAnsiString(ansi, $elm$core$Dict$toList(value)); - } - - if (tag === 'Array_elm_builtin') - { - return _Debug_ctorColor(ansi, 'Array') - + _Debug_fadeColor(ansi, '.fromList') + ' ' - + _Debug_toAnsiString(ansi, $elm$core$Array$toList(value)); - } - - if (tag === '::' || tag === '[]') - { - var output = '['; - - value.b && (output += _Debug_toAnsiString(ansi, value.a), value = value.b) - - for (; value.b; value = value.b) // WHILE_CONS - { - output += ',' + _Debug_toAnsiString(ansi, value.a); - } - return output + ']'; - } - - var output = ''; - for (var i in value) - { - if (i === '$') continue; - var str = _Debug_toAnsiString(ansi, value[i]); - var c0 = str[0]; - var parenless = c0 === '{' || c0 === '(' || c0 === '[' || c0 === '<' || c0 === '"' || str.indexOf(' ') < 0; - output += ' ' + (parenless ? str : '(' + str + ')'); - } - return _Debug_ctorColor(ansi, tag) + output; - } - - if (typeof DataView === 'function' && value instanceof DataView) - { - return _Debug_stringColor(ansi, '<' + value.byteLength + ' bytes>'); - } - - if (typeof File === 'function' && value instanceof File) - { - return _Debug_internalColor(ansi, '<' + value.name + '>'); - } - - if (typeof value === 'object') - { - var output = []; - for (var key in value) - { - var field = key[0] === '_' ? key.slice(1) : key; - output.push(_Debug_fadeColor(ansi, field) + ' = ' + _Debug_toAnsiString(ansi, value[key])); - } - if (output.length === 0) - { - return '{}'; - } - return '{ ' + output.join(', ') + ' }'; - } - - return _Debug_internalColor(ansi, ''); -} - -function _Debug_addSlashes(str, isChar) -{ - var s = str - .replace(/\\/g, '\\\\') - .replace(/\n/g, '\\n') - .replace(/\t/g, '\\t') - .replace(/\r/g, '\\r') - .replace(/\v/g, '\\v') - .replace(/\0/g, '\\0'); - - if (isChar) - { - return s.replace(/\'/g, '\\\''); - } - else - { - return s.replace(/\"/g, '\\"'); - } -} - -function _Debug_ctorColor(ansi, string) -{ - return ansi ? '\x1b[96m' + string + '\x1b[0m' : string; -} - -function _Debug_numberColor(ansi, string) -{ - return ansi ? '\x1b[95m' + string + '\x1b[0m' : string; -} - -function _Debug_stringColor(ansi, string) -{ - return ansi ? '\x1b[93m' + string + '\x1b[0m' : string; -} - -function _Debug_charColor(ansi, string) -{ - return ansi ? '\x1b[92m' + string + '\x1b[0m' : string; -} - -function _Debug_fadeColor(ansi, string) -{ - return ansi ? '\x1b[37m' + string + '\x1b[0m' : string; -} - -function _Debug_internalColor(ansi, string) -{ - return ansi ? '\x1b[94m' + string + '\x1b[0m' : string; -} - -function _Debug_toHexDigit(n) -{ - return String.fromCharCode(n < 10 ? 48 + n : 55 + n); -} - - -// CRASH - - -function _Debug_crash_UNUSED(identifier) -{ - throw new Error('https://github.com/elm/core/blob/1.0.0/hints/' + identifier + '.md'); -} - - -function _Debug_crash(identifier, fact1, fact2, fact3, fact4) -{ - switch(identifier) - { - case 0: - throw new Error('What node should I take over? In JavaScript I need something like:\n\n Elm.Main.init({\n node: document.getElementById("elm-node")\n })\n\nYou need to do this with any Browser.sandbox or Browser.element program.'); - - case 1: - throw new Error('Browser.application programs cannot handle URLs like this:\n\n ' + document.location.href + '\n\nWhat is the root? The root of your file system? Try looking at this program with `elm reactor` or some other server.'); - - case 2: - var jsonErrorString = fact1; - throw new Error('Problem with the flags given to your Elm program on initialization.\n\n' + jsonErrorString); - - case 3: - var portName = fact1; - throw new Error('There can only be one port named `' + portName + '`, but your program has multiple.'); - - case 4: - var portName = fact1; - var problem = fact2; - throw new Error('Trying to send an unexpected type of value through port `' + portName + '`:\n' + problem); - - case 5: - throw new Error('Trying to use `(==)` on functions.\nThere is no way to know if functions are "the same" in the Elm sense.\nRead more about this at https://package.elm-lang.org/packages/elm/core/latest/Basics#== which describes why it is this way and what the better version will look like.'); - - case 6: - var moduleName = fact1; - throw new Error('Your page is loading multiple Elm scripts with a module named ' + moduleName + '. Maybe a duplicate script is getting loaded accidentally? If not, rename one of them so I know which is which!'); - - case 8: - var moduleName = fact1; - var region = fact2; - var message = fact3; - throw new Error('TODO in module `' + moduleName + '` ' + _Debug_regionToString(region) + '\n\n' + message); - - case 9: - var moduleName = fact1; - var region = fact2; - var value = fact3; - var message = fact4; - throw new Error( - 'TODO in module `' + moduleName + '` from the `case` expression ' - + _Debug_regionToString(region) + '\n\nIt received the following value:\n\n ' - + _Debug_toString(value).replace('\n', '\n ') - + '\n\nBut the branch that handles it says:\n\n ' + message.replace('\n', '\n ') - ); - - case 10: - throw new Error('Bug in https://github.com/elm/virtual-dom/issues'); - - case 11: - throw new Error('Cannot perform mod 0. Division by zero error.'); - } -} - -function _Debug_regionToString(region) -{ - if (region.start.line === region.end.line) - { - return 'on line ' + region.start.line; - } - return 'on lines ' + region.start.line + ' through ' + region.end.line; -} - - - -// MATH - -var _Basics_add = F2(function(a, b) { return a + b; }); -var _Basics_sub = F2(function(a, b) { return a - b; }); -var _Basics_mul = F2(function(a, b) { return a * b; }); -var _Basics_fdiv = F2(function(a, b) { return a / b; }); -var _Basics_idiv = F2(function(a, b) { return (a / b) | 0; }); -var _Basics_pow = F2(Math.pow); - -var _Basics_remainderBy = F2(function(b, a) { return a % b; }); - -// https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf -var _Basics_modBy = F2(function(modulus, x) -{ - var answer = x % modulus; - return modulus === 0 - ? _Debug_crash(11) - : - ((answer > 0 && modulus < 0) || (answer < 0 && modulus > 0)) - ? answer + modulus - : answer; -}); - - -// TRIGONOMETRY - -var _Basics_pi = Math.PI; -var _Basics_e = Math.E; -var _Basics_cos = Math.cos; -var _Basics_sin = Math.sin; -var _Basics_tan = Math.tan; -var _Basics_acos = Math.acos; -var _Basics_asin = Math.asin; -var _Basics_atan = Math.atan; -var _Basics_atan2 = F2(Math.atan2); - - -// MORE MATH - -function _Basics_toFloat(x) { return x; } -function _Basics_truncate(n) { return n | 0; } -function _Basics_isInfinite(n) { return n === Infinity || n === -Infinity; } - -var _Basics_ceiling = Math.ceil; -var _Basics_floor = Math.floor; -var _Basics_round = Math.round; -var _Basics_sqrt = Math.sqrt; -var _Basics_log = Math.log; -var _Basics_isNaN = isNaN; - - -// BOOLEANS - -function _Basics_not(bool) { return !bool; } -var _Basics_and = F2(function(a, b) { return a && b; }); -var _Basics_or = F2(function(a, b) { return a || b; }); -var _Basics_xor = F2(function(a, b) { return a !== b; }); - - - -var _String_cons = F2(function(chr, str) -{ - return chr + str; -}); - -function _String_uncons(string) -{ - var word = string.charCodeAt(0); - return word - ? $elm$core$Maybe$Just( - 0xD800 <= word && word <= 0xDBFF - ? _Utils_Tuple2(_Utils_chr(string[0] + string[1]), string.slice(2)) - : _Utils_Tuple2(_Utils_chr(string[0]), string.slice(1)) - ) - : $elm$core$Maybe$Nothing; -} - -var _String_append = F2(function(a, b) -{ - return a + b; -}); - -function _String_length(str) -{ - return str.length; -} - -var _String_map = F2(function(func, string) -{ - var len = string.length; - var array = new Array(len); - var i = 0; - while (i < len) - { - var word = string.charCodeAt(i); - if (0xD800 <= word && word <= 0xDBFF) - { - array[i] = func(_Utils_chr(string[i] + string[i+1])); - i += 2; - continue; - } - array[i] = func(_Utils_chr(string[i])); - i++; - } - return array.join(''); -}); - -var _String_filter = F2(function(isGood, str) -{ - var arr = []; - var len = str.length; - var i = 0; - while (i < len) - { - var char = str[i]; - var word = str.charCodeAt(i); - i++; - if (0xD800 <= word && word <= 0xDBFF) - { - char += str[i]; - i++; - } - - if (isGood(_Utils_chr(char))) - { - arr.push(char); - } - } - return arr.join(''); -}); - -function _String_reverse(str) -{ - var len = str.length; - var arr = new Array(len); - var i = 0; - while (i < len) - { - var word = str.charCodeAt(i); - if (0xD800 <= word && word <= 0xDBFF) - { - arr[len - i] = str[i + 1]; - i++; - arr[len - i] = str[i - 1]; - i++; - } - else - { - arr[len - i] = str[i]; - i++; - } - } - return arr.join(''); -} - -var _String_foldl = F3(function(func, state, string) -{ - var len = string.length; - var i = 0; - while (i < len) - { - var char = string[i]; - var word = string.charCodeAt(i); - i++; - if (0xD800 <= word && word <= 0xDBFF) - { - char += string[i]; - i++; - } - state = A2(func, _Utils_chr(char), state); - } - return state; -}); - -var _String_foldr = F3(function(func, state, string) -{ - var i = string.length; - while (i--) - { - var char = string[i]; - var word = string.charCodeAt(i); - if (0xDC00 <= word && word <= 0xDFFF) - { - i--; - char = string[i] + char; - } - state = A2(func, _Utils_chr(char), state); - } - return state; -}); - -var _String_split = F2(function(sep, str) -{ - return str.split(sep); -}); - -var _String_join = F2(function(sep, strs) -{ - return strs.join(sep); -}); - -var _String_slice = F3(function(start, end, str) { - return str.slice(start, end); -}); - -function _String_trim(str) -{ - return str.trim(); -} - -function _String_trimLeft(str) -{ - return str.replace(/^\s+/, ''); -} - -function _String_trimRight(str) -{ - return str.replace(/\s+$/, ''); -} - -function _String_words(str) -{ - return _List_fromArray(str.trim().split(/\s+/g)); -} - -function _String_lines(str) -{ - return _List_fromArray(str.split(/\r\n|\r|\n/g)); -} - -function _String_toUpper(str) -{ - return str.toUpperCase(); -} - -function _String_toLower(str) -{ - return str.toLowerCase(); -} - -var _String_any = F2(function(isGood, string) -{ - var i = string.length; - while (i--) - { - var char = string[i]; - var word = string.charCodeAt(i); - if (0xDC00 <= word && word <= 0xDFFF) - { - i--; - char = string[i] + char; - } - if (isGood(_Utils_chr(char))) - { - return true; - } - } - return false; -}); - -var _String_all = F2(function(isGood, string) -{ - var i = string.length; - while (i--) - { - var char = string[i]; - var word = string.charCodeAt(i); - if (0xDC00 <= word && word <= 0xDFFF) - { - i--; - char = string[i] + char; - } - if (!isGood(_Utils_chr(char))) - { - return false; - } - } - return true; -}); - -var _String_contains = F2(function(sub, str) -{ - return str.indexOf(sub) > -1; -}); - -var _String_startsWith = F2(function(sub, str) -{ - return str.indexOf(sub) === 0; -}); - -var _String_endsWith = F2(function(sub, str) -{ - return str.length >= sub.length && - str.lastIndexOf(sub) === str.length - sub.length; -}); - -var _String_indexes = F2(function(sub, str) -{ - var subLen = sub.length; - - if (subLen < 1) - { - return _List_Nil; - } - - var i = 0; - var is = []; - - while ((i = str.indexOf(sub, i)) > -1) - { - is.push(i); - i = i + subLen; - } - - return _List_fromArray(is); -}); - - -// TO STRING - -function _String_fromNumber(number) -{ - return number + ''; -} - - -// INT CONVERSIONS - -function _String_toInt(str) -{ - var total = 0; - var code0 = str.charCodeAt(0); - var start = code0 == 0x2B /* + */ || code0 == 0x2D /* - */ ? 1 : 0; - - for (var i = start; i < str.length; ++i) - { - var code = str.charCodeAt(i); - if (code < 0x30 || 0x39 < code) - { - return $elm$core$Maybe$Nothing; - } - total = 10 * total + code - 0x30; - } - - return i == start - ? $elm$core$Maybe$Nothing - : $elm$core$Maybe$Just(code0 == 0x2D ? -total : total); -} - - -// FLOAT CONVERSIONS - -function _String_toFloat(s) -{ - // check if it is a hex, octal, or binary number - if (s.length === 0 || /[\sxbo]/.test(s)) - { - return $elm$core$Maybe$Nothing; - } - var n = +s; - // faster isNaN check - return n === n ? $elm$core$Maybe$Just(n) : $elm$core$Maybe$Nothing; -} - -function _String_fromList(chars) -{ - return _List_toArray(chars).join(''); -} - - - - -function _Char_toCode(char) -{ - var code = char.charCodeAt(0); - if (0xD800 <= code && code <= 0xDBFF) - { - return (code - 0xD800) * 0x400 + char.charCodeAt(1) - 0xDC00 + 0x10000 - } - return code; -} - -function _Char_fromCode(code) -{ - return _Utils_chr( - (code < 0 || 0x10FFFF < code) - ? '\uFFFD' - : - (code <= 0xFFFF) - ? String.fromCharCode(code) - : - (code -= 0x10000, - String.fromCharCode(Math.floor(code / 0x400) + 0xD800, code % 0x400 + 0xDC00) - ) - ); -} - -function _Char_toUpper(char) -{ - return _Utils_chr(char.toUpperCase()); -} - -function _Char_toLower(char) -{ - return _Utils_chr(char.toLowerCase()); -} - -function _Char_toLocaleUpper(char) -{ - return _Utils_chr(char.toLocaleUpperCase()); -} - -function _Char_toLocaleLower(char) -{ - return _Utils_chr(char.toLocaleLowerCase()); -} - - - -/**/ -function _Json_errorToString(error) -{ - return $elm$json$Json$Decode$errorToString(error); -} -//*/ - - -// CORE DECODERS - -function _Json_succeed(msg) -{ - return { - $: 0, - a: msg - }; -} - -function _Json_fail(msg) -{ - return { - $: 1, - a: msg - }; -} - -function _Json_decodePrim(decoder) -{ - return { $: 2, b: decoder }; -} - -var _Json_decodeInt = _Json_decodePrim(function(value) { - return (typeof value !== 'number') - ? _Json_expecting('an INT', value) - : - (-2147483647 < value && value < 2147483647 && (value | 0) === value) - ? $elm$core$Result$Ok(value) - : - (isFinite(value) && !(value % 1)) - ? $elm$core$Result$Ok(value) - : _Json_expecting('an INT', value); -}); - -var _Json_decodeBool = _Json_decodePrim(function(value) { - return (typeof value === 'boolean') - ? $elm$core$Result$Ok(value) - : _Json_expecting('a BOOL', value); -}); - -var _Json_decodeFloat = _Json_decodePrim(function(value) { - return (typeof value === 'number') - ? $elm$core$Result$Ok(value) - : _Json_expecting('a FLOAT', value); -}); - -var _Json_decodeValue = _Json_decodePrim(function(value) { - return $elm$core$Result$Ok(_Json_wrap(value)); -}); - -var _Json_decodeString = _Json_decodePrim(function(value) { - return (typeof value === 'string') - ? $elm$core$Result$Ok(value) - : (value instanceof String) - ? $elm$core$Result$Ok(value + '') - : _Json_expecting('a STRING', value); -}); - -function _Json_decodeList(decoder) { return { $: 3, b: decoder }; } -function _Json_decodeArray(decoder) { return { $: 4, b: decoder }; } - -function _Json_decodeNull(value) { return { $: 5, c: value }; } - -var _Json_decodeField = F2(function(field, decoder) -{ - return { - $: 6, - d: field, - b: decoder - }; -}); - -var _Json_decodeIndex = F2(function(index, decoder) -{ - return { - $: 7, - e: index, - b: decoder - }; -}); - -function _Json_decodeKeyValuePairs(decoder) -{ - return { - $: 8, - b: decoder - }; -} - -function _Json_mapMany(f, decoders) -{ - return { - $: 9, - f: f, - g: decoders - }; -} - -var _Json_andThen = F2(function(callback, decoder) -{ - return { - $: 10, - b: decoder, - h: callback - }; -}); - -function _Json_oneOf(decoders) -{ - return { - $: 11, - g: decoders - }; -} - - -// DECODING OBJECTS - -var _Json_map1 = F2(function(f, d1) -{ - return _Json_mapMany(f, [d1]); -}); - -var _Json_map2 = F3(function(f, d1, d2) -{ - return _Json_mapMany(f, [d1, d2]); -}); - -var _Json_map3 = F4(function(f, d1, d2, d3) -{ - return _Json_mapMany(f, [d1, d2, d3]); -}); - -var _Json_map4 = F5(function(f, d1, d2, d3, d4) -{ - return _Json_mapMany(f, [d1, d2, d3, d4]); -}); - -var _Json_map5 = F6(function(f, d1, d2, d3, d4, d5) -{ - return _Json_mapMany(f, [d1, d2, d3, d4, d5]); -}); - -var _Json_map6 = F7(function(f, d1, d2, d3, d4, d5, d6) -{ - return _Json_mapMany(f, [d1, d2, d3, d4, d5, d6]); -}); - -var _Json_map7 = F8(function(f, d1, d2, d3, d4, d5, d6, d7) -{ - return _Json_mapMany(f, [d1, d2, d3, d4, d5, d6, d7]); -}); - -var _Json_map8 = F9(function(f, d1, d2, d3, d4, d5, d6, d7, d8) -{ - return _Json_mapMany(f, [d1, d2, d3, d4, d5, d6, d7, d8]); -}); - - -// DECODE - -var _Json_runOnString = F2(function(decoder, string) -{ - try - { - var value = JSON.parse(string); - return _Json_runHelp(decoder, value); - } - catch (e) - { - return $elm$core$Result$Err(A2($elm$json$Json$Decode$Failure, 'This is not valid JSON! ' + e.message, _Json_wrap(string))); - } -}); - -var _Json_run = F2(function(decoder, value) -{ - return _Json_runHelp(decoder, _Json_unwrap(value)); -}); - -function _Json_runHelp(decoder, value) -{ - switch (decoder.$) - { - case 2: - return decoder.b(value); - - case 5: - return (value === null) - ? $elm$core$Result$Ok(decoder.c) - : _Json_expecting('null', value); - - case 3: - if (!_Json_isArray(value)) - { - return _Json_expecting('a LIST', value); - } - return _Json_runArrayDecoder(decoder.b, value, _List_fromArray); - - case 4: - if (!_Json_isArray(value)) - { - return _Json_expecting('an ARRAY', value); - } - return _Json_runArrayDecoder(decoder.b, value, _Json_toElmArray); - - case 6: - var field = decoder.d; - if (typeof value !== 'object' || value === null || !(field in value)) - { - return _Json_expecting('an OBJECT with a field named `' + field + '`', value); - } - var result = _Json_runHelp(decoder.b, value[field]); - return ($elm$core$Result$isOk(result)) ? result : $elm$core$Result$Err(A2($elm$json$Json$Decode$Field, field, result.a)); - - case 7: - var index = decoder.e; - if (!_Json_isArray(value)) - { - return _Json_expecting('an ARRAY', value); - } - if (index >= value.length) - { - return _Json_expecting('a LONGER array. Need index ' + index + ' but only see ' + value.length + ' entries', value); - } - var result = _Json_runHelp(decoder.b, value[index]); - return ($elm$core$Result$isOk(result)) ? result : $elm$core$Result$Err(A2($elm$json$Json$Decode$Index, index, result.a)); - - case 8: - if (typeof value !== 'object' || value === null || _Json_isArray(value)) - { - return _Json_expecting('an OBJECT', value); - } - - var keyValuePairs = _List_Nil; - // TODO test perf of Object.keys and switch when support is good enough - for (var key in value) - { - if (value.hasOwnProperty(key)) - { - var result = _Json_runHelp(decoder.b, value[key]); - if (!$elm$core$Result$isOk(result)) - { - return $elm$core$Result$Err(A2($elm$json$Json$Decode$Field, key, result.a)); - } - keyValuePairs = _List_Cons(_Utils_Tuple2(key, result.a), keyValuePairs); - } - } - return $elm$core$Result$Ok($elm$core$List$reverse(keyValuePairs)); - - case 9: - var answer = decoder.f; - var decoders = decoder.g; - for (var i = 0; i < decoders.length; i++) - { - var result = _Json_runHelp(decoders[i], value); - if (!$elm$core$Result$isOk(result)) - { - return result; - } - answer = answer(result.a); - } - return $elm$core$Result$Ok(answer); - - case 10: - var result = _Json_runHelp(decoder.b, value); - return (!$elm$core$Result$isOk(result)) - ? result - : _Json_runHelp(decoder.h(result.a), value); - - case 11: - var errors = _List_Nil; - for (var temp = decoder.g; temp.b; temp = temp.b) // WHILE_CONS - { - var result = _Json_runHelp(temp.a, value); - if ($elm$core$Result$isOk(result)) - { - return result; - } - errors = _List_Cons(result.a, errors); - } - return $elm$core$Result$Err($elm$json$Json$Decode$OneOf($elm$core$List$reverse(errors))); - - case 1: - return $elm$core$Result$Err(A2($elm$json$Json$Decode$Failure, decoder.a, _Json_wrap(value))); - - case 0: - return $elm$core$Result$Ok(decoder.a); - } -} - -function _Json_runArrayDecoder(decoder, value, toElmValue) -{ - var len = value.length; - var array = new Array(len); - for (var i = 0; i < len; i++) - { - var result = _Json_runHelp(decoder, value[i]); - if (!$elm$core$Result$isOk(result)) - { - return $elm$core$Result$Err(A2($elm$json$Json$Decode$Index, i, result.a)); - } - array[i] = result.a; - } - return $elm$core$Result$Ok(toElmValue(array)); -} - -function _Json_isArray(value) -{ - return Array.isArray(value) || (typeof FileList !== 'undefined' && value instanceof FileList); -} - -function _Json_toElmArray(array) -{ - return A2($elm$core$Array$initialize, array.length, function(i) { return array[i]; }); -} - -function _Json_expecting(type, value) -{ - return $elm$core$Result$Err(A2($elm$json$Json$Decode$Failure, 'Expecting ' + type, _Json_wrap(value))); -} - - -// EQUALITY - -function _Json_equality(x, y) -{ - if (x === y) - { - return true; - } - - if (x.$ !== y.$) - { - return false; - } - - switch (x.$) - { - case 0: - case 1: - return x.a === y.a; - - case 2: - return x.b === y.b; - - case 5: - return x.c === y.c; - - case 3: - case 4: - case 8: - return _Json_equality(x.b, y.b); - - case 6: - return x.d === y.d && _Json_equality(x.b, y.b); - - case 7: - return x.e === y.e && _Json_equality(x.b, y.b); - - case 9: - return x.f === y.f && _Json_listEquality(x.g, y.g); - - case 10: - return x.h === y.h && _Json_equality(x.b, y.b); - - case 11: - return _Json_listEquality(x.g, y.g); - } -} - -function _Json_listEquality(aDecoders, bDecoders) -{ - var len = aDecoders.length; - if (len !== bDecoders.length) - { - return false; - } - for (var i = 0; i < len; i++) - { - if (!_Json_equality(aDecoders[i], bDecoders[i])) - { - return false; - } - } - return true; -} - - -// ENCODE - -var _Json_encode = F2(function(indentLevel, value) -{ - return JSON.stringify(_Json_unwrap(value), null, indentLevel) + ''; -}); - -function _Json_wrap(value) { return { $: 0, a: value }; } -function _Json_unwrap(value) { return value.a; } - -function _Json_wrap_UNUSED(value) { return value; } -function _Json_unwrap_UNUSED(value) { return value; } - -function _Json_emptyArray() { return []; } -function _Json_emptyObject() { return {}; } - -var _Json_addField = F3(function(key, value, object) -{ - object[key] = _Json_unwrap(value); - return object; -}); - -function _Json_addEntry(func) -{ - return F2(function(entry, array) - { - array.push(_Json_unwrap(func(entry))); - return array; - }); -} - -var _Json_encodeNull = _Json_wrap(null); - - - -// TASKS - -function _Scheduler_succeed(value) -{ - return { - $: 0, - a: value - }; -} - -function _Scheduler_fail(error) -{ - return { - $: 1, - a: error - }; -} - -function _Scheduler_binding(callback) -{ - return { - $: 2, - b: callback, - c: null - }; -} - -var _Scheduler_andThen = F2(function(callback, task) -{ - return { - $: 3, - b: callback, - d: task - }; -}); - -var _Scheduler_onError = F2(function(callback, task) -{ - return { - $: 4, - b: callback, - d: task - }; -}); - -function _Scheduler_receive(callback) -{ - return { - $: 5, - b: callback - }; -} - - -// PROCESSES - -var _Scheduler_guid = 0; - -function _Scheduler_rawSpawn(task) -{ - var proc = { - $: 0, - e: _Scheduler_guid++, - f: task, - g: null, - h: [] - }; - - _Scheduler_enqueue(proc); - - return proc; -} - -function _Scheduler_spawn(task) -{ - return _Scheduler_binding(function(callback) { - callback(_Scheduler_succeed(_Scheduler_rawSpawn(task))); - }); -} - -function _Scheduler_rawSend(proc, msg) -{ - proc.h.push(msg); - _Scheduler_enqueue(proc); -} - -var _Scheduler_send = F2(function(proc, msg) -{ - return _Scheduler_binding(function(callback) { - _Scheduler_rawSend(proc, msg); - callback(_Scheduler_succeed(_Utils_Tuple0)); - }); -}); - -function _Scheduler_kill(proc) -{ - return _Scheduler_binding(function(callback) { - var task = proc.f; - if (task.$ === 2 && task.c) - { - task.c(); - } - - proc.f = null; - - callback(_Scheduler_succeed(_Utils_Tuple0)); - }); -} - - -/* STEP PROCESSES - -type alias Process = - { $ : tag - , id : unique_id - , root : Task - , stack : null | { $: SUCCEED | FAIL, a: callback, b: stack } - , mailbox : [msg] - } - -*/ - - -var _Scheduler_working = false; -var _Scheduler_queue = []; - - -function _Scheduler_enqueue(proc) -{ - _Scheduler_queue.push(proc); - if (_Scheduler_working) - { - return; - } - _Scheduler_working = true; - while (proc = _Scheduler_queue.shift()) - { - _Scheduler_step(proc); - } - _Scheduler_working = false; -} - - -function _Scheduler_step(proc) -{ - while (proc.f) - { - var rootTag = proc.f.$; - if (rootTag === 0 || rootTag === 1) - { - while (proc.g && proc.g.$ !== rootTag) - { - proc.g = proc.g.i; - } - if (!proc.g) - { - return; - } - proc.f = proc.g.b(proc.f.a); - proc.g = proc.g.i; - } - else if (rootTag === 2) - { - proc.f.c = proc.f.b(function(newRoot) { - proc.f = newRoot; - _Scheduler_enqueue(proc); - }); - return; - } - else if (rootTag === 5) - { - if (proc.h.length === 0) - { - return; - } - proc.f = proc.f.b(proc.h.shift()); - } - else // if (rootTag === 3 || rootTag === 4) - { - proc.g = { - $: rootTag === 3 ? 0 : 1, - b: proc.f.b, - i: proc.g - }; - proc.f = proc.f.d; - } - } -} - - - -function _Process_sleep(time) -{ - return _Scheduler_binding(function(callback) { - var id = setTimeout(function() { - callback(_Scheduler_succeed(_Utils_Tuple0)); - }, time); - - return function() { clearTimeout(id); }; - }); -} - - - - -// PROGRAMS - - -var _Platform_worker = F4(function(impl, flagDecoder, debugMetadata, args) -{ - return _Platform_initialize( - flagDecoder, - args, - impl.init, - impl.update, - impl.subscriptions, - function() { return function() {} } - ); -}); - - - -// INITIALIZE A PROGRAM - - -function _Platform_initialize(flagDecoder, args, init, update, subscriptions, stepperBuilder) -{ - var result = A2(_Json_run, flagDecoder, _Json_wrap(args ? args['flags'] : undefined)); - $elm$core$Result$isOk(result) || _Debug_crash(2 /**/, _Json_errorToString(result.a) /**/); - var managers = {}; - result = init(result.a); - var model = result.a; - var stepper = stepperBuilder(sendToApp, model); - var ports = _Platform_setupEffects(managers, sendToApp); - - function sendToApp(msg, viewMetadata) - { - result = A2(update, msg, model); - stepper(model = result.a, viewMetadata); - _Platform_dispatchEffects(managers, result.b, subscriptions(model)); - } - - _Platform_dispatchEffects(managers, result.b, subscriptions(model)); - - return ports ? { ports: ports } : {}; -} - - - -// TRACK PRELOADS -// -// This is used by code in elm/browser and elm/http -// to register any HTTP requests that are triggered by init. -// - - -var _Platform_preload; - - -function _Platform_registerPreload(url) -{ - _Platform_preload.add(url); -} - - - -// EFFECT MANAGERS - - -var _Platform_effectManagers = {}; - - -function _Platform_setupEffects(managers, sendToApp) -{ - var ports; - - // setup all necessary effect managers - for (var key in _Platform_effectManagers) - { - var manager = _Platform_effectManagers[key]; - - if (manager.a) - { - ports = ports || {}; - ports[key] = manager.a(key, sendToApp); - } - - managers[key] = _Platform_instantiateManager(manager, sendToApp); - } - - return ports; -} - - -function _Platform_createManager(init, onEffects, onSelfMsg, cmdMap, subMap) -{ - return { - b: init, - c: onEffects, - d: onSelfMsg, - e: cmdMap, - f: subMap - }; -} - - -function _Platform_instantiateManager(info, sendToApp) -{ - var router = { - g: sendToApp, - h: undefined - }; - - var onEffects = info.c; - var onSelfMsg = info.d; - var cmdMap = info.e; - var subMap = info.f; - - function loop(state) - { - return A2(_Scheduler_andThen, loop, _Scheduler_receive(function(msg) - { - var value = msg.a; - - if (msg.$ === 0) - { - return A3(onSelfMsg, router, value, state); - } - - return cmdMap && subMap - ? A4(onEffects, router, value.i, value.j, state) - : A3(onEffects, router, cmdMap ? value.i : value.j, state); - })); - } - - return router.h = _Scheduler_rawSpawn(A2(_Scheduler_andThen, loop, info.b)); -} - - - -// ROUTING - - -var _Platform_sendToApp = F2(function(router, msg) -{ - return _Scheduler_binding(function(callback) - { - router.g(msg); - callback(_Scheduler_succeed(_Utils_Tuple0)); - }); -}); - - -var _Platform_sendToSelf = F2(function(router, msg) -{ - return A2(_Scheduler_send, router.h, { - $: 0, - a: msg - }); -}); - - - -// BAGS - - -function _Platform_leaf(home) -{ - return function(value) - { - return { - $: 1, - k: home, - l: value - }; - }; -} - - -function _Platform_batch(list) -{ - return { - $: 2, - m: list - }; -} - - -var _Platform_map = F2(function(tagger, bag) -{ - return { - $: 3, - n: tagger, - o: bag - } -}); - - - -// PIPE BAGS INTO EFFECT MANAGERS - - -function _Platform_dispatchEffects(managers, cmdBag, subBag) -{ - var effectsDict = {}; - _Platform_gatherEffects(true, cmdBag, effectsDict, null); - _Platform_gatherEffects(false, subBag, effectsDict, null); - - for (var home in managers) - { - _Scheduler_rawSend(managers[home], { - $: 'fx', - a: effectsDict[home] || { i: _List_Nil, j: _List_Nil } - }); - } -} - - -function _Platform_gatherEffects(isCmd, bag, effectsDict, taggers) -{ - switch (bag.$) - { - case 1: - var home = bag.k; - var effect = _Platform_toEffect(isCmd, home, taggers, bag.l); - effectsDict[home] = _Platform_insert(isCmd, effect, effectsDict[home]); - return; - - case 2: - for (var list = bag.m; list.b; list = list.b) // WHILE_CONS - { - _Platform_gatherEffects(isCmd, list.a, effectsDict, taggers); - } - return; - - case 3: - _Platform_gatherEffects(isCmd, bag.o, effectsDict, { - p: bag.n, - q: taggers - }); - return; - } -} - - -function _Platform_toEffect(isCmd, home, taggers, value) -{ - function applyTaggers(x) - { - for (var temp = taggers; temp; temp = temp.q) - { - x = temp.p(x); - } - return x; - } - - var map = isCmd - ? _Platform_effectManagers[home].e - : _Platform_effectManagers[home].f; - - return A2(map, applyTaggers, value) -} - - -function _Platform_insert(isCmd, newEffect, effects) -{ - effects = effects || { i: _List_Nil, j: _List_Nil }; - - isCmd - ? (effects.i = _List_Cons(newEffect, effects.i)) - : (effects.j = _List_Cons(newEffect, effects.j)); - - return effects; -} - - - -// PORTS - - -function _Platform_checkPortName(name) -{ - if (_Platform_effectManagers[name]) - { - _Debug_crash(3, name) - } -} - - - -// OUTGOING PORTS - - -function _Platform_outgoingPort(name, converter) -{ - _Platform_checkPortName(name); - _Platform_effectManagers[name] = { - e: _Platform_outgoingPortMap, - r: converter, - a: _Platform_setupOutgoingPort - }; - return _Platform_leaf(name); -} - - -var _Platform_outgoingPortMap = F2(function(tagger, value) { return value; }); - - -function _Platform_setupOutgoingPort(name) -{ - var subs = []; - var converter = _Platform_effectManagers[name].r; - - // CREATE MANAGER - - var init = _Process_sleep(0); - - _Platform_effectManagers[name].b = init; - _Platform_effectManagers[name].c = F3(function(router, cmdList, state) - { - for ( ; cmdList.b; cmdList = cmdList.b) // WHILE_CONS - { - // grab a separate reference to subs in case unsubscribe is called - var currentSubs = subs; - var value = _Json_unwrap(converter(cmdList.a)); - for (var i = 0; i < currentSubs.length; i++) - { - currentSubs[i](value); - } - } - return init; - }); - - // PUBLIC API - - function subscribe(callback) - { - subs.push(callback); - } - - function unsubscribe(callback) - { - // copy subs into a new array in case unsubscribe is called within a - // subscribed callback - subs = subs.slice(); - var index = subs.indexOf(callback); - if (index >= 0) - { - subs.splice(index, 1); - } - } - - return { - subscribe: subscribe, - unsubscribe: unsubscribe - }; -} - - - -// INCOMING PORTS - - -function _Platform_incomingPort(name, converter) -{ - _Platform_checkPortName(name); - _Platform_effectManagers[name] = { - f: _Platform_incomingPortMap, - r: converter, - a: _Platform_setupIncomingPort - }; - return _Platform_leaf(name); -} - - -var _Platform_incomingPortMap = F2(function(tagger, finalTagger) -{ - return function(value) - { - return tagger(finalTagger(value)); - }; -}); - - -function _Platform_setupIncomingPort(name, sendToApp) -{ - var subs = _List_Nil; - var converter = _Platform_effectManagers[name].r; - - // CREATE MANAGER - - var init = _Scheduler_succeed(null); - - _Platform_effectManagers[name].b = init; - _Platform_effectManagers[name].c = F3(function(router, subList, state) - { - subs = subList; - return init; - }); - - // PUBLIC API - - function send(incomingValue) - { - var result = A2(_Json_run, converter, _Json_wrap(incomingValue)); - - $elm$core$Result$isOk(result) || _Debug_crash(4, name, result.a); - - var value = result.a; - for (var temp = subs; temp.b; temp = temp.b) // WHILE_CONS - { - sendToApp(temp.a(value)); - } - } - - return { send: send }; -} - - - -// EXPORT ELM MODULES -// -// Have DEBUG and PROD versions so that we can (1) give nicer errors in -// debug mode and (2) not pay for the bits needed for that in prod mode. -// - - -function _Platform_export_UNUSED(exports) -{ - scope['Elm'] - ? _Platform_mergeExportsProd(scope['Elm'], exports) - : scope['Elm'] = exports; -} - - -function _Platform_mergeExportsProd(obj, exports) -{ - for (var name in exports) - { - (name in obj) - ? (name == 'init') - ? _Debug_crash(6) - : _Platform_mergeExportsProd(obj[name], exports[name]) - : (obj[name] = exports[name]); - } -} - - -function _Platform_export(exports) -{ - scope['Elm'] - ? _Platform_mergeExportsDebug('Elm', scope['Elm'], exports) - : scope['Elm'] = exports; -} - - -function _Platform_mergeExportsDebug(moduleName, obj, exports) -{ - for (var name in exports) - { - (name in obj) - ? (name == 'init') - ? _Debug_crash(6, moduleName) - : _Platform_mergeExportsDebug(moduleName + '.' + name, obj[name], exports[name]) - : (obj[name] = exports[name]); - } -} - - - - -// HELPERS - - -var _VirtualDom_divertHrefToApp; - -var _VirtualDom_doc = typeof document !== 'undefined' ? document : {}; - - -function _VirtualDom_appendChild(parent, child) -{ - parent.appendChild(child); -} - -var _VirtualDom_init = F4(function(virtualNode, flagDecoder, debugMetadata, args) -{ - // NOTE: this function needs _Platform_export available to work - - /**_UNUSED/ - var node = args['node']; - //*/ - /**/ - var node = args && args['node'] ? args['node'] : _Debug_crash(0); - //*/ - - node.parentNode.replaceChild( - _VirtualDom_render(virtualNode, function() {}), - node - ); - - return {}; -}); - - - -// TEXT - - -function _VirtualDom_text(string) -{ - return { - $: 0, - a: string - }; -} - - - -// NODE - - -var _VirtualDom_nodeNS = F2(function(namespace, tag) -{ - return F2(function(factList, kidList) - { - for (var kids = [], descendantsCount = 0; kidList.b; kidList = kidList.b) // WHILE_CONS - { - var kid = kidList.a; - descendantsCount += (kid.b || 0); - kids.push(kid); - } - descendantsCount += kids.length; - - return { - $: 1, - c: tag, - d: _VirtualDom_organizeFacts(factList), - e: kids, - f: namespace, - b: descendantsCount - }; - }); -}); - - -var _VirtualDom_node = _VirtualDom_nodeNS(undefined); - - - -// KEYED NODE - - -var _VirtualDom_keyedNodeNS = F2(function(namespace, tag) -{ - return F2(function(factList, kidList) - { - for (var kids = [], descendantsCount = 0; kidList.b; kidList = kidList.b) // WHILE_CONS - { - var kid = kidList.a; - descendantsCount += (kid.b.b || 0); - kids.push(kid); - } - descendantsCount += kids.length; - - return { - $: 2, - c: tag, - d: _VirtualDom_organizeFacts(factList), - e: kids, - f: namespace, - b: descendantsCount - }; - }); -}); - - -var _VirtualDom_keyedNode = _VirtualDom_keyedNodeNS(undefined); - - - -// CUSTOM - - -function _VirtualDom_custom(factList, model, render, diff) -{ - return { - $: 3, - d: _VirtualDom_organizeFacts(factList), - g: model, - h: render, - i: diff - }; -} - - - -// MAP - - -var _VirtualDom_map = F2(function(tagger, node) -{ - return { - $: 4, - j: tagger, - k: node, - b: 1 + (node.b || 0) - }; -}); - - - -// LAZY - - -function _VirtualDom_thunk(refs, thunk) -{ - return { - $: 5, - l: refs, - m: thunk, - k: undefined - }; -} - -var _VirtualDom_lazy = F2(function(func, a) -{ - return _VirtualDom_thunk([func, a], function() { - return func(a); - }); -}); - -var _VirtualDom_lazy2 = F3(function(func, a, b) -{ - return _VirtualDom_thunk([func, a, b], function() { - return A2(func, a, b); - }); -}); - -var _VirtualDom_lazy3 = F4(function(func, a, b, c) -{ - return _VirtualDom_thunk([func, a, b, c], function() { - return A3(func, a, b, c); - }); -}); - -var _VirtualDom_lazy4 = F5(function(func, a, b, c, d) -{ - return _VirtualDom_thunk([func, a, b, c, d], function() { - return A4(func, a, b, c, d); - }); -}); - -var _VirtualDom_lazy5 = F6(function(func, a, b, c, d, e) -{ - return _VirtualDom_thunk([func, a, b, c, d, e], function() { - return A5(func, a, b, c, d, e); - }); -}); - -var _VirtualDom_lazy6 = F7(function(func, a, b, c, d, e, f) -{ - return _VirtualDom_thunk([func, a, b, c, d, e, f], function() { - return A6(func, a, b, c, d, e, f); - }); -}); - -var _VirtualDom_lazy7 = F8(function(func, a, b, c, d, e, f, g) -{ - return _VirtualDom_thunk([func, a, b, c, d, e, f, g], function() { - return A7(func, a, b, c, d, e, f, g); - }); -}); - -var _VirtualDom_lazy8 = F9(function(func, a, b, c, d, e, f, g, h) -{ - return _VirtualDom_thunk([func, a, b, c, d, e, f, g, h], function() { - return A8(func, a, b, c, d, e, f, g, h); - }); -}); - - - -// FACTS - - -var _VirtualDom_on = F2(function(key, handler) -{ - return { - $: 'a0', - n: key, - o: handler - }; -}); -var _VirtualDom_style = F2(function(key, value) -{ - return { - $: 'a1', - n: key, - o: value - }; -}); -var _VirtualDom_property = F2(function(key, value) -{ - return { - $: 'a2', - n: key, - o: value - }; -}); -var _VirtualDom_attribute = F2(function(key, value) -{ - return { - $: 'a3', - n: key, - o: value - }; -}); -var _VirtualDom_attributeNS = F3(function(namespace, key, value) -{ - return { - $: 'a4', - n: key, - o: { f: namespace, o: value } - }; -}); - - - -// XSS ATTACK VECTOR CHECKS - - -function _VirtualDom_noScript(tag) -{ - return tag == 'script' ? 'p' : tag; -} - -function _VirtualDom_noOnOrFormAction(key) -{ - return /^(on|formAction$)/i.test(key) ? 'data-' + key : key; -} - -function _VirtualDom_noInnerHtmlOrFormAction(key) -{ - return key == 'innerHTML' || key == 'formAction' ? 'data-' + key : key; -} - -function _VirtualDom_noJavaScriptUri_UNUSED(value) -{ - return /^javascript:/i.test(value.replace(/\s/g,'')) ? '' : value; -} - -function _VirtualDom_noJavaScriptUri(value) -{ - return /^javascript:/i.test(value.replace(/\s/g,'')) - ? 'javascript:alert("This is an XSS vector. Please use ports or web components instead.")' - : value; -} - -function _VirtualDom_noJavaScriptOrHtmlUri_UNUSED(value) -{ - return /^\s*(javascript:|data:text\/html)/i.test(value) ? '' : value; -} - -function _VirtualDom_noJavaScriptOrHtmlUri(value) -{ - return /^\s*(javascript:|data:text\/html)/i.test(value) - ? 'javascript:alert("This is an XSS vector. Please use ports or web components instead.")' - : value; -} - - - -// MAP FACTS - - -var _VirtualDom_mapAttribute = F2(function(func, attr) -{ - return (attr.$ === 'a0') - ? A2(_VirtualDom_on, attr.n, _VirtualDom_mapHandler(func, attr.o)) - : attr; -}); - -function _VirtualDom_mapHandler(func, handler) -{ - var tag = $elm$virtual_dom$VirtualDom$toHandlerInt(handler); - - // 0 = Normal - // 1 = MayStopPropagation - // 2 = MayPreventDefault - // 3 = Custom - - return { - $: handler.$, - a: - !tag - ? A2($elm$json$Json$Decode$map, func, handler.a) - : - A3($elm$json$Json$Decode$map2, - tag < 3 - ? _VirtualDom_mapEventTuple - : _VirtualDom_mapEventRecord, - $elm$json$Json$Decode$succeed(func), - handler.a - ) - }; -} - -var _VirtualDom_mapEventTuple = F2(function(func, tuple) -{ - return _Utils_Tuple2(func(tuple.a), tuple.b); -}); - -var _VirtualDom_mapEventRecord = F2(function(func, record) -{ - return { - message: func(record.message), - stopPropagation: record.stopPropagation, - preventDefault: record.preventDefault - } -}); - - - -// ORGANIZE FACTS - - -function _VirtualDom_organizeFacts(factList) -{ - for (var facts = {}; factList.b; factList = factList.b) // WHILE_CONS - { - var entry = factList.a; - - var tag = entry.$; - var key = entry.n; - var value = entry.o; - - if (tag === 'a2') - { - (key === 'className') - ? _VirtualDom_addClass(facts, key, _Json_unwrap(value)) - : facts[key] = _Json_unwrap(value); - - continue; - } - - var subFacts = facts[tag] || (facts[tag] = {}); - (tag === 'a3' && key === 'class') - ? _VirtualDom_addClass(subFacts, key, value) - : subFacts[key] = value; - } - - return facts; -} - -function _VirtualDom_addClass(object, key, newClass) -{ - var classes = object[key]; - object[key] = classes ? classes + ' ' + newClass : newClass; -} - - - -// RENDER - - -function _VirtualDom_render(vNode, eventNode) -{ - var tag = vNode.$; - - if (tag === 5) - { - return _VirtualDom_render(vNode.k || (vNode.k = vNode.m()), eventNode); - } - - if (tag === 0) - { - return _VirtualDom_doc.createTextNode(vNode.a); - } - - if (tag === 4) - { - var subNode = vNode.k; - var tagger = vNode.j; - - while (subNode.$ === 4) - { - typeof tagger !== 'object' - ? tagger = [tagger, subNode.j] - : tagger.push(subNode.j); - - subNode = subNode.k; - } - - var subEventRoot = { j: tagger, p: eventNode }; - var domNode = _VirtualDom_render(subNode, subEventRoot); - domNode.elm_event_node_ref = subEventRoot; - return domNode; - } - - if (tag === 3) - { - var domNode = vNode.h(vNode.g); - _VirtualDom_applyFacts(domNode, eventNode, vNode.d); - return domNode; - } - - // at this point `tag` must be 1 or 2 - - var domNode = vNode.f - ? _VirtualDom_doc.createElementNS(vNode.f, vNode.c) - : _VirtualDom_doc.createElement(vNode.c); - - if (_VirtualDom_divertHrefToApp && vNode.c == 'a') - { - domNode.addEventListener('click', _VirtualDom_divertHrefToApp(domNode)); - } - - _VirtualDom_applyFacts(domNode, eventNode, vNode.d); - - for (var kids = vNode.e, i = 0; i < kids.length; i++) - { - _VirtualDom_appendChild(domNode, _VirtualDom_render(tag === 1 ? kids[i] : kids[i].b, eventNode)); - } - - return domNode; -} - - - -// APPLY FACTS - - -function _VirtualDom_applyFacts(domNode, eventNode, facts) -{ - for (var key in facts) - { - var value = facts[key]; - - key === 'a1' - ? _VirtualDom_applyStyles(domNode, value) - : - key === 'a0' - ? _VirtualDom_applyEvents(domNode, eventNode, value) - : - key === 'a3' - ? _VirtualDom_applyAttrs(domNode, value) - : - key === 'a4' - ? _VirtualDom_applyAttrsNS(domNode, value) - : - ((key !== 'value' && key !== 'checked') || domNode[key] !== value) && (domNode[key] = value); - } -} - - - -// APPLY STYLES - - -function _VirtualDom_applyStyles(domNode, styles) -{ - var domNodeStyle = domNode.style; - - for (var key in styles) - { - domNodeStyle[key] = styles[key]; - } -} - - - -// APPLY ATTRS - - -function _VirtualDom_applyAttrs(domNode, attrs) -{ - for (var key in attrs) - { - var value = attrs[key]; - typeof value !== 'undefined' - ? domNode.setAttribute(key, value) - : domNode.removeAttribute(key); - } -} - - - -// APPLY NAMESPACED ATTRS - - -function _VirtualDom_applyAttrsNS(domNode, nsAttrs) -{ - for (var key in nsAttrs) - { - var pair = nsAttrs[key]; - var namespace = pair.f; - var value = pair.o; - - typeof value !== 'undefined' - ? domNode.setAttributeNS(namespace, key, value) - : domNode.removeAttributeNS(namespace, key); - } -} - - - -// APPLY EVENTS - - -function _VirtualDom_applyEvents(domNode, eventNode, events) -{ - var allCallbacks = domNode.elmFs || (domNode.elmFs = {}); - - for (var key in events) - { - var newHandler = events[key]; - var oldCallback = allCallbacks[key]; - - if (!newHandler) - { - domNode.removeEventListener(key, oldCallback); - allCallbacks[key] = undefined; - continue; - } - - if (oldCallback) - { - var oldHandler = oldCallback.q; - if (oldHandler.$ === newHandler.$) - { - oldCallback.q = newHandler; - continue; - } - domNode.removeEventListener(key, oldCallback); - } - - oldCallback = _VirtualDom_makeCallback(eventNode, newHandler); - domNode.addEventListener(key, oldCallback, - _VirtualDom_passiveSupported - && { passive: $elm$virtual_dom$VirtualDom$toHandlerInt(newHandler) < 2 } - ); - allCallbacks[key] = oldCallback; - } -} - - - -// PASSIVE EVENTS - - -var _VirtualDom_passiveSupported; - -try -{ - window.addEventListener('t', null, Object.defineProperty({}, 'passive', { - get: function() { _VirtualDom_passiveSupported = true; } - })); -} -catch(e) {} - - - -// EVENT HANDLERS - - -function _VirtualDom_makeCallback(eventNode, initialHandler) -{ - function callback(event) - { - var handler = callback.q; - var result = _Json_runHelp(handler.a, event); - - if (!$elm$core$Result$isOk(result)) - { - return; - } - - var tag = $elm$virtual_dom$VirtualDom$toHandlerInt(handler); - - // 0 = Normal - // 1 = MayStopPropagation - // 2 = MayPreventDefault - // 3 = Custom - - var value = result.a; - var message = !tag ? value : tag < 3 ? value.a : value.message; - var stopPropagation = tag == 1 ? value.b : tag == 3 && value.stopPropagation; - var currentEventNode = ( - stopPropagation && event.stopPropagation(), - (tag == 2 ? value.b : tag == 3 && value.preventDefault) && event.preventDefault(), - eventNode - ); - var tagger; - var i; - while (tagger = currentEventNode.j) - { - if (typeof tagger == 'function') - { - message = tagger(message); - } - else - { - for (var i = tagger.length; i--; ) - { - message = tagger[i](message); - } - } - currentEventNode = currentEventNode.p; - } - currentEventNode(message, stopPropagation); // stopPropagation implies isSync - } - - callback.q = initialHandler; - - return callback; -} - -function _VirtualDom_equalEvents(x, y) -{ - return x.$ == y.$ && _Json_equality(x.a, y.a); -} - - - -// DIFF - - -// TODO: Should we do patches like in iOS? -// -// type Patch -// = At Int Patch -// | Batch (List Patch) -// | Change ... -// -// How could it not be better? -// -function _VirtualDom_diff(x, y) -{ - var patches = []; - _VirtualDom_diffHelp(x, y, patches, 0); - return patches; -} - - -function _VirtualDom_pushPatch(patches, type, index, data) -{ - var patch = { - $: type, - r: index, - s: data, - t: undefined, - u: undefined - }; - patches.push(patch); - return patch; -} - - -function _VirtualDom_diffHelp(x, y, patches, index) -{ - if (x === y) - { - return; - } - - var xType = x.$; - var yType = y.$; - - // Bail if you run into different types of nodes. Implies that the - // structure has changed significantly and it's not worth a diff. - if (xType !== yType) - { - if (xType === 1 && yType === 2) - { - y = _VirtualDom_dekey(y); - yType = 1; - } - else - { - _VirtualDom_pushPatch(patches, 0, index, y); - return; - } - } - - // Now we know that both nodes are the same $. - switch (yType) - { - case 5: - var xRefs = x.l; - var yRefs = y.l; - var i = xRefs.length; - var same = i === yRefs.length; - while (same && i--) - { - same = xRefs[i] === yRefs[i]; - } - if (same) - { - y.k = x.k; - return; - } - y.k = y.m(); - var subPatches = []; - _VirtualDom_diffHelp(x.k, y.k, subPatches, 0); - subPatches.length > 0 && _VirtualDom_pushPatch(patches, 1, index, subPatches); - return; - - case 4: - // gather nested taggers - var xTaggers = x.j; - var yTaggers = y.j; - var nesting = false; - - var xSubNode = x.k; - while (xSubNode.$ === 4) - { - nesting = true; - - typeof xTaggers !== 'object' - ? xTaggers = [xTaggers, xSubNode.j] - : xTaggers.push(xSubNode.j); - - xSubNode = xSubNode.k; - } - - var ySubNode = y.k; - while (ySubNode.$ === 4) - { - nesting = true; - - typeof yTaggers !== 'object' - ? yTaggers = [yTaggers, ySubNode.j] - : yTaggers.push(ySubNode.j); - - ySubNode = ySubNode.k; - } - - // Just bail if different numbers of taggers. This implies the - // structure of the virtual DOM has changed. - if (nesting && xTaggers.length !== yTaggers.length) - { - _VirtualDom_pushPatch(patches, 0, index, y); - return; - } - - // check if taggers are "the same" - if (nesting ? !_VirtualDom_pairwiseRefEqual(xTaggers, yTaggers) : xTaggers !== yTaggers) - { - _VirtualDom_pushPatch(patches, 2, index, yTaggers); - } - - // diff everything below the taggers - _VirtualDom_diffHelp(xSubNode, ySubNode, patches, index + 1); - return; - - case 0: - if (x.a !== y.a) - { - _VirtualDom_pushPatch(patches, 3, index, y.a); - } - return; - - case 1: - _VirtualDom_diffNodes(x, y, patches, index, _VirtualDom_diffKids); - return; - - case 2: - _VirtualDom_diffNodes(x, y, patches, index, _VirtualDom_diffKeyedKids); - return; - - case 3: - if (x.h !== y.h) - { - _VirtualDom_pushPatch(patches, 0, index, y); - return; - } - - var factsDiff = _VirtualDom_diffFacts(x.d, y.d); - factsDiff && _VirtualDom_pushPatch(patches, 4, index, factsDiff); - - var patch = y.i(x.g, y.g); - patch && _VirtualDom_pushPatch(patches, 5, index, patch); - - return; - } -} - -// assumes the incoming arrays are the same length -function _VirtualDom_pairwiseRefEqual(as, bs) -{ - for (var i = 0; i < as.length; i++) - { - if (as[i] !== bs[i]) - { - return false; - } - } - - return true; -} - -function _VirtualDom_diffNodes(x, y, patches, index, diffKids) -{ - // Bail if obvious indicators have changed. Implies more serious - // structural changes such that it's not worth it to diff. - if (x.c !== y.c || x.f !== y.f) - { - _VirtualDom_pushPatch(patches, 0, index, y); - return; - } - - var factsDiff = _VirtualDom_diffFacts(x.d, y.d); - factsDiff && _VirtualDom_pushPatch(patches, 4, index, factsDiff); - - diffKids(x, y, patches, index); -} - - - -// DIFF FACTS - - -// TODO Instead of creating a new diff object, it's possible to just test if -// there *is* a diff. During the actual patch, do the diff again and make the -// modifications directly. This way, there's no new allocations. Worth it? -function _VirtualDom_diffFacts(x, y, category) -{ - var diff; - - // look for changes and removals - for (var xKey in x) - { - if (xKey === 'a1' || xKey === 'a0' || xKey === 'a3' || xKey === 'a4') - { - var subDiff = _VirtualDom_diffFacts(x[xKey], y[xKey] || {}, xKey); - if (subDiff) - { - diff = diff || {}; - diff[xKey] = subDiff; - } - continue; - } - - // remove if not in the new facts - if (!(xKey in y)) - { - diff = diff || {}; - diff[xKey] = - !category - ? (typeof x[xKey] === 'string' ? '' : null) - : - (category === 'a1') - ? '' - : - (category === 'a0' || category === 'a3') - ? undefined - : - { f: x[xKey].f, o: undefined }; - - continue; - } - - var xValue = x[xKey]; - var yValue = y[xKey]; - - // reference equal, so don't worry about it - if (xValue === yValue && xKey !== 'value' && xKey !== 'checked' - || category === 'a0' && _VirtualDom_equalEvents(xValue, yValue)) - { - continue; - } - - diff = diff || {}; - diff[xKey] = yValue; - } - - // add new stuff - for (var yKey in y) - { - if (!(yKey in x)) - { - diff = diff || {}; - diff[yKey] = y[yKey]; - } - } - - return diff; -} - - - -// DIFF KIDS - - -function _VirtualDom_diffKids(xParent, yParent, patches, index) -{ - var xKids = xParent.e; - var yKids = yParent.e; - - var xLen = xKids.length; - var yLen = yKids.length; - - // FIGURE OUT IF THERE ARE INSERTS OR REMOVALS - - if (xLen > yLen) - { - _VirtualDom_pushPatch(patches, 6, index, { - v: yLen, - i: xLen - yLen - }); - } - else if (xLen < yLen) - { - _VirtualDom_pushPatch(patches, 7, index, { - v: xLen, - e: yKids - }); - } - - // PAIRWISE DIFF EVERYTHING ELSE - - for (var minLen = xLen < yLen ? xLen : yLen, i = 0; i < minLen; i++) - { - var xKid = xKids[i]; - _VirtualDom_diffHelp(xKid, yKids[i], patches, ++index); - index += xKid.b || 0; - } -} - - - -// KEYED DIFF - - -function _VirtualDom_diffKeyedKids(xParent, yParent, patches, rootIndex) -{ - var localPatches = []; - - var changes = {}; // Dict String Entry - var inserts = []; // Array { index : Int, entry : Entry } - // type Entry = { tag : String, vnode : VNode, index : Int, data : _ } - - var xKids = xParent.e; - var yKids = yParent.e; - var xLen = xKids.length; - var yLen = yKids.length; - var xIndex = 0; - var yIndex = 0; - - var index = rootIndex; - - while (xIndex < xLen && yIndex < yLen) - { - var x = xKids[xIndex]; - var y = yKids[yIndex]; - - var xKey = x.a; - var yKey = y.a; - var xNode = x.b; - var yNode = y.b; - - var newMatch = undefined; - var oldMatch = undefined; - - // check if keys match - - if (xKey === yKey) - { - index++; - _VirtualDom_diffHelp(xNode, yNode, localPatches, index); - index += xNode.b || 0; - - xIndex++; - yIndex++; - continue; - } - - // look ahead 1 to detect insertions and removals. - - var xNext = xKids[xIndex + 1]; - var yNext = yKids[yIndex + 1]; - - if (xNext) - { - var xNextKey = xNext.a; - var xNextNode = xNext.b; - oldMatch = yKey === xNextKey; - } - - if (yNext) - { - var yNextKey = yNext.a; - var yNextNode = yNext.b; - newMatch = xKey === yNextKey; - } - - - // swap x and y - if (newMatch && oldMatch) - { - index++; - _VirtualDom_diffHelp(xNode, yNextNode, localPatches, index); - _VirtualDom_insertNode(changes, localPatches, xKey, yNode, yIndex, inserts); - index += xNode.b || 0; - - index++; - _VirtualDom_removeNode(changes, localPatches, xKey, xNextNode, index); - index += xNextNode.b || 0; - - xIndex += 2; - yIndex += 2; - continue; - } - - // insert y - if (newMatch) - { - index++; - _VirtualDom_insertNode(changes, localPatches, yKey, yNode, yIndex, inserts); - _VirtualDom_diffHelp(xNode, yNextNode, localPatches, index); - index += xNode.b || 0; - - xIndex += 1; - yIndex += 2; - continue; - } - - // remove x - if (oldMatch) - { - index++; - _VirtualDom_removeNode(changes, localPatches, xKey, xNode, index); - index += xNode.b || 0; - - index++; - _VirtualDom_diffHelp(xNextNode, yNode, localPatches, index); - index += xNextNode.b || 0; - - xIndex += 2; - yIndex += 1; - continue; - } - - // remove x, insert y - if (xNext && xNextKey === yNextKey) - { - index++; - _VirtualDom_removeNode(changes, localPatches, xKey, xNode, index); - _VirtualDom_insertNode(changes, localPatches, yKey, yNode, yIndex, inserts); - index += xNode.b || 0; - - index++; - _VirtualDom_diffHelp(xNextNode, yNextNode, localPatches, index); - index += xNextNode.b || 0; - - xIndex += 2; - yIndex += 2; - continue; - } - - break; - } - - // eat up any remaining nodes with removeNode and insertNode - - while (xIndex < xLen) - { - index++; - var x = xKids[xIndex]; - var xNode = x.b; - _VirtualDom_removeNode(changes, localPatches, x.a, xNode, index); - index += xNode.b || 0; - xIndex++; - } - - while (yIndex < yLen) - { - var endInserts = endInserts || []; - var y = yKids[yIndex]; - _VirtualDom_insertNode(changes, localPatches, y.a, y.b, undefined, endInserts); - yIndex++; - } - - if (localPatches.length > 0 || inserts.length > 0 || endInserts) - { - _VirtualDom_pushPatch(patches, 8, rootIndex, { - w: localPatches, - x: inserts, - y: endInserts - }); - } -} - - - -// CHANGES FROM KEYED DIFF - - -var _VirtualDom_POSTFIX = '_elmW6BL'; - - -function _VirtualDom_insertNode(changes, localPatches, key, vnode, yIndex, inserts) -{ - var entry = changes[key]; - - // never seen this key before - if (!entry) - { - entry = { - c: 0, - z: vnode, - r: yIndex, - s: undefined - }; - - inserts.push({ r: yIndex, A: entry }); - changes[key] = entry; - - return; - } - - // this key was removed earlier, a match! - if (entry.c === 1) - { - inserts.push({ r: yIndex, A: entry }); - - entry.c = 2; - var subPatches = []; - _VirtualDom_diffHelp(entry.z, vnode, subPatches, entry.r); - entry.r = yIndex; - entry.s.s = { - w: subPatches, - A: entry - }; - - return; - } - - // this key has already been inserted or moved, a duplicate! - _VirtualDom_insertNode(changes, localPatches, key + _VirtualDom_POSTFIX, vnode, yIndex, inserts); -} - - -function _VirtualDom_removeNode(changes, localPatches, key, vnode, index) -{ - var entry = changes[key]; - - // never seen this key before - if (!entry) - { - var patch = _VirtualDom_pushPatch(localPatches, 9, index, undefined); - - changes[key] = { - c: 1, - z: vnode, - r: index, - s: patch - }; - - return; - } - - // this key was inserted earlier, a match! - if (entry.c === 0) - { - entry.c = 2; - var subPatches = []; - _VirtualDom_diffHelp(vnode, entry.z, subPatches, index); - - _VirtualDom_pushPatch(localPatches, 9, index, { - w: subPatches, - A: entry - }); - - return; - } - - // this key has already been removed or moved, a duplicate! - _VirtualDom_removeNode(changes, localPatches, key + _VirtualDom_POSTFIX, vnode, index); -} - - - -// ADD DOM NODES -// -// Each DOM node has an "index" assigned in order of traversal. It is important -// to minimize our crawl over the actual DOM, so these indexes (along with the -// descendantsCount of virtual nodes) let us skip touching entire subtrees of -// the DOM if we know there are no patches there. - - -function _VirtualDom_addDomNodes(domNode, vNode, patches, eventNode) -{ - _VirtualDom_addDomNodesHelp(domNode, vNode, patches, 0, 0, vNode.b, eventNode); -} - - -// assumes `patches` is non-empty and indexes increase monotonically. -function _VirtualDom_addDomNodesHelp(domNode, vNode, patches, i, low, high, eventNode) -{ - var patch = patches[i]; - var index = patch.r; - - while (index === low) - { - var patchType = patch.$; - - if (patchType === 1) - { - _VirtualDom_addDomNodes(domNode, vNode.k, patch.s, eventNode); - } - else if (patchType === 8) - { - patch.t = domNode; - patch.u = eventNode; - - var subPatches = patch.s.w; - if (subPatches.length > 0) - { - _VirtualDom_addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode); - } - } - else if (patchType === 9) - { - patch.t = domNode; - patch.u = eventNode; - - var data = patch.s; - if (data) - { - data.A.s = domNode; - var subPatches = data.w; - if (subPatches.length > 0) - { - _VirtualDom_addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode); - } - } - } - else - { - patch.t = domNode; - patch.u = eventNode; - } - - i++; - - if (!(patch = patches[i]) || (index = patch.r) > high) - { - return i; - } - } - - var tag = vNode.$; - - if (tag === 4) - { - var subNode = vNode.k; - - while (subNode.$ === 4) - { - subNode = subNode.k; - } - - return _VirtualDom_addDomNodesHelp(domNode, subNode, patches, i, low + 1, high, domNode.elm_event_node_ref); - } - - // tag must be 1 or 2 at this point - - var vKids = vNode.e; - var childNodes = domNode.childNodes; - for (var j = 0; j < vKids.length; j++) - { - low++; - var vKid = tag === 1 ? vKids[j] : vKids[j].b; - var nextLow = low + (vKid.b || 0); - if (low <= index && index <= nextLow) - { - i = _VirtualDom_addDomNodesHelp(childNodes[j], vKid, patches, i, low, nextLow, eventNode); - if (!(patch = patches[i]) || (index = patch.r) > high) - { - return i; - } - } - low = nextLow; - } - return i; -} - - - -// APPLY PATCHES - - -function _VirtualDom_applyPatches(rootDomNode, oldVirtualNode, patches, eventNode) -{ - if (patches.length === 0) - { - return rootDomNode; - } - - _VirtualDom_addDomNodes(rootDomNode, oldVirtualNode, patches, eventNode); - return _VirtualDom_applyPatchesHelp(rootDomNode, patches); -} - -function _VirtualDom_applyPatchesHelp(rootDomNode, patches) -{ - for (var i = 0; i < patches.length; i++) - { - var patch = patches[i]; - var localDomNode = patch.t - var newNode = _VirtualDom_applyPatch(localDomNode, patch); - if (localDomNode === rootDomNode) - { - rootDomNode = newNode; - } - } - return rootDomNode; -} - -function _VirtualDom_applyPatch(domNode, patch) -{ - switch (patch.$) - { - case 0: - return _VirtualDom_applyPatchRedraw(domNode, patch.s, patch.u); - - case 4: - _VirtualDom_applyFacts(domNode, patch.u, patch.s); - return domNode; - - case 3: - domNode.replaceData(0, domNode.length, patch.s); - return domNode; - - case 1: - return _VirtualDom_applyPatchesHelp(domNode, patch.s); - - case 2: - if (domNode.elm_event_node_ref) - { - domNode.elm_event_node_ref.j = patch.s; - } - else - { - domNode.elm_event_node_ref = { j: patch.s, p: patch.u }; - } - return domNode; - - case 6: - var data = patch.s; - for (var i = 0; i < data.i; i++) - { - domNode.removeChild(domNode.childNodes[data.v]); - } - return domNode; - - case 7: - var data = patch.s; - var kids = data.e; - var i = data.v; - var theEnd = domNode.childNodes[i]; - for (; i < kids.length; i++) - { - domNode.insertBefore(_VirtualDom_render(kids[i], patch.u), theEnd); - } - return domNode; - - case 9: - var data = patch.s; - if (!data) - { - domNode.parentNode.removeChild(domNode); - return domNode; - } - var entry = data.A; - if (typeof entry.r !== 'undefined') - { - domNode.parentNode.removeChild(domNode); - } - entry.s = _VirtualDom_applyPatchesHelp(domNode, data.w); - return domNode; - - case 8: - return _VirtualDom_applyPatchReorder(domNode, patch); - - case 5: - return patch.s(domNode); - - default: - _Debug_crash(10); // 'Ran into an unknown patch!' - } -} - - -function _VirtualDom_applyPatchRedraw(domNode, vNode, eventNode) -{ - var parentNode = domNode.parentNode; - var newNode = _VirtualDom_render(vNode, eventNode); - - if (!newNode.elm_event_node_ref) - { - newNode.elm_event_node_ref = domNode.elm_event_node_ref; - } - - if (parentNode && newNode !== domNode) - { - parentNode.replaceChild(newNode, domNode); - } - return newNode; -} - - -function _VirtualDom_applyPatchReorder(domNode, patch) -{ - var data = patch.s; - - // remove end inserts - var frag = _VirtualDom_applyPatchReorderEndInsertsHelp(data.y, patch); - - // removals - domNode = _VirtualDom_applyPatchesHelp(domNode, data.w); - - // inserts - var inserts = data.x; - for (var i = 0; i < inserts.length; i++) - { - var insert = inserts[i]; - var entry = insert.A; - var node = entry.c === 2 - ? entry.s - : _VirtualDom_render(entry.z, patch.u); - domNode.insertBefore(node, domNode.childNodes[insert.r]); - } - - // add end inserts - if (frag) - { - _VirtualDom_appendChild(domNode, frag); - } - - return domNode; -} - - -function _VirtualDom_applyPatchReorderEndInsertsHelp(endInserts, patch) -{ - if (!endInserts) - { - return; - } - - var frag = _VirtualDom_doc.createDocumentFragment(); - for (var i = 0; i < endInserts.length; i++) - { - var insert = endInserts[i]; - var entry = insert.A; - _VirtualDom_appendChild(frag, entry.c === 2 - ? entry.s - : _VirtualDom_render(entry.z, patch.u) - ); - } - return frag; -} - - -function _VirtualDom_virtualize(node) -{ - // TEXT NODES - - if (node.nodeType === 3) - { - return _VirtualDom_text(node.textContent); - } - - - // WEIRD NODES - - if (node.nodeType !== 1) - { - return _VirtualDom_text(''); - } - - - // ELEMENT NODES - - var attrList = _List_Nil; - var attrs = node.attributes; - for (var i = attrs.length; i--; ) - { - var attr = attrs[i]; - var name = attr.name; - var value = attr.value; - attrList = _List_Cons( A2(_VirtualDom_attribute, name, value), attrList ); - } - - var tag = node.tagName.toLowerCase(); - var kidList = _List_Nil; - var kids = node.childNodes; - - for (var i = kids.length; i--; ) - { - kidList = _List_Cons(_VirtualDom_virtualize(kids[i]), kidList); - } - return A3(_VirtualDom_node, tag, attrList, kidList); -} - -function _VirtualDom_dekey(keyedNode) -{ - var keyedKids = keyedNode.e; - var len = keyedKids.length; - var kids = new Array(len); - for (var i = 0; i < len; i++) - { - kids[i] = keyedKids[i].b; - } - - return { - $: 1, - c: keyedNode.c, - d: keyedNode.d, - e: kids, - f: keyedNode.f, - b: keyedNode.b - }; -} - - - - -// ELEMENT - - -var _Debugger_element; - -var _Browser_element = _Debugger_element || F4(function(impl, flagDecoder, debugMetadata, args) -{ - return _Platform_initialize( - flagDecoder, - args, - impl.init, - impl.update, - impl.subscriptions, - function(sendToApp, initialModel) { - var view = impl.view; - /**_UNUSED/ - var domNode = args['node']; - //*/ - /**/ - var domNode = args && args['node'] ? args['node'] : _Debug_crash(0); - //*/ - var currNode = _VirtualDom_virtualize(domNode); - - return _Browser_makeAnimator(initialModel, function(model) - { - var nextNode = view(model); - var patches = _VirtualDom_diff(currNode, nextNode); - domNode = _VirtualDom_applyPatches(domNode, currNode, patches, sendToApp); - currNode = nextNode; - }); - } - ); -}); - - - -// DOCUMENT - - -var _Debugger_document; - -var _Browser_document = _Debugger_document || F4(function(impl, flagDecoder, debugMetadata, args) -{ - return _Platform_initialize( - flagDecoder, - args, - impl.init, - impl.update, - impl.subscriptions, - function(sendToApp, initialModel) { - var divertHrefToApp = impl.setup && impl.setup(sendToApp) - var view = impl.view; - var title = _VirtualDom_doc.title; - var bodyNode = _VirtualDom_doc.body; - var currNode = _VirtualDom_virtualize(bodyNode); - return _Browser_makeAnimator(initialModel, function(model) - { - _VirtualDom_divertHrefToApp = divertHrefToApp; - var doc = view(model); - var nextNode = _VirtualDom_node('body')(_List_Nil)(doc.body); - var patches = _VirtualDom_diff(currNode, nextNode); - bodyNode = _VirtualDom_applyPatches(bodyNode, currNode, patches, sendToApp); - currNode = nextNode; - _VirtualDom_divertHrefToApp = 0; - (title !== doc.title) && (_VirtualDom_doc.title = title = doc.title); - }); - } - ); -}); - - - -// ANIMATION - - -var _Browser_cancelAnimationFrame = - typeof cancelAnimationFrame !== 'undefined' - ? cancelAnimationFrame - : function(id) { clearTimeout(id); }; - -var _Browser_requestAnimationFrame = - typeof requestAnimationFrame !== 'undefined' - ? requestAnimationFrame - : function(callback) { return setTimeout(callback, 1000 / 60); }; - - -function _Browser_makeAnimator(model, draw) -{ - draw(model); - - var state = 0; - - function updateIfNeeded() - { - state = state === 1 - ? 0 - : ( _Browser_requestAnimationFrame(updateIfNeeded), draw(model), 1 ); - } - - return function(nextModel, isSync) - { - model = nextModel; - - isSync - ? ( draw(model), - state === 2 && (state = 1) - ) - : ( state === 0 && _Browser_requestAnimationFrame(updateIfNeeded), - state = 2 - ); - }; -} - - - -// APPLICATION - - -function _Browser_application(impl) -{ - var onUrlChange = impl.onUrlChange; - var onUrlRequest = impl.onUrlRequest; - var key = function() { key.a(onUrlChange(_Browser_getUrl())); }; - - return _Browser_document({ - setup: function(sendToApp) - { - key.a = sendToApp; - _Browser_window.addEventListener('popstate', key); - _Browser_window.navigator.userAgent.indexOf('Trident') < 0 || _Browser_window.addEventListener('hashchange', key); - - return F2(function(domNode, event) - { - if (!event.ctrlKey && !event.metaKey && !event.shiftKey && event.button < 1 && !domNode.target && !domNode.hasAttribute('download')) - { - event.preventDefault(); - var href = domNode.href; - var curr = _Browser_getUrl(); - var next = $elm$url$Url$fromString(href).a; - sendToApp(onUrlRequest( - (next - && curr.protocol === next.protocol - && curr.host === next.host - && curr.port_.a === next.port_.a - ) - ? $elm$browser$Browser$Internal(next) - : $elm$browser$Browser$External(href) - )); - } - }); - }, - init: function(flags) - { - return A3(impl.init, flags, _Browser_getUrl(), key); - }, - view: impl.view, - update: impl.update, - subscriptions: impl.subscriptions - }); -} - -function _Browser_getUrl() -{ - return $elm$url$Url$fromString(_VirtualDom_doc.location.href).a || _Debug_crash(1); -} - -var _Browser_go = F2(function(key, n) -{ - return A2($elm$core$Task$perform, $elm$core$Basics$never, _Scheduler_binding(function() { - n && history.go(n); - key(); - })); -}); - -var _Browser_pushUrl = F2(function(key, url) -{ - return A2($elm$core$Task$perform, $elm$core$Basics$never, _Scheduler_binding(function() { - history.pushState({}, '', url); - key(); - })); -}); - -var _Browser_replaceUrl = F2(function(key, url) -{ - return A2($elm$core$Task$perform, $elm$core$Basics$never, _Scheduler_binding(function() { - history.replaceState({}, '', url); - key(); - })); -}); - - - -// GLOBAL EVENTS - - -var _Browser_fakeNode = { addEventListener: function() {}, removeEventListener: function() {} }; -var _Browser_doc = typeof document !== 'undefined' ? document : _Browser_fakeNode; -var _Browser_window = typeof window !== 'undefined' ? window : _Browser_fakeNode; - -var _Browser_on = F3(function(node, eventName, sendToSelf) -{ - return _Scheduler_spawn(_Scheduler_binding(function(callback) - { - function handler(event) { _Scheduler_rawSpawn(sendToSelf(event)); } - node.addEventListener(eventName, handler, _VirtualDom_passiveSupported && { passive: true }); - return function() { node.removeEventListener(eventName, handler); }; - })); -}); - -var _Browser_decodeEvent = F2(function(decoder, event) -{ - var result = _Json_runHelp(decoder, event); - return $elm$core$Result$isOk(result) ? $elm$core$Maybe$Just(result.a) : $elm$core$Maybe$Nothing; -}); - - - -// PAGE VISIBILITY - - -function _Browser_visibilityInfo() -{ - return (typeof _VirtualDom_doc.hidden !== 'undefined') - ? { hidden: 'hidden', change: 'visibilitychange' } - : - (typeof _VirtualDom_doc.mozHidden !== 'undefined') - ? { hidden: 'mozHidden', change: 'mozvisibilitychange' } - : - (typeof _VirtualDom_doc.msHidden !== 'undefined') - ? { hidden: 'msHidden', change: 'msvisibilitychange' } - : - (typeof _VirtualDom_doc.webkitHidden !== 'undefined') - ? { hidden: 'webkitHidden', change: 'webkitvisibilitychange' } - : { hidden: 'hidden', change: 'visibilitychange' }; -} - - - -// ANIMATION FRAMES - - -function _Browser_rAF() -{ - return _Scheduler_binding(function(callback) - { - var id = _Browser_requestAnimationFrame(function() { - callback(_Scheduler_succeed(Date.now())); - }); - - return function() { - _Browser_cancelAnimationFrame(id); - }; - }); -} - - -function _Browser_now() -{ - return _Scheduler_binding(function(callback) - { - callback(_Scheduler_succeed(Date.now())); - }); -} - - - -// DOM STUFF - - -function _Browser_withNode(id, doStuff) -{ - return _Scheduler_binding(function(callback) - { - _Browser_requestAnimationFrame(function() { - var node = document.getElementById(id); - callback(node - ? _Scheduler_succeed(doStuff(node)) - : _Scheduler_fail($elm$browser$Browser$Dom$NotFound(id)) - ); - }); - }); -} - - -function _Browser_withWindow(doStuff) -{ - return _Scheduler_binding(function(callback) - { - _Browser_requestAnimationFrame(function() { - callback(_Scheduler_succeed(doStuff())); - }); - }); -} - - -// FOCUS and BLUR - - -var _Browser_call = F2(function(functionName, id) -{ - return _Browser_withNode(id, function(node) { - node[functionName](); - return _Utils_Tuple0; - }); -}); - - - -// WINDOW VIEWPORT - - -function _Browser_getViewport() -{ - return { - scene: _Browser_getScene(), - viewport: { - x: _Browser_window.pageXOffset, - y: _Browser_window.pageYOffset, - width: _Browser_doc.documentElement.clientWidth, - height: _Browser_doc.documentElement.clientHeight - } - }; -} - -function _Browser_getScene() -{ - var body = _Browser_doc.body; - var elem = _Browser_doc.documentElement; - return { - width: Math.max(body.scrollWidth, body.offsetWidth, elem.scrollWidth, elem.offsetWidth, elem.clientWidth), - height: Math.max(body.scrollHeight, body.offsetHeight, elem.scrollHeight, elem.offsetHeight, elem.clientHeight) - }; -} - -var _Browser_setViewport = F2(function(x, y) -{ - return _Browser_withWindow(function() - { - _Browser_window.scroll(x, y); - return _Utils_Tuple0; - }); -}); - - - -// ELEMENT VIEWPORT - - -function _Browser_getViewportOf(id) -{ - return _Browser_withNode(id, function(node) - { - return { - scene: { - width: node.scrollWidth, - height: node.scrollHeight - }, - viewport: { - x: node.scrollLeft, - y: node.scrollTop, - width: node.clientWidth, - height: node.clientHeight - } - }; - }); -} - - -var _Browser_setViewportOf = F3(function(id, x, y) -{ - return _Browser_withNode(id, function(node) - { - node.scrollLeft = x; - node.scrollTop = y; - return _Utils_Tuple0; - }); -}); - - - -// ELEMENT - - -function _Browser_getElement(id) -{ - return _Browser_withNode(id, function(node) - { - var rect = node.getBoundingClientRect(); - var x = _Browser_window.pageXOffset; - var y = _Browser_window.pageYOffset; - return { - scene: _Browser_getScene(), - viewport: { - x: x, - y: y, - width: _Browser_doc.documentElement.clientWidth, - height: _Browser_doc.documentElement.clientHeight - }, - element: { - x: x + rect.left, - y: y + rect.top, - width: rect.width, - height: rect.height - } - }; - }); -} - - - -// LOAD and RELOAD - - -function _Browser_reload(skipCache) -{ - return A2($elm$core$Task$perform, $elm$core$Basics$never, _Scheduler_binding(function(callback) - { - _VirtualDom_doc.location.reload(skipCache); - })); -} - -function _Browser_load(url) -{ - return A2($elm$core$Task$perform, $elm$core$Basics$never, _Scheduler_binding(function(callback) - { - try - { - _Browser_window.location = url; - } - catch(err) - { - // Only Firefox can throw a NS_ERROR_MALFORMED_URI exception here. - // Other browsers reload the page, so let's be consistent about that. - _VirtualDom_doc.location.reload(false); - } - })); -} - - - -// DECODER - -var _File_decoder = _Json_decodePrim(function(value) { - // NOTE: checks if `File` exists in case this is run on node - return (typeof File !== 'undefined' && value instanceof File) - ? $elm$core$Result$Ok(value) - : _Json_expecting('a FILE', value); -}); - - -// METADATA - -function _File_name(file) { return file.name; } -function _File_mime(file) { return file.type; } -function _File_size(file) { return file.size; } - -function _File_lastModified(file) -{ - return $elm$time$Time$millisToPosix(file.lastModified); -} - - -// DOWNLOAD - -var _File_downloadNode; - -function _File_getDownloadNode() -{ - return _File_downloadNode || (_File_downloadNode = document.createElement('a')); -} - -var _File_download = F3(function(name, mime, content) -{ - return _Scheduler_binding(function(callback) - { - var blob = new Blob([content], {type: mime}); - - // for IE10+ - if (navigator.msSaveOrOpenBlob) - { - navigator.msSaveOrOpenBlob(blob, name); - return; - } - - // for HTML5 - var node = _File_getDownloadNode(); - var objectUrl = URL.createObjectURL(blob); - node.href = objectUrl; - node.download = name; - _File_click(node); - URL.revokeObjectURL(objectUrl); - }); -}); - -function _File_downloadUrl(href) -{ - return _Scheduler_binding(function(callback) - { - var node = _File_getDownloadNode(); - node.href = href; - node.download = ''; - node.origin === location.origin || (node.target = '_blank'); - _File_click(node); - }); -} - - -// IE COMPATIBILITY - -function _File_makeBytesSafeForInternetExplorer(bytes) -{ - // only needed by IE10 and IE11 to fix https://github.com/elm/file/issues/10 - // all other browsers can just run `new Blob([bytes])` directly with no problem - // - return new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength); -} - -function _File_click(node) -{ - // only needed by IE10 and IE11 to fix https://github.com/elm/file/issues/11 - // all other browsers have MouseEvent and do not need this conditional stuff - // - if (typeof MouseEvent === 'function') - { - node.dispatchEvent(new MouseEvent('click')); - } - else - { - var event = document.createEvent('MouseEvents'); - event.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); - document.body.appendChild(node); - node.dispatchEvent(event); - document.body.removeChild(node); - } -} - - -// UPLOAD - -var _File_node; - -function _File_uploadOne(mimes) -{ - return _Scheduler_binding(function(callback) - { - _File_node = document.createElement('input'); - _File_node.type = 'file'; - _File_node.accept = A2($elm$core$String$join, ',', mimes); - _File_node.addEventListener('change', function(event) - { - callback(_Scheduler_succeed(event.target.files[0])); - }); - _File_click(_File_node); - }); -} - -function _File_uploadOneOrMore(mimes) -{ - return _Scheduler_binding(function(callback) - { - _File_node = document.createElement('input'); - _File_node.type = 'file'; - _File_node.multiple = true; - _File_node.accept = A2($elm$core$String$join, ',', mimes); - _File_node.addEventListener('change', function(event) - { - var elmFiles = _List_fromArray(event.target.files); - callback(_Scheduler_succeed(_Utils_Tuple2(elmFiles.a, elmFiles.b))); - }); - _File_click(_File_node); - }); -} - - -// CONTENT - -function _File_toString(blob) -{ - return _Scheduler_binding(function(callback) - { - var reader = new FileReader(); - reader.addEventListener('loadend', function() { - callback(_Scheduler_succeed(reader.result)); - }); - reader.readAsText(blob); - return function() { reader.abort(); }; - }); -} - -function _File_toBytes(blob) -{ - return _Scheduler_binding(function(callback) - { - var reader = new FileReader(); - reader.addEventListener('loadend', function() { - callback(_Scheduler_succeed(new DataView(reader.result))); - }); - reader.readAsArrayBuffer(blob); - return function() { reader.abort(); }; - }); -} - -function _File_toUrl(blob) -{ - return _Scheduler_binding(function(callback) - { - var reader = new FileReader(); - reader.addEventListener('loadend', function() { - callback(_Scheduler_succeed(reader.result)); - }); - reader.readAsDataURL(blob); - return function() { reader.abort(); }; - }); -} - - - -// eslint-disable-next-line no-unused-vars -var _Texture_load = F6(function (magnify, mininify, horizontalWrap, verticalWrap, flipY, url) { - var isMipmap = mininify !== 9728 && mininify !== 9729; - return _Scheduler_binding(function (callback) { - var img = new Image(); - function createTexture(gl) { - var texture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magnify); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, mininify); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, horizontalWrap); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, verticalWrap); - if (isMipmap) { - gl.generateMipmap(gl.TEXTURE_2D); - } - gl.bindTexture(gl.TEXTURE_2D, null); - return texture; - } - img.onload = function () { - var width = img.width; - var height = img.height; - var widthPowerOfTwo = (width & (width - 1)) === 0; - var heightPowerOfTwo = (height & (height - 1)) === 0; - var isSizeValid = (widthPowerOfTwo && heightPowerOfTwo) || ( - !isMipmap - && horizontalWrap === 33071 // clamp to edge - && verticalWrap === 33071 - ); - if (isSizeValid) { - callback(_Scheduler_succeed({ - $: 0, - createTexture: createTexture, - a: width, - b: height - })); - } else { - callback(_Scheduler_fail(A2( - $elm_explorations$webgl$WebGL$Texture$SizeError, - width, - height - ))); - } - }; - img.onerror = function () { - callback(_Scheduler_fail($elm_explorations$webgl$WebGL$Texture$LoadError)); - }; - if (url.slice(0, 5) !== 'data:') { - img.crossOrigin = 'Anonymous'; - } - img.src = url; - }); -}); - -// eslint-disable-next-line no-unused-vars -var _Texture_size = function (texture) { - return _Utils_Tuple2(texture.a, texture.b); -}; - - -function _Url_percentEncode(string) -{ - return encodeURIComponent(string); -} - -function _Url_percentDecode(string) -{ - try - { - return $elm$core$Maybe$Just(decodeURIComponent(string)); - } - catch (e) - { - return $elm$core$Maybe$Nothing; - } -} - - -var _Bitwise_and = F2(function(a, b) -{ - return a & b; -}); - -var _Bitwise_or = F2(function(a, b) -{ - return a | b; -}); - -var _Bitwise_xor = F2(function(a, b) -{ - return a ^ b; -}); - -function _Bitwise_complement(a) -{ - return ~a; -}; - -var _Bitwise_shiftLeftBy = F2(function(offset, a) -{ - return a << offset; -}); - -var _Bitwise_shiftRightBy = F2(function(offset, a) -{ - return a >> offset; -}); - -var _Bitwise_shiftRightZfBy = F2(function(offset, a) -{ - return a >>> offset; -}); - - -function _WebGL_log(/* msg */) { - // console.log(msg); -} - -var _WebGL_guid = 0; - -function _WebGL_listEach(fn, list) { - for (; list.b; list = list.b) { - fn(list.a); - } -} - -function _WebGL_listLength(list) { - var length = 0; - for (; list.b; list = list.b) { - length++; - } - return length; -} - -var _WebGL_rAF = typeof requestAnimationFrame !== 'undefined' ? - requestAnimationFrame : - function (cb) { setTimeout(cb, 1000 / 60); }; - -// eslint-disable-next-line no-unused-vars -var _WebGL_entity = F5(function (settings, vert, frag, mesh, uniforms) { - return { - $: 0, - a: settings, - b: vert, - c: frag, - d: mesh, - e: uniforms - }; -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableBlend = F2(function (gl, setting) { - gl.enable(gl.BLEND); - // a b c d e f g h i j - // eq1 f11 f12 eq2 f21 f22 r g b a - gl.blendEquationSeparate(setting.a, setting.d); - gl.blendFuncSeparate(setting.b, setting.c, setting.e, setting.f); - gl.blendColor(setting.g, setting.h, setting.i, setting.j); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableDepthTest = F2(function (gl, setting) { - gl.enable(gl.DEPTH_TEST); - // a b c d - // func mask near far - gl.depthFunc(setting.a); - gl.depthMask(setting.b); - gl.depthRange(setting.c, setting.d); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableStencilTest = F2(function (gl, setting) { - gl.enable(gl.STENCIL_TEST); - // a b c d e f g h i j k - // ref mask writeMask test1 fail1 zfail1 zpass1 test2 fail2 zfail2 zpass2 - gl.stencilFuncSeparate(gl.FRONT, setting.d, setting.a, setting.b); - gl.stencilOpSeparate(gl.FRONT, setting.e, setting.f, setting.g); - gl.stencilMaskSeparate(gl.FRONT, setting.c); - gl.stencilFuncSeparate(gl.BACK, setting.h, setting.a, setting.b); - gl.stencilOpSeparate(gl.BACK, setting.i, setting.j, setting.k); - gl.stencilMaskSeparate(gl.BACK, setting.c); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableScissor = F2(function (gl, setting) { - gl.enable(gl.SCISSOR_TEST); - gl.scissor(setting.a, setting.b, setting.c, setting.d); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableColorMask = F2(function (gl, setting) { - gl.colorMask(setting.a, setting.b, setting.c, setting.d); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableCullFace = F2(function (gl, setting) { - gl.enable(gl.CULL_FACE); - gl.cullFace(setting.a); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enablePolygonOffset = F2(function (gl, setting) { - gl.enable(gl.POLYGON_OFFSET_FILL); - gl.polygonOffset(setting.a, setting.b); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableSampleCoverage = F2(function (gl, setting) { - gl.enable(gl.SAMPLE_COVERAGE); - gl.sampleCoverage(setting.a, setting.b); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableSampleAlphaToCoverage = F2(function (gl, setting) { - gl.enable(gl.SAMPLE_ALPHA_TO_COVERAGE); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_disableBlend = function (gl) { - gl.disable(gl.BLEND); -}; - -// eslint-disable-next-line no-unused-vars -var _WebGL_disableDepthTest = function (gl) { - gl.disable(gl.DEPTH_TEST); -}; - -// eslint-disable-next-line no-unused-vars -var _WebGL_disableStencilTest = function (gl) { - gl.disable(gl.STENCIL_TEST); -}; - -// eslint-disable-next-line no-unused-vars -var _WebGL_disableScissor = function (gl) { - gl.disable(gl.SCISSOR_TEST); -}; - -// eslint-disable-next-line no-unused-vars -var _WebGL_disableColorMask = function (gl) { - gl.colorMask(true, true, true, true); -}; - -// eslint-disable-next-line no-unused-vars -var _WebGL_disableCullFace = function (gl) { - gl.disable(gl.CULL_FACE); -}; - -// eslint-disable-next-line no-unused-vars -var _WebGL_disablePolygonOffset = function (gl) { - gl.disable(gl.POLYGON_OFFSET_FILL); -}; - -// eslint-disable-next-line no-unused-vars -var _WebGL_disableSampleCoverage = function (gl) { - gl.disable(gl.SAMPLE_COVERAGE); -}; - -// eslint-disable-next-line no-unused-vars -var _WebGL_disableSampleAlphaToCoverage = function (gl) { - gl.disable(gl.SAMPLE_ALPHA_TO_COVERAGE); -}; - -function _WebGL_doCompile(gl, src, type) { - - var shader = gl.createShader(type); - _WebGL_log('Created shader'); - - gl.shaderSource(shader, src); - gl.compileShader(shader); - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - throw gl.getShaderInfoLog(shader); - } - - return shader; - -} - -function _WebGL_doLink(gl, vshader, fshader) { - - var program = gl.createProgram(); - _WebGL_log('Created program'); - - gl.attachShader(program, vshader); - gl.attachShader(program, fshader); - gl.linkProgram(program); - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - throw gl.getProgramInfoLog(program); - } - - return program; - -} - -function _WebGL_getAttributeInfo(gl, type) { - switch (type) { - case gl.FLOAT: - return { size: 1, arraySize: 1, type: Float32Array, baseType: gl.FLOAT }; - case gl.FLOAT_VEC2: - return { size: 2, arraySize: 1, type: Float32Array, baseType: gl.FLOAT }; - case gl.FLOAT_VEC3: - return { size: 3, arraySize: 1, type: Float32Array, baseType: gl.FLOAT }; - case gl.FLOAT_VEC4: - return { size: 4, arraySize: 1, type: Float32Array, baseType: gl.FLOAT }; - case gl.FLOAT_MAT4: - return { size: 4, arraySize: 4, type: Float32Array, baseType: gl.FLOAT }; - case gl.INT: - return { size: 1, arraySize: 1, type: Int32Array, baseType: gl.INT }; - } -} - -/** - * Form the buffer for a given attribute. - * - * @param {WebGLRenderingContext} gl context - * @param {WebGLActiveInfo} attribute the attribute to bind to. - * We use its name to grab the record by name and also to know - * how many elements we need to grab. - * @param {Mesh} mesh The mesh coming in from Elm. - * @param {Object} attributes The mapping between the attribute names and Elm fields - * @return {WebGLBuffer} - */ -function _WebGL_doBindAttribute(gl, attribute, mesh, attributes) { - // The length of the number of vertices that - // complete one 'thing' based on the drawing mode. - // ie, 2 for Lines, 3 for Triangles, etc. - var elemSize = mesh.a.elemSize; - - var idxKeys = []; - for (var i = 0; i < elemSize; i++) { - idxKeys.push(String.fromCharCode(97 + i)); - } - - function dataFill(data, cnt, fillOffset, elem, key) { - var i; - if (elemSize === 1) { - for (i = 0; i < cnt; i++) { - data[fillOffset++] = cnt === 1 ? elem[key] : elem[key][i]; - } - } else { - idxKeys.forEach(function (idx) { - for (i = 0; i < cnt; i++) { - data[fillOffset++] = cnt === 1 ? elem[idx][key] : elem[idx][key][i]; - } - }); - } - } - - var attributeInfo = _WebGL_getAttributeInfo(gl, attribute.type); - - if (attributeInfo === undefined) { - throw new Error('No info available for: ' + attribute.type); - } - - var dataIdx = 0; - var dataOffset = attributeInfo.size * attributeInfo.arraySize * elemSize; - var array = new attributeInfo.type(_WebGL_listLength(mesh.b) * dataOffset); - - _WebGL_listEach(function (elem) { - dataFill(array, attributeInfo.size * attributeInfo.arraySize, dataIdx, elem, attributes[attribute.name] || attribute.name); - dataIdx += dataOffset; - }, mesh.b); - - var buffer = gl.createBuffer(); - _WebGL_log('Created attribute buffer ' + attribute.name); - - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW); - return buffer; -} - -/** - * This sets up the binding caching buffers. - * - * We don't actually bind any buffers now except for the indices buffer. - * The problem with filling the buffers here is that it is possible to - * have a buffer shared between two webgl shaders; - * which could have different active attributes. If we bind it here against - * a particular program, we might not bind them all. That final bind is now - * done right before drawing. - * - * @param {WebGLRenderingContext} gl context - * @param {Mesh} mesh a mesh object from Elm - * @return {Object} buffer - an object with the following properties - * @return {Number} buffer.numIndices - * @return {WebGLBuffer} buffer.indexBuffer - * @return {Object} buffer.buffers - will be used to buffer attributes - */ -function _WebGL_doBindSetup(gl, mesh) { - _WebGL_log('Created index buffer'); - var indexBuffer = gl.createBuffer(); - var indices = (mesh.a.indexSize === 0) - ? _WebGL_makeSequentialBuffer(mesh.a.elemSize * _WebGL_listLength(mesh.b)) - : _WebGL_makeIndexedBuffer(mesh.c, mesh.a.indexSize); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); - - return { - numIndices: indices.length, - indexBuffer: indexBuffer, - buffers: {} - }; -} - -/** - * Create an indices array and fill it with 0..n - * - * @param {Number} numIndices The number of indices - * @return {Uint16Array} indices - */ -function _WebGL_makeSequentialBuffer(numIndices) { - var indices = new Uint16Array(numIndices); - for (var i = 0; i < numIndices; i++) { - indices[i] = i; - } - return indices; -} - -/** - * Create an indices array and fill it from indices - * based on the size of the index - * - * @param {List} indicesList the list of indices - * @param {Number} indexSize the size of the index - * @return {Uint16Array} indices - */ -function _WebGL_makeIndexedBuffer(indicesList, indexSize) { - var indices = new Uint16Array(_WebGL_listLength(indicesList) * indexSize); - var fillOffset = 0; - var i; - _WebGL_listEach(function (elem) { - if (indexSize === 1) { - indices[fillOffset++] = elem; - } else { - for (i = 0; i < indexSize; i++) { - indices[fillOffset++] = elem[String.fromCharCode(97 + i)]; - } - } - }, indicesList); - return indices; -} - -function _WebGL_getProgID(vertID, fragID) { - return vertID + '#' + fragID; -} - -var _WebGL_drawGL = F2(function (model, domNode) { - - var gl = model.f.gl; - - if (!gl) { - return domNode; - } - - gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); - _WebGL_log('Drawing'); - - function drawEntity(entity) { - if (!entity.d.b.b) { - return; // Empty list - } - - var progid; - var program; - if (entity.b.id && entity.c.id) { - progid = _WebGL_getProgID(entity.b.id, entity.c.id); - program = model.f.programs[progid]; - } - - if (!program) { - - var vshader; - if (entity.b.id) { - vshader = model.f.shaders[entity.b.id]; - } else { - entity.b.id = _WebGL_guid++; - } - - if (!vshader) { - vshader = _WebGL_doCompile(gl, entity.b.src, gl.VERTEX_SHADER); - model.f.shaders[entity.b.id] = vshader; - } - - var fshader; - if (entity.c.id) { - fshader = model.f.shaders[entity.c.id]; - } else { - entity.c.id = _WebGL_guid++; - } - - if (!fshader) { - fshader = _WebGL_doCompile(gl, entity.c.src, gl.FRAGMENT_SHADER); - model.f.shaders[entity.c.id] = fshader; - } - - var glProgram = _WebGL_doLink(gl, vshader, fshader); - - program = { - glProgram: glProgram, - attributes: Object.assign({}, entity.b.attributes, entity.c.attributes), - uniformSetters: _WebGL_createUniformSetters( - gl, - model, - glProgram, - Object.assign({}, entity.b.uniforms, entity.c.uniforms) - ) - }; - - progid = _WebGL_getProgID(entity.b.id, entity.c.id); - model.f.programs[progid] = program; - - } - - gl.useProgram(program.glProgram); - - _WebGL_setUniforms(program.uniformSetters, entity.e); - - var buffer = model.f.buffers.get(entity.d); - - if (!buffer) { - buffer = _WebGL_doBindSetup(gl, entity.d); - model.f.buffers.set(entity.d, buffer); - } - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.indexBuffer); - - var numAttributes = gl.getProgramParameter(program.glProgram, gl.ACTIVE_ATTRIBUTES); - - for (var i = 0; i < numAttributes; i++) { - var attribute = gl.getActiveAttrib(program.glProgram, i); - - var attribLocation = gl.getAttribLocation(program.glProgram, attribute.name); - gl.enableVertexAttribArray(attribLocation); - - if (buffer.buffers[attribute.name] === undefined) { - buffer.buffers[attribute.name] = _WebGL_doBindAttribute(gl, attribute, entity.d, program.attributes); - } - var attributeBuffer = buffer.buffers[attribute.name]; - var attributeInfo = _WebGL_getAttributeInfo(gl, attribute.type); - - gl.bindBuffer(gl.ARRAY_BUFFER, attributeBuffer); - - if (attributeInfo.arraySize === 1) { - gl.vertexAttribPointer(attribLocation, attributeInfo.size, attributeInfo.baseType, false, 0, 0); - } else { - // Point to four vec4 in case of mat4 - var offset = attributeInfo.size * 4; // float32 takes 4 bytes - var stride = offset * attributeInfo.arraySize; - for (var m = 0; m < attributeInfo.arraySize; m++) { - gl.enableVertexAttribArray(attribLocation + m); - gl.vertexAttribPointer(attribLocation + m, attributeInfo.size, attributeInfo.baseType, false, stride, offset * m); - } - } - } - _WebGL_listEach(function (setting) { - return A2($elm_explorations$webgl$WebGL$Internal$enableSetting, gl, setting); - }, entity.a); - - gl.drawElements(entity.d.a.mode, buffer.numIndices, gl.UNSIGNED_SHORT, 0); - - _WebGL_listEach(function (setting) { - return A2($elm_explorations$webgl$WebGL$Internal$disableSetting, gl, setting); - }, entity.a); - - } - - _WebGL_listEach(drawEntity, model.g); - return domNode; -}); - -function _WebGL_createUniformSetters(gl, model, program, uniformsMap) { - var textureCounter = 0; - function createUniformSetter(program, uniform) { - var uniformLocation = gl.getUniformLocation(program, uniform.name); - switch (uniform.type) { - case gl.INT: - return function (value) { - gl.uniform1i(uniformLocation, value); - }; - case gl.FLOAT: - return function (value) { - gl.uniform1f(uniformLocation, value); - }; - case gl.FLOAT_VEC2: - return function (value) { - gl.uniform2fv(uniformLocation, new Float32Array(value)); - }; - case gl.FLOAT_VEC3: - return function (value) { - gl.uniform3fv(uniformLocation, new Float32Array(value)); - }; - case gl.FLOAT_VEC4: - return function (value) { - gl.uniform4fv(uniformLocation, new Float32Array(value)); - }; - case gl.FLOAT_MAT4: - return function (value) { - gl.uniformMatrix4fv(uniformLocation, false, new Float32Array(value)); - }; - case gl.SAMPLER_2D: - var currentTexture = textureCounter++; - return function (texture) { - gl.activeTexture(gl.TEXTURE0 + currentTexture); - var tex = model.f.textures.get(texture); - if (!tex) { - _WebGL_log('Created texture'); - tex = texture.createTexture(gl); - model.f.textures.set(texture, tex); - } - gl.bindTexture(gl.TEXTURE_2D, tex); - gl.uniform1i(uniformLocation, currentTexture); - }; - case gl.BOOL: - return function (value) { - gl.uniform1i(uniformLocation, value); - }; - default: - _WebGL_log('Unsupported uniform type: ' + uniform.type); - return function () { }; - } - } - - var uniformSetters = {}; - var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); - for (var i = 0; i < numUniforms; i++) { - var uniform = gl.getActiveUniform(program, i); - uniformSetters[uniformsMap[uniform.name] || uniform.name] = createUniformSetter(program, uniform); - } - - return uniformSetters; -} - -function _WebGL_setUniforms(setters, values) { - Object.keys(values).forEach(function (name) { - var setter = setters[name]; - if (setter) { - setter(values[name]); - } - }); -} - -// VIRTUAL-DOM WIDGET - -// eslint-disable-next-line no-unused-vars -var _WebGL_toHtml = F3(function (options, factList, entities) { - return _VirtualDom_custom( - factList, - { - g: entities, - f: {}, - h: options - }, - _WebGL_render, - _WebGL_diff - ); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableAlpha = F2(function (options, option) { - options.contextAttributes.alpha = true; - options.contextAttributes.premultipliedAlpha = option.a; -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableDepth = F2(function (options, option) { - options.contextAttributes.depth = true; - options.sceneSettings.push(function (gl) { - gl.clearDepth(option.a); - }); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableStencil = F2(function (options, option) { - options.contextAttributes.stencil = true; - options.sceneSettings.push(function (gl) { - gl.clearStencil(option.a); - }); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableAntialias = F2(function (options, option) { - options.contextAttributes.antialias = true; -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enableClearColor = F2(function (options, option) { - options.sceneSettings.push(function (gl) { - gl.clearColor(option.a, option.b, option.c, option.d); - }); -}); - -// eslint-disable-next-line no-unused-vars -var _WebGL_enablePreserveDrawingBuffer = F2(function (options, option) { - options.contextAttributes.preserveDrawingBuffer = true; -}); - -/** - * Creates canvas and schedules initial _WebGL_drawGL - * @param {Object} model - * @param {Object} model.f that may contain the following properties: - gl, shaders, programs, buffers, textures - * @param {List