步骤 4 - 创建用于选择小部件的交互处理程序

在本教程中,您将创建一个应用程序,其中用户可以滚动 Widget Grid List Box 中包含的小部件列表,并使他们能够从该列表中选择由 Widget Item Prefab 表示的小部件。Grid List Box 3D 节点提供了您可以在 Kanzi Studio 项目中设置的水平滚动,但您需要定义处理小部件选择的应用程序逻辑。

在该教程的这一步骤中,您将实现在用户点击小组件时处理小组件项选择的功能:

  • 触发将摄像机缩放到特定位置的动画,以便选定的小组件在应用程序窗口左侧高亮显示。

  • 触发将选定小组件朝向摄像机的动画,使其高亮显示。

  • 使应用程序窗口右侧由 Widget Description Layer 节点表示的描述面板可见。描述面板包含每个小部件的描述、一个返回按钮和一个购买按钮。当 Widget Description Layer 可见时,Widget Grid List Box 的滚动被禁用。当相机缩放动画进行时,Back 按钮被禁用。

要创建选择小组件的交互处理程序:

  1. 在 ProgrammerTutorialApplication 类中,在 Application::onProjectLoaded 函数之后,实现用于选择 Widget Grid List Box 中小部件的事件处理程序。使用所选小部件的索引从 Widget Grid List Box 节点中检索所选小部件。

    class ProgrammerTutorialApplication : public ExampleApplication
    {
    ...
    private:
    
        // The handler for the ListBox.ItemSelected message from the Widget Grid List Box.
        // Brings the selected list box item to the front.
        void onListBoxItemSelected(ListBoxConcept::ItemSelectedMessageArguments& messageArguments)
        {
            // Retrieve the index of the selected list box item from the message arguments.
            optional<size_t> selectedItemIndex = messageArguments.getSelectedItemIndex();
    
            if (selectedItemIndex)
            {
                // Remove old playbacks to reset the values.
                // You implement this function in the next step of the tutorial.
                removePlaybacks();
    
                // Retrieve the selected list box item by its index.
                m_selectedItem = m_widgetList->getItem(*selectedItemIndex);
         ...
            }
        }
    };
    
  2. 目标动画重新定位摄像机。动画获取节点的当前变换,并动画到由另一个节点定义的另一个变换。现在,存储的摄像机变换已更新为所选小部件的平移。为摄像机创建动画,并启动动画。

    void onListBoxItemSelected(ListBoxConcept::ItemSelectedMessageArguments& messageArguments)
    {
    ...
        if (selectedItemIndex)
        {
            ...
            // Calculate a new value for the camera animation target node and start the animation.
            {
                // Get the current transformation.
                Matrix4x4 selectedItemTransformation = m_selectedItem->getFinalTransformation();
                // Get the camera's relative transformation target position.
                SRTValue3D transformationTarget = m_cameraTransformationTarget;
                // Add the position of the selected item to the target camera transformation.
                transformationTarget.setTranslation(selectedItemTransformation.getTranslation() - transformationTarget.getTranslation());
                // Create the animation for the camera.
                m_cameraAnimation = FromToAnimation<SRTValue3D, LinearEasingFunction>::create(getDomain(), chrono::seconds(1), nullopt, transformationTarget);
    
                // Start the animation.
                PropertyAnimationTimelineSharedPtr cameraTimeline = PropertyAnimationTimeline::create(getDomain(), ".", Node3D::RenderTransformationProperty, m_cameraAnimation);
                SceneGraphTimelinePlaybackContext cameraContext(*m_camera);
                m_cameraPlayback = cameraTimeline->createPlayback(cameraContext);
                getDomain()->getRootTimelineClock()->addTimelinePlayback(m_cameraPlayback);
            }
        }
    ...
    }
    
  3. 现在,Camera 动画的变换目标已更新,您可以启动所选小部件的高亮动画。高亮动画将小部件围绕其 x 轴从固定值 0 度旋转到 60 度,并在 Application::onProjectLoaded 函数中定义。

    void onListBoxItemSelected(ListBoxConcept::ItemSelectedMessageArguments& messageArguments)
    {
    ...
        if (selectedItemIndex)
        {
       ...
            // Start the animation for the selected item.
            PropertyAnimationTimelineSharedPtr selectedItemTimeline = PropertyAnimationTimeline::create(getDomain(), ".", Node3D::LayoutTransformationProperty, m_selectedItemAnimation);
            SceneGraphTimelinePlaybackContext selectedItemContext(*m_selectedItem);
            m_widgetHighlightPlayback = selectedItemTimeline->createPlayback(selectedItemContext);
            getDomain()->getRootTimelineClock()->addTimelinePlayback(m_widgetHighlightPlayback);
        }
    }
    
  4. 当动画开始时,禁用 Back button 的输入。

    void onListBoxItemSelected(ListBoxConcept::ItemSelectedMessageArguments& messageArguments)
    {
    ...
        if (selectedItemIndex)
        {
        ...
    
            // Start the animation to disable input for the Back button.
            PropertyAnimationTimelineSharedPtr backButtonEnableTimeline = PropertyAnimationTimeline::create(getDomain(), ".", Button3D::HitTestableProperty, m_backButtonEnableAnimation);
            SceneGraphTimelinePlaybackContext backButtonEnableContext(*m_backButton);
            m_backButtonEnablePlayback = backButtonEnableTimeline->createPlayback(backButtonEnableContext);
            getDomain()->getRootTimelineClock()->addTimelinePlayback(m_backButtonEnablePlayback);
        }
    }
    
  5. 从 Programmertutorial.WidgetDescription 属性获取小部件描述,并将 Text Block 2D 节点的 Text 属性的值设置为 Programmertutorial.WidgetDescription 属性的值,并使包含应用程序窗口右侧面板的 Widget Description Layer 可见。

    void onListBoxItemSelected(ListBoxConcept::ItemSelectedMessageArguments& messageArguments)
    {
    ...
        if (selectedItemIndex)
        {
        ...
            // Show the widget description by setting the Widget Description Layer visible.
            if (m_widgetDescriptionVisibilityPlayback)
            {
                getDomain()->getRootTimelineClock()->removeTimelinePlayback(*m_widgetDescriptionVisibilityPlayback);
                m_widgetDescriptionVisibilityPlayback.reset();
            }
    
            // Set the widget description to the description text. The description is taken from the widget node.
            string widgetDescription = m_selectedItem->getProperty(*m_widgetDescriptionPropertyType);
            m_widgetDescriptionTextBlock->setText(widgetDescription);
    
            // Set the Widget Description Layer visible.
            m_widgetDescriptionNode->setVisible(true);
        }
    }
    
  6. 在 Application::onProjectLoaded 函数中,在填充小部件列表后,为 Widget Grid List Box 节点的 ListBoxConcept::ItemSelectedMessage 注册消息处理程序。

    void onProjectLoaded() override
    {
    ...
        // Add a message handler for selecting the Grid List Box 3D item events.
        m_widgetList->addMessageHandler(GridListBox3D::ItemSelectedMessage, bind(&ProgrammerTutorialApplication::onListBoxItemSelected, this, placeholders::_1));
    }
    

    当点击小组件时,应用程序使用指定的两个动画高亮显示小组件,使 Widget Description Layer 节点可见,并在 Widget Description Layer 中显示小组件描述。

另请参阅

编辑动画剪辑

创建关键帧动画

动画 (Animations)