Skip to content

Commit

Permalink
Support multiple PSN slots
Browse files Browse the repository at this point in the history
  • Loading branch information
vanous committed Jun 22, 2024
1 parent c433ef4 commit a1c918f
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 48 deletions.
3 changes: 2 additions & 1 deletion dmx.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ class DMX(PropertyGroup):
panels_dmx.DMX_OP_DMX_Tracker_Remove,
panels_dmx.DMX_PT_DMX_Trackers,
panels_dmx.DMX_OT_Tracker_Followers,
panels_dmx.DMX_OT_Tracker_Followers_Add_Target,
panels_dmx.DMX_OT_Tracker_Followers_Remove_Target,
panels_dmx.DMX_UL_Tracker_Followers,
panels_dmx.DMX_OP_Unlink_Fixture_Tracker,
panels_dmx.DMX_OP_Link_Fixture_Tracker,
Expand Down Expand Up @@ -312,7 +314,6 @@ def prepare_empty_buffer(self, context):


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))
Expand Down
2 changes: 2 additions & 0 deletions dmx_temp_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from bpy.props import (BoolProperty,
StringProperty,
PointerProperty,
IntProperty,
CollectionProperty)

from bpy.types import (PropertyGroup)
Expand Down Expand Up @@ -105,3 +106,4 @@ def onUpdateLoggingFilter(self, context):
update = onUpdateLoggingFilter)

selected_tracker: StringProperty() # to pass data to fixture list
selected_tracker_index: IntProperty() # to pass data to fixture list
105 changes: 82 additions & 23 deletions panels/dmx.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
#

import os

from bpy.props import StringProperty
import bpy
from bpy.props import StringProperty, IntProperty
from bpy.types import Menu, Operator, Panel, UIList
from ..mvrx_protocol import DMX_MVR_X_Client
from ..data import DMX_Data, IntProperty
from ..data import DMX_Data
from ..logging import DMX_Log
import uuid as py_uuid
from datetime import datetime
Expand Down Expand Up @@ -189,26 +189,27 @@ class DMX_OP_Link_Fixture_Tracker(Operator):

fixture_uuid: StringProperty()
tracker_uuid: StringProperty()
tracker_index: IntProperty()

def execute(self, context):
scene = context.scene
dmx = scene.dmx

dmx = scene.dmx
layout = self.layout
target = None
for tracker in dmx.trackers:
if tracker.uuid == self.tracker_uuid:
for obj in tracker.objects:
target = obj.object


for fixture in dmx.fixtures:
if fixture.uuid == self.fixture_uuid:
for obj in fixture.objects:
if obj.name == "Target":
constraint = obj.object.constraints.new(type='COPY_LOCATION')
constraint.target = target
for idx, obj in enumerate(tracker.collection.objects):
if idx == self.tracker_index:
target = obj

if target is not None:
for fixture in dmx.fixtures:
if fixture.uuid == self.fixture_uuid:
for obj in fixture.objects:
if obj.name == "Target":
constraint = obj.object.constraints.new(type='COPY_LOCATION')
constraint.target = target

return {"FINISHED"}

Expand All @@ -225,19 +226,14 @@ def execute(self, context):
scene = context.scene
dmx = scene.dmx
layout = self.layout
target = None
for tracker in dmx.trackers:
if tracker.uuid == self.tracker_uuid:
for obj in tracker.objects:
target = obj.object

for fixture in dmx.fixtures:
if fixture.uuid == self.fixture_uuid:
for obj in fixture.objects:
if obj.name == "Target":
for constraint in obj.object.constraints:
if constraint.target.get("uuid", None) == self.tracker_uuid:
obj.object.constraints.remove(constraint)
if constraint.target != None:
if constraint.target.get("uuid", None) == self.tracker_uuid:
obj.object.constraints.remove(constraint)


return {"FINISHED"}
Expand All @@ -247,13 +243,15 @@ def execute(self, context):
class DMX_UL_Tracker_Followers(UIList):

