Ejemplo n.º 1
0
def send_collection_instance(client: Client, obj):
    if not obj.instance_collection:
        return
    instance_name = obj.name_full
    instanciated_collection = obj.instance_collection.name_full
    buffer = common.encode_string(instance_name) + common.encode_string(instanciated_collection)
    client.add_command(common.Command(common.MessageType.INSTANCE_COLLECTION, buffer, 0))
Ejemplo n.º 2
0
def get_camera_buffer(obj):
    cam = obj.data
    focal = cam.lens
    front_clip_plane = cam.clip_start
    far_clip_plane = cam.clip_end
    aperture = cam.dof.aperture_fstop
    sensor_fit_name = cam.sensor_fit
    sensor_fit = common.SensorFitMode.AUTO
    if sensor_fit_name == "AUTO":
        sensor_fit = common.SensorFitMode.AUTO
    elif sensor_fit_name == "HORIZONTAL":
        sensor_fit = common.SensorFitMode.HORIZONTAL
    elif sensor_fit_name == "VERTICAL":
        sensor_fit = common.SensorFitMode.VERTICAL
    sensor_width = cam.sensor_width
    sensor_height = cam.sensor_height

    path = get_object_path(obj)
    return (
        common.encode_string(path)
        + common.encode_string(obj.name_full)
        + common.encode_float(focal)
        + common.encode_float(front_clip_plane)
        + common.encode_float(far_clip_plane)
        + common.encode_float(aperture)
        + common.encode_int(sensor_fit.value)
        + common.encode_float(sensor_width)
        + common.encode_float(sensor_height)
    )
Ejemplo n.º 3
0
    def send_mesh(self, obj):
        logger.info("send_mesh %s", obj.name_full)
        mesh = obj.data
        mesh_name = self.get_mesh_name(mesh)
        path = self.get_object_path(obj)

        binary_buffer = common.encode_string(path) + common.encode_string(mesh_name)

        binary_buffer += mesh_api.encode_mesh(
            obj, get_mixer_prefs().send_base_meshes, get_mixer_prefs().send_baked_meshes
        )

        # For now include material slots in the same message, but maybe it should be a separated message
        # like Transform
        material_link_dict = {"OBJECT": 0, "DATA": 1}
        material_links = [material_link_dict[slot.link] for slot in obj.material_slots]
        assert len(material_links) == len(obj.data.materials)
        binary_buffer += struct.pack(f"{len(material_links)}I", *material_links)

        for slot in obj.material_slots:
            if slot.link == "DATA":
                binary_buffer += common.encode_string("")
            else:
                binary_buffer += common.encode_string(slot.material.name if slot.material is not None else "")

        self.add_command(common.Command(MessageType.MESH, binary_buffer, 0))
Ejemplo n.º 4
0
 def send_animation_buffer(self, obj_name, animation_data, channel_name, channel_index=-1):
     if not animation_data:
         return
     action = animation_data.action
     if not action:
         return
     for fcurve in action.fcurves:
         if fcurve.data_path == channel_name:
             if channel_index == -1 or fcurve.array_index == channel_index:
                 key_count = len(fcurve.keyframe_points)
                 times = []
                 values = []
                 for keyframe in fcurve.keyframe_points:
                     times.append(int(keyframe.co[0]))
                     values.append(keyframe.co[1])
                 buffer = (
                     common.encode_string(obj_name)
                     + common.encode_string(channel_name)
                     + common.encode_int(channel_index)
                     + common.int_to_bytes(key_count, 4)
                     + struct.pack(f"{len(times)}i", *times)
                     + struct.pack(f"{len(values)}f", *values)
                 )
                 self.add_command(common.Command(MessageType.CAMERA_ANIMATION, buffer, 0))
                 return
