E Story 故事编辑器开发笔记 #9 创建并美化分组

创建分组

了解分组基本结构

  • 主容器(mainContainer)
    • 头部容器(headerContainer)
    • 内容容器(contentContainer)

创建基础分组类

  1. 打开UI文件夹,创建C#文件,命名为BaseGroup
  2. 打开BaseGroup.cs,将内容修改如下:
C#
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;

namespace E.Story
{
    // 基类分组
    public class BaseGroup : Group
    {
        // 分组GUID
        public string ID { get; set; }

        // 旧分组标题
        public string OldTitle { get; set; }

        // 构造器
        public BaseGroup(string title, Vector2 position)
        {
            // 设置公共属性
            ID = GUID.Generate().ToString();
            this.title = title;
            OldTitle = title;
            SetPosition(new Rect(position, Vector2.zero));
        }
    }
}

实现创建分组方法

打开StoryGraphView.cs,新增CreateGroup方法:

C#
// 创建分组
public BaseGroup CreateGroup(string title, Vector2 position, bool moveSelectedNodes = true)
{
    BaseGroup group = new(title, position);

    AddElement(group);

    if (moveSelectedNodes)
    {
        // 如果选中了若干节点后创建分组,则将这些节点放入新的分组
        foreach (GraphElement item in selection)
        {
            if (item is BaseNode baseNode)
            {
                group.AddElement(baseNode);
            }
        }
    }

    return group;
}

添加上下文菜单按钮

修改BuildContextualMenu方法:

C#
public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
{
    /* ... 此处代码已省略 ... */

    evt.menu.AppendAction("添加分组", action =>
    {
        CreateGroup("分组", GetLocalMousePosition(action.eventInfo.localMousePosition));
    });
}

修复坐标偏移问题

  1. 修改GetLocalMousePosition方法:
C#
// 获取本地光标坐标
public Vector2 GetLocalMousePosition(Vector2 screenMousePosition, bool isNodeCreationBox = false)
{
    Vector2 windowMousePosition;
    if (isNodeCreationBox)
    {
        // 将光标的屏幕坐标转换为光标在当前窗口内的坐标
        windowMousePosition = screenMousePosition - storyEditorWindow.position.position;
    }
    else
    {
        windowMousePosition = screenMousePosition;
    }
    // 将光标在当前窗口内的坐标转换为光标在节点视图内的坐标
    Vector2 localMousePosition = contentViewContainer.WorldToLocal(windowMousePosition);
    return localMousePosition;
}
  1. 打开NodeCreationBox.cs,找到方法调用位置并修改相关参数:
C#
// 当点击对话框某个按钮时
public bool OnSelectEntry(SearchTreeEntry SearchTreeEntry, SearchWindowContext context)
{
    // 获取本地点击坐标
    Vector2 localMousePostion = graphViewer.GetLocalMousePosition(context.screenMousePosition, true);

    /* ... 此处代码已省略 ... */
}

美化分组

添加选择器

打开GraphViewStyle.uss,新增以下内容:

CSS
/* 分组头部容器 */
.group__head-container
{
}

/* 分组头部容器 > 标签 */
.group__head-container > #titleContainer > .unity-label
{
    min-height: 32px;
}

/* 分组头部容器 > 文本字段输入框 */
.group__head-container > #titleContainer > .unity-text-field > .unity-text-field__input
{
    background-color:  var(--colors-dark-grey-0);
    font-size: var(--metrics-pixels-20);
    -unity-text-align: middle-center;
}

应用样式

打开BaseGroup.cs,修改BaseGroup方法:

C#
// 构造器
public BaseGroup(string title, Vector2 position)
{
    /* ... 此处代码已省略 ... */
    
    // 添加 USS 类
    headerContainer.AddToClassList("group__head-container");
}

测试效果

最终窗口效果如下:

相关链接

留下评论