Skip to content

Commit

Permalink
Add subfixture based controlling
Browse files Browse the repository at this point in the history
  • Loading branch information
vanous committed Sep 5, 2024
1 parent 913d7d2 commit 306974b
Show file tree
Hide file tree
Showing 6 changed files with 278 additions and 59 deletions.
11 changes: 7 additions & 4 deletions data.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def set(universe, addr, val):
return

if DMX_Data._dmx is not None:
dmx = bpy.context.scene.dmx # hmm, here we use non cached dmx, probably this was safer...
dmx = bpy.context.scene.dmx # hmm, here we use non cached dmx, probably this was safer...
if dmx.get_selected_live_dmx_universe().input == "BLENDERDMX":
dmx = bpy.context.scene.dmx
dmx.dmx_values[addr - 1].channel = val
Expand All @@ -113,22 +113,25 @@ def set(universe, addr, val):

# LiveDMX view
if DMX_Data._dmx is not None:
dmx = bpy.context.scene.dmx # ...or maybe it prevents using this call before the class is ready?
dmx = bpy.context.scene.dmx # ...or maybe it prevents using this call before the class is ready?
selected_live_dmx_universe = dmx.get_selected_live_dmx_universe()
if selected_live_dmx_universe is None: # this should not happen
raise ValueError("Missing selected universe, as if DMX base class is empty...")
if selected_live_dmx_universe.input == "BLENDERDMX" and selected_live_dmx_universe.id == universe:
DMX_Data._live_view_data = DMX_Data._universes[universe]

@staticmethod
def set_virtual(fixture, attribute, value):
def set_virtual(fixture, attribute, geometry, value):
"""Set value of virtual channel for given fixture"""
DMX_Log.log.debug((fixture, attribute, value))
if value > 255:
return
if fixture not in DMX_Data._virtuals:
DMX_Data._virtuals[fixture] = {}
DMX_Data._virtuals[fixture][attribute] = value
if attribute not in DMX_Data._virtuals[fixture]:
DMX_Data._virtuals[fixture][attribute] = {}
DMX_Data._virtuals[fixture][attribute]["value"] = value
DMX_Data._virtuals[fixture][attribute]["geometry"] = geometry

@staticmethod
def get_virtual(fixture):
Expand Down
7 changes: 6 additions & 1 deletion dmx.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
from .panels import profiles as Profiles
from .panels import distribute as distribute
from .panels import classing as classing
from .panels import subfixtures as subfixtures

from .preferences import DMX_Preferences, DMX_Regenrate_UUID
from .group import FixtureGroup, DMX_Group
Expand Down Expand Up @@ -117,7 +118,8 @@ class DMX(PropertyGroup):
DMX_MVR_Xchange_Client,
DMX_MVR_Xchange,
DMX_Regenrate_UUID,
DMX_Preferences)
DMX_Preferences,
subfixtures.DMX_Subfixture)

# Classes to be registered
# The registration is done in two steps. The second only runs
Expand Down Expand Up @@ -167,6 +169,9 @@ class DMX(PropertyGroup):
groups.DMX_PT_Groups,
classing.DMX_UL_Class,
classing.DMX_PT_Classes,
subfixtures.DMX_PT_Subfixtures,
subfixtures.DMX_UL_Subfixture,
subfixtures.DMX_OT_Subfixture_Clear,
programmer.DMX_OT_Programmer_DeselectAll,
programmer.DMX_OT_Programmer_SelectAll,
programmer.DMX_OT_Programmer_SelectFiltered,
Expand Down
23 changes: 23 additions & 0 deletions dmx_temp_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

from . import fixture as fixture
from .logging import DMX_Log
from .panels import subfixtures

from .mvr_xchange import DMX_MVR_Xchange
from .panels import profiles as Profiles
Expand All @@ -31,11 +32,16 @@
CollectionProperty)

from bpy.types import (PropertyGroup)
from .fixture import DMX_Fixture_Channel

