Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make setting universes more understandable #93

Merged
merged 4 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 26 additions & 16 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,16 +270,25 @@ def prepare_empty_buffer(self, context):
# Clear the buffer on change of every protocol
DMX_Data.prepare_empty_buffer()

selected_live_dmx_source : EnumProperty(
name = "DMX Source",
description="The network protocol for which to show live DMX values",
default = "BLENDERDMX",
items = network_options_list,
update = prepare_empty_buffer,
)
selected_live_dmx_universe: IntProperty(
min = 0,
update = prepare_empty_buffer,

def get_dmx_universes(self, context):
#print(self, context)
data = []
for universe in self.universes:
data.append((str(universe.id), universe.name, str(universe.input), "", universe.id))
return data

def get_selected_live_dmx_universe(self):
for universe in self.universes:
selected_universe = universe
if self.selected_live_dmx == str(universe.id):
break
return selected_universe

selected_live_dmx: EnumProperty(
name = "Universe",
description="",
items = get_dmx_universes
)

dmx_values: CollectionProperty(
Expand Down Expand Up @@ -1319,7 +1328,7 @@ def updatePreviewVolume(self):

def addUniverse(self):
id = len(self.universes)
DMX_Universe.add(self, id, "DMX %d"%id)
DMX_Universe.add(self, id, "Universe %d"%id)

def removeUniverse(self, i):
DMX_Universe.remove(self, i)
Expand Down Expand Up @@ -1361,11 +1370,12 @@ def onDepsgraph(scene):

@bpy.app.handlers.persistent
def onLoadFile(scene):
if ('DMX' in bpy.data.scenes['Scene'].collection.children):
print("DMX", "File contains DMX show, linking...")
bpy.context.scene.dmx.linkFile()
else:
bpy.context.scene.dmx.unlinkFile()
if "Scene" in bpy.data.scenes:
if ('DMX' in bpy.data.scenes['Scene'].collection.children):
print("DMX", "File contains DMX show, linking...")
bpy.context.scene.dmx.linkFile()
else:
bpy.context.scene.dmx.unlinkFile()

# Selection callback
handle = object()
Expand Down
29 changes: 20 additions & 9 deletions artnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,24 @@ def __init__(self, ip_addr, *args, **kwargs):
self._socket = socket(AF_INET, SOCK_DGRAM)
self._socket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
self._socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
self._socket.bind((ip_addr, ARTNET_PORT))
self._socket.settimeout(20)
try:
self._socket.bind((ip_addr, ARTNET_PORT))
except OSError as e:
print(e)
self._dmx.artnet_status = "socket_error"
raise ValueError("Socket opening error")

#self._socket.settimeout(30)
self._stopped = False

def stop(self):
try:
self._socket.shutdown(SHUT_RDWR)
except Exception as e:
print("Error while stopping", e)
raise ValueError("Socket closing error")
finally:
self._stopped = True
raise ValueError("Socket closing error")
self._stopped = True


def run(self):
Expand All @@ -77,7 +83,6 @@ def run(self):
data = self._socket.recv(1024)
except Exception as e:
print(e)
print("data", data)
if len(data) < 8:
continue
if struct.unpack("!8s", data[:8])[0] != ArtnetPacket.ARTNET_HEADER:
Expand All @@ -93,6 +98,7 @@ def run(self):
self._dmx.artnet_status = "socket_close"
self._socket.close()
self._dmx.artnet_status = "offline"
self._stopped = True

def handle_ArtPoll(self):
"""ArtPoll is a message to find out which other ArtNet devices are in the network.
Expand Down Expand Up @@ -125,14 +131,14 @@ def build_ArtPollReply(self):
else:
ip = "0.0.0.0"
ip = [int(i) for i in ip.split(".")]
content += [i.to_bytes() for i in ip]
content += [struct.pack('B', i) for i in ip]
# Port
content.append(struct.pack("<H", 0x1936))
# Firmware Version
content.append(struct.pack("!H", 1))
# Net and subnet of this node
content.append(ip[1].to_bytes())
content.append(ip[0].to_bytes())
content.append(struct.pack('B', ip[1]))
content.append(struct.pack('B', ip[0]))
# OEM Code (E:Cue 1x DMX Out)
content.append(struct.pack("H", 0)) #0000
# UBEA Version -> Nope -> 0
Expand Down Expand Up @@ -169,7 +175,11 @@ def enable():
print("\t%s:%s" % (dmx.artnet_ipaddr, ARTNET_PORT))
dmx.artnet_status = "socket_open"

DMX_ArtNet._thread = DMX_ArtNet(dmx.artnet_ipaddr)
try:
DMX_ArtNet._thread = DMX_ArtNet(dmx.artnet_ipaddr)
except Exception as e:
print(e)
return
DMX_ArtNet._thread.start()

bpy.app.timers.register(DMX_ArtNet.run_render)
Expand Down Expand Up @@ -203,6 +213,7 @@ def status():
return [
("offline", "Offline", ""),
("socket_open", "Opening socket...", ""),
("socket_error", "Error opening socket... Close other Art-Net applications, re-enable Art-Net in BlenderDMX and start the other application", ""),
("listen", "Waiting for data...", ""),
("online", "Online", ""),
("stop", "Stopping thread...", ""),
Expand Down
7 changes: 3 additions & 4 deletions data.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,9 @@ def set(universe, addr, val):
if addr > 511:
return


if DMX_Data._dmx is not None:
dmx = DMX_Data._dmx
if dmx.selected_live_dmx_source == "BLENDERDMX":
if dmx.get_selected_live_dmx_universe().input == "BLENDERDMX":
dmx = bpy.context.scene.dmx
dmx.dmx_values[addr-1].channel=val
DMX_Data._universes[universe][addr-1] = val
Expand Down Expand Up @@ -132,7 +131,8 @@ def set_universe(universe, data, source):

if DMX_Data._dmx is not None:
dmx = DMX_Data._dmx
if dmx.selected_live_dmx_source == source and dmx.selected_live_dmx_universe == universe:
selected_live_dmx_universe = dmx.get_selected_live_dmx_universe()
if selected_live_dmx_universe.input == source and selected_live_dmx_universe.id == universe:
if DMX_Data._last_updated is None or (time.time() - DMX_Data._last_updated > 0.8 and changed):
# We limit update by time, too fast updates were troubling Blender's UI
for idx, val in enumerate(data):
Expand All @@ -141,6 +141,5 @@ def set_universe(universe, data, source):
except Exception as e:
print(e)
DMX_Data._last_updated = time.time()
print("update dmx")

return changed
8 changes: 7 additions & 1 deletion fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,18 @@ class DMX_Fixture(PropertyGroup):
type = DMX_Fixture_Channel
)

def ensure_universe_exists(self, context):
dmx = bpy.context.scene.dmx
dmx.ensureUniverseExists(self.universe)

universe : IntProperty(
name = "Fixture > Universe",
description="Fixture DMX Universe",
default = 0,
min = 0,
max = 511)
max = 511,
update = ensure_universe_exists
)

address : IntProperty(
name = "Fixture > Address",
Expand Down
39 changes: 35 additions & 4 deletions panels/dmx.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,13 @@ def draw_item(self, context, layout, data, item, icon, active_data, active_propn
ob = data
icon = "FILE_VOLUME"
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(item, "name", text="", emboss=False, icon=icon)
layout.label(text=item.input)
col = layout.column()
col.label(text=f"{item.id}", icon=icon)
col.ui_units_x = 3
col = layout.column()
col.prop(item, "name", text="", emboss=False)
col = layout.column()
col.label(text=item.input)
elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'
layout.label(text=str(item.id), icon=icon)
Expand Down Expand Up @@ -267,13 +272,21 @@ class DMX_PT_DMX_ArtNet(Panel):
def draw(self, context):
layout = self.layout
dmx = context.scene.dmx

artnet_universes = []
for universe in dmx.universes:
if universe.input == "ARTNET":
artnet_universes.append(universe)

row = layout.row()
row.prop(dmx, "artnet_ipaddr", text="IPv4")
row.enabled = not dmx.artnet_enabled

row = layout.row()
row.prop(dmx, "artnet_enabled")
row.enabled = len(artnet_universes)>0
row = layout.row()
row.label(text=f"Art-Net set for {len(artnet_universes)} universe(s)")
layout.label(text='Status: ' + layout.enum_item_name(dmx, 'artnet_status', dmx.artnet_status))

class DMX_PT_DMX_sACN(Panel):
Expand All @@ -290,8 +303,18 @@ def draw(self, context):
layout = self.layout
dmx = context.scene.dmx

sacn_universes = []
for index, universe in enumerate(dmx.universes):
if index == 0: # invalid for sACN
continue
if universe.input == "sACN":
sacn_universes.append(universe)

row = layout.row()
row.prop(dmx, "sacn_enabled")
row.enabled = len(sacn_universes)>0
row = layout.row()
row.label(text=f"sACN set for {len(sacn_universes)} universe(s)")
layout.label(text='Status: ' + dmx.sacn_status)

class DMX_UL_LiveDMX_items(UIList):
Expand All @@ -316,10 +339,18 @@ class DMX_PT_DMX_LiveDMX(Panel):
def draw(self, context):
layout = self.layout
dmx = context.scene.dmx
selected_universe = dmx.get_selected_live_dmx_universe()

row = layout.row()
row.prop(dmx, "selected_live_dmx_source", text="Source")
row.prop(dmx, "selected_live_dmx_universe", text="Universe")
row.prop(dmx, "selected_live_dmx", text="Source")
row = layout.row()
col = row.column()
col.label(text=f"{selected_universe.id}")
col.ui_units_x = 2
col = row.column()
row.label(text=f"{selected_universe.name}")
col = row.column()
row.label(text=f"{selected_universe.input}")
layout.template_list("DMX_UL_LiveDMX_items", "", dmx, "dmx_values", dmx, "dmx_value_index", type='GRID')

# Panel #
Expand Down
33 changes: 23 additions & 10 deletions panels/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -573,27 +573,28 @@ def draw(self, context):
c.label(text="Name")
c.ui_units_x = 8

if dmx.column_fixture_id:
if dmx.column_fixture_id and not dmx.fixture_properties_editable:

c = row.column()
c.label(text="F ID")
c.ui_units_x = 2

if dmx.column_unit_number:
if dmx.column_unit_number and not dmx.fixture_properties_editable:
c = row.column()
c.ui_units_x = 2
c.label(text="Unit #")

if dmx.column_fixture_id_numeric:
if dmx.column_fixture_id_numeric and not dmx.fixture_properties_editable:
c = row.column()
c.label(text="F ID #")
c.ui_units_x = 2

if dmx.column_custom_id:
if dmx.column_custom_id and not dmx.fixture_properties_editable:
c = row.column()
c.label(text="Cst ID")
c.ui_units_x = 2

if dmx.column_dmx_address:
if dmx.column_dmx_address and not dmx.fixture_properties_editable:
c = row.column()
c.ui_units_x = 2
if dmx.fixture_properties_editable:
Expand All @@ -604,11 +605,6 @@ def draw(self, context):
else:
c.label(text="Uni.Addr")

if dmx.fixture_properties_editable:
c = row.column()
c.ui_units_x = 2
c.label(text="Del")

layout.template_list(
"DMX_UL_Fixtures",
"",
Expand Down Expand Up @@ -730,6 +726,23 @@ def draw_item(self, context, layout, data, item, icon, active_data, active_propn
else:
c.label(text=f"{item.universe}.{item.address}")

if dmx.fixture_properties_editable:
body = None
for obj in item.collection.objects:
if obj.get("geometry_root", False):
body = obj
break
if body is not None:
col = layout.column()
col.prop(body, "location", index=0, text='')
col.ui_units_x = 3
col = layout.column()
col.ui_units_x = 3
col.prop(body, "location", index=1, text='')
col = layout.column()
col.prop(body, "location", index=2, text='')
col.ui_units_x = 3

if dmx.fixture_properties_editable:
col = layout.column()
col.context_pointer_set("fixture", item)
Expand Down
2 changes: 1 addition & 1 deletion universe.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class DMX_Universe(PropertyGroup):
name: StringProperty (
name = "Name",
description = "Name of the universe",
default = "DMX 0"
default = "Universe 0"
)

input: EnumProperty (
Expand Down