Files
UnrealEngine/Engine/Plugins/TextureGraph/Tools/ParseTextureGraph.py
2025-05-18 13:04:45 +08:00

134 lines
5.5 KiB
Python

import os
import csv
import re
# Directory containing the C++ header files
base_directory = '../Source/TextureGraph/Public'
# Regular expression pattern to match class names
class_pattern = r'class TEXTUREGRAPH_API UTG_Expression_([A-Za-z_][A-Za-z0-9_]*)\s*(?::\s*public\s*([A-Za-z_][A-Za-z0-9_]*))?\s*\{\s*((?:.|\n)*?)\s*\};'
category_pattern = r'TG_Category::([A-Za-z_]+)'
uxname_pattern = r'GetDefaultName\(\)[^{]*\{[^\"]*\"([^"]+)\"'
tooltip_pattern = r'GetTooltipText\(\)[^{]*\{[^\"]*\"([^"]+)\"'
tooltip_pattern = r'GetTooltipText\(\)[^{]*\{[^\"]*\"([^"]+)\"'
property_pattern = r'UPROPERTY\((.*)\)\s+((.*;))'
# CSV file to write the results
csv_file = 'class_info.csv'
# Initialize a list to store the results
class_info = []
def csv_header():
return ("ID", "Class", "Member", "UI Name", "Category", "Type", "Default Value", "Tooltip", "parent", "sub_items", "file_path")
def make_class_entry(class_name, class_base, category, file_path, directory_name, uxname, tooltip, sub_items):
if (class_base == "UTG_Expression"):
class_base = ""
return (class_name, class_name, "", uxname, category, "", "", tooltip, class_base, sub_items, file_path)
def make_member_entry(prop_id, member, uxname, category, prop_type, default_value, class_name):
return (prop_id, "", member, uxname, category, prop_type, default_value, "", class_name, "", "")
# Function to search for class names in a file and add them to the list
def search_class_names(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
#components = file_path.split(os.path.sep)
#if len(components) > 2:
# directory_name = components[-2]
#else:
# directory_name = None
directory_name = os.path.basename(os.path.dirname(file_path))
class_matches = re.finditer(class_pattern, content)
#class_matches = re.finditer(classcontent_pattern, content)
for class_match in class_matches:
class_name = class_match.group(1)
class_base = class_match.group(2)
class_block = class_match.group(3)
macro_matches = re.findall(category_pattern, class_block)
category = ""
for macro_match in macro_matches:
category = macro_match
uxname_matches = re.findall(uxname_pattern, class_block)
uxname = class_name #if no ux name is found probably we use the actual class name
for uxname_match in uxname_matches:
uxname = uxname_match
tooltip_matches = re.findall(tooltip_pattern, class_block)
tooltip = ""
for tooltip_match in tooltip_matches:
tooltip = tooltip_match
class_name = 'UTG_Expression_' + class_name
sub_items = ''
class_props = []
prop_matches = re.findall(property_pattern, class_block)
for prop_match in prop_matches:
prop_attribs = prop_match[0]
member_declaration = prop_match[1]
#print(f" Prop {prop_attribs} Declaration = {member_declaration}")
member_match = re.findall(r'([A-Za-z0-9_<>]*)\s*([^=]*)(?: *= *([^;]+))?;', member_declaration)
prop_type = member_match[0][0]
member_name = member_match[0][1]
default_value = member_match[0][2]
prop_category_matches = re.findall(r'Category\s*=\s*"([^"]+)"', prop_attribs)
prop_category = ""
if (len(prop_category_matches)):
prop_category = prop_category_matches[0]
prop_display_matches = re.findall(r'DisplayName\s*=\s*"([^"]+)"', prop_attribs)
prop_display = member_name
if (len(prop_display_matches)):
prop_display = prop_display_matches[0]
prop_meta_matches = re.findall(r'meta\s*=\s*"([^"]+)"', prop_attribs)
prop_meta = ""
if (len(prop_meta_matches)):
prop_meta = prop_meta_matches[0]
prop_id = class_name + '.' + member_name
sub_items += prop_id + ' '
#print(f" Prop {prop_display} pin = {member_name} category = {prop_category} type = {prop_type} default = {default_value}")
class_props.append(make_member_entry(prop_id, member_name, prop_display, prop_category, prop_type, default_value, class_name))
#print(f"Found {class_name} base = {class_base} category = {category} folder = {directory_name} uxname = {uxname}")
class_info.append(make_class_entry(class_name, class_base, category, file_path, directory_name, uxname, tooltip, sub_items))
for sub in class_props:
class_info.append(sub)
# Traverse the directory and its subdirectories
for foldername, subfolders, filenames in os.walk(base_directory):
for filename in filenames:
if filename.endswith('.h'):
file_path = os.path.join(foldername, filename)
search_class_names(file_path)
# Write the results to a CSV file
with open(csv_file, 'w', newline='') as csvfile:
csv_writer = csv.writer(csvfile)
csv_writer.writerow(csv_header())
for entry in class_info:
csv_writer.writerow(entry)
print(f"Found {len(class_info)} entries. Data written to {csv_file}.")