Merge branch 'dev/nkendallbar/node_docs' into 'main'
add node documentation and a repo tool to generate them See merge request lightspeedrtx/lss-ai-tools/comfyui-rtx_remix!5
This commit is contained in:
@@ -8,4 +8,34 @@
|
||||
|
||||
You should see RTX Remix nodes:
|
||||
|
||||

|
||||

|
||||
|
||||
## Nodes
|
||||
### Textures
|
||||
- **RTX Remix Get Textures**: Read the textures matching provided criteria from the currently open project
|
||||
- **RTX Remix Texture Type To USD Attribute**: Use this node to get the proper texture attribute on the same asset but for a different texture type
|
||||
- **RTX Remix Set Texture**: Set the texture path on an asset
|
||||
- **RTX Remix Texture Type**: Select from a list of supported texture types.
|
||||
- **RTX Remix Texture Types**: Select multiple texture types from a list of supported texture types.
|
||||
|
||||
### Ingestion
|
||||
- **RTX Remix Ingest Texture**: Ingest an image as a texture and save it to disk
|
||||
|
||||
### Common
|
||||
- **RTX Remix Rest API Details**: Provide the port information to connect to the RTX Remix Toolkit
|
||||
- **RTX Remix String Constant**: Declare a string constant
|
||||
- **RTX Remix Start Context**: Use this node to begin a graph, then pass context along to determine execution order.
|
||||
- **RTX Remix End Context**: Put this node at the end of your graph to evaluate prior nodes
|
||||
|
||||
### Layers
|
||||
- **RTX Remix Define Layer ID**: Helper node to define a layer path relative to project or another layer
|
||||
- **RTX Remix Create Layer**: Create or Insert a sublayer in the current stage
|
||||
- **RTX Remix Get Layers**: Query layer ids from the currently open project
|
||||
- **RTX Remix Remove Layer**: Remove a layer from the project
|
||||
- **RTX Remix Save Layer**: Save a project layer
|
||||
- **RTX Remix Mute Layer**: Mute or unmute a project layer
|
||||
- **RTX Remix Set Edit Target**: Designate the edit target on the open project to receive modifications
|
||||
- **RTX Remix Get Edit Target**: Get the edit target from the currently open project
|
||||
- **RTX Remix Layer Types**: Select multiple layer types from a list of supported layer types.
|
||||
- **RTX Remix Layer Type**: Select from a list of supported layer types.
|
||||
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RTXRemixStringConstant": "RTX Remix String Constant",
|
||||
"RTXRemixTexturesType": "RTX Remix Texture Type",
|
||||
"RTXRemixTexturesTypes": "RTX Remix Texture Types",
|
||||
"RTXRemixDefineLayerId": "RTX Remix Define Layer",
|
||||
"RTXRemixDefineLayerId": "RTX Remix Define Layer ID",
|
||||
"RTXRemixCreateLayer": "RTX Remix Create Layer",
|
||||
"RTXRemixGetLayers": "RTX Remix Get Layers",
|
||||
"RTXRemixRemoveLayer": "RTX Remix Remove Layer",
|
||||
|
||||
@@ -92,6 +92,7 @@ def add_context_input_and_output(cls):
|
||||
|
||||
|
||||
class RestAPIDetails:
|
||||
"""Provide the port information to connect to the RTX Remix Toolkit"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -124,6 +125,7 @@ class RestAPIDetails:
|
||||
|
||||
@add_context_outputs
|
||||
class StartContext:
|
||||
"""Use this node to begin a graph, then pass context along to determine execution order."""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -143,6 +145,7 @@ class StartContext:
|
||||
|
||||
|
||||
class EndContext:
|
||||
"""Put this node at the end of your graph to evaluate prior nodes"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -162,6 +165,8 @@ class EndContext:
|
||||
|
||||
|
||||
class StringConstant:
|
||||
"""Declare a string constant"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
return {
|
||||
|
||||
@@ -34,6 +34,7 @@ _file_name = pathlib.Path(__file__).stem
|
||||
|
||||
@add_context_input_and_output
|
||||
class IngestTexture:
|
||||
"""Ingest an image as a texture and save it to disk"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
|
||||
@@ -119,6 +119,7 @@ class DefineLayerId:
|
||||
|
||||
@add_context_input_and_output
|
||||
class CreateLayer:
|
||||
"""Create or Insert a sublayer in the current stage"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -198,6 +199,7 @@ class CreateLayer:
|
||||
|
||||
@add_context_input_and_output
|
||||
class LayerType:
|
||||
"""Select from a list of supported layer types."""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -223,6 +225,7 @@ class LayerType:
|
||||
|
||||
@add_context_input_and_output
|
||||
class LayerTypes:
|
||||
"""Select multiple layer types from a list of supported layer types."""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -255,6 +258,7 @@ class LayerTypes:
|
||||
|
||||
@add_context_input_and_output
|
||||
class GetLayers:
|
||||
"""Query layer ids from the currently open project"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -385,6 +389,7 @@ class _LayerOp:
|
||||
|
||||
@add_context_input_and_output
|
||||
class MuteLayer(_LayerOp):
|
||||
"""Mute or unmute a project layer"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
@@ -416,6 +421,7 @@ class MuteLayer(_LayerOp):
|
||||
|
||||
@add_context_input_and_output
|
||||
class RemoveLayer(_LayerOp):
|
||||
"""Remove a layer from the project"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -447,6 +453,7 @@ class RemoveLayer(_LayerOp):
|
||||
|
||||
@add_context_input_and_output
|
||||
class SaveLayer(_LayerOp):
|
||||
"""Save a project layer"""
|
||||
|
||||
def execute(self, layer_id: str) -> tuple[str]:
|
||||
address, port = self.context
|
||||
@@ -460,6 +467,7 @@ class SaveLayer(_LayerOp):
|
||||
|
||||
@add_context_input_and_output
|
||||
class GetEditTarget:
|
||||
"""Get the edit target from the currently open project"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -493,6 +501,7 @@ class GetEditTarget:
|
||||
|
||||
@add_context_input_and_output
|
||||
class SetEditTarget(_LayerOp):
|
||||
"""Designate the edit target on the open project to receive modifications"""
|
||||
|
||||
def execute(self, layer_id: str) -> tuple[str]:
|
||||
address, port = self.context
|
||||
|
||||
@@ -61,6 +61,7 @@ def validate_texture_types(texture_types: list[str], address: str, port: str):
|
||||
|
||||
@add_context_input_and_output
|
||||
class GetTextures:
|
||||
"""Read the textures matching provided criteria from the currently open project"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -185,6 +186,7 @@ class GetTextures:
|
||||
|
||||
@add_context_input_and_output
|
||||
class TexturesTypes:
|
||||
"""Select multiple texture types from a list of supported texture types."""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -218,6 +220,7 @@ class TexturesTypes:
|
||||
|
||||
@add_context_input_and_output
|
||||
class TexturesType:
|
||||
"""Select from a list of supported texture types."""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -242,6 +245,7 @@ class TexturesType:
|
||||
|
||||
@add_context_input_and_output
|
||||
class SetTexture:
|
||||
"""Set the texture path on an asset"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
@@ -284,6 +288,7 @@ class SetTexture:
|
||||
|
||||
@add_context_input_and_output
|
||||
class TextureTypeToUSDAttribute:
|
||||
"""Use this node to get the proper texture attribute on the same asset but for a different texture type"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # noqa N802
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
[repo_class_docs]
|
||||
# Tool name
|
||||
command = "class_docs"
|
||||
# [python module name or path]:[function name]
|
||||
entry_point = "${root}/tools/repoman/class_docs.py:setup_repo_tool"
|
||||
# Python install to use
|
||||
python_install = "${root}/../../../python_embeded/python.exe"
|
||||
# Root module to import
|
||||
module_name = "nodes"
|
||||
module = "${root}/nodes/__init__.py"
|
||||
# README to modify
|
||||
file_path = "${root}/README.md"
|
||||
# Header of section where change is required
|
||||
section_header = "## Nodes"
|
||||
@@ -0,0 +1,115 @@
|
||||
"""
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
|
||||
def update_comfyui_rtx_remix_readme(module, readme_path, section_header):
|
||||
"""Generate docs for node types"""
|
||||
section_header_style = section_header.split(' ')[0]
|
||||
header_num = section_header_style.count('#')
|
||||
|
||||
output = []
|
||||
nodes_by_module = {}
|
||||
for name, node in module.NODE_CLASS_MAPPINGS.items():
|
||||
nodes_by_module.setdefault(node.__module__, []).append((name, node))
|
||||
|
||||
for node_module, nodes in nodes_by_module.items():
|
||||
output.append(f"{'#' * (header_num + 1)} {node_module.split('.')[-1].capitalize()}\n")
|
||||
for node_info in nodes:
|
||||
name, node_class = node_info
|
||||
display_name = module.NODE_DISPLAY_NAME_MAPPINGS[name]
|
||||
if node_class.__doc__:
|
||||
# first line only
|
||||
doc = node_class.__doc__.strip("\n")
|
||||
line_break_index = doc.find("\n")
|
||||
if line_break_index > 0:
|
||||
doc = doc[:]
|
||||
output.append(f"- **{display_name}**: {doc}\n")
|
||||
else:
|
||||
output.append(f"**{display_name}**\n")
|
||||
|
||||
output.append("\n")
|
||||
|
||||
replace_section(readme_path, section_header, output)
|
||||
|
||||
|
||||
def replace_section(readme_path, section_header, contents):
|
||||
"""Replace a section under a specific markdown header with new contents"""
|
||||
section_header_style = section_header.split(' ')[0]
|
||||
with open(readme_path, 'r') as f:
|
||||
data = f.readlines()
|
||||
|
||||
new = []
|
||||
start = -1
|
||||
end = None
|
||||
found = False
|
||||
for i, line in enumerate(data):
|
||||
# search for the first occurence of the special section header string
|
||||
if not found:
|
||||
if line.strip() == section_header:
|
||||
found = True
|
||||
start = i + 1
|
||||
# search for the next header of the same magnitude
|
||||
elif re.match(f"{section_header_style}[^#].*", line):
|
||||
end = i
|
||||
break
|
||||
|
||||
final = data[:start] + contents
|
||||
if end:
|
||||
final += data[end:]
|
||||
with open(readme_path, 'w') as f:
|
||||
f.writelines(final)
|
||||
|
||||
|
||||
def update_readme(module, readme_path, section_header):
|
||||
"""Generic `class_docs` entry point. Add repo-specific implementation here!"""
|
||||
update_comfyui_rtx_remix_readme(module, readme_path, section_header)
|
||||
|
||||
|
||||
def setup_repo_tool(parser, _):
|
||||
parser.prog = "class_docs"
|
||||
parser.description = "Generate summary documentation for a bunch of classes"
|
||||
|
||||
def run_repo_tool(options, config):
|
||||
import subprocess
|
||||
settings = config["repo_class_docs"]
|
||||
|
||||
# Some projects will require using their own python in order to be able to import and inspect
|
||||
# classes so we use a subprocess
|
||||
python_code = textwrap.dedent(f"""\
|
||||
import sys
|
||||
sys.path.append("{os.path.dirname(__file__)}")
|
||||
import class_docs
|
||||
import importlib.util
|
||||
module_name = "{settings["module_name"]}"
|
||||
spec = importlib.util.spec_from_file_location(module_name, "{settings["module"]}")
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[module_name] = module
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
class_docs.update_readme(module, "{settings["file_path"]}", "{settings["section_header"]}")
|
||||
""")
|
||||
python_cmd = settings["python_install"]
|
||||
|
||||
if subprocess.call([python_cmd, "-c", python_code]) == 0:
|
||||
print("Success!")
|
||||
|
||||
return run_repo_tool
|
||||
Reference in New Issue
Block a user