| … | … | @@ -106,6 +106,32 @@ def _transform_items(self, context): |
| 106 | 106 | return [(n, n, "") for n in names] |
| 107 | 107 | |
| 108 | 108 | |
| 109 | def _graph_edit(self, context): |
| 110 | """ |
| 111 | Property update callback: tells the live session the graph changed. |
| 112 | |
| 113 | This is the ONLY thing that makes node edits reach the fractal. The depsgraph |
| 114 | handler in ifs_viewport was meant to do it, but an IFSNodeTree is a free-floating |
| 115 | datablock with no scene user - no object, modifier or material references it - so |
| 116 | the dependency graph never evaluates it and never reports an edit. Measured: with a |
| 117 | session running, editing a node property produced ZERO depsgraph updates, which is |
| 118 | why the graph appeared connected and drove nothing. |
| 119 | |
| 120 | Marking the graph dirty (rather than applying here) matches the panel: a slider drag |
| 121 | fires this on every pixel of movement, and the work belongs in the draw handler. |
| 122 | """ |
| 123 | if not ifs_viewport.is_running(): |
| 124 | return |
| 125 | ifs_viewport.session().mark_graph_dirty() |
| 126 | window_manager = bpy.context.window_manager |
| 127 | if window_manager is None: |
| 128 | return |
| 129 | for window in window_manager.windows: |
| 130 | for area in window.screen.areas: |
| 131 | if area.type == 'VIEW_3D': |
| 132 | area.tag_redraw() |
| 133 | |
| 134 | |
| 109 | 135 | class IFSIteratorNode(Node): |
| 110 | 136 | """One iterator: a transform plus its weights and parameters.""" |
| 111 | 137 | |
| … | … | @@ -117,23 +143,29 @@ class IFSIteratorNode(Node): |
| 117 | 143 | def poll(cls, tree): |
| 118 | 144 | return tree.bl_idname == IFSNodeTree.bl_idname |
| 119 | 145 | |
| 120 | | transform: EnumProperty(name="Transform", items=_transform_items) |
| 121 | | opacity: FloatProperty(name="Opacity", default=1.0, min=0.0, max=1.0) |
| 122 | | color_index: FloatProperty(name="Color", default=0.0, min=0.0, max=1.0) |
| 123 | | color_speed: FloatProperty(name="Color speed", default=0.5, min=0.0, max=1.0) |
| 124 | | base_weight: FloatProperty(name="Weight", default=1.0, min=0.0, soft_max=10.0) |
| 146 | transform: EnumProperty(name="Transform", items=_transform_items, |
| 147 | update=_graph_edit) |
| 148 | opacity: FloatProperty(name="Opacity", default=1.0, min=0.0, max=1.0, |
| 149 | update=_graph_edit) |
| 150 | color_index: FloatProperty(name="Color", default=0.0, min=0.0, max=1.0, |
| 151 | update=_graph_edit) |
| 152 | color_speed: FloatProperty(name="Color speed", default=0.5, min=0.0, max=1.0, |
| 153 | update=_graph_edit) |
| 154 | base_weight: FloatProperty(name="Weight", default=1.0, min=0.0, soft_max=10.0, |
| 155 | update=_graph_edit) |
| 125 | 156 | start_weight: FloatProperty( |
| 126 | 157 | name="Start weight", default=1.0, min=0.0, soft_max=10.0, |
| 127 | 158 | description="Share of RESET points that land on this iterator. Not the " |
| 128 | | "same as Weight, which scales its outgoing transitions") |
| 159 | "same as Weight, which scales its outgoing transitions", |
| 160 | update=_graph_edit) |
| 129 | 161 | |
| 130 | 162 | # Outgoing xaos weights, indexed by DESTINATION iterator. This - not the |
| 131 | 163 | # links - is what the fractal reads, because an IFS graph is cyclic and |
| 132 | 164 | # Blender invalidates cyclic links. |
| 133 | 165 | xaos: FloatVectorProperty(size=MAX_ITERATORS, default=[1.0] * MAX_ITERATORS, |
| 134 | | min=0.0, soft_max=4.0) |
| 135 | | real_values: FloatVectorProperty(size=MAX_REAL) |
| 136 | | vec3_values: FloatVectorProperty(size=MAX_VEC3 * 3) |
| 166 | min=0.0, soft_max=4.0, update=_graph_edit) |
| 167 | real_values: FloatVectorProperty(size=MAX_REAL, update=_graph_edit) |
| 168 | vec3_values: FloatVectorProperty(size=MAX_VEC3 * 3, update=_graph_edit) |
| 137 | 169 | real_names: StringProperty(default="") |
| 138 | 170 | vec3_names: StringProperty(default="") |
| 139 | 171 | |