Full Code of LudiKha/Graphene for AI

master d1527f324fbb cached
169 files
333.3 KB
92.4k tokens
732 symbols
1 requests
Download .txt
Showing preview only (374K chars total). Download the full file or copy to clipboard to get everything.
Repository: LudiKha/Graphene
Branch: master
Commit: d1527f324fbb
Files: 169
Total size: 333.3 KB

Directory structure:
gitextract_6hvvmno2/

├── .github/
│   └── FUNDING.yml
├── LICENSE
├── README.md
├── docs/
│   ├── About.md
│   ├── _config.yml
│   └── howto.md
└── src/
    ├── Core/
    │   ├── Binding/
    │   │   ├── Binder.cs
    │   │   ├── Binder.cs.meta
    │   │   ├── Binding.cs
    │   │   ├── Binding.cs.meta
    │   │   ├── BindingAttribute.cs
    │   │   ├── BindingAttribute.cs.meta
    │   │   ├── BindingsManager.cs
    │   │   ├── BindingsManager.cs.meta
    │   │   ├── CollectionBinding.cs
    │   │   ├── CollectionBinding.cs.meta
    │   │   ├── MemberBinding.cs
    │   │   └── MemberBinding.cs.meta
    │   ├── Binding.meta
    │   ├── Extensions/
    │   │   ├── ButtonGroup.cs
    │   │   ├── ButtonGroup.cs.meta
    │   │   ├── CycleField.cs
    │   │   ├── CycleField.cs.meta
    │   │   ├── Dialog.cs
    │   │   ├── Dialog.cs.meta
    │   │   ├── GrapheneRoot.cs
    │   │   ├── GrapheneRoot.cs.meta
    │   │   ├── If.cs
    │   │   ├── If.cs.meta
    │   │   ├── Route.cs
    │   │   ├── Route.cs.meta
    │   │   ├── SelectField.cs
    │   │   ├── SelectField.cs.meta
    │   │   ├── TemplateTypes/
    │   │   │   ├── Button.cs
    │   │   │   ├── Button.cs.meta
    │   │   │   ├── TemplateRef.cs
    │   │   │   └── TemplateRef.cs.meta
    │   │   ├── TemplateTypes.meta
    │   │   ├── View.cs
    │   │   ├── View.cs.meta
    │   │   ├── VisualElementExtensions.cs
    │   │   └── VisualElementExtensions.cs.meta
    │   ├── Extensions.meta
    │   ├── Graphene.cs
    │   ├── Graphene.cs.meta
    │   ├── GrapheneComponent.cs
    │   ├── GrapheneComponent.cs.meta
    │   ├── Injector.cs
    │   ├── Injector.cs.meta
    │   ├── Interfaces.cs
    │   ├── Interfaces.cs.meta
    │   ├── Model/
    │   │   ├── BindableObjects/
    │   │   │   ├── BindableBaseField.cs
    │   │   │   ├── BindableBaseField.cs.meta
    │   │   │   ├── BindableObject.cs
    │   │   │   ├── BindableObject.cs.meta
    │   │   │   ├── ListBindable.cs
    │   │   │   └── ListBindable.cs.meta
    │   │   ├── BindableObjects.meta
    │   │   ├── GenericModelAsset.cs
    │   │   ├── GenericModelAsset.cs.meta
    │   │   ├── GenericModelBehaviour.cs
    │   │   ├── GenericModelBehaviour.cs.meta
    │   │   ├── ScriptableObjectModel.cs
    │   │   ├── ScriptableObjectModel.cs.meta
    │   │   ├── ViewModel/
    │   │   │   ├── FormViewModel.cs
    │   │   │   ├── FormViewModel.cs.meta
    │   │   │   ├── MultiFormViewModel.cs
    │   │   │   ├── MultiFormViewModel.cs.meta
    │   │   │   ├── NavViewModel.cs
    │   │   │   ├── NavViewModel.cs.meta
    │   │   │   ├── ViewModelComponent.cs
    │   │   │   └── ViewModelComponent.cs.meta
    │   │   └── ViewModel.meta
    │   ├── Model.meta
    │   ├── Plate.cs
    │   ├── Plate.cs.meta
    │   ├── Rendering/
    │   │   ├── RenderUtils.cs
    │   │   ├── RenderUtils.cs.meta
    │   │   ├── Renderer.cs
    │   │   └── Renderer.cs.meta
    │   ├── Rendering.meta
    │   ├── Routing/
    │   │   ├── EnableOnState.cs
    │   │   ├── EnableOnState.cs.meta
    │   │   ├── Interpreters/
    │   │   │   ├── ApplicationStateInterpreter.cs
    │   │   │   ├── ApplicationStateInterpreter.cs.meta
    │   │   │   ├── NavigationStateHandler.cs
    │   │   │   ├── NavigationStateHandler.cs.meta
    │   │   │   ├── StateInterpreter.cs
    │   │   │   └── StateInterpreter.cs.meta
    │   │   ├── Interpreters.meta
    │   │   ├── Router.cs
    │   │   ├── Router.cs.meta
    │   │   ├── StateHandle.cs
    │   │   ├── StateHandle.cs.meta
    │   │   ├── StringEnableOnState.cs
    │   │   ├── StringEnableOnState.cs.meta
    │   │   ├── StringRouter.cs
    │   │   ├── StringRouter.cs.meta
    │   │   ├── StringStateHandle.cs
    │   │   └── StringStateHandle.cs.meta
    │   ├── Routing.meta
    │   ├── Styling/
    │   │   ├── AlignItemsOverride.cs
    │   │   ├── AlignItemsOverride.cs.meta
    │   │   ├── FlexDirectionOverride.cs
    │   │   ├── FlexDirectionOverride.cs.meta
    │   │   ├── InlineStyleOverrides.cs
    │   │   ├── InlineStyleOverrides.cs.meta
    │   │   ├── JustifyOverride.cs
    │   │   ├── JustifyOverride.cs.meta
    │   │   ├── StyleOverride.cs
    │   │   ├── StyleOverride.cs.meta
    │   │   ├── WrapOverride.cs
    │   │   └── WrapOverride.cs.meta
    │   ├── Styling.meta
    │   ├── Templating/
    │   │   ├── TemplatePreset.cs
    │   │   └── TemplatePreset.cs.meta
    │   ├── Templating.meta
    │   ├── View/
    │   │   ├── SerializedView.cs
    │   │   ├── SerializedView.cs.meta
    │   │   ├── ViewHandle.cs
    │   │   └── ViewHandle.cs.meta
    │   └── View.meta
    ├── Core.meta
    ├── Editor/
    │   ├── CustomDictionaryPropertyDrawers.cs
    │   ├── CustomDictionaryPropertyDrawers.cs.meta
    │   ├── Graphene.Editor.asmdef
    │   ├── Graphene.Editor.asmdef.meta
    │   ├── GrapheneEditorUtilities.cs
    │   ├── GrapheneEditorUtilities.cs.meta
    │   ├── ViewSelectorStringDrawer.cs
    │   └── ViewSelectorStringDrawer.cs.meta
    ├── Editor.meta
    ├── Graphene.Core.asmdef
    ├── Graphene.Core.asmdef.meta
    ├── Lib/
    │   ├── DragManipulator/
    │   │   ├── DragManipulator.cs
    │   │   └── DragManipulator.cs.meta
    │   ├── DragManipulator.meta
    │   ├── SerializableDictionary/
    │   │   ├── Editor/
    │   │   │   ├── SerializableDictionary.Editor.asmdef
    │   │   │   ├── SerializableDictionary.Editor.asmdef.meta
    │   │   │   ├── SerializableDictionaryPropertyDrawer.cs
    │   │   │   └── SerializableDictionaryPropertyDrawer.cs.meta
    │   │   ├── Editor.meta
    │   │   ├── SerializableDictionary.Runtime.asmdef
    │   │   ├── SerializableDictionary.Runtime.asmdef.meta
    │   │   ├── SerializableDictionary.cs
    │   │   └── SerializableDictionary.cs.meta
    │   └── SerializableDictionary.meta
    ├── Lib.meta
    ├── Resources/
    │   ├── Icons/
    │   │   ├── atom.png.meta
    │   │   ├── form.png.meta
    │   │   ├── graphene.png.meta
    │   │   ├── injector.png.meta
    │   │   ├── layout.png.meta
    │   │   ├── molecule.png.meta
    │   │   ├── plate.png.meta
    │   │   ├── quantum.png.meta
    │   │   ├── renderer.png.meta
    │   │   ├── router.png.meta
    │   │   ├── state.png.meta
    │   │   ├── template.png.meta
    │   │   └── theme.png.meta
    │   ├── Icons.meta
    │   ├── Logo/
    │   │   ├── graphene-logo-full.png.meta
    │   │   ├── graphene-logo-white.png.meta
    │   │   └── graphene-logo.png.meta
    │   └── Logo.meta
    ├── Resources.meta
    ├── package.json
    └── package.json.meta

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: [LudiKha] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 Khaya Ludidi - CupBearer Interactive

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<p align="center">
  <img src="https://raw.githubusercontent.com/LudiKha/Graphene/master/docs/images/graphene-logo-full.png" />
</p>

&nbsp;

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![last-commit](https://img.shields.io/github/last-commit/LudiKha/Graphene) ![open-issues](https://img.shields.io/github/issues/LudiKha/Graphene) [![](https://img.shields.io/twitter/follow/LudiKha.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=LudiKha)

Graphene is a lightweight and modular framework for building runtime user interfaces with Unity's [UI Toolkit][0f273cb2].

[0f273cb2]: https://docs.unity3d.com/2020.1/Documentation/Manual/UIElements.html "UI Toolkit"

&nbsp;

# Intro

Graphene **superconducts** your creativity for efficiently building modern interactive UI for games. It takes care of the heavy lifting by providing a framework inspired by Web standards, right into Unity.

It's **lightweight** and modular - you get to pick and choose which parts you need for your projects.

- **Declarative Hierarchy**: Graphene makes it painless to design interactive UI. Use the familiar GameObjects hierarchy to design simple `Views` as sections of the screen or nested states.
- **Reduce Boilerplate**: Focus on your custom logic and design of building UI instead of repeating low-level tasks for each unique screen you are building. Graphene comes with a number of `Controls` that greatly enhance the speed of creating interactive UI, whilst reducing the need of custom view controllers in C# by exposing vital functionality in Uxml.
- **Attribute-Based**: Instruct your UI to both draw _and_ bind templates using any data-container with a `[Bind]` attribute. Primitives, objects, collections, one-way, two-way binding, specific control selection: the parts you'll be most frequently developing with in C# are  exposed via attributes
- **State-Based Routing**: Use the GameObject hierarchy dynamically construct your router's states. Its functionality mimics url-based addresses: `index/settings/video`.
- **Template Composition**: Reuse your static assets by writing atomic templates, and dynamically compose them in runtime.

It comes with a **[component-kit][e593c071]** library, **[sample project][05f1d8f6]** several VisualElement extensions and an **[online demo][84ed822d]** to get you started.

  [e593c071]: https://github.com/LudiKha/Graphene-Components "Graphene Components"
  [05f1d8f6]: https://github.com/LudiKha/Graphene-Sample-Project "Graphene-Sample-Project"
  [84ed822d]: https://ludikha.github.io/Graphene-WebGL-Demo/ "Graphene-WebGL-Demo"


## Online Demo
### [Check out the WebGL demo ][f45eaa31]

  [f45eaa31]: https://ludikha.github.io/Graphene-WebGL-Demo/ "Graphene WebGL demo"


## Installation
### Using Unity Package Manager (For Unity 2018.3 or later)

<details>
  <summary>You can install the package via UPM by adding the line below to your project's `Packages/manifest.json` file.</summary>

&nbsp;

  >You can find this file by opening your project's *Packages* folder in a file browser, it is not displayed in the editor.

</details>

```
{
  "dependencies": {
    "com.graphene.core": "https://github.com/LudiKha/Graphene.git?path=/src",
    "com.graphene.components": "https://github.com/LudiKha/Graphene-Components.git?path=/src",
    ...
  },
}
```

>Do note that although both components and demo are optional packages, it is recommended you use them to kickstart your own Graphene-based development environment.

#### Staying updated
Updating the package can be done via `Window/Graphene/Check for updates`. Unity currently does not support updating Git packages via the Package Manager automatically.


### Using UPM Git Extension
The best way to install Graphene and stay up to date with the latest versions, is to use [UPM Git Extension][49fed258].
   1. Follow the [installation instructions][2ddc031d]
   2. In the Package Manager, click the ![Git button](docs/images/installation/git.png) button, and add `https://github.com/LudiKha/Graphene.git` under subdirectory `src`, with the latest version.
   3. Voilá! As an added bonus you are now able to update the package via the package manager.

  [49fed258]: https://github.com/mob-sakai/UpmGitExtension "Upm Git Extension"
  [2ddc031d]: https://github.com/mob-sakai/UpmGitExtension#installation "UP Git Extension Installation Instructions"


&nbsp;

---

&nbsp;

# Quickstart

For a quick start, Graphene comes with a component library and [sample project][52a86b14] - it is **highly** recommended to start your new project using the demo scene and resources provided within this project.

  [52a86b14]: https://github.com/LudiKha/Graphene-Sample-Project "Graphene Sample Project"

#### 1: Constructing the hierarchy
- Construct the high-level UI hierarchy, where each unique state is represented by a GameObject
- Add a [`Plate`][0fb2479e] component to each GameObject in the tree, with a `Graphene` component at the root.
- For each Plate in the tree, assign a static asset to its UIDocument. Root states will typically need a Layout-style [`template`](https://github.com/LudiKha/Graphene#template) for their children to be fitted in.

Press play - Graphene will now dynamically construct the VisualTree based on your GameObject hierarchy. You've completed the required part of Graphene - however, we are still getting started.

Let's draw and bind some data onto our UI.

#### 2: Rendering & binding a model
- Add a [`Theme`][a617f693] to the root Graphene component.
- Add one or more [`Renderer`][b39c255d] components to each `Plate` that has dynamic (instantiated) content
- Assign a [`Model`][19f2ae47] to the Renderer - this is a data container that serves as the model for the data-binding.
- In the type(s) assigned as model, select the members you wish to expose for binding by adding [`BindAttribute`][b3387189]s. Add an additional `DrawAttribute` to dynamically instantiate controls in runtime using [`Templates`][fe269940].

  [a617f693]: https://github.com/LudiKha/Graphene#theming "Theming"

Press play - Graphene will draw templates, and bind them to the model. If a static asset contained a control with a binding-path (e.g. a label with [`Model.Title`][04efb446]), this will be bound to the model too.

  [04efb446]: https://github.com/LudiKha/Graphene#scopes "Scopes"

The hierarchy is created and detail fields are rendered dynamically - now all that remains is to switch states.

#### 3: Routing
- Add a [`StringRouter`][1015cb88] to the root GameObject.
- Add a `StringStateHandle` to each `Plate` GameObject that needs to be activated or deactivated based on states. Children are automatically deactivated with their parents. Give the StateHandle `StateId` unique names (e.g. "start", "load", "exit").
- For each `Plate` that has one or more children using states, select which child state is enabled by default by ticking `enableWithParent`
- In order to navigate, we can instantiate controls with a `RouteAttribute` or statically type them in UXML. Make sure to set the route member to a value that corresponds the available states.


> Note: It is also possible to encapsulate a button within a Route element.
> ```html
><gr:Route route="/settings">
>  <ui:Button text="Clicking me will change state"/>
></gr:Route>
>
><gr:Route binding-path="~Model/ExitState">
>```


Press play - The router constructs its state tree from the `Plate` hierarchy. When clicking a route element (or child button), the router will attempt to change states and the view will display this state change accordingly.

  [0fb2479e]: https://github.com/LudiKha/Graphene#plates "Plates"
  [b39c255d]: https://github.com/LudiKha/Graphene#rendering "Renderer"
  [19f2ae47]: https://github.com/LudiKha/Graphene#model "Model"
  [1015cb88]: https://github.com/LudiKha/Graphene#routing "Router"
  [b3387189]: https://github.com/LudiKha/Graphene#binding "Binding"  
  [fe269940]: https://github.com/LudiKha/Graphene#templating "Templating"

Congrats! You're now done with the Quickstart and ready to tackle your first project using Graphene.

&nbsp;

---

&nbsp;

# Core Concepts

Graphene decouples fine-grained authoring from high-level logic, and in doing so aims to leverage UI Toolkit's innovations to the fullest.

## Plates
A `Plate` represents a view controller in the VisualTree, and is used by Graphene to display the hierarchy, its states and views.

A Graphene hierarchy consists of nested components called `Plates`, with a `Graphene` component at the root. `Plate`s are the core of Graphene, are analogous for a general-purpose UI controller that can be switched on or off. Other, optional MonoBehaviour components may hook into a plate, and have their functionality based on whether a plate is active or not.

The following components and logic depends on plates:
- View

These can be authored in the familiar GameObject hierarchy. Graphene then constructs the VisualElement tree at runtime into a nested view.

## Views
A `View` represents a section of the screen, and is defined as a VisualElement within the `Plate`'s UXML asset. It contains an 'id', which serves as a unique identifier within the plate. Examples of views include a sidebar, a content area, a header or footer.

Views can be used to compose static content (i.e. child Plates composing into parent Views), or to render dynamic content into (i.e. a renderer drawing a list of items into a View).

By default, Graphene components assume these two types of views will be present on a `Plate`:
- **Content View**: A view that is used to render dynamic content into, using a `Renderer` component.
- **Children View**: A view that is used to compose child plates into, based on the GameObject hierarchy.

## Rendering & Binding
Rendering refers to the process of drawing and binding a model to the view. This is done using a `Renderer` component. It requires a `Model` to be assigned, which serves as the data container for the binding.

It consists of two passes:
1. A static binding pass, where elements that are part of the static UXML asset assigned to the `Plate`'s `VisualTreeAsset` are bound to the model.
2. A dynamic rendering and binding pass, where templates are rendered and bound from the model.

A manager class called `Binder` takes care of the binding process and lifecycle management, and supports one-way and two-way binding modes.

## Model
A `Model` is a data container that serves as the model for the data-binding. Any class or struct can be used as a model, as long as it has been decorated with the `[Bind]` attribute on the members you wish to expose for binding.

## Templating
Templating refers to the process of dynamically instantiating static UXML assets at runtime, based on a predetermined type of `Control` (i.e. a button, a toggle, a slider etc). UXML templates are mapped to a `ControlType` enum in a `TemplateAsset`, and DrawAttributes are used to instruct the `Renderer` which templates to instantiate.

### Template
A `Template` is a semantic name for static asset that represents a chunk of UXML of varying granularity and complexity, which are used as building blocks to build and render the application. Moreover, templates can be declared directly in UXML based, and will be rendered at runtime based on the `Renderer` template configuration. Templates are wrapped in a `TemplateAsset` ScriptableObject, where additional variants can be created without needing to create and maintain copies of the base template.

#### Why use templates

When creating a simple element, such as a button, it may quickly end up consisting of several carefully configured elements and bindings:

```html
<ui:Button text="Button" name="ButtonFramed" focusable="true" tooltip="This is a button" binding-path="Value" class="button button-framed light">
  <ui:Style src="ButtonFramed.uss" />
  <gr:Route binding-path="Route" class="button__route" />
  <gr:Tooltip binding-path="Description" class="button__tooltip" />
  <ui:VisualElement class="button__background" />
  <ui:Label text="Label" binding-path="Label" />
  <ui:VisualElement class="button__hover" />
  <ui:VisualElement class="button__frame" />
</ui:Button>
```

Maintaining multiple versions and instances of the same chunk of UXML throughout multiple files can be both error prone and time intensive. Graphene allows you to reuse the same template, and instantiate them at runtime when required.

#### Creating a template

Create a `TemplateAsset` via the following menu command:
>  `Assets/Create/Graphene/Templating/TemplateAsset`

Assign a static UXML template, and give it an appropriate name.

#### Instantiating a template via CSharp
Templates can be instantiated directly in C# via a reference of the `TemplateAsset`.
```csharp
var clone = myTemplateAsset.Instantiate();
...

```
#### Instantiating a template via UXML
 Graphene allows you to statically type control types using the following syntax:

```html
<gr:Button text="Button" name="ButtonFramed" focusable="true" tooltip="This is a button" binding-path="Value" class="button button-framed light" />
```
At runtime, the button will be rendered to the full syntax of the first snippet, using the `Template` configuration of the `Renderer` component that initiates the binding.

## Binding

### Binding Modes
Graphene supports 3 modes of binding a model to the view. These can either be specified in the BindAttribute on the model, or using the Binder API directly.
- **OneTime**: Instructs the `Binder` to only "print" the model once onto the view. No continuous binding will be attempted. Useful for immutable data, such as titles, labels or button callbacks.
>Note: Prefixing the binding-path with the `::` syntax instructs the binder to use a one-time binding.
>```html
><ui:Label binding-path="::Title" />
>```

- **OneWay**: Creates a continuous binding from the model to the view. Updates are polled continuously but only for bindings that are currently visible (based on `Plate` state). Polling rate can be configured in the `Graphene` component.
- **TwoWay**: Creates a two-directional binding (from model to view, and view to model) for controls that support two-way binding. View to model binding is based on `INotifyPropertyChange` callbacks.

### Scopes
- Scope drilldown `.` `Renderer.Model.ChildObject.Title`
- Scope transferral `~` `~Renderer.Model` > `ChildObject.Title`

### Binding Passes
1. Static
2. Dynamic

### Static Binding
Static binding refers to binding elements that are part of the static UXML asset assigned to the `Plate`'s `VisualTreeAsset`. It allows you to bind elements that are always present in the view, such as titles, labels, buttons or other controls that may have a binding-path assigned. 

Common use-cases include binding a title label to `Model.Title`, or binding a button's `Route` to a member in the model.

### Dynamic Binding
Dynamic binding refers to binding elements that have been instantiated dynamically via the `Renderer`'s `Template` configuration, or viewmodel's `Instantiate` method. 

Common use-cases include rendering a list of items from a collection, or rendering detail fields from a complex object, such as a Settings ScriptableObject.

## Routing
Graphene supports url-like state routing via the `Router` component. This allows you to construct a state hierarchy using the GameObject hierarchy, and navigate between states using `Route` elements.

The routing system is inspired by web standards, and mimics url-based addresses: `index/settings/video`. 

## Localization
TBD

## Step-by-step process
1. Static view composition
2. Static binding pass
3. Render templates from dynamic model
4. Dynamic binding pass
5. Runtime one-way/two-way binding


&nbsp;

---

&nbsp;

# Inspector Extensions
Graphene supports two third party inspector extensions out of the box: [Sirenix Odin Inspector][5855fee6] (paid) and [NaughtyAttributes][06602d8c] (free). Graphene relies on these to expose optional enhanced functionality to the inspector windows.

[5855fee6]: https://odininspector.com/ "Sirenix Odin Inspector"
[06602d8c]: https://github.com/dbrizov/NaughtyAttributes "Naughty Attributes"

## Installation
### Odin Inspector
This asset is automatically setup when it is included in the project.
 > Define symbol: `ODIN_INSPECTOR`

### Naughty Attributes
This package requires you to follow the following steps:
1. Add the package to the project `Packages/manifest.json` file:

   >`"com.dbrizov.naughtyattributes": "https://github.com/dbrizov/NaughtyAttributes.git#upm"`
2. In Project Settings/Player/Scripting define symbols, add the following entry: `NAUGHTY_ATTRIBUTES;`

After recompilation, your project will now have enhanced inspector functionality for Graphene components.


================================================
FILE: docs/About.md
================================================
layout: page
title: "About Graphene"
permalink: /about/

![Graphene](images/graphene-logo-full.png)

# Graphene
## UI Framework for unity

## WebGL Demo


================================================
FILE: docs/_config.yml
================================================
theme: jekyll-theme-cayman

================================================
FILE: docs/howto.md
================================================


================================================
FILE: src/Core/Binding/Binder.cs
================================================
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene
{
  using Elements;
  using global::Graphene.ViewModel;
  using Kinstrife.Core.ReflectionHelpers;
  using System.Collections;
  using System.Linq;

  public interface IRoute
  {
  }

  /// <summary>
  /// Utility class to bind bindable data objects to VisualElements, using the <see cref="BindAttribute"/> to match members to <see cref="BindableElement"/>s.
  /// </summary>
  /// <remarks>Common use cases include buttons, labels, toggles, sliders etc. Supports recursive binding and drilling down into sub-scopes defined in UXML.</remarks>
  public static class Binder
  {
	internal static VisualElement InternalInstantiate(VisualTreeAsset template, Plate plate)
	{
	  var clone = template.Instantiate();
	  return clone.Children().First();
	}

	/// <summary>
	/// Binds the tree recursively
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="element"></param>
	/// <param name="context"></param>
	public static VisualElement Instantiate(in object context, VisualTreeAsset template, Plate plate)
	{
	  var clone = InternalInstantiate(template, plate);
	  var t = context.GetType();
	  if (RenderUtils.IsPrimitiveContext(t))
	  {
	  }
	  // Bind class with its own context
	  else
	  {
		if (context is ICustomAddClasses customAddClasses)
		  clone.AddMultipleToClassList(customAddClasses.ClassesToAdd);
		if (context is ICustomName customName && !string.IsNullOrWhiteSpace(customName.CustomName))
		  clone.name = customName.CustomName;

		// Get members
		List<ValueWithAttribute<BindAttribute>> members = new List<ValueWithAttribute<BindAttribute>>();
		TypeInfoCache.GetMemberValuesWithAttribute<BindAttribute>(context, members);
		Binder.BindRecursive(clone, context, members, plate, false);
	  }
	  return clone;
	}

	/// <summary>
	/// Binds the tree recursively
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="element"></param>
	/// <param name="fieldValue"></param>
	public static VisualElement InstantiatePrimitive(in object context, ref ValueWithAttribute<BindAttribute> bindableMember, VisualTreeAsset template, Plate plate)
	{
	  var clone = InternalInstantiate(template, plate);

	  if (bindableMember.Attribute == null)
	  {
		Debug.LogError($"Drawing {template.name} for primitive on {context} without Bind Attribute", template);
		return clone;
	  }

	  // Get members
	  List<ValueWithAttribute<BindAttribute>> members = new List<ValueWithAttribute<BindAttribute>>();
	  members.Add(bindableMember);

	  // Bind without scope drilldown
	  Binder.BindRecursive(clone, context, members, plate, false);

	  return clone;
	}

	/// <summary>
	/// Binds the tree recursively
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="element"></param>
	/// <param name="context"></param>
	public static void BindRecursive(VisualElement element, object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate, bool notFullyDrilledDown)
	{
	  if (members == null)
	  {
		// Get members
		members = new List<ValueWithAttribute<BindAttribute>>();
		TypeInfoCache.GetMemberValuesWithAttribute<BindAttribute>(context, members);
	  }

	  // Is bindable with binding-path in uxml
	  if (element is BindableElement el && !string.IsNullOrWhiteSpace(el.bindingPath))
	  {
		// Should drill down to a child's scope (based on binding-path '.', and scope ovveride '~')
		bool branched = notFullyDrilledDown && TryBranch(el, context, plate);
		if (branched) // Started branch via drilled down scope branch
		  return;

		BindElementValues(el, ref context, members, plate);

		// Context potentially has routing binding (TODO remove interface check)
		if (context is IRoute && plate.Router)
		  plate.Router.BindRouteToContext(el, context);
	  }
	  // Image (not bindable)
	  else if (element is Image image)
	  {
		BindImage(image, ref context, members, plate);
	  }
	  // Rout el special case
	  else if (element is Route route)
	  {
		BindRoute(route, ref context, plate);
	  }

	  BindChildren(element, context, members, plate, notFullyDrilledDown);
	}

	static void BindChildren(VisualElement element, object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate, bool scopeDrillDown)
	{
	  //element.BindValues(data);
	  if (element.childCount == 0)
	  {
		return;
	  }

	  // Loop through children and bind data to them
	  foreach (var child in element.Children())
	  {
		BindRecursive(child, context, members, plate, scopeDrillDown);
	  }
	}

	/// <summary>
	/// Binds values of a particular VisualElement to an IBindable
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="el"></param>
	/// <param name="data"></param>
	private static void BindElementValues<V>(V el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate) where V : BindableElement
	{
	  if (el.binding != null/* || el.userData != null*/)
	  {
		Debug.LogError($"Binding twice! {el}");
		return;
	  }
	  else
	  {
		el.userData = context;
		plate.Graphene.BroadcastBindCallback(el, context, plate);
	  }

	  // Pass in list of properties for possible custom logic spanning multiple properties
	  if (el is Label)
		BindLabel(el as Label, ref context, members, plate);
	  else if (el is Button)
		BindButton(el as Button, ref context, members, plate);
	  else if (el is If)
		BindIf(el as If, ref context, members, plate);
	  else if (el is Image image)
		BindImage(image, ref context, members, plate);
	  else if (el is CycleField)
		BindCycleField(el as CycleField, ref context, members, plate);
	  else if (el is DropdownField)
		BindDropdownField(el as DropdownField, ref context, members, plate);
	  else if (el is ListView)
		BindListView(el as ListView, ref context, members, plate);
	  else if (el is SelectField)
		BindSelectField(el as SelectField, ref context, members, plate);
	  else if (el is Toggle)
		BindBaseField<bool>(el as Toggle, ref context, members, plate);
	  else if (el is Slider)
		BindSlider(el as Slider, ref context, members, plate);
	  else if (el is SliderInt sliderInt)
		BindSlider(sliderInt, ref context, members, plate);
	  else if (el is MinMaxSlider minMax)
		BindMinMaxSlider(minMax, ref context, members, plate);
	  else if (el is AbstractProgressBar progress)
		BindProgress(progress, ref context, members, plate);
	  else if (el is Foldout foldout)
		BindFoldout(foldout, ref context, members, plate);
	  else if (el is ButtonGroup buttonGroup)
		BindButtonGroup(buttonGroup, ref context, members, plate);
	  else if (el is TextField)
		BindTextField(el as TextField, ref context, members, plate);
	  else if (el is TextElement)
		BindTextElement(el as TextElement, ref context, members, plate);
	}

	private static void BindTextElement(TextElement el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  foreach (var item in members)
	  {
		if (BindingPathOrTypeMatch<string>(el, in item))
		{
		  BindText(el, ref context, in item, plate);
		  break;
		}
	  }
	}
	private static void BindLabel(Label el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  foreach (var item in members)
	  {
		if (BindingPathOrTypeMatch<string>(el, in item))
		{
		  BindText(el, ref context, in item, plate);
		  break;
		}
	  }
	}


	private static void BindButton(Button el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  foreach (var item in members)
	  {
		if (BindingPathAndTypeMatch<BindableObject>(el, in item))
		{
		  //Debug.Log($"Binding BindableObject click {el.bindingPath} {context}", context as UnityEngine.Object);

		  //var data = item.Value as BindableObject;
		  BindRecursive(el, item.Value, null, plate, false);
		  var bindable = (BindableObject)item.Value;
		  el.tooltip = bindable.Tooltip;
		  BindCallbacks(el, context);
		  //Debug.Log(bindable);
		  break;
		}
		else if (BindingPathAndTypeMatch<ActionButton>(el, in item))
		{
		  //Debug.Log($"Binding ActionButton click {el.bindingPath} {context}", context as UnityEngine.Object);
		  BindRecursive(el, item.Value, null, plate, false);
		  el.tooltip = ((ActionButton)item.Value).Tooltip;
		  break;
		}
		else if (BindingPathAndTypeMatch<string>(el, in item))
		{
		  //Debug.Log($"Binding string click {el.bindingPath} {item.Value} {context}", context as UnityEngine.Object);
		  BindText(el, ref context, in item, plate);
		  //break;
		}
		else if (BindingPathOrTypeMatch<Action>(el, in item))
		{
		  //Debug.Log($"Binding click {el.GetType().Name} {el.bindingPath} ({item.MemberInfo.Name} {item.Type.Name} in {context})", context as UnityEngine.Object);
		  BindClick(el, (Action)item.Value, context, plate);
		  break;
		}
		else if (BindingPathOrTypeMatch<UnityEngine.Events.UnityEvent>(el, in item))
		{
		  //Debug.Log($"Binding UnityEvent click {el.GetType().Name} {el.bindingPath} ({item.MemberInfo.Name} {item.Type.Name} in {context})", context as UnityEngine.Object);
		  BindClick(el, (UnityEngine.Events.UnityEvent)item.Value, context, plate);
		  break;
		}
	  }
	}

	internal static void BindRoute(Route el, ref object context, Plate plate)
	{
	  // Check if parent is a button -> propagate click
	  if (el.parent is Button button)
	  {
		BindClick(button, el.clicked, context, plate);
	  }
	  else
	  {
		foreach (var item in el.Children())
		{
		  if (item is Button btn)
		  {
			BindClick(btn, el.clicked, context, plate);
		  }
		  else if (item is ButtonGroup btnGroup)
		  {
			btnGroup.clicked += (int index, string route) => { el.route = route; el.clicked?.Invoke(); }; // A bit hacky perhaps
		  }
		}
	  }

	  el.SetRouter(plate.Router);

	  // Let the (generic) router handle the way it binds routes
	  plate.Router.BindRoute(el, context);
	}

	private static void BindSlider(Slider el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  el.Q("unity-dragger").pickingMode = PickingMode.Ignore;

	  // Slider specifics
	  foreach (var item in members)
	  {
		// Primary
		if (BindingPathOrTypeMatch<float>(el, in item))
		{
		  if (item.Attribute is BindFloatAttribute floatAttribute)
		  {
			el.value = floatAttribute.startingValue;
			el.lowValue = floatAttribute.lowValue;
			el.highValue = floatAttribute.highValue;
			el.showInputField = floatAttribute.showInputField;
			break;
		  }
		}
		else if (BindingPathAndTypeMatch<float>("Min", item))
		  el.lowValue = (float)item.Value;
		else if (BindingPathAndTypeMatch<float>("Max", item))
		  el.highValue = (float)item.Value;
	  }

	  // Bind base field value & callback
	  BindBaseField(el, ref context, members, plate);
	}

	private static void BindSlider(SliderInt el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  el.Q("unity-dragger").pickingMode = PickingMode.Ignore;

	  // Slider specifics
	  foreach (var item in members)
	  {
		// Primary
		if (BindingPathOrTypeMatch<int>(el, item))
		{
		  if (item.Attribute is BindIntAttribute att)
		  {
			el.value = att.startingValue;
			el.lowValue = att.lowValue;
			el.highValue = att.highValue;
			el.showInputField = att.showInputField;
			break;
		  }
		}
		else if (BindingPathAndTypeMatch<int>("Min", item))
		  el.lowValue = (int)item.Value;
		else if (BindingPathAndTypeMatch<int>("Max", item))
		  el.highValue = (int)item.Value;
	  }

	  //el./*showMixedValue*/ = true;
	  //el.showInputField = true;

	  // Bind base field value & callback
	  BindBaseField(el, ref context, members, plate);
	}

	private static void BindMinMaxSlider(MinMaxSlider el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  el.Q("unity-dragger").pickingMode = PickingMode.Ignore;
	  // Slider specifics
	  foreach (var item in members)
	  {
		// Primary
		if (BindingPathOrTypeMatch<Vector2>(el, in item))
		{
		  if (item.Attribute is BindRangeAttribute floatAttribute)
		  {
			el.value = floatAttribute.startingValue;
			el.lowLimit = floatAttribute.lowLimit;
			el.highLimit = floatAttribute.highLimit;
			break;
		  }
		}
		else if (BindingPathAndTypeMatch<float>("Min", item))
		  el.lowLimit = (float)item.Value;
		else if (BindingPathAndTypeMatch<float>("Max", item))
		  el.highLimit = (float)item.Value;
	  }

	  // Bind base field value & callback
	  BindBaseField(el, ref context, members, plate);
	}

	private static void BindProgress(AbstractProgressBar el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  // Progress Bar specifics
	  foreach (var item in members)
	  {
		// Primary
		if (BindingPathOrTypeMatch<float>(el, item))
		{
		  if (item.Attribute is BindFloatAttribute att)
		  {
			el.value = att.startingValue;
			el.lowValue = att.lowValue;
			el.highValue = att.highValue;
			break;
		  }
		}
		else if (BindingPathAndTypeMatch<float>("Min", item))
		  el.lowValue = (float)item.Value;
		else if (BindingPathAndTypeMatch<float>("Max", item))
		  el.highValue = (float)item.Value;
	  }
	  var results = BindNotifyValueChange<AbstractProgressBar, float>(el, ref context, members, plate);
	  el.value = results.value;
	  el.title = results.label;
	}

	private static void BindTextField(TextField el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  foreach (var item in members)
	  {
		// Primary
		if (BindingPathOrTypeMatch<string>(el, in item))
		{
		  if (item.Attribute is BindStringAttribute stringAttribute)
		  {
			el.value = stringAttribute.startingValue;
			el.isPasswordField = stringAttribute.password;
			el.isReadOnly = stringAttribute.readOnly;
			el.multiline = stringAttribute.multiLine;

			if (stringAttribute.maxLength >= 0)
			  el.maxLength = stringAttribute.maxLength;
			break;
		  }
		}
	  }

	  BindBaseField(el, ref context, members, plate);
	}

	private static (TValueType value, string label) BindNotifyValueChange<TElementType, TValueType>(TElementType el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate) where TElementType : BindableElement, INotifyValueChanged<TValueType>
	{
	  bool labelFromAttribute = false;
	  string label = null;
	  foreach (var item in members)
	  {
		// Primary (value)
		if (BindingPathOrTypeMatch<TValueType>(el, in item))
		{
		  if (item.Value is TValueType value)
		  {
			el.SetValueWithoutNotify(value);
			plate.BindingsManager.TryCreate<TValueType>(el, in context, in item, plate);
		  }
		  else if (item.Value is BindableBaseField<TValueType> baseField)
		  {
			el.SetValueWithoutNotify(baseField.value);
			if (!string.IsNullOrWhiteSpace(baseField.Label))
			  label = baseField.Label;
			plate.BindingsManager.TryCreate<TValueType>(el, in item.Value, in item, plate);
		  }

		  // Set label from attribute
		  if (item.Attribute is BindBaseFieldAttribute att)
		  {
			if (!string.IsNullOrWhiteSpace(att.label))
			{
			  //el.text = att.label;
			  labelFromAttribute = true;
			  label = att.label;
			}
		  }
		}
		// Set register callback event
		else if (item.Attribute is BindValueChangeCallbackAttribute callbackAttribute)
		{
		  var target = item.Value as EventCallback<ChangeEvent<TValueType>>;
#if UNITY_ASSERTIONS
		  UnityEngine.Assertions.Assert.IsNotNull(target, "Bindable item Invalid callback - ValueType mismatch.");
#endif
		  el.RegisterValueChangedCallback(target);
		}
		// Set label from field, if not from attribute
		else if (!labelFromAttribute && item.Attribute.Path == "Label" && item.Value is string labelText)
		  label = labelText;
		//BindText(el.labelElement, ref context, labelText, in item, plate);
		else if (item.Attribute is BindTooltip)
		  el.tooltip = ObjectToString(item.Value, item.Type);
	  }

	  // Returning value & label tuple because each element implements text differently. (E.g. Foldout vs. Basefield)
	  return (el.value, label);
	}

	private static void BindBaseField<TValueType>(BaseField<TValueType> el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  var results = BindNotifyValueChange<BaseField<TValueType>, TValueType>(el, ref context, members, plate);
	  el.label = results.label;
	}

	private static void BindDropdownField(DropdownField el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  // Then bind the items
	  foreach (var item in members)
	  {
		// Model items
		if (BindingPathMatch(item.Attribute.Path, SelectField.itemsPath))
		{
		  el.choices = item.Value as List<string>;
		  break;
		}
		else if (item.Type.IsEnum) // Primitive -> Can only do two way
		{
		  el.choices = Enum.GetNames(item.Type).ToList();
		  el.SetValueWithoutNotify(ObjectToString(item.Value, item.Type) ?? el.value);

		  var t = item.Type;
		  var memberName = item.MemberInfo.Name;
		  var accessor = TypeInfoCache.GetExtendedTypeInfo(context.GetType()).Accessor;
		  var ctx = context;

		  // Filthy hax
		  el.RegisterValueChangedCallback<string>((evt) =>
		  {
			var val = Enum.Parse(t, evt.newValue);
			accessor[ctx, memberName] = val;
		  });
		}
	  }

	  // First bind base field (string)
	  BindBaseField(el, ref context, members, plate);
	}

	private static void BindSelectField(SelectField el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  // Then bind the items
	  foreach (var item in members)
	  {
		// Model items
		if (BindingPathMatch(item.Attribute.Path, SelectField.itemsPath))
		{
		  el.items = item.Value as List<string>;
		  break;
		}
	  }

	  // First bind base field (int)
	  BindBaseField(el, ref context, members, plate);
	}

	private static void BindListView(ListView el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  foreach (var bindMember in members)
	  {
		// Primary
		if (BindingPathMatch(bindMember.Attribute.Path, el.bindingPath))
		{
		  ControlType controlType = ControlType.ListItem;
		  if (context is IListViewBindable listViewBindable)
		  {
			controlType = listViewBindable.ItemControlType;
		  }

		  IList list = bindMember.Value as IList;

		  RenderUtils.templatesDefault.TryGetTemplateAsset(controlType, out VisualTreeAsset template);
		  InternalBindListView(el, in context, list, template, plate);

		  plate.BindingsManager.TryCreate<IList>(el, in context, in bindMember, plate);
		  break;
		}
	  }

	  // Fallback
	  if (context is IListViewBindable listViewBindable2)
	  {
		RenderUtils.templatesDefault.TryGetTemplateAsset(listViewBindable2.ItemControlType, out VisualTreeAsset template);
		InternalBindListView(el, in context, listViewBindable2.ItemsSource, template, plate);
	  }
	}

	internal static void BindListView(ListView el, in object context, Plate plate, VisualTreeAsset templateAsset, in ValueWithAttribute<BindAttribute> member)
	{
	  IList list = member.Value as IList;
	  InternalBindListView(el, in context, list, templateAsset, plate);
	  plate.BindingsManager.TryCreate<IList>(el, in context, in member, plate);
	}


	internal static void InternalBindListView(ListView el, in object context, IList itemsSource, VisualTreeAsset templateAsset, Plate plate)
	{
	  bool elementsPickable = true;

	  if (context is IListViewBindable bindable)
	  {
		bindable.Apply(el);
		BindCallbacks(el, context);
		elementsPickable = bindable.ElementsPickable;
	  }

	  Func<VisualElement> makeItem = () =>
	  {
		var e = InternalInstantiate(templateAsset, plate);
		e.pickingMode = elementsPickable ? PickingMode.Position : PickingMode.Ignore;
		return e;
	  };
	  Action<VisualElement, int> bindItem = (e, i) =>
	  {
		var src = itemsSource[i];
		e.userData = src;
		Binder.BindRecursive(e, src, null, plate, false);
		if (!(e is BindableElement))
		{
		  BindCallbacks(e, src);
		}
	  };

	  el.makeItem = makeItem;
	  el.bindItem = bindItem;
	  el.itemsSource = itemsSource;
	}

	private static void BindCycleField(CycleField el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  // Then bind the items
	  foreach (var item in members)
	  {
		// Model items
		if (BindingPathMatch(item.Attribute.Path, CycleField.itemsPath))
		{
		  el.items = item.Value as List<string>;
		  break;
		}
	  }

	  // First bind base field (int)
	  BindBaseField(el, ref context, members, plate);
	}

	private static void BindIf(If el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  // Then bind the items
	  foreach (var item in members)
	  {
		// Model items
		if (BindingPathMatch(el, in item))
		{
		  plate.BindingsManager.TryCreate<object>(el, in context, in item, plate); // This shows/hides the bindable
		  el.OnModelChange(item.Value);
		  return;
		}
	  }
	}

	private static void BindImage(Image el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  // Then bind the items
	  foreach (var item in members)
	  {
		// Model items
		if (BindingPathOrTypeMatch<Texture>("Image", item))
		{
		  el.image = item.Value as Texture;
		  if (item.Attribute.hideIfEmpty)
			el.SetShowHide(el.image != null);
		  return;
		}
		else if (BindingPathOrTypeMatch<Sprite>("Image", item))
		{
		  el.sprite = item.Value as Sprite;
		  if (item.Attribute.hideIfEmpty)
			el.SetShowHide(el.sprite != null);
		  return;
		}
	  }
	}

	private static void BindFoldout(Foldout el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  foreach (var member in members)
	  {
		if (BindingPathMatch(el, in member) && member.Value is BindableBaseField baseField)
		{
		  BindRecursive(el, baseField, null, plate, false);
		  return;
		}
	  }

	  if (context is BindableBaseField<bool> baseFieldContext)
	  {
		el.SetValueWithoutNotify(baseFieldContext.value);
		if (!string.IsNullOrWhiteSpace(baseFieldContext.Label))
		  el.text = baseFieldContext.Label;
	  }

	  foreach (var member in members)
	  {
		if (member.Value is bool)
		  plate.BindingsManager.TryCreate<bool>(el, in context, in member, plate);
		else if (member.Value is string)
		  plate.BindingsManager.TryCreate<string>(el, in context, in member, plate);
	  }

	  //var results = BindNotifyValueChange<Foldout, bool>(el, ref context, members, plate);
	}

	private static void BindButtonGroup(ButtonGroup el, ref object context, List<ValueWithAttribute<BindAttribute>> members, Plate plate)
	{
	  // Then bind the items
	  foreach (var item in members)
	  {
		// Model items
		if (BindingPathAndTypeMatch<ICollection<string>>(el, item))
		{
		  el.items = item.Value as List<string>;
		  break;
		}
		else if (BindingPathAndTypeMatch<ICollection<ActionButton>>(el, item))
		{
		  el.items.Clear();
		  var items = item.Value as List<ActionButton>;
		  if (items == null || items.Count == 0)
			continue;

		  el.ClearItems();
		  foreach (var action in items)
			el.AddItem(action.Label, action.Tooltip);

		  el.SourceData = items;

		  //el.ClearCallback();
		  //el.clicked += (int i, string name) => items[i].OnClick?.Invoke();
		  break;
		}
	  }
	}

	private static void BindText(TextElement el, ref object context, in ValueWithAttribute<BindAttribute> member, Plate plate)
	{
	  // Add translation here
	  el.text = ObjectToString(in member.Value, member.Type);

	  plate.BindingsManager.TryCreate(el, ref context, in member, plate);
	}

	private static void BindClick(Button el, System.Action action, in object context, Plate plate)
	{
	  el.clicked += action;
	  BindCallbacks(el, context);
	}

	private static void BindClick(Button el, UnityEngine.Events.UnityEvent unityEvent, in object context, Plate plate)
	{
	  el.clicked += delegate { unityEvent?.Invoke(); };
	  BindCallbacks(el, context);
	}

	[System.Obsolete("Use IBindableToVisualElement and apply in bindable object")]
	static void BindCallbacks(VisualElement el, in object context)
	{
	  if (context is IHasTooltip tooltip)
	  {
		el.tooltip = tooltip.Tooltip;
		if (context is IBindableToVisualElement bindable)
		{
		  el.SetEnabled(bindable.isEnabled);
		  el.SetActive(bindable.isActive2);
		  el.SetShowHide(bindable.isShown);
		  bindable.SetBinding(el);


		  bindable.onSetEnabled += el.SetEnabled;
		  bindable.onShowHide += el.SetShowHide;
		  bindable.onSetActive += el.SetActive;
		  //Debug.Log($"On bind element {el} to context <b>{context}</b> ");
		}
	  }
	}

	public static string[] stringSplitOptions = new string[] { ".", "~", "::", "_" };

	public const char nestedScopeChar = '.';
	public const char relativeScopeChar = '_';
	public const string oneTimeBindingChar = "::";

	private static bool TryBranch(BindableElement el, object data, Plate owner)
	{
	  var scopes = el.bindingPath.Split(nestedScopeChar);
	  if (scopes.Length == 1)
		return false;

	  // Create sub scope '~'
	  bool createSubScope = false;
	  string bindingPath = el.bindingPath;
	  if (el.bindingPath.IndexOf(relativeScopeChar) == 0)
	  {
		createSubScope = true;
		bindingPath = bindingPath.Remove(0, 1);
	  }

	  return DrillDownToChildScopeRecursive(el, data, owner, bindingPath, createSubScope);
	}


	private static bool DrillDownToChildScopeRecursive(BindableElement el, object data, Plate owner, string currentScope, bool createSubScope)
	{
	  if (data == null)
	  {
		Debug.LogError($"Data was null for scope {currentScope} {owner}", owner);
		return false;
	  }

	  //Debug.Log($"Drilling down to child scope {currentScope} {data} ({el})", data as UnityEngine.Object);

	  // Get binding members info
	  List<ValueWithAttribute<BindAttribute>> members = new List<ValueWithAttribute<BindAttribute>>();
	  TypeInfoCache.GetMemberValuesWithAttribute<BindAttribute>(data, members);
	  // Context doesn't have any bindable members
	  if (members.Count == 0)
		return false;

	  // Split it & remove '~' and '::'
	  var scopes = currentScope.Split(stringSplitOptions, StringSplitOptions.RemoveEmptyEntries);
	  // We're at the leaf scope - bind
	  if (scopes.Length == 1)
	  {
		// Override the element's path now we found the scope
		el.bindingPath = currentScope;

		// Start a new binding branch here and terminate the one we came from
		if (createSubScope)
		{
		  BindRecursive(el, data, members, owner, createSubScope);
		  return true;
		}
		// Only bind the element values, and carry on with the child binding as usual
		else
		{
		  BindElementValues(el, ref data, members, owner);
		  return false;
		}
	  }

	  // Select the topmost scope
	  string targetScope = scopes[0];

	  ValueWithAttribute<BindAttribute>[] matchingMembers = members.Where(x => x.Attribute.Path?.ToLower() == targetScope?.ToLower()).ToArray();
	  // Might need/want to throw an error here
	  if (matchingMembers.Length == 0)
		return false;

	  bool startedBranch = false;
	  string newPath = currentScope.Substring(currentScope.IndexOf(nestedScopeChar) + 1);
	  foreach (var member in matchingMembers)
	  {
		if (DrillDownToChildScopeRecursive(el, member.Value, owner, newPath, createSubScope))
		  startedBranch = true;
	  }
	  return startedBranch;
	}

	#region Internals
	internal static bool BindingPathMatch(in string a, in string b)
	{
	  return string.CompareOrdinal(a, b) == 0;
	}
	internal static bool BindingPathMatch(BindableElement el, in ValueWithAttribute<BindAttribute> member)
	{
	  return string.CompareOrdinal(el.bindingPath, member.Attribute.Path) == 0;
	}
	internal static bool BindingPathOrTypeMatch<T>(BindableElement el, in ValueWithAttribute<BindAttribute> member)
	{
	  return string.CompareOrdinal(el.bindingPath, member.Attribute.Path) == 0 || (string.IsNullOrEmpty(member.Attribute.Path) && typeof(T).IsAssignableFrom(member.Type));
	}
	internal static bool BindingPathOrTypeMatch<T>(in string path, in ValueWithAttribute<BindAttribute> member)
	{
	  return string.CompareOrdinal(path, member.Attribute.Path) == 0 || (string.IsNullOrEmpty(member.Attribute.Path) && typeof(T).IsAssignableFrom(member.Type));
	}
	internal static bool BindingPathAndTypeMatch<T>(in BindableElement el, in ValueWithAttribute<BindAttribute> member)
	{
	  return string.CompareOrdinal(el.bindingPath, member.Attribute.Path) == 0 && typeof(T).IsAssignableFrom(member.Type);
	}
	internal static bool BindingPathAndTypeMatch<T>(in string a, in ValueWithAttribute<BindAttribute> member)
	{
	  return string.CompareOrdinal(a, member.Attribute.Path) == 0 && typeof(T).IsAssignableFrom(member.Type);
	}
	internal static string ObjectToString(in object obj, in Type t)
	{
	  // Add translation here
	  if (obj is string str)
		return str;
	  else if (t.IsEnum)
		return Enum.GetName(t, obj);
	  else if (obj != null)
		return obj.ToString();

	  return default;
	}
	#endregion
  }
}

================================================
FILE: src/Core/Binding/Binder.cs.meta
================================================
fileFormatVersion: 2
guid: f25cd91944aa2e546b1708c66852751c
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Binding/Binding.cs
================================================


using System;
using System.ComponentModel;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene
{
  using Elements;
  using Kinstrife.Core.ReflectionHelpers;

  /// <summary>
  /// Base class for runtime Bindings between a context object and a VisualElement
  /// </summary>
  public abstract class Binding : IDisposable, IBinding
  {
	public bool scheduleDispose;
	public virtual void Dispose()
	{
	}

	public abstract void PreUpdate();

	public abstract void Release();

	public abstract void Update();
  }
  public abstract class Binding<T> : Binding
  {
	protected object context;
	[SerializeField] protected T lastValue;
	[SerializeField] protected T newValue;

	protected BindableElement element;
	[SerializeField] BindAttribute attribute;

	// The target field
	protected string memberName;
	protected ExtendedTypeInfo extendedTypeInfo;

	public Binding(BindableElement el, in object context, in ValueWithAttribute<BindAttribute> member)
	{
	  this.element = el;
	  this.context = context;
	  this.extendedTypeInfo = TypeInfoCache.GetExtendedTypeInfo(context.GetType()); // K: 28-10-2020 -> Could be optimized with member.MemberInfo.DeclaringType;

	  this.attribute = member.Attribute;
	  this.memberName = member.MemberInfo.Name;

	  //el.binding = this;

	  DetermineBindingMode();
	  RegisterEvents();
	}

	void DetermineBindingMode()
	{
	  if (context is INotifyPropertyChanged notifyPropertyChanged)
	  {
		notifyPropertyChanged.PropertyChanged += Model_PropertyChanged;
	  }
	  // Specifically set to not have two-way binding
	  if (attribute.bindingMode.HasValue)
	  {
		if (attribute.bindingMode == BindingMode.TwoWay)
		  RegisterTwoWayValueChangeCallback();
	  }
	  // No value set - Determine based on control type
	  else
	  {
		// Can't two-way bind a label
		if (this.element is Label || element is If)
		  return;
		else if (this.element is INotifyValueChanged<T>)
		  RegisterTwoWayValueChangeCallback();
	  }
	}

	void RegisterEvents()
	{
	  if (context is IHasTooltip hasTooltip)
	  {
		element.tooltip = hasTooltip.Tooltip;
		if (element is BaseField<T> baseField)
		  baseField.labelElement.tooltip = hasTooltip.Tooltip;

		if (context is IBindableToVisualElement bindable)
		{
		  element.SetEnabled(bindable.isEnabled);
		  element.SetActive(bindable.isActive2);
		  element.SetShowHide(bindable.isShown);
		  bindable.SetBinding(element);


		  bindable.onSetEnabled += element.SetEnabled;
		  bindable.onShowHide += element.SetShowHide;
		  bindable.onSetActive += element.SetActive;

		  element.RegisterCallback<DetachFromPanelEvent>(OnDetach);
		}
	  }
	}

	void OnDetach(DetachFromPanelEvent evt) => UnregisterEvents();

	void UnregisterEvents()
	{
	  if (context is IBindableToVisualElement bindable)
	  {
		bindable.onSetEnabled -= element.SetEnabled;
		bindable.onShowHide -= element.SetShowHide;
		bindable.onSetActive -= element.SetActive;
	  }
	}

	void SyncVisualElementToModel()
	{

	}

	protected virtual void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
	{
	}

	public override void Dispose()
	{
	  base.Dispose();
	  UnregisterEvents();
	}
	public override void PreUpdate()
	{
	  throw new NotImplementedException();
	}

	public override void Release()
	{
	  throw new NotImplementedException();
	}

	public override void Update()
	{
	  // Needs to be disposed because the context ceased to exist
	  if (context == null || !IsValidBinding())
	  {
		scheduleDispose = true;
		return;
	  }

	  newValue = GetValueFromMemberInfo();

	  UpdateFromModel(in newValue);
	}

	protected virtual void UpdateFromModel(in T newValue)
	{
	  // Model changed -> Update view
	  if (this.lastValue != null && !this.lastValue.Equals(newValue))
	  {
		if (newValue is T && element is INotifyValueChanged<T> notifyValueChanged)
		  notifyValueChanged.SetValueWithoutNotify(newValue);
		else if (newValue is string text && element is TextElement textEl)
		  textEl.text = text;
		else if (newValue is string foldoutText && element is Foldout foldout)
		  foldout.text = foldoutText;
		else if (element is IBindableElement<object> bindableEl)
		  bindableEl.OnModelChange(newValue);
		else
		  Debug.LogError($"No binding found for {element?.bindingPath} {context}", context as UnityEngine.Object);
	  }

	  lastValue = newValue;
	}

	void RegisterTwoWayValueChangeCallback()
	{
	  if (element is INotifyValueChanged<T> notifyValChangedEl)
	  {
		notifyValChangedEl.RegisterValueChangedCallback((evt) =>
		{
		  if (context is INotifyValueChanged<T> ctx)
			ctx.value = notifyValChangedEl.value;
		  else
			SetValueFromMemberInfo(evt.newValue);
		});
	  }
	}

	protected abstract bool IsValidBinding();
	protected abstract T GetValueFromMemberInfo();
	protected abstract void SetValueFromMemberInfo(T value);

  }
}

================================================
FILE: src/Core/Binding/Binding.cs.meta
================================================
fileFormatVersion: 2
guid: 4c859ae80f4d89648b8c3b6dc1839149
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Binding/BindingAttribute.cs
================================================
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;

namespace Graphene
{
  public class UIAttribute : System.Attribute
  {

  }

  public enum BindingMode
  {
    /// <summary>
    /// For immutable data. Use this for things like menu (buttons/labels) and static text.
    /// </summary>
    OneTime,
    /// <summary>
    /// For dynamic data. Use this for mutable data that isn't changable via UI.
    /// </summary>
    OneWay,
    /// <summary>
    /// For dynamic data which is changable through the UI.
    /// </summary>
    TwoWay
  }

  [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property)]
  public class BindAttribute : UIAttribute
  {
    string path = ""; public string Path => path;
    /// <summary>
    /// The binding mode for this binding. When left null, the system will pick a binding mode based on the control type (recommended).
    /// </summary>
    public BindingMode? bindingMode = null; // By default don't override binding mode

    public bool hideIfEmpty;

    public BindAttribute()
    {
    }

    public BindAttribute(string path)
    {
      this.path = path;
    }
    public BindAttribute(BindingMode bindingMode)
    {
      this.bindingMode = bindingMode;
    }
    public BindAttribute(string path, BindingMode bindingMode)
    {
      this.path = path;
      this.bindingMode = bindingMode;
	}
	public BindAttribute(string path, BindingMode bindingMode, bool hideIfEmpty)
	{
	  this.path = path;
	  this.bindingMode = bindingMode;
      this.hideIfEmpty = hideIfEmpty;
	}
  }

  [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property)]
  public class BindBaseFieldAttribute : BindAttribute
  {
    public string label;
    public bool showInputField;

    public BindBaseFieldAttribute(string path, string label = null, bool showInput = false) : base(path)
    {
      this.label = label;
      this.showInputField = showInput;
    }

    public BindBaseFieldAttribute(string path, BindingMode bindingMode, string label = null, bool showInput = false) : base(path, bindingMode)
    {
      this.label = label;
      this.showInputField = showInput;
    }
  }

  // For fields & properties
  [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property)]
  public class BindFloatAttribute : BindBaseFieldAttribute
  {
    public float startingValue;
    public float lowValue;
    public float highValue;

    public BindFloatAttribute(string path, float startingValue, float min, float max, string label = null, bool showInput = false) : base(path, label, showInput)
    {
      this.startingValue = startingValue;
      this.lowValue = min;
      this.highValue = max;
    }
    public BindFloatAttribute(string path, BindingMode bindingMode, float startingValue, float min, float max, string label = null, bool showInput = false) : base(path, bindingMode, label, showInput)
    {
      this.startingValue = startingValue;
      this.lowValue = min;
      this.highValue = max;
    }
  }


  // For fields & properties
  [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property)]
  public class BindIntAttribute : BindBaseFieldAttribute
  {
    public int startingValue;
    public int lowValue;
    public int highValue;

    public BindIntAttribute(string path, int startingValue, int min, int max, string label = null, bool showInput = false) : base(path, label, showInput)
    {
      this.startingValue = startingValue;
      this.lowValue = min;
      this.highValue = max;
    }
    public BindIntAttribute(string path, BindingMode bindingMode, int startingValue, int min, int max, string label = null, bool showInput = false) : base(path, bindingMode, label, showInput)
    {
      this.startingValue = startingValue;
      this.lowValue = min;
      this.highValue = max;
    }
  }
  // For fields & properties
  [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property)]
  public class BindRangeAttribute : BindBaseFieldAttribute
  {
	public Vector2 startingValue;
	public float lowLimit;
	public float highLimit;

	public BindRangeAttribute(string path, Vector2 startingValue, float min, float max, string label = null) : base(path, label, showInput:false)
	{
	  this.startingValue = startingValue;
	  this.lowLimit = min;
	  this.highLimit = max;
	}
	public BindRangeAttribute(string path, BindingMode bindingMode, Vector2 startingValue, float min, float max, string label = null) : base(path, bindingMode, label, showInput: false)
	{
	  this.startingValue = startingValue;
	  this.lowLimit = min;
	  this.highLimit = max;
	}
  }

  // For fields & properties
  [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property)]
  public class BindStringAttribute : BindBaseFieldAttribute
  {
    public readonly string startingValue;
    public readonly int maxLength;
    public readonly bool readOnly;
    public readonly bool multiLine;
    public readonly bool password;

    public BindStringAttribute(string path, string startingValue, int maxLength = -1, bool readOnly = false, bool multiLine = false, bool password = false, string label = null, bool showInput = false) : base(path, label, showInput)
    {
      this.startingValue = startingValue;
      this.maxLength = maxLength;
      this.readOnly = readOnly;
      this.multiLine = multiLine;
    }
    public BindStringAttribute(string path, BindingMode bindingMode, string startingValue, int maxLength = -1, bool readOnly = false, bool multiLine = false, bool password = false, string label = null, bool showInput = false) : base(path, bindingMode, label, showInput)
    {
      this.startingValue = startingValue;
      this.maxLength = maxLength;
      this.readOnly = readOnly;
      this.multiLine = multiLine;
    }
  }

  [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property)]
  public class BindTooltip : BindAttribute
  {
    public BindTooltip(string path) : base(path)
    {
    }
  }

  [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property)]
  public class BindValueChangeCallbackAttribute : BindAttribute
  {
    public BindValueChangeCallbackAttribute(string path) : base(path)
    {
    }
  }


  /// <summary>
  /// Marks a field or property to be drawn when an entire type is marked for rendering
  /// </summary>
  [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property | System.AttributeTargets.Class)]
  public class DrawAttribute : System.Attribute
  {
    public ControlType controlType = ControlType.None;

    public int order;

    //public DrawAttribute(ControlType controlType)
    //{
    //  this.controlType = controlType;
    //}

    public DrawAttribute([CallerLineNumber]int order = 0)
    {
      this.order = order;
    }

    public DrawAttribute(ControlType controlType, [CallerLineNumber] int order = 0)
    {
      this.controlType = controlType;
      this.order = order;
    }
  }

  public enum Typography
  {
    None,
    h1,
    h2,
    h3,
    h4,
    h5,
    h6,
    subtitle1,
    subtitle2,
    body1,
    body2,
    caption,
    overline
  }

  /// <summary>
  /// Marks a field or property to be drawn when an entire type is marked for rendering
  /// </summary>
  [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property | System.AttributeTargets.Class)]
  public class DrawTextAttribute : DrawAttribute
  {
    public Typography typography = Typography.None;

    public DrawTextAttribute([CallerLineNumber] int order = 0) : base(order)
    {
      this.order = order;
    }

    public DrawTextAttribute(Typography typography, [CallerLineNumber] int order = 0) : base(ControlType.Label, order)
    {
      this.typography = typography;
    }
  }

  [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property)]
  public class RouteAttribute : UIAttribute
  {
    public RouteAttribute()
    {
    }
  }
}

