material.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. # Created: 06.04.2018
  2. # Copyright (c) 2018, Manfred Moitzi
  3. # License: MIT License
  4. from typing import TYPE_CHECKING, Iterable
  5. from ezdxf.lldxf.const import DXFStructureError
  6. from .dxfobjects import none_subclass, DXFAttr, DXFAttributes, DefSubclass, ExtendedTags, DXFObject
  7. from .object_manager import ObjectManager
  8. from . import matrix_accessors
  9. if TYPE_CHECKING:
  10. from ezdxf.eztypes import Drawing, Matrix44
  11. _MATERIAL_TPL = """0
  12. MATERIAL
  13. 5
  14. 0
  15. 102
  16. {ACAD_REACTORS
  17. 102
  18. }
  19. 330
  20. 0
  21. 100
  22. AcDbMaterial
  23. 1
  24. Name
  25. 94
  26. 63
  27. """
  28. _MATERIAL_CLS = """0
  29. CLASS
  30. 1
  31. MATERIAL
  32. 2
  33. AcDbMaterial
  34. 3
  35. ObjectDBX Classes
  36. 90
  37. 1153
  38. 91
  39. 0
  40. 280
  41. 0
  42. 281
  43. 0
  44. """
  45. material_subclass = DefSubclass('AcDbMaterial', {
  46. 'name': DXFAttr(1),
  47. 'description': DXFAttr(2, default=''),
  48. 'ambient_color_method': DXFAttr(70, default=0), # 0=use current color; 1=override current color
  49. 'ambient_color_factor': DXFAttr(40, default=1.), # valid range is 0.0 to 1.0
  50. 'ambient_color_value': DXFAttr(90), # integer representing an AcCmEntityColor
  51. 'diffuse_color_method': DXFAttr(71, default=0), # 0=use current color; 1=override current color
  52. 'diffuse_color_factor': DXFAttr(41, default=1.), # valid range is 0.0 to 1.0
  53. 'diffuse_color_value': DXFAttr(91), # integer representing an AcCmEntityColor
  54. 'diffuse_map_blend_factor': DXFAttr(42, default=1.), # valid range is 0.0 to 1.0
  55. '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)
  56. 'diffuse_map_file_name': DXFAttr(3, default=''),
  57. 'diffuse_map_projection_method': DXFAttr(73, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere
  58. 'diffuse_map_tiling_method': DXFAttr(74, default=1), # 1=Tile; 2=Crop; 3=Clamp
  59. 'diffuse_map_auto_transform_method': DXFAttr(75, default=1), # bitset;
  60. # 1 = No auto transform
  61. # 2 = Scale mapper to current entity extents; translate mapper to entity origin
  62. # 4 = Include current block transform in mapper transform
  63. # 16x group code 43: Transform matrix of diffuse map mapper (16 reals; row major format; default = identity matrix)
  64. 'specular_gloss_factor': DXFAttr(44, default=.5), # valid range is 0.0 to 1.0
  65. 'specular_color_method': DXFAttr(73, default=0), # 0=use current color; 1=override current color
  66. 'specular_color_factor': DXFAttr(45, default=1.), # valid range is 0.0 to 1.0
  67. 'specular_color_value': DXFAttr(92), # integer representing an AcCmEntityColor
  68. 'specular_map_blend_factor': DXFAttr(46, default=1.), # valid range is 0.0 to 1.0
  69. '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)
  70. 'specular_map_file_name': DXFAttr(4, default=''),
  71. 'specular_map_projection_method': DXFAttr(78, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere
  72. 'specular_map_tiling_method': DXFAttr(79, default=1), # 1=Tile; 2=Crop; 3=Clamp
  73. 'specular_map_auto_transform_method': DXFAttr(170, default=1), # bitset;
  74. # 1 = No auto transform
  75. # 2 = Scale mapper to current entity extents; translate mapper to entity origin
  76. # 4 = Include current block transform in mapper transform
  77. # 16x group code 47: Transform matrix of specular map mapper (16 reals; row major format; default = identity matrix)
  78. 'reflection_map_blend_factor': DXFAttr(48, default=1.), # valid range is 0.0 to 1.0
  79. '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)
  80. 'reflection_map_file_name': DXFAttr(6, default=''),
  81. 'reflection_map_projection_method': DXFAttr(172, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere
  82. 'reflection_map_tiling_method': DXFAttr(173, default=1), # 1=Tile; 2=Crop; 3=Clamp
  83. 'reflection_map_auto_transform_method': DXFAttr(174, default=1), # bitset;
  84. # 1 = No auto transform
  85. # 2 = Scale mapper to current entity extents; translate mapper to entity origin
  86. # 4 = Include current block transform in mapper transform
  87. # 16x group code 49: Transform matrix of reflection map mapper (16 reals; row major format; default = identity matrix)
  88. 'opacity': DXFAttr(140, default=1.), # valid range is 0.0 to 1.0
  89. 'opacity_map_blend_factor': DXFAttr(141, default=1.), # valid range is 0.0 to 1.0
  90. '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)
  91. 'opacity_map_file_name': DXFAttr(7, default=''),
  92. 'opacity_map_projection_method': DXFAttr(176, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere
  93. 'opacity_map_tiling_method': DXFAttr(177, default=1), # 1=Tile; 2=Crop; 3=Clamp
  94. 'opacity_map_auto_transform_method': DXFAttr(178, default=1), # bitset;
  95. # 1 = No auto transform
  96. # 2 = Scale mapper to current entity extents; translate mapper to entity origin
  97. # 4 = Include current block transform in mapper transform
  98. # 16x group code 142: Transform matrix of reflection map mapper (16 reals; row major format; default = identity matrix)
  99. 'bump_map_blend_factor': DXFAttr(143, default=1.), # valid range is 0.0 to 1.0
  100. '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)
  101. 'bump_map_file_name': DXFAttr(8, default=''),
  102. 'bump_map_projection_method': DXFAttr(270, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere
  103. 'bump_map_tiling_method': DXFAttr(271, default=1), # 1=Tile; 2=Crop; 3=Clamp
  104. 'bump_map_auto_transform_method': DXFAttr(272, default=1), # bitset;
  105. # 1 = No auto transform
  106. # 2 = Scale mapper to current entity extents; translate mapper to entity origin
  107. # 4 = Include current block transform in mapper transform
  108. # 16x group code 144: Transform matrix of bump map mapper (16 reals; row major format; default = identity matrix)
  109. 'refraction_index': DXFAttr(145, default=1.), # valid range is 0.0 to 1.0
  110. 'refraction_map_blend_factor': DXFAttr(146, default=1.), # valid range is 0.0 to 1.0
  111. '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)
  112. 'refraction_map_file_name': DXFAttr(9, default=''),
  113. 'refraction_map_projection_method': DXFAttr(274, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere
  114. 'refraction_map_tiling_method': DXFAttr(275, default=1), # 1=Tile; 2=Crop; 3=Clamp
  115. 'refraction_map_auto_transform_method': DXFAttr(276, default=1), # bitset;
  116. # 1 = No auto transform
  117. # 2 = Scale mapper to current entity extents; translate mapper to entity origin
  118. # 4 = Include current block transform in mapper transform
  119. # 16x group code 147: Transform matrix of reflection map mapper (16 reals; row major format; default = identity matrix)
  120. # normal map shares group codes with diffuse map
  121. 'normal_map_method': DXFAttr(271),
  122. 'normal_map_strength': DXFAttr(465),
  123. 'normal_map_blend_factor': DXFAttr(42, default=1.), # valid range is 0.0 to 1.0
  124. '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)
  125. 'normal_map_file_name': DXFAttr(3, default=''),
  126. 'normal_map_projection_method': DXFAttr(73, default=1), # 1=Planar; 2=Box; 3=Cylinder; 4=Sphere
  127. 'normal_map_tiling_method': DXFAttr(74, default=1), # 1=Tile; 2=Crop; 3=Clamp
  128. 'normal_map_auto_transform_method': DXFAttr(75, default=1), # bitset;
  129. # 1 = No auto transform
  130. # 2 = Scale mapper to current entity extents; translate mapper to entity origin
  131. # 4 = Include current block transform in mapper transform
  132. # 16x group code 43: Transform matrix of reflection map mapper (16 reals; row major format; default = identity matrix)
  133. 'color_bleed_scale': DXFAttr(460),
  134. 'indirect_dump_scale': DXFAttr(461),
  135. 'reflectance_scale': DXFAttr(462),
  136. 'transmittance_scale': DXFAttr(463),
  137. 'two_sided_material': DXFAttr(290),
  138. 'luminance': DXFAttr(464),
  139. 'luminance_mode': DXFAttr(270),
  140. 'materials_anonymous': DXFAttr(293),
  141. 'global_illumination_mode': DXFAttr(272),
  142. 'final_gather_mMode': DXFAttr(273),
  143. 'gen_proc_name': DXFAttr(300),
  144. 'gen_proc_val_bool': DXFAttr(291),
  145. 'gen_proc_val_int': DXFAttr(271),
  146. 'gen_proc_val_real': DXFAttr(469),
  147. 'gen_proc_val_text': DXFAttr(301),
  148. 'gen_proc_table_end': DXFAttr(292),
  149. 'gen_proc_val_color_index': DXFAttr(62),
  150. 'gen_proc_val_color_rgb': DXFAttr(420),
  151. 'gen_proc_val_color_name': DXFAttr(430),
  152. 'map_utile': DXFAttr(270),
  153. 'translucence': DXFAttr(148),
  154. 'self_illuminaton': DXFAttr(90),
  155. 'reflectivity': DXFAttr(468),
  156. 'illumination_model': DXFAttr(93),
  157. 'channel_flags': DXFAttr(94),
  158. })
  159. class Material(DXFObject):
  160. __slots__ = ()
  161. TEMPLATE = ExtendedTags.from_text(_MATERIAL_TPL)
  162. CLASS = ExtendedTags.from_text(_MATERIAL_CLS)
  163. DXFATTRIBS = DXFAttributes(
  164. none_subclass,
  165. material_subclass,
  166. )
  167. def _get_matrix(self, code: int) -> 'Matrix44':
  168. subclass = self.tags.subclasses[1] # always 2nd subclass
  169. try:
  170. return matrix_accessors.get_matrix(subclass, code)
  171. except DXFStructureError:
  172. raise DXFStructureError('Invalid transformation matrix in entity ' + self.__str__())
  173. def _set_matrix(self, code: int, data: Iterable[float]):
  174. subclass = self.tags.subclasses[1] # always 2nd subclass
  175. matrix_accessors.set_matrix(subclass, code, list(data))
  176. def set_transformation_matrix_diffuse_map(self, matrix: Iterable[float]):
  177. self._set_matrix(code=43, data=matrix)
  178. def get_transformation_matrix_diffuse_map(self) -> 'Matrix44':
  179. return self._get_matrix(code=43)
  180. def set_transformation_matrix_normal_map(self, matrix: Iterable[float]): # collision with diffuse map
  181. self._set_matrix(code=43, data=matrix)
  182. def get_transformation_matrix_normal_map(self) -> 'Matrix44': # collision with diffuse map
  183. return self._get_matrix(code=43)
  184. def set_transformation_matrix_specular_map(self, matrix: Iterable[float]):
  185. self._set_matrix(code=47, data=matrix)
  186. def get_transformation_matrix_specular_map(self) -> 'Matrix44':
  187. return self._get_matrix(code=47)
  188. def set_transformation_matrix_reflection_map(self, matrix: Iterable[float]):
  189. self._set_matrix(code=49, data=matrix)
  190. def get_transformation_matrix_reflection_map(self) -> 'Matrix44':
  191. return self._get_matrix(code=49)
  192. def set_transformation_matrix_opacity_map(self, matrix: Iterable[float]):
  193. self._set_matrix(code=142, data=matrix)
  194. def get_transformation_matrix_opacity_map(self) -> 'Matrix44':
  195. return self._get_matrix(code=142)
  196. def set_transformation_matrix_bump_map(self, matrix: Iterable[float]):
  197. self._set_matrix(code=144, data=matrix)
  198. def get_transformation_matrix_bump_map(self) -> 'Matrix44':
  199. return self._get_matrix(code=144)
  200. def set_transformation_matrix_refraction_map(self, matrix: Iterable[float]):
  201. self._set_matrix(code=147, data=matrix)
  202. def get_transformation_matrix_refraction_map(self) -> 'Matrix44':
  203. return self._get_matrix(code=147)
  204. class MaterialManager(ObjectManager):
  205. def __init__(self, drawing: 'Drawing'):
  206. super().__init__(drawing, dict_name='ACAD_MATERIAL', object_type='MATERIAL')
  207. self.create_required_entries()
  208. def create_required_entries(self) -> None:
  209. for name in ('ByBlock', 'ByLayer', 'Global'):
  210. if name not in self.object_dict:
  211. self.new(name)