Ejemplo n.º 5
0
def soa_buffers(datablock_proxy: Optional[DatablockProxy]) -> List[bytes]:
    if datablock_proxy is None:
        # empty update, should not happen
        return [encode_int(0)]

    # Layout is
    #   number of AosProxy: 2
    #       soa path in datablock : ("vertices")
    #       number of SoaElement : 2
    #           element name: "co"
    #           array
    #           element name: "normals"
    #           array
    #       soa path in datablock : ("edges")
    #       number of SoaElement : 1
    #           element name: "vertices"
    #           array

    items: List[bytes] = []
    items.append(encode_int(len(datablock_proxy._soas)))
    for path, soa_proxies in datablock_proxy._soas.items():
        path_string = json.dumps(path)
        items.append(encode_string(path_string))
        items.append(encode_int(len(soa_proxies)))
        for element_name, soa_element in soa_proxies:
            if soa_element._array is not None:
                items.append(encode_string(element_name))
                items.append(encode_py_array(soa_element._array))
    return items
Ejemplo n.º 6
0
def send_add_object_to_collection(client: Client, collection_name, obj_name):
    logger.info("send_add_object_to_collection %s <- %s", collection_name,
                obj_name)
    buffer = common.encode_string(collection_name) + common.encode_string(
        obj_name)
    client.add_command(
        common.Command(common.MessageType.ADD_OBJECT_TO_COLLECTION, buffer, 0))
Ejemplo n.º 7
0
def get_light_buffer(obj):
    light = obj.data
    light_type_name = light.type
    light_type = common.LightType.SUN
    if light_type_name == "POINT":
        light_type = common.LightType.POINT
    elif light_type_name == "SPOT":
        light_type = common.LightType.SPOT
    elif light_type_name == "SUN":
        light_type = common.LightType.SUN
    elif light_type_name == "AREA":
        light_type = common.LightType.AREA
    else:
        return None
    color = light.color
    power = light.energy
    if bpy.context.scene.render.engine == "CYCLES":
        shadow = light.cycles.cast_shadow
    else:
        shadow = light.use_shadow

    spot_blend = 10.0
    spot_size = 0.0
    if light_type == common.LightType.SPOT:
        spot_size = light.spot_size
        spot_blend = light.spot_blend

    return (common.encode_string(get_object_path(obj)) +
            common.encode_string(light.name_full) +
            common.encode_int(light_type.value) + common.encode_int(shadow) +
            common.encode_color(color) + common.encode_float(power) +
            common.encode_float(spot_size) + common.encode_float(spot_blend))
Ejemplo n.º 8
0
def get_camera_buffer(obj):
    cam = obj.data
    focal = cam.lens
    front_clip_plane = cam.clip_start
    far_clip_plane = cam.clip_end
    dof_enabled = cam.dof.use_dof
    aperture = cam.dof.aperture_fstop
    colimator_name = cam.dof.focus_object.name_full if cam.dof.focus_object is not None else ""
    sensor_fit_name = cam.sensor_fit
    sensor_fit = common.SensorFitMode.AUTO
    if sensor_fit_name == "AUTO":
        sensor_fit = common.SensorFitMode.AUTO
    elif sensor_fit_name == "HORIZONTAL":
        sensor_fit = common.SensorFitMode.HORIZONTAL
    elif sensor_fit_name == "VERTICAL":
        sensor_fit = common.SensorFitMode.VERTICAL
    sensor_width = cam.sensor_width
    sensor_height = cam.sensor_height

    path = get_object_path(obj)
    return (common.encode_string(path) + common.encode_string(obj.name_full) +
            common.encode_float(focal) +
            common.encode_float(front_clip_plane) +
            common.encode_float(far_clip_plane) +
            common.encode_bool(dof_enabled) + common.encode_float(aperture) +
            common.encode_string(colimator_name) +
            common.encode_int(sensor_fit.value) +
            common.encode_float(sensor_width) +
            common.encode_float(sensor_height))
