Added generate mindmap in Screenwriter
tin2tin opened this issue · 10 comments
Hi,
I added generation of screenplay mindmaps(very early steps) to the Blender Screenwriter add-on, but only if your add-on is installed: https://github.com/tin2tin/Blender_Screenwriter
Loads of stuff I don't know about when it comes to nodes ex. how to make links and how to return the node intent in link order to Screenwriter.
Blender_.C__Users_45239_Documents_Blender.Projekter_Add-ons_Mural_send_to_mural_01.blend.2023-04-26.17-43-45.mp4
Hmm, I'll have to ask for some help. Do you have any idea why I can't connect the sockets of the Mindmap addon like this:
# create links between nodes
for i in range(nodes_cnt-1):
tree.links.new(nodes[i].outputs[0], nodes[i+1].inputs[0])
Possibly range() does not return a compatible type, I would have thought it would work, but it doesn't.
I got it to work by wrapping the range() in a len(), like this:
for i in range(len(nodes_cnt-1))
which spits out an integer at the end that Blender is happy with.
I hacked together a quick test script, I'll post it below, it will connect every node to the node added after it in the MindMap and print a message to the console when it gets an invalid value. Probably not the best way to handle it, but it should give you something to work from:
import bpy
tree = bpy.data.node_groups['Mind Mapper']
nodes = tree.nodes
count = range(len(nodes))
for i in count:
try:
tree.links.new(nodes[i].outputs[0], nodes[i+1].inputs[0])
except:
print("Job's Done!")
You can also refer to nodes by name, which might not be that convenient in this case, eg: nodes[0] could also be accessed as nodes['Mindmap'], nodes[1] as nodes['Mindmap.001'] and so on, with Blender's naming convention being: add .001, .002, .003 etc for each additional object.
If you're writing a script you can also refer to them by variable name within the script. I find that this is the most convenient when you want to deal with a lot of nodes, or a lot of complex connections, but to take advantage of that you would want to be creating the nodes from the script as well.
You can check out the approach I took to that in the objects for my GhibliGenerator addon: https://github.com/SpectralVectors/GhibliGenerator/blob/main/Objects/RainPlane.py
I didn't actually watch your video until now, wow that's cool!
Thank you for the code now the links are working. It was this line missing:
tree = bpy.data.node_groups['Mind Mapper']
Phew, I'm a complete noob when it comes to coding nodes...
The code is very much wip. I don't know if I can get line breaks to work in the nodes, if not a lot of code can go out:
https://github.com/tin2tin/Blender_Screenwriter/blob/master/operators/mindmap_fountain.py
Do you have any ideas for returning the linked nodes back to text?
ChatGPT came up with this for extracting the texts:
nodes = tree.nodes
# Initialize the arrays to store the node order and labels
node_order = []
node_labels = []
# Loop through the nodes in the material's node tree
for node in nodes:
# Check if the node is connected
if node.inputs:
# Loop through the inputs of the node
for input in node.inputs:
# Check if the input is connected
if input.is_linked:
# Loop through the links of the input
for link in input.links:
# Add the from_node to the node_order array
node_order.append(link.from_node)
# Add the label of the from_node to the node_labels array
node_labels.append(link.from_node.my_string_prop)
# Print the node order and labels
print(node_order)
print(node_labels)
I think ChatGPT might be complicating things more than it needs to, the following code returns all the node strings in the node order:
import bpy
tree = bpy.data.node_groups['Mind Mapper']
nodes = tree.nodes
for node in nodes:
print(node.my_string_prop)
If you need them to be in a certain order then you would have to sort them, this will return - Mindmap, Mindmap.001, Mindmap.002 etc.
If you had branching paths then you might need to separate those and run multiple loops, but to just get the label string back you can get it 'top-level' from the node, rather than going through the inputs to collect the values, like usual.
I have another script that scrapes and outputs positions, links and input values from material node trees, I'll post it here whenever I have the chance, in case it helps.
re: line breaks - that was an issue for me, too. Right now the lines are automatically broken at a certain length.
You could possibly add a line break as a character that it checks for to determine where the line should be broken, rather than at a certain line length, but I'm not sure how to do that right now, it was a bit of a hack to even get text to render on multiple lines without using multiple string props!
I wanted it to go through the linked nodes, preferable starting with the one with only an output first and end with the one with only an input. So, the links will determine the order(which means there can only be one link), and then the rest without links should be added afterward.
Btw. could be cool to batch add images for ex. the VSE as nodes too. That's properly doable, too. I have this add-on which can generate Stable Diffusion images, could be cool if you could batch add them to the mindmapper too, so you can throw both text and images around when designing stories.
Maybe the strings could be wrapped after forced line breaks?
Too late here now. Gotta call it a day. Thanks for the help!
Got the returning of node texts working, so it'll work in screenplay format. The sorting is properly not working as good as it should.
Blender_.C__Users_45239_Documents_Blender.Projekter_Add-ons_Mural_send_to_mural_01.blend.2023-04-27.10-58-51.mp4
BTW. if you add this to your mindmap code in line 204, the line spacing will be less:
box = box.column(align=True)