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/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 deleted file mode 100644 index f6de46289..000000000 --- a/website/build.sbt +++ /dev/null @@ -1,26 +0,0 @@ -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 - ) - -addCommandAlias( - "publishIndigoSite", - List( - "makeSite", - "ghpagesPushSite" - ).mkString(";", ";", "") -) diff --git a/website/build.sh b/website/build.sh deleted file mode 100644 index afbb4a14a..000000000 --- a/website/build.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# TODO -# Auto update the demos? - -set -e - -WEBSITE_DIR=$(pwd) -PROJECT_DIR=$WEBSITE_DIR/.. -INDIGO_ENGINE_DIR=$PROJECT_DIR/indigo/ - -# ----- -# generate / check docs -# - "indigo/doc" // Docs in ./indigo/target/scala-3.3.0/unidoc/ -# - "docs/mdoc" // Docs in ./indigo/indigo-docs/target/mdoc -cd $INDIGO_ENGINE_DIR -sbt gendocs -cd $WEBSITE_DIR - -# ----- -# build the site -yarn run build - -# ----- -# Publish -cp -R $INDIGO_ENGINE_DIR/target/scala-3.*/unidoc/. $WEBSITE_DIR/build/indigo-site/api/ -sbt clean 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/build.properties b/website/project/build.properties deleted file mode 100644 index 875b706a8..000000000 --- a/website/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version=1.9.2 diff --git a/website/project/plugins.sbt b/website/project/plugins.sbt deleted file mode 100644 index 12499a721..000000000 --- a/website/project/plugins.sbt +++ /dev/null @@ -1,2 +0,0 @@ -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