Ejemplo n.º 9
0
def send_remove_object_from_scene(client: Client, scene_name: str,
                                  object_name: str):
    logger.info("send_remove_object_from_scene %s <- %s", scene_name,
                object_name)
    buffer = common.encode_string(scene_name) + common.encode_string(
        object_name)
    client.add_command(
        common.Command(common.MessageType.REMOVE_OBJECT_FROM_SCENE, buffer, 0))
Ejemplo n.º 10
0
def send_remove_object_from_collection(client: Client, collection_name,
                                       obj_name):
    logger.info("send_remove_object_from_collection %s <- %s", collection_name,
                obj_name)
    buffer = common.encode_string(collection_name) + common.encode_string(
        obj_name)
    client.add_command(
        common.Command(common.MessageType.REMOVE_OBJECT_FROM_COLLECTION,
                       buffer, 0))
Ejemplo n.º 11
0
def send_data_removals(removals: RemovalChangeset):
    if not share_data.use_experimental_sync():
        return

    for uuid, _, debug_info in removals:
        logger.info("send_removal: %s (%s)", uuid, debug_info)
        buffer = encode_string(uuid) + encode_string(debug_info)
        command = Command(MessageType.BLENDER_DATA_REMOVE, buffer, 0)
        share_data.client.add_command(command)
Ejemplo n.º 12
0
def send_add_collection_to_scene(client: Client, scene_name: str,
                                 collection_name: str):
    logger.info("send_add_collection_to_scene %s <- %s", scene_name,
                collection_name)

    buffer = common.encode_string(scene_name) + common.encode_string(
        collection_name)
    client.add_command(
        common.Command(common.MessageType.ADD_COLLECTION_TO_SCENE, buffer, 0))
Ejemplo n.º 13
0
def send_remove_collection_from_scene(client: Client, scene_name: str,
                                      collection_name: str):
    logger.info("send_remove_collection_from_scene %s <- %s", scene_name,
                collection_name)

    buffer = common.encode_string(scene_name) + common.encode_string(
        collection_name)
    client.add_command(
        common.Command(common.MessageType.REMOVE_COLLECTION_FROM_SCENE, buffer,
                       0))
Ejemplo n.º 14
0
def send_scene():
    get_state()
    buffer = common.encode_int(len(share_data.shot_manager.shots))
    for s in share_data.shot_manager.shots:
        buffer += (common.encode_string(s.name) +
                   common.encode_string(s.camera_name) +
                   common.encode_int(s.start) + common.encode_int(s.end) +
                   common.encode_bool(s.enabled))
    share_data.client.add_command(
        common.Command(common.MessageType.SHOT_MANAGER_CONTENT, buffer, 0))
Ejemplo n.º 15
0
def send_data_renames(renames: RenameChangeset):
    if not share_data.use_experimental_sync():
        return

    for uuid, new_name, debug_info in renames:
        logger.info("send_rename: %s (%s) into %s", uuid, debug_info, new_name)
        buffer = common.encode_string(uuid) + common.encode_string(
            new_name) + common.encode_string(debug_info)
        command = common.Command(common.MessageType.BLENDER_DATA_RENAME,
                                 buffer, 0)
        share_data.client.add_command(command)
Ejemplo n.º 16
0
def send_data_removals(removals: List[Tuple[str, str]]):
    if not share_data.use_experimental_sync():
        return

    for collection_name, key in removals:
        logger.info("send_removal: %s[%s]", collection_name, key)
        buffer = common.encode_string(collection_name) + common.encode_string(
            key)
        command = common.Command(common.MessageType.BLENDER_DATA_REMOVE,
                                 buffer, 0)
        share_data.client.add_command(command)
Ejemplo n.º 17
0
 def send_camera_attributes(self, obj):
     buffer = (common.encode_string(obj.name_full) +
               common.encode_float(obj.data.lens) +
               common.encode_float(obj.data.dof.aperture_fstop) +
               common.encode_float(obj.data.dof.focus_distance))
     self.add_command(
         common.Command(MessageType.CAMERA_ATTRIBUTES, buffer, 0))
