Merge branch '146-add-support-for-internal-textures' into 'develop'

Resolve "Add support for internal textures"

See merge request slumber/multi-user!78
This commit is contained in:
Swann Martinez
2020-12-02 15:36:01 +00:00
7 changed files with 139 additions and 13 deletions

View File

@ -43,6 +43,7 @@ Currently, not all data-block are supported for replication over the wire. The f
| node_groups | ❗ | Material only | | node_groups | ❗ | Material only |
| metaball | ✔️ | | | metaball | ✔️ | |
| object | ✔️ | | | object | ✔️ | |
| textures | ❗ | Supported for modifiers only |
| texts | ✔️ | | | texts | ✔️ | |
| scene | ✔️ | | | scene | ✔️ | |
| world | ✔️ | | | world | ✔️ | |

View File

@ -39,7 +39,8 @@ __all__ = [
'bl_sound', 'bl_sound',
'bl_file', 'bl_file',
'bl_sequencer', 'bl_sequencer',
'bl_node_group' 'bl_node_group',
'bl_texture'
] # Order here defines execution order ] # Order here defines execution order
from . import * from . import *

View File

@ -35,7 +35,7 @@ def load_pose(target_bone, data):
def find_data_from_name(name=None): def find_data_from_name(name=None):
instance = None instance = None
if not name: if not name:
pass pass
elif name in bpy.data.meshes.keys(): elif name in bpy.data.meshes.keys():
instance = bpy.data.meshes[name] instance = bpy.data.meshes[name]
elif name in bpy.data.lights.keys(): elif name in bpy.data.lights.keys():
@ -78,6 +78,19 @@ def _is_editmode(object: bpy.types.Object) -> bool:
child_data.is_editmode) child_data.is_editmode)
def find_textures_dependencies(collection):
""" Check collection
"""
textures = []
for item in collection:
for attr in dir(item):
inst = getattr(item, attr)
if issubclass(type(inst), bpy.types.Texture) and inst is not None:
textures.append(inst)
return textures
class BlObject(BlDatablock): class BlObject(BlDatablock):
bl_id = "objects" bl_id = "objects"
bl_class = bpy.types.Object bl_class = bpy.types.Object
@ -105,9 +118,9 @@ class BlObject(BlDatablock):
data_id = data.get("data") data_id = data.get("data")
object_data = get_datablock_from_uuid( object_data = get_datablock_from_uuid(
data_uuid, data_uuid,
find_data_from_name(data_id), find_data_from_name(data_id),
ignore=['images']) #TODO: use resolve_from_id ignore=['images']) # TODO: use resolve_from_id
instance = bpy.data.objects.new(object_name, object_data) instance = bpy.data.objects.new(object_name, object_data)
instance.uuid = self.uuid instance.uuid = self.uuid
@ -120,14 +133,15 @@ class BlObject(BlDatablock):
data_id = data.get("data") data_id = data.get("data")
if target.data and (target.data.name != data_id): if target.data and (target.data.name != data_id):
target.data = get_datablock_from_uuid(data_uuid, find_data_from_name(data_id), ignore=['images']) target.data = get_datablock_from_uuid(
data_uuid, find_data_from_name(data_id), ignore=['images'])
# vertex groups # vertex groups
if 'vertex_groups' in data: if 'vertex_groups' in data:
target.vertex_groups.clear() target.vertex_groups.clear()
for vg in data['vertex_groups']: for vg in data['vertex_groups']:
vertex_group=target.vertex_groups.new(name = vg['name']) vertex_group = target.vertex_groups.new(name=vg['name'])
point_attr='vertices' if 'vertices' in vg else 'points' point_attr = 'vertices' if 'vertices' in vg else 'points'
for vert in vg[point_attr]: for vert in vg[point_attr]:
vertex_group.add( vertex_group.add(
[vert['index']], vert['weight'], 'REPLACE') [vert['index']], vert['weight'], 'REPLACE')
@ -136,12 +150,12 @@ class BlObject(BlDatablock):
if 'shape_keys' in data: if 'shape_keys' in data:
target.shape_key_clear() target.shape_key_clear()
object_data=target.data object_data = target.data
# Create keys and load vertices coords # Create keys and load vertices coords
for key_block in data['shape_keys']['key_blocks']: for key_block in data['shape_keys']['key_blocks']:
key_data=data['shape_keys']['key_blocks'][key_block] key_data = data['shape_keys']['key_blocks'][key_block]
target.shape_key_add(name = key_block) target.shape_key_add(name=key_block)
loader.load( loader.load(
target.data.shape_keys.key_blocks[key_block], key_data) target.data.shape_keys.key_blocks[key_block], key_data)
@ -384,4 +398,7 @@ class BlObject(BlDatablock):
# TODO: uuid based # TODO: uuid based
deps.append(self.instance.instance_collection) deps.append(self.instance.instance_collection)
if self.instance.modifiers:
deps.extend(find_textures_dependencies(self.instance.modifiers))
return deps return deps

View File

@ -0,0 +1,77 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####
import bpy
import mathutils
from .dump_anything import Loader, Dumper
from .bl_datablock import BlDatablock
class BlTexture(BlDatablock):
bl_id = "textures"
bl_class = bpy.types.Texture
bl_delay_refresh = 1
bl_delay_apply = 1
bl_automatic_push = True
bl_check_common = False
bl_icon = 'TEXTURE'
def _load_implementation(self, data, target):
loader = Loader()
loader.load(target, data)
def _construct(self, data):
return bpy.data.textures.new(data["name"], data["type"])
def _dump_implementation(self, data, instance=None):
assert(instance)
dumper = Dumper()
dumper.depth = 1
dumper.exclude_filter = [
'tag',
'original',
'user',
'uuid',
'is_embedded_data',
'is_evaluated',
'name_full'
]
data = dumper.dump(instance)
color_ramp = getattr(instance, 'color_ramp', None)
if color_ramp:
dumper.depth = 4
data['color_ramp'] = dumper.dump(color_ramp)
return data
def _resolve_deps_implementation(self):
# TODO: resolve material
deps = []
image = getattr(self.instance,"image", None)
if image:
deps.append(image)
return deps

View File

@ -23,6 +23,7 @@ import queue
import random import random
import shutil import shutil
import string import string
import sys
import time import time
from operator import itemgetter from operator import itemgetter
from pathlib import Path from pathlib import Path
@ -38,7 +39,7 @@ from replication.exception import NonAuthorizedOperationError
from replication.interface import session from replication.interface import session
from . import bl_types, delayable, environment, ui, utils from . import bl_types, delayable, environment, ui, utils
from .presence import (SessionStatusWidget, renderer, view3d_find) from .presence import SessionStatusWidget, renderer, view3d_find
background_execution_queue = Queue() background_execution_queue = Queue()
delayables = [] delayables = []
@ -195,9 +196,14 @@ class SessionStartOperator(bpy.types.Operator):
timout=type_local_config.bl_delay_apply, timout=type_local_config.bl_delay_apply,
target_type=type_module_class)) target_type=type_module_class))
if bpy.app.version[1] >= 91:
python_binary_path = sys.executable
else:
python_binary_path = bpy.app.binary_path_python
session.configure( session.configure(
factory=bpy_factory, factory=bpy_factory,
python_path=bpy.app.binary_path_python, python_path=python_binary_path,
external_update_handling=use_extern_update) external_update_handling=use_extern_update)
if settings.update_method == 'DEPSGRAPH': if settings.update_method == 'DEPSGRAPH':

