From 0a3d11cf6a787b024dd61d562d5b9ceca49e0216 Mon Sep 17 00:00:00 2001 From: vanous Date: Mon, 26 Aug 2024 14:36:44 +0200 Subject: [PATCH] save --- dmx.py | 78 +++++++++++++++++++++++++++++++------------- fixture.py | 77 +++++++++++++++++++++++-------------------- material.py | 72 ++++++++++++++++++++++++++++------------ panels/programmer.py | 19 +++++++---- 4 files changed, 160 insertions(+), 86 deletions(-) diff --git a/dmx.py b/dmx.py index 3f024fe..8b1cd36 100644 --- a/dmx.py +++ b/dmx.py @@ -1372,27 +1372,45 @@ def onProgrammerColorWheel(self, context): }) self.render() - def onProgrammerGobo(self, context): + def onProgrammerGobo1(self, context): for fixture in self.fixtures: if fixture.collection is None: continue if fixture.is_selected(): fixture.setDMX({ - 'Gobo1':int(self.programmer_gobo), - 'Gobo2':int(self.programmer_gobo) + 'Gobo1':int(self.programmer_gobo1), }) self.render() - def onProgrammerGoboIndex(self, context): + def onProgrammerGoboIndex1(self, context): for fixture in self.fixtures: if fixture.collection is None: continue if fixture.is_selected(): fixture.setDMX({ - 'Gobo1Pos':int(self.programmer_gobo_index), - 'Gobo1PosRotate':int(self.programmer_gobo_index), - 'Gobo2Pos':int(self.programmer_gobo_index), - 'Gobo2PosRotate':int(self.programmer_gobo_index) + 'Gobo1Pos':int(self.programmer_gobo_index1), + 'Gobo1PosRotate':int(self.programmer_gobo_index1), + }) + self.render() + + def onProgrammerGobo2(self, context): + for fixture in self.fixtures: + if fixture.collection is None: + continue + if fixture.is_selected(): + fixture.setDMX({ + 'Gobo2':int(self.programmer_gobo2), + }) + self.render() + + def onProgrammerGoboIndex2(self, context): + for fixture in self.fixtures: + if fixture.collection is None: + continue + if fixture.is_selected(): + fixture.setDMX({ + 'Gobo2Pos':int(self.programmer_gobo_index2), + 'Gobo2PosRotate':int(self.programmer_gobo_index2), }) self.render() @@ -1441,19 +1459,33 @@ def onProgrammerShutter(self, context): default = 0, update = onProgrammerIris) - programmer_gobo: IntProperty( - name = "Programmer Gobo", + programmer_gobo1: IntProperty( + name = "Programmer Gobo1", + min = 0, + max = 255, + default = 0, + update = onProgrammerGobo1) + + programmer_gobo_index1: IntProperty( + name = "Gobo1 Rotation", + min = 0, + max = 255, + default = 63, + update = onProgrammerGoboIndex1) + + programmer_gobo2: IntProperty( + name = "Programmer Gobo2", min = 0, max = 255, default = 0, - update = onProgrammerGobo) + update = onProgrammerGobo2) - programmer_gobo_index: IntProperty( - name = "Gobo Rotation", + programmer_gobo_index2: IntProperty( + name = "Gobo2 Rotation", min = 0, max = 255, default = 63, - update = onProgrammerGoboIndex) + update = onProgrammerGoboIndex2) programmer_shutter: IntProperty( name = "Programmer Shutter", @@ -1477,8 +1509,10 @@ def syncProgrammer(self): self.programmer_color_wheel = 0 self.programmer_color_temperature = 0 self.programmer_iris = 0 - self.programmer_gobo = 0 - self.programmer_gobo_index = 63 + self.programmer_gobo1 = 0 + self.programmer_gobo_index1 = 63 + self.programmer_gobo2 = 0 + self.programmer_gobo_index2 = 63 return elif (n > 1): return active = selected[0] @@ -1504,17 +1538,17 @@ def syncProgrammer(self): if ('Iris' in data): self.programmer_iris = int(data['Iris']) if ('Gobo1' in data): - self.programmer_gobo = int(data['Gobo1']) + self.programmer_gobo1 = int(data['Gobo1']) if ('Gobo2' in data): - self.programmer_gobo = int(data['Gobo2']) + self.programmer_gobo2 = int(data['Gobo2']) if ('Gobo1Pos' in data): - self.programmer_gobo_index = int(data['Gobo1Pos']) + self.programmer_gobo_index1 = int(data['Gobo1Pos']) if ('Gobo1PosRotate' in data): - self.programmer_gobo_index = int(data['Gobo1PosRotate']) + self.programmer_gobo_index1 = int(data['Gobo1PosRotate']) if ('Gobo2Pos' in data): - self.programmer_gobo_index = int(data['Gobo2Pos']) + self.programmer_gobo_index2 = int(data['Gobo2Pos']) if ('Gobo2PosRotate' in data): - self.programmer_gobo_index = int(data['Gobo2PosRotate']) + self.programmer_gobo_index2 = int(data['Gobo2PosRotate']) if ('ColorAdd_R' in data and 'ColorAdd_G' in data and 'ColorAdd_B' in data): rgb = [data['ColorAdd_R'],data['ColorAdd_G'],data['ColorAdd_B']] self.programmer_color = (*flatten_color(rgb), 255) diff --git a/fixture.py b/fixture.py index 70b5b1f..08dc46e 100644 --- a/fixture.py +++ b/fixture.py @@ -606,7 +606,8 @@ def render(self, skip_cache = False, current_frame = None): shutter_dimmer_geometries={} # item: shutter, dimmer, unused, dimmer bits pan_rotating_geometries={} tilt_rotating_geometries={} - gobo1 = [None, None] #gobo selection (Gobo1, Gobo2), gobo indexing/rotation (Gobo1Pos, Gobo2Pos) + gobo1 = [None, None] #gobo selection (Gobo1), gobo indexing/rotation (Gobo1Pos) + gobo2 = [None, None] #gobo selection (Gobo2), gobo indexing/rotation (Gobo2Pos) for vchannel in self.virtual_channels: geometry = vchannel.geometry # for now. But, no way to know, as BlenderDMX controls are universal @@ -721,8 +722,8 @@ def render(self, skip_cache = False, current_frame = None): elif (channels[c] == 'ColorMacro1'): color1 = data[c] elif (channels[c] == 'Gobo1'): gobo1[0] = data[c] elif (channels[c] == 'Gobo1Pos' or channels[c] == 'Gobo1PosRotate'): gobo1[1] = data[c] - elif (channels[c] == 'Gobo2'): gobo1[0] = data[c] - elif (channels[c] == 'Gobo2Pos' or channels[c] == 'Gobo2PosRotate'): gobo1[1] = data[c] + elif (channels[c] == 'Gobo2'): gobo2[0] = data[c] + elif (channels[c] == 'Gobo2Pos' or channels[c] == 'Gobo2PosRotate'): gobo2[1] = data[c] elif (channels[c] == 'XYZ_X'): xyz_moving_geometries[geometry][0] = data[c] elif (channels[c] == 'XYZ_Y'): xyz_moving_geometries[geometry][1] = data[c] elif (channels[c] == 'XYZ_Z'): xyz_moving_geometries[geometry][2] = data[c] @@ -793,7 +794,10 @@ def render(self, skip_cache = False, current_frame = None): self.updateZoom(zoom, current_frame) if gobo1[0] is not None: - self.updateGobo(gobo1, current_frame) + self.updateGobo(gobo1, 1, current_frame) + + if gobo2[0] is not None: + self.updateGobo(gobo2, 2, current_frame) for geometry, xyz in xyz_moving_geometries.items(): self.updatePosition(geometry=geometry, x=xyz[0], y=xyz[1], z=xyz[2], current_frame=current_frame) @@ -1008,12 +1012,13 @@ def updateRGB(self, colors, geometry, colorwheel_color, color_temperature, curre def updateCMY(self, cmy, colorwheel_color, color_temperature, current_frame): rgb=[0,0,0] rgb=cmy_to_rgb(cmy) - + print("rgb", rgb) if all([c == 255 for c in rgb]) and (colorwheel_color is not None or color_temperature is not None): rgb=[0,0,0] # without this, default white would always be overwriting ctc if colorwheel_color is not None: - rgb = add_rgb(rgb, colorwheel_color[:3]) + print("cw", colorwheel_color[:3]) + rgb = add_rgb(rgb, colorwheel_color) if color_temperature is not None: rgb = add_rgb(rgb, color_temperature[:3]) if not all([c == 255 for c in self.gel_color_rgb]): @@ -1026,6 +1031,7 @@ def updateCMY(self, cmy, colorwheel_color, color_temperature, current_frame): if current_frame and self.dmx_cache_dirty: emitter_material.material.node_tree.nodes[1].inputs[COLOR].keyframe_insert(data_path='default_value', frame=current_frame) for light in self.lights: + print("final", rgb) light.object.data.color = rgb if current_frame and self.dmx_cache_dirty: light.object.data.keyframe_insert(data_path='color', frame=current_frame) @@ -1079,7 +1085,7 @@ def get_colorwheel_color(self, color1): index = int(color1/int(255/(len(colors)-1))) if len(colors) > index: - return colors[index] + return list(colors[index]) def get_color_temperature(self, ctc): if ctc == 0: @@ -1102,36 +1108,36 @@ def update_iris(self, iris, current_frame): light_obj.data.keyframe_insert(data_path="shadow_soft_size", frame=current_frame) iris_size.keyframe_insert(data_path="default_value", frame=current_frame) - def updateGobo(self, gobo1, current_frame): + def updateGobo(self, gobo, n, current_frame): if "gobos" not in self.images: - self.hide_gobo(current_frame=current_frame) + self.hide_gobo([n], current_frame=current_frame) return gobos = self.images["gobos"] - if gobo1[0] == 0: - self.hide_gobo(current_frame=current_frame) + if gobo[0] == 0: + self.hide_gobo([n], current_frame=current_frame) return if not gobos.count: - self.hide_gobo(current_frame=current_frame) + self.hide_gobo([n], current_frame=current_frame) return - self.hide_gobo(False, current_frame=current_frame) - index = int(gobo1[0]/int(255/(gobos.count-1))) - self.set_gobo(index, current_frame=current_frame) + self.hide_gobo([n], False, current_frame=current_frame) + index = int(gobo[0]/int(255/(gobos.count-1))) + self.set_gobo(n, index, current_frame=current_frame) - if gobo1[1] is None: + if gobo[1] is None: #self.hide_gobo() #? return for obj in self.collection.objects: #EEVEE if "gobo" in obj.get("geometry_type", ""): - if gobo1[1]<128: # half for indexing + if gobo[1]<128: # half for indexing obj.driver_remove("rotation_euler") - obj.rotation_euler[2] = (gobo1[1]/62.0-1)*360*(math.pi/360) + obj.rotation_euler[2] = (gobo[1]/62.0-1)*360*(math.pi/360) else: # half for rotation driver = obj.driver_add("rotation_euler", 2) - value = gobo1[1]-128-62 # rotating in both direction, slowest in the middle + value = gobo[1]-128-62 # rotating in both direction, slowest in the middle driver.driver.expression=f"frame*{value*0.005}" if current_frame and self.dmx_cache_dirty: @@ -1139,17 +1145,17 @@ def updateGobo(self, gobo1, current_frame): for light in self.lights: #CYCLES light_obj = light.object - gobo_rotation = light_obj.data.node_tree.nodes.get("Gobo1Rotation") - if gobo1[1]<128: # half for indexing - gobo_rotation.inputs[3].driver_remove("rotation_euler") - gobo_rotation.inputs[3].default_value = (gobo1[1]/62.0-1)*360*(math.pi/360) + gobo_rotation = light_obj.data.node_tree.nodes.get(f"Gobo{n}Rotation") + if gobo[1]<128: # half for indexing + gobo_rotation.inputs[3].driver_remove("default_value") + gobo_rotation.inputs[3].default_value = (gobo[1]/62.0-1)*360*(math.pi/360) else: # half for rotation - driver = gobo_rotation.inputs[3].driver_add("rotation_euler") - value = gobo1[1]-128-62 # rotating in both direction, slowest in the middle + driver = gobo_rotation.inputs[3].driver_add("default_value") + value = gobo[1]-128-62 # rotating in both direction, slowest in the middle driver.driver.expression=f"frame*{value*0.005}" if current_frame and self.dmx_cache_dirty: - gobo_rotation.inputs[3].keyframe_insert(data_path='rotation_euler', frame=current_frame) + gobo_rotation.inputs[3].keyframe_insert(data_path="default_value", frame=current_frame) def updatePosition(self, geometry = None, x=None, y=None, z=None, current_frame=None): if geometry is None: @@ -1383,7 +1389,7 @@ def clear(self): DMX_Data.set(self.universe, self.address+i, ch.default) self.render() - def set_gobo(self, index=-1, current_frame=None): + def set_gobo(self, n, index=-1, current_frame=None): gobos = self.images["gobos"] for obj in self.collection.objects: #EEVEE if "gobo" in obj.get("geometry_type", ""): @@ -1403,7 +1409,7 @@ def set_gobo(self, index=-1, current_frame=None): for light in self.lights: # CYCLES light_obj = light.object - texture = light_obj.data.node_tree.nodes.get("Gobo1Texture") + texture = light_obj.data.node_tree.nodes.get(f"Gobo{n}Texture") if texture.image is None: texture.image = gobos.image texture.image.source = "SEQUENCE" @@ -1430,7 +1436,7 @@ def set_spot_diameter_to_normal(self, light_obj): size = light_obj.data.get("beam_radius", 0.01) light_obj.data.shadow_soft_size = size - def hide_gobo(self, hide = True, current_frame = None): + def hide_gobo(self, n=[1,2], hide = True, current_frame = None): for obj in self.collection.objects: if "gobo" in obj.get("geometry_type", ""): obj.hide_viewport = hide @@ -1438,19 +1444,18 @@ def hide_gobo(self, hide = True, current_frame = None): obj.keyframe_insert("hide_viewport", frame = current_frame) for light in self.lights: # CYCLES light_obj = light.object - mix = light_obj.data.node_tree.nodes.get("Mix") - if hide: - mix.blend_type = "MIX" - else: - mix.blend_type = "MULTIPLY" + for i in n: + #mix = light_obj.data.node_tree.nodes.get(f"Gobo{i}Mix") + mix_factor = light_obj.data.node_tree.nodes.get(f"Gobo{i}Mix").inputs["Factor"] + mix_factor.default_value = 1 if hide else 0 #mix_factor = light_obj.data.node_tree.nodes.get("Mix").inputs["Factor"] #mix_factor.default_value = 1 if hide else 0 self.set_spot_diameter_to_normal(light_obj) # make the beam large if no gobo is used if current_frame and self.dmx_cache_dirty: light_obj.data.keyframe_insert(data_path="shadow_soft_size", frame=current_frame) - #mix_factor.keyframe_insert(data_path="default_value", frame=current_frame) - mix.keyframe_insert(data_path="blend_type", frame=current_frame) + mix_factor.keyframe_insert(data_path="default_value", frame=current_frame) + #mix.keyframe_insert(data_path="blend_type", frame=current_frame) def has_attributes(self, attributes, lower = False): diff --git a/material.py b/material.py index 369fc83..b6d45f5 100644 --- a/material.py +++ b/material.py @@ -133,40 +133,70 @@ def set_light_nodes(light): light_node = light_obj.data.node_tree.nodes.get(LIGHT_NODE) # set gobo node - gobo_image_rotate = light_obj.data.node_tree.nodes.new("ShaderNodeVectorRotate") - gobo_image_rotate.name = "Gobo1Rotation" - gobo_image_rotate.rotation_type = "Z_AXIS" - gobo_image_rotate.invert = True - gobo_image_rotate.inputs[1].default_value[:2] = [0.5] * 2 - gobo_image = light_obj.data.node_tree.nodes.new(SHADER_NODE_TEX_IMAGE) - gobo_image.name = "Gobo1Texture" + + gobo2_image_rotate = light_obj.data.node_tree.nodes.new("ShaderNodeVectorRotate") + gobo2_image_rotate.name = "Gobo2Rotation" + gobo2_image_rotate.rotation_type = "Z_AXIS" + gobo2_image_rotate.invert = True + gobo2_image_rotate.inputs[1].default_value[:2] = [0.5] * 2 + gobo2_image = light_obj.data.node_tree.nodes.new(SHADER_NODE_TEX_IMAGE) + gobo2_image.name = "Gobo2Texture" + + gobo1_image_rotate = light_obj.data.node_tree.nodes.new("ShaderNodeVectorRotate") + gobo1_image_rotate.name = "Gobo1Rotation" + gobo1_image_rotate.rotation_type = "Z_AXIS" + gobo1_image_rotate.invert = True + gobo1_image_rotate.inputs[1].default_value[:2] = [0.5] * 2 + gobo1_image = light_obj.data.node_tree.nodes.new(SHADER_NODE_TEX_IMAGE) + gobo1_image.name = "Gobo1Texture" gobo_geometry_node = light_obj.data.node_tree.nodes.new("ShaderNodeNewGeometry") gobo_geometry_node.location = (-694.17, 457.04) - gobo_image_rotate.location = (-405.22, 486.14) - - light_obj.data.node_tree.links.new(gobo_geometry_node.outputs[5], gobo_image_rotate.inputs[0]) - light_obj.data.node_tree.links.new(gobo_image_rotate.outputs[0], gobo_image.inputs[0]) + gobo1_image_rotate.location = (-405.22, 486.14) + gobo2_image_rotate.location = (-406.19, 229.93) + + light_obj.data.node_tree.links.new(gobo_geometry_node.outputs[5], gobo1_image_rotate.inputs[0]) + light_obj.data.node_tree.links.new(gobo1_image_rotate.outputs[0], gobo1_image.inputs[0]) + light_obj.data.node_tree.links.new(gobo_geometry_node.outputs[5], gobo2_image_rotate.inputs[0]) + light_obj.data.node_tree.links.new(gobo2_image_rotate.outputs[0], gobo2_image.inputs[0]) + + gobo1_mix = light_obj.data.node_tree.nodes.new(SHADER_NODE_MIX) + gobo1_mix.data_type = "RGBA" + gobo1_mix.blend_type = "MIX" + gobo1_mix.name = "Gobo1Mix" + gobo1_mix.inputs[0].default_value = 1 + + gobo2_mix = light_obj.data.node_tree.nodes.new(SHADER_NODE_MIX) + gobo2_mix.data_type = "RGBA" + gobo2_mix.blend_type = "MIX" + gobo2_mix.name = "Gobo2Mix" + gobo2_mix.inputs[0].default_value = 1 # gobo mix - gobo_mix = light_obj.data.node_tree.nodes.new(SHADER_NODE_MIX) - gobo_mix.data_type = "RGBA" - gobo_mix.blend_type = "DARKEN" - gobo_mix.name = "Mix" - gobo_mix.inputs[0].default_value = 1 - light_obj.data.node_tree.links.new(gobo_image.outputs[0], gobo_mix.inputs["A"]) + gobos_mix = light_obj.data.node_tree.nodes.new(SHADER_NODE_MIX) + gobos_mix.data_type = "RGBA" + gobos_mix.blend_type = "DARKEN" + gobos_mix.name = "Mix" + gobos_mix.inputs[0].default_value = 1 + + light_obj.data.node_tree.links.new(gobo1_image.outputs[0], gobo1_mix.inputs["A"]) + light_obj.data.node_tree.links.new(gobo2_image.outputs[0], gobo2_mix.inputs["A"]) + + light_obj.data.node_tree.links.new(gobo1_mix.outputs["Result"], gobos_mix.inputs["A"]) + light_obj.data.node_tree.links.new(gobo2_mix.outputs["Result"], gobos_mix.inputs["B"]) mix = light_obj.data.node_tree.nodes.new(SHADER_NODE_MIX) mix.data_type = "RGBA" mix.blend_type = "DARKEN" - mix.name = "Mix" + mix.name = "IrisMix" mix.inputs[0].default_value = 1 + light_obj.data.node_tree.links.new(gobos_mix.outputs["Result"], mix.inputs["A"]) light_obj.data.node_tree.links.new(mix.outputs["Result"], emission.inputs[0]) - light_obj.data.node_tree.links.new(gobo_mix.outputs["Result"], mix.inputs["A"]) - gobo_image.location = (-221.73, 486.83) - gobo_mix.location = (82.07, 489.56) + gobo1_image.location = (-221.73, 486.83) + gobo2_image.location = (-225.50, 280.40) + gobos_mix.location = (82.07, 489.56) mix.location = (319.60, 489.01) emission.location = (529.09, 509.87) light_node.location = (733.60, 536.36) diff --git a/panels/programmer.py b/panels/programmer.py index 03e3c8f..b0d1526 100644 --- a/panels/programmer.py +++ b/panels/programmer.py @@ -193,8 +193,8 @@ def execute(self, context): scene.dmx.programmer_color_wheel = 0 scene.dmx.programmer_color_temperature = 0 scene.dmx.programmer_iris = 0 - scene.dmx.programmer_gobo = 0 - scene.dmx.programmer_gobo_index = 63 + scene.dmx.programmer_gobo1 = 0 + scene.dmx.programmer_gobo_index1 = 63 scene.dmx.programmer_shutter = 0 return {"FINISHED"} @@ -526,9 +526,12 @@ def draw(self, context): box.prop(scene.dmx, "programmer_color_temperature", text=_("Color Temperature"), translate=False) if selected_fixtures[0].has_attributes(["Iris"]): box.prop(scene.dmx, "programmer_iris", text=_("Iris"), translate=False) - if selected_fixtures[0].has_attributes(["Gobo"]): - box.prop(scene.dmx, "programmer_gobo", text=_("Gobo"), translate=False) - box.prop(scene.dmx, "programmer_gobo_index", text=_("Gobo Rotation"), translate=False) + if selected_fixtures[0].has_attributes(["Gobo1"]): + box.prop(scene.dmx, "programmer_gobo1", text=_("Gobo1"), translate=False) + box.prop(scene.dmx, "programmer_gobo_index1", text=_("Gobo1 Rotation"), translate=False) + if selected_fixtures[0].has_attributes(["Gobo2"]): + box.prop(scene.dmx, "programmer_gobo2", text=_("Gobo2"), translate=False) + box.prop(scene.dmx, "programmer_gobo_index2", text=_("Gobo2 Rotation"), translate=False) if selected_fixtures[0].has_attributes(["shutter"], lower=True): box.prop(scene.dmx, "programmer_shutter", text=_("Strobe"), translate=False) else: @@ -559,8 +562,10 @@ def draw(self, context): box.prop(scene.dmx, "programmer_color_wheel", text=_("Color Wheel"), translate=False) box.prop(scene.dmx, "programmer_color_temperature", text=_("Color Temperature"), translate=False) box.prop(scene.dmx, "programmer_iris", text=_("Iris"), translate=False) - box.prop(scene.dmx, "programmer_gobo", text=_("Gobo"), translate=False) - box.prop(scene.dmx, "programmer_gobo_index", text=_("Gobo Rotation"), translate=False) + box.prop(scene.dmx, "programmer_gobo1", text=_("Gobo1"), translate=False) + box.prop(scene.dmx, "programmer_gobo_index1", text=_("Gobo1 Rotation"), translate=False) + box.prop(scene.dmx, "programmer_gobo2", text=_("Gobo2"), translate=False) + box.prop(scene.dmx, "programmer_gobo_index2", text=_("Gobo2 Rotation"), translate=False) box.prop(scene.dmx, "programmer_shutter", text=_("Strobe"), translate=False) box.enabled = selected