Skip to content

Commit

Permalink
some cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
BradyAJohnston committed May 24, 2024
1 parent 01f3d2f commit a4ca10e
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 128 deletions.
60 changes: 32 additions & 28 deletions docs/build_node_docs.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import os
import pathlib
import sys

import bpy
import griffe
from quartodoc import MdRenderer

import molecularnodes as mn
import griffe
import os
import sys
import pathlib

sys.path.insert(0, os.path.abspath('..'))
sys.path.insert(0, os.path.abspath(".."))

folder = pathlib.Path(__file__).resolve().parent
file_output_qmd = os.path.join(folder, "nodes/index.qmd")
Expand All @@ -28,12 +30,12 @@ def get_values(sockets):
default = None
if dtype == "Float":
default = round(socket.default_value, 2)
elif dtype in ['Geometry', 'Collection', 'Object']:
elif dtype in ["Geometry", "Collection", "Object"]:
default = None
elif dtype == "Vector":
default = [round(x, 2) for x in socket.default_value]
elif dtype == "Material":
default = '`MN Default`'
default = "`MN Default`"
elif dtype == "Color":
default = col_to_rgb_str(socket.default_value)
else:
Expand All @@ -44,62 +46,64 @@ def get_values(sockets):
name=socket.name,
annotation=dtype,
value=default,
description=socket.description
description=socket.description,
)
)
return param_list


cat = ''
cat = ""
text = griffe.docstrings.dataclasses.DocstringSectionText
params = griffe.docstrings.dataclasses.DocstringSectionParameters

categories = {}
for category, node_list in mn.ui.node_info.menu_items.items():
objects = []
objects.append(
[text(title=None, value=f"## {mn.blender.nodes.format_node_name(category)}")])
[text(title=None, value=f"## {mn.blender.nodes.format_node_name(category)}")]
)

for item in node_list:
if isinstance(item, str):
continue

iter_list = [item]

if item['label'] == "custom":
iter_list = item['values']
if item["label"] == "custom":
iter_list = item["values"]

for entry in iter_list:
name = entry['name']
name = entry["name"]
if name.startswith("mn."):
name = entry['backup']
name = entry["backup"]

entry_list = []
desc = entry.get('description')
urls = entry.get('video_url')
desc = entry.get("description")
urls = entry.get("video_url")

inputs = params(get_values(
mn.blender.nodes.inputs(bpy.data.node_groups[name])))
outputs = params(get_values(
mn.blender.nodes.outputs(bpy.data.node_groups[name])))
inputs = params(
get_values(mn.blender.nodes.inputs(bpy.data.node_groups[name]))
)
outputs = params(
get_values(mn.blender.nodes.outputs(bpy.data.node_groups[name]))
)

title = mn.blender.nodes.format_node_name(entry.get('label'))
title = mn.blender.nodes.format_node_name(entry.get("label"))
entry_list.append(text(title=None, value=f"### {title}"))
if desc:
entry_list.append(text(title=None, value=desc))
if urls:
if not isinstance(urls, list):
urls = [urls]
[
entry_list.append(
text(title=None, value=f"![]({url}.mp4)")
) for url in urls
entry_list.append(text(title=None, value=f"![]({url}.mp4)"))
for url in urls
]

if len(inputs.as_dict()['value']) > 0:
if len(inputs.as_dict()["value"]) > 0:
entry_list.append(text(value="\n#### Inputs"))
entry_list.append(inputs)
if len(outputs.as_dict()['value']) > 0:
if len(outputs.as_dict()["value"]) > 0:
entry_list.append(text(value="\n#### Outputs"))
entry_list.append(outputs)