View File

@ -13,7 +13,7 @@ def main():
if len(sys.argv) > 2: if len(sys.argv) > 2:
blender_rev = sys.argv[2] blender_rev = sys.argv[2]
else: else:
blender_rev = "2.90.0" blender_rev = "2.91.0"
try: try:
exit_val = BAT.test_blender_addon(addon_path=addon, blender_revision=blender_rev) exit_val = BAT.test_blender_addon(addon_path=addon, blender_revision=blender_rev)

View File

@ -0,0 +1,24 @@
import os
import pytest
from deepdiff import DeepDiff
import bpy
import random
from multi_user.bl_types.bl_texture import BlTexture
TEXTURE_TYPES = ['NONE', 'BLEND', 'CLOUDS', 'DISTORTED_NOISE', 'IMAGE', 'MAGIC', 'MARBLE', 'MUSGRAVE', 'NOISE', 'STUCCI', 'VORONOI', 'WOOD']
@pytest.mark.parametrize('texture_type', TEXTURE_TYPES)
def test_texture(clear_blend, texture_type):
datablock = bpy.data.textures.new('test', texture_type)
implementation = BlTexture()
expected = implementation._dump(datablock)
bpy.data.textures.remove(datablock)
test = implementation._construct(expected)
implementation._load(expected, test)
result = implementation._dump(test)
assert not DeepDiff(expected, result)