feat: resolve refactoring, ground work to resolve undo errors

Related to #32, Undo errors
This commit is contained in:
Swann Martinez 2020-01-13 18:51:31 +01:00
parent 28ca489fc3
commit f55319c453
No known key found for this signature in database
GPG Key ID: 414CCAFD8DA720E1
22 changed files with 195 additions and 245 deletions

View File

@ -38,16 +38,19 @@ logger.setLevel(logging.ERROR)
def generate_supported_types():
stype_dict = {'supported_types':{}}
for type in bl_types.types_to_register():
_type = getattr(bl_types, type)
props = {}
props['bl_delay_refresh']=_type.bl_delay_refresh
props['bl_delay_apply']=_type.bl_delay_apply
props['use_as_filter'] = False
props['icon'] = _type.bl_icon
props['auto_push']=_type.bl_automatic_push
props['bl_name']=_type.bl_id
type_module = getattr(bl_types, type)
type_impl_name = "Bl{}".format(type.split('_')[1].capitalize())
type_module_class = getattr(type_module, type_impl_name)
stype_dict['supported_types'][_type.bl_rep_class.__name__] = props
props = {}
props['bl_delay_refresh']=type_module_class.bl_delay_refresh
props['bl_delay_apply']=type_module_class.bl_delay_apply
props['use_as_filter'] = False
props['icon'] = type_module_class.bl_icon
props['auto_push']=type_module_class.bl_automatic_push
props['bl_name']=type_module_class.bl_id
stype_dict['supported_types'][type_impl_name] = props
return stype_dict

View File

@ -7,7 +7,13 @@ from .bl_datablock import BlDatablock
# WIP
class BlAction(BlDatablock):
bl_id = "actions"
bl_class = bpy.types.Action
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'ACTION_TWEAK'
def construct(self, data):
return bpy.data.actions.new(data["name"])
@ -108,18 +114,8 @@ class BlAction(BlDatablock):
data["fcurves"].append(fc)
return data
def resolve(self):
assert(self.data)
self.pointer = bpy.data.actions.get(self.data['name'])
def is_valid(self):
return bpy.data.actions.get(self.data['name'])
bl_id = "actions"
bl_class = bpy.types.Action
bl_rep_class = BlAction
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'ACTION_TWEAK'

View File

@ -10,6 +10,13 @@ from .bl_datablock import BlDatablock
class BlArmature(BlDatablock):
bl_id = "armatures"
bl_class = bpy.types.Armature
bl_delay_refresh = 1
bl_delay_apply = 0
bl_automatic_push = True
bl_icon = 'ARMATURE_DATA'
def construct(self, data):
return bpy.data.armatures.new(data["name"])
@ -114,18 +121,5 @@ class BlArmature(BlDatablock):
item.name for item in container_users if isinstance(item, bpy.types.Scene)]
return data
def resolve(self):
assert(self.data)
self.pointer = bpy.data.armatures.get(self.data['name'])
def is_valid(self):
return bpy.data.armatures.get(self.data['name'])
bl_id = "armatures"
bl_class = bpy.types.Armature
bl_rep_class = BlArmature
bl_delay_refresh = 1
bl_delay_apply = 0
bl_automatic_push = True
bl_icon = 'ARMATURE_DATA'

View File

@ -6,6 +6,13 @@ from .bl_datablock import BlDatablock
class BlCamera(BlDatablock):
bl_id = "cameras"
bl_class = bpy.types.Camera
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'CAMERA_DATA'
def load(self, data, target):
utils.dump_anything.load(target, data)
@ -45,17 +52,5 @@ class BlCamera(BlDatablock):
]
return dumper.dump(pointer)
def resolve(self):
self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.cameras)
def is_valid(self):
return bpy.data.cameras.get(self.data['name'])
bl_id = "cameras"
bl_class = bpy.types.Camera
bl_rep_class = BlCamera
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'CAMERA_DATA'

View File

