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:
- Proje Penceresi'ne sağ tıklayın
- 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/Themes
bulunabilir.
Durumlar
Yeni Theme
bir 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:
- Proje Penceresi'ne sağ tıklayın
- Oluştur Karma Gerçeklik Araç Seti>Durumu'nı> seçin
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:
InteractableActivateTheme
InteractableAnimatorTheme
InteractableAudioTheme
InteractableColorChildrenTheme
InteractableColorTheme
InteractableGrabScaleTheme
InteractableMaterialTheme
InteractableOffsetTheme
InteractableRotationTheme
InteractableScaleTheme
InteractableShaderTheme
InteractableStringTheme
InteractableTextureTheme
ScaleOffsetColorTheme
Varsayılan Tema Altyapıları altında MRTK/SDK/Features/UX/Scripts/VisualThemes/ThemeEngines
bulunabilir.
Ö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.Name
tanı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.Name
tanı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.
Önerilen geçersiz kılmalar
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.ShaderPropertyName
aracı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.
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;
}
}