def _get_material(base_renderable, upper_material): """Get material from a base renderable and an upper material.""" upper_mat_is_multimat = is_multimat(upper_material) return (base_renderable.material if (upper_material is None or upper_mat_is_multimat) else upper_material)
def _get_rends_from_window(obj, name, material, mesher, **kwargs): """Get renderables from an Window object (from Arch workbench). Parameters: obj -- the Window object name -- the name assigned to the Window object for rendering material -- the material for the Window object (should be a multimaterial) mesher -- a callable object which converts a shape into a mesh Returns: A list of renderables for the Window object """ # Subobjects names window_parts = obj.WindowParts if not window_parts and hasattr(obj, "CloneOf") and obj.CloneOf: # Workaround: if obj is a window Clone, WindowsParts is unfortunately # not replicated (must be a bug...). Therefore we look at base's # WindowsParts window_parts = obj.CloneOf.WindowParts subnames = window_parts[0::5] # Names every 5th item... names = ["%s_%s" % (name, s.replace(' ', '_')) for s in subnames] # Subobjects meshes meshes = [mesher(s) for s in obj.Shape.childShapes()] # Subobjects colors transparency_boost = kwargs.get("transparency_boost", 0) faces_len = [len(s.Faces) for s in obj.Shape.Solids] if obj.ViewObject is not None: # Gui is up colors = [ _boost_tp(obj.ViewObject.DiffuseColor[i], transparency_boost) for i in itertools.accumulate([0] + faces_len[:-1]) ] else: colors = [RGBA(0.8, 0.8, 0.8, 1)] * len(subnames) # Subobjects materials if material is not None: assert is_multimat(material), "Multimaterial expected" mats_dict = dict(zip(material.Names, material.Materials)) mats = [mats_dict.get(s) for s in subnames] if [m for m in mats if not m]: msg = translate("Render", "Incomplete multimaterial (missing {})") missing_mats = ', '.join(set(subnames) - mats_dict.keys()) warn("Window", obj.Label, msg.format(missing_mats)) else: mats = [None] * len(subnames) # Build renderables return [Renderable(*r) for r in zip(names, meshes, mats, colors)]
def _get_rends_from_wall(obj, name, material, mesher, **kwargs): """Get renderables from an Window object (from Arch workbench). Parameters: obj -- the Window object name -- the name assigned to the Window object for rendering material -- the material for the Window object (should be a multimaterial) mesher -- a callable object which converts a shape into a mesh Returns: A list of renderables for the Window object """ if material is None or not is_multimat(material): # No multimaterial: handle wall as a plain Part::Feature return _get_rends_from_partfeature(obj, name, material, mesher, **kwargs) shapes = obj.Shape.childShapes() # Subobjects names names = ["{}_{}".format(name, i) for i in range(len(shapes))] # Subobjects meshes meshes = [mesher(s) for s in shapes] # Subobjects materials materials = material.Materials # Subobjects colors tp_boost = kwargs.get("transparency_boost", 0) colors = [ _boost_tp(RGBA(*m.Color[0:3], m.Transparency), tp_boost) for m in materials ] # Build renderables return [Renderable(*r) for r in zip(names, meshes, materials, colors)]
def get_renderables(obj, name, upper_material, mesher, **kwargs): """Get the renderables from a FreeCAD object. A renderable is a tuple (name, mesh, material). There can be several renderables for one object, for instance if the object is a compound of subobjects, so the result of this function is a **list** of renderables. If this function does not know how to extract renderables from the given object, a TypeError is raised Parameters: obj -- the FreeCAD object from which to extract the renderables name -- the name of the object upper_material -- the FreeCAD material inherited from the upper level mesher -- a callable which can convert a shape into a mesh Keywords arguments: ignore_unknown -- a flag to prevent exception raising if 'obj' is of no renderable type transparency_boost -- a factor (positive integer) to boost transparency in shape color Returns: A list of renderables """ obj_is_applink = obj.isDerivedFrom("App::Link") obj_is_partfeature = obj.isDerivedFrom("Part::Feature") obj_is_meshfeature = obj.isDerivedFrom("Mesh::Feature") obj_is_app_part = obj.isDerivedFrom("App::Part") obj_type = getproxyattr(obj, "Type", "") mat = (getattr(obj, "Material", None) if upper_material is None else upper_material) mat = mat if is_valid_material(mat) or is_multimat(mat) else None del upper_material # Should not be used after this point... label = getattr(obj, "Label", name) ignore_unknown = bool(kwargs.get("ignore_unknown", False)) transparency_boost = int(kwargs.get("transparency_boost", 0)) # Link (plain) if obj_is_applink and not obj.ElementCount: debug("Object", label, "'Link (plain)' detected") renderables = \ _get_rends_from_plainapplink(obj, name, mat, mesher, **kwargs) # Link (array) elif obj_is_applink and obj.ElementCount: debug("Object", label, "'Link (array)' detected") renderables = \ _get_rends_from_elementlist(obj, name, mat, mesher, **kwargs) # Array, PathArray elif obj_is_partfeature and obj_type in ("Array", "PathArray"): debug("Object", label, "'%s' detected" % obj_type) expand_array = getattr(obj, "ExpandArray", False) renderables = (_get_rends_from_array(obj, name, mat, mesher, **kwargs) if not expand_array else _get_rends_from_elementlist( obj, name, mat, mesher, **kwargs)) # Window elif obj_is_partfeature and obj_type == "Window": debug("Object", label, "'Window' detected") renderables = _get_rends_from_window(obj, name, mat, mesher, **kwargs) # Wall elif obj_is_partfeature and obj_type == "Wall": debug("Object", label, "'Wall' detected") renderables = _get_rends_from_wall(obj, name, mat, mesher, **kwargs) # App part elif obj_is_app_part: debug("Object", label, "'App::Part' detected") renderables = _get_rends_from_part(obj, name, mat, mesher, **kwargs) # Plain part feature elif obj_is_partfeature: debug("Object", label, "'Part::Feature' detected") renderables = _get_rends_from_feature(obj, name, mat, mesher, **kwargs) # Mesh elif obj_is_meshfeature: debug("Object", label, "'Mesh::Feature' detected") color = _get_shapecolor(obj, transparency_boost) renderables = [Renderable(name, obj.Mesh, mat, color)] # Unhandled else: renderables = [] if not ignore_unknown: ascendants = ", ".join(obj.getAllDerivedFrom()) msg = translate("Render", "Unhandled object type (%s)" % ascendants) raise TypeError(msg) debug("Object", label, "Not renderable") return renderables