Skip to content

Commit d33df65

Browse files
author
David Khristepher Santos
committed
Move ComfyUI parser to separate project
Add parser for AnimatedWebP "Make" Workflow Added tools to extract node properties for use in said workflow
1 parent da70012 commit d33df65

30 files changed

Lines changed: 701 additions & 223 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@ packages
3434
build
3535
build-self-contained
3636
.vscode
37+
/Diffusion.Toolkit/Tools/*.json
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using System.Text.Json;
2+
3+
namespace Diffusion.ComfyUI;
4+
5+
public class AnimatedWebPWorkflowParser : IWorkflowParser
6+
{
7+
private readonly Dictionary<string, List<string>> _propertiesLookup;
8+
9+
public AnimatedWebPWorkflowParser(INodePropertyCache nodePropertyCache)
10+
{
11+
_propertiesLookup = nodePropertyCache.GetPropertiesLookup();
12+
}
13+
14+
public IReadOnlyCollection<Node> Parse(string workflowId, JsonElement rootElement)
15+
{
16+
var nodes = rootElement.GetProperty("nodes").EnumerateArray();
17+
18+
var result = new List<Node>();
19+
20+
foreach (var node in nodes)
21+
{
22+
var id = node.GetProperty("id").GetInt32().ToString();
23+
var name = node.GetProperty("type").GetString();
24+
25+
if (_propertiesLookup.TryGetValue(name, out var properties))
26+
{
27+
var values = node.GetProperty("widgets_values").EnumerateArray()
28+
.Select(d =>
29+
{
30+
switch (d.ValueKind)
31+
{
32+
case JsonValueKind.String:
33+
return (object)d.GetString();
34+
case JsonValueKind.Number:
35+
try
36+
{
37+
return (object)d.GetInt32();
38+
}
39+
catch (Exception e)
40+
{
41+
return (object)d.GetDouble();
42+
}
43+
default:
44+
return (object)null;
45+
}
46+
});
47+
48+
49+
var inputs = properties.Zip(values)
50+
.Where(d => d.Second != null)
51+
.Select(d => new Input(workflowId, $"[{id}].inputs[\"{d.First}\"]", d.First, d.Second))
52+
.ToList();
53+
54+
var outputNode = new Node()
55+
{
56+
Id = id,
57+
Name = name,
58+
Inputs = inputs,
59+
};
60+
61+
result.Add(outputNode);
62+
63+
}
64+
65+
}
66+
return result;
67+
}
68+
}

Diffusion.ComfyUI/ComfyUIParser.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System.Text.Json;
2+
using System.Text.Json.Serialization;
3+
4+
namespace Diffusion.ComfyUI;
5+
6+
public interface INodePropertyCache
7+
{
8+
Dictionary<string, List<string>> GetPropertiesLookup();
9+
}
10+
11+
public class ComfyUIParser
12+
{
13+
private INodePropertyCache _cache;
14+
15+
public ComfyUIParser(INodePropertyCache cache)
16+
{
17+
_cache = cache;
18+
}
19+
20+
public IReadOnlyCollection<Node>? Parse(string workflowId, string? workflow)
21+
{
22+
if (workflow == null) return null;
23+
var root = JsonDocument.Parse(workflow);
24+
25+
JsonElement rootElement = root.RootElement;
26+
27+
if (rootElement.TryGetProperty("prompt", out var tempElement))
28+
{
29+
rootElement = tempElement;
30+
}
31+
32+
if (rootElement.ValueKind == JsonValueKind.String)
33+
{
34+
var tempRoot = JsonDocument.Parse(rootElement.GetString());
35+
rootElement = tempRoot.RootElement;
36+
}
37+
38+
IWorkflowParser parser;
39+
40+
if (rootElement.TryGetProperty("nodes", out var nodesProperty) && nodesProperty.ValueKind == JsonValueKind.Array)
41+
{
42+
parser = new AnimatedWebPWorkflowParser(_cache);
43+
}
44+
else
45+
{
46+
parser = new SimpleWorkflowParser();
47+
}
48+
49+
50+
return parser.Parse(workflowId, rootElement);
51+
}
52+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<None Update="comfy-nodes.json">
11+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
12+
</None>
13+
</ItemGroup>
14+
15+
</Project>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using System.Text.Json;
2+
3+
namespace Diffusion.ComfyUI;
4+
5+
public interface IWorkflowParser
6+
{
7+
public IReadOnlyCollection<Node> Parse(string workflowId, JsonElement rootElement);
8+
}

Diffusion.ComfyUI/Input.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace Diffusion.ComfyUI;
2+
3+
public class Input
4+
{
5+
public string WorkflowId { get; set; }
6+
public string Path { get; set; }
7+
public string Name { get; set; }
8+
public string Label { get; set; }
9+
public object Value { get; set; }
10+
11+
public Input(string workflowId, string path, string name, object value)
12+
{
13+
WorkflowId = workflowId;
14+
Path = path;
15+
Name = name;
16+
Label = name.Replace("_", "__");
17+
Value = value;
18+
}
19+
}

Diffusion.ComfyUI/Node.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
namespace Diffusion.ComfyUI
2+
{
3+
public class Node
4+
{
5+
private string _name;
6+
public int RefId { get; set; }
7+
public string Id { get; set; }
8+
9+
public string Name
10+
{
11+
get => _name;
12+
set => _name = value;
13+
}
14+
15+
public string Label => _name.Replace("_", "__");
16+
17+
public List<Input> Inputs { get; set; }
18+
public object ImageRef { get; set; }
19+
20+
public override int GetHashCode()
21+
{
22+
var hash = Id.GetHashCode();
23+
24+
if (Name != null)
25+
{
26+
hash = (hash * 397) ^ Name.GetHashCode();
27+
}
28+
29+
if (Inputs != null)
30+
{
31+
foreach (var input in Inputs)
32+
{
33+
hash = (hash * 397) ^ input.Name.GetHashCode();
34+
}
35+
}
36+
37+
return hash;
38+
}
39+
}
40+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Text.Json;
2+
3+
namespace Diffusion.ComfyUI;
4+
5+
public class NodePropertyCache : INodePropertyCache
6+
{
7+
private Dictionary<string, List<string>> _cache;
8+
9+
public void Load(string path)
10+
{
11+
var json = File.ReadAllText(path);
12+
_cache = JsonSerializer.Deserialize<Dictionary<string, List<string>>>(json);
13+
}
14+
15+
public Dictionary<string, List<string>> GetPropertiesLookup()
16+
{
17+
return _cache;
18+
}
19+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using System.Text.Json;
2+
3+
namespace Diffusion.ComfyUI;
4+
5+
public class SimpleWorkflowParser : IWorkflowParser
6+
{
7+
public IReadOnlyCollection<Node> Parse(string workflowId, JsonElement rootElement)
8+
{
9+
var rootProperties = rootElement
10+
.EnumerateObject().ToDictionary(n => n.Name, n => n.Value);
11+
12+
13+
var nodes = new List<Node>();
14+
15+
foreach (var element in rootProperties)
16+
{
17+
var node = new Node();
18+
node.Id = element.Key;
19+
20+
foreach (var props in element.Value.EnumerateObject())
21+
{
22+
if (props.Name == "inputs")
23+
{
24+
node.Inputs = new List<Input>();
25+
26+
foreach (var prop2 in props.Value.EnumerateObject())
27+
{
28+
var name = prop2.Name;
29+
30+
string path = $"[{node.Id}].inputs[\"{prop2.Name}\"]";
31+
32+
switch (prop2.Value.ValueKind)
33+
{
34+
case JsonValueKind.Undefined:
35+
break;
36+
case JsonValueKind.Object:
37+
break;
38+
case JsonValueKind.Array:
39+
break;
40+
case JsonValueKind.String:
41+
node.Inputs.Add(new Input(workflowId, path, name, prop2.Value.GetString()));
42+
break;
43+
case JsonValueKind.Number:
44+
node.Inputs.Add(new Input(workflowId, path, name, prop2.Value.GetDouble()));
45+
break;
46+
case JsonValueKind.True:
47+
node.Inputs.Add(new Input(workflowId, path, name, prop2.Value.GetBoolean()));
48+
break;
49+
case JsonValueKind.False:
50+
node.Inputs.Add(new Input(workflowId, path, name, prop2.Value.GetBoolean()));
51+
break;
52+
case JsonValueKind.Null:
53+
break;
54+
default:
55+
throw new ArgumentOutOfRangeException();
56+
}
57+
}
58+
}
59+
else if (props.Name == "class_type")
60+
{
61+
node.Name = props.Value.GetString();
62+
}
63+
}
64+
nodes.Add(node);
65+
}
66+
67+
return nodes;
68+
}
69+
}

0 commit comments

Comments
 (0)