Alchemy/README.md

327 lines
10 KiB
Markdown
Raw Normal View History

2023-12-01 20:54:41 -05:00
# Alchemy
2024-02-20 01:53:56 -05:00
<img src="https://github.com/AnnulusGames/Alchemy/blob/main/docs/images/header.png" width="800">
2023-12-01 20:54:41 -05:00
2023-12-02 01:17:12 -05:00
[![license](https://img.shields.io/badge/LICENSE-MIT-green.svg)](LICENSE)
2023-12-02 01:17:50 -05:00
[日本語版READMEはこちら](README_JA.md)
2023-12-02 01:17:12 -05:00
## Overview
2024-02-20 01:53:56 -05:00
Alchemy is a library that provides inspector extensions using attributes.
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
In addition to adding easy and powerful editor extensions based on attributes, it allows serialization of any type (Dictionary, Hashset, Nullable, Tuple, etc...) through its own serialization process, making it possible to edit them in the inspector. By using Source Generator to dynamically generate the necessary code, it works simply by adding attributes to the target type marked as partial. There is no need to inherit from dedicated classes as with Odin.
<img src="https://github.com/AnnulusGames/Alchemy/blob/main/docs/images/img-v2.0.png" width="800">
Additionally, with the new features of v2.0, EditorWindow extensions and Hierarchy extensions have been added. These make it easy to create tools that streamline the development workflow in the editor.
2023-12-02 01:17:12 -05:00
## Features
* Adds over 30 attributes to extend the Inspector
2024-02-20 01:53:56 -05:00
* Supports SerializeReference, allowing selection of types from a dropdown
* Serialize any type (Dictionary, Hashset, Nullable, Tuple, etc...) / Editable in Inspector
* Creation of EditorWindow using attributes
* Provides features to improve usability of the Hierarchy
* Creation of custom attributes that work with Alchemy
2023-12-02 01:17:12 -05:00
## Setup
### Requirements
2024-02-20 01:53:56 -05:00
* Unity 2021.2 or higher (Recommended: 2022.1 or higher for serialization extensions)
* Serialization 2.0 or higher (for serialization extensions)
2023-12-02 01:17:12 -05:00
### Installation
2024-02-20 01:53:56 -05:00
1. Open Package Manager from Window > Package Manager
2. Click on the "+" button > Add package from git URL
2023-12-02 01:17:12 -05:00
3. Enter the following URL:
```
https://github.com/AnnulusGames/Alchemy.git?path=/Alchemy/Assets/Alchemy
```
2024-02-20 01:53:56 -05:00
Or open Packages/manifest.json and add the following to the dependencies block:
2023-12-02 01:17:12 -05:00
```json
{
"dependencies": {
"com.annulusgames.alchemy": "https://github.com/AnnulusGames/Alchemy.git?path=/Alchemy/Assets/Alchemy"
}
}
```
2024-02-20 01:53:56 -05:00
## Documentation
2023-12-02 08:24:21 -05:00
2024-02-20 01:53:56 -05:00
The full version of the documentation can be found [here](https://annulusgames.github.io/Alchemy/).
2023-12-02 08:24:21 -05:00
2023-12-02 01:17:12 -05:00
## Basic Usage
To customize the display in the Inspector, add attributes to the fields of the class.
```cs
using UnityEngine;
using UnityEngine.UIElements;
2024-02-20 01:53:56 -05:00
using Alchemy.Inspector;
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
public class AttributesExample : MonoBehaviour
2023-12-02 01:17:12 -05:00
{
[LabelText("Custom Label")]
public float foo;
[HideLabel]
public Vector3 bar;
[AssetsOnly]
public GameObject baz;
[Title("Title")]
[HelpBox("HelpBox", HelpBoxMessageType.Info)]
[ReadOnly]
public string message = "Read Only";
}
```
2024-02-20 01:53:56 -05:00
<img src="https://github.com/AnnulusGames/Alchemy/blob/main/docs/images/img-attributes-example.png" width="600">
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
Various attributes for grouping each field are also provided. Each group can be nested by separating with a slash `/`.
2023-12-02 01:17:12 -05:00
```cs
using UnityEngine;
using Alchemy.Inspector;
2024-02-20 01:53:56 -05:00
public class GroupAttributesExample : MonoBehaviour
2023-12-02 01:17:12 -05:00
{
2024-02-20 01:53:56 -05:00
[FoldoutGroup("Foldout")]
public int a;
[FoldoutGroup("Foldout")]
public int b;
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
[FoldoutGroup("Foldout")]
public int c;
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
[TabGroup("Tab", "Tab1")]
public int x;
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
[TabGroup("Tab", "Tab2")]
public string y;
[TabGroup("Tab", "Tab3")]
public Vector3 z;
2023-12-02 01:17:12 -05:00
}
```
2024-02-20 01:53:56 -05:00
<img src="https://github.com/AnnulusGames/Alchemy/blob/main/docs/images/img-group-1.png" width="600">
2023-12-02 01:17:12 -05:00
By adding the `[Button]` attribute to a method, the method can be executed from the Inspector.
```cs
using System.Text;
using UnityEngine;
using Alchemy.Inspector;
[Serializable]
2024-02-20 01:53:56 -05:00
public sealed class Example : IExample
2023-12-02 01:17:12 -05:00
{
public float foo;
public Vector3 bar;
public GameObject baz;
}
2024-02-20 01:53:56 -05:00
public class ButtonExample : MonoBehaviour
2023-12-02 01:17:12 -05:00
{
[Button]
public void Foo()
{
Debug.Log("Foo");
}
[Button]
public void Foo(int parameter)
{
Debug.Log("Foo: " + parameter);
}
[Button]
2024-02-20 01:53:56 -05:00
public void Foo(Example parameter)
2023-12-02 01:17:12 -05:00
{
var builder = new StringBuilder();
builder.AppendLine();
builder.Append("foo = ").AppendLine(parameter.foo.ToString());
builder.Append("bar = ").AppendLine(parameter.bar.ToString());
builder.Append("baz = ").Append(parameter.baz == null ? "Null" : parameter.baz.ToString());
Debug.Log("Foo: " + builder.ToString());
}
}
```
2024-02-20 01:53:56 -05:00
<img src="https://github.com/AnnulusGames/Alchemy/blob/main/docs/images/img-button.png" width="600">
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
Alchemy provides many other attributes. The list of available attributes can be found in the [documentation](https://annulusgames.github.io/Alchemy/articles/en/inspector-extension-with-attributes.html).
2023-12-02 01:17:12 -05:00
## Editing Interfaces/Abstract Classes
2024-02-20 01:53:56 -05:00
Alchemy supports Unity's SerializeReference. By adding the `[SerializeReference]` attribute, interfaces and abstract classes can be edited in the Inspector.
2023-12-02 01:17:12 -05:00
```cs
using UnityEngine;
2024-02-20 01:53:56 -05:00
public interface IExample { }
2023-12-02 01:17:12 -05:00
[Serializable]
2024-02-20 01:53:56 -05:00
public sealed class ExampleA : IExample
2023-12-02 01:17:12 -05:00
{
public float alpha;
}
[Serializable]
2024-02-20 01:53:56 -05:00
public sealed class ExampleB : IExample
2023-12-02 01:17:12 -05:00
{
public Vector3 beta;
}
[Serializable]
2024-02-20 01:53:56 -05:00
public sealed class ExampleC : IExample
2023-12-02 01:17:12 -05:00
{
public GameObject gamma;
}
2024-02-20 01:53:56 -05:00
public class SerializeReferenceExample : MonoBehaviour
2023-12-02 01:17:12 -05:00
{
2024-02-20 01:53:56 -05:00
[SerializeReference] public IExample Example;
[SerializeReference] public IExample[] ExampleArray;
2023-12-02 01:17:12 -05:00
}
```
2024-02-20 01:53:56 -05:00
<img src="https://github.com/AnnulusGames/Alchemy/blob/main/docs/images/img-serialize-reference.png" width="600">
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
Interfaces/abstract classes are displayed as shown above, and you can select child classes from the dropdown to instantiate them.
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
For more details, refer to [SerializeReference](https://annulusgames.github.io/Alchemy/articles/en/serialize-reference.html).
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
## Hierarchy
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
By introducing Alchemy, several features are added to extend the Hierarchy.
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
<img src="https://github.com/AnnulusGames/Alchemy/blob/main/docs/images/img-hierarchy.png" width="600">
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
### Toggles and Icons
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
<img src="https://github.com/AnnulusGames/Alchemy/blob/main/docs/images/gif-hierarchy-toggle.gif" width="600">
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
Toggles to switch between active/inactive states of objects and icons to display the components of objects can be added to the Hierarchy. These can be configured from ProjectSettings.
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
<img src="https://github.com/AnnulusGames/Alchemy/blob/main/docs/images/img-project-settings.png" width="600">
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
### Decoration
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
Additionally, objects to decorate the Hierarchy can be created from the Create menu.
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
<img src="https://github.com/AnnulusGames/Alchemy/blob/main/docs/images/img-create-hierarchy-object.png" width="600">
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
These objects are automatically excluded during build time. (If they have child objects, all child objects are detached before deletion.)
For more details, refer to [Decorating Hierarchy](https://annulusgames.github.io/Alchemy/articles/en/decor
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
ating-hierarchy.html).
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
## AlchemyEditorWindow
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
By inheriting from the `AlchemyEditorWindow` class instead of the usual `Editor` class, you can create editor windows using Alchemy attributes.
2023-12-02 01:17:12 -05:00
```cs
using System;
using System.Collections.Generic;
2024-02-20 01:53:56 -05:00
using UnityEditor;
2023-12-02 01:17:12 -05:00
using UnityEngine;
2024-02-20 01:53:56 -05:00
using UnityEngine.UIElements;
using Alchemy.Editor;
using Alchemy.Inspector;
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
public class EditorWindowExample : AlchemyEditorWindow
2023-12-02 01:17:12 -05:00
{
2024-02-20 01:53:56 -05:00
[MenuItem("Window/Example")]
static void Open()
2023-12-02 01:17:12 -05:00
{
2024-02-20 01:53:56 -05:00
var window = GetWindow<EditorWindowExample>("Example");
window.Show();
2023-12-02 01:17:12 -05:00
}
2024-02-20 01:53:56 -05:00
[Serializable]
[HorizontalGroup]
public class DatabaseItem
2023-12-02 01:17:12 -05:00
{
2024-02-20 01:53:56 -05:00
[LabelWidth(30f)]
public float foo;
[LabelWidth(30f)]
public Vector3 bar;
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
[LabelWidth(30f)]
public GameObject baz;
2023-12-02 01:17:12 -05:00
}
2024-02-20 01:53:56 -05:00
[ListViewSettings(ShowAlternatingRowBackgrounds = AlternatingRowBackground.All, ShowFoldoutHeader = false)]
public List<DatabaseItem> items;
[Button, HorizontalGroup]
public void Button1() { }
[Button, HorizontalGroup]
public void Button2() { }
[Button, HorizontalGroup]
public void Button3() { }
2023-12-02 01:17:12 -05:00
}
```
2024-02-20 01:53:56 -05:00
<img src="https://github.com/AnnulusGames/Alchemy/blob/main/docs/images/img-editor-window.png" width="600">
2023-12-02 01:17:12 -05:00
2024-02-20 01:53:56 -05:00
The data of windows created by inheriting from `AlchemyEditorWindow` is saved in json format in the ProjectSettings folder of the project. For more details, refer to [Saving Editor Window Data](https://annulusgames.github.io/Alchemy/articles/en/saving-editor-window-data.html).
## Using Serialization Extensions
If you want to edit types that Unity cannot serialize, such as Dictionary, you can use the `[AlchemySerialize]` attribute to perform serialization.
If you want to use serialization extensions, you will need the [Unity.Serialization](https://docs.unity3d.com/Packages/com.unity.serialization@3.1/manual/index.html) package. Additionally, reflection-based serialization using Unity.Serialization may not work in AOT environments prior to Unity 2022.1. Check the package manual for details.
Below is a sample using Alchemy's serialization extension to make various types serializable/editable in the Inspector.
2023-12-02 01:17:12 -05:00
```cs
using System;
using System.Collections.Generic;
using UnityEngine;
using Alchemy.Serialization;
2024-02-20 01:53:56 -05:00
// By adding the [AlchemySerialize] attribute, Alchemy's serialization extension is enabled.
// It can be used with any type that has an optional base class, but the target type must be partial for the Source Generator to generate code.
2023-12-02 01:17:12 -05:00
[AlchemySerialize]
2024-02-20 01:53:56 -05:00
public partial class AlchemySerializationExample : MonoBehaviour
2023-12-02 01:17:12 -05:00
{
2024-02-20 01:53:56 -05:00
// Add [AlchemySerializeField] and [NonSerialized] attributes to the target fields.
2023-12-02 01:17:12 -05:00
[AlchemySerializeField, NonSerialized]
2024-02-20 01:53:56 -05:00
public HashSet<GameObject> hashset = new();
2023-12-02 05:51:06 -05:00
2024-02-20 01:53:56 -05:00
[AlchemySerializeField, NonSerialized]
public Dictionary<string, GameObject> dictionary = new();
2023-12-02 05:51:06 -05:00
2024-02-20 01:53:56 -05:00
[AlchemySerializeField, NonSerialized]
public (int, int) tuple;
2023-12-02 05:51:06 -05:00
2024-02-20 01:53:56 -05:00
[AlchemySerializeField, NonSerialized]
public Vector3? nullable = null;
2023-12-02 05:51:06 -05:00
}
```
2024-02-20 01:53:56 -05:00
<img src="https://github.com/AnnulusGames/Alchemy/blob/main/docs/images/img-serialization-sample.png" width="600">
2023-12-02 05:51:06 -05:00
2024-02-20 01:53:56 -05:00
For technical details of the serialization process, refer to [Alchemy Serialization Process](https://annulusgames.github.io/Alchemy/articles/en/alchemy-serialization-process.html) in the documentation.
2023-12-02 05:51:06 -05:00
2023-12-03 00:44:05 -05:00
## Help
Unity forum: https://forum.unity.com/threads/released-alchemy-inspector-serialization-extensions.1523665/
2023-12-02 01:17:12 -05:00
## License
[MIT License](LICENSE)