@ -6,6 +6,13 @@ from .bl_datablock import BlDatablock
class BlCollection(BlDatablock):
bl_id = "collections"
bl_icon = 'FILE_FOLDER'
bl_class = bpy.types.Collection
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
def construct(self, data):
if self.is_library:
with bpy.data.libraries.load(filepath=bpy.data.libraries[self.data['library']].filepath, link=True) as (sourceData, targetData):
@ -68,19 +75,8 @@ class BlCollection(BlDatablock):
data['children'] = collection_children
# dumper = utils.dump_anything.Dumper()
# dumper.depth = 2
# dumper.include_filter = ['name','objects', 'children']
# return dumper.dump(pointer)
return data
def resolve(self):
self.pointer = utils.find_from_attr(
'uuid',
self.uuid,
bpy.data.collections)
def resolve_dependencies(self):
deps = []
@ -94,11 +90,3 @@ class BlCollection(BlDatablock):
def is_valid(self):
return bpy.data.collections.get(self.data['name'])
bl_id = "collections"
bl_icon = 'FILE_FOLDER'
bl_class = bpy.types.Collection
bl_rep_class = BlCollection
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True

View File

@ -5,6 +5,13 @@ from .. import utils
from .bl_datablock import BlDatablock
class BlCurve(BlDatablock):
bl_id = "curves"
bl_class = bpy.types.Curve
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'CURVE_DATA'
def construct(self, data):
return bpy.data.curves.new(data["name"], 'CURVE')
@ -52,15 +59,5 @@ class BlCurve(BlDatablock):
data['type'] = 'CURVE'
return data
def resolve(self):
self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.curves)
def is_valid(self):
return bpy.data.curves.get(self.data['name'])
bl_id = "curves"
bl_class = bpy.types.Curve
bl_rep_class = BlCurve
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'CURVE_DATA'

View File

@ -26,15 +26,17 @@ def load_driver(target_datablock, src_driver):
# Variables
for src_variable in src_driver_data['variables']:
src_var_data = src_driver_data['variables'][src_variable]
src_var_data = src_driver_data['variables'][src_variable]
new_var = new_driver.driver.variables.new()
new_var.name = src_var_data['name']
new_var.type = src_var_data['type']
for src_target in src_var_data['targets']:
src_target_data = src_var_data['targets'][src_target]
new_var.targets[src_target].id = utils.resolve_from_id(src_target_data['id'],src_target_data['id_type'])
utils.dump_anything.load(new_var.targets[src_target], src_target_data)
new_var.targets[src_target].id = utils.resolve_from_id(
src_target_data['id'], src_target_data['id_type'])
utils.dump_anything.load(
new_var.targets[src_target], src_target_data)
# Fcurve
new_fcurve = new_driver.keyframe_points
@ -45,9 +47,22 @@ def load_driver(target_datablock, src_driver):
for index, src_point in enumerate(src_driver['keyframe_points']):
new_point = new_fcurve[index]
utils.dump_anything.load(new_point, src_driver['keyframe_points'][src_point])
utils.dump_anything.load(
new_point, src_driver['keyframe_points'][src_point])
class BlDatablock(ReplicatedDatablock):
"""BlDatablock
bl_id : blender internal storage identifier
bl_class : blender internal type
bl_delay_refresh : refresh rate in second for observers
bl_delay_apply : refresh rate in sec for apply
bl_automatic_push : boolean
bl_icon : type icon (blender icon name)
"""
bl_id = "scenes"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
pointer = kwargs.get('pointer', None)
@ -91,6 +106,16 @@ class BlDatablock(ReplicatedDatablock):
def resolve_dependencies_library(self):
return [self.pointer.library]
def resolve(self):
self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.scenes)
if not self.pointer:
self.pointer = getattr(bpy.data,self.bl_id).get(self.data['name'])
print(self.data['name'])
if self.pointer:
setattr(self.pointer, 'uuid', self.uuid)
def dump(self, pointer=None):
data = {}
if utils.has_action(pointer):
@ -99,9 +124,10 @@ class BlDatablock(ReplicatedDatablock):
data['animation_data'] = dumper.dump(pointer.animation_data)
if utils.has_driver(pointer):
dumped_drivers = {'animation_data':{'drivers': []}}
dumped_drivers = {'animation_data': {'drivers': []}}
for driver in pointer.animation_data.drivers:
dumped_drivers['animation_data']['drivers'].append(dump_driver(driver))
dumped_drivers['animation_data']['drivers'].append(
dump_driver(driver))
data.update(dumped_drivers)
data.update(self.dump_implementation(data, pointer=pointer))
@ -124,7 +150,7 @@ class BlDatablock(ReplicatedDatablock):
for driver in data['animation_data']['drivers']:
load_driver(target, driver)
if 'action' in data['animation_data']:
if 'action' in data['animation_data']:
target.animation_data.action = bpy.data.actions[data['animation_data']['action']]
self.load_implementation(data, target)