================================================
FILE: src/Core/Binding/BindingAttribute.cs.meta
================================================
fileFormatVersion: 2
guid: 1f614598db3d14645979fed59a3b5945
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Binding/BindingsManager.cs
================================================


using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine.UIElements;

namespace Graphene
{
  using global::Graphene.Elements;
  using Kinstrife.Core.ReflectionHelpers;
  using UnityEngine;
  using UnityEngine.Profiling;

  /// <summary>
  /// Manages the creation, updating, and disposal of bindings between UI elements and data contexts.
  /// </summary>
  public class BindingsManager : GrapheneComponent
  {
	#region ShowInInspectorAttribute
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ShowInInspector]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.ShowInInspector]
#endif
	#endregion
	/// <summary>
	/// Mapping of all current bindings, keyed by panels
	/// </summary>
	Dictionary<Plate, List<Binding>> bindings = new Dictionary<Plate, List<Binding>>();

	#region ShowInInspectorAttribute
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ShowInInspector]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.ShowInInspector]
#endif
	#endregion
	Dictionary<Plate, List<Binding>> disposePostUpdate = new Dictionary<Plate, List<Binding>>();
    Dictionary<Plate, List<Binding>> createPostUpdate = new Dictionary<Plate, List<Binding>>();

    internal uint bindingsCount;


#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.InfoBox("$bindingsInfo")]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.InfoBox("bindingsInfo")]
#endif
	[SerializeField] float bindingRefreshRate = 0.2f;


#if UNITY_EDITOR
	public string bindingsInfo => $"{bindingsCount} bindings";
#endif

	#region ReadOnlyAttribute
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ReadOnly, Sirenix.OdinInspector.ShowInInspector]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.ReadOnly, NaughtyAttributes.ShowInInspector]
#endif
	#endregion
	float lastRefreshTime;

	//#if UNITY_EDITOR
	//    [UnityEditor.InitializeOnEnterPlayMode]
	//    public static void InitializeOnEnterPlayMode()
	//    {
	//      bindings = new Dictionary<Plate, List<Binding>>();
	//      disposePostUpdate = new Dictionary<Plate, List<Binding>>();
	//      createPostUpdate = new Dictionary<Plate, List<Binding>>();
	//    }
	//#endif


	void LateUpdate()
	{
#if UNITY_EDITOR
      if (!Application.isPlaying && !runInEditMode)
		return;
#endif

      if (Time.unscaledTime - lastRefreshTime < bindingRefreshRate)
		return;

	  if (!graphene || !graphene.IsActiveAndVisible)
		return;

	  OnUpdate();
	  lastRefreshTime = Time.unscaledTime;
	}
	public void OnUpdate()
	{
      bindingsCount = 0;
#if UNITY_ASSERTIONS
	  Profiler.BeginSample("Update Bindings", this);
#endif
	  // Update the bindings for active/visible panels
	  foreach (var kvp in bindings)
     {
		var plate = kvp.Key;
        // Was disposed
        if (!plate)
          continue;
		// The panel is invisible, or inactive
		if (!plate.IsActive || !plate.Graphene.IsActiveAndVisible)
          continue;

        if (plate.bindingRefreshMode == BindingRefreshMode.None || (plate.bindingRefreshMode == BindingRefreshMode.ModelChange && !plate.wasChangedThisFrame))
          continue;
        plate.wasChangedThisFrame = false;

#if UNITY_ASSERTIONS
		Profiler.BeginSample(plate.DebugName, plate);
#endif
		foreach (var binding in kvp.Value)
        {
          // Needs to be disposed
          if (binding.scheduleDispose)
          {
            ScheduleDispose(kvp.Key, binding);
          }
          // Update the binding
          else
          {
            binding.Update();
            bindingsCount++;
          }
        }
#if UNITY_ASSERTIONS
        Profiler.EndSample();
#endif
	  }
#if UNITY_ASSERTIONS
	  Profiler.EndSample();
#endif

#if UNITY_ASSERTIONS
	  Profiler.BeginSample("CreateDispose");
#endif
	  // Create bindings
	  foreach (var kvp in createPostUpdate)
      {
        var list = GetList(kvp.Key, bindings);
        foreach (var binding in kvp.Value)
          list.Add(binding);
      }

      // Dispose unused bindings
      foreach (var kvp in disposePostUpdate)
        foreach (var binding in kvp.Value)
          Destroy(kvp.Key, binding);


      createPostUpdate.Clear();
      disposePostUpdate.Clear();

#if UNITY_ASSERTIONS
	  Profiler.EndSample();
#endif
	}

	List<Binding> GetList(Plate panel, Dictionary<Plate, List<Binding>> bindings)
    {
      if (bindings.ContainsKey(panel))
        return bindings[panel];

      List<Binding> list = new List<Binding>();
      bindings.Add(panel, list);
      return list;
    }

    /// <summary>
    /// Creates a continuous binding between a TextElement and a member variable on a context (scope) and panel
    /// </summary>
    /// <param name="el"></param>
    /// <param name="context"></param>
    /// <param name="bindingPath"></param>
    /// <param name="panel"></param>
    public void TryCreate(TextElement el, ref object context, in ValueWithAttribute<BindAttribute> member, Plate panel)
    {
      // Specifically set to one-time -> cancel binding
      if (member.Attribute.bindingMode.HasValue && member.Attribute.bindingMode.Value == BindingMode.OneTime)
        return;

      CreateBinding<string>(el, in context, in member, panel);
    }

    /// <summary>
    /// Creates a continuous binding between a BaseField<typeparamref name="TValueType"/> and a member variable on a context (scope) and panel
    /// </summary>
    /// <typeparam name="TValueType"></typeparam>
    /// <param name="el"></param>
    /// <param name="context"></param>
    /// <param name="member"></param>
    /// <param name="panel"></param>
    public void TryCreate<TValueType>(BaseField<TValueType> el, in object context, in ValueWithAttribute<BindAttribute> member, Plate panel)
    {
      // Specifically set to one-time
      if (member.Attribute.bindingMode.HasValue && member.Attribute.bindingMode.Value != BindingMode.OneTime)
        return;

      CreateBinding<TValueType>(el, in context, in member, panel);
    }


    /// <summary>
    /// Creates a continuous binding between a TextElement and a member variable on a context (scope) and panel
    /// </summary>
    /// <param name="el"></param>
    /// <param name="context"></param>
    /// <param name="bindingPath"></param>
    /// <param name="panel"></param>
    public void TryCreate<TValueType>(BindableElement el, in object context, in ValueWithAttribute<BindAttribute> member, Plate panel)
    {
      // Specifically set to one-time -> cancel binding
      if (member.Attribute.bindingMode.HasValue && member.Attribute.bindingMode.Value == BindingMode.OneTime)
        return;

      CreateBinding<TValueType>(el, in context, in member, panel);
    }

    internal void CreateBinding<TValueType>(BindableElement el, in object context, in ValueWithAttribute<BindAttribute> member, Plate panel)
    {
      Binding binding = null;
      // Collection binding
      if (el is ListView && typeof(TValueType).IsAssignableFrom(typeof(ICollection)))
        binding = new CollectionBinding(el, in context, in member);
      // Single binding
      else
        binding = new MemberBinding<TValueType>(el, in context, in member);

      if (binding != null)
        GetList(panel, createPostUpdate).Add(binding);
    }

    void ScheduleDispose(Plate panel, Binding binding)
    {
      GetList(panel, disposePostUpdate).Add(binding);
    }

    void Destroy(Plate panel, Binding binding)
    {
      GetList(panel, bindings).Remove(binding);
      binding.Dispose();
      binding = null;
    }

    internal void DisposePlate(Plate plate, bool isDestroyed)
    {
      if(bindings.TryGetValue(plate, out var list))
      {
        if (isDestroyed)
          bindings.Remove(plate);
        else
          list.Clear();
	  }
      if (disposePostUpdate.ContainsKey(plate))
		disposePostUpdate.Remove(plate);
    }
  }

}

================================================
FILE: src/Core/Binding/BindingsManager.cs.meta
================================================
fileFormatVersion: 2
guid: 4e490e9f02423f245a808e66b6d9c602
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Binding/CollectionBinding.cs
================================================
using System.Collections;
using UnityEngine.UIElements;

namespace Graphene
{
    using Kinstrife.Core.ReflectionHelpers;

    public class CollectionBinding : Binding<ICollection>
  {
    protected int? lastLength;

    public CollectionBinding(BindableElement el, in object context, in ValueWithAttribute<BindAttribute> member) : base(el, in context, in member)
    {
      if (member.Value is ICollection)
      {
      }
      else
      {
        scheduleDispose = true;
        return;
      }

      lastValue = GetValueFromMemberInfo();
      lastLength = lastValue?.Count;
    }

    protected override bool IsValidBinding()
    {
      return memberName != null;
    }
    protected override ICollection GetValueFromMemberInfo()
    {
      return (ICollection)extendedTypeInfo.Accessor[context, memberName];
    }
    protected override void SetValueFromMemberInfo(ICollection value)
    {
      extendedTypeInfo.Accessor[context, memberName] = value;
    }

    protected override void UpdateFromModel(in ICollection newValue)
    {
      // Collection reference/count changed -> Assign new list
      if (!this.lastValue.Equals(newValue) || newValue.Count != lastLength.Value)
        if (element is ListView listView && newValue is IList iList)
        {
          listView.itemsSource = iList;
          lastLength = iList?.Count;
        }
    }
  }
}

================================================
FILE: src/Core/Binding/CollectionBinding.cs.meta
================================================
fileFormatVersion: 2
guid: 6df237851253fc241a8dd9e269f6276c
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Binding/MemberBinding.cs
================================================
using UnityEngine.UIElements;

namespace Graphene
{
  using Kinstrife.Core.ReflectionHelpers;
  using UnityEngine;

  public class MemberBinding<T> : Binding<T>
  {
	public MemberBinding(BindableElement el, in object context, in ValueWithAttribute<BindAttribute> member) : base(el, in context, in member)
	{
	  lastValue = GetValueFromMemberInfo();
	}

	protected override bool IsValidBinding()
	{
	  return context != null;
	}

	protected override T GetValueFromMemberInfo()
	{
#if UNITY_ASSERTIONS
	  var val = extendedTypeInfo.Accessor[context, memberName];
	 // if(val == null)
	 // {
		//Debug.LogError($"Trying to cast a null member {memberName} {extendedTypeInfo.Accessor.Type}");
		//return default(T);
	 // }
	  if (val != null && !typeof(T).IsAssignableFrom(val.GetType()))
	  {
		Debug.LogError($"InvalidCastException for member {memberName} {extendedTypeInfo.Accessor.Type}: Trying to cast binding {val.GetType().Name} to {typeof(T).Name}. " +
		  $"\n{element.GetType().Name}");
		return default(T);
	  }
#endif

	  return (T)extendedTypeInfo.Accessor[context, memberName];
	}

	protected override void SetValueFromMemberInfo(T value)
	{
	  extendedTypeInfo.Accessor[context, memberName] = value;
	}
  }
}

