Vizuális témák

A témák lehetővé teszik a felhasználói felületi eszközök rugalmas vezérlését a különböző államok közötti váltások során. Ez magában foglalhatja egy gomb színének megváltoztatását, egy elem átméretezését a fókuszra adott válaszként stb. A Visual Themes keretrendszer két fő darabból áll: 1) konfigurációból és 2) futásidejű motorból.

A témakonfigurációk tulajdonságok és típusok definíciói, míg a témamotorok olyan osztályok, amelyek felhasználják a konfigurációkat, és implementálják az átalakítások, anyagok stb. frissítésére vonatkozó logikát futásidőben.

Témakonfiguráció

A témakonfigurációk ScriptableObjectek, amelyek meghatározzák a témamotorok futásidőben való inicializálását. Ezek határozzák meg, hogy milyen tulajdonságokat és értékeket kell használni a bemeneti vagy egyéb állapotváltozások esetén az alkalmazás futtatásakor. A ScriptableObjects-eszközökként a témakonfigurációk egyszer definiálhatók, majd újra felhasználhatók a különböző felhasználói felületi összetevőkben.

Új adateszköz Theme létrehozása:

  1. Kattintson a jobb gombbal a Project ablakban
  2. Válassza a CreateMixed Reality Toolkit Theme(Eszközkészlet-témalétrehozása) lehetőséget

A témakonfigurációs példaeszközök a következő alatt találhatók: MRTK/SDK/Features/UX/Interactable/Themes .

Theme ScriptableObject példa az Inspectorban

Állapotok

Új létrehozásakor először az elérhető államokat Theme kell beállítani. A States tulajdonság azt jelzi, hogy a témakonfigurációnak hány értéket kell meghatároznia, mivel állapotonként egy érték lesz. A fenti példaképen az Interakcióra használható összetevő alapértelmezetten definiált állama: Default, Focus,Pressed, és Disabled. Ezek az DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States) eszközfájlban vannak meghatározva.

Új adateszköz State létrehozása:

  1. Kattintson a jobb gombbal a Project ablakban
  2. Válassza a CreateMixed Reality Toolkit State(Eszközkészlet-állapot létrehozása)lehetőséget

States ScriptableObject példa az Inspectorban

A ScriptableObject az állapotok listáját és az ezen állapotok számára létrehozendő StateState típusát is meghatározza. A StateModel egy olyan osztály, amely kibővíti és megvalósítja az állapotgép logikáját az aktuális állapot futásidőben való létrehozásához. Az osztály aktuális állapotát általában a témamotorok használják futásidőben, hogy megszabják, milyen értékeket kell beállítani az anyagtulajdonságok, a GameObject-átalakítások stb. alapján.

Témamotor tulajdonságai

Az államokon kívülaz eszközök a témamotorok listáját és a hozzájuk tartozó tulajdonságokat is meghatározzák. A témamotor újra meghatározza a megfelelő értékeknek a GameObjectre futásidőben való beállításához szükséges logikát.

Egy eszköz több témamotor meghatározásával kifinomult vizuális államok közötti váltásokat érhet el, amelyek több Theme GameObject tulajdonságot céloznak meg.

Téma-futtatás

Meghatározza a létrehozható témamotor osztálytípusát

Enyhítése

Egyes témamotorok,ha igazként határozzák meg az IsEasingSupported tulajdonságukat, támogatják az államok közötti eassziálást. Például két szín közötti lerakting állapotváltozás esetén. Az Időtartam másodpercben adja meg, hogy mennyi idő legyen a kezdő értéktől a záró értékig, az Animációs görbe pedig az adott időszak változási sebességét határozza meg.

Árnyékolási tulajdonságok

Ha egyes témamotorokigazként határozzák meg az AreShadersSupported tulajdonságot, akkor a futásidőben bizonyos árnyékoló tulajdonságokat módosít. A Shader ésa Property mező határozza meg a megcélzott árnyékoló tulajdonságot.

Témakonfiguráció létrehozása kóddal

Általánosságban elmondható, hogy a Unity vizsgálóval egyszerűbb témakonfigurációkat tervezni, de vannak olyan esetek, amikor a témákat futásidőben, kóddal kell dinamikusan generálni. Az alábbi kódrészlet egy példát mutat be a feladat elvégzésére.

A fejlesztés felgyorsítása érdekében az alábbi segítő módszerek segítenek leegyszerűsíteni a beállítást.

Interactable.GetDefaultInteractableStates()– létrehoz egy új States ScriptableObject objektumot az Interakcióra használható összetevőben használt négy alapértelmezett Interactable.GetDefaultInteractableStates()

ThemeDefinition.GetDefaultThemeDefinition<T>() – Minden témamotor meghatároz egy alapértelmezett konfigurációt, amely az adott téma-futtatási típushoz szükséges megfelelő tulajdonságokkal rendelkezik. Ez a segítő létrehoz egy definíciót az adott témamotor-típushoz.