View File

@ -34,6 +34,13 @@ def load_gpencil_layer(target=None, data=None, create=False):
class BlGpencil(BlDatablock):
bl_id = "grease_pencils"
bl_class = bpy.types.GreasePencil
bl_delay_refresh = 5
bl_delay_apply = 5
bl_automatic_push = True
bl_icon = 'GREASEPENCIL'
def construct(self, data):
return bpy.data.grease_pencils.new(data["name"])
@ -64,9 +71,6 @@ class BlGpencil(BlDatablock):
pointer, ['layers'], 9, data)
return data
def resolve(self):
self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.grease_pencils)
def resolve_dependencies(self):
deps = []
@ -76,12 +80,4 @@ class BlGpencil(BlDatablock):
return deps
def is_valid(self):
return bpy.data.grease_pencils.get(self.data['name'])
bl_id = "grease_pencils"
bl_class = bpy.types.GreasePencil
bl_rep_class = BlGpencil
bl_delay_refresh = 5
bl_delay_apply = 5
bl_automatic_push = True
bl_icon = 'GREASEPENCIL'
return bpy.data.grease_pencils.get(self.data['name'])

View File

@ -24,6 +24,13 @@ def dump_image(image):
return pixels
class BlImage(BlDatablock):
bl_id = "images"
bl_class = bpy.types.Image
bl_delay_refresh = 0
bl_delay_apply = 0
bl_automatic_push = False
bl_icon = 'IMAGE_DATA'
def construct(self, data):
return bpy.data.images.new(
name=data['name'],
@ -57,19 +64,9 @@ class BlImage(BlDatablock):
2,
data)
return data
def resolve(self):
self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.images)
def diff(self):
return False
def is_valid(self):
return bpy.data.images.get(self.data['name'])
bl_id = "images"
bl_class = bpy.types.Image
bl_rep_class = BlImage
bl_delay_refresh = 0
bl_delay_apply = 0
bl_automatic_push = False
bl_icon = 'IMAGE_DATA'

View File

@ -6,6 +6,13 @@ from .bl_datablock import BlDatablock
class BlLattice(BlDatablock):
bl_id = "lattices"
bl_class = bpy.types.Lattice
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'LATTICE_DATA'
def load(self, data, target):
utils.dump_anything.load(target, data)
@ -38,17 +45,8 @@ class BlLattice(BlDatablock):
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'

View File

@ -6,6 +6,13 @@ from .bl_datablock import BlDatablock
class BlLibrary(BlDatablock):
bl_id = "libraries"
bl_class = bpy.types.Library
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'LIBRARY_DATA_DIRECT'
def construct(self, data):
with bpy.data.libraries.load(filepath=data["filepath"], link=True) as (sourceData, targetData):
targetData = sourceData
@ -17,16 +24,5 @@ class BlLibrary(BlDatablock):
assert(pointer)
return utils.dump_datablock(pointer, 1)
def resolve(self):
self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.libraries)
def is_valid(self):
return bpy.data.libraries.get(self.data['name'])
bl_id = "libraries"
bl_class = bpy.types.Library
bl_rep_class = BlLibrary
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'LIBRARY_DATA_DIRECT'
return bpy.data.libraries.get(self.data['name'])

View File

@ -6,6 +6,13 @@ from .bl_datablock import BlDatablock
class BlLight(BlDatablock):
bl_id = "lights"
bl_class = bpy.types.Light
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'LIGHT_DATA'
def construct(self, data):
return bpy.data.lights.new(data["name"], data["type"])
@ -39,16 +46,6 @@ class BlLight(BlDatablock):
data = dumper.dump(pointer)
return data
def resolve(self):
self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.lights)
def is_valid(self):
return bpy.data.lights.get(self.data['name'])
bl_id = "lights"
bl_class = bpy.types.Light
bl_rep_class = BlLight
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'LIGHT_DATA'

