Editor/ShaderGraphPlus/ShaderGraphPlus.cs
using Editor;
using ShaderGraphPlus.Nodes;
using static Editor.SceneViewportWidget;
namespace ShaderGraphPlus;
public enum BlendMode
{
[Icon( "circle" )]
Opaque,
[Icon( "radio_button_unchecked" )]
Masked,
[Icon( "blur_on" )]
Translucent,
}
public enum ShadingModel
{
[Icon( "tungsten" )]
Lit,
[Icon( "brightness_3" )]
Unlit,
//[Icon( "build" )] // TODO
//Custom,
}
public enum ShaderDomain
{
[Icon( "view_in_ar" )]
Surface,
[Icon( "brush" )]
[Hide]
BlendingSurface, // TODO : Hidden for now since its broken.
[Icon( "desktop_windows" )]
PostProcess,
}
public enum RenderFace
{
[Icon( "visibility" )]
Front,
[Icon( "visibility_off" )]
Back,
[Icon( "visibility_off" )]
Both,
}
public class PreviewSettings
{
public ViewMode ViewMode { get; set; } = ViewMode.Perspective;
public bool RenderBackfaces { get; set; } = false;
public bool EnableShadows { get; set; } = true;
public bool ShowGround { get; set; } = false;
public bool ShowSkybox { get; set; } = true;
public Color BackgroundColor { get; set; } = Color.Black;
public Color Tint { get; set; } = Color.White;
}
[AssetType( Name = ShaderGraphPlusGlobals.AssetTypeName, Extension = ShaderGraphPlusGlobals.AssetTypeExtension, Flags = AssetTypeFlags.NoEmbedding ), Icon( "account_tree" )]
public partial class ShaderGraphPlus : INodeGraph
{
[Hide]
public int Version => 9;
[Hide, JsonIgnore]
public IEnumerable<BaseNodePlus> Nodes => _nodes.Values;
[Hide, JsonIgnore]
private readonly Dictionary<string, BaseNodePlus> _nodes = new();
[Hide, JsonIgnore]
IEnumerable<IGraphNode> INodeGraph.Nodes => Nodes;
[Hide, JsonIgnore]
public IEnumerable<BlackboardParameter> Parameters => _parameters.Values;
[Hide, JsonIgnore]
public readonly Dictionary<Guid, BlackboardParameter> _parameters = new();
[Hide]
public bool IsSubgraph { get; set; }
[Hide]
public string Path { get; set; }
[Hide]
public string Model { get; set; }
/// <summary>
/// The name of the Node when used in ShaderGraph
/// </summary>
[ShowIf( nameof( IsSubgraph ), true )]
public string Title { get; set; }
public string Description { get; set; }
/// <summary>
/// The category of the Node when browsing the Node Library (optional)
/// </summary>
[ShowIf( nameof( AddToNodeLibrary ), true )]
public string Category { get; set; }
[IconName, ShowIf( nameof( IsSubgraph ), true )]
public string Icon { get; set; }
/// <summary>
/// Whether or not this Node should appear when browsing the Node Library.
/// Otherwise can only be referenced by dragging the Subgraph asset into the graph.
/// </summary>
[ShowIf( nameof( IsSubgraph ), true )]
public bool AddToNodeLibrary { get; set; }
public BlendMode BlendMode { get; set; }
[ShowIf( nameof( ShowShadingModel ), true )]
public ShadingModel ShadingModel { get; set; }
[ShowIf( nameof( ShowShadingModel ), true )]
public RenderFace RenderFace { get; set; }
[Hide] private bool ShowShadingModel => Domain != ShaderDomain.PostProcess;
public ShaderDomain Domain { get; set; }
/// <summary>
/// Custom key-value storage for this project.
/// </summary>
[Hide]
public Dictionary<string, object> Metadata { get; set; } = new Dictionary<string, object>();
[Hide]
public PreviewSettings PreviewSettings { get; set; } = new();
public ShaderGraphPlus()
{
}
public bool ContainsNode( string id )
{
if ( _nodes.ContainsKey( id ) ) return true;
return false;
}
public void AddNode( BaseNodePlus node )
{
node.Graph = this;
_nodes.Add( node.Identifier, node );
}
public void RemoveNode( BaseNodePlus node )
{
if ( node.Graph != this )
return;
//SGPLog.Info( $"Removing node with id : {node.Identifier}");
_nodes.Remove( node.Identifier );
}
public BaseNodePlus FindNode( string name )
{
_nodes.TryGetValue( name, out var node );
return node;
}
public BlackboardParameter FindParameter( Guid identifier )
{
if ( _parameters.TryGetValue( identifier, out var parameter ) )
{
return parameter;
}
throw new Exception( $"There is no parameter with the identifier : {identifier}" );
}
public BlackboardParameter FindParameter( string name )
{
var parameter = _parameters.Values.FirstOrDefault( x => x.Name == name );
if ( parameter != null )
return parameter;
throw new Exception( $"There is no parameter with the name : {name}" );
}
public T FindParameter<T>( Guid identifier ) where T : BlackboardParameter
{
if ( _parameters.TryGetValue( identifier, out var parameter ) )
{
return (T)parameter;
}
throw new Exception( $"There is no parameter with the identifier : {identifier}" );
}
public T FindParameter<T>( string name ) where T : BlackboardParameter
{
var parameter = _parameters.Values.OfType<T>().FirstOrDefault( x => x.Name == name );
if ( parameter != null )
return parameter;
throw new Exception( $"There is no parameter with the name : {name}" );
}
public bool HasParameterWithName( string name )
{
return _parameters.Any( x => x.Value.Name == name );
}
public void AddParameter( BlackboardParameter parameter )
{
parameter.Graph = this;
_parameters.Add( parameter.Identifier, parameter );
}
public void UpdateParameter( IBlackboardParameter parameter )
{
var blackboardParameter = parameter as BlackboardParameter;
if ( blackboardParameter.Graph != this )
return;
_parameters[parameter.Identifier] = blackboardParameter;
}
public void UpdateParameterValue( Guid identifier, object value )
{
if ( !_parameters.ContainsKey( identifier ) )
throw new Exception( $"There is no parameter with the identifier : {identifier}" );
_parameters[identifier].SetValue( value );
}
public void RemoveParameter( BlackboardParameter parameter )
{
if ( parameter.Graph != this )
return;
RemoveParameter( parameter.Identifier );
}
public void RemoveParameter( Guid identifier )
{
_parameters.Remove( identifier );
}
internal NamedRerouteDeclarationNode FindNamedRerouteDeclarationNode( string name )
{
var node = Nodes.OfType<NamedRerouteDeclarationNode>().Where( x => x.Name == name ).FirstOrDefault();
if ( node != null )
{
return node;
}
SGPLogger.Error( $"Could not find NamedReroute \"{name}\"" );
return null;
}
public void ClearNodes()
{
_nodes.Clear();
}
public void ClearParameters()
{
_parameters.Clear();
}
string INodeGraph.SerializeNodes( IEnumerable<IGraphNode> nodes )
{
return SerializeNodes( nodes.Cast<BaseNodePlus>() );
}
IEnumerable<IGraphNode> INodeGraph.DeserializeNodes( string serialized )
{
return DeserializeNodes( serialized );
}
void INodeGraph.AddNode( IGraphNode node )
{
AddNode( (BaseNodePlus)node );
}
void INodeGraph.RemoveNode( IGraphNode node )
{
RemoveNode( (BaseNodePlus)node );
}
public void AddParameter( IBlackboardParameter parameter )
{
AddParameter( (BlackboardParameter)parameter );
}
/// <summary>
/// Try to get a value at given key in <see cref="ShaderGraphPlus.Metadata"/>.
/// </summary>
/// <typeparam name="T">Type of the value.</typeparam>
/// <param name="keyname">The key to retrieve the value of.</param>
/// <param name="outvalue"> The value, if it was present in the metadata storage.</param>
/// <returns>Whether the value was successfully retrieved.</returns>
public bool TryGetMeta<T>( string keyname, out T outvalue )
{
outvalue = default( T );
if ( Metadata == null )
{
return false;
}
if ( !Metadata.TryGetValue( keyname, out var value ) )
{
return false;
}
if ( value is T val )
{
outvalue = val;
return true;
}
if ( value is JsonElement element )
{
try
{
T val2 = element.Deserialize<T>( new JsonSerializerOptions() );
outvalue = ((val2 != null) ? val2 : default( T ));
}
catch ( Exception )
{
return false;
}
}
return true;
}
/// <summary>
/// Store custom data at given key in <see cref="ShaderGraphPlus.Metadata"/>.
/// </summary>
/// <param name="keyname">The key for the data.</param>
/// <param name="outvalue">The data itself to store.</param>
/// <returns>Always true.</returns>
public bool SetMeta( string keyname, object outvalue )
{
if ( Metadata == null )
{
Dictionary<string, object> dictionary2 = (Metadata = new Dictionary<string, object>());
}
if ( outvalue == null )
{
return Metadata.Remove( keyname );
}
Metadata[keyname] = outvalue;
return true;
}
}
[AssetType( Name = ShaderGraphPlusGlobals.SubgraphAssetTypeName, Extension = ShaderGraphPlusGlobals.SubgraphAssetTypeExtension, Flags = AssetTypeFlags.NoEmbedding )]
public sealed partial class ShaderGraphPlusSubgraph : ShaderGraphPlus
{
}