Rename Custom Nodes (local package)

Hi All,

We built a local package with around 400 custom nodes.
Now i would like to rename these nodes (text-editor) to the latest naming standards.
Preferably I would not rebuild the nodes, and leave the existing graphs intact
I have tried this in the past and it messed up the layout of my nodes big time.

Does anyone have a reliable method to do this?

Layout likely will change as your node names change length. I recommend ā€˜scaling upā€™ the graph on open to prevent much of this type of issue using either the bulk graph resizing tool Iā€™ve posted elsewhere, the graph updater built into newer builds of Dynamo, or the ā€œgraph resizererā€ which is built into Monocle.

Once you scale up slightly you can usually quickly correct any issues which come along the way, or just leave the added white space between nodes. :slight_smile:

Thanks for your response @jacob.small, but what i meant is that the layout of the custom nodes itself is messed up. So all (nested) nodes inside are lying on top of each other.

Yeah - same method. That said editing the raw text is possibly messing with the json structure of the .dyf in a way which creates a corrupt layout, which is causing things to reset. Make sure you arenā€™t changing any GUIDs, other than perhaps the one for the full definition.

I think Iā€™ve found a working method.
NB! Always make backups and do the following only at your own risk.

  1. Open the custom node in a text editor.
  2. Change the ā€œNameā€ of the node.
  3. Change the ā€œCategoryā€ of the node if necessary.

2023-12-12_p01

2023-12-12_p02

  1. Save and close the text editor.
  2. Change the name of the *.dyf file itself.

2023-12-12_p03

  1. Start Dynamo.
  2. Open a graph in which an (old) instance of the newly modified node already exists.
  3. Select everything in the opened graph and click ā€œDeleteā€.
  4. Click ā€œCtrlā€ + ā€œzā€, delete will be undone, and a new/updated instance of the custom node will be placed.
  5. The yellow ā€œRenamedā€ label will appear on the affected node.

2023-12-12_p04

  1. Right-click on the custom node in question, and select ā€œEdit Custom Node Propertiesā€¦ā€.
  2. Click ā€œOKā€ in the new window that opens.
  3. The name of the node in question is now corrected and the yellow label has disappeared.
  4. If you open the custom node now, the layout should be unchanged.
  5. If you skipped steps 8 and 9, there is a good chance that all nested nodes are on top of each other in the top left corner.

Itā€™s a cumbersome method, but recreating 400+ nodes and then updating all the graphs isnā€™t ideal either. I will continue testing with this method, but if anyone has a simpler method, I would like to hear about it.

It your mean is just rename node or any rule for category include ?

This is my step will posible to do that just for rename :

  • Create a schema json python class to read data dyf
  • Export Name,Category to excel
  • Rename with your rule in excel
  • Load new rule excel (400Node ++) and replace Name.Category
  • Save with json
  • Rename format extension to .dyf
1 Like

Hi @chuongmep,

Your method looks promising, but I donā€™t have the knowledge to implement it this way :slightly_frowning_face:.

You may also have better results (and less steps) using a newer Dynamo build for the edits. 2022 is like 8 or 10 versions behind at this point if I recall correctly.

1 Like

I guess this is all what you need follow step by step with iā€™m guidle :

  1. Create a schema json python class to read data dyf
from dataclasses import dataclass
from typing import List, Optional

@dataclass
class Parameter:
    Name: str
    TypeName: str
    TypeRank: int
    DefaultValue: Optional[object]
    Description: str

@dataclass
class Camera:
    Name: str
    EyeX: float
    EyeY: float
    EyeZ: float
    LookX: float
    LookY: float
    LookZ: float
    UpX: float
    UpY: float
    UpZ: float

@dataclass
class Connector:
    Start: str
    End: str
    Id: str
    IsHidden: str

@dataclass
class Dynamo:
    ScaleFactor: float
    HasRunWithoutCrash: bool
    IsVisibleInDynamoLibrary: bool
    Version: str
    RunType: str
    RunPeriod: str

@dataclass
class ElementResolver:
    ResolutionMap: Optional[object]

@dataclass
class Input:
    Id: str
    Name: str
    Description: str
    UsingDefaultValue: bool
    Level: int
    UseLevels: bool
    KeepListStructure: bool

@dataclass
class Node:
    ConcreteType: str
    NodeType: str
    Parameter: Parameter
    Id: str
    Inputs: List[Input]
    Outputs: List['Output']
    Replication: str
    Description: str
    ElementResolver: Optional[object]
    Symbol: str