View File

@ -5,7 +5,14 @@ from .. import utils
from .bl_datablock import BlDatablock
class BlLightProbe(BlDatablock):
class BlLightprobe(BlDatablock):
bl_id = "lightprobes"
bl_class = bpy.types.LightProbe
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'LIGHTPROBE_GRID'
def load(self, data, target):
utils.dump_anything.load(target, data)
@ -33,17 +40,5 @@ class BlLightProbe(BlDatablock):
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'

View File

@ -68,6 +68,13 @@ def load_link(target_node_tree, source):
class BlMaterial(BlDatablock):
bl_id = "materials"
bl_class = bpy.types.Material
bl_delay_refresh = 10
bl_delay_apply = 10
bl_automatic_push = True
bl_icon = 'MATERIAL_DATA'
def construct(self, data):
return bpy.data.materials.new(data["name"])
@ -175,9 +182,6 @@ class BlMaterial(BlDatablock):
utils.dump_datablock_attibutes(pointer, ["grease_pencil"], 3, data)
return data
def resolve(self):
self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.materials)
def resolve_dependencies(self):
# TODO: resolve node group deps
deps = []
@ -194,11 +198,3 @@ class BlMaterial(BlDatablock):
def is_valid(self):
return bpy.data.materials.get(self.data['name'])
bl_id = "materials"
bl_class = bpy.types.Material
bl_rep_class = BlMaterial
bl_delay_refresh = 10
bl_delay_apply = 10
bl_automatic_push = True
bl_icon = 'MATERIAL_DATA'

View File

@ -75,6 +75,13 @@ def dump_mesh(mesh, data={}):
return mesh_data
class BlMesh(BlDatablock):
bl_id = "meshes"
bl_class = bpy.types.Mesh
bl_delay_refresh = 10
bl_delay_apply = 10
bl_automatic_push = True
bl_icon = 'MESH_DATA'
def construct(self, data):
instance = bpy.data.meshes.new(data["name"])
instance.uuid = self.uuid
@ -154,9 +161,6 @@ class BlMesh(BlDatablock):
return data
def resolve(self):
self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.meshes)
def resolve_dependencies(self):
deps = []
@ -168,11 +172,4 @@ class BlMesh(BlDatablock):
def is_valid(self):
return bpy.data.meshes.get(self.data['name'])
bl_id = "meshes"
bl_class = bpy.types.Mesh
bl_rep_class = BlMesh
bl_delay_refresh = 10
bl_delay_apply = 10
bl_automatic_push = True
bl_icon = 'MESH_DATA'

View File

@ -6,6 +6,13 @@ from .bl_datablock import BlDatablock
class BlMetaball(BlDatablock):
bl_id = "metaballs"
bl_class = bpy.types.MetaBall
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'META_BALL'
def construct(self, data):
return bpy.data.metaballs.new(data["name"])
@ -26,16 +33,5 @@ class BlMetaball(BlDatablock):
data = dumper.dump(pointer)
return data
def resolve(self):
self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.metaballs)
def is_valid(self):
return bpy.data.metaballs.get(self.data['name'])
bl_id = "metaballs"
bl_class = bpy.types.MetaBall
bl_rep_class = BlMetaball
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'META_BALL'

View File

@ -22,6 +22,13 @@ def load_constraints(target, data):
class BlObject(BlDatablock):
bl_id = "objects"
bl_class = bpy.types.Object
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'OBJECT_DATA'
def construct(self, data):
pointer = None
@ -245,10 +252,6 @@ class BlObject(BlDatablock):
return data
def resolve(self):
self.pointer = utils.find_from_attr(
'uuid', self.uuid, bpy.data.objects)
def resolve_dependencies(self):
deps = super().resolve_dependencies()
@ -272,10 +275,3 @@ class BlObject(BlDatablock):
return bpy.data.objects.get(self.data['name'])
bl_id = "objects"
bl_class = bpy.types.Object
bl_rep_class = BlObject
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'OBJECT_DATA'

View File

