Files
multi-user/multi_user/io_bpy/bl_mesh.py
2021-04-21 11:10:24 +02:00

203 lines
6.3 KiB
Python

# ##### 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 bmesh
import mathutils
import logging
import numpy as np
from .dump_anything import (Dumper,
Loader,
np_load_collection_primitives,
np_dump_collection_primitive,
np_load_collection, np_dump_collection)
from replication.constants import DIFF_BINARY
from replication.exception import ContextError
from replication.protocol import ReplicatedDatablock
from replication.objects import Node
from .bl_datablock import get_datablock_from_uuid, stamp_uuid
from .bl_material import dump_materials_slots, load_materials_slots
from ..preferences import get_preferences
VERTICE = ['co']
EDGE = [
'vertices',
'crease',
'bevel_weight',
'use_seam',
'use_edge_sharp',
]
LOOP = [
'vertex_index',
'normal',
]
POLYGON = [
'loop_total',
'loop_start',
'use_smooth',
'material_index',
]
class BlMesh(ReplicatedDatablock):
bl_id = "meshes"
bl_class = bpy.types.Mesh
bl_check_common = False
bl_icon = 'MESH_DATA'
bl_reload_parent = True
@staticmethod
def construct(data: dict) -> object:
datablock = bpy.data.meshes.new(data["name"])
datablock.uuid = data['uuid']
return datablock
@staticmethod
def load(data: dict, datablock: object):
data = data
if not datablock or datablock.is_editmode:
raise ContextError
else:
loader = Loader()
loader.load(datablock, data)
# MATERIAL SLOTS
src_materials = data.get('materials', None)
if src_materials:
load_materials_slots(src_materials, datablock.materials)
# CLEAR GEOMETRY
if datablock.vertices:
datablock.clear_geometry()
datablock.vertices.add(data["vertex_count"])
datablock.edges.add(data["egdes_count"])
datablock.loops.add(data["loop_count"])
datablock.polygons.add(data["poly_count"])
# LOADING
np_load_collection(data['vertices'], datablock.vertices, VERTICE)
np_load_collection(data['edges'], datablock.edges, EDGE)
np_load_collection(data['loops'], datablock.loops, LOOP)
np_load_collection(data["polygons"], datablock.polygons, POLYGON)
# UV Layers
if 'uv_layers' in data.keys():
for layer in data['uv_layers']:
if layer not in datablock.uv_layers:
datablock.uv_layers.new(name=layer)
np_load_collection_primitives(
datablock.uv_layers[layer].data,
'uv',
data["uv_layers"][layer]['data'])
# Vertex color
if 'vertex_colors' in data.keys():
for color_layer in data['vertex_colors']:
if color_layer not in datablock.vertex_colors:
datablock.vertex_colors.new(name=color_layer)
np_load_collection_primitives(
datablock.vertex_colors[color_layer].data,
'color',
data["vertex_colors"][color_layer]['data'])
datablock.validate()
datablock.update()
@staticmethod
def dump(datablock: object) -> dict:
stamp_uuid(datablock)
if (datablock.is_editmode or bpy.context.mode == "SCULPT") and not get_preferences().sync_flags.sync_during_editmode:
raise ContextError("Mesh is in edit mode")
mesh = datablock
dumper = Dumper()
dumper.depth = 1
dumper.include_filter = [
'uuid'
'name',
'use_auto_smooth',
'auto_smooth_angle',
'use_customdata_edge_bevel',
'use_customdata_edge_crease'
]
data = dumper.dump(mesh)
# VERTICES
data["vertex_count"] = len(mesh.vertices)
data["vertices"] = np_dump_collection(mesh.vertices, VERTICE)
# EDGES
data["egdes_count"] = len(mesh.edges)
data["edges"] = np_dump_collection(mesh.edges, EDGE)
# POLYGONS
data["poly_count"] = len(mesh.polygons)
data["polygons"] = np_dump_collection(mesh.polygons, POLYGON)
# LOOPS
data["loop_count"] = len(mesh.loops)
data["loops"] = np_dump_collection(mesh.loops, LOOP)
# UV Layers
if mesh.uv_layers:
data['uv_layers'] = {}
for layer in mesh.uv_layers:
data['uv_layers'][layer.name] = {}
data['uv_layers'][layer.name]['data'] = np_dump_collection_primitive(
layer.data, 'uv')
# Vertex color
if mesh.vertex_colors:
data['vertex_colors'] = {}
for color_map in mesh.vertex_colors:
data['vertex_colors'][color_map.name] = {}
data['vertex_colors'][color_map.name]['data'] = np_dump_collection_primitive(
color_map.data, 'color')
# Materials
data['materials'] = dump_materials_slots(datablock.materials)
return data
@staticmethod
def resolve_deps(datablock: object) -> [object]:
deps = []
for material in datablock.materials:
if material:
deps.append(material)
return deps
def diff(self):
if 'EDIT' in bpy.context.mode \
and not get_preferences().sync_flags.sync_during_editmode:
return False
else:
return super().diff()