gpt4 book ai didi

c# - 自定义窗口模仿 SceneView

转载 作者:行者123 更新时间:2023-12-04 15:19:51 27 4
gpt4 key购买 nike

我正在构建一个自定义窗口,我正在尝试重用 Unity 的场景 View ,以便能够直接从此特定窗口进行绘制。

我设法通过扩展 UnityEditor.SceneView 来重现正确的窗口,这就是我所拥有的:

enter image description here

代码如下:

[EditorWindowTitle(title = "Shape Editor", useTypeNameAsIconName = false)]
public class StrokeEditor : SceneView
{
[MenuItem("Recognizer/Shape Editor")]
public static void Init()
{
var w = GetWindow<StrokeEditor>();
w.in2DMode = true;

EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
}

protected override void OnGUI()
{
using (new GUILayout.HorizontalScope())
{
GUILayout.Button("Add Stroke");
GUILayout.Button("Edit Stroke");
GUILayout.Button("Delete Stroke");
}

base.OnGUI();
}
}

有了这个,我可能就差不多完成了。

这是正确的方法吗?我觉得有些不对劲,因为每当我使用 EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); 时,它还会为主场景 View 创建一个新场景。 (我希望主场景 View 保持不变)我还应该能够从场景 View 中看到这些工具,例如:

enter image description here

有没有更好的方法来实现我想要的?

编辑 1:

所有这一切的最终用途是能够像手机手势一样通过点击和拖动鼠标在窗口内绘制二维形状。从那以后,我将能够获得一些职位来提供我的一种算法......

最佳答案

您可以使用新的 GraphView .这为您提供了一些您正在“免费”寻找的东西,主要是缩放和平移 View 。由于 ShaderGraph 使用了它,因此构建节点、选择它们并四处移动它们应该会更容易,如果这是您想要的。

这是一个自定义编辑器窗口的玩具示例,它允许您编辑可编写脚本的对象中的点列表:

enter image description here


Shape.cs
- 带有点列表的简单脚本化对象。

[CreateAssetMenu(menuName = "Test/ShapeObject")]
public class Shape : ScriptableObject
{
public List<Vector2> PointList = new List<Vector2>();
}

ShapeEditorWindow.cs
- 带有工具栏和图形 View 的编辑器窗口,可打开 Shape 类型的可编写脚本的对象。

using UnityEngine;
using UnityEditor;
using UnityEditor.UIElements;

public class ShapeEditorWindow : EditorWindow
{
private ShapeEditorGraphView _shapeEditorGraphView;
private Shape _shape;

[UnityEditor.Callbacks.OnOpenAsset(1)]
private static bool Callback(int instanceID, int line)
{
var shape = EditorUtility.InstanceIDToObject(instanceID) as Shape;
if (shape != null)
{
OpenWindow(shape);
return true;
}
return false; // we did not handle the open
}

private static void OpenWindow(Shape shape)
{
var window = GetWindow<ShapeEditorWindow>();
window.titleContent = new GUIContent("Shape Editor");
window._shape = shape;
window.rootVisualElement.Clear();
window.CreateGraphView();
window.CreateToolbar();
}

private void CreateToolbar()
{
var toolbar = new Toolbar();
var clearBtn = new ToolbarButton(()=>_shape.PointList.Clear()); ;
clearBtn.text = "Clear";
var undoBtn = new ToolbarButton(() =>_shape.PointList.RemoveAt(_shape.PointList.Count-1));
undoBtn.text = "Undo";
toolbar.Add(clearBtn);
toolbar.Add(new ToolbarSpacer());
toolbar.Add(undoBtn);
rootVisualElement.Add(toolbar);
}

private void CreateGraphView()
{
_shapeEditorGraphView = new ShapeEditorGraphView(_shape);
_shapeEditorGraphView.name = "Shape Editor Graph";
rootVisualElement.Add(_shapeEditorGraphView);
}
}

ShapeEditorGraphView.cs
- 具有缩放、网格、平移(使用 ContentDragger)和形状编辑器的图形 View 。

using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;

public class ShapeEditorGraphView : GraphView
{
const float _pixelsPerUnit = 100f;
const bool _invertYPosition = true;
public ShapeEditorGraphView(Shape shape){
styleSheets.Add(Resources.Load<StyleSheet>("ShapeEditorGraph"));
this.StretchToParentSize();

SetupZoom(ContentZoomer.DefaultMinScale, ContentZoomer.DefaultMaxScale);
Add(new GridBackground());

//pan with Alt-LeftMouseButton drag/ MidleMouseButton drag
this.AddManipulator(new ContentDragger());

//other things that might interest you
//this.AddManipulator(new SelectionDragger());
//this.AddManipulator(new RectangleSelector());
//this.AddManipulator(new ClickSelector());

this.AddManipulator(new ShapeManipulator(shape));

contentViewContainer.BringToFront();
contentViewContainer.Add(new Label { name = "origin", text = "(0,0)" });

//set the origin to the center of the window
this.schedule.Execute(() =>
{
contentViewContainer.transform.position = parent.worldBound.size / 2f;
});
}

public Vector2 WorldtoScreenSpace(Vector2 pos)
{
var position = pos * _pixelsPerUnit - contentViewContainer.layout.position;
if (_invertYPosition) position.y = -position.y;
return contentViewContainer.transform.matrix.MultiplyPoint3x4(position);
}

public Vector2 ScreenToWorldSpace(Vector2 pos)
{
Vector2 position = contentViewContainer.transform.matrix.inverse.MultiplyPoint3x4(pos);
if (_invertYPosition) position.y = -position.y;
return (position + contentViewContainer.layout.position) / _pixelsPerUnit;
}
}