// This code example builds a Theme ScriptableObject that can be used with an Interactable component.
// A random color is selected for the on pressed state every time this code is executed.

// Use the default states utilized in the Interactable component
var defaultStates = Interactable.GetDefaultInteractableStates();

// Get the default configuration for the Theme engine InteractableColorTheme
var newThemeType = ThemeDefinition.GetDefaultThemeDefinition<InteractableColorTheme>().Value;

// Define a color for every state in our Default Interactable States
newThemeType.StateProperties[0].Values = new List<ThemePropertyValue>()
{
    new ThemePropertyValue() { Color = Color.black},  // Default
    new ThemePropertyValue() { Color = Color.black}, // Focus
    new ThemePropertyValue() { Color = Random.ColorHSV()},   // Pressed
    new ThemePropertyValue() { Color = Color.black},   // Disabled
};

// Create the Theme configuration asset
Theme testTheme = ScriptableObject.CreateInstance<Theme>();
testTheme.States = defaultStates;
testTheme.Definitions = new List<ThemeDefinition>() { newThemeType };

Témamotorok

A témamotor egy osztály, amely a osztálytól terjed ki. Ezek az osztályok futásidőben példányosulnak, és a korábban ismertetett ThemeDefinition objektummal vannak konfigurálva.

Alapértelmezett témamotorok

Az MRTK az alábbi alapértelmezett témamotorokat tartalmazza:

Az alapértelmezett témamotorok a alatt MRTK/SDK/Features/UX/Scripts/VisualThemes/ThemeEngines találhatók.

Egyéni témamotorok

A témamotorok a osztálytól való kiterjesztésű osztályként vannak InteractableThemeBase definiálva. Ezért az új témamotornak csak ki kell terjesztenie ezt az osztályt, és a következőket kell megvalósítania:

Kötelező implementációk

public abstract void SetValue(ThemeStateProperty property, int index, float percentage) (xref:Microsoft.MixedReality.Toolkit.UI.InteractableThemeBase.SetValue)

A által azonosítható adott tulajdonsághoz állítsa be az aktuális állapotát a megcélzott GameObject gazdagépen (azaz állítsa be az anyag ThemeStateProperty.Name színét stb.). Az index jelzi az aktuálisan elérhető állapotértéket, és a százalékos értéket() egy 0 és 1 közötti lebegő érték használja az értékek közötti easszűrés/lerálás érdekében.

public abstract ThemePropertyValue GetProperty(ThemeStateProperty property)(xref:Microsoft.MixedReality.Toolkit.UI.InteractableThemeBase.GetProperty)

A által azonosítható adott tulajdonsághoz adja vissza a célzott GameObject gazdagépen beállított aktuális értéket (például az aktuális anyagszínt, az aktuális helyi pozíció eltolási értékét ThemeStateProperty.Name stb.). Ezt elsősorban a kezdőérték gyorsítótárazásakor használják az államok közötti easeringkor.

public abstract ThemeDefinition GetDefaultThemeDefinition()(xref:Microsoft.MixedReality.Toolkit.UI.InteractableThemeBase.GetDefaultThemeDefinition)

Egy objektumot ad vissza, amely meghatározza az egyéni témához szükséges alapértelmezett ThemeDefinition tulajdonságokat és konfigurációt

protected abstract void SetValue(ThemeStateProperty property, ThemePropertyValue value)

A nyilvános definíció védett változata, kivéve a SetValue() megadott ThemePropertyValue beállítást az index és/vagy százalékos konfiguráció használata helyett.

InteractableThemeBase.Init(GameObject host, ThemeDefinition settings)

Hajtsa végre a megadott GameObject paramétert célzó inicializálási lépéseket, és használja a ThemeDefinition paraméterben meghatározott tulajdonságokat és konfigurációkat. Javasoljuk, hogy base.Init(host, settings) egy felülbírálás elején hívja meg a következőt: .

InteractableThemeBase.IsEasingSupported

Ha az egyéni témamotor támogatja a tulajdonságon keresztül konfigurált értékek közötti ThemeDefinition.Easing easinget.

InteractableThemeBase.AreShadersSupported

Ha az egyéni témamotor támogatja a célárnyékolási tulajdonságokat. Javasoljuk, hogy a InteractableShaderThemeInteractableShaderThemesegítségével hatékonyan állítsa be/szerezze be az árnyékoló tulajdonságait a meglévő infrastruktúra kihasználása érdekében. A shader tulajdonságinformációit a és a tárolja ThemeStatePropertyThemeStateProperty.TargetShaderThemeStateProperty.ShaderPropertyName mindegyikben.

Megjegyzés

A kiterjesztésekor hasznos lehet felülbírálni a InteractableShaderThemeInteractableShaderTheme az új segítségével.

Példakód: protected new const string DefaultShaderProperty = "_Color";