================================================
FILE: src/Core/Binding/MemberBinding.cs.meta
================================================
fileFormatVersion: 2
guid: 51eed3340e1759745903e1cc5f44143d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Binding.meta
================================================
fileFormatVersion: 2
guid: 6c2a5a11ef9582442b314d518afb15ec
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions/ButtonGroup.cs
================================================

using Graphene.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.Elements
{
  public class ButtonGroup : GroupBox, IBindableElement<int>, INotifyValueChanged<int>
  {
    public const string itemsPath = "Items";

    [SerializeField]
    private List<string> m_Items = new List<string>();

    public List<string> items
    {
      get => m_Items;
      set
      {
        SetItems(value);
      }
    }

    /// <summary>
    /// Instantiates a <see cref="id"/> using the data read from a UXML file.
    /// </summary>
    public new class UxmlFactory : UxmlFactory<ButtonGroup, UxmlTraits> { }

    /// <summary>
    /// Defines <see cref="UxmlTraits"/> for the <see cref="id"/>.
    /// </summary>
    public new class UxmlTraits : BindableElement.UxmlTraits
    {
      UxmlIntAttributeDescription m_ActiveIndex = new UxmlIntAttributeDescription { name = "activeIndex" };
      UxmlStringAttributeDescription m_Items = new UxmlStringAttributeDescription { name = "items" };

      /// <summary>
      /// Initialize <see cref="id"/> properties using values from the attribute bag.
      /// </summary>
      /// <param name="ve">The object to initialize.</param>
      /// <param name="bag">The attribute bag.</param>
      /// <param name="cc">The creation context; unused.</param>
      public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
      {
        base.Init(ve, bag, cc);

		ButtonGroup buttonGroup = (ButtonGroup)ve;

		buttonGroup.value = m_ActiveIndex.GetValueFromBag(bag, cc);
		buttonGroup.items = SelectField.ParseChoiceList(m_Items.GetValueFromBag(bag, cc));
      }
    }

    [SerializeField]
    private int m_ActiveIndex = 0;
    public virtual int value
    {
      get { return m_ActiveIndex; }
      set
      {
        value = Mathf.Clamp(value, 0, childCount - 1);
        if (m_ActiveIndex == value)
        {
          SetValueWithoutNotify(value);
          return;
        }

        // in order for the serialization binding to update it's expecting you
        // to dispatch the event
        using (ChangeEvent<int> valueChangeEvent = ChangeEvent<int>.GetPooled(m_ActiveIndex, value))
        {
          valueChangeEvent.target = this; // very umportant
          SetValueWithoutNotify(value); // actually set the value and do any init with the value
          SendEvent(valueChangeEvent);
        }
      }
    }

    public event System.Action<int, string> clicked;

    public void SetValueWithoutNotify(int value)
    {
      m_ActiveIndex = Mathf.Clamp(value, 0, childCount - 1);
      SetButtonActive();
    }

    /// <summary>
    /// USS class name of elements of this type.
    /// </summary>
    /// <remarks>
    /// Unity adds this USS class to every instance of the TabGroup element. Any styling applied to
    /// this class affects every button located beside, or below the stylesheet in the visual tree.
    /// </remarks>
    public static new readonly string ussClassName = "gr-button-group ";
    public static readonly string ussActiveClassName = "active";

    /// <summary>
    /// Constructs an TabGroup.
    /// </summary>
    public ButtonGroup()
    {
      AddToClassList(ussClassName);
    }

    /// <summary>
    /// Callback from two-way binding system that model changed
    /// </summary>
    /// <param name="newValue"></param>
    public void OnModelChange(int newValue)
    {
      tabIndex = newValue;
    }

    internal void SetButtonActive()
    {
      int i = 0;
      foreach (var child in Children())
      {
        if (i == value)
        {
          child.AddToClassList(ussActiveClassName);
        }
        else
          child.RemoveFromClassList(ussActiveClassName);
        i++;
      }
    }

    public void SetItems(List<string> items)
    {
      m_Items = items ?? new List<string>();
      RefreshButtons();
    }

    public IList<ActionButton> SourceData = new List<ActionButton>();

    public void RefreshButtons()
	{
	  Clear();

      foreach (var item in items)
      {
		InternalAddItem(item);
	  }
	}

    internal void ButtonClicked(int i)
    {
      value = i;
      clicked?.Invoke(i, items[i]);

      if (SourceData != null && i < SourceData.Count)
        SourceData[i].OnClick?.Invoke();
    }

    public void ClearItems()
    {
      m_Items.Clear();
      Clear();
    }

    public void ClearCallback()
    {
      clicked = null;
    }

    public void AddItem(string text, string tooltip = null)
    {
      items.Add(text);
      InternalAddItem(text, tooltip);
	}

    void InternalAddItem(string text, string tooltip = null)
	{
	  int buttonIndex = childCount;
	  var btn = new Button(() => ButtonClicked(buttonIndex));
	  btn.text = text.ToUpper();
	  btn.tooltip = tooltip;
	  btn.AddToClassList("gr-button");
	  Add(btn);
	}
  }
}

================================================
FILE: src/Core/Extensions/ButtonGroup.cs.meta
================================================
fileFormatVersion: 2
guid: bc01c42213f651244a970ed2b40bca5a
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions/CycleField.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

using UnityEngine.UIElements;

namespace Graphene.Elements
{
  public class CycleField : BaseField<int>
  {
    public const string itemsPath = "Items";

    [SerializeField]
    private List<string> m_Items = new List<string>();

    public List<string> items { get => m_Items;
    set
      {
        if (value != null)
          m_Items = value;
        else
          m_Items = new List<string>();
      }
    }

    /// <summary>
    /// Instantiates a <see cref="CycleField"/> using the data read from a UXML file.
    /// </summary>
    public new class UxmlFactory : UxmlFactory<CycleField, UxmlTraits> { }

    /// <summary>
    /// Defines <see cref="UxmlTraits"/> for the <see cref="CycleField"/>.
    /// </summary>
    public new class UxmlTraits : BaseFieldTraits<int, UxmlIntAttributeDescription>
    {
      UxmlStringAttributeDescription m_Text = new UxmlStringAttributeDescription { name = "text" };
      UxmlStringAttributeDescription m_Items = new UxmlStringAttributeDescription { name = "items" };
      UxmlStringAttributeDescription m_Plus = new UxmlStringAttributeDescription { name = "plusSymbol" };
      UxmlStringAttributeDescription m_Minus = new UxmlStringAttributeDescription { name = "minusSymbol" };

      /// <summary>
      /// Initialize <see cref="CycleField"/> properties using values from the attribute bag.
      /// </summary>
      /// <param name="ve">The object to initialize.</param>
      /// <param name="bag">The attribute bag.</param>
      /// <param name="cc">The creation context; unused.</param>
      public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
      {
        base.Init(ve, bag, cc);
        var cycleField = (CycleField)ve;
		cycleField.text = m_Text.GetValueFromBag(bag, cc);
		cycleField.items = m_Items.GetValueFromBag(bag, cc).Split(';').Where(x => !string.IsNullOrEmpty(x)).ToList();
        cycleField.plusSymbol = m_Plus.GetValueFromBag(bag, cc);
        cycleField.minusSymbol = m_Minus.GetValueFromBag(bag, cc);
	  }
	}

    /// <summary>
    /// USS class name of elements of this type.
    /// </summary>
    public new static readonly string ussClassName = "gr-cycle-field";
    /// <summary>
    /// USS class name of labels in elements of this type.
    /// </summary>
    public new static readonly string labelUssClassName = ussClassName + "__label";
    /// <summary>
    /// USS class name of input elements in elements of this type.
    /// </summary>
    public new static readonly string inputUssClassName = ussClassName + "__input";
    /// <summary>
    /// USS class name of elements of this type, when there is no text.
    /// </summary>
    public static readonly string noTextVariantUssClassName = ussClassName + "--no-text";


    public static readonly string previousButtonUssClassName = ussClassName + "__button-previous";
    public static readonly string nextButtonUssClassName = ussClassName + "__button-next";

    /// <summary>
    /// USS class name of text elements in elements of this type.
    /// </summary>
    public static readonly string textUssClassName = ussClassName + "__text";

    public static readonly string hiddenClassName = "hidden";


    private Label m_Label;
    private VisualElement visualInput;

    Button m_Next;
    Button m_Previous;

	public string plusSymbol = "›";   // › ▶〉→
	public string minusSymbol = "‹";  // ‹ ◀〈 ←

	public CycleField()
        : this(null) {
    }

    public CycleField(string label)
        : base(label, null)
    {
      // Hax
      var children = hierarchy.Children().ToList();
      visualInput = hierarchy.Children().ToList().Find(x => x.ClassListContains("unity-base-field__input"));

      AddToClassList(ussClassName);
      AddToClassList(noTextVariantUssClassName);

      visualInput.AddToClassList(inputUssClassName);
      labelElement.AddToClassList(labelUssClassName);

      // The picking mode needs to be Position in order to have the Pseudostate Hover applied...
      visualInput.pickingMode = PickingMode.Position;

      // Allocate and add the buttons to the hierarchy
      m_Previous = new Button();
      m_Next = new Button();

      m_Previous.text = minusSymbol;
      m_Next.text = plusSymbol;
      //m_Next.AddToClassList("bold");
      //m_Previous.AddToClassList("bold");

      m_Previous.focusable = true;
      m_Next.focusable = true;

      m_Previous.AddToClassList(previousButtonUssClassName);
      m_Next.AddToClassList(nextButtonUssClassName);
	  m_Previous.AddToClassList("nomargin");
	  m_Next.AddToClassList("nomargin");

	  visualInput.Add(m_Previous);

      m_Label = new Label
      {
        pickingMode = PickingMode.Ignore
      };
      m_Label.text = "Select an option";
      visualInput.Add(m_Label);
      visualInput.Add(m_Next);

      m_Previous.clicked += M_Previous_clicked;
      m_Next.clicked += M_Next_clicked;

      // Set-up the label and text...
      text = null;
    }

    private void M_Previous_clicked()
    {
      int newValue = value - 1;
      if (newValue < 0)
        newValue = items.Count - 1;

      value = newValue;
    }

    private void M_Next_clicked()
    {
      int newValue = value + 1;
      if (newValue >= items.Count)
        newValue = 0;

      value = newValue;
    }

    public override void SetValueWithoutNotify(int newValue)
    {
      base.SetValueWithoutNotify(newValue);
      string newText = "";

      if (newValue >= 0 && newValue < items.Count)
        newText = items[newValue];

      text = newText;
    }


    /// <summary>
    /// Optional text after the toggle.
    /// </summary>
    public string text
    {
      get { return m_Label?.text; }
      set
      {
        if (!string.IsNullOrEmpty(value))
        {
          // Lazy allocation of label if needed...
          if (m_Label == null)
          {
            m_Label = new Label
            {
              pickingMode = PickingMode.Ignore
            };
            m_Label.AddToClassList(textUssClassName);
            RemoveFromClassList(noTextVariantUssClassName);
            visualInput.Add(m_Label);
          }

          m_Label.text = value;
        }
      }
    }

  }
}

================================================
FILE: src/Core/Extensions/CycleField.cs.meta
================================================
fileFormatVersion: 2
guid: eeb1b79b04839bd4389dd0e1a6457758
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions/Dialog.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

using UnityEngine.UIElements;

namespace Graphene.Elements
{
  public class Dialog : VisualElement, IDisposable
  {
    /// <summary>
    /// Instantiates a <see cref="Dialog"/> using the data read from a UXML file.
    /// </summary>
    public new class UxmlFactory : UxmlFactory<Dialog, UxmlTraits> { }

    /// <summary>
    /// Defines <see cref="UxmlTraits"/> for the <see cref="Dialog"/>.
    /// </summary>
    public new class UxmlTraits : BindableElement.UxmlTraits
    {
      /// <summary>
      /// Initialize <see cref="Dialog"/> properties using values from the attribute bag.
      /// </summary>
      /// <param name="ve">The object to initialize.</param>
      /// <param name="bag">The attribute bag.</param>
      /// <param name="cc">The creation context; unused.</param>
      public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
      {
        base.Init(ve, bag, cc);
      }
    }

    /// <summary>
    /// USS class name of elements of this type.
    /// </summary>
    public static readonly string ussClassName = "gr-dialog";
    /// <summary>
    /// USS class name of elements of this type.
    /// </summary>
    public static readonly string dialogBackgroundUssClassName = ussClassName + "__background";
    public static readonly string dialogPanelUssClassName = ussClassName + "__panel";

    public static readonly string hiddenClassName = "hidden";

    VisualElement m_Background;
    private View m_PanelView;

    public event System.Action onClose;

    public Dialog()
        : this(null, null) {
    }

    public Dialog(IPanel panel, VisualElement content)
    {
      AddToClassList(ussClassName);

      // Set-up the label and text...
      //this.AddManipulator(new Clickable(OnClickEvent));

      if (panel == null)
        panel = this.panel;

      m_Background = new VisualElement();
      m_Background.AddToClassList(dialogBackgroundUssClassName);
      m_Background.AddToClassList("unity-ui-document__child");
      m_Background.AddManipulator(new Clickable(OnClickBackground));

      // Add background to root
      panel?.TopRoot().Add(m_Background);
      //panel.visualTree.Add(m_Background);
      
      // Add dialog to background
      m_Background.Add(this);
      //hierarchy.Add(m_Background);

      //Set up view
      m_PanelView = new View("GR__Content");
      this.Add(m_PanelView);

      m_PanelView.isDefault = true;

      m_PanelView.AddToClassList(dialogPanelUssClassName);
      m_PanelView.Focus();

      if (content != null)
      {
        m_PanelView.Add(content);
        content.Focus();
      }

      m_Background.BringToFront();
      this.BringToFront();

    }


    bool ProcessClick(EventBase evt)
    {
      if (evt.eventTypeId == MouseUpEvent.TypeId())
      {
        var ce = (IMouseEvent)evt;
        if (ce.button == (int)MouseButton.LeftMouse)
        {
          return true; 
        }
      }
      else if (evt.eventTypeId == PointerUpEvent.TypeId() || evt.eventTypeId == ClickEvent.TypeId())
      {
        var ce = (IPointerEvent)evt;
        if (ce.button == (int)MouseButton.LeftMouse)
        {
          return true;

        }
      }
      return false;
    }

    void OnClickBackground(EventBase evt)
    {
      if (ProcessClick(evt))
      {
        onClose?.Invoke();
        Dispose();
      }
    }

    public void Dispose()
    {
      if(this.m_Background != null && this.m_Background.parent != null)
        this.m_Background.parent.Remove(this.m_Background);
    }

    public Dialog WithStyles(VisualElementStyleSheetSet styleSheets)
    {
      for (int i = 0; i < styleSheets.count; i++)
      {
        m_Background.styleSheets.Add(styleSheets[i]);
      }
      return this;
    }
  }
}

================================================
FILE: src/Core/Extensions/Dialog.cs.meta
================================================
fileFormatVersion: 2
guid: 6ba5abe3b1bb58c439073459c2b50355
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions/GrapheneRoot.cs
================================================

using System;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.Elements
{
  /// <summary>
  /// Root Graphene class that contains injec
  /// </summary>
  public class GrapheneRoot : BindableElement
  {
    ///// <summary>
    ///// Instantiates a <see cref="GrapheneRoot"/> using the data read from a UXML file.
    ///// </summary>
    //public new class UxmlFactory : UxmlFactory<GrapheneRoot, UxmlTraits> { }

    [SerializeField]
    private Router m_Router;
    public virtual Router router
    {
      get { return router; }
      set
      {
        m_Router = value;
      }
    }

    /// <summary>
    /// USS class name of elements of this type.
    /// </summary>
    /// <remarks>
    /// Unity adds this USS class to every instance of the GrapheneRoot element. Any styling applied to
    /// this class affects every button located beside, or below the stylesheet in the visual tree.
    /// </remarks>
    public static readonly string ussClassName = "gr-root";

    /// <summary>
    /// Constructs a GrapheneRoot.
    /// </summary>
    public GrapheneRoot() : this(null)
    {
    }

    /// <summary>
    /// Constructs a GrapheneRoot.
    /// </summary>
    public GrapheneRoot(Router router)
    {
      AddToClassList(ussClassName);
      this.AddMultipleToClassList($"absolute fill {VisualElementExtensions.documentChildUssClassName}");
      this.router = router;
    }
  }
}

================================================
FILE: src/Core/Extensions/GrapheneRoot.cs.meta
================================================
fileFormatVersion: 2
guid: 41eb40e62488c9842b7021276222eaf1
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions/If.cs
================================================

using System;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.Elements
{
  public class If : BindableElement, IBindableElement<object>
  {
    /// <summary>
    /// Instantiates a <see cref="id"/> using the data read from a UXML file.
    /// </summary>
    public new class UxmlFactory : UxmlFactory<If, UxmlTraits> { }

    /// <summary>
    /// Defines <see cref="UxmlTraits"/> for the <see cref="id"/>.
    /// </summary>
    public new class UxmlTraits : BindableElement.UxmlTraits
    {
      UxmlBoolAttributeDescription m_Value = new UxmlBoolAttributeDescription { name = "value" };

      /// <summary>
      /// Initialize <see cref="id"/> properties using values from the attribute bag.
      /// </summary>
      /// <param name="ve">The object to initialize.</param>
      /// <param name="bag">The attribute bag.</param>
      /// <param name="cc">The creation context; unused.</param>
      public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
      {
        base.Init(ve, bag, cc);

        bool startEnabled = false;
#if UNITY_EDITOR
		startEnabled = Application.isPlaying ? false : m_Value.GetValueFromBag(bag, cc);
#endif
        ((If)ve).value = startEnabled;
      }
    }

    private bool m_Value = false;
    public virtual bool value
    {
      get { return m_Value; }
      set
      {
        m_Value = value;
        if (m_Value)
          this.Show();
        else
          this.Hide();
      }
    }

    /// <summary>
    /// USS class name of elements of this type.
    /// </summary>
    /// <remarks>
    /// Unity adds this USS class to every instance of the If element. Any styling applied to
    /// this class affects every button located beside, or below the stylesheet in the visual tree.
    /// </remarks>
    public static readonly string ussClassName = "gr-if";

    /// <summary>
    /// Constructs an If.
    /// </summary>
    public If() 
    {
      AddToClassList(ussClassName);
      value = false;
    }

    public void OnModelChange(object newValue)
    {
      if (newValue is bool b)
        value = b;
      else if (ReferenceEquals(newValue, null))
        value = false;
      else if (newValue is null || newValue.Equals(false))
        value = false;
      else if (newValue is string s && (string.IsNullOrEmpty(s) || string.IsNullOrWhiteSpace(s)))
        value = false;
      else
        value = true;
    }
  }
}

================================================
FILE: src/Core/Extensions/If.cs.meta
================================================
fileFormatVersion: 2
guid: 6c0886185b9292347a8eef22665cc9e5
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions/Route.cs
================================================

using System;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.Elements
{
    public class Route : BindableElement
  {
    /// <summary>
    /// Instantiates a <see cref="Route"/> using the data read from a UXML file.
    /// </summary>
    public new class UxmlFactory : UxmlFactory<Route, UxmlTraits> { }

    /// <summary>
    /// Defines <see cref="UxmlTraits"/> for the <see cref="Route"/>.
    /// </summary>
    public new class UxmlTraits : BindableElement.UxmlTraits
    {
      UxmlStringAttributeDescription m_Route = new UxmlStringAttributeDescription { name = "route" };

      /// <summary>
      /// Initialize <see cref="View"/> properties using values from the attribute bag.
      /// </summary>
      /// <param name="ve">The object to initialize.</param>
      /// <param name="bag">The attribute bag.</param>
      /// <param name="cc">The creation context; unused.</param>
      public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
      {
        base.Init(ve, bag, cc);

        ((Route)ve).route = m_Route.GetValueFromBag(bag, cc);
      }
    }


    public Router<string> router;
    [SerializeField]
    private string m_Route = String.Empty;
    public virtual string route
    {
      get { return m_Route; }
      set
      {
        m_Route = value?.ToLower();
      }
    }

    /// <summary>
    /// USS class name of elements of this type.
    /// </summary>
    /// <remarks>
    /// Unity adds this USS class to every instance of the Route element. Any styling applied to
    /// this class affects every button located beside, or below the stylesheet in the visual tree.
    /// </remarks>
    public static readonly string ussClassName = "unity-route";
  
    /// <summary>
    /// Constructs a Route.
    /// </summary>
    public Route() : this(null)
    {
    }

    /// <summary>
    /// Constructs a route with an Action that is triggered when the button is clicked.
    /// </summary>
    /// <param name="clickEvent">The action triggered when the button is clicked.</param>
    /// <remarks>
    /// By default, a single left mouse click triggers the Action. To change the activator, modify <see cref="clickable"/>.
    /// </remarks>
    public Route(string route)
    {
      AddToClassList(ussClassName);
      this.route = route;

      // Add click to itself
      this.AddManipulator(new Clickable(OnClickEvent));

      clicked += Clicked;
    }

    public Action clicked;

    public void Clicked()
    {
      router.TryChangeState(route);
    }

    bool ProcessClick(EventBase evt)
    {
      if (evt.eventTypeId == MouseUpEvent.TypeId())
      {
        var ce = (IMouseEvent)evt;
        if (ce.button == (int)MouseButton.LeftMouse)
        {
          return true;
        }
      }
      else if (evt.eventTypeId == PointerUpEvent.TypeId() || evt.eventTypeId == ClickEvent.TypeId())
      {
        var ce = (IPointerEvent)evt;
        if (ce.button == (int)MouseButton.LeftMouse)
        {
          return true;

        }
      }
      return false;
    }

    void OnClickEvent(EventBase evt)
    {
      if (ProcessClick(evt)) {
        clicked.Invoke();
      }
    }

    internal void SetRouter(Router r)
    {
      this.router = r as Router<string>;
      r.onRoutingBlocked += OnRoutingBlocked;
      r.onRoutingUnblocked += OnRoutingUnblocked;
    }

    private void OnRoutingUnblocked()
    {
      SetEnabled(true);
    }

    private void OnRoutingBlocked()
    {
      SetEnabled(false);
    }
  }
}

================================================
FILE: src/Core/Extensions/Route.cs.meta
================================================
fileFormatVersion: 2
guid: 2cc316cb1922df641ac18819655d7e7b
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions/SelectField.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

using UnityEngine.UIElements;

namespace Graphene.Elements
{
  public class SelectField : BaseField<int>, IDisposable
  {
    public const string itemsPath = "Items";
    public int defaultItemHeight = 24;

    [SerializeField]
    private List<string> m_Items = new List<string>();

    public List<string> items { get => m_Items;
    set
      {
        if (value != null)
          m_Items = value;
        else
          m_Items = new List<string>();
      }
    }

    /// <summary>
    /// Instantiates a <see cref="SelectField"/> using the data read from a UXML file.
    /// </summary>
    public new class UxmlFactory : UxmlFactory<SelectField, UxmlTraits> { }

    /// <summary>
    /// Defines <see cref="UxmlTraits"/> for the <see cref="SelectField"/>.
    /// </summary>
    public new class UxmlTraits : BaseFieldTraits<int, UxmlIntAttributeDescription>
    {
      UxmlIntAttributeDescription m_ItemHeight = new UxmlIntAttributeDescription { name = "itemHeight" };
      UxmlStringAttributeDescription m_Text = new UxmlStringAttributeDescription { name = "text" };
      UxmlStringAttributeDescription m_Items = new UxmlStringAttributeDescription { name = "items" };

      /// <summary>
      /// Initialize <see cref="SelectField"/> properties using values from the attribute bag.
      /// </summary>
      /// <param name="ve">The object to initialize.</param>
      /// <param name="bag">The attribute bag.</param>
      /// <param name="cc">The creation context; unused.</param>
      public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
      {
        base.Init(ve, bag, cc);

        int itemHeight = m_ItemHeight.GetValueFromBag(bag, cc);
        if (itemHeight > 0)
          ((SelectField)ve).defaultItemHeight = itemHeight;

        ((SelectField)ve).text = m_Text.GetValueFromBag(bag, cc);
        ((SelectField)ve).items = ParseChoiceList(m_Items.GetValueFromBag(bag, cc));
      }
    }

    /// <summary>
    /// USS class name of elements of this type.
    /// </summary>
    public new static readonly string ussClassName = "gr-select-field";
    /// <summary>
    /// USS class name of labels in elements of this type.
    /// </summary>
    public new static readonly string labelUssClassName = ussClassName + "__label";
    /// <summary>
    /// USS class name of input elements in elements of this type.
    /// </summary>
    public new static readonly string inputUssClassName = ussClassName + "__input";
    /// <summary>
    /// USS class name of elements of this type, when there is no text.
    /// </summary>
    public static readonly string noTextVariantUssClassName = ussClassName + "--no-text";
    /// <summary>
    /// USS class name of elements of this type.
    /// </summary>
    public static readonly string listContainerUssClassName = ussClassName + "__list-container";
    public static readonly string listViewUssClassName = ussClassName + "__list-view";
    /// <summary>
    /// USS class name of text elements in elements of this type.
    /// </summary>
    public static readonly string textUssClassName = ussClassName + "__text";

    public static readonly string hiddenClassName = "hidden";

    private Label m_Label;
    private VisualElement visualInput;
    private ListView m_ListView;
    private Dialog m_Dialog;

    Toggle m_Toggle;
    

    public SelectField()
        : this(null) {
    }

    public SelectField(string label)
        : base(label, null)
    {
      // Hax
      var children = hierarchy.Children().ToList();
      visualInput = hierarchy.Children().ToList().Find(x => x.ClassListContains("unity-base-field__input"));

      AddToClassList(ussClassName);
      AddToClassList(noTextVariantUssClassName);

      visualInput.AddToClassList(inputUssClassName);
      labelElement.AddToClassList(labelUssClassName);

      // The picking mode needs to be Position in order to have the Pseudostate Hover applied...
      //visualInput.pickingMode = PickingMode.Position;

      // Set-up the label and text...
      text = null;
      this.AddManipulator(new Clickable(OnClickEvent));

      m_Toggle = new Toggle();
      m_Toggle.text = text;
      m_Toggle.RegisterValueChangedCallback((evt) =>
      {
        SetToggleState(m_Toggle.value);
        evt.StopPropagation();
      });
      visualInput.Add(m_Toggle);
      m_Toggle.Hide();

      // Manual dispose
      RegisterCallback<DetachFromPanelEvent>((evt) => Dispose());

    }

    private void M_ListView_onItemsChosen(IEnumerable<object> obj)
    {
      value = m_ListView.selectedIndex;
    }

    private void M_ListView_onSelectionChange(IEnumerable<object> obj)
    {
      value = m_ListView.selectedIndex;
    }

    public override void SetValueWithoutNotify(int newValue)
    {
      base.SetValueWithoutNotify(newValue);

      string newText = "";
      if (newValue >= 0 && newValue < m_Items.Count)
        newText = m_Items[newValue];

      text = newText;
      m_Toggle.text = newText;
    }

    /// <summary>
    /// Optional text after the toggle.
    /// </summary>
    public string text
    {
      get { return m_Label?.text; }
      set
      {
        if (!string.IsNullOrEmpty(value))
        {
          // Lazy allocation of label if needed...
          if (m_Label == null)
          {
            m_Label = new Label
            {
              pickingMode = PickingMode.Ignore
            };
            m_Label.AddToClassList(textUssClassName);
            RemoveFromClassList(noTextVariantUssClassName);
            visualInput.Add(m_Label);
          }

          m_Label.text = value;
        }
        else if (m_Label != null)
        {
          m_Label.RemoveFromHierarchy();
          AddToClassList(noTextVariantUssClassName);
          m_Label = null;
        }
      }
    }

    bool ProcessClick(EventBase evt)
    {
      if (evt.eventTypeId == MouseUpEvent.TypeId())
      {
        var ce = (IMouseEvent)evt;
        if (ce.button == (int)MouseButton.LeftMouse)
        {
          return true; 
        }
      }
      else if (evt.eventTypeId == PointerUpEvent.TypeId() || evt.eventTypeId == ClickEvent.TypeId())
      {
        var ce = (IPointerEvent)evt;
        if (ce.button == (int)MouseButton.LeftMouse)
        {
          return true;

        }
      }
      return false;
    }

    void OnClickEvent(EventBase evt)
    {
      if(ProcessClick(evt))
        OnClick();
    }

    protected override void ExecuteDefaultActionAtTarget(EventBase evt)
    {
      base.ExecuteDefaultActionAtTarget(evt);

      if (evt == null)
      {
        return;
      }

      if (IsActivationEvent(evt))
      {
        OnClick();
        evt.StopPropagation();
      }

      bool IsActivationEvent(EventBase e)
      {
        if (e.eventTypeId == KeyDownEvent.TypeId())
        {
          var keyDownEvent = (KeyDownEvent)e;
          return keyDownEvent.keyCode == KeyCode.KeypadEnter ||
              keyDownEvent.keyCode == KeyCode.Return;
        }
        return false;
      }
    }


    void OnClick()
    {
      m_Toggle.value = !m_Toggle.value;
    }

    void SetToggleState(bool value)
    {
      if (value)
      {
        m_ListView = CreateListView();
        m_Dialog = new Dialog(panel, m_ListView);
        m_Dialog.onClose += M_Dialog_onClose;
      }
    }

    private void M_Dialog_onClose()
    {
      // Focus back on the select field
      Focus();
    }

    VisualElement MakeItem()
    {
      return new Button();
    }

    void BindItem(VisualElement el, int index)
    {
      (el as TextElement).text = items[index];
      Debug.Log($"Created item at element {index}");
    }

    ListView CreateListView()
    {
      var listView = new ListView(items, defaultItemHeight, MakeItem, BindItem);

      listView.AddToClassList(listViewUssClassName);
      listView.AddToClassList("h6");
      listView.bindingPath = "Items";
      listView.focusable = true;

      listView.onSelectionChange += M_ListView_onSelectionChange;
      listView.onItemsChosen += M_ListView_onItemsChosen;

      Func<VisualElement> makeItem = () => new Label("ListViewOption");
      Action<VisualElement, int> bindItem = (e, i) => (e as Label).text = (e as Label).text + " " + i;
      bindItem = (e, i) => (e as Label).text = items[i];

      listView.makeItem = makeItem;
      listView.bindItem = bindItem;
      //m_ListView.reorderable = true;
      listView.itemsSource = items;
      return listView;
    }

    public void Dispose()
    {
      if (m_Dialog != null)
        m_Dialog.Dispose();
    }

	#region Util
	internal static List<string> ParseChoiceList(string choicesFromBag)
	{
	  if (string.IsNullOrEmpty(choicesFromBag.Trim()))
	  {
		return null;
	  }

	  string[] array = choicesFromBag.Split(new char[1] { ',' });
	  if (array.Length != 0)
	  {
		List<string> list = new List<string>();
		string[] array2 = array;
		foreach (string text in array2)
		{
		  list.Add(text.Trim());
		}

		return list;
	  }

	  return null;
	}
	#endregion
  }
}

================================================
FILE: src/Core/Extensions/SelectField.cs.meta
================================================
fileFormatVersion: 2
guid: bac1afa6a79c1714680bfc884ada8948
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions/TemplateTypes/Button.cs
================================================

using System;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.Elements
{
  public class GrButton : TemplateRef, IBindableElement<ControlType>, IGrapheneElement
  {
    /// <summary>
    /// Instantiates a <see cref="id"/> using the data read from a UXML file.
    /// </summary>
    public new class UxmlFactory : UxmlFactory<GrButton, UxmlTraits> { }

    /// <summary>
    /// USS class name of elements of this type.
    /// </summary>
    /// <remarks>
    /// Graphene adds this USS class to every instance of the Template element. Any styling applied to
    /// this class affects every button located beside, or below the stylesheet in the visual tree.
    /// </remarks>
    public static readonly new string ussClassName = "gr-button-ref";

    /// <summary>
    /// Constructs an Template.
    /// </summary>
    public GrButton() : this(null)
    {
      m_Type = ControlType.Button;
    }

    public GrButton(Renderer renderer) : base(renderer)
    {
      m_Type = ControlType.Button;
      AddToClassList(ussClassName);
    }
  }
}

================================================
FILE: src/Core/Extensions/TemplateTypes/Button.cs.meta
================================================
fileFormatVersion: 2
guid: 4063ec610a60a9049a8dc4a3a2d75ab8
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions/TemplateTypes/TemplateRef.cs
================================================
using System.Linq;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.Elements
{
  public class TemplateRef : BindableElement, IBindableElement<ControlType>, IGrapheneElement
  {
	/// <summary>
	/// Instantiates a <see cref="id"/> using the data read from a UXML file.
	/// </summary>
	public new class UxmlFactory : UxmlFactory<TemplateRef, UxmlTraits> { }

	/// <summary>
	/// Defines <see cref="UxmlTraits"/> for the <see cref="type"/>.
	/// </summary>
	public new class UxmlTraits : BindableElement.UxmlTraits
	{
	  UxmlEnumAttributeDescription<ControlType> m_Value = new UxmlEnumAttributeDescription<ControlType> { name = "type" };

	  /// <summary>
	  /// Initialize <see cref="id"/> properties using values from the attribute bag.
	  /// </summary>
	  /// <param name="ve">The object to initialize.</param>
	  /// <param name="bag">The attribute bag.</param>
	  /// <param name="cc">The creation context; unused.</param>
	  public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
	  {
		base.Init(ve, bag, cc);
		ControlType type = m_Value.GetValueFromBag(bag, cc);

		// Only override if defined
		if (type != ControlType.None)
		  ((TemplateRef)ve).type = type;
	  }
	}

	private GrapheneRoot root;
	protected VisualElement m_ChildTemplate;
	protected Renderer renderer;

	[SerializeField]
	protected ControlType m_Type = ControlType.None;
	public virtual ControlType type
	{
	  get { return m_Type; }
	  set
	  {
		m_Type = value;

		Render();
	  }
	}

	/// <summary>
	/// USS class name of elements of this type.
	/// </summary>
	/// <remarks>
	/// Unity adds this USS class to every instance of the Template element. Any styling applied to
	/// this class affects every button located beside, or below the stylesheet in the visual tree.
	/// </remarks>
	public static readonly string ussClassName = "gr-template-ref";

	/// <summary>
	/// Constructs an Template.
	/// </summary>
	public TemplateRef() : this(null)
	{
	}

	public TemplateRef(Renderer renderer)
	{
	  AddToClassList(ussClassName);
	  this.renderer = renderer;
	}

	public void Inject(GrapheneRoot root, Plate plate, Renderer renderer)
	{
	  this.renderer = renderer;
	}

	public void OnModelChange(ControlType newValue)
	{
	  type = newValue;
	}

	void InstantiateTemplate()
	{
	  renderer.Templates.TryGetTemplateAsset(this.type, out VisualTreeAsset template);
	  var clone = Binder.InternalInstantiate(template, renderer.Plate);

	  string name = this.name.Replace("Template", "").Replace("TemplateRef", "");
	  // Transfer binding path to top-level children & custom classes
	  if (!string.IsNullOrWhiteSpace(bindingPath))
	  {
		var classes = this.GetClasses().Where(c => c != ussClassName);

		clone.Query<TemplateContainer>().Children<BindableElement>().ForEach(x =>
		{
		  x.bindingPath = bindingPath;
		  x.AddMultipleToClassList(classes);

		  if (!string.IsNullOrWhiteSpace(name))
			clone.name = name;
		}
		);

		this.ClearClassList();
		this.AddToClassList(ussClassName);
	  }

	  Add(clone);
	  m_ChildTemplate = clone;
	}

	public void Render()
	{
	  if (m_ChildTemplate != null)
		ClearTemplate();

	  if (!renderer)
		return;

	  // Clear 
	  InstantiateTemplate();
	}

	void ClearTemplate()
	{
	  Remove(m_ChildTemplate);
	}
  }
}

================================================
FILE: src/Core/Extensions/TemplateTypes/TemplateRef.cs.meta
================================================
fileFormatVersion: 2
guid: d20f4dbc23d31124ca95a7906001617f
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions/TemplateTypes.meta
================================================
fileFormatVersion: 2
guid: 4de6f3d3fa92a844a98caeaeabfba7d4
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions/View.cs
================================================

using System;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.Elements
{
  public class View : VisualElement
  {
    /// <summary>
    /// Instantiates a <see cref="id"/> using the data read from a UXML file.
    /// </summary>
    public new class UxmlFactory : UxmlFactory<View, UxmlTraits> { }

    /// <summary>
    /// Defines <see cref="UxmlTraits"/> for the <see cref="id"/>.
    /// </summary>
    public new class UxmlTraits : BindableElement.UxmlTraits
    {
      UxmlStringAttributeDescription m_Id = new UxmlStringAttributeDescription { name = "id" };
      UxmlBoolAttributeDescription m_Default = new UxmlBoolAttributeDescription { name = "default" };

      /// <summary>
      /// Initialize <see cref="id"/> properties using values from the attribute bag.
      /// </summary>
      /// <param name="ve">The object to initialize.</param>
      /// <param name="bag">The attribute bag.</param>
      /// <param name="cc">The creation context; unused.</param>
      public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
      {
        base.Init(ve, bag, cc);

        ((View)ve).id = m_Id.GetValueFromBag(bag, cc);
        ((View)ve).isDefault = m_Default.GetValueFromBag(bag, cc);
      }
    }

    [SerializeField]
    private string m_Id = String.Empty;
    public virtual string id
    {
      get { return m_Id; }
      set
      {
        m_Id = value;
      }
    }

    [SerializeField]
    private bool m_Default = false;
    public virtual bool isDefault
    {
      get { return m_Default; }
      set
      {
        m_Default = value;
      }
    }

    /// <summary>
    /// USS class name of elements of this type.
    /// </summary>
    /// <remarks>
    /// Unity adds this USS class to every instance of the View element. Any styling applied to
    /// this class affects every button located beside, or below the stylesheet in the visual tree.
    /// </remarks>
    public static readonly string ussClassName = "unity-view";

    /// <summary>
    /// Constructs a View.
    /// </summary>
    public View() : this(null)
    {
    }

    /// <summary>
    /// Constructs a View with an Action that is triggered when the button is clicked.
    /// </summary>
    /// <param name="clickEvent">The action triggered when the button is clicked.</param>
    /// <remarks>
    /// By default, a single left mouse click triggers the Action. To change the activator, modify <see cref="clickable"/>.
    /// </remarks>
    public View(string id) : base ()
    {
      AddToClassList(ussClassName);
      this.id = id;
    }
  }
}

