浏览代码

#29 Window now tells `MaterialGraphPresenter` to update previews, rather than using schedulers per node

/main
Peter Bay Bastian 7 年前
当前提交
4b24135e
共有 5 个文件被更改,包括 79 次插入105 次删除
  1. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/MaterialGraphEditWindow.cs
  2. 53
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/MaterialGraphPresenter.cs
  3. 9
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/MaterialNodePresenter.cs
  4. 66
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/NodePreviewPresenter.cs
  5. 53
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/MaterialNodeView.cs

3
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/MaterialGraphEditWindow.cs


bool shouldRepaint
{
get { return allowAlwaysRepaint && inMemoryAsset != null && inMemoryAsset.shouldRepaint; }
get { return m_GraphEditorView != null && m_GraphEditorView.presenter.hasTimeDependentNodes; }
}
[SerializeField]

void Update()
{
m_GraphEditorView.presenter.UpdateTimeDependentNodes();
if (shouldRepaint)
Repaint();
}

53
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/MaterialGraphPresenter.cs


[Serializable]
public class MaterialGraphPresenter : GraphViewPresenter
{
HashSet<INode> m_TimeDependentNodes = new HashSet<INode>();
Dictionary<Guid, MaterialNodePresenter> m_TimeDependentPresenters = new Dictionary<Guid, MaterialNodePresenter>();
public bool hasTimeDependentNodes { get { return m_TimeDependentPresenters.Any(); }}
protected GraphTypeMapper typeMapper { get; set; }

// Calculate which nodes require updates each frame (i.e. are time-dependent).
// Let the node set contain all the nodes that are directly time-dependent.
m_TimeDependentNodes.Clear();
foreach (var node in graphAsset.graph.GetNodes<INode>().Where(x => x is IRequiresTime))
m_TimeDependentNodes.Add(node);
m_TimeDependentPresenters.Clear();
foreach (var presenter in m_Elements.OfType<MaterialNodePresenter>().Where(x => x.node is IRequiresTime))
m_TimeDependentPresenters.Add(presenter.node.guid, presenter);
var wavefront = new Stack<INode>(m_TimeDependentNodes);
var wavefront = new Stack<MaterialNodePresenter>(m_TimeDependentPresenters.Values);
var node = wavefront.Pop();
var presenter = wavefront.Pop();
foreach (var slot in node.GetOutputSlots<ISlot>())
foreach (var slot in presenter.node.GetOutputSlots<ISlot>())
foreach (var edge in node.owner.GetEdges(slot.slotReference))
foreach (var edge in graphAsset.graph.GetEdges(slot.slotReference))
var inputNode = node.owner.GetNodeFromGuid(edge.inputSlot.nodeGuid);
if (!m_TimeDependentNodes.Contains(inputNode))
// We look at each node we feed into.
var inputNodeGuid = edge.inputSlot.nodeGuid;
// If the input node is already in the set of time-dependent nodes, we don't need to process it.
if (m_TimeDependentPresenters.ContainsKey(inputNodeGuid))
continue;
// Find the matching presenter.
var inputPresenter = m_Elements.OfType<MaterialNodePresenter>().FirstOrDefault(p => p.node.guid == inputNodeGuid);
if (inputPresenter == null)
// If the node is not in the set of time-dependent nodes, add it.
m_TimeDependentNodes.Add(inputNode);
// Also add it to the wavefront, such that we can process the nodes that it feeds into.
wavefront.Push(inputNode);
Debug.LogErrorFormat("A presenter could not be found for the node with guid `{0}`", inputNodeGuid);
continue;
// Add the node to the set of time-dependent nodes, and to the wavefront such that we can process the nodes that it feeds into.
m_TimeDependentPresenters.Add(inputPresenter.node.guid, inputPresenter);
wavefront.Push(inputPresenter);
// Update presenters `requiresTime` based on the hash set values.
foreach (var nodePresenter in m_Elements.OfType<MaterialNodePresenter>())
nodePresenter.requiresTime = m_TimeDependentNodes.Contains(nodePresenter.node);
}
public virtual void Initialize(IGraphAsset graphAsset, MaterialGraphEditWindow container)

public override void RemoveElement(GraphElementPresenter element)
{
throw new ArgumentException("Not supported on Serializable Graph, data comes from data store");
}
public void UpdateTimeDependentNodes()
{
foreach (var nodePresenter in m_TimeDependentPresenters.Values)
{
nodePresenter.OnModified(ModificationScope.Node);
}
}
}
}

9
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/MaterialNodePresenter.cs


