Browse Source

Replace RespStateList crazy with a nicer solution

Many thanks to Deledrius for pointing out an example of this hackery in
Blender's node groups!
pull/6/head
Adam Johnson 10 years ago
parent
commit
b9381e078e
  1. 25
      korman/nodes/node_core.py
  2. 61
      korman/nodes/node_responder.py
  3. 1
      korman/operators/__init__.py
  4. 55
      korman/operators/op_nodes.py
  5. 4
      korman/properties/modifiers/region.py

25
korman/nodes/node_core.py

@ -51,14 +51,26 @@ class PlasmaNodeBase:
def link_input(self, tree, node, out_key, in_key):
"""Links a given Node's output socket to a given input socket on this Node"""
if isinstance(in_key, str):
in_socket = self.find_input_socket(in_key)
else:
in_socket = in_key
if isinstance(out_key, str):
out_socket = node.find_output_socket(out_key)
else:
out_socket = out_key
link = tree.links.new(in_socket, out_socket)
def link_output(self, tree, node, out_key, in_key):
"""Links a given Node's input socket to a given output socket on this Node"""
if isinstance(in_key, str):
in_socket = node.find_input_socket(in_key)
else:
in_socket = in_key
if isinstance(out_key, str):
out_socket = self.find_output_socket(out_key)
else:
out_socket = out_key
link = tree.links.new(in_socket, out_socket)
@classmethod
@ -66,6 +78,19 @@ class PlasmaNodeBase:
return (context.bl_idname == "PlasmaNodeTree")
class PlasmaNodeVariableInput(PlasmaNodeBase):
def ensure_sockets(self, idname, name, identifier=None):
"""Ensures there is one (and only one) empty input socket"""
empty = [i for i in self.inputs if i.bl_idname == idname and not i.links]
if not empty:
if identifier is None:
self.inputs.new(idname, name)
else:
self.inputs.new(idname, name, identifier)
while len(empty) > 1:
self.inputs.remove(empty.pop())
class PlasmaNodeSocketBase:
def draw(self, context, layout, node, text):
layout.label(text)

61
korman/nodes/node_responder.py

@ -29,67 +29,30 @@ class PlasmaResponderNode(PlasmaNodeBase, bpy.types.Node):
self.outputs.new("PlasmaRespStateSocket", "States", "states")
class PlasmaResponderStateNode(PlasmaNodeBase, bpy.types.Node):
class PlasmaResponderStateNode(PlasmaNodeVariableInput, bpy.types.Node):
bl_category = "LOGIC"
bl_idname = "PlasmaResponderStateNode"
bl_label = "Responder State"
default_state = BoolProperty(name="Default State",
description="This state is the responder's default",
default=False)
def init(self, context):
self.inputs.new("PlasmaRespStateSocket", "Condition", "whodoneit")
self.outputs.new("PlasmaRespCommandSocket", "Commands", "cmds")
self.outputs.new("PlasmaRespStateSocket", "Trigger", "gotostate").link_limit = 1
def draw_buttons(self, context, layout):
# This actually draws nothing, but it makes sure we have at least one empty input slot
# We need this because it's possible that multiple OTHER states can call us
self.ensure_sockets("PlasmaRespStateSocket", "Condition")
class PlasmaRespStateSocketBase(PlasmaNodeSocketBase):
bl_color = (0.388, 0.78, 0.388, 1.0)
class PlasmaRespStateSocket(PlasmaRespStateSocketBase, bpy.types.NodeSocket):
default_state = BoolProperty(name="Default State",
description="This state is the Responder's default",
default=False)
def draw(self, context, layout, node, text):
# If this is a RespoderState node and the parent is a Responder, offer the user the
# ability to make this the default state.
if self.is_linked and not self.is_output:
# Before we do anything, see if we need to do a delayed update...
if node.bl_idname == "PlasmaResponderStateNode":
parent = node.find_input("whodoneit", "PlasmaResponderNode")
if parent is not None:
# Now draw a prop
layout.prop(self, "default_state")
return
# Still here? Draw the text.
layout.label(text)
class PlasmaResponderStateListNode(PlasmaNodeBase, bpy.types.Node):
bl_category = "LOGIC"
bl_idname = "PlasmaResponderStateListNode"
bl_label = "Responder State List"
def add_state_input(self):
self.inputs.new("PlasmaRespStateListSocket", str(uuid.uuid4()))
def init(self, context):
# Inputs will be added by the user
self.outputs.new("PlasmaRespStateSocket", "Go To State", "gotostate")
def draw_buttons(self, context, layout):
# This will allow us to add input states on the fly.
# Caveat: We're only showing this operator in the properties because we need the node
# to be active in the operator...
op = layout.operator("node.plasma_add_responder_state", text="Add State", icon="ZOOMIN")
op.node_name = self.name
class PlasmaRespStateListSocket(PlasmaRespStateSocketBase, bpy.types.NodeSocket):
def draw(self, context, layout, node, text):
# We'll allow them to delete all their inputs if they want to be stupid...
props = layout.operator("node.plasma_remove_responder_state", text="", icon="X")
props.node_name = node.name
props.socket_name = self.name
class PlasmaRespStateSocket(PlasmaNodeSocketBase, bpy.types.NodeSocket):
bl_color = (0.388, 0.78, 0.388, 1.0)
class PlasmaResponderCommandNode(PlasmaNodeBase, bpy.types.Node):