================================================
FILE: src/Core/Extensions/View.cs.meta
================================================
fileFormatVersion: 2
guid: a191edcfe0e527d4d91c17ee1926751d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions/VisualElementExtensions.cs
================================================
using System.Collections.Generic;
using UnityEngine.UIElements;

namespace Graphene
{
  public static class VisualElementExtensions
  {
    internal const string documentRootUssClassName = "unity-ui-document__root";
    internal const string documentChildUssClassName = "unity-ui-document__child";
    internal const string hiddenUssClassName = "hidden";
    internal const string invisibleUssClassName = "invisible";
	internal const string fadeoutUssClassName = "fadeout";
    internal const string transitioningUssClassName = "transitioning";
    //internal const string fadeinUssClassName = "fadein";

    internal const string activeUssClassName = "active";
    internal const string selectedUssClassName = "selected";

    public static bool IsHidden(this VisualElement el)
    { 
      return el.ClassListContains(hiddenUssClassName);
    }

    public static void Show(this VisualElement el)
    {
      el.RemoveFromClassList(hiddenUssClassName);
    }
    public static void Hide(this VisualElement el)
    {
      el.AddToClassList(hiddenUssClassName);
    }

    public static void SetShowHide(this VisualElement el, bool value)
    {
      if (value)
        el.Show();
      else
        el.Hide();
    }

	public static void SetVisibility(this VisualElement el, bool value)
	{
	  if (value)
		el.RemoveFromClassList(invisibleUssClassName);
	  else
		el.AddToClassList(invisibleUssClassName);
	}
	public static void SetActive(this VisualElement el, bool value)
    {
      if(value)
        el.AddToClassList(activeUssClassName);
      else
        el.RemoveFromClassList(activeUssClassName);
	}

	public static void ToggleClass(this VisualElement el, string className, bool value)
	{
	  if (value)
		el.AddToClassList(className);
	  else
		el.RemoveFromClassList(className);
	}


	public static void FadeIn(this VisualElement el)
    {
      el.RemoveFromClassList(fadeoutUssClassName);
    }

    public static void FadeOut(this VisualElement el)
    {
      el.AddToClassList(fadeoutUssClassName);
    }
	public static void StartTransition(this VisualElement el)
	{
	  el.AddToClassList(transitioningUssClassName);
	}
	public static void StopTransition(this VisualElement el)
	{
	  el.RemoveFromClassList(transitioningUssClassName);
	}

	public static bool IsFadingOut(this VisualElement el)
	{
	  return el.ClassListContains(fadeoutUssClassName);
	}

	public static bool IsTransitioning(this VisualElement el)
	{
	  return el.ClassListContains(transitioningUssClassName);
	}
	public static VisualElement TopRoot(this VisualElement el)
    {
      return el.panel?.visualTree.Q(null, documentRootUssClassName);
    }
    public static VisualElement TopRoot(this IPanel panel)
    {
      return panel?.visualTree.Query(null, documentRootUssClassName).Last();
    }

    public static void AddStyles(this VisualElement el, VisualElementStyleSheetSet styleSheets)
    {
      for (int i = 0; i < styleSheets.count; i++)
      {
        var sheet = styleSheets[i];
        if (sheet != null)
          el.styleSheets.Add(sheet);
#if UNITY_EDITOR
        else
          UnityEngine.Debug.LogError("Trying to add null stylesheet");
#endif
      }
    }

    public static void AddStyles(this VisualElement el, IEnumerable<StyleSheet> styleSheets)
    {
      foreach (var styleSheet in styleSheets)
      {
        if(styleSheet)
          el.styleSheets.Add(styleSheet);
#if UNITY_EDITOR
        else
          UnityEngine.Debug.LogError("Trying to add null stylesheet");
#endif
      }
    }

    /// <summary>
    /// Adds multiple classes to VisualElement. ClassNames separated by space ' '.
    /// </summary>
    /// <param name="el"></param>
    /// <param name="classes">Separated by space</param>
    public static void AddMultipleToClassList(this VisualElement el, string classes)
    {
      if (string.IsNullOrWhiteSpace(classes))
        return;
        AddMultipleToClassList(el, Parse(classes));
    }

    public static void AddMultipleToClassList(this VisualElement el, IEnumerable<string> classes)
    {
      foreach (var className in classes)
        el.AddToClassList(className);
    }


	/// <summary>
	/// Removes multiple classes from VisualElement. ClassNames separated by space ' '.
	/// </summary>
	/// <param name="el"></param>
	/// <param name="classes">Separated by space</param>
	public static void RemoveMultipleFromClassList(this VisualElement el, string classes)
	{
	  if (string.IsNullOrWhiteSpace(classes))
		return;

	  RemoveMultipleFromClassList(el, Parse(classes));
	}
	public static void RemoveMultipleFromClassList(this VisualElement el, IEnumerable<string> classes)
	{
	  foreach (var className in classes)
		el.RemoveFromClassList(className);
	}

    public static IEnumerable<string> Parse(string classes)
    {
      return classes?.Split(new string[] { " " }, System.StringSplitOptions.RemoveEmptyEntries);

	}
  }
}

================================================
FILE: src/Core/Extensions/VisualElementExtensions.cs.meta
================================================
fileFormatVersion: 2
guid: fd3bb9a5a9100d24cb94c9a528a30eb0
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Extensions.meta
================================================
fileFormatVersion: 2
guid: 4abeed0c73932b946972d66da4b7ae42
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Graphene.cs
================================================
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.UIElements;

namespace Graphene
{
  using Elements;
  using System.Collections;

  [ExecuteInEditMode]
  [RequireComponent(typeof(UIDocument))]
  [RequireComponent(typeof(BindingsManager))]
  [DisallowMultipleComponent]
  public class Graphene : MonoBehaviour
  {
	[SerializeField, Tooltip("Disable this if you want to manually initialize Graphene")] bool initializeOnStart = true;
	[SerializeField, Tooltip("Disable this if you want to manually initialize Graphene")] new bool runInEditMode = false;
	[SerializeField] string addClasses;
	[SerializeField] public PickingMode defaultPickingMode;

	[SerializeField] List<Plate> plates = new List<Plate>(); public IReadOnlyList<Plate> Plates => plates;

	List<IGrapheneDependent> dependents = new List<IGrapheneDependent>();
	public event System.Action<ICollection<IGrapheneDependent>> onPreInitialize;
	public event System.Action<ICollection<IGrapheneDependent>> onPostInitialize;
	public event System.Action<BindableElement, object> onBindElement;

	/// <summary>
	/// Root Graphene element controller
	/// </summary>
	GrapheneRoot grapheneRoot; public GrapheneRoot GrapheneRoot => grapheneRoot;

	/// <summary>
	/// The UI Document
	/// </summary>
	[SerializeField] UIDocument doc; public UIDocument Doc => doc;
	/// <summary>
	/// The router
	/// </summary>
	[SerializeField] Router router; public Router Router => router;
	[SerializeField] BindingsManager binder; public BindingsManager Binder => binder;

	public bool IsInitialized => grapheneRoot != null;

	public bool IsActiveAndInitialized => isActiveAndEnabled && IsInitialized;

	public bool IsActiveAndVisible => IsActiveAndInitialized && !grapheneRoot.IsHidden();

	#region Events
	public event System.Action<Plate> plateOnShow;
	public event System.Action<Plate> plateOnHide;
	#endregion

	protected void Start()
	{
	  GetLocalReferences();
	  if (!Application.isPlaying)
	  {
		GetChildPlates();
		return;
	  }

	  if (enabled && initializeOnStart)
		Initialize();
	}

	#region Attributes
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ShowInInspector]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.ShowInInspector]
#endif
	#endregion
	public bool Initialized { get; private set; }

	public bool IsValid => doc && doc.panelSettings && doc.visualTreeAsset;

	#region ButtonAttribute
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ResponsiveButtonGroup]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.Button]
#endif
	#endregion
	public void Initialize()
	{
	  if (Initialized)
		return;
	  GetLocalReferences();

	  if (!IsValid)
	  {
		UnityEngine.Debug.LogError($"Graphene missing requirements. Please make sure UIDocument is present, has PanelSettings and a VisualTreeAsset", this);
		return;
	  }

	  RunInstallation();

	  //doc.enabled = false;
	  //doc.enabled = true;
	  Initialized = true;

	  FinalizeInitialzation();
	}

	protected void GetLocalReferences()
	{
	  doc ??= GetComponent<UIDocument>();
	  router ??= GetComponent<Router>();
	  binder = GetComponent<BindingsManager>();
	}

#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ResponsiveButtonGroup]
#endif
	public void GetChildPlates()
	{
	  GetComponentsInChildren<Plate>(includeInactive: true, plates);
	  foreach (var p in plates)
		p.Inject(this);
	}

	protected void RunInstallation()
	{
	  var sw = new Stopwatch();
	  sw.Start();

	  // Get all dependents
	  GetComponentsInChildren<IGrapheneDependent>(true, dependents);
	  GetChildPlates();

	  // Inject Graphene into
	  foreach (var c in dependents)
	  {
		if (c is IGrapheneInjectable gc)
		  gc.Inject(this);
	  }

	  Profiler.BeginSample("Graphene Initialize", this);
	  onPreInitialize?.Invoke(dependents);
	  // First initialize
	  foreach (var item in dependents)
	  {
		if (item is IGrapheneInitializable i)
		  i.Initialize();
	  }
	  Profiler.EndSample();

	  Profiler.BeginSample("Graphene Construct VisualTree", this);
	  // Construct the visual tree hierarchy 
	  ConstructVisualTree(plates);
	  Profiler.EndSample();

	  Profiler.BeginSample("Graphene Late Initialize", this);
	  // Second initialize
	  // First initialize
	  foreach (var item in dependents)
	  {
		if (item is IGrapheneLateInitializable i)
		  i.LateInitialize();
	  }
	  onPostInitialize?.Invoke(dependents);
	  Profiler.EndSample();
	  sw.Stop();

	  //#if UNITY_EDITOR
	  //	  UnityEngine.Debug.Log($"Graphene ({gameObject.scene.name}/{gameObject.name}) initialization: {sw.ElapsedMilliseconds}ms", this);
	  //#endif
	}


	void ConstructVisualTree(List<Plate> plates)
	{
	  var sw = new Stopwatch();
	  sw.Start();

	  // Create the root controller
	  CreateRootElement();

	  // Clone the visual tree for each plate
	  foreach (Plate plate in plates)
	  {
		if (!plate.VisualTreeAsset)
		{
		  UnityEngine.Debug.LogError($"Missing Plate VisualTreeAsset {plate}", plate);
		  continue;
		}

		try
		{
		  plate.Dispose();
		  plate.ConstructVisualTree();
		}
		catch (System.Exception e)
		{
		  UnityEngine.Debug.LogError(e, plate);
		}
	  }

	  // Refresh hierarchy -> render & compose children
	  foreach (Plate plate in plates)
	  {
		if (!plate.VisualTreeAsset)
		  continue;

		RegisterPlate(plate);
	  }

	  sw.Stop();
	  //UnityEngine.Debug.Log($"Graphene ConstructVisualTree: {sw.ElapsedMilliseconds}ms");
	}

	public void AddPlate(Plate plate)
	{
	  if (!plates.Contains(plate))
		plates.Add(plate);
	}

	public void RegisterPlate(Plate plate)
	{
	  if (plate.IsRootPlate)
	  {
		grapheneRoot.Add(plate.Root);
		plate.Root.AddToClassList("unity-ui-document__child");
	  }

	  plate.Root.name = $"{plate.gameObject.name}-container";
	  plate.RenderAndComposeChildren();
	  plate.HideImmediately(); // Hide immediately by default

	  plate.onShow.AddListener(() => { plateOnShow?.Invoke(plate); });
	  plate.onHide.AddListener(() => { plateOnHide?.Invoke(plate); });

	  // Enable on start
	  //if(plate.gameObject.activeSelf)
	  plate.ReevaluateState();
	}

	#region Build VisualElement

	void CreateRootElement()
	{
	  // Create the root controller
	  grapheneRoot = new GrapheneRoot(router);
	  grapheneRoot.AddMultipleToClassList(addClasses);
	  grapheneRoot.pickingMode = defaultPickingMode;

#if UNITY_EDITOR
	  grapheneRoot.RegisterCallback<DetachFromPanelEvent>(DetachFromPanel);
#endif

	  doc.rootVisualElement.Add(grapheneRoot);
	}

#if UNITY_EDITOR
	IEnumerator coroutine;
	void DetachFromPanel(DetachFromPanelEvent evt)
	{
	  if (!Application.isPlaying || !gameObject.activeInHierarchy || !doc.enabled)
		return;
	  coroutine = RebuildDelayed(0.1f);
	  StartCoroutine(coroutine);
	}

	IEnumerator RebuildDelayed(float delay)
	{
	  yield return new WaitForSeconds(delay);
	  grapheneRoot.UnregisterCallback<DetachFromPanelEvent>(DetachFromPanel);
	  doc.rootVisualElement.Add(grapheneRoot);
	  grapheneRoot.RegisterCallback<DetachFromPanelEvent>(DetachFromPanel);
	  yield break;
	  //Rebuild();
	}
#endif

	void RebuildRootElement()
	{
	  var oldRoot = grapheneRoot;

	  CreateRootElement();

	  if (oldRoot != null)
	  {
		// Add root plates
		if (oldRoot.childCount > 0)
		{
		  var children = oldRoot.Children().ToList();
		  foreach (var child in children)
			grapheneRoot.Add(child);
		}

		doc.rootVisualElement.Remove(oldRoot);
	  }
	}
	#endregion

	#region BuildHierarchy
	#endregion

	void FinalizeInitialzation()
	{
	  /// Needs to go here because UIDocuments may initialize late
	  grapheneRoot.BringToFront();
	}

	public void RebuildBranch(Plate plate)
	{

	}

	// Needs to be in because UIDocument destroys the root
	private void OnEnable()
	{
#if UNITY_EDITOR
	  if (UnityEditor.EditorApplication.isCompiling || UnityEditor.BuildPipeline.isBuildingPlayer)
		return;
#endif

	  if (grapheneRoot != null && initializeOnStart)
		// Live reload
		Rebuild();
	  return;
	}


	private void OnDisable()
	{
#if UNITY_EDITOR
	  if (UnityEditor.EditorApplication.isCompiling || UnityEditor.BuildPipeline.isBuildingPlayer)
		return;
#endif
	}

	bool canRebuild => Initialized && doc.enabled && isActiveAndEnabled;

	public event System.Action onRebuild;

	int rebuildCount;

	#region ButtonAttribute
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ResponsiveButtonGroup]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.Button]
#endif
	#endregion
	public void Rebuild()
	{
	  if (!Application.isPlaying && !runInEditMode)
		return;

	  if (!Initialized)
	  {
		Initialize();
		return;
	  }

	  if (!canRebuild)
		return;

//#if UNITY_EDITOR
//		UnityEngine.Debug.Log($"Rebuilding Graphene {name} {gameObject.scene.name}", this);
//#endif

	  if (grapheneRoot != null)
	  {
		grapheneRoot.parent?.Remove(grapheneRoot);
		grapheneRoot.Clear();
		grapheneRoot = null;
	  }

	  ConstructVisualTree(plates);
	  FinalizeInitialzation();
	  onRebuild?.Invoke();
	}

	public void RefreshAllActiveContent()
	{
	  foreach (var p in plates)
	  {
		if (!p.IsActive)
		  continue;
		p.Renderer?.Refresh();
	  }
	}

	//private void OnValidate()
	//{

	//  LiveLink
	//  if (Application.isPlaying || doc.rootVisualElement == null)
	//    return;

	//  RebuildRootElement();
	//}

	public void BroadcastBindCallback(BindableElement el, object context, Plate plate) => onBindElement?.Invoke(el, context);
  }
}

================================================
FILE: src/Core/Graphene.cs.meta
================================================
fileFormatVersion: 2
guid: 3df2f2c9411e2af419b0ebc039577ce4
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {fileID: 2800000, guid: a7567e94e4334dd4bb5bed2d09495114, type: 3}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/GrapheneComponent.cs
================================================
using UnityEngine;

namespace Graphene
{
    /// <summary>
    /// Base class for all components that participate in the Graphene dependency injection system.
    /// Provides access to the injected <see cref="Graphene"/> instance and its <see cref="BindingsManager"/>.
    /// </summary>
    public class GrapheneComponent : MonoBehaviour, IGrapheneInjectable
    {
        /// <summary>
        /// Cached debug name for this component, used for identification and logging.
        /// </summary>
        internal string debugNameCached;

        /// <summary>
        /// Gets the cached debug name for this component.
        /// </summary>
        public string DebugName => debugNameCached;

#if ODIN_INSPECTOR
        [Sirenix.OdinInspector.HideIf(nameof(graphene))]
#endif
        /// <summary>
        /// The injected Graphene instance that manages bindings and dependencies for this component.
        /// </summary>
        [SerializeField] protected Graphene graphene;

        /// <summary>
        /// Gets the injected <see cref="Graphene"/> instance.
        /// </summary>
        public Graphene Graphene => graphene;

        /// <summary>
        /// Gets the <see cref="BindingsManager"/> from the injected <see cref="Graphene"/> instance.
        /// </summary>
        public BindingsManager BindingsManager => graphene?.Binder;

        /// <summary>
        /// Injects the specified <see cref="Graphene"/> instance into this component.
        /// </summary>
        /// <param name="graphene">The Graphene instance to inject.</param>
        public virtual void Inject(Graphene graphene)
        {
            this.graphene = graphene;

            if (string.IsNullOrEmpty(debugNameCached))
                debugNameCached = name;
        }

        /// <summary>
        /// Unity Awake callback. Ensures the debug name is initialized.
        /// </summary>
        protected virtual void Awake()
        {
            if (string.IsNullOrEmpty(debugNameCached))
                debugNameCached = name;
        }
    }
}

================================================
FILE: src/Core/GrapheneComponent.cs.meta
================================================
fileFormatVersion: 2
guid: d32a65210f6ccde4ba4983f9164de0b3
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Injector.cs
================================================
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using UnityEngine;

namespace Graphene
{
  [DisallowMultipleComponent]
  public class Injector : MonoBehaviour
  {
    [SerializeField] Graphene graphene; 
    private void Awake()
    {
      if (graphene || (graphene = GetComponent<Graphene>()))
        graphene.onPreInitialize += Graphene_onPreInitialize;
    }

    private void Graphene_onPreInitialize(ICollection<IGrapheneDependent> dependents)
    {
      foreach (var dependent in dependents)
      {
        if (dependent is Router router)
          router.InjectIntoHierarchy();
      }
    }
  }
}

================================================
FILE: src/Core/Injector.cs.meta
================================================
fileFormatVersion: 2
guid: d8e759c0d6277b6448cce98e37e22305
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {fileID: 2800000, guid: d249967811185734b8114d4b8977f433, type: 3}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Interfaces.cs
================================================
namespace Graphene
{
  using Elements;
  using UnityEngine.UIElements;

  public interface IGrapheneDependent
  {
  }

  public interface IBindableToVisualElement : IHasTooltip
  {
    bool isShown { get; }
    System.Action<bool> onShowHide { get; set; }

    bool isEnabled { get; }
    System.Action<bool> onSetEnabled { get; set; }

	bool isActive2 { get; }
	System.Action<bool> onSetActive { get; set; }

    //event System.Action<VisualElement> onBindToElement;// { get; set; }

	VisualElement boundToElement { get; }

	void ResetCallbacks ();

    void SetBinding(VisualElement boundToElement);

    //System.Action syncVisualElement { get; set; }
  }

  public interface IBindableElement<TValue>
  {
    /// <summary>
    /// Callback to VisualElement control that model changed, and view needs to be updated
    /// </summary>
    /// <param name="newValue"></param>
    void OnModelChange(TValue newValue);
  }

  public enum InteractionMode
  {
    Button,
    Submit,
    Cancel
  }

  public interface IBindableInteractionType
  {
    public InteractionMode InteractionType { get; }
    public int Size { get; }
  }

  public interface IGrapheneElement
  {
    void Inject(GrapheneRoot root, Plate plate, Renderer renderer);
  }

#if !DEPENDENCY_INJEcTION
  public interface IGrapheneInitializable : IGrapheneDependent
  {
    void Initialize();
  }
  public interface IGrapheneLateInitializable : IGrapheneDependent
  {
    void LateInitialize();
  }

  public interface IGrapheneInjectable : IGrapheneDependent
  {
    void Inject(Graphene graphene);
  }
#endif

  #region IModel

  public interface IModel
  {
	void Initialize(VisualElement container, Plate plate);
	bool Render { get; }

	System.Action onModelChange { get; set; }

	void Refresh(VisualElement container);
  }

  /// <summary>
  /// Instructs the <see cref="Renderer"/> to use a custom <see cref="BindAttribute"/> context
  /// </summary>
  public interface ICustomBindContext
  {
	public object GetCustomBindContext { get; }
  }

  /// <summary>
  /// Instructs the <see cref="Renderer"/> to use a custom <see cref="DrawAttribute"/> context
  /// </summary>
  public interface ICustomDrawContext
  {
	public object GetCustomDrawContext { get; }
  }

  public interface IForm
  {
	[Bind("Title")]
	string Title { get; }
	void OnSubmit();
	void OnCancel();
  }
  #endregion

  #region Misc

  public interface IHasTooltip
  {
	string Tooltip { get; }
  }

  public interface IHasCustomVisualTreeAsset
  {
	VisualTreeAsset VisualTreeAsset { get; }
  }

  #endregion

}

================================================
FILE: src/Core/Interfaces.cs.meta
================================================
fileFormatVersion: 2
guid: 59b985a9f1ab787479e438f05a3b2567
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Model/BindableObjects/BindableBaseField.cs
================================================
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Text;
using UnityEngine;
using UnityEngine.UIElements;

#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#endif

namespace Graphene.ViewModel
{
  [System.Serializable]
  [DataContract]
  public abstract class BindableBaseField : BindableObjectBase
  {
	[field: SerializeField]
	[Bind(nameof(Label), BindingMode.OneWay)]
	[IgnoreDataMember]
	public virtual string Label { get; set; }
  }

  [System.Serializable]
  [DataContract]
  public abstract class BindableBaseField<T> : BindableBaseField, INotifyValueChanged<T>, INotifyPropertyChanged
  {
	[SerializeField]
	protected T m_Value;

	public BindableBaseField() { }

	public BindableBaseField([CallerMemberName] string label = "Label") : this()
	{
	  this.Label = label;
	}

	[BindBaseField("Value")]
	[DataMember(Name = "Value")]
	public virtual T value
	{
	  get => m_Value; set
	  {
		SetValueWithoutNotify(value);
		ValueChangeCallback(m_Value);
	  }
	}


	/*[BindValueChangeCallback(nameof(ValueChange))]*/
	[IgnoreDataMember]
	public EventCallback<ChangeEvent<T>> ValueChange => (changeEvent) => { ValueChangeCallback(changeEvent.newValue); };

	public event System.EventHandler<T> OnValueChange;
	public event PropertyChangedEventHandler PropertyChanged;

	public virtual void SetValueWithoutNotify(T newValue)
	{
	  m_Value = newValue;
	}

#if UNITY_EDITOR
	PropertyChangedEventArgs propertyChangedArgs;
#endif

	protected virtual void ValueChangeCallback(T value)
	{
	  OnValueChange?.Invoke(this, value);
#if UNITY_EDITOR
	  if (propertyChangedArgs == null)
		propertyChangedArgs = new PropertyChangedEventArgs(Label);
	  PropertyChanged?.Invoke(this, propertyChangedArgs);
#else
	  PropertyChanged?.Invoke(this, null);
#endif
	}

	public override void ResetCallbacks()
	{
	  base.ResetCallbacks();
	  OnValueChange = null;
	  PropertyChanged = null;
	}
  }



  [System.Serializable, Draw(ControlType.Toggle), DataContract]
  public class BindableBool : BindableBaseField<bool>
  {
	public BindableBool(string name = null) : base(name) { }
	public BindableBool() : base(null) 	{}
  }



  [System.Serializable, Draw(ControlType.Slider), DataContract]
  public abstract class RangeBaseField<TValueType> : BindableBaseField<TValueType>
  {
	public abstract float normalizedValue { get; }

	// These come first, so the ranges are deserialized _before_ the value
#if ODIN_INSPECTOR
	[PropertyOrder(1)]
#endif
	[Bind("Min"), DataMember(Name = "Min")]
	public TValueType min;
#if ODIN_INSPECTOR
	[PropertyOrder(1)]
#endif
	[Bind("Max"), DataMember(Name = "Max")]
	public TValueType max;

	[BindBaseField("Value")]
	[DataMember(Name = "Value")]
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ShowInInspector, Sirenix.OdinInspector.PropertyRange(0, 1, MinGetter = nameof(min), MaxGetter = nameof(max))]
#endif
	public override TValueType value { get => base.value; set => base.value = value; }

	public TValueType Min { get => min; set => min = value; }
	public TValueType Max { get => max; set => max = value; }

	public RangeBaseField() : base() { }

	protected float Normalize(float value, float min, float max)
	{
	  return Mathf.InverseLerp(min, max, value);
	}
  }

  public interface INumericBindable
  {
	float normalizedValue { get; }
	float value { get; set; }

	float Min { get; set; }
	float Max { get; set; }

	void SetValueWithoutNotify(float value);
  }

  [System.Serializable, Draw(ControlType.Slider), DataContract]
  public class BindableFloat : RangeBaseField<float>, INumericBindable
  {
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ShowInInspector, Sirenix.OdinInspector.PropertyRange(0, 1)]
#endif
	public override float normalizedValue => Normalize(m_Value, min, max);

	public BindableFloat() : base()
	{
	  min = 0;
	  max = 1;
	  m_Value = 0.5f;
	}

	public override void SetValueWithoutNotify(float newValue)
	{
	  m_Value = Mathf.Clamp(newValue, min, max);
	}
  }

  [System.Serializable, Draw(ControlType.SliderInt), DataContract]
  public class BindableInt : RangeBaseField<int>, INumericBindable
  {
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ShowInInspector, Sirenix.OdinInspector.PropertyRange(0, 1)]
#endif
	public override float normalizedValue => Normalize(m_Value, min, max);

	float INumericBindable.value { get => value; set => base.value = (int)value; }
	float INumericBindable.Min { get => min; set => min = (int)value; }
	float INumericBindable.Max { get => max; set => max = (int)value; }

	public BindableInt() : base()
	{
	  min = 0;
	  max = 100;
	  m_Value = 50;
	  //m_Value = 5;
	}

	public override void SetValueWithoutNotify(int newValue)
	{
	  m_Value = Mathf.Clamp(newValue, min, max);
	}

	void INumericBindable.SetValueWithoutNotify(float value) => SetValueWithoutNotify((int)value);
  }

  [System.Serializable, Draw(ControlType.CycleField), DataContract]
  public class BindableNamedInt : BindableBaseField<int>
  {
	[field: SerializeField]
	[Bind("Items"), IgnoreDataMember]
	public List<string> items { get; set; } = new List<string>();

	public float normalizedValue => (float)m_Value / items.Count;

	public void InitFromEnum<T>(bool splitUppercase = true)
	{
	  this.items.Clear();

	  foreach (string s in System.Enum.GetNames(typeof(T)).ToList())
	  {
		string item = s;
		if (splitUppercase)
		  item = StringUtility.InsertSpaceBeforeUpperCase(s);
		item = item.Replace("_", " ").Trim();

		this.items.Add(item);
	  }
	}
	public void InitFromList(IEnumerable<string> list)
	{
	  this.items.Clear();
	  this.items = list.ToList();
	}

	public BindableNamedInt() : base() { }

  }

  [System.Serializable, Draw(ControlType.DropdownField), DataContract]
  public class BindableStringSelect : BindableBaseField<string>
  {
	[field: SerializeField]
	[Bind("Items"), IgnoreDataMember]
	public List<string> items { get; set; } = new List<string>();

	public float normalizedValue => (float)Index / items.Count;

	public int Index => items.IndexOf(value);

	public void InitFromEnum<T>(bool splitUppercase = true)
	{
	  this.items.Clear();

	  foreach (string s in System.Enum.GetNames(typeof(T)).ToList())
	  {
		string item = s;
		if (splitUppercase)
		  item = StringUtility.InsertSpaceBeforeUpperCase(s);

		this.items.Add(item);
	  }
	}
	public void InitFromList(IEnumerable<string> list)
	{
	  this.items.Clear();
	  this.items = list.ToList();
	}

	public BindableStringSelect() : base() { }
  }


  [System.Serializable, Draw(ControlType.TextField), DataContract]
  public class BindableInput : BindableBaseField<string>
  {
	public BindableInput() : base() { }
  }


  [System.Serializable, Draw(ControlType.MinMaxSlider), DataContract]
  public class BindableRange : BindableBaseField<Vector2>
  {
	[BindBaseField("Value")]
	[DataMember(Name = "Value")]
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ShowInInspector, Sirenix.OdinInspector.MinMaxSlider(0, 1, MinValueGetter = nameof(min), MaxValueGetter = nameof(max))]
#endif
	public override Vector2 value { get => base.value; set => base.value = value; }

	[Bind("Min"), DataMember(Name = "Min")]
	public float min;
	[Bind("Max"), DataMember(Name = "Max")]
	public float max;

	public float Min { get => min; set => min = value; }
	public float Max { get => max; set => max = value; }

	public BindableRange() : base()
	{
	  min = 0;
	  max = 1;
	  m_Value = new Vector2(0, 1);
	}

	protected float Normalize(float value, float min, float max)
	{
	  return Mathf.InverseLerp(min, max, value);
	}
  }

  public static class StringUtility
  {
	public static string InsertSpaceBeforeUpperCase(this string str)
	{
	  var sb = new StringBuilder();

	  char previousChar = char.MinValue; // Unicode '\0'

	  foreach (char c in str)
	  {
		if (char.IsUpper(c))
		{
		  // If not the first character and previous character is not a space, insert a space before uppercase

		  if (sb.Length != 0 && previousChar != ' ')
		  {
			sb.Append(' ');
		  }
		}

		sb.Append(c);

		previousChar = c;
	  }

	  return sb.ToString();
	}
  }
}


================================================
FILE: src/Core/Model/BindableObjects/BindableBaseField.cs.meta
================================================
fileFormatVersion: 2
guid: b7a28165c3f71c34e9b0eb23b27cb50d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Model/BindableObjects/BindableObject.cs
================================================

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UIElements;

#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#endif

namespace Graphene.ViewModel
{
  /// <summary>
  /// BindableObjects are the atomic data units that can be bound to VisualElements. They are used to author data in the inspector, or can be generated at runtime to decouple data from view logic.
  /// </summary>
  /// <example>Common use cases include buttons, labels, toggles, sliders etc.</example>
  [System.Serializable]
#if ODIN_INSPECTOR
  [Toggle("<isEnabled>k__BackingField")]
#endif
  public abstract class BindableObjectBase : IBindableToVisualElement
  {
#if ODIN_INSPECTOR
	[field: LabelText(SdfIconType.TypeStrikethrough)]
#endif
	[field: SerializeField, IgnoreDataMember, OnValueChanged(nameof(SetEnabled))] public bool isEnabled { get; set; } = true;
	public Action<bool> onSetEnabled { get; set; }

#if ODIN_INSPECTOR
	[field: LabelText(SdfIconType.Eye), OnValueChanged(nameof(SetShow))]
#endif
	[field: SerializeField, IgnoreDataMember] public bool isShown { get; set; } = true;
	public Action<bool> onShowHide { get; set; }

#if ODIN_INSPECTOR
	[field: LabelText(SdfIconType.Check), OnValueChanged(nameof(SetActive))]
#endif
	[field: SerializeField, IgnoreDataMember] public bool isActive2 { get; set; } = false;
	public Action<bool> onSetActive { get; set; }

	public VisualElement boundToElement { get; set; }
	public System.Action<VisualElement> onBindToElement;// { get; set; }

	public void SetBinding(VisualElement el)
	{
	  boundToElement = el;
	  onBindToElement?.Invoke(el);
	}

	[field: SerializeField] public string Tooltip { get; set; }

	void ToggleEnable() => SetEnabled(!isEnabled);
	void ToggleShow() => SetShow(!isShown);
	void ToggleActive() => SetActive(!isActive2);

	public void SetEnabled(bool enabled)
	{
	  isEnabled = enabled;
	  onSetEnabled?.Invoke(enabled);
	}

	public void SetShow(bool show)
	{
	  isShown = show;
	  onShowHide?.Invoke(show);
	}
	public void SetActive(bool active)
	{
	  isActive2 = active;
	  onSetActive?.Invoke(active);
	}

	public virtual void ResetCallbacks()
	{
	  onSetEnabled = null;
	  onShowHide = null;
	}
  }

  /// <summary>
  /// BindableObjects are the atomic data units that can be bound to VisualElements. They are used to author data in the inspector, or can be generated at runtime to decouple data from view logic.
  /// </summary>
  /// <example>Common use cases include buttons, labels, toggles, sliders etc.</example>
  // Atomic "Über" object for the view
  [System.Serializable, Draw(ControlType.Button)]
  public class BindableObject : BindableObjectBase, IRoute, ICustomControlType, ICustomAddClasses, ICustomName, IHasCustomVisualTreeAsset
  {
	[field: SerializeField]
	public ControlType ControlType { get; set; }

	[field: SerializeField]
	public VisualTreeAsset VisualTreeAsset { get; set; }

	[field: SerializeField]
	[Bind("Label", BindingMode.OneWay)]
	public string Name { get; set; }

	[field: SerializeField]
	[Bind("Value")]
	public string Value { get; set; }

	[field: SerializeField]
	[Route]
	public string route;

	[field: SerializeField]
	[BindTooltip("Description")]
	public string Description { get; set; }

	[field: SerializeField]
	[Bind("Image")]
	public Texture Image { get; set; }

	#region FoldoutAttribute
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.FoldoutGroup("Additionals")]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.Foldout("Additionals")]
#endif
	#endregion
	public string addClass; public string ClassesToAdd => addClass;

	#region FoldoutAttribute
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.FoldoutGroup("Additionals")]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.Foldout("Additionals")]
#endif
	#endregion
	public string customName; public string CustomName => customName;

	#region FoldoutAttribute
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.FoldoutGroup("Additionals")]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.Foldout("Additionals")]
#endif
	#endregion
	[Bind("")]
	public UnityEvent OnClick = new UnityEvent();

	#region Util
	public override string ToString()
	{
	  return $"{this.GetType().Name} - [{this.Name}]";
	}
	#endregion

	public BindableObject()
	{
	}

	public BindableObject(UnityAction callback) : this()
	{
	  OnClick.AddListener(callback);
	}
  }

  // Atomic "Über" object for the view
  [System.Serializable, Draw(ControlType.Button)]
  public class ContextBindableObject : BindableObject, IBindableInteractionType
  {
	[Bind("Content")]
	[field: SerializeField] public List<ContextBindableObject> Content { get; private set; }

	[Bind("HasContent")][field: SerializeField] public bool HasContent { get; private set; }

	[Bind("Actions")]
	[field: SerializeField]
	public List<ActionButton> Actions { get; set; }

	[Bind("HasActions")]
	public bool HasActions => Actions != null && Actions.Count > 0;


	[field: SerializeField]
	public InteractionMode InteractionType { get; set; }

	[field: SerializeField]
	public int Size { get; set; }

	public void AddAction(string name, Action callback, string tooltip = null)
	{
	  if (Actions == null)
		Actions = new List<ActionButton>();
	  var action = new ActionButton
	  {
		Label = name,
		Tooltip = tooltip,
		OnClick = callback
	  };
	  Actions.Add(action);
	}
  }

  [Draw(ControlType.Button)]
  [System.Serializable]
  public class ActionButton : IHasTooltip
  {
	[field: SerializeField]
	[Bind("Label")]
	public string Label { get; set; }

	[field: SerializeField]
	[Bind]
	public System.Action OnClick { get; set; }

	[field: SerializeField]	public string Tooltip { get; set; }

	[Bind("Enabled")]
	public bool Enabled => OnClick != null;
  }
}


