Görsel temalar — MRTK2

Temalar, çeşitli durum geçişlerine yanıt olarak UX varlıklarının esnek bir şekilde denetlenebilmesini sağlar. Bu, düğmenin rengini değiştirmeyi, odaklanmaya yanıt olarak bir öğeyi yeniden boyutlandırmayı vb. içerebilir. Görsel Temalar çerçevesi iki önemli parçadan oluşur: 1) yapılandırma ve 2) çalışma zamanı altyapıları.

Tema yapılandırmaları özelliklerin ve türlerin tanımlarıyken , Tema Altyapıları yapılandırmaları kullanan ve çalışma zamanında dönüşümleri, malzemeleri ve daha fazlasını güncelleştirmek için mantığı uygulayan sınıflardır.

Tema yapılandırması

Tema yapılandırmaları, Tema Altyapılarının çalışma zamanında nasıl başlatılacağını tanımlayan ScriptableObjects'tir . Uygulama çalışırken girişe veya diğer durum değişikliklerine yanıt olarak hangi özelliklerin ve değerlerin kullanılacağını tanımlar. ScriptableObjects varlıkları olarak tema yapılandırmaları bir kez tanımlanabilir ve ardından farklı UX bileşenlerinde yeniden kullanılabilir.

Yeni Theme varlık oluşturmak için:

  1. Proje Penceresi'ne sağ tıklayın
  2. Oluştur Karma Gerçeklik Araç Seti>Teması'nı> seçin

Örnek Tema yapılandırma varlıkları altında MRTK/SDK/Features/UX/Interactable/Themesbulunabilir.

Denetçide Theme ScriptableObject örneği

Durumlar

Yeni Themebir oluştururken, ayarlanacağı ilk şey hangi durumların kullanılabilir olduğudur. States özelliği, durum başına bir değer olacağı için Tema yapılandırmasının tanımlaması gereken değer sayısını gösterir. Yukarıdaki örnek görüntüde, Etkileşimli bileşen için tanımlanan varsayılan durumlarVarsayılan, Odak, Basıldı ve Devre Dışı'dır. Bunlar (Assets/MRTK/SDK/Features/UX/Interactable/States) varlık dosyasında tanımlanır DefaultInteractableStates .

Yeni State varlık oluşturmak için:

  1. Proje Penceresi'ne sağ tıklayın
  2. Oluştur Karma Gerçeklik Araç Seti>Durumu'nı> seçin

Denetçide States ScriptableObject örneği

ScriptableObject State hem durum listesini hem de bu durumlar için oluşturulacak StateModel türünü tanımlar. StateModel, çalışma zamanında geçerli durumu oluşturmak için durum makinesi mantığını genişleten BaseStateModel ve uygulayan bir sınıftır. Bu sınıftaki geçerli durum genellikle Tema Motorları tarafından malzeme özellikleri, GameObject dönüşümleri ve daha fazlası için hangi değerlerin ayarlandığını dikte etmek için çalışma zamanında kullanılır.

Tema altyapısı özellikleri

Eyaletler dışında bir Theme varlık, Tema Altyapılarının listesini ve bu altyapılar için ilişkili özellikleri de tanımlar. Tema altyapısı, çalışma zamanında GameObject için doğru değerleri ayarlama mantığını yeniden tanımlar.

Bir Theme varlık, birden çok GameObject özelliğini hedefleyen gelişmiş görsel durum geçişleri elde etmek için birden çok Tema Altyapısı tanımlayabilir.

Tema Çalışma Zamanı

Oluşturulacak Tema altyapısının sınıf türünü tanımlar

Hareket hızı

Bazı Tema Altyapıları, IsEasingSupported özelliğini true olarak tanımlıyorsa, durumlar arasında kolaylaştırmayı destekler. Örneğin, durum değişikliği gerçekleştiğinde iki renk arasında lerping. Süre, başlangıç değerinden bitiş değerine ne kadar süreyle kolaylaştırıldığını saniye cinsinden tanımlar ve Animasyon Eğrisi de bu zaman aralığındaki değişiklik oranını tanımlar.

Gölgelendirici özellikleri

Bazı Tema Altyapıları, AreShadersSupported özelliğini true olarak tanımlarsa, çalışma zamanında belirli gölgelendirici özelliklerini değiştirir. Gölgelendirici ve Özellik alanları hedeflene gölgelendirici özelliğini tanımlar.

Kod aracılığıyla tema yapılandırması oluşturma

Genel olarak, Unity denetçisi aracılığıyla Tema yapılandırmaları tasarlamak daha kolaydır, ancak çalışma zamanında kod aracılığıyla dinamik olarak Tema oluşturulması gereken durumlar vardır. Aşağıdaki kod parçacığı, bu görevin nasıl yerine getir yapılacağını gösteren bir örnek verir.

Geliştirmeyi hızlandırmaya yardımcı olmak için aşağıdaki yardımcı yöntemler kurulumu basitleştirmek için yararlıdır.

Interactable.GetDefaultInteractableStates() - Interactable bileşeninde kullanılan dört varsayılan durum değeriyle yeni bir States ScriptableObject oluşturur.

ThemeDefinition.GetDefaultThemeDefinition<T>() - Her Tema Altyapısı, tema çalışma zamanı türü için gereken doğru özelliklere sahip bir varsayılan yapılandırma tanımlar. Bu yardımcı, verilen Tema Altyapısı türü için bir tanım oluşturur.

// 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 };

Tema motorları