from .i18n import DMX_Lang
_ = DMX_Lang._

class DMX_TempData(PropertyGroup):
filtered_subfixtures=[]

def set_filtered_subfixtures(self, subs):
DMX_TempData.filtered_subfixtures = subs

def onUpdateCollections(self, context):
dmx = context.scene.dmx
Expand Down Expand Up @@ -129,3 +135,20 @@ def onUpdateLoggingFilter(self, context):
dist_gap: FloatProperty(name="Gap", default=2)
dist_diameter: FloatProperty(name="Diameter", default=2)
dist_rotate: BoolProperty(name="Rotate", default=False)
programmer_source: StringProperty(name="Source")

subfixtures: CollectionProperty(
name = _("Subfixtures"),
type=subfixtures.DMX_Subfixture
)

active_subfixtures: CollectionProperty(
name = _("Active Subfixtures"),
type=PropertyGroup
)

active_subfixture_i : IntProperty(
default = -1
)

selected_fixture_label: StringProperty()
114 changes: 68 additions & 46 deletions fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,17 +544,32 @@ def build(self, name, profile, mode, universe, address, gel_color, display_beams
# Interface Methods #

def setDMX(self, pvalues):
channels = [c.id for c in self.channels]
virtuals = [c.id for c in self.virtual_channels]

temp_data = bpy.context.window_manager.dmx

#channels = [c.id for c in self.channels]
#virtuals = [c.id for c in self.virtual_channels]

for attribute, value in pvalues.items():
for idx, channel in enumerate(channels):
if channel == attribute:
DMX_Log.log.info(("Set DMX data", channel, value))
DMX_Data.set(self.universe, self.address+idx, value)
for vchannel in virtuals:
if vchannel == attribute:
DMX_Log.log.info(("Set Virtual data", attribute, value))
DMX_Data.set_virtual(self.name, attribute, value)
for idx, channel in enumerate(self.channels):
if channel.id == attribute:
if len(temp_data.active_subfixtures)>0:
if any(channel.geometry == g.name for g in temp_data.active_subfixtures):
DMX_Log.log.info(("Set DMX data", channel.id, value))
DMX_Data.set(self.universe, self.address+idx, value)
else:
DMX_Log.log.info(("Set DMX data", channel, value))
DMX_Data.set(self.universe, self.address+idx, value)
for vchannel in self.virtual_channels:
if vchannel.id == attribute:
if len(temp_data.active_subfixtures)>0:
if any(vchannel.geometry == g.name for g in temp_data.active_subfixtures):
DMX_Log.log.info(("Set Virtual data", attribute, value))
geometry = next(vchannel.geometry == g.name for g in temp_data.active_subfixtures)
DMX_Data.set_virtual(self.name, attribute, geometry, value)
else:
DMX_Log.log.info(("Set Virtual data", attribute, value))
DMX_Data.set_virtual(self.name, attribute, None, value)

def render(self, skip_cache = False, current_frame = None):

Expand All @@ -563,12 +578,12 @@ def render(self, skip_cache = False, current_frame = None):
return

channels = [c.id for c in self.channels]
virtual_channels = [c.id for c in self.virtual_channels]
#virtual_channels = [c.id for c in self.virtual_channels]

data = DMX_Data.get(self.universe, self.address, len(channels))
data_virtual = DMX_Data.get_virtual(self.name)

s_data = [int(b) for b in data] + [int(b) for b in data_virtual.values()] # create cache
s_data = [int(b) for b in data] + [int(b["value"]) for b in data_virtual.values()] # create cache
if list(self["dmx_values"]) == s_data: # this helps to eliminate flicker with Ethernet DMX signal when the data for this particular device is not changing
if skip_cache is False: # allow to save a keyframe when using the programmer in Blender
DMX_Log.log.debug("caching DMX")
Expand All @@ -591,8 +606,8 @@ def render(self, skip_cache = False, current_frame = None):
tilt_rotating_geometries={}
gobo1 = [None, None] #gobo selection (Gobo1, Gobo2), gobo indexing/rotation (Gobo1Pos, Gobo2Pos)

for attribute in virtual_channels:
geometry = None # for now. But, no way to know, as BlenderDMX controls are universal
for vchannel in self.virtual_channels:
geometry = vchannel.geometry # for now. But, no way to know, as BlenderDMX controls are universal
if geometry not in rgb_mixing_geometries.keys():
rgb_mixing_geometries[geometry] = [None] * 12 # R, G, B, White, WW, CW, Amber, Lime, UV, cyan, magenta, yellow
if geometry not in xyz_moving_geometries.keys():
Expand All @@ -605,44 +620,44 @@ def render(self, skip_cache = False, current_frame = None):
pan_rotating_geometries[geometry]=[None, 1]
if geometry not in tilt_rotating_geometries.keys():
tilt_rotating_geometries[geometry]=[None, 1]
if attribute in data_virtual:
if attribute == "Shutter1": shutter_dimmer_geometries[geometry][0] = data_virtual[attribute]
elif attribute == "Dimmer": shutter_dimmer_geometries[geometry][1] = data_virtual[attribute]
elif attribute == "+Dimmer":
shutter_dimmer_geometries[geometry][1] = shutter_dimmer_geometries[geometry][1] * 256 + data_virtual[attribute]
if vchannel.id in data_virtual:
if vchannel.id == "Shutter1": shutter_dimmer_geometries[geometry][0] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "Dimmer": shutter_dimmer_geometries[geometry][1] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "+Dimmer":
shutter_dimmer_geometries[geometry][1] = shutter_dimmer_geometries[geometry][1] * 256 + data_virtual[vchannel.id]["value"]
shutter_dimmer_geometries[geometry][3] = 256

elif (attribute == "ColorAdd_R" or attribute == "ColorRGB_Red"): rgb_mixing_geometries[geometry][0] = data_virtual[attribute]
elif (attribute == "ColorAdd_G" or attribute == "ColorRGB_Green"): rgb_mixing_geometries[geometry][1] = data_virtual[attribute]
elif (attribute == "ColorAdd_B" or attribute == "ColorRGB_Blue"): rgb_mixing_geometries[geometry][2] = data_virtual[attribute]
elif attribute == "ColorSub_C": cmy[0] = data_virtual[attribute]
elif attribute == "ColorSub_M": cmy[1] = data_virtual[attribute]
elif attribute == "ColorSub_Y": cmy[2] = data_virtual[attribute]
elif attribute == "Pan":
panTilt[0] = data_virtual[attribute]
pan_rotating_geometries[geometry][0] = data_virtual[attribute]
elif attribute == "+Pan":
panTilt[0] = panTilt[0] * 256 + data_virtual[attribute]
elif (vchannel.id == "ColorAdd_R" or vchannel.id == "ColorRGB_Red"): rgb_mixing_geometries[geometry][0] = data_virtual[vchannel.id]["value"]
elif (vchannel.id == "ColorAdd_G" or vchannel.id == "ColorRGB_Green"): rgb_mixing_geometries[geometry][1] = data_virtual[vchannel.id]["value"]
elif (vchannel.id == "ColorAdd_B" or vchannel.id == "ColorRGB_Blue"): rgb_mixing_geometries[geometry][2] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "ColorSub_C": cmy[0] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "ColorSub_M": cmy[1] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "ColorSub_Y": cmy[2] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "Pan":
panTilt[0] = data_virtual[vchannel.id]["value"]
pan_rotating_geometries[geometry][0] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "+Pan":
panTilt[0] = panTilt[0] * 256 + data_virtual[vchannel.id]["value"]
panTilt[2] = 256 # 16bit
pan_rotating_geometries[geometry][0] = pan_rotating_geometries[geometry][0] * 256 + data_virtual[attribute]
pan_rotating_geometries[geometry][0] = pan_rotating_geometries[geometry][0] * 256 + data_virtual[vchannel.id]["value"]
pan_rotating_geometries[geometry][2] = 256

elif attribute == "Tilt":
panTilt[1] = data_virtual[attribute]
tilt_rotating_geometries[geometry][0] = data_virtual[attribute]
elif attribute == "+Tilt":
panTilt[1] = panTilt[1] * 256 + data_virtual[attribute]
elif vchannel.id == "Tilt":
panTilt[1] = data_virtual[vchannel.id]["value"]
tilt_rotating_geometries[geometry][0] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "+Tilt":
panTilt[1] = panTilt[1] * 256 + data_virtual[vchannel.id]["value"]
panTilt[3] = 256 # 16bit
tilt_rotating_geometries[geometry][0] = tilt_rotating_geometries[geometry][0] * 256 + data_virtual[attribute]
tilt_rotating_geometries[geometry][0] = tilt_rotating_geometries[geometry][0] * 256 + data_virtual[vchannel.id]["value"]
tilt_rotating_geometries[geometry][2] = 256

elif attribute == "Zoom": zoom = data_virtual[attribute]
elif attribute == "XYZ_X": xyz_moving_geometries[geometry][0] = data_virtual[attribute]
elif attribute == "XYZ_Y": xyz_moving_geometries[geometry][1] = data_virtual[attribute]
elif attribute == "XYZ_Z": xyz_moving_geometries[geometry][2] = data_virtual[attribute]
elif attribute == "Rot_X": xyz_rotating_geometries[geometry][0] = data_virtual[attribute]
elif attribute == "Rot_Y": xyz_rotating_geometries[geometry][1] = data_virtual[attribute]
elif attribute == "Rot_Z": xyz_rotating_geometries[geometry][2] = data_virtual[attribute]
elif vchannel.id == "Zoom": zoom = data_virtual[vchannel.id]["value"]
elif vchannel.id == "XYZ_X": xyz_moving_geometries[geometry][0] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "XYZ_Y": xyz_moving_geometries[geometry][1] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "XYZ_Z": xyz_moving_geometries[geometry][2] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "Rot_X": xyz_rotating_geometries[geometry][0] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "Rot_Y": xyz_rotating_geometries[geometry][1] = data_virtual[vchannel.id]["value"]
elif vchannel.id == "Rot_Z": xyz_rotating_geometries[geometry][2] = data_virtual[vchannel.id]["value"]

for c in range(len(channels)):
geometry=self.channels[c].geometry
Expand Down Expand Up @@ -716,6 +731,8 @@ def render(self, skip_cache = False, current_frame = None):
self.remove_unset_geometries_from_multigeometry_attributes_1(pan_rotating_geometries)
self.remove_unset_geometries_from_multigeometry_attributes_1(tilt_rotating_geometries)



colorwheel_color = None
if (color1 is not None):
colorwheel_color = self.get_colorwheel_color(color1)
Expand Down Expand Up @@ -1384,14 +1401,19 @@ def hide_gobo(self, hide = True, current_frame = None):

def has_attribute(self, attribute, lower = False):

temp_data = bpy.context.window_manager.dmx
def low(id):
if lower:
return id.lower()
else:
return id
if len(temp_data.active_subfixtures) > 0:
real = any([attribute in low(channel.id) for channel in self.channels if any(channel.geometry == g.name for g in temp_data.active_subfixtures)])
virtual = any([attribute in channel.id for channel in self.virtual_channels if any(channel.geometry == g.name for g in temp_data.active_subfixtures)])
else:
real = any([attribute in low(channel.id) for channel in self.channels])
virtual = any([attribute in channel.id for channel in self.virtual_channels])

real = any([attribute in low(channel.id) for channel in self.channels])
virtual = any([attribute in channel.id for channel in self.virtual_channels])

return (real or virtual)

Expand Down
Loading

0 comments on commit 306974b

Please sign in to comment.