================================================
FILE: src/Core/Model/BindableObjects/BindableObject.cs.meta
================================================
fileFormatVersion: 2
guid: 2a481b0795ebfad4c9771a06eb5677c0
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Model/BindableObjects/ListBindable.cs
================================================
using Sirenix.OdinInspector;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.ViewModel
{
  public interface IListViewBindable
  {
	IList ItemsSource { get; }
	ControlType ItemControlType { get; }
	CollectionVirtualizationMethod CollectionVirtualizationMethod { get; }
	SelectionType SelectionType { get; }
	bool ShowBorder { get; }
	string HeaderTitle { get; }
	bool ShowFoldoutHeader { get; }
	bool ShowAddRemoveFooter { get; }
	AlternatingRowBackground AlternatingRowBackground { get; }
	bool Reorderable { get; }
	ListViewReorderMode ReorderMode { get; }
	bool ShowCollectionSize { get; }

	void Apply(ListView el);

	bool ElementsPickable { get; }
  }

  public abstract class ListBindable : BindableObjectBase
  {
	[SerializeField] private ControlType controlType = ControlType.ListItem; public ControlType ItemControlType => controlType;
	public CollectionVirtualizationMethod collectionVirtualizationMethod = CollectionVirtualizationMethod.DynamicHeight; public CollectionVirtualizationMethod CollectionVirtualizationMethod => collectionVirtualizationMethod;

	[Range(0, 100)] public int height = 30;
	public SelectionType selectionType = SelectionType.Single; public SelectionType SelectionType => selectionType;
	public bool showBorder; public bool ShowBorder => showBorder;
	public string headerTitle; public string HeaderTitle => headerTitle;
	public bool showFoldoutHeader; public bool ShowFoldoutHeader => showFoldoutHeader;
	public bool showAddRemoveFooter; public bool ShowAddRemoveFooter => showAddRemoveFooter;
	public AlternatingRowBackground alternatingRowBackground; public AlternatingRowBackground AlternatingRowBackground => alternatingRowBackground;
	public bool reorderable; public bool Reorderable => reorderable;
	public ListViewReorderMode reorderMode; public ListViewReorderMode ReorderMode => reorderMode;
	public bool showCollectionSize; public bool ShowCollectionSize => showCollectionSize;
	public bool elementsPickable = true; public bool ElementsPickable => elementsPickable;

	// Bound element
	public ListView listView;

	[ResponsiveButtonGroup]
	public void Rebuild()
	{
	  if (listView == null)
		return;

	  Apply(listView);
	  listView.Rebuild();
	}

	public void Apply(ListView el)
	{
	  this.listView = el;
	  el.virtualizationMethod = collectionVirtualizationMethod;
	  el.fixedItemHeight = this.height;
	  el.selectionType = selectionType;
	  el.showBorder = showBorder;
	  el.headerTitle = headerTitle;
	  el.showFoldoutHeader = showFoldoutHeader;
	  el.showAddRemoveFooter = showAddRemoveFooter;
	  el.showAlternatingRowBackgrounds = alternatingRowBackground;
	  el.reorderable = reorderable;
	  el.reorderMode = reorderMode;
	  el.showBoundCollectionSize = showCollectionSize;
	}
  }

  [System.Serializable]
  [Draw(controlType = ControlType.ListView)]
  public class ListBindable<TObjectType> : ListBindable, IListViewBindable//, IList<TObjectType>
  {
	[Bind("Items")] public List<TObjectType> SourceItems = new List<TObjectType>();

	public IList ItemsSource => SourceItems;

	#region IList<T>
	public TObjectType this[int index] { get => SourceItems[index]; set => SourceItems[index] = value; }

	public int Count => SourceItems.Count;

	public bool IsReadOnly => false;

	public void Add(TObjectType item) => SourceItems.Add(item);

	public void Clear() => SourceItems.Clear();

	public bool Contains(TObjectType item) => SourceItems.Contains(item);

	public void CopyTo(TObjectType[] array, int arrayIndex) => SourceItems.CopyTo(array, arrayIndex);

	public IEnumerator<TObjectType> GetEnumerator() => SourceItems.GetEnumerator();

	public int IndexOf(TObjectType item) => SourceItems.IndexOf(item);

	public void Insert(int index, TObjectType item) => SourceItems.Insert(index, item);

	public bool Remove(TObjectType item) => SourceItems.Remove(item);

	public void RemoveAt(int index) => SourceItems.RemoveAt(index);

	//IEnumerator IEnumerable.GetEnumerator() => SourceItems.GetEnumerator();
	#endregion
  }
}


================================================
FILE: src/Core/Model/BindableObjects/ListBindable.cs.meta
================================================
fileFormatVersion: 2
guid: 90b16a7dd3d8c654693abccb70045774
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Model/BindableObjects.meta
================================================
fileFormatVersion: 2
guid: 21f4f86d9ed39a04dae5f8a10dc50541
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Model/GenericModelAsset.cs
================================================
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.ViewModel
{
  public abstract class ScriptableObjectModel<T> : ScriptableObjectModel
  {
    [Draw(ControlType.Button)]
    public List<T> model = new List<T>();
  }

  /// <summary>
  /// A generic model asset that can be used to author a list of BindableObject.
  /// </summary>
  [CreateAssetMenu(menuName = "Graphene/Model/GenericModelAsset")]
  public class GenericModelAsset : ScriptableObjectModel<BindableObject>
  {
    public override void Initialize(VisualElement container, Plate plate)
    {
    }
  }
}


================================================
FILE: src/Core/Model/GenericModelAsset.cs.meta
================================================
fileFormatVersion: 2
guid: 3c77b204580fbe947b11e389b5321ed7
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {fileID: 2800000, guid: 806f5574c9706cd4e812686596744160, type: 3}
  userData:
  assetBundleName:
  assetBundleVariant:


================================================
FILE: src/Core/Model/GenericModelBehaviour.cs
================================================
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.ViewModel
{
  public abstract class GenericModelBehaviour<T> : ViewModelComponent
  {
	public override bool HasContent => items?.Count > 0; 

	[Draw(ControlType.Button)]
    [SerializeField]
    protected List<T> items = new List<T>();

    public abstract List<T> Items { get; }
  }

  public class GenericModelBehaviour : GenericModelBehaviour<BindableObject>
  {
	[SerializeField] bool validateRouteAdresses = true;
	[SerializeField] bool hideInvalidAdress;
	protected StringRouter router;

	public override List<BindableObject> Items => items;

	public override void Inject(Graphene graphene)
	{
	  base.Inject(graphene);
	  if (graphene.Router is StringRouter stringRouter)
		router = stringRouter;
	}

	protected override void OnShow()
	{
	  base.OnShow();
	  ValidateAddresses();
	}

	void ValidateAddresses()
	{
	  if (router && validateRouteAdresses)
	  {
		foreach (var item in items)
		{
		  if (!string.IsNullOrEmpty(item.route))
		  {
			bool exists = router.ValidateAddress(item.route);
			item.SetEnabled(exists);			
			//item.isEnabled = exists;
			if (hideInvalidAdress)
			  item.SetShow(exists);
		  }
		}
	  }
	}

	//public override void Refresh(VisualElement container)
	//{
	//  if (router && validateRouteAdresses)
	//  {
	//	foreach (var item in items)
	//	{
	//	  if (!string.IsNullOrEmpty(item.route))
	//	  {
	//		bool exists = router.ValidateAddress(item.route);
	//		item.isEnabled = exists;
	//		if (hideInvalidAdress)
	//		  item.isShown = exists;
	//	  }
	//	}
	//  }

	//  base.Refresh(container);
	//}

	public override void Initialize(VisualElement container, Plate plate)
    {
	  ValidateAddresses();
    }
  }
}


================================================
FILE: src/Core/Model/GenericModelBehaviour.cs.meta
================================================
fileFormatVersion: 2
guid: 35cb04044c5eb594495aaeae5ccb11a2
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {fileID: 2800000, guid: 806f5574c9706cd4e812686596744160, type: 3}
  userData:
  assetBundleName:
  assetBundleVariant:


================================================
FILE: src/Core/Model/ScriptableObjectModel.cs
================================================

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene
{
  /// <summary>
  /// An IModel that is also a ScriptableObject, allowing it to be saved as an asset in Unity.
  /// </summary>
  public abstract class ScriptableObjectModel : ScriptableObject, IModel
  {
    [field: SerializeField][Bind("Title")] public string Title { get; set; } = "Title";
    [field: SerializeField][Bind("Render")] public bool Render { get; set; } = true;
    public Action onModelChange { get; set; }

    public event System.Action Redraw;

    //public abstract List<object> GetDrawableObjects() { }

    public abstract void Initialize(VisualElement container, Plate plate);

	public void Refresh(VisualElement container)
	{
	}


	#region ButtonAttribute
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.Button]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.Button]
#endif
    #endregion
    internal void ForceRedraw()
    {
      Redraw?.Invoke();
    }

    //public abstract void Render(UnityEngine.UIElements.VisualElement container, UIControlsTemplates templates);

    //[Button]
    //public abstract void OnSubmit();
    //[Button]
    //public abstract void OnCancel();
  }
}

================================================
FILE: src/Core/Model/ScriptableObjectModel.cs.meta
================================================
fileFormatVersion: 2
guid: 9c7aa560e9cd18a45baf58f91137a8cb
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {fileID: 2800000, guid: 806f5574c9706cd4e812686596744160, type: 3}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Model/ViewModel/FormViewModel.cs
================================================
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.ViewModel
{
  public interface IFormViewModel : IModel
  {
	bool IsModelDirty { get; }
	bool BlockRoutingOnDirty { get; set; }
	bool HideButtons { get; set; }

	bool PlateIsActive { get; }

	void Submit();
	void Cancel();
	void Reset();

	void PromptReset();

	public event System.Action onSubmit;
	public event System.Action onCancel;

	void UpdateFormButtonsState(bool enabled, bool active);
  }

  public abstract class FormViewModel : ViewModelComponent, IFormViewModel, IStateInterpreter<string>, IGrapheneInitializable
  {
	#region Bindables
	//[Bind("Title")] public override string Title => originalCached?.Title;

	public event System.Action onSubmit;
	public event System.Action onCancel;
	public event System.Action onReset;

	[Bind("Submit")]
	public BindableObject submitBinding =  new BindableObject();
	[Bind("Cancel")]
	public BindableObject cancelBinding =  new BindableObject();
	[Bind("Reset")]
	public BindableObject resetBinding = new BindableObject();

	bool initialized;

#if ODIN_INSPECTOR
	[field: ShowInInspector]
#endif
	public bool IsModelDirty { get; set; }
	[field: SerializeField] public bool BlockRoutingOnDirty { get; set; } = true;

	[field: SerializeField] public bool HideButtons { get; set; } = false;
	#endregion

	#region VisualElement
	Button submitButton;
	Button cancelButton;
	Button resetButton;
	#endregion

	Router<string> router;
	#region LifeCycle
	protected override void Awake()
	{
	  base.Awake();
	  //submitBinding = Submit;
	  //cancelBinding = Cancel;
	  submitBinding.OnClick.AddListener(Submit);
	  cancelBinding.OnClick.AddListener(Cancel);
	  resetBinding.OnClick.AddListener(Reset);
	  MarkDirty(false);
	}

	public virtual void Initialize()
	{
	  router = graphene.Router as Router<string>;
	  router.RegisterInterpreter(this);
	  initialized = true;
	}

	void OnEnable()
	{
	  if (!initialized)
		return;
	  router.RegisterInterpreter(this);
	  Subscribe();
	}

	void OnDisable()
	{
	  UnSubscribe();
	  graphene?.Router.UnregisterInterpreter(this);
	}
	bool subscribed;

	void Subscribe()
	{
	  if (subscribed)
		return;
	  subscribed = true;
	}
	void UnSubscribe()
	{
	  subscribed = false;
	}
	#endregion

	public bool TrySubmit()
	{
	  if (!enabled)
		return false;

	  Submit();
	  return true;
	}

	public bool TryCancel()
	{
	  Cancel();
	  return true;
	}

	public bool TryReset()
	{
	  Reset();
	  return true;
	}
	bool IStateInterpreter.CanCatch(object state) => TryCatch((string)state);
	public bool CanCatch(string state)
	{
	  if (!enabled || !gameObject.activeInHierarchy)
		return false;

	  if (state == "submit")
		return true;
	  else if (state == "cancel")
		return true;
	  else if (state == "reset")
		return true;
	  return false;
	}
	bool IStateInterpreter.TryCatch(object state) => TryCatch((string)state);

	public bool TryCatch(string state)
	{
	  if (!enabled || !gameObject.activeInHierarchy)
		return false;


	  if (state == "submit")
	  {
		TrySubmit();
		return true;
	  }
	  else if (state == "cancel")
	  {
		TryCancel();
		return true;
	  }
	  else if (state == "reset")
	  {
		TryReset();
		return true;
	  }

	  // Show confirmation dialog here
	  if (IsModelDirty)
		return true;
	  
	  return false;
	}


	[ResponsiveButtonGroup]
	public abstract void Cancel();
	[ResponsiveButtonGroup]
	public abstract void Submit();

	public abstract void Reset();
	public abstract void PromptReset();

	protected void MarkDirty(bool dirty)
	{
	  IsModelDirty = dirty;
	  SetButtonsDirty(dirty);

	  // Block router
	  if (BlockRoutingOnDirty && graphene?.Router)
	  {
		if (dirty)
		  graphene.Router.TryBlock(this);
		else
		  graphene.Router.TryUnblock(this);
	  }
	  ModelChange();
	}

	[Button]
	protected virtual void SetButtonsDirty(bool dirty)
	{
	  submitButton?.SetEnabled(dirty && CanSubmit());
	  cancelButton?.SetEnabled(dirty && CanCancel());
	  submitBinding?.SetEnabled(dirty && CanSubmit());
	  cancelBinding?.SetEnabled(dirty && CanCancel());


	  resetButton?.SetEnabled(CanReset());
	  resetBinding?.SetEnabled(CanReset());
	}
	public void UpdateFormButtonsState(bool enabled, bool active)
	{
	  SetButtonsDirty(enabled);
	  submitButton?.SetActive(active);
	  cancelButton?.SetActive(active);
	  submitBinding?.SetActive(active);
	  cancelBinding?.SetActive(active);


	  resetButton?.SetActive(active);
	  resetBinding?.SetActive(active);
	}

	public virtual bool CanSubmit() => true;
	public virtual bool CanCancel() => true;
	public virtual bool CanReset() => true;
  }

  public abstract class FormViewModel<T> : FormViewModel, ICustomDrawContext
  {
	[ShowInInspector] T originalCached;
	[System.NonSerialized, ShowInInspector, InlineEditor] public T viewModelCopy;
	object ICustomDrawContext.GetCustomDrawContext { get => viewModelCopy; }

	public abstract void UpdateSourceData();
  }
}

================================================
FILE: src/Core/Model/ViewModel/FormViewModel.cs.meta
================================================
fileFormatVersion: 2
guid: 4966129684538d749affd14e9fd70661
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Model/ViewModel/MultiFormViewModel.cs
================================================
using Sirenix.OdinInspector;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.ViewModel
{

  public class MultiFormViewModel : FormViewModel, IStateInterpreter, IFormViewModel
  {
	[SerializeField] GenericModelBehaviour buttonsViewModel;

#if ODIN_INSPECTOR
	[ShowInInspector]
#endif
	List<IFormViewModel> childForms;
	bool formsInitialized;

	#region LifeCycle
	public override void Initialize(VisualElement container, Plate plate)
	{
	  if (!formsInitialized)
	  {
		var forms = transform.GetComponentsInChildren<IFormViewModel>().ToList();
		forms.Remove(this);
		childForms = forms;
		foreach (var item in childForms)
		{
		  item.BlockRoutingOnDirty = false;
		  item.HideButtons = true;
		  item.UpdateFormButtonsState(false, false);
		}
		formsInitialized = true;
	  }

	  if (buttonsViewModel)
	  {
		buttonsViewModel.Items.Clear();
		buttonsViewModel.Items.Add(new BindableObject
		{
		  Name = "SUBMIT",
		  customName = "SubmitButton",
		  addClass = "submit",
		  route = "index"
		});
		buttonsViewModel.Items.Add(new BindableObject
		{
		  Name = "CANCEL",
		  customName = "CancelButton",
		  addClass = "return",
		  route = "index"
		});
		buttonsViewModel.Items.Add(new BindableObject
		{
		  Name = "RESET",
		  customName = "ResetButton",
		  addClass = "cancel",
		  //route = "index"
		});

		buttonsViewModel.Items[0].OnClick.AddListener(Submit);
		buttonsViewModel.Items[1].OnClick.AddListener(Cancel);
		buttonsViewModel.Items[2].OnClick.AddListener(Reset);
	  }
	}
	#endregion

	public override void Cancel()
	{
	  foreach (var form in childForms)
	  {
		if (form.IsModelDirty)
		  form.Cancel();
	  }
	}

	public override void Submit()
	{
	  foreach (var form in childForms)
	  {
		if (form.IsModelDirty)
		  form.Submit();
	  }
	}

	public override void Reset()
	{
	  foreach (var form in childForms)
	  {
		if (form.PlateIsActive)
		  form.PromptReset();
	  }
	}

	public override void PromptReset()
	{
	  throw new System.NotImplementedException();
	}

	protected override void SetButtonsDirty(bool dirty)
	{
	  if (buttonsViewModel && buttonsViewModel.Items.Count > 1)
	  {
		buttonsViewModel.Items[0].SetEnabled(dirty);
		buttonsViewModel.Items[1].SetEnabled(dirty);
	  }
	}

  }
}

================================================
FILE: src/Core/Model/ViewModel/MultiFormViewModel.cs.meta
================================================
fileFormatVersion: 2
guid: bf9529738e742e84fbf6e0d45ae2e2d8
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Model/ViewModel/NavViewModel.cs
================================================
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.ViewModel
{
  public class NavViewModel : GenericModelBehaviour
  {
	[Bind("HasContent")]
	public override bool HasContent => Routes != null && Routes.Count > 0 || base.HasContent;


	[field: SerializeField]
	public bool TitleFromRoutes { get; private set; }

	public enum RenderMode
	{
	  Manual,
	  Siblings,
	  SiblingsWithState
	}

	[field: SerializeField]
	public RenderMode renderMode { get; private set; } = NavViewModel.RenderMode.SiblingsWithState;

	[field: SerializeField] public Plate OverridePlate { get; private set; }

	[Bind("Routes")]
	public List<string> Routes = new List<string>();

	public override void Initialize(VisualElement container, Plate plate)
	{
	  switch (renderMode)
	  {
		case RenderMode.SiblingsWithState:
		  CreateBindableObjectsFromSiblingsWithState(OverridePlate ?? plate);
		  break;
	  }
	}

	public override void Inject(Graphene graphene)
	{
	  base.Inject(graphene);
	  if(router)
		router.onStateChange += Router_onStateChange;
	}
	private void Router_onStateChange(string newState)
	{
	  if (TitleFromRoutes)
	  {
		var index = Routes.IndexOf(newState);
		if (index >= 0)
		  Title = Routes[index].ToUpper();
		ModelChange();
	  }
	}
	void OnDestroy()
	{
	  if (router)
		router.onStateChange -= Router_onStateChange;
	}

	void CreateBindableObjectsFromSiblingsWithState(Plate plate)
	{
	  this.Routes.Clear();

	  IReadOnlyList<Plate> children = plate.Parent ? plate.Parent.Children : null;

	  if (children == null || children.Count == 0)
		return;

	  foreach (var sibling in children)
	  {
		if (!sibling || !(sibling.StateHandle is StringStateHandle stringStateHandle))
		  continue;

		if (stringStateHandle)
		{
		  Routes.Add(stringStateHandle.StateID);
		}
	  }
	}
  }
}

================================================
FILE: src/Core/Model/ViewModel/NavViewModel.cs.meta
================================================
fileFormatVersion: 2
guid: ddce112e23d338443b4d10a813ce4c25
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Model/ViewModel/ViewModelComponent.cs
================================================
using System;
using UnityEngine;
using UnityEngine.UIElements;

namespace Graphene.ViewModel
{
  /// <summary>
  /// A ViewModel is a component that implements IModel and is responsible for providing data to be rendered by a Renderer on a Plate.
  /// </summary>
  [RequireComponent(typeof(Renderer))]
  public abstract class ViewModelComponent : GrapheneComponent, IModel
  {
	[SerializeField, HideInInspector] protected new Renderer renderer; public Renderer Renderer => renderer;
	[SerializeField, HideInInspector] protected Plate plate; public Plate Plate => plate;

	[Bind("Title", BindingMode.OneWay)]
    [field: SerializeField] public virtual string Title { get; set; }

	[Bind("HasContent")]
	public virtual bool HasContent => Render;

	[field: SerializeField] public bool Render { get; set; } = true;
    public Action onModelChange { get; set; }

	public bool PlateIsActive => plate && plate.IsActive;

	protected override void Awake()
	{
	  base.Awake();
	  if (!this.plate)
		this.plate = GetComponent<Plate>();
	  if (!this.renderer)
		renderer = GetComponent<Renderer>();
	}

	public override void Inject(Graphene graphene)
	{
	  base.Inject(graphene);
	  if(!this.plate)
		this.plate = GetComponent<Plate>();
	  if(!this.renderer)
		renderer = GetComponent<Renderer>();

	  plate.onShow.AddListener(OnShow);
	  plate.onHide.AddListener(OnHide);
	}

	public abstract void Initialize(VisualElement container, Plate plate);

    // For enabled
    void Start()
    {
    }

	protected virtual void OnShow() { }
	protected virtual void OnHide() { }

#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ResponsiveButtonGroup]
#endif
	public virtual void ModelChange()
	{
	  onModelChange?.Invoke();
	}
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ResponsiveButtonGroup]
#endif
	public virtual void Refresh(VisualElement container)
	{
	}
  }
}

================================================
FILE: src/Core/Model/ViewModel/ViewModelComponent.cs.meta
================================================
fileFormatVersion: 2
guid: 94c3d559523a63c4298689c839b2109d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Model/ViewModel.meta
================================================
fileFormatVersion: 2
guid: c868cc3a0db70c940af6b51404f58456
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Model.meta
================================================
fileFormatVersion: 2
guid: d78566ea2cede254091b6cbfd364100d
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: src/Core/Plate.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UIElements;

#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#endif

namespace Graphene
{
  using Elements;
  using UnityEngine.Profiling;

  /// <summary>
  /// Determines the <see cref="Position"> mode for a plate when the hierarchy is built
  /// </summary>
  public enum PositionMode
  {
	/// <summary>
	/// Don't override the <see cref="Position"/> mode
	/// </summary>
	None,
	/// <summary>
	/// Sets the plate to <see cref="Position.Relative"/>
	/// </summary>
	Relative,
	/// <summary>
	/// Sets the plate to <see cref="Position.Absolute"/>
	/// </summary>
	Absolute
  }

  /// <summary>
  /// Determines how the binding system refreshes bindings on this plate
  /// </summary>
  public enum BindingRefreshMode
  {
	None,
	/// <summary>
	/// Bindings are refreshed every update of the BindingsManager.
	/// </summary>
	Continuous,
	/// <summary>
	/// Bindings only update when the model triggers its ModelChanged callback.
	/// </summary>
	ModelChange
  }

  /// <summary>
  /// Determines whether the plate shows/hides immediately or with a transition.
  /// </summary>
  public enum ShowHideMode
  {
	Immediate,
	Transition
  }
  ///<summary>
  /// <para>A `Plate` represents a view controller in the VisualTree, and is used when by Graphene to the hierarchy, its states and views.</para> 
  /// <para><see href="https://github.com/LudiKha/Graphene#plates">Read more in the online documentation</see></para>
  ///</summary>
  [DisallowMultipleComponent]
  public class Plate : GrapheneComponent, IGrapheneInitializable, IDisposable
  {
    #region Constants

    /// <summary>
    /// The default class name for a plate root element.
    /// </summary>
    public const string plateClassName = "plate";
    /// <summary>
    /// Selector for the content view.
    /// </summary>
    public const string contentViewSelector = "Content";
    /// <summary>
    /// Selector for the children view.
    /// </summary>
    public const string childViewSelector = "Children";
    #endregion

    #region Inspector/Authoring
    /// <summary>
    /// The VisualTreeAsset used to instantiate the plate's UI.
    /// </summary>
    [SerializeField, OnValueChanged(nameof(OnChangeDocument))]
    VisualTreeAsset visualAsset;
    /// <summary>
    /// Gets or sets the VisualTreeAsset for this plate.
    /// </summary>
    public VisualTreeAsset VisualTreeAsset { get => visualAsset; set => SetVisualTreeAsset(value); }

    [SerializeField, HideInInspector]
    VisualTreeAsset cachedAsset;

    /// <summary>
    /// Determines how picking is handled for the root element.
    /// </summary>
    [SerializeField]
    PickingMode pickingMode = PickingMode.Position;

    /// <summary>
    /// Controls how bindings are refreshed.
    /// </summary>
    [SerializeField]
    public BindingRefreshMode bindingRefreshMode = BindingRefreshMode.ModelChange;

    /// <summary>
    /// Inline style overrides for the plate.
    /// </summary>
    [SerializeField, FoldoutGroup("Styles Overrides")]
    InlineStyleOverrides styleOverrides = new InlineStyleOverrides() { positionMode = PositionMode.Relative };

    /// <summary>
    /// List of style overrides for individual views.
    /// </summary>
    [SerializeField, FoldoutGroup("Styles Overrides"), ListDrawerSettings(HideAddButton = true, HideRemoveButton = true, ListElementLabelName = "Id")]
    List<SerializedView> viewStyleOverrides = new List<SerializedView>();
    #endregion

    #region State
    /// <summary>
    /// Indicates if the plate was changed this frame.
    /// </summary>
    internal bool wasChangedThisFrame;

    bool isActive = true;
    /// <summary>
    /// Gets whether the plate is currently active and enabled in the hierarchy.
    /// </summary>
    public bool IsActive => isActive && enabled && gameObject.activeInHierarchy;
    #endregion

    #region Properties
    /// <summary>
    /// Returns true if this plate is the root plate (has no parent).
    /// </summary>
    public bool IsRootPlate => !parent;

    /// <summary>
    /// Returns true if this plate requires views to be rendered.
    /// </summary>
    public bool RequiresViews => children.Count > 0 || renderer != null;

    /// <summary>
    /// Returns true if the plate requires a rebuild of its views.
    /// </summary>
    public bool RequiresRebuild => cachedAsset != visualAsset || viewIds.Count != viewStyleOverrides.Count;
    #endregion

    #region Component Reference
    [ShowInInspector]
    Plate parent;
    /// <summary>
    /// Gets the parent plate, if any.
    /// </summary>
    public Plate Parent => parent;

    [ShowInInspector]
    List<Plate> children = new List<Plate>();
    /// <summary>
    /// Gets the child plates of this plate.
    /// </summary>
    public IReadOnlyList<Plate> Children => children;

    /// <summary>
    /// List of view IDs in the template.
    /// </summary>
    [SerializeField, ReadOnly]
    public List<string> viewIds = new List<string>();

    /// <summary>
    /// Reference to the default view.
    /// </summary>
    [SerializeField]
    public ViewRef defaultViewRef = new ViewRef(childViewSelector);

    /// <summary>
    /// Reference to the content view.
    /// </summary>
    [SerializeField]
    public ViewRef contentViewRef = new ViewRef(contentViewSelector);

    /// <summary>
    /// Reference to the view to attach to in the parent plate.
    /// </summary>
    [SerializeField]
    public ViewRef attachToParentView = new ViewRef("");

    /// <summary>
    /// The router associated with this plate.
    /// </summary>
    [SerializeField]
    protected Router router;
    public Router Router => router;

    /// <summary>
    /// The state handle associated with this plate.
    /// </summary>
    [SerializeField]
    protected StateHandle stateHandle;
    public StateHandle StateHandle => stateHandle;

    /// <summary>
    /// The renderer associated with this plate.
    /// </summary>
    [SerializeField]
    new protected Renderer renderer;
    public Renderer Renderer => renderer;
    #endregion

    #region VisualElements Reference
    private TemplateContainer clone;
    /// <summary>
    /// The root visual element of this plate.
    /// </summary>
    public VisualElement Root { get; private set; }

    /// <summary>
    /// Main container for attached renderer's output of (repeat) elements.
    /// </summary>
    public VisualElement ContentContainer => contentViewRef.view;

    /// <summary>
    /// The default view. This controller's children will be added to this by default.
    /// </summary>
    View defaultView => defaultViewRef.view;

    /// <summary>
    /// Dictionary of views in the template, keyed by ID.
    /// </summary>
    Dictionary<string, View> views = new Dictionary<string, View>();

    /// <summary>
    /// Tracks which child plates are attached to which views.
    /// </summary>
    Dictionary<View, List<Plate>> childAttachments = new Dictionary<View, List<Plate>>();
    #endregion

    #region (Unity) Events
    /// <summary>
    /// Invoked when the plate's state is evaluated.
    /// </summary>
    public event System.Action onEvaluateState;
    /// <summary>
    /// Invoked when static content is refreshed.
    /// </summary>
    public event System.Action onRefreshStatic;
    /// <summary>
    /// Invoked when dynamic content is refreshed.
    /// </summary>
    public event System.Action onRefreshDynamic;
    /// <summary>
    /// Invoked when the visual tree is refreshed.
    /// </summary>
    public event System.Action onRefreshVisualTree;

    /// <summary>
    /// Unity event invoked when the plate is shown.
    /// </summary>
    public UnityEvent onShow = new UnityEvent();
    /// <summary>
    /// Unity event invoked when the plate is hidden.
    /// </summary>
    public UnityEvent onHide = new UnityEvent();
    #endregion

    /// <summary>
    /// Gets or sets whether the plate has been initialized.
    /// </summary>
    public bool Initialized { get; set; }
    bool registeredToParent;

    /// <summary>
    /// Initializes the plate, setting up references and parent-child relationships.
    /// </summary>
    public virtual void Initialize()
    {
      GetLocalReferences();

      if (parent && !registeredToParent)
      {
        parent.onShow.AddListener(Parent_OnShow);
        parent.onHide.AddListener(Parent_OnHide);
        registeredToParent = true;
      }
    }

    /// <summary>
    /// Called when the component awakens. Clears events and child list.
    /// </summary>
    protected override void Awake()
    {
      base.Awake();
      // Clear events
      onRefreshDynamic = null;
      onRefreshStatic = null;
      onRefreshVisualTree = null;
      onShow.RemoveAllListeners();
      onHide.RemoveAllListeners();
      children.Clear();
    }

    /// <summary>
    /// Gets local component references and registers with parent plate if applicable.
    /// </summary>
    protected virtual void GetLocalReferences()
    {
      if (graphene)
      {
        router ??= graphene.Router;
      }
      //customView ??= GetComponent<ViewHandle>();

      stateHandle ??= GetComponent<StateHandle>();
      renderer ??= GetComponent<Renderer>();

      // Get nearest parent
      if ((Application.isPlaying && parent) || (parent = transform.parent?.GetComponentInParent<Plate>(true))) 
          parent.RegisterChild(this);
    }

    /// <summary>
    /// Constructs the visual tree for this plate, instantiating views and applying styles.
    /// </summary>
    internal void ConstructVisualTree()
    {
      Profiler.BeginSample("Graphene Plate Construct VisualTree", this);
      Root?.Clear();

      clone = visualAsset.CloneTree();
	  Root = clone.Children().First();

#if UNITY_ASSERTIONS
      Debug.Assert(clone != null, this);
      Debug.Assert(Root != null, this);
      Debug.Assert(clone.childCount == 1, $"{nameof(Plate)} {nameof(TemplateContainer)} must have exactly 1 child {nameof(VisualElement)}", this);
      //Assert.IsNotNull(RootPlateEl);
#endif

      Root.pickingMode = pickingMode;

      if(pickingMode == PickingMode.Ignore)
        Root.Query().ForEach(t => t.pickingMode = PickingMode.Ignore);

	  if (RequiresRebuild)
		EditModeCacheViewIds();

	  // Get views
	  InitViewsRuntime();

      RefreshClassesAndStyles();

      Root.AddToClassList(plateClassName);

      Initialized = true;
      onRefreshVisualTree?.Invoke();

      Root.RegisterCallback<MouseOverEvent>((evt) => ChangeEvent());
      Root.RegisterCallback<PointerCaptureEvent>((evt) => ChangeEvent());
      Root.RegisterCallback<PointerMoveEvent>((evt) => ChangeEvent());
      Root.RegisterCallback<PointerDownEvent>((evt) => ChangeEvent());
      Root.RegisterCallback<PointerUpEvent>((evt) => ChangeEvent());

      if (IsRootPlate)
      {
        graphene.GrapheneRoot.Add(Root);
        Root.AddToClassList("unity-ui-document__child");
      }

	  // Hide on start
	  if (styleOverrides.showHideMode == ShowHideMode.Transition)
		Root.FadeOut();

	  // Fadeout events
	  //Root.RegisterCallback<TransitionStartEvent>(Root_StartTransition);

	  Profiler.EndSample();
    }

    void Root_StartTransition(TransitionStartEvent evt)
    {
      //Debug.Log($"Start transition {evt.target}");
    }
    void Root_EndTransition(TransitionEndEvent evt)
	{
	  //Debug.Log($"End transition {evt.target}");
	  if (evt.target != Root)
        return;

      ApplyActiveState();
	  Root.UnregisterCallback<TransitionEndEvent>(Root_EndTransition);

	  //if (!isActive || Root.ClassListContains(VisualElementExtensions.fadeoutUssClassName))
	  //{

	  //}
	  //else
	  //  Show();
	}

	void ChangeEvent()
    {
      wasChangedThisFrame = true;
    }

    protected void RegisterChild(Plate child)
    {
      if (!children.Contains(child))
        children.Add(child);
    }

    #region ButtonAttribute
#if ODIN_INSPECTOR
    [Sirenix.OdinInspector.ResponsiveButtonGroup("ShowHide/Actions"), FoldoutGroup("ShowHide")]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.Button]
#endif
    #endregion
    protected virtual void Clear()
    {
      // Clear the dynamic content
      ContentContainer?.Clear();
    }

    public void RefreshContentContainer()
    {
      DetachChildPlates(contentViewRef.view);
      Clear();
      ReattachChildPlates(contentViewRef.view);
    }

	#region ButtonAttribute
#if ODIN_INSPECTOR
	[Sirenix.OdinInspector.ResponsiveButtonGroup("ShowHide/Actions"), FoldoutGroup("ShowHide")]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.Button]
#endif
    #endregion
    internal virtual void RenderAndComposeChildren()
    {
      Profiler.BeginSample("RenderAndComposeChildren", this);
      // Detach the children so they don't get bound to the scope
      DetachChildPlates();
      Clear();

      onRefreshStatic?.Invoke();

      // (Re)attach & compose the tree
      AttachChildPlates();

      onRefreshDynamic?.Invoke();
      Profiler.EndSample();
    }

    // UIDocument removes the root OnDisable, so we only need OnEnable
    private void OnEnable()
    {
      if (!Initialized)
        return;
      Show();
      //ConstructVisualTree();
      //RenderAndComposeChildren();
      //ReevaluateState();
    }

    private void OnDisable()
    {
      if (!Initialized)
        return;
      Hide();
    }

    void InitViewsRuntime()
    {
      if (Root == null)
        return;

      var views = Root.Query<View>().ToList();
      this.views.Clear();
      View resolvedDefaultView = null;
      foreach (var view in views)
      {
        this.views.Add(view.id, view);
        if (view.isDefault || (resolvedDefaultView == null))
		  resolvedDefaultView = view;
      }

      defaultViewRef.ResolveView(this);

      if (resolvedDefaultView == null)
		resolvedDefaultView = views.FirstOrDefault();

      if (!defaultViewRef.initialized)
        defaultViewRef.view = resolvedDefaultView;

      if (!defaultViewRef.initialized)
      {
#if UNITY_ASSERTIONS
        if(children.Count > 0 || renderer != null)
          Debug.LogWarning($"No default view {defaultViewRef.Id}", this);
#endif
      }

	  contentViewRef.ResolveView(this);

      if (parent != null)
        attachToParentView.ResolveView(parent);
    }

    void EditModeCacheViewIds()
    {
      // Playing & already initialized
      if (Root != null)
        return;

      var el = Root != null ? Root : this.visualAsset.CloneTree();
      viewIds.Clear();
      el.Query<View>().ForEach(v => viewIds.Add(v.id));

      // Sync Ids
      if (this.viewStyleOverrides.Count != viewIds.Count)
      {
        this.viewStyleOverrides = new List<SerializedView>();
        foreach (var view in viewIds)
          this.viewStyleOverrides.Add(new SerializedView(view));
	  }
    }

    void SetVisualTreeAsset(VisualTreeAsset asset)
    {
      if(this.visualAsset == asset) 
        return;
      this.visualAsset = asset;
      OnChangeDocument();
	}

    void OnChangeDocument()
    {
	  UpdateViewPlates();
      RefreshClassesAndStyles();
    }

    void UpdateViewPlates()
    {
	  EditModeCacheViewIds();

	  defaultViewRef.SetPlate(this);
      contentViewRef.SetPlate(this);

	  if (parent != null)
		attachToParentView.SetPlate(parent);
	  else
		attachToParentView.NoParent();

	}

    #region ButtonAttribute
#if ODIN_INSPECTOR
    [Sirenix.OdinInspector.ResponsiveButtonGroup("ShowHide/Actions"), FoldoutGroup("ShowHide")]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.Button]
#endif
    #endregion
    public void Show()
    {
      if (!Initialized)
        return;

      if (isActive) return;

      if (canShow != null && !canShow.Invoke())
        return;

      // Cannot show
      if (transform.parent?.gameObject.activeInHierarchy == false)
        return;

      SetActive(true);
      ApplyActiveState(); // Immediately activate GO

      // Enable
      if (styleOverrides.showHideMode == ShowHideMode.Transition)
        Root.FadeIn();
    }

    #region ButtonAttribute
#if ODIN_INSPECTOR
    [Sirenix.OdinInspector.ResponsiveButtonGroup("ShowHide/Actions"), FoldoutGroup("ShowHide")]
