From 8f970911183a59992f897e0f9c1206d46625a74c Mon Sep 17 00:00:00 2001 From: Swann Martinez Date: Mon, 4 Nov 2019 16:16:07 +0100 Subject: [PATCH 1/6] fix: connection close on new file opening #21 --- multi_user/operators.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/multi_user/operators.py b/multi_user/operators.py index 78ee645..b07ca1e 100644 --- a/multi_user/operators.py +++ b/multi_user/operators.py @@ -20,6 +20,10 @@ from . import bl_types, delayable, environment, presence, ui, utils from .libs.replication.replication.data import ReplicatedDataFactory from .libs.replication.replication.exception import NonAuthorizedOperationError from .libs.replication.replication.interface import Session +from .libs.replication.replication.constants import ( + STATE_ACTIVE, + STATE_INITIAL, + STATE_SYNCING) logger = logging.getLogger(__name__) logger.setLevel(logging.ERROR) @@ -335,13 +339,21 @@ classes = ( SessionApply, SessionCommit, ) +@persistent +def load_pre_handler(dummy): + global client + if client and client.state in [STATE_ACTIVE, STATE_SYNCING]: + bpy.ops.session.stop() + def register(): from bpy.utils import register_class for cls in classes: register_class(cls) + bpy.app.handlers.load_pre.append(load_pre_handler) + def unregister(): global client @@ -352,6 +364,8 @@ def unregister(): from bpy.utils import unregister_class for cls in reversed(classes): unregister_class(cls) + + bpy.app.handlers.load_pre.remove(load_pre_handler) if __name__ == "__main__": register() From 345a5d55e71138a4df611128857456f2aacbf65f Mon Sep 17 00:00:00 2001 From: Swann Martinez Date: Mon, 4 Nov 2019 16:42:18 +0100 Subject: [PATCH 2/6] fix: AttributeError in presence --- multi_user/presence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/multi_user/presence.py b/multi_user/presence.py index b42fed7..eb04970 100644 --- a/multi_user/presence.py +++ b/multi_user/presence.py @@ -129,7 +129,7 @@ class User(): def update_presence(self, context): global renderer - if 'renderer' in globals(): + if 'renderer' in globals() and hasattr(renderer, 'run'): if self.enable_presence: renderer.run() else: From cfadc91299334fa84dacef45ab1e974c9c83fc46 Mon Sep 17 00:00:00 2001 From: Swann Martinez Date: Mon, 4 Nov 2019 17:55:41 +0100 Subject: [PATCH 3/6] feat: progress on unsupported types #21 --- multi_user/bl_types/__init__.py | 5 ++- multi_user/bl_types/bl_curve.py | 7 ++++ multi_user/bl_types/bl_lattice.py | 54 ++++++++++++++++++++++++++++ multi_user/bl_types/bl_lightprobe.py | 49 +++++++++++++++++++++++++ multi_user/bl_types/bl_object.py | 8 +++++ multi_user/bl_types/bl_speaker.py | 50 ++++++++++++++++++++++++++ 6 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 multi_user/bl_types/bl_lattice.py create mode 100644 multi_user/bl_types/bl_lightprobe.py create mode 100644 multi_user/bl_types/bl_speaker.py diff --git a/multi_user/bl_types/__init__.py b/multi_user/bl_types/__init__.py index 6e1f71c..7f0991a 100644 --- a/multi_user/bl_types/__init__.py +++ b/multi_user/bl_types/__init__.py @@ -14,7 +14,10 @@ __all__ = [ 'bl_armature', 'bl_action', 'bl_world', - 'bl_metaball' + 'bl_metaball', + 'bl_lattice', + 'bl_lightprobe', + 'bl_speaker' ] # Order here defines execution order from . import * diff --git a/multi_user/bl_types/bl_curve.py b/multi_user/bl_types/bl_curve.py index 0b73eb6..1957caf 100644 --- a/multi_user/bl_types/bl_curve.py +++ b/multi_user/bl_types/bl_curve.py @@ -43,6 +43,13 @@ class BlCurve(BlDatablock): spline_data['bezier_points'] = dumper.dump(spline.bezier_points) spline_data['type'] = dumper.dump(spline.type) data['splines'][index] = spline_data + + if isinstance(pointer,'TextCurve'): + data['type'] = 'TEXT' + if isinstance(pointer,'SurfaceCurve'): + data['type'] = 'SURFACE' + if isinstance(pointer,'TextCurve'): + data['type'] = 'CURVE' return data def resolve(self): diff --git a/multi_user/bl_types/bl_lattice.py b/multi_user/bl_types/bl_lattice.py new file mode 100644 index 0000000..2a50908 --- /dev/null +++ b/multi_user/bl_types/bl_lattice.py @@ -0,0 +1,54 @@ +import bpy +import mathutils + +from .. import utils +from .bl_datablock import BlDatablock + + +class BlLattice(BlDatablock): + def load(self, data, target): + utils.dump_anything.load(target, data) + + for point in data['points']: + utils.dump_anything.load(target.points[point], data["points"][point]) + def construct(self, data): + return bpy.data.lattices.new(data["name"]) + + def dump(self, pointer=None): + assert(pointer) + + dumper = utils.dump_anything.Dumper() + dumper.depth = 3 + dumper.include_filter = [ + "name", + 'type', + 'points_u', + 'points_v', + 'points_w', + 'interpolation_type_u', + 'interpolation_type_v', + 'interpolation_type_w', + 'use_outside', + 'points', + 'co', + 'weight_softbody', + 'co_deform' + ] + data = dumper.dump(pointer) + + return data + + def resolve(self): + self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.lattices) + + def is_valid(self): + return bpy.data.lattices.get(self.data['name']) + + +bl_id = "lattices" +bl_class = bpy.types.Lattice +bl_rep_class = BlLattice +bl_delay_refresh = 1 +bl_delay_apply = 1 +bl_automatic_push = True +bl_icon = 'LATTICE_DATA' diff --git a/multi_user/bl_types/bl_lightprobe.py b/multi_user/bl_types/bl_lightprobe.py new file mode 100644 index 0000000..69cbb5b --- /dev/null +++ b/multi_user/bl_types/bl_lightprobe.py @@ -0,0 +1,49 @@ +import bpy +import mathutils + +from .. import utils +from .bl_datablock import BlDatablock + + +class BlLightProbe(BlDatablock): + def load(self, data, target): + utils.dump_anything.load(target, data) + + def construct(self, data): + return bpy.data.lightprobes.new(data["name"]) + + def dump(self, pointer=None): + assert(pointer) + + dumper = utils.dump_anything.Dumper() + dumper.depth = 1 + dumper.include_filter = [ + "name", + 'influence_type', + 'influence_distance', + 'falloff', + 'intensity', + 'clip_start', + 'clip_end', + 'visibility_collection', + 'use_custom_parallax', + 'parallax_type', + 'parallax_distance', + ] + + return dumper.dump(pointer) + + def resolve(self): + self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.lattices) + + def is_valid(self): + return bpy.data.lattices.get(self.data['name']) + + +bl_id = "lightprobes" +bl_class = bpy.types.LightProbe +bl_rep_class = BlLightProbe +bl_delay_refresh = 1 +bl_delay_apply = 1 +bl_automatic_push = True +bl_icon = 'LIGHTPROBE_GRID' diff --git a/multi_user/bl_types/bl_object.py b/multi_user/bl_types/bl_object.py index 6b0a062..d3af6a2 100644 --- a/multi_user/bl_types/bl_object.py +++ b/multi_user/bl_types/bl_object.py @@ -37,6 +37,14 @@ class BlObject(BlDatablock): pointer = bpy.data.grease_pencils[data["data"]] elif data["data"] in bpy.data.curves.keys(): pointer = bpy.data.curves[data["data"]] + elif data["data"] in bpy.data.lattices.keys(): + pointer = bpy.data.lattices[data["data"]] + elif data["data"] in bpy.data.speakers.keys(): + pointer = bpy.data.speakers[data["data"]] + elif data["data"] in bpy.data.lightprobes.keys(): + pass + # bpy need to support correct lightprobe creation from python + # pointer = bpy.data.lightprobes[data["data"]] instance = bpy.data.objects.new(data["name"], pointer) instance.uuid = self.uuid diff --git a/multi_user/bl_types/bl_speaker.py b/multi_user/bl_types/bl_speaker.py new file mode 100644 index 0000000..537b60f --- /dev/null +++ b/multi_user/bl_types/bl_speaker.py @@ -0,0 +1,50 @@ +import bpy +import mathutils + +from .. import utils +from .bl_datablock import BlDatablock + + +class BlSpeaker(BlDatablock): + def load(self, data, target): + utils.dump_anything.load(target, data) + + def construct(self, data): + return bpy.data.speakers.new(data["name"]) + + def dump(self, pointer=None): + assert(pointer) + + dumper = utils.dump_anything.Dumper() + dumper.depth = 1 + dumper.include_filter = [ + "muted", + 'volume', + 'name', + 'pitch', + 'volume_min', + 'volume_max', + 'attenuation', + 'distance_max', + 'distance_reference', + 'cone_angle_outer', + 'cone_angle_inner', + 'cone_volume_outer' + ] + + return dumper.dump(pointer) + + def resolve(self): + self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.lattices) + + def is_valid(self): + return bpy.data.lattices.get(self.data['name']) + + +bl_id = "speakers" +bl_class = bpy.types.Speaker +bl_rep_class = BlSpeaker +bl_delay_refresh = 1 +bl_delay_apply = 1 +bl_automatic_push = True +bl_icon = 'SPEAKER' From ebe6af8082e958c3db36f31f5af3af1b2258b71a Mon Sep 17 00:00:00 2001 From: Swann Martinez Date: Mon, 18 Nov 2019 18:14:21 +0100 Subject: [PATCH 4/6] feat: selection tests for non visible objects related to #34 --- multi_user/libs/replication | 2 +- multi_user/presence.py | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/multi_user/libs/replication b/multi_user/libs/replication index f4bbe3b..de24d35 160000 --- a/multi_user/libs/replication +++ b/multi_user/libs/replication @@ -1 +1 @@ -Subproject commit f4bbe3b897c98ed7749a99dad12a1789d1fa1cb6 +Subproject commit de24d35afeef583802eca1fe002b3efc171a7ffe diff --git a/multi_user/presence.py b/multi_user/presence.py index eb04970..7f9cc0c 100644 --- a/multi_user/presence.py +++ b/multi_user/presence.py @@ -56,6 +56,18 @@ def get_target_far(region, rv3d, coord, distance): return [target.x, target.y, target.z] +def get_default_bbox(obj, radius): + coords = [ + (-radius, -radius, -radius), (+radius, -radius, -radius), + (-radius, +radius, -radius), (+radius, +radius, -radius), + (-radius, -radius, +radius), (+radius, -radius, +radius), + (-radius, +radius, +radius), (+radius, +radius, +radius)] + + base = obj.matrix_world + bbox_corners = [base @ mathutils.Vector(corner) for corner in coords] + + return [(point.x, point.y, point.z) + for point in bbox_corners] def get_client_cam_points(): area, region, rv3d = view3d_find() @@ -211,11 +223,7 @@ class DrawFactory(object): for select_ob in client_selection: drawable_key = "{}_select_{}".format(client_uuid, select_ob) - indices = ( - (0, 1), (1, 2), (2, 3), (0, 3), - (4, 5), (5, 6), (6, 7), (4, 7), - (0, 4), (1, 5), (2, 6), (3, 7) - ) + ob = utils.find_from_attr("uuid",select_ob,bpy.data.objects) if not ob: return @@ -235,12 +243,28 @@ class DrawFactory(object): indices) if ob.type == 'MESH': + indices = ( + (0, 1), (1, 2), (2, 3), (0, 3), + (4, 5), (5, 6), (6, 7), (4, 7), + (0, 4), (1, 5), (2, 6), (3, 7)) + self.append_3d_item( drawable_key, client_color, get_bb_coords_from_obj(ob), indices) - + else: + indices = ( + (0, 1), (0, 2), (1, 3), (2, 3), + (4, 5), (4, 6), (5, 7), (6, 7), + (0, 4), (1, 5), (2, 6), (3, 7)) + + self.append_3d_item( + drawable_key, + client_color, + get_default_bbox(ob, ob.scale.x), + indices) + def append_3d_item(self,key,color, coords, indices): shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') color = color From 43eeb8299e7cad8c9deda0e4de0093ef524caf95 Mon Sep 17 00:00:00 2001 From: Swann Martinez Date: Thu, 21 Nov 2019 17:14:31 +0100 Subject: [PATCH 5/6] feat: smooth overlay lines fix: selection flush None object error related to #34. --- multi_user/presence.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/multi_user/presence.py b/multi_user/presence.py index 7f9cc0c..95c5479 100644 --- a/multi_user/presence.py +++ b/multi_user/presence.py @@ -193,7 +193,7 @@ class DrawFactory(object): self.d3d_items.clear() self.d2d_items.clear() - def flush_selection(self, user): + def flush_selection(self, user=None): key_to_remove = [] select_key = "{}_select".format(user) if user else "select" for k in self.d3d_items.keys(): @@ -224,19 +224,17 @@ class DrawFactory(object): for select_ob in client_selection: drawable_key = "{}_select_{}".format(client_uuid, select_ob) - ob = utils.find_from_attr("uuid",select_ob,bpy.data.objects) + ob = utils.find_from_attr("uuid", select_ob, bpy.data.objects) if not ob: return - item_to_draw = [] if ob.type == 'EMPTY': - # Child case - + # TODO: Child case # Collection instance case if ob.instance_collection: for obj in ob.instance_collection.objects: if obj.type == 'MESH': - self.append_3d_item( + self.append_3d_item( drawable_key, client_color, get_bb_coords_from_obj(obj, parent=ob), @@ -301,6 +299,9 @@ class DrawFactory(object): def draw3d_callback(self): bgl.glLineWidth(1.5) bgl.glEnable(bgl.GL_DEPTH_TEST) + bgl.glEnable(bgl.GL_BLEND) + bgl.glEnable(bgl.GL_LINE_SMOOTH) + try: for shader, batch, color in self.d3d_items.values(): shader.bind() From af923feecd4b9df065ea779a702f2a0713841a2f Mon Sep 17 00:00:00 2001 From: Swann Martinez Date: Fri, 22 Nov 2019 18:51:24 +0100 Subject: [PATCH 6/6] feat: metaball selection drawing related to #34 --- multi_user/presence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/multi_user/presence.py b/multi_user/presence.py index 95c5479..3c13e1d 100644 --- a/multi_user/presence.py +++ b/multi_user/presence.py @@ -240,7 +240,7 @@ class DrawFactory(object): get_bb_coords_from_obj(obj, parent=ob), indices) - if ob.type == 'MESH': + if ob.type in ['MESH','META']: indices = ( (0, 1), (1, 2), (2, 3), (0, 3), (4, 5), (5, 6), (6, 7), (4, 7),