1
korman/operators/__init__.py

@ -16,7 +16,6 @@
from . import op_export as exporter
from . import op_lightmap as lightmap
from . import op_modifier as modifier
from . import op_nodes as node
from . import op_world as world
def register():

55
korman/operators/op_nodes.py

@ -1,55 +0,0 @@
# This file is part of Korman.
#
# Korman is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Korman is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
import bpy
from bpy.props import *
class NodeOperator:
def get_node_tree(self, context):
space = context.space_data
if space.type != "NODE_EDITOR":
raise RuntimeError("Operator '{}' should only be used in the node editor".format(self.bl_idname))
return space.node_tree
@classmethod
def poll(cls, context):
return context.scene.render.engine == "PLASMA_GAME"
class ResponderStateAddOperator(NodeOperator, bpy.types.Operator):
bl_idname = "node.plasma_add_responder_state"
bl_label = "Add Responder State Socket"
node_name = StringProperty(name="Node's name", options={"HIDDEN"})
def execute(self, context):
tree = self.get_node_tree(context)
tree.nodes[self.node_name].add_state_input()
return {"FINISHED"}
class ResponderStateRemoveOperator(NodeOperator, bpy.types.Operator):
bl_idname = "node.plasma_remove_responder_state"
bl_label = "Remove Responder State Socket"
node_name = StringProperty(name="Node's name", options={"HIDDEN"})
socket_name = StringProperty(name="Socket name to remove", options={"HIDDEN"})
def execute(self, context):
tree = self.get_node_tree(context)
node = tree.nodes[self.node_name]
socket = node.inputs[self.socket_name]
node.inputs.remove(socket)
return {"FINISHED"}

4
korman/properties/modifiers/region.py

@ -94,8 +94,8 @@ class PlasmaFootstepRegion(PlasmaModifierProperties, PlasmaModifierLogicWiz):
respmod = nodes.new("PlasmaResponderNode")
respmod.link_input(tree, logicmod, "trigger", "whodoneit")
respstate = nodes.new("PlasmaResponderStateNode")
respstate.link_input(tree, respmod, "states", "whodoneit")
respstate.find_input_socket("whodoneit").default_state = True
respstate.link_input(tree, respmod, "states", respstate.inputs.new("PlasmaRespStateSocket", "Responder"))
respstate.default_state = True
respcmd = nodes.new("PlasmaResponderCommandNode")
respcmd.link_input(tree, respstate, "cmds", "whodoneit")

Loading…
Cancel
Save