Ejemplo n.º 18
0
def send_data_updates(updates: List[BpyIDProxy]):
    if not share_data.use_experimental_sync():
        return
    if not updates:
        return
    codec = Codec()
    for proxy in updates:
        # We send an ID, so we need to make sure that it includes a bp.data collection name
        # and the associated key
        try:
            collection_name, key = blenddata_path(proxy)
        except InvalidPath:
            logger.error("... update ignored")
            continue

        logger.info("send_data_update %s[%s]", collection_name, key)

        try:
            encoded_proxy = codec.encode(proxy)
        except InvalidPath:
            logger.error("send_update: Exception :")
            log_traceback(logger.error)
            logger.error(
                f"while processing bpy.data.{collection_name}[{key}]:")

        # For BpyIdProxy, the target is encoded in the proxy._blenddata_path
        buffer = common.encode_string(encoded_proxy)
        command = common.Command(common.MessageType.BLENDER_DATA_UPDATE,
                                 buffer, 0)
        share_data.client.add_command(command)
Ejemplo n.º 19
0
 def send_texture_data(self, path, data):
     name_buffer = common.encode_string(path)
     self.textures.add(path)
     self.add_command(
         common.Command(MessageType.TEXTURE,
                        name_buffer + common.encode_int(len(data)) + data,
                        0))
Ejemplo n.º 20
0
    def __init__(self, server: Server, room_name: str, creator: Connection):
        self.name = room_name
        self.keep_open = False  # Should the room remain open when no more clients are inside ?
        self.byte_size = 0
        self.joinable = False  # A room becomes joinable when its first client has send all the initial content

        self.custom_attributes: Dict[str, Any] = {
        }  # custom attributes are used between clients, but not by the server

        self._commands: List[common.Command] = []

        self._commands_mutex: threading.RLock = threading.RLock()
        self._connections: List[Connection] = [creator]

        self.join_count: int = 0
        # this is used to ensure a room cannot be deleted while clients are joining (creator is not considered to be joining)
        # Server is responsible of increasing / decreasing join_count, with mutex protection

        creator.room = self
        creator.send_command(
            common.Command(common.MessageType.JOIN_ROOM,
                           common.encode_string(self.name)))
        creator.send_command(
            common.Command(common.MessageType.CONTENT)
        )  # self.joinable will be set to true by creator later
Ejemplo n.º 21
0
    def grab(self, host, port, room_name: str):
        with Client(host, port) as client:
            client.join_room(room_name)

            attempts_max = 20
            attempts = 0
            try:
                while attempts < attempts_max:
                    received_commands = client.fetch_incoming_commands()

                    attempts += 1
                    time.sleep(0.01)

                    for command in received_commands:
                        attempts = 0
                        if command.type <= MessageType.COMMAND:
                            continue
                        # Ignore command serial Id, that may not match
                        command.id = 0
                        self.streams.data[command.type].append(command.data)
            except ClientDisconnectedException:
                print("Grabber: disconnected before received command stream.",
                      file=sys.stderr)

            client.send_command(
                Command(MessageType.SET_ROOM_KEEP_OPEN,
                        encode_string(room_name) + encode_bool(False)))
            client.send_command(
                Command(MessageType.LEAVE_ROOM, room_name.encode("utf8")))

            if not client.wait(MessageType.LEAVE_ROOM):
                print("Grabber: disconnected before receiving LEAVE_ROOM.",
                      file=sys.stderr)
Ejemplo n.º 22
0
def send_grease_pencil_layer(layer, name):
    buffer = common.encode_string(name)
    buffer += common.encode_bool(layer.hide)
    buffer += common.encode_int(len(layer.frames))
    for frame in layer.frames:
        buffer += send_grease_pencil_frame(frame)
    return buffer
