# Created: 06.04.2018 # Copyright (c) 2018, Manfred Moitzi # License: MIT License from typing import TYPE_CHECKING, Iterable from ezdxf.lldxf.const import DXFStructureError from .dxfobjects import none_subclass, DXFAttr, DXFAttributes, DefSubclass, ExtendedTags, DXFObject from .object_manager import ObjectManager from . import matrix_accessors if TYPE_CHECKING: from ezdxf.eztypes import Drawing, Matrix44 _MATERIAL_TPL = """0 MATERIAL 5 0 102 {ACAD_REACTORS 102 } 330 0 100 AcDbMaterial 1 Name 94 63 """ _MATERIAL_CLS = """0 CLASS 1 MATERIAL 2 AcDbMaterial 3 ObjectDBX Classes 90 1153 91 0 280 0 281 0 """ material_subclass = DefSubclass('AcDbMaterial', { 'name': DXFAttr(1), 'description': DXFAttr(2, default=''), 'ambient_color_method': DXFAttr(70, default=0), # 0=use current color; 1=override current color 'ambient_color_factor': DXFAttr(40, default=1.), # valid range is 0.0 to 1.0 'ambient_color_value': DXFAttr(90), # integer representing an AcCmEntityColor 'diffuse_color_method': DXFAttr(71, default=0), # 0=use current color; 1=override current color 'diffuse_color_factor': DXFAttr(41, default=1.), # valid range is 0.0 to 1.0 'diffuse_color_value': DXFAttr(91), # integer representing an AcCmEntityColor 'diffuse_map_blend_factor': DXFAttr(42, default=1.), # valid range is 0.0 to 1.0 'diffuse_map_source': DXFAttr(72, default=1), # 0=use current scene; 1=use image file (specified by file name; null file name specifies no map) 'diffuse_map_file_name': DXFAttr(3, default=''), 'diffuse_map_projection_method': DXFAttr(73, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere 'diffuse_map_tiling_method': DXFAttr(74, default=1), # 1=Tile; 2=Crop; 3=Clamp 'diffuse_map_auto_transform_method': DXFAttr(75, default=1), # bitset; # 1 = No auto transform # 2 = Scale mapper to current entity extents; translate mapper to entity origin # 4 = Include current block transform in mapper transform # 16x group code 43: Transform matrix of diffuse map mapper (16 reals; row major format; default = identity matrix) 'specular_gloss_factor': DXFAttr(44, default=.5), # valid range is 0.0 to 1.0 'specular_color_method': DXFAttr(73, default=0), # 0=use current color; 1=override current color 'specular_color_factor': DXFAttr(45, default=1.), # valid range is 0.0 to 1.0 'specular_color_value': DXFAttr(92), # integer representing an AcCmEntityColor 'specular_map_blend_factor': DXFAttr(46, default=1.), # valid range is 0.0 to 1.0 'specular_map_source': DXFAttr(77, default=1), # 0=use current scene; 1=use image file (specified by file name; null file name specifies no map) 'specular_map_file_name': DXFAttr(4, default=''), 'specular_map_projection_method': DXFAttr(78, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere 'specular_map_tiling_method': DXFAttr(79, default=1), # 1=Tile; 2=Crop; 3=Clamp 'specular_map_auto_transform_method': DXFAttr(170, default=1), # bitset; # 1 = No auto transform # 2 = Scale mapper to current entity extents; translate mapper to entity origin # 4 = Include current block transform in mapper transform # 16x group code 47: Transform matrix of specular map mapper (16 reals; row major format; default = identity matrix) 'reflection_map_blend_factor': DXFAttr(48, default=1.), # valid range is 0.0 to 1.0 'reflection_map_source': DXFAttr(171, default=1), # 0=use current scene; 1=use image file (specified by file name; null file name specifies no map) 'reflection_map_file_name': DXFAttr(6, default=''), 'reflection_map_projection_method': DXFAttr(172, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere 'reflection_map_tiling_method': DXFAttr(173, default=1), # 1=Tile; 2=Crop; 3=Clamp 'reflection_map_auto_transform_method': DXFAttr(174, default=1), # bitset; # 1 = No auto transform # 2 = Scale mapper to current entity extents; translate mapper to entity origin # 4 = Include current block transform in mapper transform # 16x group code 49: Transform matrix of reflection map mapper (16 reals; row major format; default = identity matrix) 'opacity': DXFAttr(140, default=1.), # valid range is 0.0 to 1.0 'opacity_map_blend_factor': DXFAttr(141, default=1.), # valid range is 0.0 to 1.0 'opacity_map_source': DXFAttr(175, default=1), # 0=use current scene; 1=use image file (specified by file name; null file name specifies no map) 'opacity_map_file_name': DXFAttr(7, default=''), 'opacity_map_projection_method': DXFAttr(176, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere 'opacity_map_tiling_method': DXFAttr(177, default=1), # 1=Tile; 2=Crop; 3=Clamp 'opacity_map_auto_transform_method': DXFAttr(178, default=1), # bitset; # 1 = No auto transform # 2 = Scale mapper to current entity extents; translate mapper to entity origin # 4 = Include current block transform in mapper transform # 16x group code 142: Transform matrix of reflection map mapper (16 reals; row major format; default = identity matrix) 'bump_map_blend_factor': DXFAttr(143, default=1.), # valid range is 0.0 to 1.0 'bump_map_source': DXFAttr(179, default=1), # 0=use current scene; 1=use image file (specified by file name; null file name specifies no map) 'bump_map_file_name': DXFAttr(8, default=''), 'bump_map_projection_method': DXFAttr(270, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere 'bump_map_tiling_method': DXFAttr(271, default=1), # 1=Tile; 2=Crop; 3=Clamp 'bump_map_auto_transform_method': DXFAttr(272, default=1), # bitset; # 1 = No auto transform # 2 = Scale mapper to current entity extents; translate mapper to entity origin # 4 = Include current block transform in mapper transform # 16x group code 144: Transform matrix of bump map mapper (16 reals; row major format; default = identity matrix) 'refraction_index': DXFAttr(145, default=1.), # valid range is 0.0 to 1.0 'refraction_map_blend_factor': DXFAttr(146, default=1.), # valid range is 0.0 to 1.0 'refraction_map_source': DXFAttr(273, default=1), # 0=use current scene; 1=use image file (specified by file name; null file name specifies no map) 'refraction_map_file_name': DXFAttr(9, default=''), 'refraction_map_projection_method': DXFAttr(274, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere 'refraction_map_tiling_method': DXFAttr(275, default=1), # 1=Tile; 2=Crop; 3=Clamp 'refraction_map_auto_transform_method': DXFAttr(276, default=1), # bitset; # 1 = No auto transform # 2 = Scale mapper to current entity extents; translate mapper to entity origin # 4 = Include current block transform in mapper transform # 16x group code 147: Transform matrix of reflection map mapper (16 reals; row major format; default = identity matrix) # normal map shares group codes with diffuse map 'normal_map_method': DXFAttr(271), 'normal_map_strength': DXFAttr(465), 'normal_map_blend_factor': DXFAttr(42, default=1.), # valid range is 0.0 to 1.0 'normal_map_source': DXFAttr(72, default=1), # 0=use current scene; 1=use image file (specified by file name; null file name specifies no map) 'normal_map_file_name': DXFAttr(3, default=''), 'normal_map_projection_method': DXFAttr(73, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere 'normal_map_tiling_method': DXFAttr(74, default=1), # 1=Tile; 2=Crop; 3=Clamp 'normal_map_auto_transform_method': DXFAttr(75, default=1), # bitset; # 1 = No auto transform # 2 = Scale mapper to current entity extents; translate mapper to entity origin # 4 = Include current block transform in mapper transform # 16x group code 43: Transform matrix of reflection map mapper (16 reals; row major format; default = identity matrix) 'color_bleed_scale': DXFAttr(460), 'indirect_dump_scale': DXFAttr(461), 'reflectance_scale': DXFAttr(462), 'transmittance_scale': DXFAttr(463), 'two_sided_material': DXFAttr(290), 'luminance': DXFAttr(464), 'luminance_mode': DXFAttr(270), 'materials_anonymous': DXFAttr(293), 'global_illumination_mode': DXFAttr(272), 'final_gather_mMode': DXFAttr(273), 'gen_proc_name': DXFAttr(300), 'gen_proc_val_bool': DXFAttr(291), 'gen_proc_val_int': DXFAttr(271), 'gen_proc_val_real': DXFAttr(469), 'gen_proc_val_text': DXFAttr(301), 'gen_proc_table_end': DXFAttr(292), 'gen_proc_val_color_index': DXFAttr(62), 'gen_proc_val_color_rgb': DXFAttr(420), 'gen_proc_val_color_name': DXFAttr(430), 'map_utile': DXFAttr(270), 'translucence': DXFAttr(148), 'self_illuminaton': DXFAttr(90), 'reflectivity': DXFAttr(468), 'illumination_model': DXFAttr(93), 'channel_flags': DXFAttr(94), }) class Material(DXFObject): __slots__ = () TEMPLATE = ExtendedTags.from_text(_MATERIAL_TPL) CLASS = ExtendedTags.from_text(_MATERIAL_CLS) DXFATTRIBS = DXFAttributes( none_subclass, material_subclass, ) def _get_matrix(self, code: int) -> 'Matrix44': subclass = self.tags.subclasses[1] # always 2nd subclass try: return matrix_accessors.get_matrix(subclass, code) except DXFStructureError: raise DXFStructureError('Invalid transformation matrix in entity ' + self.__str__()) def _set_matrix(self, code: int, data: Iterable[float]): subclass = self.tags.subclasses[1] # always 2nd subclass matrix_accessors.set_matrix(subclass, code, list(data)) def set_transformation_matrix_diffuse_map(self, matrix: Iterable[float]): self._set_matrix(code=43, data=matrix) def get_transformation_matrix_diffuse_map(self) -> 'Matrix44': return self._get_matrix(code=43) def set_transformation_matrix_normal_map(self, matrix: Iterable[float]): # collision with diffuse map self._set_matrix(code=43, data=matrix) def get_transformation_matrix_normal_map(self) -> 'Matrix44': # collision with diffuse map return self._get_matrix(code=43) def set_transformation_matrix_specular_map(self, matrix: Iterable[float]): self._set_matrix(code=47, data=matrix) def get_transformation_matrix_specular_map(self) -> 'Matrix44': return self._get_matrix(code=47) def set_transformation_matrix_reflection_map(self, matrix: Iterable[float]): self._set_matrix(code=49, data=matrix) def get_transformation_matrix_reflection_map(self) -> 'Matrix44': return self._get_matrix(code=49) def set_transformation_matrix_opacity_map(self, matrix: Iterable[float]): self._set_matrix(code=142, data=matrix) def get_transformation_matrix_opacity_map(self) -> 'Matrix44': return self._get_matrix(code=142) def set_transformation_matrix_bump_map(self, matrix: Iterable[float]): self._set_matrix(code=144, data=matrix) def get_transformation_matrix_bump_map(self) -> 'Matrix44': return self._get_matrix(code=144) def set_transformation_matrix_refraction_map(self, matrix: Iterable[float]): self._set_matrix(code=147, data=matrix) def get_transformation_matrix_refraction_map(self) -> 'Matrix44': return self._get_matrix(code=147) class MaterialManager(ObjectManager): def __init__(self, drawing: 'Drawing'): super().__init__(drawing, dict_name='ACAD_MATERIAL', object_type='MATERIAL') self.create_required_entries() def create_required_entries(self) -> None: for name in ('ByBlock', 'ByLayer', 'Global'): if name not in self.object_dict: self.new(name)