Emellett az alábbi osztályok kibővítik az osztályt, amely szintén InteractableShaderThemeInteractableShaderTheme segítségével módosítja a shader tulajdonságértékeket. Ez a megközelítés segít a teljesítményben, mert a MaterialPropertyBlocks nem hoz létre új példányos anyagokat az értékek módosításakor. A material osztály jellemző tulajdonságainak elérése azonban nem a várt értékeket adja vissza. A MaterialPropertyBlocks használatával lekért és érvényesítheti az aktuális anyagtulajdonságok értékeit (például _Color vagy _MainTex).

InteractableThemeBase.Reset

Arra irányítja a témát, hogy visszaállítsa a módosított tulajdonságokat az eredeti értékükre, amelyek a gameObject gazdagépen a témamotor inicializálásakor voltak beállítva.

Példa egyéni témamotorra

Az alábbi osztály egy példa egy egyéni új témamotorra. Ez az implementáció egy MeshRenderer összetevőt fog találni az inicializált gazdaobjektumon, és az aktuális állapot alapján fogja szabályozni a láthatóságát.

using Microsoft.MixedReality.Toolkit.UI;
using System;
using System.Collections.Generic;
using UnityEngine;

// This class demonstrates a custom theme to control a Host's MeshRenderer visibility
public class MeshVisibilityTheme : InteractableThemeBase
{
    // Bool visibility does not make sense for lerping
    public override bool IsEasingSupported => false;

    // No material or shaders are being modified
    public override bool AreShadersSupported => false;

    // Cache reference to the MeshRenderer component on our Host
    private MeshRenderer meshRenderer;

    public MeshVisibilityTheme()
    {
        Types = new Type[] { typeof(MeshRenderer) };
        Name = "Mesh Visibility Theme";
    }

    // Define a default configuration to simplify initialization of this theme engine
    // There is only one state property with a value per available state
    // This state property is a boolean that defines whether the renderer is enabled
    public override ThemeDefinition GetDefaultThemeDefinition()
    {
        return new ThemeDefinition()
        {
            ThemeType = GetType(),
            StateProperties = new List<ThemeStateProperty>()
            {
                new ThemeStateProperty()
                {
                    Name = "Mesh Visible",
                    Type = ThemePropertyTypes.Bool,
                    Values = new List<ThemePropertyValue>(),
                    Default = new ThemePropertyValue() { Bool = true }
                },
            },
            CustomProperties = new List<ThemeProperty>()
        };
    }

    // When initializing, cache a reference to the MeshRenderer component
    public override void Init(GameObject host, ThemeDefinition definition)
    {
        base.Init(host, definition);

        meshRenderer = host.GetComponent<MeshRenderer>();
    }

    // Get the current state of the MeshRenderer visibility
    public override ThemePropertyValue GetProperty(ThemeStateProperty property)
    {
        return new ThemePropertyValue()
        {
            Bool = meshRenderer.enabled
        };
    }

    // Update the MeshRenderer visibility based on the property state value data
    public override void SetValue(ThemeStateProperty property, int index, float percentage)
    {
        meshRenderer.enabled = property.Values[index].Bool;
    }
}

Teljes példa

A korábbi szakaszban meghatározott egyéni témamotor kibővítését az alábbi példakód bemutatja, hogyan vezérelheti ezt a témát futásidőben. A téma aktuális állapotának beállítása a MeshRenderer láthatóságának megfelelő módosítása érdekében.

Megjegyzés

theme.OnUpdate(state,force) általában az Update() metódusban kell őket meghívni az értékek közötti easing/lerpinget támogató témamotorok támogatásához.

using Microsoft.MixedReality.Toolkit.UI;
using System;
using System.Collections.Generic;
using UnityEngine;

public class MeshVisibilityController : MonoBehaviour
{
    private MeshVisibilityTheme themeEngine;
    private bool hideMesh = false;

    private void Start()
    {
        // Define the default configuration. State 0 will be on while State 1 will be off
        var themeDefinition = ThemeDefinition.GetDefaultThemeDefinition<MeshVisibilityTheme>().Value;
        themeDefinition.StateProperties[0].Values = new List<ThemePropertyValue>()
        {
            new ThemePropertyValue() { Bool = true }, // show state
            new ThemePropertyValue() { Bool = false }, // hide state
        };

        // Create the actual Theme engine and initialize it with the GameObject we are attached to
        themeEngine = (MeshVisibilityTheme)InteractableThemeBase.CreateAndInitTheme(themeDefinition, this.gameObject);
    }

    private void Update()
    {
        // Update the theme engine to set our MeshRenderer visibility
        // based on our current state (i.e the hideMesh variable)
        themeEngine.OnUpdate(Convert.ToInt32(hideMesh));
    }

    public void ToggleVisibility()
    {
        // Alternate state of visibility
        hideMesh = !hideMesh;
    }
}

Lásd még