Expand All @@ -116,10 +120,10 @@ def get_values(sockets):
"""

for category, object in categories.items():
with open(os.path.join(folder, f'nodes/{category}.qmd'), 'w') as file:
with open(os.path.join(folder, f"nodes/{category}.qmd"), "w") as file:
file.write(header)
for doc in object:
section = ''
section = ""
for sec in doc:
file.write(ren.render(sec))
file.write("\n\n")
Expand Down
8 changes: 2 additions & 6 deletions docs/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,12 @@


def main():

python = os.path.realpath(sys.executable)

commands = [
f'{python} -m pip install .',
f'{python} -m pip install quartodoc'
]
commands = [f"{python} -m pip install .", f"{python} -m pip install quartodoc"]

for command in commands:
subprocess.run(command.split(' '))
subprocess.run(command.split(" "))


if __name__ == "__main__":
Expand Down
5 changes: 2 additions & 3 deletions molecularnodes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"warning": "",
"doc_url": "https://bradyajohnston.github.io/MolecularNodes/",
"tracker_url": "https://github.com/BradyAJohnston/MolecularNodes/issues",
"category": "Import"
"category": "Import",
}

auto_load.init()
Expand All @@ -40,8 +40,7 @@
def register():
auto_load.register()
bpy.types.NODE_MT_add.append(MN_add_node_menu)
bpy.types.Object.mn = bpy.props.PointerProperty(
type=MolecularNodesObjectProperties)
bpy.types.Object.mn = bpy.props.PointerProperty(type=MolecularNodesObjectProperties)
for func in universe_funcs:
try:
bpy.app.handlers.load_post.append(func)
Expand Down
54 changes: 42 additions & 12 deletions molecularnodes/auto_load.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import os
import bpy
import sys
import typing
import inspect
import pkgutil
Expand All @@ -18,13 +16,15 @@
modules = None
ordered_classes = None


def init():
global modules
global ordered_classes

modules = get_all_submodules(Path(__file__).parent)
ordered_classes = get_ordered_classes_to_register(modules)


def register():
for cls in ordered_classes:
bpy.utils.register_class(cls)
Expand All @@ -35,6 +35,7 @@ def register():
if hasattr(module, "register"):
module.register()


def unregister():
for cls in reversed(ordered_classes):
bpy.utils.unregister_class(cls)
Expand All @@ -49,13 +50,16 @@ def unregister():
# Import modules
#################################################


def get_all_submodules(directory):
return list(iter_submodules(directory, directory.name))


def iter_submodules(path, package_name):
for name in sorted(iter_submodule_names(path)):
yield importlib.import_module("." + name, package_name)


def iter_submodule_names(path, root=""):
for _, module_name, is_package in pkgutil.iter_modules([str(path)]):
if is_package:
Expand All @@ -69,29 +73,38 @@ def iter_submodule_names(path, root=""):
# Find classes to register
#################################################


def get_ordered_classes_to_register(modules):
return toposort(get_register_deps_dict(modules))


def get_register_deps_dict(modules):
my_classes = set(iter_my_classes(modules))
my_classes_by_idname = {cls.bl_idname : cls for cls in my_classes if hasattr(cls, "bl_idname")}
my_classes_by_idname = {
cls.bl_idname: cls for cls in my_classes if hasattr(cls, "bl_idname")
}

deps_dict = {}
for cls in my_classes:
deps_dict[cls] = set(iter_my_register_deps(cls, my_classes, my_classes_by_idname))
deps_dict[cls] = set(
iter_my_register_deps(cls, my_classes, my_classes_by_idname)
)
return deps_dict


def iter_my_register_deps(cls, my_classes, my_classes_by_idname):
yield from iter_my_deps_from_annotations(cls, my_classes)
yield from iter_my_deps_from_parent_id(cls, my_classes_by_idname)


def iter_my_deps_from_annotations(cls, my_classes):
for value in typing.get_type_hints(cls, {}, {}).values():
dependency = get_dependency_from_annotation(value)
if dependency is not None:
if dependency in my_classes:
yield dependency


def get_dependency_from_annotation(value):
if blender_version >= (2, 93):
if isinstance(value, bpy.props._PropertyDeferred):
Expand All @@ -102,6 +115,7 @@ def get_dependency_from_annotation(value):
return value[1]["type"]
return None


def iter_my_deps_from_parent_id(cls, my_classes_by_idname):
if bpy.types.Panel in cls.__bases__:
parent_idname = getattr(cls, "bl_parent_id", None)
Expand All @@ -110,38 +124,54 @@ def iter_my_deps_from_parent_id(cls, my_classes_by_idname):
if parent_cls is not None:
yield parent_cls


def iter_my_classes(modules):
base_types = get_register_base_types()
for cls in get_classes_in_modules(modules):
if any(base in base_types for base in cls.__bases__):
if not getattr(cls, "is_registered", False):
yield cls


def get_classes_in_modules(modules):
classes = set()
for module in modules:
for cls in iter_classes_in_module(module):
classes.add(cls)
return classes


def iter_classes_in_module(module):
for value in module.__dict__.values():
if inspect.isclass(value):
yield value


def get_register_base_types():
return set(getattr(bpy.types, name) for name in [
"Panel", "Operator", "PropertyGroup",
"AddonPreferences", "Header", "Menu",
"Node", "NodeSocket", "NodeTree",
"UIList", "RenderEngine",
"Gizmo", "GizmoGroup",
])
return set(
getattr(bpy.types, name)
for name in [
"Panel",
"Operator",
"PropertyGroup",
"AddonPreferences",
"Header",
"Menu",
"Node",
"NodeSocket",
"NodeTree",
"UIList",
"RenderEngine",
"Gizmo",
"GizmoGroup",
]
)


# Find order to register to solve dependencies
#################################################


def toposort(deps_dict):
sorted_list = []
sorted_values = set()
Expand All @@ -153,5 +183,5 @@ def toposort(deps_dict):
sorted_values.add(value)
else:
unsorted.append(value)
deps_dict = {value : deps_dict[value] - sorted_values for value in unsorted}
deps_dict = {value: deps_dict[value] - sorted_values for value in unsorted}
return sorted_list
Loading

0 comments on commit a4ca10e

Please sign in to comment.