Tema Altyapısı, sınıfından genişleten InteractableThemeBase bir sınıftır. Bu sınıfların örneği çalışma zamanında oluşturulur ve daha önce açıklandığı gibi bir ThemeDefinition nesneyle yapılandırılır.

Varsayılan tema altyapıları

MRTK, aşağıda listelenen varsayılan Tema Altyapıları kümesiyle birlikte gelir:

Varsayılan Tema Altyapıları altında MRTK/SDK/Features/UX/Scripts/VisualThemes/ThemeEnginesbulunabilir.

Özel tema altyapıları

Belirtildiği gibi, Tema Altyapısı sınıfından genişleten InteractableThemeBase bir sınıf olarak tanımlanır. Bu nedenle, yeni Tema Altyapısı'nın yalnızca bu sınıfı genişletmesi ve aşağıdakileri uygulaması gerekir:

Zorunlu uygulamalar

public abstract void SetValue(ThemeStateProperty property, int index, float percentage)

tarafından ThemeStateProperty.Nametanımlanabilen verilen özellik için, hedeflenen GameObject konağındaki (malzeme rengini vb.) geçerli durum değerini ayarlayın. Dizin, erişilmesi gereken geçerli durum değerini ve değerler arasında kolaylaştırma/lerping için 0 ile 1 arasında bir kayan değer olan yüzdeyi gösterir.

public abstract ThemePropertyValue GetProperty(ThemeStateProperty property)

tarafından ThemeStateProperty.Nametanımlanabilen verilen özellik için, hedeflenen Host GameObject üzerinde ayarlanan geçerli değeri (geçerli malzeme rengi, geçerli yerel konum uzaklığı vb.) döndürür. Bu, öncelikle durumlar arasında geçiş yaparken başlangıç değerini önbelleğe almak için kullanılır.

public abstract ThemeDefinition GetDefaultThemeDefinition()

Özel tema için gereken varsayılan özellikleri ve yapılandırmayı tanımlayan bir ThemeDefinition nesne döndürür

protected abstract void SetValue(ThemeStateProperty property, ThemePropertyValue value)

Dizin ve/veya yüzde yapılandırmasını kullanmaya yönlendirmek yerine ayarlanacak ThemePropertyValue dışında genel SetValue() tanımın korumalı değişkeni.

InteractableThemeBase.Init(GameObject host, ThemeDefinition settings)

Burada sağlanan GameObject parametresini hedefleyen ve ThemeDefinition parametresinde tanımlanan özellikleri ve yapılandırmaları kullanarak başlatma adımlarını gerçekleştirin. Bir geçersiz kılmanın başında çağrısı base.Init(host, settings) önerilir.

InteractableThemeBase.IsEasingSupported

Özel Tema Altyapısı özelliği aracılığıyla ThemeDefinition.Easing yapılandırılan değerler arasında kolaylaştırmayı destekleyebilirse.

InteractableThemeBase.AreShadersSupported

Özel Tema Altyapısı gölgelendirici özelliklerini hedeflemeyi destekleyebilirse. MaterialPropertyBlocks aracılığıyla gölgelendirici özelliklerini verimli bir şekilde ayarlamak/almak için mevcut altyapıdan yararlanmak için'i InteractableShaderTheme genişletmenizi öneririz. Gölgelendirici özellik bilgileri ve ThemeStateProperty.ShaderPropertyNamearacılığıyla ThemeStateProperty.TargetShader her ThemeStateProperty birinde depolanır.

Not

genişletiyorsanızInteractableShaderTheme, yeni aracılığıyla InteractableShaderTheme.DefaultShaderProperty öğesini geçersiz kılmak da yararlı olabilir.

Örnek kod: protected new const string DefaultShaderProperty = "_Color";

Ayrıca aşağıdaki sınıflar, gölgelendirici özellik değerlerini değiştirmek için MaterialPropertyBlocks kullanan sınıfını genişletirInteractableShaderTheme. Değerler değiştiğinde MaterialPropertyBlocks yeni örneklenmiş malzemeler oluşturmadığından bu yaklaşım performansa yardımcı olur. Ancak, tipik Material sınıfı özelliklerine erişmek beklenen değerleri döndürmez. Geçerli malzeme özelliği değerlerini (_Color veya_MainTex) almak ve doğrulamak için MaterialPropertyBlocks kullanın.

InteractableThemeBase.Reset

Bu tema altyapısı başlatıldığında, değiştirilmiş özellikleri ana GameObject'te ayarlanan özgün değerlerine sıfırlamak için temayı yönlendirir.

Özel tema altyapısı örneği

Aşağıdaki sınıf, özel bir yeni Tema Altyapısı örneğidir. Bu uygulama, başlatılan konak nesnesinde bir MeshRenderer bileşeni bulur ve geçerli duruma göre görünürlüğünü denetler.

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;
    }
}

Uçtan uca örnek

Önceki bölümde tanımlanan özel Tema Altyapısı'nın kapsamını genişleten aşağıdaki kod örneği, çalışma zamanında bu temayı denetlemeyi gösterir. Özellikle, MeshRenderer görünürlüğünün uygun şekilde güncelleştirilmesi için temadaki geçerli durumun nasıl ayarlanacağı.

Not

theme.OnUpdate(state,force) genellikle değerler arasında kolaylaştırıcı/lerping kullanan Tema Altyapılarını desteklemek için Update() yönteminde çağrılmalıdır.

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;
    }
}

Ayrıca bkz.