def check_meshes_use_auto_smooth(cls, _context) -> CheckResult: mesh_count = 0 use_auto_smooth_mesh_count = 0 obj: bpy.types.Object for obj in bpy.data.objects: if obj.type != 'MESH': continue if obj.hide_render: continue mesh: bpy.types.Mesh = obj.data mesh_count += 1 if not mesh.use_auto_smooth: continue use_auto_smooth_mesh_count += 1 return CheckResult( _('Meshes Use Auto Smooth'), CheckResultStatus.GOOD if use_auto_smooth_mesh_count == 0 else CheckResultStatus.WARNING, min(use_auto_smooth_mesh_count * 0.7, 3), f'{use_auto_smooth_mesh_count} / {mesh_count}', _('= 0 is Good'), editable=False )
class PyramidClothAdjusterSettingsPropertyGroup(bpy.types.PropertyGroup): string_pin_weight: bpy.props.FloatProperty( name=_('String Pin Weight'), min=0.0, max=1.0, precision=3, step=10, get=lambda p: PyramidMeshEditor(p.id_data).string_pin_weight, set=lambda p, v: setattr(PyramidMeshEditor(p.id_data), 'string_pin_weight', v), ) apex_pin_weight: bpy.props.FloatProperty( name=_('Apex Pin Weight'), min=0.0, max=1.0, precision=3, step=10, get=lambda p: PyramidMeshEditor(p.id_data).apex_pin_weight, set=lambda p, v: setattr(PyramidMeshEditor(p.id_data), 'apex_pin_weight', v), ) base_pin_weight: bpy.props.FloatProperty( name=_('Base Pin Weight'), min=0.0, max=1.0, precision=3, step=10, get=lambda p: PyramidMeshEditor(p.id_data).base_pin_weight, set=lambda p, v: setattr(PyramidMeshEditor(p.id_data), 'base_pin_weight', v), ) time_scale: bpy.props.FloatProperty( name=_('Speed Multiplier'), min=0.0, soft_max=10.0, precision=3, step=10, get=lambda p: PyramidMeshEditor(p.id_data).time_scale, set=lambda p, v: setattr(PyramidMeshEditor(p.id_data), 'time_scale', v), ) @staticmethod def register(): # pylint: disable=assignment-from-no-return bpy.types.Object.mmd_uuunyaa_tools_pyramid_cloth_settings = bpy.props.PointerProperty(type=PyramidClothAdjusterSettingsPropertyGroup) @staticmethod def unregister(): del bpy.types.Object.mmd_uuunyaa_tools_pyramid_cloth_settings
def import_vpd(vpd_file_path, scale=0.08, asset=None): asset_path, _ = _Utilities.resolve_path(asset) print(f'import_vpd({vpd_file_path},{scale},{asset_path})') try: bpy.ops.mmd_tools.import_vpd('INVOKE_DEFAULT', filepath=os.path.join( asset_path, vpd_file_path), scale=scale) except AttributeError as ex: if str( ex ) != 'Calling operator "bpy.ops.mmd_tools.import_vpd" error, could not be found': raise raise MessageException( _('Failed to invoke mmd_tools\nPlease install mmd_tools.') ) from ex except RuntimeError as ex: if str( ex ) != 'Operator bpy.ops.mmd_tools.import_vpd.poll() failed, context is incorrect': raise raise MessageException( _('Select an object.\nThe target object for pose import is not selected.' )) from ex
def check_materials_method(cls, _context) -> CheckResult: active_materials: Set[bpy.types.Material] = set() obj: bpy.types.Object for obj in bpy.data.objects: if obj.type != 'MESH': continue if obj.hide_render: continue material_slot: bpy.types.MaterialSlot for material_slot in obj.material_slots: active_materials.add(material_slot.material) material_count = len(active_materials) alpha_hashed_material_count = 0 for material in active_materials: if material.blend_method != 'HASHED' and material.shadow_method != 'HASHED': continue alpha_hashed_material_count += 1 return CheckResult( _('Materials Use Alpha Hashed'), CheckResultStatus.GOOD if alpha_hashed_material_count == 0 else CheckResultStatus.WARNING, min(alpha_hashed_material_count * 0.4, 2), f'{alpha_hashed_material_count} / {material_count}', _('= 0 is Good'), editable=False )
def draw(self, context: bpy.types.Context): world: bpy.types.World = context.scene.world utilities = MaterialEditor(world) layout = self.layout node_frame = utilities.find_node_frame() if node_frame is None: layout.label(text=_('UuuNyaa World not found.')) return scene_has_irradiance_volumes = self._scene_has_irradiance_volumes() if not scene_has_irradiance_volumes: layout.label(text=_('IrradianceVolume not found. Please add it.'), icon='ERROR') utilities.draw_setting_shader_node_properties( layout, utilities.list_nodes(node_frame=node_frame)) col = layout.column(align=True) col.label(text=_('for Eevee lighting, check Render Properties.')) if not scene_has_irradiance_volumes: return col.operator('scene.light_cache_bake', text=_('Bake Indirect Lighting'), icon='RENDER_STILL')
class EmissionAdjuster(MaterialAdjusterABC): @classmethod def get_id(cls) -> str: return 'MATERIAL_ADJUSTER_EMISSION' @classmethod def get_name(cls) -> str: return _('Emission Adjuster') translation_properties = [ _('Min'), _('Max'), _('Blood Color'), _('Subsurface'), _('Subsurface Color'), ] def attach(self) -> ShaderNodeGroup: node_frame = self.get_adjusters_node_frame() node_emission_adjuster = self.find_node(ShaderNodeGroup, label=self.get_name(), node_frame=node_frame) node_shader = self.find_active_principled_shader_node() node_emission_adjuster = self.edit( self.get_emission_adjuster_node(), { 'Min': self.to_link_or_value(node_shader.inputs['Subsurface']), 'Max': 0.300, 'Blood Color': self.to_link_or_value(node_shader.inputs['Subsurface Color']), }, { 'location': self.grid_to_position(-2, -8), 'parent': node_frame }) self.edit(node_shader, { 'Subsurface': node_emission_adjuster.outputs['Subsurface'], 'Subsurface Color': node_emission_adjuster.outputs['Subsurface Color'], }, force=True) return node_emission_adjuster def detach(self): node_emission_adjuster = self.get_emission_adjuster_node() self.edit(self.find_active_principled_shader_node(), { 'Subsurface': self.to_link_or_value(node_emission_adjuster.inputs['Min']), 'Subsurface Color': self.to_link_or_value( node_emission_adjuster.inputs['Blood Color']), }, force=True) self.nodes.remove(node_emission_adjuster)
def draw(self, context): layout = self.layout col = layout.column() box = col.box().column(align=True) box.label(text=_('Reload local asset JSON files')) box.operator(ReloadAssetJsons.bl_idname, icon='FILE_REFRESH') preferences = get_preferences() box = col.box().column(align=True) box.label(text=_('Download and Update to the latest assets')) operator = box.operator(UpdateAssetJson.bl_idname, icon='TRIA_DOWN_BAR') operator.repo = preferences.asset_json_update_repo operator.query = preferences.asset_json_update_query props = context.scene.mmd_uuunyaa_tools_asset_operator row = col.row(align=True) row.prop( props, 'debug_expanded', icon='TRIA_DOWN' if props.debug_expanded else 'TRIA_RIGHT', icon_only=True, emboss=False, ) row.label(text=_('Debug')) if not props.debug_expanded: return box = col.box().column() box.label(text=_('Fetch an asset for debug'), icon='MODIFIER') box.column(align=True).prop(props, 'debug_issue_number', text=_('issue #')) row = box.row(align=True) row.operator(DeleteDebugAssetJson.bl_idname, icon='CANCEL') row.operator( UpdateDebugAssetJson.bl_idname, icon='TRIA_DOWN_BAR').issue_number = props.debug_issue_number box = col.box().column() box.label(text=_( 'Download and Update to the latest filtered assets for debug'), icon='FILTER') box.prop(props, 'repo', text=_('Repository')) box.prop(props, 'query', text=_('Query')) box.prop(props, 'output_json', text=_('Write to')) operator = box.operator(UpdateAssetJson.bl_idname, text=_('Update Assets JSON by query'), icon='TRIA_DOWN_BAR') operator.repo = props.repo operator.query = props.query operator.output_json = props.output_json
class WetAdjuster(MaterialAdjusterABC): @classmethod def get_id(cls) -> str: return 'MATERIAL_ADJUSTER_WET' @classmethod def get_name(cls) -> str: return _('Wet Adjuster') translation_properties = [ _('Specular'), _('Roughness'), _('Wet'), ] def attach(self): node_frame = self.get_adjusters_node_frame() node_wet_adjuster = self.find_node(ShaderNodeGroup, label=WetAdjuster.get_name(), node_frame=node_frame) node_shader = self.find_active_principled_shader_node() node_wet_adjuster = self.edit( self.get_wet_adjuster_node(), { 'Specular': self.to_link_or_value(node_shader.inputs['Specular']), 'Roughness': self.to_link_or_value(node_shader.inputs['Roughness']), 'Wet': self.edit(self.get_vertex_color_node(), {}, { 'location': self.grid_to_position(-4, -10), 'parent': node_frame }).outputs['Color'], }, { 'location': self.grid_to_position(-2, -10), 'parent': node_frame }) self.edit(node_shader, { 'Specular': node_wet_adjuster.outputs['Specular'], 'Roughness': node_wet_adjuster.outputs['Roughness'], }, force=True) return node_wet_adjuster def detach(self): node_wet_adjuster = self.get_wet_adjuster_node() self.edit(self.find_active_principled_shader_node(), { 'Specular': self.to_link_or_value(node_wet_adjuster.inputs['Specular']), 'Roughness': self.to_link_or_value(node_wet_adjuster.inputs['Roughness']), }, force=True) self.nodes.remove(node_wet_adjuster) self.nodes.remove(self.get_vertex_color_node())
def check_use_ssr(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Use Screen Space Refraction'), CheckResultStatus.WARNING if context.scene.eevee.use_ssr else CheckResultStatus.GOOD, 0 if context.scene.eevee.use_ssr else -11.4, 'scene.eevee.use_ssr', _('= False is Good'), )
def check_use_motion_blur(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Use Motion Blur'), CheckResultStatus.AVERAGE if context.scene.eevee.use_motion_blur else CheckResultStatus.GOOD, 0 if context.scene.eevee.use_motion_blur else -3.4, 'scene.eevee.use_motion_blur', _('= False is Good'), )
def check_use_bloom(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Use Bloom'), CheckResultStatus.AVERAGE if context.scene.eevee.use_bloom else CheckResultStatus.GOOD, 0 if context.scene.eevee.use_bloom else -2.9, 'scene.eevee.use_bloom', _('= False is Good'), )
def check_use_gtao(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Use Ambient Occlusion'), CheckResultStatus.AVERAGE if context.scene.eevee.use_gtao else CheckResultStatus.GOOD, 0 if context.scene.eevee.use_gtao else -3.9, 'scene.eevee.use_gtao', _('= False is Good'), )
def check_use_compositing(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Use Compositing'), CheckResultStatus.WARNING if context.scene.render.use_compositing else CheckResultStatus.GOOD, -(0.6-1.7) if context.scene.render.use_compositing else 0, 'scene.render.use_compositing', _('= False is Good'), )
def check_use_pass_ambient_occlusion(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Pass Ambient Occlusion'), CheckResultStatus.WARNING if context.view_layer.use_pass_ambient_occlusion else CheckResultStatus.GOOD, -(-0.3-6.4) if context.view_layer.use_pass_ambient_occlusion else 0, 'view_layer.use_pass_ambient_occlusion', _('= False is Good'), )
def check_use_pass_diffuse_direct(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Pass Diffuse Light'), CheckResultStatus.POOR if context.view_layer.use_pass_diffuse_direct else CheckResultStatus.GOOD, -(-0.7-26.8) if context.view_layer.use_pass_diffuse_direct else 0, 'view_layer.use_pass_diffuse_direct', _('= False is Good'), )
def check_render_engine(context: bpy.types.Context): return CheckResult( _('Render Engine'), CheckResultStatus.GOOD if context.scene.render.engine == 'BLENDER_EEVEE' else CheckResultStatus.BAD, 0, 'scene.render.engine', _('= Eevee is Good'), )
def draw(self, context: bpy.types.Context): layout = self.layout col = layout.column() col.label(text=_('Batch Operation:')) col.operator('rigidbody.object_settings_copy', text=_('Copy to Selected'), icon='DUPLICATE')
def check_use_sequencer(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Use Sequencer'), CheckResultStatus.WARNING if context.scene.render.use_sequencer else CheckResultStatus.GOOD, 0, 'scene.render.use_sequencer', _('= False is Good'), )
def check_use_pass_z(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Pass Z'), CheckResultStatus.WARNING if context.view_layer.use_pass_z else CheckResultStatus.GOOD, -(-0.2-1.6) if context.view_layer.use_pass_z else 0, 'view_layer.use_pass_z', _('= False is Good'), )
def check_use_pass_environment(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Pass Environment'), CheckResultStatus.WARNING if context.view_layer.use_pass_environment else CheckResultStatus.GOOD, -(-0.6-2.3) if context.view_layer.use_pass_environment else 0, 'view_layer.use_pass_environment', _('= False is Good'), )
def check_use_pass_bloom(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Pass Bloom'), CheckResultStatus.WARNING if context.view_layer.eevee.use_pass_bloom else CheckResultStatus.GOOD, -(-0.8-2.6) if context.view_layer.eevee.use_pass_bloom else 0, 'view_layer.eevee.use_pass_bloom', _('= False is Good'), )
def check_use_pass_normal(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Pass Normal'), CheckResultStatus.WARNING if context.view_layer.use_pass_normal else CheckResultStatus.GOOD, -(-0.6-4.4) if context.view_layer.use_pass_normal else 0, 'view_layer.use_pass_normal', _('= False is Good'), )
def check_use_pass_shadow(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Pass Shadow'), CheckResultStatus.WARNING if context.view_layer.use_pass_shadow else CheckResultStatus.GOOD, -(-0.4-8.6) if context.view_layer.use_pass_shadow else 0, 'view_layer.use_pass_shadow', _('= False is Good'), )
def check_use_pass_diffuse_color(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Pass Diffuse Color'), CheckResultStatus.WARNING if context.view_layer.use_pass_diffuse_color else CheckResultStatus.GOOD, -(-0.7-14.5) if context.view_layer.use_pass_diffuse_color else 0, 'view_layer.use_pass_diffuse_color', _('= False is Good'), )
class SkyPanel(bpy.types.Panel): bl_idname = 'UUUNYAA_PT_sky_panel' bl_label = _('MMD UuuNyaa Sky') bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = 'world' @classmethod def poll(cls, context): return context.scene.world is not None translation_properties = [ _('Light Strength'), _('Image Strength'), ] def draw(self, context: bpy.types.Context): world: bpy.types.World = context.scene.world utilities = MaterialEditor(world) layout = self.layout node_frame = utilities.find_node_frame() if node_frame is None: layout.label(text=_('UuuNyaa World not found.')) return scene_has_irradiance_volumes = self._scene_has_irradiance_volumes() if not scene_has_irradiance_volumes: layout.label(text=_('IrradianceVolume not found. Please add it.'), icon='ERROR') utilities.draw_setting_shader_node_properties( layout, utilities.list_nodes(node_frame=node_frame)) col = layout.column(align=True) col.label(text=_('for Eevee lighting, check Render Properties.')) if not scene_has_irradiance_volumes: return col.operator('scene.light_cache_bake', text=_('Bake Indirect Lighting'), icon='RENDER_STILL') @staticmethod def _scene_has_irradiance_volumes(): obj: bpy.types.Object for obj in bpy.data.objects: if obj.type != 'LIGHT_PROBE': continue light_probe = obj.data if light_probe.type == 'GRID': return True return False
def check_taa_render_samples(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Render Samples'), cls.sample_to_status(context.scene.eevee.taa_render_samples), 0.0141 * context.scene.eevee.taa_render_samples + -0.439, 'scene.eevee.taa_render_samples', _('<= 16 is Good'), 1 )
def check_blender_version(_context: bpy.types.Context): return CheckResult( _('Blender Version'), CheckResultStatus.GOOD if bpy.app.version >= (2, 93, 0) else CheckResultStatus.BAD, 0, bpy.app.version_string, _('>= 2.93 LTS is Good'), editable=False, )
def check_taa_samples(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Viewport Samples'), cls.sample_to_status(context.scene.eevee.taa_samples), 0, 'scene.eevee.taa_samples', _('<= 16 is Good'), 1 )
def check_use_ssr_halfres(cls, context: bpy.types.Context) -> CheckResult: return CheckResult( _('Use Half Res Trace'), CheckResultStatus.AVERAGE if not context.scene.eevee.use_ssr_halfres else CheckResultStatus.GOOD, -2.2 if context.scene.eevee.use_ssr_halfres else 0, 'scene.eevee.use_ssr_halfres', _('= True is Good'), 1 )
def check_use_pass_volume_direct(cls, context: bpy.types.Context) -> Union[CheckResult, None]: if not hasattr(context.view_layer.eevee, 'use_pass_volume_direct'): return None return CheckResult( _('Pass Volume Light'), CheckResultStatus.WARNING if context.view_layer.eevee.use_pass_volume_direct else CheckResultStatus.GOOD, -(-0.7-2.9) if context.view_layer.eevee.use_pass_volume_direct else 0, 'view_layer.eevee.use_pass_volume_direct', _('= False is Good'), )