@dataclass
class NodeView:
    Name: str
    ShowGeometry: bool
    Id: str
    IsSetAsInput: bool
    IsSetAsOutput: bool
    Excluded: bool
    X: float
    Y: float

@dataclass
class Output:
    Id: str
    Name: str
    Description: str
    UsingDefaultValue: bool
    Level: int
    UseLevels: bool
    KeepListStructure: bool

@dataclass
class ResolutionMap:
    pass

@dataclass
class Root:
    Uuid: str
    IsCustomNode: bool
    Category: str
    Description: str
    Name: str
    ElementResolver: ElementResolver
    Inputs: List[object]
    Outputs: List[object]
    Nodes: List[Node]
    Connectors: List[Connector]
    Dependencies: List[object]
    NodeLibraryDependencies: List[object]
    Author: str
    Bindings: List[object]
    View: 'View'

@dataclass
class View:
    Dynamo: Dynamo
    Camera: Camera
    ConnectorPins: List[object]
    NodeViews: List[NodeView]
    Annotations: List[object]
    X: float
    Y: float
    Zoom: float

  1. Export Name,Category to excel
import json
def read_dyf_file(file_path):
    with open(file_path, 'r') as file:
        dyf_data = json.load(file)
    return dyf_data

dir = r'C:\Users\chuongho\AppData\Roaming\Dynamo\Dynamo Core\2.17\definitions'
# read all dyf files
import os
dyf_files = [os.path.join(dir, f) for f in os.listdir(dir) if f.endswith('.dyf')]
print("Totle number of dyf files: ", len(dyf_files))
# read dyf data
dyf_data = [read_dyf_file(f) for f in dyf_files]

Build Dataframe export Excel :

# create data to save excel
import pandas as pd
## save to excel with columns: Name,Category, Description
df = pd.DataFrame(columns=['Name', 'Category', 'Description'])
for dyf in dyf_data:
    uuid = dyf['Uuid']
    name = dyf['Name']
    new_name = dyf['Name']
    category = dyf['Category']
    description = dyf['Description']
    df = pd.concat([df, pd.DataFrame([[uuid,name,new_name, category, description]], columns=['Uuid','Name','NewName', 'Category', 'Description'])])
df = pd.DataFrame(df)
# reorder columns : uuid, name,new_name, category, description
df = df[['Uuid','Name','NewName', 'Category', 'Description']]
df

Export Excel :slight_smile:

# save to excel
df.to_excel('rename-name.xlsx', index=False)

  1. Rename with your rule in excel
  • Load new rule excel (400Node ++) and replace Name.Category
# load excel to rename name
import pandas as pd
df = pd.read_excel('rename-name.xlsx')
df
  1. Rename mapping with uuid and save
import json
import os
import pandas as pd

def read_dyf_file(file_path):
    with open(file_path, 'r') as file:
        dyf_data = json.load(file)
    return dyf_data

# Directory containing dyf files
dir = r'C:\Users\chuongho\AppData\Roaming\Dynamo\Dynamo Core\2.17\definitions'

# Read all dyf files
dyf_files = [os.path.join(dir, f) for f in os.listdir(dir) if f.endswith('.dyf')]
print("Total number of dyf files: ", len(dyf_files))

# Read dyf data
dyf_data = [read_dyf_file(f) for f in dyf_files]

# Load Excel file
excel_file_name = 'rename-name.xlsx'
df = pd.read_excel(excel_file_name)

# Create a mapping of uuid to new names
uuid_mapping = dict(zip(df['Uuid'], df['NewName']))
# Update 'Uuid' field inside each dyf file
for dyf in dyf_data:
    uuid = dyf.get('Uuid', '')
    new_name = uuid_mapping.get(uuid, '')
    name = dyf['Name']
    print(name)
    if new_name:
        print(f"Update uuid for {dyf['Name']} to {new_name}")
        dyf['Name'] = new_name
    else:
        print(f"Uuid not found for {dyf['Name']}")

    #Optionally, you can save the modified dyf_data back to the original .dyf file
    #with open(os.path.join(dir, f"{new_name}.dyf"), 'w') as file:
        #json.dump(dyf, file, indent=4)

# Print or further process the updated dyf_data
print(dyf_data)

Warning : I donā€™t have time to recheck, you need recheck code by your self and donā€™t test with real folder contains dyf package.

2 Likes