Boat Attack使用了Universal RP的许多新图形功能,可以用于探索 Universal RP 的使用方式和技巧。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

310 行
11 KiB

using UnityEditor.IMGUI.Controls;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Unity.Collections;
using UnityEngine;
namespace Unity.Entities.Editor
{
internal delegate void SetEntityListSelection(EntityListQuery query);
internal class EntityQueryListView : TreeView {
private static Dictionary<ComponentSystemBase, List<EntityQueryDesc>> queriesBySystem = new Dictionary<ComponentSystemBase, List<EntityQueryDesc>>();
private static readonly Dictionary<EntityQuery, EntityQueryDesc> queriesByGroup = new Dictionary<EntityQuery, EntityQueryDesc>();
private static EntityQueryDesc GetQueryForGroup(EntityQuery group)
{
if (!queriesByGroup.ContainsKey(group))
{
var query = new EntityQueryDesc()
{
All = group.GetQueryTypes().Where(x => x.AccessModeType != ComponentType.AccessMode.Exclude).ToArray(),
Any = new ComponentType[0],
None = group.GetQueryTypes().Where(x => x.AccessModeType == ComponentType.AccessMode.Exclude).ToArray()
};
queriesByGroup.Add(group, query);
}
return queriesByGroup[group];
}
private readonly Dictionary<int, EntityQuery> componentGroupsById = new Dictionary<int, EntityQuery>();
private readonly Dictionary<int, EntityQueryDesc> queriesById = new Dictionary<int, EntityQueryDesc>();
private readonly Dictionary<int, EntityQueryGUIControl> controlsById = new Dictionary<int, EntityQueryGUIControl>();
public ComponentSystemBase SelectedSystem
{
get { return selectedSystem; }
set
{
if (selectedSystem != value)
{
selectedSystem = value;
Reload();
}
}
}
private ComponentSystemBase selectedSystem;
private readonly WorldSelectionGetter getWorldSelection;
private readonly SetEntityListSelection entityListSelectionCallback;
private static TreeViewState GetStateForSystem(ComponentSystemBase system, List<TreeViewState> states, List<string> stateNames)
{
if (system == null)
return new TreeViewState();
var currentSystemName = system.GetType().FullName;
var stateForCurrentSystem = states.Where((t, i) => stateNames[i] == currentSystemName).FirstOrDefault();
if (stateForCurrentSystem != null)
return stateForCurrentSystem;
stateForCurrentSystem = new TreeViewState();
if (system.EntityQueries != null && system.EntityQueries.Length > 0)
stateForCurrentSystem.expandedIDs = new List<int> {1};
states.Add(stateForCurrentSystem);
stateNames.Add(currentSystemName);
return stateForCurrentSystem;
}
public static EntityQueryListView CreateList(ComponentSystemBase system, List<TreeViewState> states, List<string> stateNames,
SetEntityListSelection entityQuerySelectionCallback, WorldSelectionGetter worldSelectionGetter)
{
var state = GetStateForSystem(system, states, stateNames);
return new EntityQueryListView(state, system, entityQuerySelectionCallback, worldSelectionGetter);
}
public EntityQueryListView(TreeViewState state, ComponentSystemBase system, SetEntityListSelection entityListSelectionCallback, WorldSelectionGetter worldSelectionGetter) : base(state)
{
this.getWorldSelection = worldSelectionGetter;
this.entityListSelectionCallback = entityListSelectionCallback;
selectedSystem = system;
rowHeight += 1;
showAlternatingRowBackgrounds = true;
Reload();
}
public float Height { get; private set; }
protected override float GetCustomRowHeight(int row, TreeViewItem item)
{
return controlsById.ContainsKey(item.id) ? controlsById[item.id].Height + 2 : rowHeight;
}
private static List<EntityQueryDesc> GetQueriesForSystem(ComponentSystemBase system)
{
List<EntityQueryDesc> queries;
if (queriesBySystem.TryGetValue(system, out queries))
return queries;
queries = new List<EntityQueryDesc>();
var currentType = system.GetType();
while (currentType != null)
{
foreach (var field in currentType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
if (field.FieldType == typeof(EntityQueryDesc))
queries.Add(field.GetValue(system) as EntityQueryDesc);
}
currentType = currentType.BaseType;
}
return queries;
}
protected override TreeViewItem BuildRoot()
{
componentGroupsById.Clear();
queriesById.Clear();
controlsById.Clear();
var currentId = 0;
var root = new TreeViewItem { id = currentId++, depth = -1, displayName = "Root" };
if (getWorldSelection() == null)
{
root.AddChild(new TreeViewItem { id = currentId, displayName = "No world selected"});
}
else if (SelectedSystem == null)
{
root.AddChild(new TreeViewItem { id = currentId, displayName = "Null System"});
}
else
{
var queries = GetQueriesForSystem(SelectedSystem);
var entityManager = getWorldSelection().EntityManager;
foreach (var query in queries)
{
var group = entityManager.CreateEntityQuery(query);
queriesById.Add(currentId, query);
componentGroupsById.Add(currentId, group);
var groupItem = new TreeViewItem { id = currentId++ };
root.AddChild(groupItem);
}
if (SelectedSystem.EntityQueries != null)
{
foreach (var group in SelectedSystem.EntityQueries)
{
componentGroupsById.Add(currentId, group);
var groupItem = new TreeViewItem { id = currentId++ };
root.AddChild(groupItem);
}
}
if (componentGroupsById.Count == 0)
{
root.AddChild(new TreeViewItem { id = currentId, displayName = "No Component Groups or Queries in Manager"});
}
else
{
SetupDepthsFromParentsAndChildren(root);
foreach (var idGroupPair in componentGroupsById)
{
var newControl = new EntityQueryGUIControl(idGroupPair.Value.GetQueryTypes(), idGroupPair.Value.GetReadAndWriteTypes(), true);
controlsById.Add(idGroupPair.Key, newControl);
}
}
}
return root;
}
private float width;
private const float kBorderWidth = 60f;
public void SetWidth(float newWidth)
{
newWidth -= kBorderWidth;
if (newWidth != width)
{
width = newWidth;
foreach (var control in controlsById.Values)
control.UpdateSize(width);
}
RefreshCustomRowHeights();
var height = 0f;
foreach (var child in rootItem.children)
height += GetCustomRowHeight(0, child);
Height = height;
}
public override void OnGUI(Rect rect)
{
if (getWorldSelection()?.EntityManager.IsCreated == true)
{
if (Event.current.type == EventType.Repaint)
{
SetWidth(rect.width);
}
base.OnGUI(rect);
}
}
protected void DrawCount(RowGUIArgs args)
{
EntityQuery entityQuery;
if (componentGroupsById.TryGetValue(args.item.id, out entityQuery))
{
var countString = entityQuery.CalculateLength().ToString();
DefaultGUI.LabelRightAligned(args.rowRect, countString, args.selected, args.focused);
}
}
protected override void RowGUI(RowGUIArgs args)
{
base.RowGUI(args);
if (Event.current.type != EventType.Repaint || !controlsById.ContainsKey(args.item.id))
return;
var position = args.rowRect.position;
position.x = GetContentIndent(args.item);
position.y += 1;
controlsById[args.item.id].OnGUI(position);
DrawCount(args);
}
protected override void SelectionChanged(IList<int> selectedIds)
{
if (selectedIds.Count > 0)
{
EntityQuery entityQuery;
if (componentGroupsById.TryGetValue(selectedIds[0], out entityQuery))
entityListSelectionCallback(new EntityListQuery(entityQuery));
}
else
{
entityListSelectionCallback(null);
}
}
protected override bool CanMultiSelect(TreeViewItem item)
{
return false;
}
public void SetEntityListSelection(EntityListQuery newListQuery)
{
if (newListQuery == null)
{
SetSelection(new List<int>());
return;
}
if (newListQuery.Group != null)
{
foreach (var pair in componentGroupsById)
{
if (pair.Value == newListQuery.Group)
{
SetSelection(new List<int> {pair.Key});
return;
}
}
}
else
{
foreach (var pair in queriesById)
{
if (pair.Value == newListQuery.QueryDesc)
{
SetSelection(new List<int> {pair.Key});
return;
}
}
}
SetSelection(new List<int>());
}
public void SetEntityQuerySelection(EntityQuery group)
{
SetSelection(new List<int>());
}
public void TouchSelection()
{
SetSelection(GetSelection(), TreeViewSelectionOptions.FireSelectionChanged);
}
public bool NeedsReload
{
get
{
var expectedGroupCount = SelectedSystem?.EntityQueries?.Length ?? 0;
return expectedGroupCount != componentGroupsById.Count;
}
}
public void ReloadIfNecessary()
{
if (NeedsReload)
Reload();
}
}
}