不幸的是,网格背景和网格线的颜色相同,所以为了看到网格线,我们必须编写一个样式表并设置 GridBackground 属性。此文件必须位于编辑器/资源中,并加载 styleSheets.Add(Resources.Load<StyleSheet>("ShapeEditorGraph"));

Editor/Resources/ShapeEditorGraph.uss

GridBackground {
--grid-background-color: rgba(32,32,32,1);
--line-color: rgba(255,255,255,.1);
--thick-line-color: rgba(255,255,255,.3);
--spacing: 100;
}

ShapeManipulator.cs
- 绘制和编辑形状。这类似于 RectangleSelector .

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UIElements;

public class ShapeManipulator : MouseManipulator
{
private Shape _shape;
private ShapeDraw _shapeDraw;

public ShapeManipulator(Shape shape)
{
activators.Add(new ManipulatorActivationFilter { button = MouseButton.LeftMouse });
_shape = shape;
_shapeDraw = new ShapeDraw { points = shape.PointList };
}
protected override void RegisterCallbacksOnTarget()
{
target.Add(_shapeDraw);
target.Add(new Label { name = "mousePosition", text = "(0,0)" });
target.RegisterCallback<MouseDownEvent>(MouseDown);
target.RegisterCallback<MouseMoveEvent>(MouseMove);
target.RegisterCallback<MouseCaptureOutEvent>(MouseOut);
target.RegisterCallback<MouseUpEvent>(MouseUp);
}

protected override void UnregisterCallbacksFromTarget()
{
target.UnregisterCallback<MouseDownEvent>(MouseDown);
target.UnregisterCallback<MouseUpEvent>(MouseUp);
target.UnregisterCallback<MouseMoveEvent>(MouseMove);
target.UnregisterCallback<MouseCaptureOutEvent>(MouseOut);
}

private void MouseOut(MouseCaptureOutEvent evt) => _shapeDraw.drawSegment = false;

private void MouseMove(MouseMoveEvent evt)
{
var t = target as ShapeEditorGraphView;
var mouseLabel = target.Q("mousePosition") as Label;
mouseLabel.transform.position = evt.localMousePosition + Vector2.up * 20;
mouseLabel.text = t.ScreenToWorldSpace(evt.localMousePosition).ToString();

//if left mouse is pressed
if ((evt.pressedButtons & 1) != 1) return;
_shapeDraw.end = t.ScreenToWorldSpace(evt.localMousePosition);
_shapeDraw.MarkDirtyRepaint();
}

private void MouseUp(MouseUpEvent evt)
{
if (!CanStopManipulation(evt)) return;
target.ReleaseMouse();
if (!_shapeDraw.drawSegment) return;

if (_shape.PointList.Count == 0) _shape.PointList.Add(_shapeDraw.start);

var t = target as ShapeEditorGraphView;
_shape.PointList.Add(t.ScreenToWorldSpace(evt.localMousePosition));
_shapeDraw.drawSegment = false;

_shapeDraw.MarkDirtyRepaint();
}

private void MouseDown(MouseDownEvent evt)
{
if (!CanStartManipulation(evt)) return;
target.CaptureMouse();

_shapeDraw.drawSegment = true;
var t = target as ShapeEditorGraphView;

if (_shape.PointList.Count != 0) _shapeDraw.start = _shape.PointList.Last();
else _shapeDraw.start = t.ScreenToWorldSpace(evt.localMousePosition);

_shapeDraw.end = t.ScreenToWorldSpace(evt.localMousePosition);
_shapeDraw.MarkDirtyRepaint();
}
private class ShapeDraw : ImmediateModeElement
{
public List<Vector2> points { get; set; } = new List<Vector2>();
public Vector2 start { get; set; }
public Vector2 end { get; set; }
public bool drawSegment { get; set; }
protected override void ImmediateRepaint()
{
var lineColor = new Color(1.0f, 0.6f, 0.0f, 1.0f);
var t = parent as ShapeEditorGraphView;
//Draw shape
for (int i = 0; i < points.Count - 1; i++)
{
var p1 = t.WorldtoScreenSpace(points[i]);
var p2 = t.WorldtoScreenSpace(points[i + 1]);
GL.Begin(GL.LINES);
GL.Color(lineColor);
GL.Vertex(p1);
GL.Vertex(p2);
GL.End();
}

if (!drawSegment) return;

//Draw current segment
GL.Begin(GL.LINES);
GL.Color(lineColor);
GL.Vertex(t.WorldtoScreenSpace(start));
GL.Vertex(t.WorldtoScreenSpace(end));
GL.End();
}
}
}

这只是示例代码。目标是让一些东西工作并绘制到屏幕上。

关于c# - 自定义窗口模仿 SceneView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63557744/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com