tracker_uuid: StringProperty()
tracker_index: IntProperty()

def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
fixture = item
scene = context.scene
dmx = scene.dmx
icon = "FILE_VOLUME"
self.tracker_uuid = context.window_manager.dmx.selected_tracker
self.tracker_index = context.window_manager.dmx.selected_tracker_index

linked = None
for obj in fixture.objects:
Expand All @@ -280,6 +278,7 @@ def draw_item(self, context, layout, data, item, icon, active_data, active_propn
op = col.operator("dmx.psn_tracker_follower_link", icon="UNLINKED", text="")
op.fixture_uuid = fixture.uuid
op.tracker_uuid = self.tracker_uuid
op.tracker_index = self.tracker_index
elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'
layout.label(text=item.name, icon=icon)
Expand All @@ -292,13 +291,15 @@ class DMX_OT_Tracker_Followers(Operator):
bl_options = {'UNDO'}

tracker_uuid: StringProperty()
tracker_index: IntProperty()
fixture_i: IntProperty()

def draw(self, context):
layout = self.layout
scene = context.scene
dmx = scene.dmx
context.window_manager.dmx.selected_tracker = self.tracker_uuid
context.window_manager.dmx.selected_tracker_index = self.tracker_index
layout.template_list("DMX_UL_Tracker_Followers", "", dmx, "fixtures", self, "fixture_i")


Expand Down Expand Up @@ -373,7 +374,65 @@ def draw(self, context):
layout.prop(tracker, "ip_address")
layout.prop(tracker, "ip_port")
layout.prop(tracker, "enabled")
layout.operator("dmx.psn_tracker_followers", text=_("Link Tracker Followers"), icon="PLUS").tracker_uuid = tracker.uuid
add_trackers = True
for idx, obj in enumerate(tracker.collection.objects):
row = layout.row()
col = row.column()
op=col.operator("dmx.psn_tracker_followers", text=_(f"Link Followers to {obj.name}"), icon="LINKED")
op.tracker_uuid = tracker.uuid
op.tracker_index = idx
if len(tracker.collection.objects) > 1:
col = row.column()
op = col.operator("dmx.psn_remove_tracker_followers_target", text="", icon="TRASH")
op.object_name = obj.name
op.tracker_uuid = tracker.uuid

if idx >= 9: # we support max 10 trackers, edit tracker.py and psn.py if more is needed
add_trackers = False
row = layout.row()
op = row.operator("dmx.psn_add_tracker_followers_target", text=_("Add Tracking Target"), icon="PLUS")
op.tracker_uuid = tracker.uuid
row.enabled = add_trackers



class DMX_OT_Tracker_Followers_Remove_Target(Operator):
bl_label = _("Remove Followers Target")
bl_idname = "dmx.psn_remove_tracker_followers_target"
bl_description = _("Remove target")
bl_options = {'UNDO'}

object_name: StringProperty()
tracker_uuid: StringProperty()

def execute(self, context):
dmx = context.scene.dmx
for tracker in dmx.trackers:
if tracker.uuid == self.tracker_uuid:
if self.object_name in tracker.collection.objects:
rem_obj = tracker.collection.objects[self.object_name]
bpy.data.objects.remove(rem_obj)

return {"FINISHED"}

class DMX_OT_Tracker_Followers_Add_Target(Operator):
bl_label = _("Add Followers Target")
bl_idname = "dmx.psn_add_tracker_followers_target"
bl_description = _("Add target")
bl_options = {'UNDO'}

tracker_uuid: StringProperty()

def execute(self, context):
dmx = context.scene.dmx
for tracker in dmx.trackers:
if tracker.uuid == self.tracker_uuid:
for obj in tracker.collection.objects:
duplicate_obj = obj.copy()
tracker.collection.objects.link(duplicate_obj)
break

return {"FINISHED"}

class DMX_PT_DMX_MVR_X(Panel):
bl_label = _("MVR-xchange")
Expand Down
12 changes: 7 additions & 5 deletions psn.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ def __init__(self, callback, ip_address, port):

def callback(psn_data, tracker):
if isinstance(psn_data, pypsn.psn_data_packet):
position = psn_data.trackers[0].pos # Currently, we are only using the first tracker
DMX_PSN.set_data(tracker.uuid, position)
for idx, slot in enumerate(psn_data.trackers):
position = slot.pos
DMX_PSN.set_data(tracker.uuid, idx, position)
if isinstance(psn_data, pypsn.psn_info_packet):
DMX_Log.log.info(f"Tracker info server: {psn_data.name}")
for tracker_info in psn_data.trackers:
Expand All @@ -32,7 +33,7 @@ def enable(tracker):
DMX_PSN._instances[uuid] = DMX_PSN(None, tracker.ip_address, tracker.ip_port)
DMX_PSN._instances[uuid].receiver.callback = partial(DMX_PSN.callback, tracker=tracker)
DMX_PSN._instances[uuid].receiver.start()
DMX_PSN._data[uuid] = None
DMX_PSN._data[uuid] = [[],] * 10 # hardcoded to 10 slots
if bpy.app.timers.is_registered(DMX_PSN.run_render):
# we are already rendering
pass
Expand Down Expand Up @@ -62,10 +63,11 @@ def disable(tracker):
def get_data(tracker_uuid):
if tracker_uuid in DMX_PSN._data:
return DMX_PSN._data[tracker_uuid]
return []

@staticmethod
def set_data(tracker_uuid, data):
DMX_PSN._data[tracker_uuid] = data
def set_data(tracker_uuid, slot, data):
DMX_PSN._data[tracker_uuid][slot] = data

@staticmethod
def run_render():
Expand Down
41 changes: 22 additions & 19 deletions tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def onPsnEnable(self, context):
def add_tracker():
dmx = bpy.context.scene.dmx
new_tracker = dmx.trackers.add()
new_tracker["position"]=None
new_tracker["position"] = [[],] * 10 # hardcoded to 10 slots
new_tracker.uuid = str(uuid.uuid4())
new_id = len(dmx.trackers)
new_tracker.name = generate_tracker_name(new_id)
Expand Down Expand Up @@ -115,8 +115,9 @@ def remove_tracker(uuid):
for obj in fixture.objects:
if obj.name == "Target":
for constraint in obj.object.constraints:
if constraint.target.get("uuid", None) == uuid:
obj.object.constraints.remove(constraint)
if constraint.target is not None:
if constraint.target.get("uuid", None) == uuid:
obj.object.constraints.remove(constraint)

if tracker is not None:
if tracker.collection is not None:
Expand Down Expand Up @@ -148,23 +149,25 @@ def get_tracker(uuid):

def render(self, current_frame = None):
data = DMX_PSN.get_data(self.uuid)
if data is None:
return
if self["position"] is not None:
if list(self["position"]) == list(data):
for idx, slot_data in enumerate(data):
if idx > 10: # hardcoded number of PSN slots
return
x, y, z = data
self["position"] = list(data)
for obj in self.objects:
obj = obj.object
if x is not None:
obj.location.x = x
if y is not None:
obj.location.y = y
if z is not None:
obj.location.z = z
if current_frame:
obj.keyframe_insert(data_path="location", frame=current_frame)
if list(self["position"][idx]) == list(slot_data):
return

x, y, z = slot_data
self["position"][idx] = list(data)

for obj_idx, obj in enumerate(self.collection.objects):
if obj_idx == idx:
if x is not None:
obj.location.x = x
if y is not None:
obj.location.y = y
if z is not None:
obj.location.z = z
if current_frame:
obj.keyframe_insert(data_path="location", frame=current_frame)

def generate_tracker_name(new_id):
dmx = bpy.context.scene.dmx
Expand Down

0 comments on commit a1c918f

Please sign in to comment.