Ejemplo n.º 23
0
 def send_light_attributes(self, obj):
     buffer = (
         common.encode_string(obj.name_full)
         + common.encode_float(obj.data.energy)
         + common.encode_color(obj.data.color)
     )
     self.add_command(common.Command(MessageType.LIGHT_ATTRIBUTES, buffer, 0))
Ejemplo n.º 24
0
 def join_room(
     self,
     room_name: str,
     blender_version: str,
     mixer_version: str,
     ignore_version_check: bool,
     generic_protocol: bool,
 ):
     name = common.encode_string(room_name)
     bl_version = common.encode_string(blender_version)
     mix_version = common.encode_string(mixer_version)
     version_check = common.encode_bool(ignore_version_check)
     protocol = common.encode_bool(generic_protocol)
     return self.send_command(
         common.Command(
             common.MessageType.JOIN_ROOM,
             name + bl_version + mix_version + version_check + protocol, 0))
Ejemplo n.º 25
0
 def get_transform_buffer(self, obj):
     path = self.get_object_path(obj)
     return (
         common.encode_string(path)
         + common.encode_matrix(obj.matrix_parent_inverse)
         + common.encode_matrix(obj.matrix_basis)
         + common.encode_matrix(obj.matrix_local)
     )
Ejemplo n.º 26
0
    def encode(datablock_proxy: DatablockProxy) -> bytes:
        media_desc = getattr(datablock_proxy, "_media", None)
        if media_desc is None:
            return b""

        path, bytes_ = media_desc
        items = [encode_string(path), bytes_]
        return b"".join(items)
Ejemplo n.º 27
0
def send_media_creations(proxy: DatablockProxy):
    media_desc = getattr(proxy, "_media", None)
    if media_desc is None:
        return

    path, bytes_ = media_desc
    items = [encode_string(path), bytes_]
    command = Command(MessageType.BLENDER_DATA_MEDIA, b"".join(items), 0)
    share_data.client.add_command(command)
Ejemplo n.º 28
0
def send_object_visibility(client: Client, object_: bpy.types.Object):
    logger.debug("send_object_visibility %s", object_.name_full)
    buffer = (common.encode_string(object_.name_full) +
              common.encode_bool(object_.hide_viewport) +
              common.encode_bool(object_.hide_select) +
              common.encode_bool(object_.hide_render) +
              common.encode_bool(object_.hide_get()))
    client.add_command(
        common.Command(common.MessageType.OBJECT_VISIBILITY, buffer, 0))
Ejemplo n.º 29
0
def send_grease_pencil_mesh(client: Client, obj):
    grease_pencil = obj.data
    buffer = common.encode_string(grease_pencil.name_full)

    buffer += common.encode_int(len(grease_pencil.materials))
    for material in grease_pencil.materials:
        if not material:
            material_name = "Default"
        else:
            material_name = material.name_full
        buffer += common.encode_string(material_name)

    buffer += common.encode_int(len(grease_pencil.layers))
    for name, layer in grease_pencil.layers.items():
        buffer += send_grease_pencil_layer(layer, name)

    client.add_command(common.Command(common.MessageType.GREASE_PENCIL_MESH, buffer, 0))

    send_grease_pencil_time_offset(client, obj)
Ejemplo n.º 30
0
def encode_arrays(datablock_proxy: DatablockProxy) -> List[bytes]:
    if not hasattr(datablock_proxy, "_arrays"):
        return [encode_int(0)]

    items = []
    items.append(encode_int(len(datablock_proxy._arrays)))
    for array_group_name, arrays in datablock_proxy._arrays.items():
        # for vertex groups, _arrays layout is
        # { "vertex_groups: [
        #       ([0, "i"], indices_array_of_vertex_group_0),
        #       ([0, "w"], weights_array_of_vertex_group_0),
        #       ...
        # ]}
        items.append(encode_string(array_group_name))
        items.append(encode_int(len(arrays)))
        for key, array_ in arrays:
            key_string = json.dumps(key)
            items.append(encode_string(key_string))
            items.append(encode_py_array(array_))
    return items