### Install App UI Unity Package
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/setup.md
Steps to add the App UI Unity Package to your project using the Unity Package Manager by providing a Git URL.
```Unity
Windows > Package Manager
+ button > Add package from git URL...
com.unity.dt.app-ui
Add button
```
--------------------------------
### Implement Navigation Component Setup in NavigationScreen
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/navigation.md
This example illustrates an alternative pattern where navigation component setup methods like SetupAppBar are overridden directly within a custom NavigationScreen implementation. This approach allows for screen-specific control over navigation UI elements.
```cs
class MyAppHomeScreen : NavigationScreen
{
public override void SetupAppBar(AppBar appBar, NavController navController)
{
appBar.title = "Home";
}
}
```
--------------------------------
### App UI Project Settings Configuration
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/setup.md
Details on configuring the App UI package settings within the Unity Editor. This includes options for UI scaling, editor-only mode, update frequency, Android manifest overrides, and shader inclusion.
```APIDOC
App UI Settings:
Generate Settings File:
- Description: Generates the default App UI settings file in the Assets folder.
- Location: Edit > Project Settings > App UI
Auto correct the UI scale:
- Description: Enables or disables automatic UI scaling to match OS pixel density. Designed for 96 DPI screens.
- Type: Boolean
- Default: Enabled (implied)
Editor-only mode:
- Description: Injects a scripting definition symbol to prevent App UI assemblies from being included in builds. Useful for editor-only features.
- Type: Boolean
- Default: Disabled
Editor Update Frequency:
- Description: Configures how often App UI updates in the editor. Affects internal message queue. Standalone builds use MonoBehaviour.Update().
- Type: Integer
- Default: 60 (updates per second)
- Example: Set to 1 to simulate slower devices.
Override Android Main Manifest:
- Description: Allows overriding the Android main manifest file for custom permissions (e.g., VIBRATE for haptic feedback). Affects only Android builds.
- Type: Boolean
- Default: Enabled
Include App UI Shaders In Player Build:
- Description: Includes App UI shaders in the player build to render UI elements. Disable to reduce build size if shaders are not used.
- Type: Boolean
- Default: Enabled
```
--------------------------------
### Refactor SplitView Component in XML
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Demonstrates the new structure of the SplitView component, which now supports multiple Pane children and has a refactored implementation for greater flexibility. The example shows how to define panes with specific widths and stretch behavior.
```xml
```
--------------------------------
### Redux Store Creation with Slices
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Shows the refactored Redux API for creating stores and slices in Unity App UI. Slices must be provided during store creation, and cannot be added afterward.
```csharp
var store = new Store();
store.AddSlice("sliceName", new MySliceState(), builder => { /* ... */ });
store.AddSlice("slice2Name", /* ... */ );
```
```csharp
var store = StoreFactory.CreateStore(new [] {
StoreFactory.CreateSlice("sliceName", new MySliceState(), builder => { /* ... */ }),
StoreFactory.CreateSlice("slice2Name", /* ... */ )
// ...
});
```
--------------------------------
### Custom Theme File Reference
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/theming.md
Example of a theme file that imports a stylesheet and is referenced in `PanelSettings` for applying custom themes to a `UIDocument` component.
```css
@import url("darkBlue.uss");
VisualElement {}
```
--------------------------------
### Implement INavVisualController in C#
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Shows the addition of the `SetupNavigationRail` method to the `INavVisualController` interface. This method must be implemented to configure the navigation rail, similar to existing methods for bottom navigation bars, app bars, and drawers.
```csharp
public class MyNavController : INavVisualController
{
public void SetupBottomNavBar(BottomNavBar bottomNavBar, NavDestination destination, NavController navController)
{
if (destination.showBottombar)
{
/* ... */
}
}
public void SetupAppBar(AppBar appBar, NavDestination destination, NavController navController)
{
if (destination.showAppBar)
{
/* ... */
}
}
public void SetupDrawer(Drawer drawer, NavDestination destination, NavController navController)
{
if (destination.showDrawer)
{
/* ... */
}
}
}
```
```csharp
public class MyNavController : INavVisualController
{
public void SetupBottomNavBar(BottomNavBar bottomNavBar, NavDestination destination, NavController navController)
{
if (destination.showBottombar)
{
/* ... */
}
}
public void SetupAppBar(AppBar appBar, NavDestination destination, NavController navController)
{
if (destination.showAppBar)
{
/* ... */
}
}
public void SetupDrawer(Drawer drawer, NavDestination destination, NavController navController)
{
if (destination.showDrawer)
{
/* ... */
}
}
public void SetupNavigationRail(NavigationRail navigationRail, NavDestination destination, NavController navController)
{
if (destination.showNavigationRail)
{
/* ... */
}
}
}
```
--------------------------------
### MVVM App Creation: InitializeComponent Override
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Illustrates the change in MVVM app creation within Unity App UI. Developers can now override the InitializeComponent method to set up the visual tree, offering more flexibility.
```csharp
public class MyApp : App
{
public MyApp(MainPage mainPage)
{
var panel = new Panel();
panel.Add(mainPage);
this.mainPage = panel;
}
}
```
```csharp
public class MyApp : App
{
public new static MyApp current => (MyApp)App.current;
public override void InitializeComponent()
{
base.InitializeComponent();
rootVisualElement.Add(services.GetRequiredService());
}
}
```
--------------------------------
### Implement IPartionableState Interface
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/state-management.md
Illustrates the implementation of the `IPartionableState` interface for managing state slices. The `Get` and `Set` methods are crucial for retrieving and updating specific parts of the state immutably.
```csharp
using Unity.AppUI.Redux;
class MyState : IPartionableState
{
public TSliceState Get(string sliceName)
{
// Implement the method to return the slice state.
}
public MyState Set(string sliceName, TSliceState sliceState)
{
// Implement the method to set the slice state.
// Remember that the state object is immutable, so the returned object should be a new instance.
}
}
```
--------------------------------
### Custom Theme Stylesheet Variables
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/theming.md
Example of a stylesheet file defining USS variables for a custom theme. Requires the `appui--` prefix for theme names to be recognized by the App UI context provider.
```css
.appui--darkBlue {
--appui-primary-100: #E3F2FD;
...
}
```
--------------------------------
### App UI Support for New Input System
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/faq.md
Confirms that App UI components are compatible with Unity's New Input System. It also provides instructions on how to install the Input System package and configure input actions for newer Unity versions.
```text
Install the "Input System" package via the Package Manager. For Unity 2023.2+, configure UI input actions in Project Settings > Input System Package > Input Actions.
```
--------------------------------
### Implement INavVisualController for Navigation Components
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/navigation.md
This example demonstrates implementing the INavVisualController interface to control the visual state of navigation components such as AppBar, BottomNavBar, Drawer, and NavigationRail. It requires the Unity.AppUI.Navigation and Unity.AppUI.UI namespaces and allows for custom logic based on navigation destinations.
```cs
class MyVisualController : INavVisualController
{
public void SetupBottomNavBar(BottomNavBar bottomNavBar, NavDestination destination, NavController navController)
{
if (!destination.showBottomNavBar)
return;
var homeButton = new BottomNavBarItem("info", "Home", () => navController.Navigate(Actions.navigateToHome))
{
isSelected = destination.name == Screens.home
};
bottomNavBar.Add(homeButton);
// etc ...
}
public void SetupAppBar(AppBar appBar, NavDestination destination, NavController navController)
{
if (!destination.showAppBar)
return;
appBar.title = destination.label;
}
public void SetupDrawer(Drawer drawer, NavDestination destination, NavController navController)
{
if (!destination.showDrawer)
return;
drawer.Add(new DrawerHeader());
drawer.Add(new Divider { vertical = false });
var homeButton = new MenuItem {icon = "info", label = "Home", selectable = true};
homeButton.SetValueWithoutNotify(destination.name == Screens.home);
homeButton.clickable.clicked += () => navController.Navigate(Actions.navigateToHome);
drawer.Add(homeButton);
// etc ...
}
public void SetupNavigationRail(NavigationRail navigationRail, NavDestination destination, NavController navController)
{
navigationRail.anchor = NavigationRailAnchor.End;
navigationRail.labelType = LabelType.Selected;
navigationRail.groupAlignment = GroupAlignment.Center;
var homeButton = new NavigationRailItem { icon = "info", label = "Home", selected = destination.name == Destinations.home };
homeButton.clickable.clicked += () => navController.Navigate(Actions.navigateToHome);
navigationRail.mainContainer.Add(homeButton);
// etc ...
}
}
```
--------------------------------
### Declare Action Creators in C#
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Demonstrates how to declare action creators using `ActionCreator` or `ActionCreator` classes directly. It shows the transition from using `Store.CreateAction` to simpler assignments, including implicit string conversion and `nameof` for payload types.
```csharp
static readonly ActionCreator actionType0 = Store.CreateAction("actionType0");
static readonly ActionCreator actionType1 = Store.CreateAction("actionType1");
```
```csharp
static readonly ActionCreator actionType0 = "actionType0"; // no payload
static readonly ActionCreator actionType1 = nameof(actionType1); // with int payload
```
--------------------------------
### Migrate Dropzone Logic to DropzoneController
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Explains the refactoring of the Dropzone component, where most logic is moved to a new `DropzoneController`. The `Dropzone` class now focuses on visuals, while the controller handles drop logic via an `acceptDrag` delegate and the `dropped` event. The `dragStarted` event has been removed.
```csharp
// Before:
var dropzone = new Dropzone();
dropzone.tryGetDroppableFromPath = TryGetDroppableFromPath;
dropzone.tryGetDroppablesFromUnityObjects = TryGetDroppableFromUnityObjects;
dropzone.dropped += OnDropped;
dropzone.dragStarted += OnEditorDragStarted;
dropzone.dragEnded += OnDragEndedOrCanceled;
// After:
var dropzone = new Dropzone();
var dropzoneController = dropzone.controller;
dropzoneController.acceptDrag = ShouldAcceptDrag;
dropzoneController.dropped += OnDropped;
dropzoneController.dragEnded += OnDragEndedOrCanceled;
```
--------------------------------
### Manage Store Subscriptions in C#
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Details the updated method for subscribing to store changes. Instead of returning a function for unsubscription, the `store.Subscribe` method now returns an `IDisposableSubscription` instance, which provides `Dispose()` and `IsValid()` methods for managing the subscription lifecycle.
```csharp
Unsubscriber unsub;
// Subscribe to store changes
unsub = store.Subscribe("sliceName", state => { /* ... */ });
// Unsubscribe
unsub();
```
```csharp
IDisposableSubscription subscription;
// Subscribe to store changes
subscription = store.Subscribe("sliceName", state => { /* ... */ });
// Unsubscribe
subscription.Dispose();
// Check if subscription is valid
Assert.IsFalse(subscription.IsValid());
```
--------------------------------
### Replace Platform Theme Properties with DarkMode Boolean
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Describes the update to native platform theme handling, simplifying it to differentiate only between light and dark themes. The `Platform.systemThemeChanged` event and `Platform.systemTheme` string property are replaced by `Platform.darkModeChanged` event and `Platform.darkMode` boolean property.
```csharp
// Before:
Platform.systemThemeChanged += theme => Debug.Log($"Theme changed to {theme}");
if (Platform.systemTheme == "dark")
{
/* ... */
}
// After:
Platform.darkModeChanged += darkMode => Debug.Log($"Dark mode changed to {darkMode}");
if (Platform.darkMode)
{
/* ... */
}
```
--------------------------------
### Redux Slice Reducer Builder: AddCase Method
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Details the change in Redux slice creation for defining reducers. The AddCase method replaces the Add method for primary reducers, while AddDefault and AddMatcher remain for extra reducers.
```csharp
store.AddSlice("sliceName", new MySliceState(), builder => {
builder.Add("actionType", (state, action) => { /* ... */ });
});
```
```csharp
StoreFactory.CreateSlice("sliceName", new MySliceState(), builder => {
builder.AddCase("actionType", (state, action) => { /* ... */ });
});
```
--------------------------------
### Update Reducer Signatures in C#
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Explains the change in reducer method signatures. Reducers now accept an `IAction` interface type as the second parameter instead of the older `Action` or `Action` types, improving type safety and consistency for payload handling.
```csharp
// with no payload
static MyAppState MyReducer1(MyAppState state, Action action) { /* ... */ }
// with int payload
static MyAppState MyReducer2(MyAppState state, Action action) { /* ... */ }
```
```csharp
// with no payload
static MyAppState MyReducer1(MyAppState state, IAction action) { /* ... */ }
// with int payload
static MyAppState MyReducer2(MyAppState state, IAction action) { /* ... */ }
```
--------------------------------
### Clipboard Text and PNG Operations
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/native-integration.md
Provides examples for interacting with the system clipboard using Unity App UI. It demonstrates how to retrieve and set text content (UTF-8 encoded) and PNG image data from the clipboard. The code includes necessary encoding/decoding for text and handling byte arrays for image data, along with checks for data availability.
```csharp
using UnityEngine;
using Unity.AppUI.Core;
using System.Text;
public class ClipboardManager : MonoBehaviour
{
void InteractWithClipboard()
{
// --- Text Operations ---
// Get text content from the clipboard
byte[] clipboardTextBytes = Platform.GetPasteboardData(PasteboardType.Text);
if (clipboardTextBytes != null && clipboardTextBytes.Length > 0)
{
string clipboardText = Encoding.UTF8.GetString(clipboardTextBytes);
Debug.Log($"Clipboard text content: {clipboardText}");
}
else
{
Debug.Log("Clipboard is empty or does not contain text.");
}
// Set text content to the clipboard
string textToCopy = "Hello from Unity App UI!";
Platform.SetPasteboardData(PasteboardType.Text, Encoding.UTF8.GetBytes(textToCopy));
Debug.Log($"Set clipboard text to: {textToCopy}");
// --- PNG Image Operations ---
// Get PNG image content from the clipboard
byte[] clipboardImageBytes = Platform.GetPasteboardData(PasteboardType.PNG);
if (clipboardImageBytes != null && clipboardImageBytes.Length > 0)
{
Texture2D texture = new Texture2D(2, 2); // Create a dummy texture
if (texture.LoadImage(clipboardImageBytes))
{
Debug.Log($"Clipboard image loaded: {texture.width}x{texture.height}");
// You can now use this texture, e.g., assign it to a UI Image component
}
else
{
Debug.LogError("Failed to load image from clipboard data.");
}
}
else
{
Debug.Log("Clipboard is empty or does not contain PNG data.");
}
// Set PNG image content to the clipboard
// Example: Create a simple 1x1 red texture
Texture2D textureToCopy = new Texture2D(1, 1);
textureToCopy.SetPixel(0, 0, Color.red);
textureToCopy.Apply();
byte[] imageBytesToCopy = textureToCopy.EncodeToPNG();
Platform.SetPasteboardData(PasteboardType.PNG, imageBytesToCopy);
Debug.Log("Set clipboard PNG data.");
// --- Check for data ---
bool hasText = Platform.HasPasteboardData(PasteboardType.Text);
Debug.Log($"Clipboard has text data: {hasText}");
bool hasPng = Platform.HasPasteboardData(PasteboardType.PNG);
Debug.Log($"Clipboard has PNG data: {hasPng}");
}
}
```
--------------------------------
### Build and Configure Modal
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/overlays.md
Illustrates the creation and configuration of a Modal dialog using a fluent API. This includes setting full-screen mode and other potential configurations for modal dialogs.
```APIDOC
Modal.Build(content)
.SetFullScreenMode(ModalFullScreenMode.None)
// ... other configurations
// Methods:
// Build(content): Creates a new Modal builder instance.
// - content: The UI content to display within the modal.
// SetFullScreenMode(mode): Sets the modal to occupy the full screen or a specific mode.
// - mode: An enum value from ModalFullScreenMode (e.g., None, Auto, Always).
// Additional methods for configuration would follow a similar pattern to Popover.
```
--------------------------------
### MyApp Entry Point
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/mvvm-sample.md
Shows the MyApp class, an implementation of App, serving as the entry point for the application. It defines the main UI by adding the MainPage to the rootVisualElement and utilizes Dependency Injection for service resolution.
```C#
public class MyApp : App
{
public new static MyApp current => (MyApp)App.current;
public override void InitializeComponent()
{
base.InitializeComponent();
rootVisualElement.Add(services.GetRequiredService());
}
public override void Shutdown()
{
// Called when the app is shutting down
}
}
```
--------------------------------
### Get Localized String with LangContext (C#)
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/localization.md
Demonstrates how to retrieve a localized string using the `LangContext`. It registers a callback for context changes and shows how to get the current localized string asynchronously. Requires the `Unity.AppUI.UI` namespace and `Unity.AppUI.Core.LangContext`.
```C#
using Unity.AppUI.UI;
public class MyComponent : BaseVisualElement
{
public MyComponent()
{
this.RegisterContextChangedCallback(OnLangContextChanged);
}
// This method will be called when the LangContext changes
async void OnLangContextChanged(ContextChangedEvent evt)
{
var ctx = evt.context;
if (ctx != null)
{
var translatedString = await ctx.GetLocalizedStringAsync("@myTable:myEntry");
}
}
// This method will check for the currently provided locale
// without using any listener
public void TranslateNow()
{
var ctx = this.GetContext();
if (ctx != null)
{
var translatedString = ctx.GetLocalizedStringAsync("@myTable:myEntry");
}
}
}
```
--------------------------------
### Build and Configure Menu
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/overlays.md
Shows how to construct a context menu or navigation menu using a fluent API. It supports adding actions, pushing sub-menus, and displaying them relative to a target element.
```APIDOC
MenuBuilder.Build(anchor)
.AddAction(123, "An Item", "info", evt => Debug.Log("Item clicked"))
.PushSubMenu(456, "My Sub Menu", "help")
.AddAction(789, "Sub Menu Item", "info", evt => Debug.Log("Sub Item clicked"))
.PushSubMenu(3455, "Another Sub Menu", "help")
.AddAction(7823129, "Another Sub Menu Item", "info", evt => Debug.Log("Other Item clicked"))
.Pop()
.Pop()
.Show();
// Methods:
// Build(anchor): Initializes the MenuBuilder with a target anchor element.
// - anchor: The UI element the menu will be displayed next to.
// AddAction(id, text, icon, onClick): Adds a clickable menu item.
// - id: Unique identifier for the action.
// - text: The display text for the menu item.
// - icon: Optional icon identifier or path.
// - onClick: Event handler for when the item is clicked.
// PushSubMenu(id, text, icon): Creates and pushes a new sub-menu onto the stack.
// - id: Unique identifier for the sub-menu.
// - text: The display text for the sub-menu trigger.
// - icon: Optional icon identifier or path.
// Pop(): Removes the current sub-menu from the stack, returning to the parent menu.
// Show(): Displays the constructed menu.
```
--------------------------------
### ActionGroup Component Usage
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/actions.md
Provides an example of how to group multiple ActionButton components using the ActionGroup component, allowing for toggling between different actions.
```xml
```
--------------------------------
### Build and Configure Popover
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/overlays.md
Demonstrates how to build and configure a Popover component using a fluent API. This includes setting placement, flip behavior, offsets, arrow visibility, padding, dismissal behavior, and modal backdrop.
```APIDOC
Popover.Build(target, content)
.SetPlacement(placement)
.SetShouldFlip(shouldFlip)
.SetOffset(offset)
.SetCrossOffset(crossOffset)
.SetArrowVisible(showArrow)
.SetContainerPadding(containerPadding)
.SetOutsideClickDismiss(outsideClickDismissEnabled)
.SetModalBackdrop(modalBackdrop)
.SetKeyboardDismiss(keyboardDismissEnabled);
// Methods:
// Build(target, content): Creates a new Popover builder instance.
// - target: The UI element the popover is anchored to.
// - content: The UI content to display within the popover.
// SetPlacement(placement): Sets the preferred placement of the popover relative to the target.
// - placement: An enum value indicating the desired position (e.g., Top, Bottom, Left, Right).
// SetShouldFlip(shouldFlip): Enables or disables automatic flipping of placement if the popover overflows the screen.
// - shouldFlip: Boolean, true to enable flipping, false otherwise.
// SetOffset(offset): Sets the distance between the popover and the target element.
// - offset: Float value for the offset.
// SetCrossOffset(crossOffset): Sets the offset along the cross axis relative to the target.
// - crossOffset: Float value for the cross offset.
// SetArrowVisible(showArrow): Controls the visibility of the arrow pointing to the target.
// - showArrow: Boolean, true to show the arrow, false to hide it.
// SetContainerPadding(containerPadding): Sets padding around the popover content.
// - containerPadding: Float value for padding.
// SetOutsideClickDismiss(outsideClickDismissEnabled): Configures whether clicking outside the popover dismisses it.
// - outsideClickDismissEnabled: Boolean, true to enable dismissal, false otherwise.
// SetModalBackdrop(modalBackdrop): Configures the modal backdrop behavior.
// - modalBackdrop: Boolean, true to show a modal backdrop, false otherwise.
// SetKeyboardDismiss(keyboardDismissEnabled): Configures whether pressing the Escape key dismisses the popover.
// - keyboardDismissEnabled: Boolean, true to enable dismissal, false otherwise.
// Show(): Displays the configured popover.
```
--------------------------------
### Gesture Handling: Magnification and Pan
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Demonstrates the refactoring of gesture handling in Unity App UI. MagnificationGestureEvent is replaced by PinchGestureEvent, and PanGestureEvent is replaced by WheelEvent for pan-like behavior on non-touch devices.
```csharp
public class MyComponent : VisualElement
{
public MyComponent()
{
this.AddManipulator(new MagnificationManipulator());
this.RegisterCallback(OnMagnification);
this.RegisterCallback(OnPan);
}
private void OnMagnification(MagnificationGestureEvent evt)
{
/* ... */
}
private void OnPan(PanGestureEvent evt)
{
/* ... */
}
}
```
```csharp
public class MyComponent : VisualElement
{
public MyComponent()
{
this.AddManipulator(new PinchManipulator());
this.RegisterCallback(OnPinch);
this.RegisterCallback(OnPan);
}
private void OnPinch(PinchGestureEvent evt)
{
/* ... */
}
private void OnPan(WheelEvent evt)
{
/* ... */
}
}
```
--------------------------------
### Generic StoryBookEnumProperty in C#
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Illustrates the change of `StoryBookEnumProperty` to a generic class. This update allows it to handle any enum type directly, simplifying usage and preventing casting errors compared to the previous non-generic implementation.
```csharp
var enumProperty = new StoryBookEnumProperty(
nameof(Button.variant),
(btn) => ((Button)btn).variant,
(btn, val) => ((Button)btn).variant = (ButtonVariant)val);
```
```csharp
var enumProperty = new StoryBookEnumProperty(
nameof(Button.variant),
(btn) => ((Button)btn).variant,
(btn, val) => ((Button)btn).variant = val);
```
--------------------------------
### Create Redux Store with Simple State
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/state-management.md
Demonstrates how to create a Redux store using the generic `Store.CreateStore` method. It takes the state type, a reducer function, and an initial state object as parameters.
```csharp
using Unity.AppUI.Redux;
record MyState {}
var store = Store.CreateStore((state, action) => state, new MyState());
```
--------------------------------
### MyAppBuilder Implementation
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/mvvm-sample.md
Demonstrates the MyAppBuilder class, an implementation of UIToolkitAppBuilder, used to define runtime app configuration and hook into the app lifecycle events. It allows specifying the App implementation and handling initialization and shutdown.
```C#
public class MyAppBuilder : UIToolkitAppBuilder
{
protected override void OnAppInitialized(MyApp app)
{
base.OnAppInitialized(app);
// Called after the app is initialized
}
protected override void OnConfiguringApp(AppBuilder builder)
{
base.OnConfiguringApp(builder);
// Called during app configuration
}
protected override void OnAppShuttingDown(MyApp app)
{
base.OnAppShuttingDown(app);
// Called before the app is shut down
}
}
```
--------------------------------
### Register Dependencies in AppBuilder
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/mvvm-di.md
Provides an example of how to register custom dependencies within the App UI framework. It shows accessing the IServiceCollection via the AppBuilder during the OnConfiguringApp event to add services.
```csharp
public class MyAppBuilder : UIToolkitAppBuilder
{
protected override void OnConfiguringApp(AppBuilder appBuilder)
{
base.OnConfiguringApp(appBuilder);
// Register dependencies here
// ex: appBuilder.services.AddSingleton();
}
}
```
--------------------------------
### Unity App UI Core Platform API Reference
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/native-integration.md
This section provides an overview of key properties and methods available in the `Unity.AppUI.Core.Platform` class for interacting with the underlying operating system and device features. It covers accessing system-level information and triggering platform-specific actions.
```APIDOC
Unity.AppUI.Core.Platform:
// Properties
textScaleFactor: float
// Description: Gets the current text scaling factor applied by the system.
// Use case: Adjust font sizes or UI element dimensions based on user's text scaling preference.
layoutDirection: LayoutDirection
// Description: Gets the current layout direction of the system (e.g., Left-to-Right or Right-to-Left).
// Use case: Adapt UI layout for different language directions, e.g., using flexbox properties.
darkMode: bool
// Description: Gets a boolean indicating whether the system theme is currently set to dark mode.
// Use case: Dynamically change the application's theme (light/dark) to match the system setting.
// Events
systemThemeChanged: event Action
// Description: Event that is invoked when the system's dark mode setting changes.
// Parameters:
// darkMode: bool - True if the new system theme is dark, false otherwise.
// Use case: Subscribe to this event to update the application's theme in real-time.
// Methods
RunHapticFeedback(): void
// Description: Triggers haptic feedback on supported platforms (e.g., iOS, Android).
// Limitations: Currently, no App UI components use this directly; it's for custom implementation.
// Use case: Provide tactile feedback for user interactions.
GetPasteboardData(pasteboardType: PasteboardType): byte[]
// Description: Retrieves data from the system clipboard for a specified pasteboard type.
// Parameters:
// pasteboardType: PasteboardType - The type of data to retrieve (e.g., Text, PNG).
// Returns: byte[] - The data from the clipboard, or null/empty if no data of that type is available.
// Supported Types:
// PasteboardType.Text: UTF-8 encoded string.
// PasteboardType.PNG: PNG image data.
// Notes:
// On Windows, Text content is automatically converted between UTF-8 (C#) and UTF-16LE (OS).
// Use case: Copying text or images from other applications into your app.
SetPasteboardData(pasteboardType: PasteboardType, data: byte[]): void
// Description: Sets data to the system clipboard for a specified pasteboard type.
// Parameters:
// pasteboardType: PasteboardType - The type of data to set (e.g., Text, PNG).
// data: byte[] - The byte array containing the data to be placed on the clipboard.
// Supported Types:
// PasteboardType.Text: UTF-8 encoded string.
// PasteboardType.PNG: PNG image data.
// Notes:
// On Windows, Text content is automatically converted between UTF-8 (C#) and UTF-16LE (OS).
// Use case: Copying text or images from your app to the system clipboard.
HasPasteboardData(pasteboardType: PasteboardType): bool
// Description: Checks if the system clipboard currently contains data of the specified type.
// Parameters:
// pasteboardType: PasteboardType - The type of data to check for (e.g., Text, PNG).
// Returns: bool - True if data of the specified type is available, false otherwise.
// Use case: Pre-checking clipboard content before attempting to retrieve it.
// Enum
Unity.AppUI.Core.PasteboardType:
Text
PNG
```
--------------------------------
### Create Redux Store with Slices
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/state-management.md
Shows how to create a Redux store using `StoreFactory.CreateStore` with multiple slices. Each slice is defined with a name, initial state, and a builder function for configuration, enabling modular state management.
```csharp
using Unity.AppUI.Redux;
record MyState {}
var store = StoreFactory.CreateStore(new []
{
StoreFactory.CreateSlice(
"mySlice",
new MyState(),
builder => { /* ... */ },
)
});
```
--------------------------------
### React to Layout Direction Changes with ContextChangedEvent
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/accessibility.md
Provides an example of registering a callback for `ContextChangedEvent` to programmatically react to changes in the layout direction context. This allows for dynamic UI logic adjustments based on LTR or RTL settings.
```csharp
using Unity.AppUI.Core;
using Unity.AppUI.UI;
var myElement = new VisualElement();
myElement.RegisterContextChangedCallback(OnDirContextChanged);
void OnDirContextChanged(ContextChangedEvent evt)
{
var dir = evt.context?.dir ?? Dir.Ltr;
UpdateMyLogic(dir);
}
```
--------------------------------
### Resolve Scoped Service in ViewModel
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/mvvm-di.md
Shows how to resolve a scoped service within a ViewModel. This example demonstrates obtaining a scoped service instance by creating a new service scope and then retrieving the dependency from that scope.
```csharp
using Unity.AppUI.MVVM;
public class MyViewModel : ObservableObject
{
public MyViewModel(IServiceProvider serviceProvider)
{
using (var scope = serviceProvider.CreateScope())
{
var scopedService = scope.ServiceProvider.GetRequiredService();
}
}
}
```
--------------------------------
### Logger Middleware and Store Enhancement in C#
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/state-management.md
Illustrates how to create a logger middleware that logs actions before they are dispatched and how to combine multiple middlewares using Store.ApplyMiddleware to create a store enhancer. This enhancer is then used to create a store with the logging functionality.
```cs
using Unity.AppUI.Redux;
using UnityEngine;
public static class Application
{
public static Middleware LoggerMiddleware()
where TStore : Store
{
return (store) => (nextMiddleware) => (action) =>
{
Debug.Log($"Action: {action.type}");
return nextMiddleware(action);
};
}
public static StoreEnhancer EnhanceStoreWithLogger()
where TStore : Store
{
return Store.ApplyMiddleware(LoggerMiddleware());
}
static void Main()
{
// At this point you can use your Enhancer to create a new store with the logger middleware.
var store = Store.CreateStore(new []
{
Store.CreateSlice(
"mySlice",
new MyState(), // Assuming MyState is defined elsewhere
builder => { /* ... */ }),
}, EnhanceStoreWithLogger());
}
}
```
--------------------------------
### Redux Slice Reducer Builder: Action Creator Usage
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Explains how to use ActionCreator instances or string representations with the Redux slice builder's AddCase method. Explicit casting is required when passing string action types.
```csharp
store.AddSlice("sliceName", new MySliceState(), builder => {
builder.Add("actionType", (state, action) => { /* ... */ });
});
```
```csharp
static readonly ActionCreator actionType0 = "actionType0"; // no payload
static readonly ActionCreator actionType1 = nameof(actionType1); // with int payload
StoreFactory.CreateSlice("sliceName", new MySliceState(), builder => {
builder.AddCase((ActionCreator)"actionType2", (state, action) => { /* ... */ }); // cast to ActionCreator
});
```
--------------------------------
### Use App UI Components in EditorWindow
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/faq.md
Demonstrates how to integrate App UI components within Unity's EditorWindow class. It covers loading the necessary theme stylesheet either programmatically via C# or directly within the UXML file.
```cs
class MyWindow : EditorWindow
{
void CreateGUI()
{
const string defaultTheme = "Packages/com.unity.dt.app-ui/PackageResources/Styles/Themes/App UI.tss";
rootVisualElement.styleSheets.Add(AssetDatabase.LoadAssetAtPath(defaultTheme));
rootVisualElement.AddToClassList("unity-editor"); // Enable Editor related styles
}
}
```
```xml
```
--------------------------------
### Custom Component as Context Provider/Listener
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/contexts.md
Illustrates creating a custom UI component that inherits from BaseVisualElement and integrates context provision and consumption. It shows how to use ProvideContext and RegisterContextChangedCallback within the component's constructor.
```C#
using Unity.AppUI.Core;
using Unity.AppUI.UI;
public class MyCustomComponent : BaseVisualElement
{
public MyCustomComponent()
{
// Provide a custom context
ProvideContext(new MyContext(42));
// Or Register the context changed callback
// Note that this callback will be also called when the listener element is also a the provider
RegisterContextChangedCallback(OnMyContextChanged);
}
public void OnContextChanged(ContextChangedEvent evt) where T : class, IContext
{
// Do something with the context
}
void OnMyContextChanged(ContextChangedEvent evt)
{
// Do something with the context
}
}
```
--------------------------------
### Basic Panel Component Usage
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/using-app-ui.md
Demonstrates how to include the `Panel` component from the `Unity.AppUI.UI` namespace within a UXML file. The `Panel` component is crucial for providing initial context, such as theme, language, and layout direction, to its children and manages a layering system for overlays.
```UXML
```
--------------------------------
### Update Toast Action Method from SetAction to AddAction
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/migrate.md
Details the change in how actions are added to a Toast component. The `Toast.SetAction` method has been replaced by `Toast.AddAction`, which is more consistent with the ability to remove actions using `Toast.RemoveAction`. The callback signature also changed to accept a toast reference.
```csharp
// Before:
var toast = Toast.Build(/* ... */);
tost.SetAction(DISMISS_ACTION, "Dismiss", () => Debug.Log("Dismissed"));
// After:
var toast = Toast.Build(/* ... */);
tost.AddAction(DISMISS_ACTION, "Dismiss", toastRef => Debug.Log("Dismissed"));
```
--------------------------------
### Registering Dependencies as Interfaces in C#
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/mvvm-di.md
Demonstrates how to register dependencies as interfaces in C#, allowing for multiple implementations and conditional instantiation based on context. Includes service registration within an application builder.
```cs
public interface IMyService
{
void DoSomething();
}
public class MyDebugService : IMyService
{
public void DoSomething()
{
// Do something
}
}
public class MyProductionService : IMyService
{
public void DoSomething()
{
// Do something
}
}
// Register the services inside the app builder
public class MyAppBuilder : UIToolkitAppBuilder
{
protected override void OnConfiguringApp(AppBuilder appBuilder)
{
base.OnConfiguringApp(appBuilder);
if (IsDebugMode())
appBuilder.services.AddSingleton();
else
appBuilder.services.AddSingleton();
}
}
```
--------------------------------
### Use Screen Scale Factor in Custom UI
Source: https://github.com/thephuongcqt/unity-app-ui-docs/blob/main/native-integration.md
Demonstrates how to use the `Platform.scaleFactor` property to accurately scale UI elements based on screen DPI and OS display scaling settings. This example shows its application within a custom `VisualElement` for rendering content to a `RenderTexture`.
```csharp
using Unity.AppUI.Core;
using Unity.AppUI.UI;
using UnityEngine;
class MyCustomElement : VisualElement
{
RenderTexture m_RT;
static readonly Vertex[] k_Vertices = new Vertex[4];
static readonly ushort[] k_Indices = { 0, 1, 2, 2, 3, 0 };
static MyCustomElement()
{
k_Vertices[0].tint = Color.white;
k_Vertices[1].tint = Color.white;
k_Vertices[2].tint = Color.white;
k_Vertices[3].tint = Color.white;
}
public MyCustomElement()
{
generateVisualContent += OnGenerateVisualContent;
}
void OnGenerateVisualContent(MeshGenerationContext ctx)
{
var rect = contentRect;
if (!rect.IsValid())
return;
// check the current scale factor to apply on the RenderTexture
var dpi = Mathf.Max(Platform.scaleFactor, 1f);
var rectSize = rect.size * dpi;
// create or re-create the RenderTexture if the size has changed
if (m_RT && (Mathf.Abs(m_RT.width - rectSize.x) > 1 || Mathf.Abs(m_RT.height - rectSize.y) > 1))
{
m_RT.Release();
UnityObject.Destroy(m_RT);
m_RT = null;
}
if (!m_RT)
{
m_RT = new RenderTexture((int) rectSize.x, (int) rectSize.y, 24)
{
hideFlags = HideFlags.HideAndDontSave,
};
m_RT.Create();
}
// TODO: draw the content on the RenderTexture here...
// Place the RenderTexture in the MeshGenerationContext
var left = paddingRect.xMin;
var right = paddingRect.xMax;
var top = paddingRect.yMin;
var bottom = paddingRect.yMax;
k_Vertices[0].position = new Vector3(left, bottom, Vertex.nearZ);
k_Vertices[1].position = new Vector3(left, top, Vertex.nearZ);
k_Vertices[2].position = new Vector3(right, top, Vertex.nearZ);
k_Vertices[3].position = new Vector3(right, bottom, Vertex.nearZ);
var mwd = ctx.Allocate(k_Vertices.Length, k_Indices.Length, m_RT);
#if !UNITY_2023_1_OR_NEWER
// Since the texture may be stored in an atlas, the UV coordinates need to be
// adjusted. Simply rescale them in the provided uvRegion.
var uvRegion = mwd.uvRegion;
#else
var uvRegion = new Rect(0, 0, 1, 1);
#endif
k_Vertices[0].uv = new Vector2(0, 0) * uvRegion.size + uvRegion.min;
k_Vertices[1].uv = new Vector2(0, 1) * uvRegion.size + uvRegion.min;
k_Vertices[2].uv = new Vector2(1, 1) * uvRegion.size + uvRegion.min;
k_Vertices[3].uv = new Vector2(1, 0) * uvRegion.size + uvRegion.min;
mwd.SetAllVertices(k_Vertices);
mwd.SetAllIndices(k_Indices);
}
}
```