#elif NAUGHTY_ATTRIBUTES
    [NaughtyAttributes.Button]
#endif
    #endregion
    public void Hide()
    {
      if (!Initialized)
        return;

      if (!isActive)
        return;

      SetActive(false);

      if (styleOverrides.showHideMode == ShowHideMode.Immediate)
        ApplyActiveState();
      else
      {
		Root.RegisterCallback<TransitionEndEvent>(Root_EndTransition);
		Root.FadeOut();
      }
    }

    internal void HideImmediately()
    {
      if (!Initialized)
        return;
      SetActive(false);
      ApplyActiveState();
    }

    void SetActive(bool active)
    {
      // Not changed
      if (this.isActive == active)
        return;

      this.isActive = active;
    }

    void ApplyActiveState()
    {
      gameObject.SetActive(isActive);
      RefreshClassesAndStyles();

      if (Root != null)
      {
        if (isActive)
        {
          Root.Show();
          //ContentContainer?.Focus();
          onShow?.Invoke();
          ChangeEvent();
        }
        else
        {
          Root.Hide();
          onHide?.Invoke();
        }
      }

#if UNITY_EDITOR
      if (Application.isPlaying)
      {
        //gameObject.SetActive(IsActive);

        gameObject.name = gameObject.name.Trim('*');
        if (isActive)
          gameObject.name = gameObject.name + "*";
      }
#endif
    }

    internal void ReevaluateState()
    {
      if (!Initialized)
        return;

      if (!stateHandle)
      {
        if(!parent || parent.isActive)
          Show();
      }

      onEvaluateState?.Invoke();
    }

    public Func<bool> canShow;
    void Parent_OnShow()
    {
      if (!stateHandle)
        Show();
    }

    void Parent_OnHide()
    {
      if (!stateHandle)
        Hide();
    }

    VisualElement temp;
	internal void Detach()
    {
      if(temp == null)
        temp = new VisualElement();
      temp.Add(Root);
    }

	protected virtual void DetachChildPlates()
	{
	  foreach (var child in children)
	  {
		if (child)
		  child.Detach();
	  }
	}
	protected virtual void DetachChildPlates(View view)
	{
      if(view == null)
        return;

	  if (childAttachments.TryGetValue(view, out var children))
	  {
        foreach (var child in children)
		  child.Detach();
	  }
	}

	protected virtual void ReattachChildPlates(View view)
	{
	  if (view == null)
		return;
	  if (childAttachments.TryGetValue(view, out var children))
	  {
		foreach (var child in children)
          InternalAttach(view, child);
	  }
	}

	/// <summary>
	/// Attaches child plates into designated view(s)
	/// </summary>
	void AttachChildPlates()
    {
      // Prolly unnecessary and will prevent dynamic child attackments
      if (childAttachments.Count > 0)
        ReattachChildren();

      // Rebuild from afresh
      childAttachments.Clear();

	  foreach (var child in children)
      {
        // Child can have optional view override
        if (child.attachToParentView)
        {
          var customView = GetViewById(child.attachToParentView.Id);
		  AttachChild(customView, child);

		  //customView.Add(child.Root);
        }
        else
        {
		  // By default we attach children to default view
		  AttachChild(defaultView, child);
		  //defaultView.Add(child.Root);
        }
      }
    }

    void ReattachChildren()
    {
      foreach (var kvp in childAttachments)
      {
        var view = kvp.Key;
        var children = kvp.Value;
        foreach (var child in children)
        {
          InternalAttach(view, child);
        }
      }
    }

    void AttachChild(View view, Plate child)
    {
      if(childAttachments.TryGetValue(view, o
Download .txt
gitextract_6hvvmno2/

├── .github/
│   └── FUNDING.yml
├── LICENSE
├── README.md
├── docs/
│   ├── About.md
│   ├── _config.yml
│   └── howto.md
└── src/
    ├── Core/
    │   ├── Binding/
    │   │   ├── Binder.cs
    │   │   ├── Binder.cs.meta
    │   │   ├── Binding.cs
    │   │   ├── Binding.cs.meta
    │   │   ├── BindingAttribute.cs
    │   │   ├── BindingAttribute.cs.meta
    │   │   ├── BindingsManager.cs
    │   │   ├── BindingsManager.cs.meta
    │   │   ├── CollectionBinding.cs
    │   │   ├── CollectionBinding.cs.meta
    │   │   ├── MemberBinding.cs
    │   │   └── MemberBinding.cs.meta
    │   ├── Binding.meta
    │   ├── Extensions/
    │   │   ├── ButtonGroup.cs
    │   │   ├── ButtonGroup.cs.meta
    │   │   ├── CycleField.cs
    │   │   ├── CycleField.cs.meta
    │   │   ├── Dialog.cs
    │   │   ├── Dialog.cs.meta
    │   │   ├── GrapheneRoot.cs
    │   │   ├── GrapheneRoot.cs.meta
    │   │   ├── If.cs
    │   │   ├── If.cs.meta
    │   │   ├── Route.cs
    │   │   ├── Route.cs.meta
    │   │   ├── SelectField.cs
    │   │   ├── SelectField.cs.meta
    │   │   ├── TemplateTypes/
    │   │   │   ├── Button.cs
    │   │   │   ├── Button.cs.meta
    │   │   │   ├── TemplateRef.cs
    │   │   │   └── TemplateRef.cs.meta
    │   │   ├── TemplateTypes.meta
    │   │   ├── View.cs
    │   │   ├── View.cs.meta
    │   │   ├── VisualElementExtensions.cs
    │   │   └── VisualElementExtensions.cs.meta
    │   ├── Extensions.meta
    │   ├── Graphene.cs
    │   ├── Graphene.cs.meta
    │   ├── GrapheneComponent.cs
    │   ├── GrapheneComponent.cs.meta
    │   ├── Injector.cs
    │   ├── Injector.cs.meta
    │   ├── Interfaces.cs
    │   ├── Interfaces.cs.meta
    │   ├── Model/
    │   │   ├── BindableObjects/
    │   │   │   ├── BindableBaseField.cs
    │   │   │   ├── BindableBaseField.cs.meta
    │   │   │   ├── BindableObject.cs
    │   │   │   ├── BindableObject.cs.meta
    │   │   │   ├── ListBindable.cs
    │   │   │   └── ListBindable.cs.meta
    │   │   ├── BindableObjects.meta
    │   │   ├── GenericModelAsset.cs
    │   │   ├── GenericModelAsset.cs.meta
    │   │   ├── GenericModelBehaviour.cs
    │   │   ├── GenericModelBehaviour.cs.meta
    │   │   ├── ScriptableObjectModel.cs
    │   │   ├── ScriptableObjectModel.cs.meta
    │   │   ├── ViewModel/
    │   │   │   ├── FormViewModel.cs
    │   │   │   ├── FormViewModel.cs.meta
    │   │   │   ├── MultiFormViewModel.cs
    │   │   │   ├── MultiFormViewModel.cs.meta
    │   │   │   ├── NavViewModel.cs
    │   │   │   ├── NavViewModel.cs.meta
    │   │   │   ├── ViewModelComponent.cs
    │   │   │   └── ViewModelComponent.cs.meta
    │   │   └── ViewModel.meta
    │   ├── Model.meta
    │   ├── Plate.cs
    │   ├── Plate.cs.meta
    │   ├── Rendering/
    │   │   ├── RenderUtils.cs
    │   │   ├── RenderUtils.cs.meta
    │   │   ├── Renderer.cs
    │   │   └── Renderer.cs.meta
    │   ├── Rendering.meta
    │   ├── Routing/
    │   │   ├── EnableOnState.cs
    │   │   ├── EnableOnState.cs.meta
    │   │   ├── Interpreters/
    │   │   │   ├── ApplicationStateInterpreter.cs
    │   │   │   ├── ApplicationStateInterpreter.cs.meta
    │   │   │   ├── NavigationStateHandler.cs
    │   │   │   ├── NavigationStateHandler.cs.meta
    │   │   │   ├── StateInterpreter.cs
    │   │   │   └── StateInterpreter.cs.meta
    │   │   ├── Interpreters.meta
    │   │   ├── Router.cs
    │   │   ├── Router.cs.meta
    │   │   ├── StateHandle.cs
    │   │   ├── StateHandle.cs.meta
    │   │   ├── StringEnableOnState.cs
    │   │   ├── StringEnableOnState.cs.meta
    │   │   ├── StringRouter.cs
    │   │   ├── StringRouter.cs.meta
    │   │   ├── StringStateHandle.cs
    │   │   └── StringStateHandle.cs.meta
    │   ├── Routing.meta
    │   ├── Styling/
    │   │   ├── AlignItemsOverride.cs
    │   │   ├── AlignItemsOverride.cs.meta
    │   │   ├── FlexDirectionOverride.cs
    │   │   ├── FlexDirectionOverride.cs.meta
    │   │   ├── InlineStyleOverrides.cs
    │   │   ├── InlineStyleOverrides.cs.meta
    │   │   ├── JustifyOverride.cs
    │   │   ├── JustifyOverride.cs.meta
    │   │   ├── StyleOverride.cs
    │   │   ├── StyleOverride.cs.meta
    │   │   ├── WrapOverride.cs
    │   │   └── WrapOverride.cs.meta
    │   ├── Styling.meta
    │   ├── Templating/
    │   │   ├── TemplatePreset.cs
    │   │   └── TemplatePreset.cs.meta
    │   ├── Templating.meta
    │   ├── View/
    │   │   ├── SerializedView.cs
    │   │   ├── SerializedView.cs.meta
    │   │   ├── ViewHandle.cs
    │   │   └── ViewHandle.cs.meta
    │   └── View.meta
    ├── Core.meta
    ├── Editor/
    │   ├── CustomDictionaryPropertyDrawers.cs
    │   ├── CustomDictionaryPropertyDrawers.cs.meta
    │   ├── Graphene.Editor.asmdef
    │   ├── Graphene.Editor.asmdef.meta
    │   ├── GrapheneEditorUtilities.cs
    │   ├── GrapheneEditorUtilities.cs.meta
    │   ├── ViewSelectorStringDrawer.cs
    │   └── ViewSelectorStringDrawer.cs.meta
    ├── Editor.meta
    ├── Graphene.Core.asmdef
    ├── Graphene.Core.asmdef.meta
    ├── Lib/
    │   ├── DragManipulator/
    │   │   ├── DragManipulator.cs
    │   │   └── DragManipulator.cs.meta
    │   ├── DragManipulator.meta
    │   ├── SerializableDictionary/
    │   │   ├── Editor/
    │   │   │   ├── SerializableDictionary.Editor.asmdef
    │   │   │   ├── SerializableDictionary.Editor.asmdef.meta
    │   │   │   ├── SerializableDictionaryPropertyDrawer.cs
    │   │   │   └── SerializableDictionaryPropertyDrawer.cs.meta
    │   │   ├── Editor.meta
    │   │   ├── SerializableDictionary.Runtime.asmdef
    │   │   ├── SerializableDictionary.Runtime.asmdef.meta
    │   │   ├── SerializableDictionary.cs
    │   │   └── SerializableDictionary.cs.meta
    │   └── SerializableDictionary.meta
    ├── Lib.meta
    ├── Resources/
    │   ├── Icons/
    │   │   ├── atom.png.meta
    │   │   ├── form.png.meta
    │   │   ├── graphene.png.meta
    │   │   ├── injector.png.meta
    │   │   ├── layout.png.meta
    │   │   ├── molecule.png.meta
    │   │   ├── plate.png.meta
    │   │   ├── quantum.png.meta
    │   │   ├── renderer.png.meta
    │   │   ├── router.png.meta
    │   │   ├── state.png.meta
    │   │   ├── template.png.meta
    │   │   └── theme.png.meta
    │   ├── Icons.meta
    │   ├── Logo/
    │   │   ├── graphene-logo-full.png.meta
    │   │   ├── graphene-logo-white.png.meta
    │   │   └── graphene-logo.png.meta
    │   └── Logo.meta
    ├── Resources.meta
    ├── package.json
    └── package.json.meta
Download .txt
SYMBOL INDEX (732 symbols across 57 files)

FILE: src/Core/Binding/Binder.cs
  type IRoute (line 14) | public interface IRoute
  class Binder (line 22) | public static class Binder
    method InternalInstantiate (line 24) | internal static VisualElement InternalInstantiate(VisualTreeAsset temp...
    method Instantiate (line 36) | public static VisualElement Instantiate(in object context, VisualTreeA...
    method InstantiatePrimitive (line 65) | public static VisualElement InstantiatePrimitive(in object context, re...
    method BindRecursive (line 91) | public static void BindRecursive(VisualElement element, object context...
    method BindChildren (line 128) | static void BindChildren(VisualElement element, object context, List<V...
    method BindElementValues (line 149) | private static void BindElementValues<V>(V el, ref object context, Lis...
    method BindTextElement (line 199) | private static void BindTextElement(TextElement el, ref object context...
    method BindLabel (line 210) | private static void BindLabel(Label el, ref object context, List<Value...
    method BindButton (line 223) | private static void BindButton(Button el, ref object context, List<Val...
    method BindRoute (line 267) | internal static void BindRoute(Route el, ref object context, Plate plate)
    method BindSlider (line 295) | private static void BindSlider(Slider el, ref object context, List<Val...
    method BindSlider (line 324) | private static void BindSlider(SliderInt el, ref object context, List<...
    method BindMinMaxSlider (line 356) | private static void BindMinMaxSlider(MinMaxSlider el, ref object conte...
    method BindProgress (line 383) | private static void BindProgress(AbstractProgressBar el, ref object co...
    method BindTextField (line 409) | private static void BindTextField(TextField el, ref object context, Li...
    method BindNotifyValueChange (line 433) | private static (TValueType value, string label) BindNotifyValueChange<...
    method BindBaseField (line 487) | private static void BindBaseField<TValueType>(BaseField<TValueType> el...
    method BindDropdownField (line 493) | private static void BindDropdownField(DropdownField el, ref object con...
    method BindSelectField (line 527) | private static void BindSelectField(SelectField el, ref object context...
    method BindListView (line 544) | private static void BindListView(ListView el, ref object context, List...
    method BindListView (line 575) | internal static void BindListView(ListView el, in object context, Plat...
    method InternalBindListView (line 583) | internal static void InternalBindListView(ListView el, in object conte...
    method BindCycleField (line 616) | private static void BindCycleField(CycleField el, ref object context, ...
    method BindIf (line 633) | private static void BindIf(If el, ref object context, List<ValueWithAt...
    method BindImage (line 648) | private static void BindImage(Image el, ref object context, List<Value...
    method BindFoldout (line 671) | private static void BindFoldout(Foldout el, ref object context, List<V...
    method BindButtonGroup (line 700) | private static void BindButtonGroup(ButtonGroup el, ref object context...
    method BindText (line 731) | private static void BindText(TextElement el, ref object context, in Va...
    method BindClick (line 739) | private static void BindClick(Button el, System.Action action, in obje...
    method BindClick (line 745) | private static void BindClick(Button el, UnityEngine.Events.UnityEvent...
    method BindCallbacks (line 751) | [System.Obsolete("Use IBindableToVisualElement and apply in bindable o...
    method TryBranch (line 779) | private static bool TryBranch(BindableElement el, object data, Plate o...
    method DrillDownToChildScopeRecursive (line 798) | private static bool DrillDownToChildScopeRecursive(BindableElement el,...
    method BindingPathMatch (line 856) | internal static bool BindingPathMatch(in string a, in string b)
    method BindingPathMatch (line 860) | internal static bool BindingPathMatch(BindableElement el, in ValueWith...
    method BindingPathOrTypeMatch (line 864) | internal static bool BindingPathOrTypeMatch<T>(BindableElement el, in ...
    method BindingPathOrTypeMatch (line 868) | internal static bool BindingPathOrTypeMatch<T>(in string path, in Valu...
    method BindingPathAndTypeMatch (line 872) | internal static bool BindingPathAndTypeMatch<T>(in BindableElement el,...
    method BindingPathAndTypeMatch (line 876) | internal static bool BindingPathAndTypeMatch<T>(in string a, in ValueW...
    method ObjectToString (line 880) | internal static string ObjectToString(in object obj, in Type t)

FILE: src/Core/Binding/Binding.cs
  class Binding (line 16) | public abstract class Binding : IDisposable, IBinding
    method Dispose (line 19) | public virtual void Dispose()
    method PreUpdate (line 23) | public abstract void PreUpdate();
    method Release (line 25) | public abstract void Release();
    method Update (line 27) | public abstract void Update();
    method Binding (line 42) | public Binding(BindableElement el, in object context, in ValueWithAttr...
    method DetermineBindingMode (line 57) | void DetermineBindingMode()
    method RegisterEvents (line 80) | void RegisterEvents()
    method OnDetach (line 105) | void OnDetach(DetachFromPanelEvent evt) => UnregisterEvents();
    method UnregisterEvents (line 107) | void UnregisterEvents()
    method SyncVisualElementToModel (line 117) | void SyncVisualElementToModel()
    method Model_PropertyChanged (line 122) | protected virtual void Model_PropertyChanged(object sender, PropertyCh...
    method Dispose (line 126) | public override void Dispose()
    method PreUpdate (line 131) | public override void PreUpdate()
    method Release (line 136) | public override void Release()
    method Update (line 141) | public override void Update()
    method UpdateFromModel (line 155) | protected virtual void UpdateFromModel(in T newValue)
    method RegisterTwoWayValueChangeCallback (line 175) | void RegisterTwoWayValueChangeCallback()
    method IsValidBinding (line 189) | protected abstract bool IsValidBinding();
    method GetValueFromMemberInfo (line 190) | protected abstract T GetValueFromMemberInfo();
    method SetValueFromMemberInfo (line 191) | protected abstract void SetValueFromMemberInfo(T value);
  class Binding (line 29) | public abstract class Binding<T> : Binding
    method Dispose (line 19) | public virtual void Dispose()
    method PreUpdate (line 23) | public abstract void PreUpdate();
    method Release (line 25) | public abstract void Release();
    method Update (line 27) | public abstract void Update();
    method Binding (line 42) | public Binding(BindableElement el, in object context, in ValueWithAttr...
    method DetermineBindingMode (line 57) | void DetermineBindingMode()
    method RegisterEvents (line 80) | void RegisterEvents()
    method OnDetach (line 105) | void OnDetach(DetachFromPanelEvent evt) => UnregisterEvents();
    method UnregisterEvents (line 107) | void UnregisterEvents()
    method SyncVisualElementToModel (line 117) | void SyncVisualElementToModel()
    method Model_PropertyChanged (line 122) | protected virtual void Model_PropertyChanged(object sender, PropertyCh...
    method Dispose (line 126) | public override void Dispose()
    method PreUpdate (line 131) | public override void PreUpdate()
    method Release (line 136) | public override void Release()
    method Update (line 141) | public override void Update()
    method UpdateFromModel (line 155) | protected virtual void UpdateFromModel(in T newValue)
    method RegisterTwoWayValueChangeCallback (line 175) | void RegisterTwoWayValueChangeCallback()
    method IsValidBinding (line 189) | protected abstract bool IsValidBinding();
    method GetValueFromMemberInfo (line 190) | protected abstract T GetValueFromMemberInfo();
    method SetValueFromMemberInfo (line 191) | protected abstract void SetValueFromMemberInfo(T value);

FILE: src/Core/Binding/BindingAttribute.cs
  class UIAttribute (line 8) | public class UIAttribute : System.Attribute
  type BindingMode (line 13) | public enum BindingMode
  class BindAttribute (line 29) | [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeT...
    method BindAttribute (line 40) | public BindAttribute()
    method BindAttribute (line 44) | public BindAttribute(string path)
    method BindAttribute (line 48) | public BindAttribute(BindingMode bindingMode)
    method BindAttribute (line 52) | public BindAttribute(string path, BindingMode bindingMode)
    method BindAttribute (line 57) | public BindAttribute(string path, BindingMode bindingMode, bool hideIf...
  class BindBaseFieldAttribute (line 65) | [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeT...
    method BindBaseFieldAttribute (line 71) | public BindBaseFieldAttribute(string path, string label = null, bool s...
    method BindBaseFieldAttribute (line 77) | public BindBaseFieldAttribute(string path, BindingMode bindingMode, st...
  class BindFloatAttribute (line 85) | [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeT...
    method BindFloatAttribute (line 92) | public BindFloatAttribute(string path, float startingValue, float min,...
    method BindFloatAttribute (line 98) | public BindFloatAttribute(string path, BindingMode bindingMode, float ...
  class BindIntAttribute (line 108) | [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeT...
    method BindIntAttribute (line 115) | public BindIntAttribute(string path, int startingValue, int min, int m...
    method BindIntAttribute (line 121) | public BindIntAttribute(string path, BindingMode bindingMode, int star...
  class BindRangeAttribute (line 129) | [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeT...
    method BindRangeAttribute (line 136) | public BindRangeAttribute(string path, Vector2 startingValue, float mi...
    method BindRangeAttribute (line 142) | public BindRangeAttribute(string path, BindingMode bindingMode, Vector...
  class BindStringAttribute (line 151) | [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeT...
    method BindStringAttribute (line 160) | public BindStringAttribute(string path, string startingValue, int maxL...
    method BindStringAttribute (line 167) | public BindStringAttribute(string path, BindingMode bindingMode, strin...
  class BindTooltip (line 176) | [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeT...
    method BindTooltip (line 179) | public BindTooltip(string path) : base(path)
  class BindValueChangeCallbackAttribute (line 184) | [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeT...
    method BindValueChangeCallbackAttribute (line 187) | public BindValueChangeCallbackAttribute(string path) : base(path)
  class DrawAttribute (line 196) | [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeT...
    method DrawAttribute (line 208) | public DrawAttribute([CallerLineNumber]int order = 0)
    method DrawAttribute (line 213) | public DrawAttribute(ControlType controlType, [CallerLineNumber] int o...
  type Typography (line 220) | public enum Typography
  class DrawTextAttribute (line 240) | [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeT...
    method DrawTextAttribute (line 245) | public DrawTextAttribute([CallerLineNumber] int order = 0) : base(order)
    method DrawTextAttribute (line 250) | public DrawTextAttribute(Typography typography, [CallerLineNumber] int...
  class RouteAttribute (line 256) | [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeT...
    method RouteAttribute (line 259) | public RouteAttribute()

FILE: src/Core/Binding/BindingsManager.cs
  class BindingsManager (line 19) | public class BindingsManager : GrapheneComponent
    method LateUpdate (line 78) | void LateUpdate()
    method OnUpdate (line 94) | public void OnUpdate()
    method GetList (line 165) | List<Binding> GetList(Plate panel, Dictionary<Plate, List<Binding>> bi...
    method TryCreate (line 182) | public void TryCreate(TextElement el, ref object context, in ValueWith...
    method TryCreate (line 199) | public void TryCreate<TValueType>(BaseField<TValueType> el, in object ...
    method TryCreate (line 216) | public void TryCreate<TValueType>(BindableElement el, in object contex...
    method CreateBinding (line 225) | internal void CreateBinding<TValueType>(BindableElement el, in object ...
    method ScheduleDispose (line 239) | void ScheduleDispose(Plate panel, Binding binding)
    method Destroy (line 244) | void Destroy(Plate panel, Binding binding)
    method DisposePlate (line 251) | internal void DisposePlate(Plate plate, bool isDestroyed)

FILE: src/Core/Binding/CollectionBinding.cs
  class CollectionBinding (line 8) | public class CollectionBinding : Binding<ICollection>
    method CollectionBinding (line 12) | public CollectionBinding(BindableElement el, in object context, in Val...
    method IsValidBinding (line 27) | protected override bool IsValidBinding()
    method GetValueFromMemberInfo (line 31) | protected override ICollection GetValueFromMemberInfo()
    method SetValueFromMemberInfo (line 35) | protected override void SetValueFromMemberInfo(ICollection value)
    method UpdateFromModel (line 40) | protected override void UpdateFromModel(in ICollection newValue)

FILE: src/Core/Binding/MemberBinding.cs
  class MemberBinding (line 8) | public class MemberBinding<T> : Binding<T>
    method MemberBinding (line 10) | public MemberBinding(BindableElement el, in object context, in ValueWi...
    method IsValidBinding (line 15) | protected override bool IsValidBinding()
    method GetValueFromMemberInfo (line 20) | protected override T GetValueFromMemberInfo()
    method SetValueFromMemberInfo (line 40) | protected override void SetValueFromMemberInfo(T value)

FILE: src/Core/Extensions/ButtonGroup.cs
  class ButtonGroup (line 11) | public class ButtonGroup : GroupBox, IBindableElement<int>, INotifyValue...
    class UxmlFactory (line 30) | public new class UxmlFactory : UxmlFactory<ButtonGroup, UxmlTraits> { }
    class UxmlTraits (line 35) | public new class UxmlTraits : BindableElement.UxmlTraits
      method Init (line 46) | public override void Init(VisualElement ve, IUxmlAttributes bag, Cre...
    method SetValueWithoutNotify (line 84) | public void SetValueWithoutNotify(int value)
    method ButtonGroup (line 103) | public ButtonGroup()
    method OnModelChange (line 112) | public void OnModelChange(int newValue)
    method SetButtonActive (line 117) | internal void SetButtonActive()
    method SetItems (line 132) | public void SetItems(List<string> items)
    method RefreshButtons (line 140) | public void RefreshButtons()
    method ButtonClicked (line 150) | internal void ButtonClicked(int i)
    method ClearItems (line 159) | public void ClearItems()
    method ClearCallback (line 165) | public void ClearCallback()
    method AddItem (line 170) | public void AddItem(string text, string tooltip = null)
    method InternalAddItem (line 176) | void InternalAddItem(string text, string tooltip = null)

FILE: src/Core/Extensions/CycleField.cs
  class CycleField (line 11) | public class CycleField : BaseField<int>
    class UxmlFactory (line 31) | public new class UxmlFactory : UxmlFactory<CycleField, UxmlTraits> { }
    class UxmlTraits (line 36) | public new class UxmlTraits : BaseFieldTraits<int, UxmlIntAttributeDes...
      method Init (line 49) | public override void Init(VisualElement ve, IUxmlAttributes bag, Cre...
    method CycleField (line 98) | public CycleField()
    method CycleField (line 102) | public CycleField(string label)
    method M_Previous_clicked (line 152) | private void M_Previous_clicked()
    method M_Next_clicked (line 161) | private void M_Next_clicked()
    method SetValueWithoutNotify (line 170) | public override void SetValueWithoutNotify(int newValue)

FILE: src/Core/Extensions/Dialog.cs
  class Dialog (line 11) | public class Dialog : VisualElement, IDisposable
    class UxmlFactory (line 16) | public new class UxmlFactory : UxmlFactory<Dialog, UxmlTraits> { }
    class UxmlTraits (line 21) | public new class UxmlTraits : BindableElement.UxmlTraits
      method Init (line 29) | public override void Init(VisualElement ve, IUxmlAttributes bag, Cre...
    method Dialog (line 52) | public Dialog()
    method Dialog (line 56) | public Dialog(IPanel panel, VisualElement content)
    method ProcessClick (line 100) | bool ProcessClick(EventBase evt)
    method OnClickBackground (line 122) | void OnClickBackground(EventBase evt)
    method Dispose (line 131) | public void Dispose()
    method WithStyles (line 137) | public Dialog WithStyles(VisualElementStyleSheetSet styleSheets)

FILE: src/Core/Extensions/GrapheneRoot.cs
  class GrapheneRoot (line 11) | public class GrapheneRoot : BindableElement
    method GrapheneRoot (line 41) | public GrapheneRoot() : this(null)
    method GrapheneRoot (line 48) | public GrapheneRoot(Router router)

FILE: src/Core/Extensions/If.cs
  class If (line 8) | public class If : BindableElement, IBindableElement<object>
    class UxmlFactory (line 13) | public new class UxmlFactory : UxmlFactory<If, UxmlTraits> { }
    class UxmlTraits (line 18) | public new class UxmlTraits : BindableElement.UxmlTraits
      method Init (line 28) | public override void Init(VisualElement ve, IUxmlAttributes bag, Cre...
    method If (line 66) | public If()
    method OnModelChange (line 72) | public void OnModelChange(object newValue)

FILE: src/Core/Extensions/Route.cs
  class Route (line 8) | public class Route : BindableElement
    class UxmlFactory (line 13) | public new class UxmlFactory : UxmlFactory<Route, UxmlTraits> { }
    class UxmlTraits (line 18) | public new class UxmlTraits : BindableElement.UxmlTraits
      method Init (line 28) | public override void Init(VisualElement ve, IUxmlAttributes bag, Cre...
    method Route (line 61) | public Route() : this(null)
    method Route (line 72) | public Route(string route)
    method Clicked (line 85) | public void Clicked()
    method ProcessClick (line 90) | bool ProcessClick(EventBase evt)
    method OnClickEvent (line 112) | void OnClickEvent(EventBase evt)
    method SetRouter (line 119) | internal void SetRouter(Router r)
    method OnRoutingUnblocked (line 126) | private void OnRoutingUnblocked()
    method OnRoutingBlocked (line 131) | private void OnRoutingBlocked()

FILE: src/Core/Extensions/SelectField.cs
  class SelectField (line 11) | public class SelectField : BaseField<int>, IDisposable
    class UxmlFactory (line 32) | public new class UxmlFactory : UxmlFactory<SelectField, UxmlTraits> { }
    class UxmlTraits (line 37) | public new class UxmlTraits : BaseFieldTraits<int, UxmlIntAttributeDes...
      method Init (line 49) | public override void Init(VisualElement ve, IUxmlAttributes bag, Cre...
    method SelectField (line 98) | public SelectField()
    method SelectField (line 102) | public SelectField(string label)
    method M_ListView_onItemsChosen (line 137) | private void M_ListView_onItemsChosen(IEnumerable<object> obj)
    method M_ListView_onSelectionChange (line 142) | private void M_ListView_onSelectionChange(IEnumerable<object> obj)
    method SetValueWithoutNotify (line 147) | public override void SetValueWithoutNotify(int newValue)
    method ProcessClick (line 192) | bool ProcessClick(EventBase evt)
    method OnClickEvent (line 214) | void OnClickEvent(EventBase evt)
    method ExecuteDefaultActionAtTarget (line 220) | protected override void ExecuteDefaultActionAtTarget(EventBase evt)
    method OnClick (line 248) | void OnClick()
    method SetToggleState (line 253) | void SetToggleState(bool value)
    method M_Dialog_onClose (line 263) | private void M_Dialog_onClose()
    method MakeItem (line 269) | VisualElement MakeItem()
    method BindItem (line 274) | void BindItem(VisualElement el, int index)
    method CreateListView (line 280) | ListView CreateListView()
    method Dispose (line 303) | public void Dispose()
    method ParseChoiceList (line 310) | internal static List<string> ParseChoiceList(string choicesFromBag)

FILE: src/Core/Extensions/TemplateTypes/Button.cs
  class GrButton (line 8) | public class GrButton : TemplateRef, IBindableElement<ControlType>, IGra...
    class UxmlFactory (line 13) | public new class UxmlFactory : UxmlFactory<GrButton, UxmlTraits> { }
    method GrButton (line 27) | public GrButton() : this(null)
    method GrButton (line 32) | public GrButton(Renderer renderer) : base(renderer)

FILE: src/Core/Extensions/TemplateTypes/TemplateRef.cs
  class TemplateRef (line 7) | public class TemplateRef : BindableElement, IBindableElement<ControlType...
    class UxmlFactory (line 12) | public new class UxmlFactory : UxmlFactory<TemplateRef, UxmlTraits> { }
    class UxmlTraits (line 17) | public new class UxmlTraits : BindableElement.UxmlTraits
      method Init (line 27) | public override void Init(VisualElement ve, IUxmlAttributes bag, Cre...
    method TemplateRef (line 67) | public TemplateRef() : this(null)
    method TemplateRef (line 71) | public TemplateRef(Renderer renderer)
    method Inject (line 77) | public void Inject(GrapheneRoot root, Plate plate, Renderer renderer)
    method OnModelChange (line 82) | public void OnModelChange(ControlType newValue)
    method InstantiateTemplate (line 87) | void InstantiateTemplate()
    method Render (line 116) | public void Render()
    method ClearTemplate (line 128) | void ClearTemplate()

FILE: src/Core/Extensions/View.cs
  class View (line 8) | public class View : VisualElement
    class UxmlFactory (line 13) | public new class UxmlFactory : UxmlFactory<View, UxmlTraits> { }
    class UxmlTraits (line 18) | public new class UxmlTraits : BindableElement.UxmlTraits
      method Init (line 29) | public override void Init(VisualElement ve, IUxmlAttributes bag, Cre...
    method View (line 72) | public View() : this(null)
    method View (line 83) | public View(string id) : base ()

FILE: src/Core/Extensions/VisualElementExtensions.cs
  class VisualElementExtensions (line 6) | public static class VisualElementExtensions
    method IsHidden (line 19) | public static bool IsHidden(this VisualElement el)
    method Show (line 24) | public static void Show(this VisualElement el)
    method Hide (line 28) | public static void Hide(this VisualElement el)
    method SetShowHide (line 33) | public static void SetShowHide(this VisualElement el, bool value)
    method SetVisibility (line 41) | public static void SetVisibility(this VisualElement el, bool value)
    method SetActive (line 48) | public static void SetActive(this VisualElement el, bool value)
    method ToggleClass (line 56) | public static void ToggleClass(this VisualElement el, string className...
    method FadeIn (line 65) | public static void FadeIn(this VisualElement el)
    method FadeOut (line 70) | public static void FadeOut(this VisualElement el)
    method StartTransition (line 74) | public static void StartTransition(this VisualElement el)
    method StopTransition (line 78) | public static void StopTransition(this VisualElement el)
    method IsFadingOut (line 83) | public static bool IsFadingOut(this VisualElement el)
    method IsTransitioning (line 88) | public static bool IsTransitioning(this VisualElement el)
    method TopRoot (line 92) | public static VisualElement TopRoot(this VisualElement el)
    method TopRoot (line 96) | public static VisualElement TopRoot(this IPanel panel)
    method AddStyles (line 101) | public static void AddStyles(this VisualElement el, VisualElementStyle...
    method AddStyles (line 115) | public static void AddStyles(this VisualElement el, IEnumerable<StyleS...
    method AddMultipleToClassList (line 133) | public static void AddMultipleToClassList(this VisualElement el, strin...
    method AddMultipleToClassList (line 140) | public static void AddMultipleToClassList(this VisualElement el, IEnum...
    method RemoveMultipleFromClassList (line 152) | public static void RemoveMultipleFromClassList(this VisualElement el, ...
    method RemoveMultipleFromClassList (line 159) | public static void RemoveMultipleFromClassList(this VisualElement el, ...
    method Parse (line 165) | public static IEnumerable<string> Parse(string classes)

FILE: src/Core/Graphene.cs
  class Graphene (line 13) | [ExecuteInEditMode]
    method Start (line 57) | protected void Start()
    method Initialize (line 82) | #if ODIN_INSPECTOR
    method GetLocalReferences (line 109) | protected void GetLocalReferences()
    method GetChildPlates (line 116) | #if ODIN_INSPECTOR
    method RunInstallation (line 126) | protected void RunInstallation()
    method ConstructVisualTree (line 175) | void ConstructVisualTree(List<Plate> plates)
    method AddPlate (line 216) | public void AddPlate(Plate plate)
    method RegisterPlate (line 222) | public void RegisterPlate(Plate plate)
    method CreateRootElement (line 244) | void CreateRootElement()
    method DetachFromPanel (line 260) | void DetachFromPanel(DetachFromPanelEvent evt)
    method RebuildDelayed (line 268) | IEnumerator RebuildDelayed(float delay)
    method RebuildRootElement (line 279) | void RebuildRootElement()
    method FinalizeInitialzation (line 303) | void FinalizeInitialzation()
    method RebuildBranch (line 309) | public void RebuildBranch(Plate plate)
    method OnEnable (line 315) | private void OnEnable()
    method OnDisable (line 329) | private void OnDisable()
    method Rebuild (line 344) | #if ODIN_INSPECTOR
    method RefreshAllActiveContent (line 380) | public void RefreshAllActiveContent()
    method BroadcastBindCallback (line 400) | public void BroadcastBindCallback(BindableElement el, object context, ...

FILE: src/Core/GrapheneComponent.cs
  class GrapheneComponent (line 9) | public class GrapheneComponent : MonoBehaviour, IGrapheneInjectable
    method Inject (line 43) | public virtual void Inject(Graphene graphene)
    method Awake (line 54) | protected virtual void Awake()

FILE: src/Core/Injector.cs
  class Injector (line 8) | [DisallowMultipleComponent]
    method Awake (line 12) | private void Awake()
    method Graphene_onPreInitialize (line 18) | private void Graphene_onPreInitialize(ICollection<IGrapheneDependent> ...

FILE: src/Core/Interfaces.cs
  type IGrapheneDependent (line 6) | public interface IGrapheneDependent
  type IBindableToVisualElement (line 10) | public interface IBindableToVisualElement : IHasTooltip
    method ResetCallbacks (line 25) | void ResetCallbacks ();
    method SetBinding (line 27) | void SetBinding(VisualElement boundToElement);
  type IBindableElement (line 32) | public interface IBindableElement<TValue>
    method OnModelChange (line 38) | void OnModelChange(TValue newValue);
  type InteractionMode (line 41) | public enum InteractionMode
  type IBindableInteractionType (line 48) | public interface IBindableInteractionType
  type IGrapheneElement (line 54) | public interface IGrapheneElement
    method Inject (line 56) | void Inject(GrapheneRoot root, Plate plate, Renderer renderer);
  type IGrapheneInitializable (line 60) | public interface IGrapheneInitializable : IGrapheneDependent
    method Initialize (line 62) | void Initialize();
  type IGrapheneLateInitializable (line 64) | public interface IGrapheneLateInitializable : IGrapheneDependent
    method LateInitialize (line 66) | void LateInitialize();
  type IGrapheneInjectable (line 69) | public interface IGrapheneInjectable : IGrapheneDependent
    method Inject (line 71) | void Inject(Graphene graphene);
  type IModel (line 77) | public interface IModel
    method Initialize (line 79) | void Initialize(VisualElement container, Plate plate);
    method Refresh (line 84) | void Refresh(VisualElement container);
  type ICustomBindContext (line 90) | public interface ICustomBindContext
  type ICustomDrawContext (line 98) | public interface ICustomDrawContext
  type IForm (line 103) | public interface IForm
    method OnSubmit (line 107) | void OnSubmit();
    method OnCancel (line 108) | void OnCancel();
  type IHasTooltip (line 114) | public interface IHasTooltip
  type IHasCustomVisualTreeAsset (line 119) | public interface IHasCustomVisualTreeAsset

FILE: src/Core/Model/BindableObjects/BindableBaseField.cs
  class BindableBaseField (line 16) | [System.Serializable]
    method BindableBaseField (line 33) | public BindableBaseField() { }
    method BindableBaseField (line 35) | public BindableBaseField([CallerMemberName] string label = "Label") : ...
    method SetValueWithoutNotify (line 59) | public virtual void SetValueWithoutNotify(T newValue)
    method ValueChangeCallback (line 68) | protected virtual void ValueChangeCallback(T value)
    method ResetCallbacks (line 80) | public override void ResetCallbacks()
  class BindableBaseField (line 26) | [System.Serializable]
    method BindableBaseField (line 33) | public BindableBaseField() { }
    method BindableBaseField (line 35) | public BindableBaseField([CallerMemberName] string label = "Label") : ...
    method SetValueWithoutNotify (line 59) | public virtual void SetValueWithoutNotify(T newValue)
    method ValueChangeCallback (line 68) | protected virtual void ValueChangeCallback(T value)
    method ResetCallbacks (line 80) | public override void ResetCallbacks()
  class BindableBool (line 90) | [System.Serializable, Draw(ControlType.Toggle), DataContract]
    method BindableBool (line 93) | public BindableBool(string name = null) : base(name) { }
    method BindableBool (line 94) | public BindableBool() : base(null) 	{}
  class RangeBaseField (line 99) | [System.Serializable, Draw(ControlType.Slider), DataContract]
    method RangeBaseField (line 126) | public RangeBaseField() : base() { }
    method Normalize (line 128) | protected float Normalize(float value, float min, float max)
  type INumericBindable (line 134) | public interface INumericBindable
    method SetValueWithoutNotify (line 142) | void SetValueWithoutNotify(float value);
  class BindableFloat (line 145) | [System.Serializable, Draw(ControlType.Slider), DataContract]
    method BindableFloat (line 153) | public BindableFloat() : base()
    method SetValueWithoutNotify (line 160) | public override void SetValueWithoutNotify(float newValue)
  class BindableInt (line 166) | [System.Serializable, Draw(ControlType.SliderInt), DataContract]
    method BindableInt (line 178) | public BindableInt() : base()
    method SetValueWithoutNotify (line 186) | public override void SetValueWithoutNotify(int newValue)
    method SetValueWithoutNotify (line 191) | void INumericBindable.SetValueWithoutNotify(float value) => SetValueWi...
  class BindableNamedInt (line 194) | [System.Serializable, Draw(ControlType.CycleField), DataContract]
    method InitFromEnum (line 203) | public void InitFromEnum<T>(bool splitUppercase = true)
    method InitFromList (line 217) | public void InitFromList(IEnumerable<string> list)
    method BindableNamedInt (line 223) | public BindableNamedInt() : base() { }
  class BindableStringSelect (line 227) | [System.Serializable, Draw(ControlType.DropdownField), DataContract]
    method InitFromEnum (line 238) | public void InitFromEnum<T>(bool splitUppercase = true)
    method InitFromList (line 251) | public void InitFromList(IEnumerable<string> list)
    method BindableStringSelect (line 257) | public BindableStringSelect() : base() { }
  class BindableInput (line 261) | [System.Serializable, Draw(ControlType.TextField), DataContract]
    method BindableInput (line 264) | public BindableInput() : base() { }
  class BindableRange (line 268) | [System.Serializable, Draw(ControlType.MinMaxSlider), DataContract]
    method BindableRange (line 286) | public BindableRange() : base()
    method Normalize (line 293) | protected float Normalize(float value, float min, float max)
  class StringUtility (line 299) | public static class StringUtility
    method InsertSpaceBeforeUpperCase (line 301) | public static string InsertSpaceBeforeUpperCase(this string str)

FILE: src/Core/Model/BindableObjects/BindableObject.cs
  class BindableObjectBase (line 19) | [System.Serializable]
    method SetBinding (line 46) | public void SetBinding(VisualElement el)
    method ToggleEnable (line 54) | void ToggleEnable() => SetEnabled(!isEnabled);
    method ToggleShow (line 55) | void ToggleShow() => SetShow(!isShown);
    method ToggleActive (line 56) | void ToggleActive() => SetActive(!isActive2);
    method SetEnabled (line 58) | public void SetEnabled(bool enabled)
    method SetShow (line 64) | public void SetShow(bool show)
    method SetActive (line 69) | public void SetActive(bool active)
    method ResetCallbacks (line 75) | public virtual void ResetCallbacks()
  class BindableObject (line 87) | [System.Serializable, Draw(ControlType.Button)]
    method ToString (line 145) | public override string ToString()
    method BindableObject (line 151) | public BindableObject()
    method BindableObject (line 155) | public BindableObject(UnityAction callback) : this()
  class ContextBindableObject (line 162) | [System.Serializable, Draw(ControlType.Button)]
    method AddAction (line 184) | public void AddAction(string name, Action callback, string tooltip = n...
  class ActionButton (line 198) | [Draw(ControlType.Button)]

FILE: src/Core/Model/BindableObjects/ListBindable.cs
  type IListViewBindable (line 9) | public interface IListViewBindable
    method Apply (line 24) | void Apply(ListView el);
  class ListBindable (line 29) | public abstract class ListBindable : BindableObjectBase
    method Rebuild (line 49) | [ResponsiveButtonGroup]
    method Apply (line 59) | public void Apply(ListView el)
    method Add (line 91) | public void Add(TObjectType item) => SourceItems.Add(item);
    method Clear (line 93) | public void Clear() => SourceItems.Clear();
    method Contains (line 95) | public bool Contains(TObjectType item) => SourceItems.Contains(item);
    method CopyTo (line 97) | public void CopyTo(TObjectType[] array, int arrayIndex) => SourceItems...
    method GetEnumerator (line 99) | public IEnumerator<TObjectType> GetEnumerator() => SourceItems.GetEnum...
    method IndexOf (line 101) | public int IndexOf(TObjectType item) => SourceItems.IndexOf(item);
    method Insert (line 103) | public void Insert(int index, TObjectType item) => SourceItems.Insert(...
    method Remove (line 105) | public bool Remove(TObjectType item) => SourceItems.Remove(item);
    method RemoveAt (line 107) | public void RemoveAt(int index) => SourceItems.RemoveAt(index);
  class ListBindable (line 76) | [System.Serializable]
    method Rebuild (line 49) | [ResponsiveButtonGroup]
    method Apply (line 59) | public void Apply(ListView el)
    method Add (line 91) | public void Add(TObjectType item) => SourceItems.Add(item);
    method Clear (line 93) | public void Clear() => SourceItems.Clear();
    method Contains (line 95) | public bool Contains(TObjectType item) => SourceItems.Contains(item);
    method CopyTo (line 97) | public void CopyTo(TObjectType[] array, int arrayIndex) => SourceItems...
    method GetEnumerator (line 99) | public IEnumerator<TObjectType> GetEnumerator() => SourceItems.GetEnum...
    method IndexOf (line 101) | public int IndexOf(TObjectType item) => SourceItems.IndexOf(item);
    method Insert (line 103) | public void Insert(int index, TObjectType item) => SourceItems.Insert(...
    method Remove (line 105) | public bool Remove(TObjectType item) => SourceItems.Remove(item);
    method RemoveAt (line 107) | public void RemoveAt(int index) => SourceItems.RemoveAt(index);

FILE: src/Core/Model/GenericModelAsset.cs
  class ScriptableObjectModel (line 7) | public abstract class ScriptableObjectModel<T> : ScriptableObjectModel
  class GenericModelAsset (line 16) | [CreateAssetMenu(menuName = "Graphene/Model/GenericModelAsset")]
    method Initialize (line 19) | public override void Initialize(VisualElement container, Plate plate)

FILE: src/Core/Model/GenericModelBehaviour.cs
  class GenericModelBehaviour (line 7) | public abstract class GenericModelBehaviour<T> : ViewModelComponent
    method Inject (line 26) | public override void Inject(Graphene graphene)
    method OnShow (line 33) | protected override void OnShow()
    method ValidateAddresses (line 39) | void ValidateAddresses()
    method Initialize (line 76) | public override void Initialize(VisualElement container, Plate plate)
  class GenericModelBehaviour (line 18) | public class GenericModelBehaviour : GenericModelBehaviour<BindableObject>
    method Inject (line 26) | public override void Inject(Graphene graphene)
    method OnShow (line 33) | protected override void OnShow()
    method ValidateAddresses (line 39) | void ValidateAddresses()
    method Initialize (line 76) | public override void Initialize(VisualElement container, Plate plate)

FILE: src/Core/Model/ScriptableObjectModel.cs
  class ScriptableObjectModel (line 12) | public abstract class ScriptableObjectModel : ScriptableObject, IModel
    method Initialize (line 22) | public abstract void Initialize(VisualElement container, Plate plate);
    method Refresh (line 24) | public void Refresh(VisualElement container)
    method ForceRedraw (line 30) | #if ODIN_INSPECTOR

FILE: src/Core/Model/ViewModel/FormViewModel.cs
  type IFormViewModel (line 7) | public interface IFormViewModel : IModel
    method Submit (line 15) | void Submit();
    method Cancel (line 16) | void Cancel();
    method Reset (line 17) | void Reset();
    method PromptReset (line 19) | void PromptReset();
    method UpdateFormButtonsState (line 24) | void UpdateFormButtonsState(bool enabled, bool active);
  class FormViewModel (line 27) | public abstract class FormViewModel : ViewModelComponent, IFormViewModel...
    method Awake (line 62) | protected override void Awake()
    method Initialize (line 73) | public virtual void Initialize()
    method OnEnable (line 80) | void OnEnable()
    method OnDisable (line 88) | void OnDisable()
    method Subscribe (line 95) | void Subscribe()
    method UnSubscribe (line 101) | void UnSubscribe()
    method TrySubmit (line 107) | public bool TrySubmit()
    method TryCancel (line 116) | public bool TryCancel()
    method TryReset (line 122) | public bool TryReset()
    method CanCatch (line 127) | bool IStateInterpreter.CanCatch(object state) => TryCatch((string)state);
    method CanCatch (line 128) | public bool CanCatch(string state)
    method TryCatch (line 141) | bool IStateInterpreter.TryCatch(object state) => TryCatch((string)state);
    method TryCatch (line 143) | public bool TryCatch(string state)
    method Cancel (line 173) | [ResponsiveButtonGroup]
    method Submit (line 175) | [ResponsiveButtonGroup]
    method Reset (line 178) | public abstract void Reset();
    method PromptReset (line 179) | public abstract void PromptReset();
    method MarkDirty (line 181) | protected void MarkDirty(bool dirty)
    method SetButtonsDirty (line 197) | [Button]
    method UpdateFormButtonsState (line 209) | public void UpdateFormButtonsState(bool enabled, bool active)
    method CanSubmit (line 222) | public virtual bool CanSubmit() => true;
    method CanCancel (line 223) | public virtual bool CanCancel() => true;
    method CanReset (line 224) | public virtual bool CanReset() => true;
    method UpdateSourceData (line 233) | public abstract void UpdateSourceData();
  class FormViewModel (line 227) | public abstract class FormViewModel<T> : FormViewModel, ICustomDrawContext
    method Awake (line 62) | protected override void Awake()
    method Initialize (line 73) | public virtual void Initialize()
    method OnEnable (line 80) | void OnEnable()
    method OnDisable (line 88) | void OnDisable()
    method Subscribe (line 95) | void Subscribe()
    method UnSubscribe (line 101) | void UnSubscribe()
    method TrySubmit (line 107) | public bool TrySubmit()
    method TryCancel (line 116) | public bool TryCancel()
    method TryReset (line 122) | public bool TryReset()
    method CanCatch (line 127) | bool IStateInterpreter.CanCatch(object state) => TryCatch((string)state);
    method CanCatch (line 128) | public bool CanCatch(string state)
    method TryCatch (line 141) | bool IStateInterpreter.TryCatch(object state) => TryCatch((string)state);
    method TryCatch (line 143) | public bool TryCatch(string state)
    method Cancel (line 173) | [ResponsiveButtonGroup]
    method Submit (line 175) | [ResponsiveButtonGroup]
    method Reset (line 178) | public abstract void Reset();
    method PromptReset (line 179) | public abstract void PromptReset();
    method MarkDirty (line 181) | protected void MarkDirty(bool dirty)
    method SetButtonsDirty (line 197) | [Button]
    method UpdateFormButtonsState (line 209) | public void UpdateFormButtonsState(bool enabled, bool active)
    method CanSubmit (line 222) | public virtual bool CanSubmit() => true;
    method CanCancel (line 223) | public virtual bool CanCancel() => true;
    method CanReset (line 224) | public virtual bool CanReset() => true;
    method UpdateSourceData (line 233) | public abstract void UpdateSourceData();

FILE: src/Core/Model/ViewModel/MultiFormViewModel.cs
  class MultiFormViewModel (line 10) | public class MultiFormViewModel : FormViewModel, IStateInterpreter, IFor...
    method Initialize (line 21) | public override void Initialize(VisualElement container, Plate plate)
    method Cancel (line 69) | public override void Cancel()
    method Submit (line 78) | public override void Submit()
    method Reset (line 87) | public override void Reset()
    method PromptReset (line 96) | public override void PromptReset()
    method SetButtonsDirty (line 101) | protected override void SetButtonsDirty(bool dirty)

FILE: src/Core/Model/ViewModel/NavViewModel.cs
  class NavViewModel (line 7) | public class NavViewModel : GenericModelBehaviour
    type RenderMode (line 16) | public enum RenderMode
    method Initialize (line 31) | public override void Initialize(VisualElement container, Plate plate)
    method Inject (line 41) | public override void Inject(Graphene graphene)
    method Router_onStateChange (line 47) | private void Router_onStateChange(string newState)
    method OnDestroy (line 57) | void OnDestroy()
    method CreateBindableObjectsFromSiblingsWithState (line 63) | void CreateBindableObjectsFromSiblingsWithState(Plate plate)

FILE: src/Core/Model/ViewModel/ViewModelComponent.cs
  class ViewModelComponent (line 10) | [RequireComponent(typeof(Renderer))]
    method Awake (line 27) | protected override void Awake()
    method Inject (line 36) | public override void Inject(Graphene graphene)
    method Initialize (line 48) | public abstract void Initialize(VisualElement container, Plate plate);
    method Start (line 51) | void Start()
    method OnShow (line 55) | protected virtual void OnShow() { }
    method OnHide (line 56) | protected virtual void OnHide() { }
    method ModelChange (line 58) | #if ODIN_INSPECTOR
    method Refresh (line 65) | #if ODIN_INSPECTOR

FILE: src/Core/Plate.cs
  type PositionMode (line 20) | public enum PositionMode
  type BindingRefreshMode (line 39) | public enum BindingRefreshMode
  type ShowHideMode (line 55) | public enum ShowHideMode
  class Plate (line 64) | [DisallowMultipleComponent]
    method Initialize (line 278) | public virtual void Initialize()
    method Awake (line 293) | protected override void Awake()
    method GetLocalReferences (line 308) | protected virtual void GetLocalReferences()
    method ConstructVisualTree (line 327) | internal void ConstructVisualTree()
    method Root_StartTransition (line 382) | void Root_StartTransition(TransitionStartEvent evt)
    method Root_EndTransition (line 386) | void Root_EndTransition(TransitionEndEvent evt)
    method ChangeEvent (line 403) | void ChangeEvent()
    method RegisterChild (line 408) | protected void RegisterChild(Plate child)
    method Clear (line 415) | #if ODIN_INSPECTOR
    method RefreshContentContainer (line 427) | public void RefreshContentContainer()
    method RenderAndComposeChildren (line 435) | #if ODIN_INSPECTOR
    method OnEnable (line 458) | private void OnEnable()
    method OnDisable (line 468) | private void OnDisable()
    method InitViewsRuntime (line 475) | void InitViewsRuntime()
    method EditModeCacheViewIds (line 512) | void EditModeCacheViewIds()
    method SetVisualTreeAsset (line 531) | void SetVisualTreeAsset(VisualTreeAsset asset)
    method OnChangeDocument (line 539) | void OnChangeDocument()
    method UpdateViewPlates (line 545) | void UpdateViewPlates()
    method Show (line 560) | #if ODIN_INSPECTOR
    method Hide (line 589) | #if ODIN_INSPECTOR
    method HideImmediately (line 614) | internal void HideImmediately()
    method SetActive (line 622) | void SetActive(bool active)
    method ApplyActiveState (line 631) | void ApplyActiveState()
    method ReevaluateState (line 664) | internal void ReevaluateState()
    method Parent_OnShow (line 679) | void Parent_OnShow()
    method Parent_OnHide (line 685) | void Parent_OnHide()
    method Detach (line 692) | internal void Detach()
    method DetachChildPlates (line 699) | protected virtual void DetachChildPlates()
    method DetachChildPlates (line 707) | protected virtual void DetachChildPlates(View view)
    method ReattachChildPlates (line 719) | protected virtual void ReattachChildPlates(View view)
    method AttachChildPlates (line 733) | void AttachChildPlates()
    method ReattachChildren (line 761) | void ReattachChildren()
    method AttachChild (line 774) | void AttachChild(View view, Plate child)
    method InternalAttach (line 789) | void InternalAttach(View view, Plate child)
    method GetVisualElement (line 800) | public VisualElement GetVisualElement(ICollection<string> names)
    method GetViewById (line 821) | public View GetViewById(string id)
    method OnDestroy (line 829) | private void OnDestroy()
    method Dispose (line 833) | public void Dispose()
    method OnValidate (line 839) | void OnValidate()
    method RefreshClassesAndStyles (line 856) | internal void RefreshClassesAndStyles()

FILE: src/Core/Rendering/RenderUtils.cs
  class RenderUtils (line 11) | internal static class RenderUtils
    method IsPrimitiveContext (line 22) | internal static bool IsPrimitiveContext(this System.Type type) => type...
    method DrawDataContainer (line 32) | internal static void DrawDataContainer(Plate plate, VisualElement cont...
    method DrawFromObjectContext (line 92) | static void DrawFromObjectContext(Plate panel, VisualElement container...
    method DrawFromPrimitiveContext (line 133) | static void DrawFromPrimitiveContext(Plate panel, VisualElement contai...
    method DrawFromEnumerableContext (line 152) | static void DrawFromEnumerableContext(Plate plate, VisualElement conta...
    method DrawListView (line 188) | static void DrawListView(Plate plate, ListView listView, in object con...

FILE: src/Core/Rendering/Renderer.cs
  class Renderer (line 13) | [RequireComponent(typeof(Plate))]
    method Initialize (line 30) | public void Initialize()
    method SetModel (line 45) | void SetModel(IModel newViewModel)
    method RebindStatic (line 56) | public void RebindStatic()
    method BindStatic (line 85) | internal void BindStatic(IModel viewModelContext)
    method Plate_onRefreshDynamic (line 99) | internal void Plate_onRefreshDynamic()
    method Model_onModelChange (line 104) | internal void Model_onModelChange()
    method RenderToContainer (line 110) | internal void RenderToContainer(VisualElement container)
    method GetTemplatesFromParentsRecursive (line 128) | TemplatePreset GetTemplatesFromParentsRecursive(Renderer current)
    method Refresh (line 140) | #if ODIN_INSPECTOR
    method HardRefresh (line 151) | #if ODIN_INSPECTOR
    method ClearContent (line 169) | #if ODIN_INSPECTOR
    method GetDrawContainer (line 181) | internal VisualElement GetDrawContainer()

FILE: src/Core/Routing/EnableOnState.cs
  class EnableOnState (line 10) | [RequireComponent(typeof(Plate))]
    type ActivationMode (line 14) | public enum ActivationMode
    method Initialize (line 26) | public virtual void Initialize()
    method Inject (line 46) | public void Inject(Router<T> router)
    method Router_onStateChange (line 52) | private void Router_onStateChange(T address)
    method Plate_onEvaluateState (line 74) | protected void Plate_onEvaluateState()

FILE: src/Core/Routing/Interpreters/ApplicationStateInterpreter.cs
  type RouterCommand (line 15) | public enum RouterCommand
  type NavigationInput (line 26) | [System.Flags]
  class InputOverride (line 35) | #if ODIN_INSPECTOR
  class ApplicationStateInterpreter (line 55) | public class ApplicationStateInterpreter : StateInterpreter<string>, IGr...
    type StateCommandHandle (line 57) | #if ODIN_INSPECTOR
      method ValidateCustomState (line 76) | bool ValidateCustomState(string customState)
    method Inject (line 92) | public void Inject(Router<string> router)
    method Initialize (line 98) | public void Initialize()
    method CanCatch (line 121) | public override bool CanCatch(object state)
    method CanCatch (line 126) | public override bool CanCatch(string state)
    method TryCatch (line 141) | public override bool TryCatch(object state)
    method TryCatch (line 146) | public override bool TryCatch(string state)
    method HandleRouterCommand (line 173) | void HandleRouterCommand(RouterCommand routerCommand)
    method TryExit (line 196) | public virtual void TryExit()
    method Plate_OnShow (line 207) | protected virtual void Plate_OnShow()
    method Plate_OnHide (line 212) | protected virtual void Plate_OnHide()
    method OnEnable (line 217) | private void OnEnable()
    method OnDisable (line 230) | private void OnDisable()
    method OnDestroy (line 243) | private void OnDestroy()
    method RegisterInput (line 249) | void RegisterInput()
    method OnNavigationSubmit (line 272) | void OnNavigationSubmit(InputOverride item, NavigationSubmitEvent evt)
    method OnNavigationCancel (line 278) | void OnNavigationCancel(InputOverride item, NavigationCancelEvent evt)
    method OnNavigationMove (line 284) | void OnNavigationMove(InputOverride item, NavigationMoveEvent evt)
    method Handle (line 291) | void Handle(InputOverride item, EventBase evt)

FILE: src/Core/Routing/Interpreters/NavigationStateHandler.cs
  class NavigationStateHandler (line 12) | [RequireComponent(typeof(Plate))]
    method Inject (line 23) | public void Inject(Router<string> router)
    method Initialize (line 29) | public void Initialize()
    method HasElements (line 46) | bool HasElements()
    method Router_onStateChange (line 67) | private void Router_onStateChange(string newState)
    method TryCatch (line 85) | public override bool TryCatch(object state)
    method TryCatch (line 90) | public override bool TryCatch(string state)
    method CanCatch (line 111) | public override bool CanCatch(object state)
    method CanCatch (line 116) | public override bool CanCatch(string state)
    method Plate_OnShow (line 127) | internal void Plate_OnShow()
    method Plate_OnHide (line 137) | internal void Plate_OnHide()
    method OnEnable (line 142) | private void OnEnable()
    method OnDisable (line 150) | private void OnDisable()

FILE: src/Core/Routing/Interpreters/StateInterpreter.cs
  type IStateInterpreter (line 7) | public interface IStateInterpreter
    method CanCatch (line 9) | bool CanCatch(object state);
    method TryCatch (line 10) | bool TryCatch(object state);
    method CanCatch (line 14) | bool CanCatch(TStateType state);
    method TryCatch (line 16) | bool TryCatch(TStateType state);
  type IStateInterpreter (line 12) | public interface IStateInterpreter<TStateType> : IStateInterpreter
    method CanCatch (line 9) | bool CanCatch(object state);
    method TryCatch (line 10) | bool TryCatch(object state);
    method CanCatch (line 14) | bool CanCatch(TStateType state);
    method TryCatch (line 16) | bool TryCatch(TStateType state);
  class StateInterpreter (line 22) | public abstract class StateInterpreter : GrapheneComponent, IStateInterp...
    method CanCatch (line 24) | public abstract bool CanCatch(object state);
    method TryCatch (line 25) | public abstract bool TryCatch(object state);
    method CanCatch (line 30) | public abstract bool CanCatch(TStateType state);
    method TryCatch (line 31) | public abstract bool TryCatch(TStateType state);
  class StateInterpreter (line 28) | public abstract class StateInterpreter<TStateType> : StateInterpreter, I...
    method CanCatch (line 24) | public abstract bool CanCatch(object state);
    method TryCatch (line 25) | public abstract bool TryCatch(object state);
    method CanCatch (line 30) | public abstract bool CanCatch(TStateType state);
    method TryCatch (line 31) | public abstract bool TryCatch(TStateType state);

FILE: src/Core/Routing/Router.cs
  class Router (line 15) | [RequireComponent(typeof(Graphene))]
    method InjectIntoHierarchy (line 32) | public abstract void InjectIntoHierarchy();
    method Initialize (line 33) | public abstract void Initialize();
    method BindRouteToContext (line 34) | public abstract void BindRouteToContext(BindableElement el, object data);
    method BindRoute (line 35) | public abstract void BindRoute(Route el, object data);
    method TryGoToPreviousState (line 36) | public abstract void TryGoToPreviousState();
    method TryGoToNextState (line 37) | public abstract void TryGoToNextState();
    method TryGoUpOneState (line 38) | public abstract void TryGoUpOneState();
    method ResetState (line 39) | public abstract void ResetState();
    method RegisterInterpreter (line 41) | public void RegisterInterpreter(IStateInterpreter stateInterpreter)
    method UnregisterInterpreter (line 49) | public void UnregisterInterpreter(IStateInterpreter stateInterpreter)
    method TryBlock (line 57) | public void TryBlock(Object caller)
    method TryUnblock (line 65) | public void TryUnblock(Object caller)
    method OnValidate (line 74) | protected void OnValidate()
    method GetStateKeys (line 120) | IEnumerable<T> GetStateKeys()
    method InjectIntoHierarchy (line 138) | public override void InjectIntoHierarchy()
    method Initialize (line 147) | public override void Initialize()
    method LateInitialize (line 160) | public void LateInitialize()
    method BindRouteToContext (line 182) | public override void BindRouteToContext(BindableElement el, object con...
    method BindRoute (line 205) | public override void BindRoute(Route el, object context)
    method RegisterState (line 247) | public void RegisterState(T state, T parentState)
    method UnregisterState (line 263) | public void UnregisterState(T state)
    method RegisterInterpreter (line 274) | public void RegisterInterpreter(IStateInterpreter<T> stateInterpreter)
    method UnregisterInterpreter (line 283) | public void UnregisterInterpreter(IStateInterpreter<T> stateInterpreter)
    method InterpreterDestroyed (line 289) | public void InterpreterDestroyed(IStateInterpreter<T> stateInterpreter)
    method ValidateAddress (line 297) | public bool ValidateAddress(T state)
    method TryChangeState (line 309) | public virtual bool TryChangeState(T state)
    method TryGoToPreviousState (line 341) | public override void TryGoToPreviousState()
    method TryGoUpOneState (line 350) | public override void TryGoUpOneState()
    method TryGoToNextState (line 362) | public override void TryGoToNextState()
    method ResetState (line 366) | public override void ResetState()
    method StateIsActive (line 371) | public bool StateIsActive(T state)
    method IsSiblingState (line 376) | public bool IsSiblingState(T state, T otherState)
    method IsSiblingToCurrentState (line 381) | public bool IsSiblingToCurrentState(T state)
    method ValidState (line 392) | public abstract bool ValidState(T state);
    method AddressExists (line 394) | public abstract bool AddressExists(T address);
    method GetStatesFromAddress (line 395) | public abstract T[] GetStatesFromAddress(T address);
    method LeafStateFromAddress (line 397) | public abstract T LeafStateFromAddress(T address);
    method GetActiveStateHierarchy (line 399) | protected abstract T[] GetActiveStateHierarchy(T state);
    method UpdateTraversedStates (line 401) | protected void UpdateTraversedStates(T newState)
  class Router (line 84) | public abstract class Router<T> : Router, IGrapheneInitializable, IGraph...
    method InjectIntoHierarchy (line 32) | public abstract void InjectIntoHierarchy();
    method Initialize (line 33) | public abstract void Initialize();
    method BindRouteToContext (line 34) | public abstract void BindRouteToContext(BindableElement el, object data);
    method BindRoute (line 35) | public abstract void BindRoute(Route el, object data);
    method TryGoToPreviousState (line 36) | public abstract void TryGoToPreviousState();
    method TryGoToNextState (line 37) | public abstract void TryGoToNextState();
    method TryGoUpOneState (line 38) | public abstract void TryGoUpOneState();
    method ResetState (line 39) | public abstract void ResetState();
    method RegisterInterpreter (line 41) | public void RegisterInterpreter(IStateInterpreter stateInterpreter)
    method UnregisterInterpreter (line 49) | public void UnregisterInterpreter(IStateInterpreter stateInterpreter)
    method TryBlock (line 57) | public void TryBlock(Object caller)
    method TryUnblock (line 65) | public void TryUnblock(Object caller)
    method OnValidate (line 74) | protected void OnValidate()
    method GetStateKeys (line 120) | IEnumerable<T> GetStateKeys()
    method InjectIntoHierarchy (line 138) | public override void InjectIntoHierarchy()
    method Initialize (line 147) | public override void Initialize()
    method LateInitialize (line 160) | public void LateInitialize()
    method BindRouteToContext (line 182) | public override void BindRouteToContext(BindableElement el, object con...
    method BindRoute (line 205) | public override void BindRoute(Route el, object context)
    method RegisterState (line 247) | public void RegisterState(T state, T parentState)
    method UnregisterState (line 263) | public void UnregisterState(T state)
    method RegisterInterpreter (line 274) | public void RegisterInterpreter(IStateInterpreter<T> stateInterpreter)
    method UnregisterInterpreter (line 283) | public void UnregisterInterpreter(IStateInterpreter<T> stateInterpreter)
    method InterpreterDestroyed (line 289) | public void InterpreterDestroyed(IStateInterpreter<T> stateInterpreter)
    method ValidateAddress (line 297) | public bool ValidateAddress(T state)
    method TryChangeState (line 309) | public virtual bool TryChangeState(T state)
    method TryGoToPreviousState (line 341) | public override void TryGoToPreviousState()
    method TryGoUpOneState (line 350) | public override void TryGoUpOneState()
    method TryGoToNextState (line 362) | public override void TryGoToNextState()
    method ResetState (line 366) | public override void ResetState()
    method StateIsActive (line 371) | public bool StateIsActive(T state)
    method IsSiblingState (line 376) | public bool IsSiblingState(T state, T otherState)
    method IsSiblingToCurrentState (line 381) | public bool IsSiblingToCurrentState(T state)
    method ValidState (line 392) | public abstract bool ValidState(T state);
    method AddressExists (line 394) | public abstract bool AddressExists(T address);
    method GetStatesFromAddress (line 395) | public abstract T[] GetStatesFromAddress(T address);
    method LeafStateFromAddress (line 397) | public abstract T LeafStateFromAddress(T address);
    method GetActiveStateHierarchy (line 399) | protected abstract T[] GetActiveStateHierarchy(T state);
    method UpdateTraversedStates (line 401) | protected void UpdateTraversedStates(T newState)

FILE: src/Core/Routing/StateHandle.cs
  type ChildActivationMode (line 5) | public enum ChildActivationMode
  class StateHandle (line 12) | [RequireComponent(typeof(Plate))]
    method Initialize (line 26) | public virtual void Initialize()
    method Plate_onEvaluateState (line 38) | protected abstract void Plate_onEvaluateState();
    method TryActivate (line 40) | public virtual bool TryActivate() => throw new System.NotImplementedEx...
    method Inject (line 52) | public void Inject(Router<T> router)
    method Initialize (line 57) | public override void Initialize()
    method OnDestroy (line 74) | private void OnDestroy()
    method Router_onStateChange (line 83) | private void Router_onStateChange(T address)
    method Plate_onEvaluateState (line 106) | protected override void Plate_onEvaluateState()
    method TryActivate (line 111) | #if ODIN_INSPECTOR
  class StateHandle (line 43) | public class StateHandle<T> : StateHandle
    method Initialize (line 26) | public virtual void Initialize()
    method Plate_onEvaluateState (line 38) | protected abstract void Plate_onEvaluateState();
    method TryActivate (line 40) | public virtual bool TryActivate() => throw new System.NotImplementedEx...
    method Inject (line 52) | public void Inject(Router<T> router)
    method Initialize (line 57) | public override void Initialize()
    method OnDestroy (line 74) | private void OnDestroy()
    method Router_onStateChange (line 83) | private void Router_onStateChange(T address)
    method Plate_onEvaluateState (line 106) | protected override void Plate_onEvaluateState()
    method TryActivate (line 111) | #if ODIN_INSPECTOR

FILE: src/Core/Routing/StringEnableOnState.cs
  class StringEnableOnState (line 10) | public class StringEnableOnState : EnableOnState<string>

FILE: src/Core/Routing/StringRouter.cs
  class StringRouter (line 13) | public class StringRouter : Router<string>
    method StringRouter (line 18) | public StringRouter()
    method GetStatesFromAddress (line 23) | public override string[] GetStatesFromAddress(string address)
    method GetActiveStateHierarchy (line 32) | protected override string[] GetActiveStateHierarchy(string routeRequest)
    method AddressFromRelativeState (line 47) | public string[] AddressFromRelativeState(string relativeAddress)
    method GetParentStatesRecursive (line 69) | List<string> GetParentStatesRecursive(string state, List<string> list)
    method ChangeState (line 84) | #if ODIN_INSPECTOR
    method ValidState (line 91) | public override bool ValidState(string state)
    method AddressExists (line 97) | public override bool AddressExists(string address)
    method LeafStateFromAddress (line 107) | public override string LeafStateFromAddress(string address)

FILE: src/Core/Routing/StringStateHandle.cs
  class StringStateHandle (line 10) | public class StringStateHandle : StateHandle<string>
    method Awake (line 15) | protected override void Awake()
    method GameObjectNameAsStateId (line 22) | string GameObjectNameAsStateId () => gameObject.name.ToLower();

FILE: src/Core/Styling/AlignItemsOverride.cs
  class AlignItemsOverride (line 8) | [System.Serializable]
    method TryApply (line 11) | public override void TryApply(VisualElement visualElement)

FILE: src/Core/Styling/FlexDirectionOverride.cs
  class FlexDirectionOverride (line 8) | [System.Serializable]
    method TryApply (line 11) | public override void TryApply(VisualElement visualElement)
  class FlexGrowOverride (line 20) | [System.Serializable]
    method TryApply (line 23) | public override void TryApply(VisualElement visualElement)

FILE: src/Core/Styling/InlineStyleOverrides.cs
  class InlineStyleOverrides (line 12) | [System.Serializable]
    method Apply (line 33) | internal void Apply(VisualElement el)

FILE: src/Core/Styling/JustifyOverride.cs
  class JustifyOverride (line 10) | [System.Serializable]
    method TryApply (line 13) | public override void TryApply(VisualElement visualElement)
  class StyleLengthOverride (line 22) | public abstract class StyleLengthOverride : StyleOverride<float>
  class WidthOverride (line 27) | [System.Serializable]
    method TryApply (line 30) | public override void TryApply(VisualElement visualElement)
  class HeightOverride (line 39) | [System.Serializable]
    method TryApply (line 42) | public override void TryApply(VisualElement visualElement)

FILE: src/Core/Styling/StyleOverride.cs
  class StyleOverride (line 9) | #if ODIN_INSPECTOR
    method TryApply (line 19) | public abstract void TryApply(VisualElement visualElement);
    method StyleOverride (line 24) | public StyleOverride()
    method StyleOverride (line 28) | public StyleOverride(T value)

FILE: src/Core/Styling/WrapOverride.cs
  class WrapOverride (line 8) | [System.Serializable]
    method TryApply (line 11) | public override void TryApply(VisualElement visualElement)

FILE: src/Core/Templating/TemplatePreset.cs
  type ControlType (line 16) | public enum ControlType
  type ICustomControlType (line 42) | public interface ICustomControlType
  type ICustomAddClasses (line 47) | public interface ICustomAddClasses
  type ICustomName (line 52) | public interface ICustomName
  type ISubContext (line 57) | public interface ISubContext
  class ControlVisualTreeAssetMapping (line 62) | [Serializable] public class ControlVisualTreeAssetMapping : Serializable...
  class TemplatePreset (line 67) | [CreateAssetMenu(menuName = "Graphene/Templating/ComponentTemplates")]
    method ResolveControlType (line 74) | public static ControlType ResolveControlType(object data, bool isPrimi...
    method GetControlTypeFromData (line 95) | public static ControlType GetControlTypeFromData(object data, bool isP...
    method TryGetTemplateAsset (line 118) | public bool TryGetTemplateAsset(ControlType controlType, out VisualTre...

FILE: src/Core/View/SerializedView.cs
  type SerializedView (line 13) | [System.Serializable, Toggle(nameof(Enabled))]
    method SerializedView (line 20) | public SerializedView(string id)
    method Apply (line 27) | public void Apply(VisualElement el)

FILE: src/Core/View/ViewHandle.cs
  class ViewRef (line 14) | [Serializable]
    method GetViewsFromVisualTreeAsset (line 58) | public IEnumerable<string> GetViewsFromVisualTreeAsset()
    method ViewRef (line 72) | public ViewRef(string defaultId)
    method ResolveView (line 86) | public void ResolveView(Plate plate)
    method SetPlate (line 101) | public void SetPlate(Plate plate)
    method NoParent (line 109) | public void NoParent()
  class ViewHandle (line 116) | [System.Obsolete("Use ViewRef instead")]
    method GetViewsFromVisualTreeAsset (line 143) | public IEnumerable<string> GetViewsFromVisualTreeAsset()

FILE: src/Editor/CustomDictionaryPropertyDrawers.cs
  class AnySerializableDictionaryStoragePropertyDrawer (line 9) | [CustomPropertyDrawer(typeof(SerializableDictionary<ControlType, VisualT...

FILE: src/Editor/GrapheneEditorUtilities.cs
  class GrapheneEditorUtilities (line 9) | internal static class GrapheneEditorUtilities
    class PackageRequest (line 15) | public class PackageRequest
    method CheckForUpdates (line 19) | [MenuItem("Window/Graphene/Check for updates/Graphene Core")]
    method CheckForUpdatesComponents (line 25) | [MenuItem("Window/Graphene/Check for updates/Graphene Components")]
    method MonitorPackageUpdate (line 31) | static IEnumerator MonitorPackageUpdate(PackageRequest owner, string g...

FILE: src/Lib/DragManipulator/DragManipulator.cs
  class DragManipulator (line 130) | public class DragManipulator : IManipulator {
    method OnCustomStyleResolved (line 181) | private void OnCustomStyleResolved(CustomStyleResolvedEvent e) {
    method DragBegin (line 186) | private void DragBegin(PointerDownEvent ev) {
    method DragEnd (line 204) | private void DragEnd(IPointerEvent ev) {
    method Drop (line 227) | protected virtual void Drop(VisualElement droppable) {
    method ChangeParent (line 251) | public static IVisualElementScheduledItem ChangeParent(VisualElement t...
    method ResetPosition (line 275) | public virtual void ResetPosition() {
    method CanDrop (line 279) | protected virtual bool CanDrop(Vector3 position, out VisualElement dro...
    method PointerMove (line 292) | private void PointerMove(PointerMoveEvent ev) {
  class DropEvent (line 316) | public class DropEvent : EventBase<DropEvent> {
    method Init (line 320) | protected override void Init() {
    method LocalInit (line 325) | private void LocalInit() {
    method GetPooled (line 330) | public static DropEvent GetPooled(DragManipulator dragger, VisualEleme...
    method DropEvent (line 337) | public DropEvent() => this.LocalInit();
  class IsExternalInit (line 345) | [EditorBrowsable(EditorBrowsableState.Never)]

FILE: src/Lib/SerializableDictionary/Editor/SerializableDictionaryPropertyDrawer.cs
  class SerializableDictionaryPropertyDrawer (line 8) | public class SerializableDictionaryPropertyDrawer : PropertyDrawer
    class ConflictState (line 23) | class ConflictState
    type PropertyIdentity (line 34) | struct PropertyIdentity
      method PropertyIdentity (line 36) | public PropertyIdentity(SerializedProperty property)
    type Action (line 48) | enum Action
    method OnGUI (line 55) | public override void OnGUI(Rect position, SerializedProperty property,...
    method DrawKeyValueLine (line 208) | static float DrawKeyValueLine(SerializedProperty keyProperty, Serializ...
    method DrawKeyValueLineSimple (line 225) | static float DrawKeyValueLineSimple(SerializedProperty keyProperty, Se...
    method DrawKeyValueLineExpand (line 251) | static float DrawKeyValueLineExpand(SerializedProperty keyProperty, Se...
    method CanPropertyBeExpanded (line 271) | static bool CanPropertyBeExpanded(SerializedProperty property)
    method SaveProperty (line 284) | static void SaveProperty(SerializedProperty keyProperty, SerializedPro...
    method GetPropertyHeight (line 298) | public override float GetPropertyHeight(SerializedProperty property, G...
    method GetConflictState (line 328) | static ConflictState GetConflictState(SerializedProperty property)
    method SerializableDictionaryPropertyDrawer (line 342) | static SerializableDictionaryPropertyDrawer()
    method IconContent (line 375) | static GUIContent IconContent(string name, string tooltip)
    method TempContent (line 381) | static GUIContent TempContent(string text)
    method DeleteArrayElementAtIndex (line 387) | static void DeleteArrayElementAtIndex(SerializedProperty arrayProperty...
    method GetPropertyValue (line 399) | public static object GetPropertyValue(SerializedProperty p)
    method SetPropertyValue (line 415) | static void SetPropertyValue(SerializedProperty p, object v)
    method GetPropertyValueArray (line 431) | static object GetPropertyValueArray(SerializedProperty property)
    method GetPropertyValueGeneric (line 442) | static object GetPropertyValueGeneric(SerializedProperty property)
    method SetPropertyValueArray (line 459) | static void SetPropertyValueArray(SerializedProperty property, object v)
    method SetPropertyValueGeneric (line 470) | static void SetPropertyValueGeneric(SerializedProperty property, objec...
    method ComparePropertyValues (line 485) | static bool ComparePropertyValues(object value1, object value2)
    method CompareDictionaries (line 499) | static bool CompareDictionaries(Dictionary<string, object> dict1, Dict...
    type EnumerationEntry (line 520) | struct EnumerationEntry
      method EnumerationEntry (line 526) | public EnumerationEntry(SerializedProperty keyProperty, SerializedPr...
    method EnumerateEntries (line 534) | static IEnumerable<EnumerationEntry> EnumerateEntries(SerializedProper...
  class SerializableDictionaryStoragePropertyDrawer (line 552) | public class SerializableDictionaryStoragePropertyDrawer : PropertyDrawer
    method OnGUI (line 554) | public override void OnGUI(Rect position, SerializedProperty property,...
    method GetPropertyHeight (line 560) | public override float GetPropertyHeight(SerializedProperty property, G...

FILE: src/Lib/SerializableDictionary/SerializableDictionary.cs
  class SerializableDictionaryBase (line 7) | public abstract class SerializableDictionaryBase<TKey, TValue, TValueSto...
    method SerializableDictionaryBase (line 14) | public SerializableDictionaryBase()
    method SerializableDictionaryBase (line 18) | public SerializableDictionaryBase(IDictionary<TKey, TValue> dict) : ba...
    method SerializableDictionaryBase (line 26) | protected SerializableDictionaryBase(SerializationInfo info, Streaming...
    method SetValue (line 28) | protected abstract void SetValue(TValueStorage[] storage, int i, TValu...
    method GetValue (line 29) | protected abstract TValue GetValue(TValueStorage[] storage, int i);
    method CopyFrom (line 31) | public void CopyFrom(IDictionary<TKey, TValue> dict)
    method OnAfterDeserialize (line 40) | public void OnAfterDeserialize()
    method OnBeforeSerialize (line 57) | public void OnBeforeSerialize()
  class SerializableDictionary (line 73) | public class SerializableDictionary<TKey, TValue> : SerializableDictiona...
    method SerializableDictionary (line 75) | public SerializableDictionary()
    method SerializableDictionary (line 79) | public SerializableDictionary(IDictionary<TKey, TValue> dict) : base(d...
    method SerializableDictionary (line 83) | protected SerializableDictionary(SerializationInfo info, StreamingCont...
    method GetValue (line 85) | protected override TValue GetValue(TValue[] storage, int i)
    method SetValue (line 90) | protected override void SetValue(TValue[] storage, int i, TValue value)
    class Storage (line 98) | public class Storage<T>
    method SerializableDictionary (line 106) | public SerializableDictionary()
    method SerializableDictionary (line 110) | public SerializableDictionary(IDictionary<TKey, TValue> dict) : base(d...
    method SerializableDictionary (line 114) | protected SerializableDictionary(SerializationInfo info, StreamingCont...
    method GetValue (line 116) | protected override TValue GetValue(TValueStorage[] storage, int i)
    method SetValue (line 121) | protected override void SetValue(TValueStorage[] storage, int i, TValu...
  class SerializableDictionary (line 96) | public static class SerializableDictionary
    method SerializableDictionary (line 75) | public SerializableDictionary()
    method SerializableDictionary (line 79) | public SerializableDictionary(IDictionary<TKey, TValue> dict) : base(d...
    method SerializableDictionary (line 83) | protected SerializableDictionary(SerializationInfo info, StreamingCont...
    method GetValue (line 85) | protected override TValue GetValue(TValue[] storage, int i)
    method SetValue (line 90) | protected override void SetValue(TValue[] storage, int i, TValue value)
    class Storage (line 98) | public class Storage<T>
    method SerializableDictionary (line 106) | public SerializableDictionary()
    method SerializableDictionary (line 110) | public SerializableDictionary(IDictionary<TKey, TValue> dict) : base(d...
    method SerializableDictionary (line 114) | protected SerializableDictionary(SerializationInfo info, StreamingCont...
    method GetValue (line 116) | protected override TValue GetValue(TValueStorage[] storage, int i)
    method SetValue (line 121) | protected override void SetValue(TValueStorage[] storage, int i, TValu...
  class SerializableDictionary (line 104) | public class SerializableDictionary<TKey, TValue, TValueStorage> : Seria...
    method SerializableDictionary (line 75) | public SerializableDictionary()
    method SerializableDictionary (line 79) | public SerializableDictionary(IDictionary<TKey, TValue> dict) : base(d...
    method SerializableDictionary (line 83) | protected SerializableDictionary(SerializationInfo info, StreamingCont...
    method GetValue (line 85) | protected override TValue GetValue(TValue[] storage, int i)
    method SetValue (line 90) | protected override void SetValue(TValue[] storage, int i, TValue value)
    class Storage (line 98) | public class Storage<T>
    method SerializableDictionary (line 106) | public SerializableDictionary()
    method SerializableDictionary (line 110) | public SerializableDictionary(IDictionary<TKey, TValue> dict) : base(d...
    method SerializableDictionary (line 114) | protected SerializableDictionary(SerializationInfo info, StreamingCont...
    method GetValue (line 116) | protected override TValue GetValue(TValueStorage[] storage, int i)
    method SetValue (line 121) | protected override void SetValue(TValueStorage[] storage, int i, TValu...
Condensed preview — 169 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (372K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 721,
    "preview": "# These are supported funding model platforms\n\ngithub: [LudiKha] # Replace with up to 4 GitHub Sponsors-enabled username"
  },
  {
    "path": "LICENSE",
    "chars": 1093,
    "preview": "MIT License\n\nCopyright (c) 2020 Khaya Ludidi - CupBearer Interactive\n\nPermission is hereby granted, free of charge, to a"
  },
  {
    "path": "README.md",
    "chars": 16751,
    "preview": "<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/LudiKha/Graphene/master/docs/images/graphene-logo-full."
  },
  {
    "path": "docs/About.md",
    "chars": 153,
    "preview": "layout: page\ntitle: \"About Graphene\"\npermalink: /about/\n\n![Graphene](images/graphene-logo-full.png)\n\n# Graphene\n## UI Fr"
  },
  {
    "path": "docs/_config.yml",
    "chars": 26,
    "preview": "theme: jekyll-theme-cayman"
  },
  {
    "path": "docs/howto.md",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/Core/Binding/Binder.cs",
    "chars": 28585,
    "preview": "using System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene\n{\n "
  },
  {
    "path": "src/Core/Binding/Binder.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: f25cd91944aa2e546b1708c66852751c\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Binding/Binding.cs",
    "chars": 4781,
    "preview": "\n\nusing System;\nusing System.ComponentModel;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene\n{\n  u"
  },
  {
    "path": "src/Core/Binding/Binding.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 4c859ae80f4d89648b8c3b6dc1839149\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Binding/BindingAttribute.cs",
    "chars": 8089,
    "preview": "using System.Collections;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing UnityEngine;\n\n"
  },
  {
    "path": "src/Core/Binding/BindingAttribute.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 1f614598db3d14645979fed59a3b5945\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Binding/BindingsManager.cs",
    "chars": 7727,
    "preview": "\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing UnityEngine."
  },
  {
    "path": "src/Core/Binding/BindingsManager.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 4e490e9f02423f245a808e66b6d9c602\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Binding/CollectionBinding.cs",
    "chars": 1368,
    "preview": "using System.Collections;\nusing UnityEngine.UIElements;\n\nnamespace Graphene\n{\n    using Kinstrife.Core.ReflectionHelper"
  },
  {
    "path": "src/Core/Binding/CollectionBinding.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 6df237851253fc241a8dd9e269f6276c\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Binding/MemberBinding.cs",
    "chars": 1219,
    "preview": "using UnityEngine.UIElements;\n\nnamespace Graphene\n{\n  using Kinstrife.Core.ReflectionHelpers;\n  using UnityEngine;\n\n  p"
  },
  {
    "path": "src/Core/Binding/MemberBinding.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 51eed3340e1759745903e1cc5f44143d\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Binding.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 6c2a5a11ef9582442b314d518afb15ec\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Core/Extensions/ButtonGroup.cs",
    "chars": 4890,
    "preview": "\nusing Graphene.ViewModel;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing "
  },
  {
    "path": "src/Core/Extensions/ButtonGroup.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: bc01c42213f651244a970ed2b40bca5a\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Extensions/CycleField.cs",
    "chars": 6281,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\n\nusing "
  },
  {
    "path": "src/Core/Extensions/CycleField.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: eeb1b79b04839bd4389dd0e1a6457758\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Extensions/Dialog.cs",
    "chars": 3866,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\n\nusing "
  },
  {
    "path": "src/Core/Extensions/Dialog.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 6ba5abe3b1bb58c439073459c2b50355\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Extensions/GrapheneRoot.cs",
    "chars": 1422,
    "preview": "\nusing System;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene.Elements\n{\n  /// <summary>\n  /// Ro"
  },
  {
    "path": "src/Core/Extensions/GrapheneRoot.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 41eb40e62488c9842b7021276222eaf1\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Extensions/If.cs",
    "chars": 2435,
    "preview": "\nusing System;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene.Elements\n{\n  public class If : Bind"
  },
  {
    "path": "src/Core/Extensions/If.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 6c0886185b9292347a8eef22665cc9e5\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Extensions/Route.cs",
    "chars": 3533,
    "preview": "\nusing System;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene.Elements\n{\n    public class Route :"
  },
  {
    "path": "src/Core/Extensions/Route.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 2cc316cb1922df641ac18819655d7e7b\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Extensions/SelectField.cs",
    "chars": 9134,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\n\nusing "
  },
  {
    "path": "src/Core/Extensions/SelectField.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: bac1afa6a79c1714680bfc884ada8948\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Extensions/TemplateTypes/Button.cs",
    "chars": 1069,
    "preview": "\nusing System;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene.Elements\n{\n  public class GrButton "
  },
  {
    "path": "src/Core/Extensions/TemplateTypes/Button.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 4063ec610a60a9049a8dc4a3a2d75ab8\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Extensions/TemplateTypes/TemplateRef.cs",
    "chars": 3274,
    "preview": "using System.Linq;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene.Elements\n{\n  public class Templ"
  },
  {
    "path": "src/Core/Extensions/TemplateTypes/TemplateRef.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: d20f4dbc23d31124ca95a7906001617f\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Extensions/TemplateTypes.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 4de6f3d3fa92a844a98caeaeabfba7d4\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Core/Extensions/View.cs",
    "chars": 2611,
    "preview": "\nusing System;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene.Elements\n{\n  public class View : Vi"
  },
  {
    "path": "src/Core/Extensions/View.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: a191edcfe0e527d4d91c17ee1926751d\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Extensions/VisualElementExtensions.cs",
    "chars": 4875,
    "preview": "using System.Collections.Generic;\nusing UnityEngine.UIElements;\n\nnamespace Graphene\n{\n  public static class VisualEleme"
  },
  {
    "path": "src/Core/Extensions/VisualElementExtensions.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: fd3bb9a5a9100d24cb94c9a528a30eb0\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Extensions.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 4abeed0c73932b946972d66da4b7ae42\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Core/Graphene.cs",
    "chars": 9276,
    "preview": "using System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Pro"
  },
  {
    "path": "src/Core/Graphene.cs.meta",
    "chars": 294,
    "preview": "fileFormatVersion: 2\nguid: 3df2f2c9411e2af419b0ebc039577ce4\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/GrapheneComponent.cs",
    "chars": 2050,
    "preview": "using UnityEngine;\n\nnamespace Graphene\n{\n    /// <summary>\n    /// Base class for all components that participate in the"
  },
  {
    "path": "src/Core/GrapheneComponent.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: d32a65210f6ccde4ba4983f9164de0b3\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Injector.cs",
    "chars": 640,
    "preview": "using System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace Graphene\n{"
  },
  {
    "path": "src/Core/Injector.cs.meta",
    "chars": 294,
    "preview": "fileFormatVersion: 2\nguid: d8e759c0d6277b6448cce98e37e22305\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Interfaces.cs",
    "chars": 2550,
    "preview": "namespace Graphene\n{\n  using Elements;\n  using UnityEngine.UIElements;\n\n  public interface IGrapheneDependent\n  {\n  }\n\n"
  },
  {
    "path": "src/Core/Interfaces.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 59b985a9f1ab787479e438f05a3b2567\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Model/BindableObjects/BindableBaseField.cs",
    "chars": 8061,
    "preview": "using System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Runtime.CompilerServices"
  },
  {
    "path": "src/Core/Model/BindableObjects/BindableBaseField.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: b7a28165c3f71c34e9b0eb23b27cb50d\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Model/BindableObjects/BindableObject.cs",
    "chars": 5727,
    "preview": "\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.Serialization;\nusing UnityEngine;\nusing UnityEngin"
  },
  {
    "path": "src/Core/Model/BindableObjects/BindableObject.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 2a481b0795ebfad4c9771a06eb5677c0\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Model/BindableObjects/ListBindable.cs",
    "chars": 4050,
    "preview": "using Sirenix.OdinInspector;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing Unity"
  },
  {
    "path": "src/Core/Model/BindableObjects/ListBindable.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 90b16a7dd3d8c654693abccb70045774\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Model/BindableObjects.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 21f4f86d9ed39a04dae5f8a10dc50541\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Core/Model/GenericModelAsset.cs",
    "chars": 621,
    "preview": "using System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene.ViewModel\n{\n  pu"
  },
  {
    "path": "src/Core/Model/GenericModelAsset.cs.meta",
    "chars": 291,
    "preview": "fileFormatVersion: 2\nguid: 3c77b204580fbe947b11e389b5321ed7\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Model/GenericModelBehaviour.cs",
    "chars": 1754,
    "preview": "using System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene.ViewModel\n{\n  pu"
  },
  {
    "path": "src/Core/Model/GenericModelBehaviour.cs.meta",
    "chars": 291,
    "preview": "fileFormatVersion: 2\nguid: 35cb04044c5eb594495aaeae5ccb11a2\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Model/ScriptableObjectModel.cs",
    "chars": 1228,
    "preview": "\nusing System;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene\n{"
  },
  {
    "path": "src/Core/Model/ScriptableObjectModel.cs.meta",
    "chars": 294,
    "preview": "fileFormatVersion: 2\nguid: 9c7aa560e9cd18a45baf58f91137a8cb\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Model/ViewModel/FormViewModel.cs",
    "chars": 4900,
    "preview": "using Sirenix.OdinInspector;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene.ViewModel\n{\n  public "
  },
  {
    "path": "src/Core/Model/ViewModel/FormViewModel.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 4966129684538d749affd14e9fd70661\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Model/ViewModel/MultiFormViewModel.cs",
    "chars": 2286,
    "preview": "using Sirenix.OdinInspector;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.U"
  },
  {
    "path": "src/Core/Model/ViewModel/MultiFormViewModel.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: bf9529738e742e84fbf6e0d45ae2e2d8\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Model/ViewModel/NavViewModel.cs",
    "chars": 1828,
    "preview": "using System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene.ViewModel\n{\n  pub"
  },
  {
    "path": "src/Core/Model/ViewModel/NavViewModel.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: ddce112e23d338443b4d10a813ce4c25\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Model/ViewModel/ViewModelComponent.cs",
    "chars": 1843,
    "preview": "using System;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene.ViewModel\n{\n  /// <summary>\n  /// A "
  },
  {
    "path": "src/Core/Model/ViewModel/ViewModelComponent.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 94c3d559523a63c4298689c839b2109d\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Model/ViewModel.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: c868cc3a0db70c940af6b51404f58456\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Core/Model.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: d78566ea2cede254091b6cbfd364100d\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Core/Plate.cs",
    "chars": 22015,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.Events;\nusing U"
  },
  {
    "path": "src/Core/Plate.cs.meta",
    "chars": 547,
    "preview": "fileFormatVersion: 2\nguid: 53b76209daa58fc4787cd6e9815c5a8c\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Rendering/RenderUtils.cs",
    "chars": 7485,
    "preview": "using Kinstrife.Core.ReflectionHelpers;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing"
  },
  {
    "path": "src/Core/Rendering/RenderUtils.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 8d558fdcdf4792b49aaa6d7a87ce230c\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Rendering/Renderer.cs",
    "chars": 5212,
    "preview": "using System.Collections;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene\n{\n  using Elements;\n\n  /"
  },
  {
    "path": "src/Core/Rendering/Renderer.cs.meta",
    "chars": 432,
    "preview": "fileFormatVersion: 2\nguid: e3452e75856c69d42a3a5f4e1dbea800\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Rendering.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 0dd9ac2526742164ea65cbcc31b12095\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Core/Routing/EnableOnState.cs",
    "chars": 1934,
    "preview": "using System.Collections.Generic;\nusing UnityEngine;\n\nnamespace Graphene\n{\n  /// <summary>\n  /// Component that activat"
  },
  {
    "path": "src/Core/Routing/EnableOnState.cs.meta",
    "chars": 294,
    "preview": "fileFormatVersion: 2\nguid: 5cb892b6070f21c4aa006bc9cde8ecf0\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Routing/Interpreters/ApplicationStateInterpreter.cs",
    "chars": 7817,
    "preview": "using Graphene;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UIElem"
  },
  {
    "path": "src/Core/Routing/Interpreters/ApplicationStateInterpreter.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 11e217e82870451488cdb1a2928425f1\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Routing/Interpreters/NavigationStateHandler.cs",
    "chars": 3744,
    "preview": "using UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graphene\n{\n  using Elements;\n\n  /// <summary>\n  /// Navigat"
  },
  {
    "path": "src/Core/Routing/Interpreters/NavigationStateHandler.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: db9704c18ef205445b684710a72a91dc\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Routing/Interpreters/StateInterpreter.cs",
    "chars": 985,
    "preview": "using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace Graphene\n{\n  public interface"
  },
  {
    "path": "src/Core/Routing/Interpreters/StateInterpreter.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 8142e1a2c5cc51e4495dd52a607b82ae\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Routing/Interpreters.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 7b0d94d5c697e88419f85d034e9257a5\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Core/Routing/Router.cs",
    "chars": 10307,
    "preview": "\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Graph"
  },
  {
    "path": "src/Core/Routing/Router.cs.meta",
    "chars": 294,
    "preview": "fileFormatVersion: 2\nguid: b0572ba23ed7bfb45bccb3d798fa328e\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Routing/StateHandle.cs",
    "chars": 3172,
    "preview": "using UnityEngine;\n\nnamespace Graphene\n{\n  public enum ChildActivationMode\n  {\n    Manual,\n    ShowWithParent,\n    Defa"
  },
  {
    "path": "src/Core/Routing/StateHandle.cs.meta",
    "chars": 294,
    "preview": "fileFormatVersion: 2\nguid: ed9a3898638b389418cb68abe6b00ef9\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Routing/StringEnableOnState.cs",
    "chars": 297,
    "preview": "using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace Graphene\n{\n  /// <summary>\n  "
  },
  {
    "path": "src/Core/Routing/StringEnableOnState.cs.meta",
    "chars": 294,
    "preview": "fileFormatVersion: 2\nguid: 67e79be0a9fe43f41bd545143176b6fa\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Routing/StringRouter.cs",
    "chars": 3146,
    "preview": "\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\n\nnamespace Graphene\n{\n  /// <summary>\n "
  },
  {
    "path": "src/Core/Routing/StringRouter.cs.meta",
    "chars": 294,
    "preview": "fileFormatVersion: 2\nguid: 905d8383600c12b4dba5c1916e276442\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Routing/StringStateHandle.cs",
    "chars": 834,
    "preview": "using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace Graphene\n{\n  /// <summary>\n  "
  },
  {
    "path": "src/Core/Routing/StringStateHandle.cs.meta",
    "chars": 294,
    "preview": "fileFormatVersion: 2\nguid: 7203da84032242f48a61f59888ca04d7\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Routing.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: e687d2c6d99c2d4459b39b680325660b\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Core/Styling/AlignItemsOverride.cs",
    "chars": 376,
    "preview": "using UnityEngine.UIElements;\n\n#if ODIN_INSPECTOR\n#endif\n\nnamespace Graphene\n{\n  [System.Serializable]\n  public sealed "
  },
  {
    "path": "src/Core/Styling/AlignItemsOverride.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: c9b2129d52baf0043a23668a36c090a4\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Styling/FlexDirectionOverride.cs",
    "chars": 665,
    "preview": "using UnityEngine.UIElements;\n\n#if ODIN_INSPECTOR\n#endif\n\nnamespace Graphene\n{\n  [System.Serializable]\n  public sealed "
  },
  {
    "path": "src/Core/Styling/FlexDirectionOverride.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: efa16af0abd783f4aab05bc4bec5f92b\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Styling/InlineStyleOverrides.cs",
    "chars": 2768,
    "preview": "using UnityEngine;\nusing UnityEngine.UIElements;\n\nusing Sirenix.OdinInspector;\n\nnamespace Graphene\n{\n\n  /// <summary>\n "
  },
  {
    "path": "src/Core/Styling/InlineStyleOverrides.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 1997ab07644fc094695caf1539f96170\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Styling/JustifyOverride.cs",
    "chars": 1184,
    "preview": "using UnityEngine.UIElements;\nusing static UnityEngine.UI.CanvasScaler;\n\n\n#if ODIN_INSPECTOR\n#endif\n\nnamespace Graphene"
  },
  {
    "path": "src/Core/Styling/JustifyOverride.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: cd169699503c46e49b265c0504c2e1e2\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Styling/StyleOverride.cs",
    "chars": 691,
    "preview": "using System;\nusing UnityEngine.UIElements;\n\n#if ODIN_INSPECTOR\n#endif\n\nnamespace Graphene\n{\n#if ODIN_INSPECTOR\n  [Sire"
  },
  {
    "path": "src/Core/Styling/StyleOverride.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 80d10b93078bca343931a18a83a5027d\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Styling/WrapOverride.cs",
    "chars": 362,
    "preview": "using UnityEngine.UIElements;\n\n#if ODIN_INSPECTOR\n#endif\n\nnamespace Graphene\n{\n  [System.Serializable]\n  public sealed "
  },
  {
    "path": "src/Core/Styling/WrapOverride.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: abf88d1f7dd2cef43ae6a6fc899bdb04\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Styling.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 7243c0fb90369024fadd0cb72120c84f\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Core/Templating/TemplatePreset.cs",
    "chars": 3582,
    "preview": "\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Events;"
  },
  {
    "path": "src/Core/Templating/TemplatePreset.cs.meta",
    "chars": 294,
    "preview": "fileFormatVersion: 2\nguid: fecf578bfcf34544fb992fb36cc63ce3\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/Templating.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 18f3fea75a8c9b24da7bb9ab083e531d\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Core/View/SerializedView.cs",
    "chars": 749,
    "preview": "using UnityEngine;\nusing UnityEngine.UIElements;\n\n#if ODIN_INSPECTOR\nusing Sirenix.OdinInspector;\n#endif\n\nnamespace Gra"
  },
  {
    "path": "src/Core/View/SerializedView.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 7b1deb9f87a8f914cac2440ff9be962a\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/View/ViewHandle.cs",
    "chars": 3945,
    "preview": "using Graphene.Elements;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing Un"
  },
  {
    "path": "src/Core/View/ViewHandle.cs.meta",
    "chars": 294,
    "preview": "fileFormatVersion: 2\nguid: 6ebff670864e5cd4d87ede0a925c3a68\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Core/View.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 6f3253f7286180045afee8f02c25b53b\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Core.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 3e44d045c365d3345a3368115362a35f\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Editor/CustomDictionaryPropertyDrawers.cs",
    "chars": 415,
    "preview": "using System.Collections;\nusing System.Collections.Generic;\nusing UnityEditor;\nusing UnityEngine;\nusing UnityEngine.UIE"
  },
  {
    "path": "src/Editor/CustomDictionaryPropertyDrawers.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 46100f4664e80f14dab215b9e06a4763\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Editor/Graphene.Editor.asmdef",
    "chars": 545,
    "preview": "{\n    \"name\": \"Graphene.Editor\",\n    \"references\": [\n        \"GUID:5182bff32a626fa409ad510e8c679a69\",\n        \"GUID:a9d2"
  },
  {
    "path": "src/Editor/Graphene.Editor.asmdef.meta",
    "chars": 166,
    "preview": "fileFormatVersion: 2\nguid: 979c01504af7b11408532aa7eaf930d2\nAssemblyDefinitionImporter:\n  externalObjects: {}\n  userData"
  },
  {
    "path": "src/Editor/GrapheneEditorUtilities.cs",
    "chars": 1587,
    "preview": "using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditor;\nusing Unity.EditorCor"
  },
  {
    "path": "src/Editor/GrapheneEditorUtilities.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 49bdd157a434fa944a0149e48ef81046\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Editor/ViewSelectorStringDrawer.cs",
    "chars": 924,
    "preview": "\n//#if ODIN_INSPECTOR\n//using System.Collections;\n//using System.Collections.Generic;\n//using UnityEngine;\n//using Unity"
  },
  {
    "path": "src/Editor/ViewSelectorStringDrawer.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 5ae8cf884934ad44b9796dc46b098012\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Editor.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 199242626b096f64a80e9a0629ed98dc\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Graphene.Core.asmdef",
    "chars": 497,
    "preview": "{\n    \"name\": \"Graphene.Core\",\n    \"rootNamespace\": \"\",\n    \"references\": [\n        \"GUID:a9d2a6efafebd5e47b01684a70d95c"
  },
  {
    "path": "src/Graphene.Core.asmdef.meta",
    "chars": 166,
    "preview": "fileFormatVersion: 2\nguid: 5182bff32a626fa409ad510e8c679a69\nAssemblyDefinitionImporter:\n  externalObjects: {}\n  userData"
  },
  {
    "path": "src/Lib/DragManipulator/DragManipulator.cs",
    "chars": 12494,
    "preview": "/* Original code[1] Copyright (c) 2022 Shane Celis[2]\n   Licensed under the MIT License[3]\n\n   [1]: https://gist.github."
  },
  {
    "path": "src/Lib/DragManipulator/DragManipulator.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 4ed0bf7b15ca4544e9c8ca59068db3c1\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "src/Lib/DragManipulator.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 04fced0da9d8a4c4bb8d1a6e2af0ecff\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Lib/SerializableDictionary/Editor/SerializableDictionary.Editor.asmdef",
    "chars": 412,
    "preview": "{\n    \"name\": \"SerializableDictionary.Editor\",\n    \"references\": [\n        \"GUID:a9d2a6efafebd5e47b01684a70d95cc5\"\n    ]"
  },
  {
    "path": "src/Lib/SerializableDictionary/Editor/SerializableDictionary.Editor.asmdef.meta",
    "chars": 166,
    "preview": "fileFormatVersion: 2\nguid: dd4a8158362adf24fa2558eb7adb4b12\nAssemblyDefinitionImporter:\n  externalObjects: {}\n  userData"
  },
  {
    "path": "src/Lib/SerializableDictionary/Editor/SerializableDictionaryPropertyDrawer.cs",
    "chars": 18587,
    "preview": "using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEditor;\nusing System.Reflecti"
  },
  {
    "path": "src/Lib/SerializableDictionary/Editor/SerializableDictionaryPropertyDrawer.cs.meta",
    "chars": 264,
    "preview": "fileFormatVersion: 2\nguid: 91da51d02ab9ebc459d80d5965d40d19\ntimeCreated: 1492869349\nlicenseType: Store\nMonoImporter:\n  s"
  },
  {
    "path": "src/Lib/SerializableDictionary/Editor.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 38f5d7794faaa21468f705ca2a23149f\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Lib/SerializableDictionary/SerializableDictionary.Runtime.asmdef",
    "chars": 47,
    "preview": "{\n\t\"name\": \"SerializableDictionary.Runtime\"\n}\n"
  },
  {
    "path": "src/Lib/SerializableDictionary/SerializableDictionary.Runtime.asmdef.meta",
    "chars": 166,
    "preview": "fileFormatVersion: 2\nguid: a9d2a6efafebd5e47b01684a70d95cc5\nAssemblyDefinitionImporter:\n  externalObjects: {}\n  userData"
  },
  {
    "path": "src/Lib/SerializableDictionary/SerializableDictionary.cs",
    "chars": 2794,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Runtime.Serialization;\nusing Uni"
  },
  {
    "path": "src/Lib/SerializableDictionary/SerializableDictionary.cs.meta",
    "chars": 264,
    "preview": "fileFormatVersion: 2\nguid: e7be1c9624387604fba4005ccf7dbd5a\ntimeCreated: 1492868176\nlicenseType: Store\nMonoImporter:\n  s"
  },
  {
    "path": "src/Lib/SerializableDictionary.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: ec22cd43b8631bf4dbb28130429205be\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Lib.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 896708c62f5edba45b8a132d08ee914d\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Resources/Icons/atom.png.meta",
    "chars": 2552,
    "preview": "fileFormatVersion: 2\nguid: d17647a721ae9b6418d60aabba5be55f\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons/form.png.meta",
    "chars": 2552,
    "preview": "fileFormatVersion: 2\nguid: 806f5574c9706cd4e812686596744160\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons/graphene.png.meta",
    "chars": 2552,
    "preview": "fileFormatVersion: 2\nguid: db72b2a2b6f47b544a0458d9aa7b0e69\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons/injector.png.meta",
    "chars": 2552,
    "preview": "fileFormatVersion: 2\nguid: d249967811185734b8114d4b8977f433\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons/layout.png.meta",
    "chars": 2085,
    "preview": "fileFormatVersion: 2\nguid: 779432a5e218db5438ca646cb9970341\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons/molecule.png.meta",
    "chars": 2552,
    "preview": "fileFormatVersion: 2\nguid: 2a950971ac44a1f4bbec1a1338d2f483\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons/plate.png.meta",
    "chars": 2552,
    "preview": "fileFormatVersion: 2\nguid: d5720deaef5568642aae7621cd85c1d4\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons/quantum.png.meta",
    "chars": 2552,
    "preview": "fileFormatVersion: 2\nguid: ab20f1c106c55d84b82bc7d5a640819b\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons/renderer.png.meta",
    "chars": 2552,
    "preview": "fileFormatVersion: 2\nguid: 9d85d8a741327e143b28987b5a69ef93\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons/router.png.meta",
    "chars": 2552,
    "preview": "fileFormatVersion: 2\nguid: 3fa61ff64b7c4e64e8b944ba5d308365\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons/state.png.meta",
    "chars": 2552,
    "preview": "fileFormatVersion: 2\nguid: 724b44860269a9f4abed118244135936\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons/template.png.meta",
    "chars": 2552,
    "preview": "fileFormatVersion: 2\nguid: 9c6112e092c235c4388c5cc406349194\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons/theme.png.meta",
    "chars": 2554,
    "preview": "fileFormatVersion: 2\nguid: 73d27894540ca4a47ba97356fee56092\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Icons.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 0df9eec597c9c3f4db1681e862dd42b9\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Resources/Logo/graphene-logo-full.png.meta",
    "chars": 2554,
    "preview": "fileFormatVersion: 2\nguid: 4ba3b61aa9eee63418d9a0c7be4901f8\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Logo/graphene-logo-white.png.meta",
    "chars": 2880,
    "preview": "fileFormatVersion: 2\nguid: 79495ad5c6a23a54e9a080b692eca7b1\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Logo/graphene-logo.png.meta",
    "chars": 2552,
    "preview": "fileFormatVersion: 2\nguid: a7567e94e4334dd4bb5bed2d09495114\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjec"
  },
  {
    "path": "src/Resources/Logo.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: 2a9a343a7c0ac0d4781c5c2075c9129c\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/Resources.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: c57b36d4b8516cb49b133e196e2765ed\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "src/package.json",
    "chars": 638,
    "preview": "{\n  \"name\": \"com.graphene.core\",\n  \"version\": \"0.1.4\",\n  \"displayName\": \"Graphene\",\n  \"description\": \"A lightweight & fl"
  },
  {
    "path": "src/package.json.meta",
    "chars": 163,
    "preview": "fileFormatVersion: 2\nguid: a7886040c573d5c4183352bdef617071\nPackageManifestImporter:\n  externalObjects: {}\n  userData: \n"
  }
]

About this extraction

This page contains the full source code of the LudiKha/Graphene GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 169 files (333.3 KB), approximately 92.4k tokens, and a symbol index with 732 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!