mrtk_developmentreleases/2.0.0releases/2.1.0releases/2.2.0
  • 指南
  • API 文档
  • 指南

    Show / Hide Table of Contents
    • MRTK入门
      • 发布说明
      • MRTK包内容
      • 从早期版本更新
      • 从HTK更新
      • 生成和部署MRTK
      • NuGet包
      • MRTK配置对话框
      • 开始使用 MRTK和XR SDK
      • 性能
      • 全息图稳定
      • 在大型项目中使用MRTK
    • 架构
      • 概述
      • 框架和运行时
      • 输入系统
        • 术语
        • 核心系统
        • Controllers, pointers, and focus
      • 系统,扩展服务和 data providers
    • 功能概述
      • 边界系统 Boundary System
        • 边界系统概述
        • 配置边界可视化
      • 相机系统 Camera System
        • 相机系统概述
        • Camera Settings Providers
          • Windows 混合现实相机设置
          • Unity AR相机设置[实验性]
          • 创建camera settings provider
      • 跨平台支持
        • 为iOS和Android配置MRTK
      • 检测平台能力
      • 诊断系统 Diagnostics System
        • 诊断系统概述
        • 配置诊断系统
        • 使用可视化分析器
      • 扩展服务 Extension Services
        • 扩展服务创建向导
        • 场景过渡服务概述
      • 输入系统 Input System
        • 输入概览
        • 输入动作 Input Actions
        • 输入事件 Input Events
        • Input Providers
          • Input Providers 概述
          • 创建一个 input data provider
        • 控制器 Controllers
        • 眼动跟踪 Eyes
          • 概述
          • 入门
          • 通过代码访问数据
          • 验证跟踪校准 Validate Tracking Calibration
        • 凝视 Gaze
        • 手势 Gestures
        • 手部 Hands
        • 如何添加近距离交互 Near Interaction
        • 编辑器内输入模拟 In-Editor Input Simulation
        • 指针 Pointers
        • 语音输入 Voice Input
          • 语音转录 Dictation
          • 语音(命令和控制) Speech
      • 多场景系统 Multi Scene System
        • 多场景系统概述
        • 场景类型 Scene Types
        • 内容场景加载 Content Scene Loading
        • 监测内容加载 Monitoring Content Loading
        • 光照场景操作 Lighting Scene Operations
      • 打包 Packaging
        • MRTK包 MRTK Packages
        • MRTK模块化 MRTK Modularization
      • 配置文件 Profiles
        • 配置文件概述
        • 配置指南 Configuration Guide
      • 渲染 Rendering
        • 材质实例概述 Material Instance Overview
        • Shaders
          • MRTK标准着色器 MRTK Standard Shader
      • 服务 Services
        • 什么是混合现实特性
        • 什么是 MixedRealityServiceRegistry 和IMixedRealityServiceRegistrar
        • 扩展服务 Extension services
      • 空间感知系统 Spatial Awareness System
        • 空间感知概述
        • Spatial Observers
          • 为设备配置 Observers
          • 为Editor配置 Observers
          • 通过代码控制 Observers
          • 创建自定义 Observer
      • 传送系统概述 Teleport System Overview
      • 工具
        • Dependency Window
        • Extension Service Creation Wizard
        • Holographic Remoting
        • Input Animation Recording
          • Input Animation File Format Specification
        • Optimize Window
        • Runtime tools
          • Controller Mapping tool
      • UX 构建模块
        • 工具箱窗口 Toolbox Window
        • 按钮 Button
        • 边界框 Bounding Box
        • 对象操纵器 Object Manipulator
        • Manipulation Handler [废弃]
        • Slate
        • 系统键盘 System Keyboard
        • 可交互的 Interactable
        • Solvers
          • 点击放置 Tap to Place
        • 对象集合 Object Collection
        • 提示工具条 Tooltips
        • 滑动条 Slider
        • 手部菜单 Hand Menu
        • 近处菜单 Near Menu
        • 应用程序栏 App Bar
        • 指尖可视化 Fingertip Visualization
        • 进度指示器 Progress Indicator
        • 对话框 Dialog [实验性]
        • 手势教学 Hand Coach [实验性]
        • 可滚动对象集合 Scrolling Object Collection [实验性]
        • 脉冲着色器 Pulse Shader [实验性]
        • 停靠控件 Dock Control [实验性]
        • HoloLens键盘助手 [实验性]
      • 示例场景
        • 示例中心
        • 手势交互示例场景
        • 眼动跟踪示例场景
    • Contributing
      • Contributing Overview
      • Coding Guidelines
      • Writing and Running Tests
      • Writing Documentation
      • Pull Requests
      • Experimental Features
      • Breaking Changes
      • How to use DocFX
    • Planning
      • Roadmap
    • Notice
    • Authors

    Visual Themes

    Themes allow for flexible control of UX assets in response to various states transitions. This may involve changing a button's color, resizing an element in response to focus, etc. The Visual Themes framework is made up of two key pieces: 1) configuration and 2) runtime engines.

    Theme configurations are definitions of properties and types while Theme Engines are classes that consume the configurations and implement the logic to update transforms, materials, and more at runtime.

    Theme configuration

    Theme configurations are ScriptableObjects that define how Theme Engines will be initialized at runtime. They define what properties and values to utilize in response to input or other state changes when the app is running. As ScriptableObjects assets, theme configurations can be defined once and then re-used across different UX components.

    To create a new Theme asset:

    1. Right click in the Project Window
    2. Select Create > Mixed Reality Toolkit > Theme

    Example Theme configuration assets can be found under MixedRealityToolkit.SDK/Features/UX/Interactable/Themes.

    Theme ScriptableObject example in inspector

    States

    When creating a new Theme, the first thing to set is what states are available. The States property indicates how many values a Theme configuration needs to define as there will be one value per state. In the example image above, the default states defined for the Interactable component are Default, Focus, Pressed, and Disabled. These are defined in the DefaultInteractableStates asset file.

    To create a new State asset:

    1. Right click in the Project Window
    2. Select Create > Mixed Reality Toolkit > State

    States ScriptableObject example in inspector

    A State ScriptableObject defines both the list of states as well as the type of StateModel to create for these states. A StateModel is a class that extends BaseStateModel and implements the state machine logic to generate the current state at runtime. The current state from this class is generally used by Theme Engines at runtime to dictate what values to set against material properties, GameObject transforms, and more.

    Theme Engine properties

    Outside of States, a Theme asset also defines a list of Theme Engines and the associated properties for these engines. A Theme engine again defines the logic to set the correct values against a GameObject at runtime.

    A Theme asset can define multiple Theme Engines to achieve sophisticated visual states transitions targeting multiple GameObject properties.

    Theme Runtime

    Defines the class type of the Theme engine that will be created

    Easing

    Some Theme Engines, if they define their property IsEasingSupported as true, support easing between states. For example, lerping between two colors when a state change occurs. The Duration defines in seconds how long to ease from start value to end value and the Animation Curve defines the rate of change during that time period.

    Shader properties

    Some Theme Engines, if they define their property AreShadersSupported as true, will modify particular shader properties at runtime. The Shader and Property fields define the shader property to target.

    Create a theme configuration via code

    In general, it is easier to design Theme configurations via the Unity inspector but there are cases where Themes must be dynamically generated at runtime via code. The code snippet below gives an example of how to accomplish this task.

    To help expedite development, the following helper methods are useful for simplifying setup.

    Interactable.GetDefaultInteractableStates() - creates a new States ScriptableObject with the four default state values used in the Interactable component.

    ThemeDefinition.GetDefaultThemeDefinition<T>() - Every Theme Engine defines a default configuration with the correct properties needed for that Theme runtime type. This helper creates a definition for the given Theme Engine type.

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

    Theme Engines

    A Theme Engine is a class that extends from the InteractableThemeBase class. These classes are instantiated at runtime and configured with a ThemeDefinition object as outlined earlier.

    Default Theme Engines

    MRTK ships with a default set of Theme Engines listed below:

    • InteractableActivateTheme
    • InteractableAnimatorTheme
    • InteractableAudioTheme
    • InteractableColorChildrenTheme
    • InteractableColorTheme
    • InteractableGrabScaleTheme
    • InteractableMaterialTheme
    • InteractableOffsetTheme
    • InteractableRotationTheme
    • InteractableScaleTheme
    • InteractableShaderTheme
    • InteractableStringTheme
    • InteractableTextureTheme
    • ScaleOffsetColorTheme

    The default Theme Engines can be found under MixedRealityToolkit.SDK/Features/UX/Scripts/VisualThemes/ThemeEngines.

    Custom Theme Engines

    As stated, a Theme Engine is defined as a class that extends from the InteractableThemeBase class. Thus, new Theme Engine need only extend this class and implement the following:

    Mandatory implementations

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

    For the given property, which can be identified by ThemeStateProperty.Name, set its current state value on the targeted GameObject host (i.e set the material color, etc). The index indicates the current state value to access and the percentage, a float between 0 and 1, is used for easing/lerping between values.

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

    For the given property, which can be identified by ThemeStateProperty.Name, return the current value set on the targeted Host GameObject (i.e the current material color, the current local position offset, etc). This is primarily used for caching the start value when easing between states.

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

    Returns a ThemeDefinition object that defines the default properties and configuration needed for the custom theme

    Recommended overrides

    InteractableThemeBase.Init(GameObject host, ThemeDefinition settings)

    Perform any initialization steps here targeting the provided GameObject parameter and using the properties and configurations defined in the ThemeDefinition parameter. It is recommended to call base.Init(host, settings) at the beginning of an override.

    InteractableThemeBase.IsEasingSupported

    If the custom Theme Engine can support easing between values which is configured via the ThemeDefinition.Easing property.

    InteractableThemeBase.AreShadersSupported

    If the custom Theme Engine can support targeting shader properties. It is recommended to extend from InteractableShaderTheme to benefit from the existing infrastructure to efficiently set/get shader properties via MaterialPropertyBlocks. The shader property information is stored in each ThemeStateProperty via ThemeStateProperty.TargetShader and ThemeStateProperty.ShaderPropertyName.

    Note

    If extending InteractableShaderTheme, it can also be useful to override the InteractableShaderTheme.DefaultShaderProperty via new.

    Example code: protected new const string DefaultShaderProperty = "_Color";

    Furthermore, the following classes below extend the InteractableShaderTheme class which again uses MaterialPropertyBlocks to modify shader property values. This approach helps performance because MaterialPropertyBlocks do not create new instanced materials when values change. However, accessing the typical Material class properties will not return expected values. Use MaterialPropertyBlocks to get and validate current material property values (i.e _Color or _MainTex).

    • InteractableColorChildrenTheme
    • InteractableColorTheme
    • InteractableTextureTheme
    • ScaleOffsetColorTheme

    Custom Theme Engine example

    The class below is an example of a custom new Theme Engine. This implementation will find a MeshRenderer component on the initialized host object and control its visibility based on the current state.

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

    End-to-end example

    Extending off of the custom Theme Engine defined in the earlier section, the code example below demonstrates how to control this theme at runtime. In particular, how to set the current state on the theme so the MeshRenderer visibility is updated appropriately.

    Note

    theme.OnUpdate(state,force) should generally be called in the Update() method to support Theme Engines that utilize easing/lerping between values.

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

    See also

    • Interactable
    • Improve this Doc
    In This Article
    • Theme configuration
      • States
      • Theme Engine properties
      • Create a theme configuration via code
    • Theme Engines
      • Default Theme Engines
      • Custom Theme Engines
        • Mandatory implementations
        • Recommended overrides
      • Custom Theme Engine example
    • End-to-end example
    • See also
    Back to top Generated by DocFX