[SerializeField]
int m_Version;
[SerializeField]
bool m_RequiresTime;
public bool requiresTime
{
get { return m_RequiresTime; }
set { m_RequiresTime = value; }
}
public override bool expanded
{
get { return base.expanded; }

66
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/NodePreviewPresenter.cs


protected NodePreviewPresenter()
{}
private MaterialGraphPreviewGenerator m_PreviewGenerator;
MaterialGraphPreviewGenerator m_PreviewGenerator;
private int m_LastShaderVersion = -1;
int m_LastShaderVersion = -1;
private Material m_PreviewMaterial;
Material m_PreviewMaterial;
private Shader m_PreviewShader;
Shader m_PreviewShader;
private AbstractMaterialNode m_Node;
AbstractMaterialNode m_Node;
private ModificationScope m_modificationScope;
ModificationScope m_ModificationScope;
// Null means no modification is currently in progress.
public ModificationScope modificationScope

return m_modificationScope;
return m_ModificationScope;
if (m_modificationScope >= value)
if (m_ModificationScope >= value)
m_modificationScope = value;
m_ModificationScope = value;
private Texture m_texture;
Texture m_Texture;
private PreviewMode m_GeneratedShaderMode = PreviewMode.Preview2D;
public Texture texture
{
get { return m_Texture; }
}
PreviewMode m_GeneratedShaderMode = PreviewMode.Preview2D;
public Material previewMaterial
{

}
}
private MaterialGraphPreviewGenerator previewGenerator
MaterialGraphPreviewGenerator previewGenerator
{
get
{

public void Initialize(AbstractMaterialNode node)
{
m_Node = node;
m_modificationScope = ModificationScope.Graph;
m_ModificationScope = ModificationScope.Graph;
public Texture Render(Vector2 dimension)
public void UpdateTexture()
return null;
{
m_Texture = null;
return;
}
return null;
{
m_Texture = null;
return;
}
var scope = m_modificationScope;
m_modificationScope = ModificationScope.Nothing;
var scope = m_ModificationScope;
m_ModificationScope = ModificationScope.Nothing;
bool status = false;
status = UpdatePreviewShader();
var status = UpdatePreviewShader();
m_texture = RenderPreview(dimension);
m_Texture = RenderPreview(new Vector2(256, 256));
else if (m_texture == null)
else if (texture == null)
m_texture = RenderPreview(dimension);
m_Texture = RenderPreview(new Vector2(256, 256));
return m_texture;
protected virtual string GetPreviewShaderString()
{

return ShaderGenerator.GeneratePreviewShader(m_Node, out m_GeneratedShaderMode);
}
private bool UpdatePreviewShader()
bool UpdatePreviewShader()
{
if (m_Node == null || m_Node.hasError)
return false;

/// RenderPreview gets called in OnPreviewGUI. Nodes can override
/// RenderPreview and do their own rendering to the render texture
/// </summary>
private Texture RenderPreview(Vector2 targetSize)
Texture RenderPreview(Vector2 targetSize)
{
previewMaterial.shader = m_PreviewShader;
UpdateMaterialProperties(m_Node, previewMaterial);

private static void SetPreviewMaterialProperty(PreviewProperty previewProperty, Material mat)
static void SetPreviewMaterialProperty(PreviewProperty previewProperty, Material mat)
{
switch (previewProperty.m_PropType)
{

53
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/MaterialNodeView.cs


VisualElement m_ControlsContainer;
List<GraphControlPresenter> m_CurrentControls;
Image m_PreviewImage;
NodePreviewPresenter m_CurrentPreview;
bool m_IsScheduled;
public MaterialNodeView()

AddToClassList("MaterialNode");
onEnter += SchedulePolling;
onLeave += UnschedulePolling;
}
void CreateContainers()

leftContainer.Add(m_PreviewImage);
}
void SchedulePolling()
{
if (panel != null)
{
if (!m_IsScheduled)
{
this.Schedule(InvalidateUIIfNeedsTime).StartingIn(0).Every(16);
m_IsScheduled = true;
}
}
else
{
m_IsScheduled = false;
}
}
void UnschedulePolling()
{
if (m_IsScheduled && panel != null)
{
this.Unschedule(InvalidateUIIfNeedsTime);
}
m_IsScheduled = false;
}
void InvalidateUIIfNeedsTime(TimerState timerState)
{
var nodePresenter = GetPresenter<MaterialNodePresenter>();
if (nodePresenter.requiresTime)
{
nodePresenter.OnModified(ModificationScope.Node);
UpdatePreviewTexture(m_CurrentPreview);
}
}
var texture = preview != null ? preview.Render(new Vector2(256, 256)) : null;
if (texture == null)
if (preview != null)
preview.UpdateTexture();
if (preview == null || preview.texture == null)
{
m_PreviewImage.AddToClassList("inactive");
m_PreviewImage.image = Texture2D.whiteTexture;

m_PreviewImage.RemoveFromClassList("inactive");
m_PreviewImage.image = texture;
m_PreviewImage.image = preview.texture;
}
Dirty(ChangeType.Repaint);
}

m_ControlsContainer.Clear();
m_CurrentControls.Clear();
m_PreviewImage.AddToClassList("inactive");
m_CurrentPreview = null;
UpdatePreviewTexture(m_CurrentPreview);
UpdatePreviewTexture(null);
m_CurrentPreview = node.preview;
UpdatePreviewTexture(m_CurrentPreview);
UpdatePreviewTexture(node.preview);
if (node.expanded)
m_PreviewImage.RemoveFromClassList("hidden");

正在加载...
取消
保存