LudiKha / Graphene

Graphene for Unity UI Toolkit is a lightweight and modular framework for building user interfaces
MIT License
147 stars 9 forks source link
attributes csharp css game-development graphene html toolkit ui ui-components unity unity3d uss uxml web

 

License: MIT last-commit open-issues

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

 

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.

It comes with a component-kit library, sample project several VisualElement extensions and an online demo to get you started.

Online Demo

Check out the WebGL demo

Installation

Using Unity Package Manager (For Unity 2018.3 or later)

You can install the package via UPM by adding the line below to your project's `Packages/manifest.json` file.   >You can find this file by opening your project's *Packages* folder in a file browser, it is not displayed in the editor.
{
  "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.

  1. Follow the installation instructions
  2. In the Package Manager, click the Git button 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.

 


 

Quickstart

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

1: Constructing the hierarchy

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

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), this will be bound to the model too.

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

3: Routing

Note: It is also possible to encapsulate a button within a Route element.

<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.

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

 


 

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. Plates 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:

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

Views

Rendering

Model

Templating

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:

<ui:Button text="Button" name="ButtonFramed" focusable="true" tooltip="This is a button" binding-path="Value" class="button button-framed light">
  <ui:Style src="https://github.com/LudiKha/Graphene/raw/master/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.

var clone = myTemplateAsset.Instantiate();
...

Instantiating a template via UXML

Graphene allows you to statically type control types using the following syntax:

<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.

Scopes

Binding Passes

  1. Static
  2. Dynamic

    Static Binding

Dynamic Binding

Routing

Theming

Theme

A Theme is a data asset that can be used to author high-level styling configurations for (parts of) the VisualTree. It consists of a collection of StyleSheets, and can be nested to create reusable styling configurations using overrides.

Using themes

Create a theme via the following menu command:

Assets/Create/Graphene/Theming/Theme

Themes are assigned to the VisualTree when assigned to the Graphene component, or a sub-section when assigned to a Plate.

To manually apply a theme to a VisualElement, the following method is available.

myTheme.ApplyStyles(el);

Localization

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

 


 

Inspector Extensions

Graphene supports two third party inspector extensions out of the box: Sirenix Odin Inspector (paid) and NaughtyAttributes (free). Graphene relies on these to expose optional enhanced functionality to the inspector windows.

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.