@ -5,6 +5,13 @@ from .. import utils
from .bl_datablock import BlDatablock
class BlScene(BlDatablock):
bl_id = "scenes"
bl_class = bpy.types.Scene
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'SCENE_DATA'
def construct(self, data):
instance = bpy.data.scenes.new(data["name"])
instance.uuid = self.uuid
@ -58,14 +65,6 @@ class BlScene(BlDatablock):
return data
def resolve(self):
scene_name = self.data['name']
self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.scenes)
if not self.pointer:
self.pointer = bpy.data.scenes.get(scene_name)
def resolve_dependencies(self):
deps = []
@ -88,11 +87,4 @@ class BlScene(BlDatablock):
return deps
def is_valid(self):
return bpy.data.scenes.get(self.data['name'])
bl_id = "scenes"
bl_class = bpy.types.Scene
bl_rep_class = BlScene
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'SCENE_DATA'
return bpy.data.scenes.get(self.data['name'])

View File

@ -6,6 +6,13 @@ from .bl_datablock import BlDatablock
class BlSpeaker(BlDatablock):
bl_id = "speakers"
bl_class = bpy.types.Speaker
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_icon = 'SPEAKER'
def load(self, data, target):
utils.dump_anything.load(target, data)
@ -34,17 +41,6 @@ class BlSpeaker(BlDatablock):
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'

View File

@ -9,6 +9,13 @@ from ..libs.replication.replication.constants import UP
class BlUser(BlDatablock):
bl_id = "users"
bl_class = presence.User
bl_delay_refresh = .1
bl_delay_apply = .1
bl_automatic_push = True
bl_icon = 'CON_ARMATURE'
def construct(self, name):
return presence.User()
@ -39,10 +46,4 @@ class BlUser(BlDatablock):
return True
bl_id = "users"
bl_class = presence.User
bl_rep_class = BlUser
bl_delay_refresh = .1
bl_delay_apply = .1
bl_automatic_push = True
bl_icon = 'CON_ARMATURE'

View File

@ -7,6 +7,13 @@ from .bl_material import load_link, load_node
class BlWorld(BlDatablock):
bl_id = "worlds"
bl_class = bpy.types.World
bl_delay_refresh = 4
bl_delay_apply = 4
bl_automatic_push = True
bl_icon = 'WORLD_DATA'
def construct(self, data):
return bpy.data.worlds.new(data["name"])
@ -83,9 +90,6 @@ class BlWorld(BlDatablock):
pointer.node_tree, ["links"], 3, data['node_tree'])
return data
def resolve(self):
self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.worlds)
def resolve_dependencies(self):
deps = []
@ -100,11 +104,3 @@ class BlWorld(BlDatablock):
def is_valid(self):
return bpy.data.worlds.get(self.data['name'])
bl_id = "worlds"
bl_class = bpy.types.World
bl_rep_class = BlWorld
bl_delay_refresh = 4
bl_delay_apply = 4
bl_automatic_push = True
bl_icon = 'WORLD_DATA'

View File

@ -8,7 +8,6 @@ import subprocess
import time
from operator import itemgetter
from pathlib import Path
import msgpack
import bpy
@ -61,22 +60,25 @@ class SessionStartOperator(bpy.types.Operator):
ui_context = context.copy()
# init the factory with supported types
for type in bl_types.types_to_register():
_type = getattr(bl_types, type)
supported_bl_types.append(_type.bl_id)
type_module = getattr(bl_types, type)
type_impl_name = "Bl{}".format(type.split('_')[1].capitalize())
type_module_class = getattr(type_module, type_impl_name)
supported_bl_types.append(type_module_class.bl_id)
# Retreive local replicated types settings
type_local_config = settings.supported_datablock[_type.bl_rep_class.__name__]
type_local_config = settings.supported_datablock[type_impl_name]
bpy_factory.register_type(
_type.bl_class,
_type.bl_rep_class,
type_module_class.bl_class,
type_module_class,
timer=type_local_config.bl_delay_refresh,
automatic=type_local_config.auto_push)
if type_local_config.bl_delay_apply > 0:
delayables.append(delayable.ApplyTimer(
timout=type_local_config.bl_delay_apply,
target_type=_type.bl_rep_class))
target_type=type_module_class))
client = Session(factory=bpy_factory)