from .functions import * from bpy.types import AddonPreferences # # UPDATE FUNCTIONS # def update_bones_prop(self, attr_name, attr_value): prefs = bpy.context.preferences.addons["goo_physics"].preferences if self.gp_update: coll = bpy.data.collections.get("Goo Physics") if coll is not None: for pb in bpy.context.selected_pose_bones: # Dont propagate settings between softbody and cloth if bone has a different setting if pb.gp_has_sb_physics == False and bpy.context.active_pose_bone.gp_has_sb_physics: continue if pb.gp_has_jg_physics == False and bpy.context.active_pose_bone.gp_has_jg_physics: continue if pb.gp_has_cl_physics == False and bpy.context.active_pose_bone.gp_has_cl_physics: continue if prefs.apply_to_all_chains == False and pb.gp_chain_id != bpy.context.active_pose_bone.gp_chain_id: continue if prefs.apply_to_all_bones == False and pb != bpy.context.active_pose_bone: continue pb.gp_update = False setattr(pb, attr_name, attr_value) ob = coll.objects.get(pb.gp_sim_object) if ob is not None and (pb.gp_has_sb_physics or pb.gp_has_cl_physics or pb.gp_has_jg_physics): for mod in ob.modifiers: if mod.type == "SOFT_BODY": if pb.gp_has_sb_physics: mod.settings.goal_min = pb.gp_sim_strength mod.settings.goal_spring = pb.gp_sim_stiffness mod.settings.goal_friction = pb.gp_sim_damping mod.settings.speed = pb.gp_sim_speed mod.settings.friction = pb.gp_sim_friction mod.settings.mass = pb.gp_sim_mass mod.settings.use_edge_collision = pb.gp_sim_use_collision mod.settings.effector_weights.gravity = pb.gp_sim_gravity if pb.gp_sim_limit_collision: if pb.gp_has_sb_physics: mod.settings.collision_collection = bpy.data.collections.get("Goo Physics Soft Body Colliders") else: mod.settings.collision_collection = bpy.data.collections.get("Goo Physics Jiggle Colliders") else: mod.settings.collision_collection = None track_cons = pb.constraints.get("GP_Track") if track_cons: track_cons.influence = pb.gp_sim_influence follow_cons = pb.constraints.get("GP_Follow") if follow_cons: follow_cons.influence = pb.gp_sim_influence pb.gp_update = True self.gp_update = False track_cons = self.constraints.get("GP_Track") if track_cons: track_cons.influence = self.gp_sim_influence follow_cons = self.constraints.get("GP_Follow") if follow_cons: follow_cons.influence = self.gp_sim_influence self.gp_update = True return def update_bones_speed(self, context): update_bones_prop(self, "gp_sim_speed", context.active_pose_bone.gp_sim_speed) return def update_bones_friction(self, context): update_bones_prop(self, "gp_sim_friction", context.active_pose_bone.gp_sim_friction) return def update_bones_mass(self, context): update_bones_prop(self, "gp_sim_mass", context.active_pose_bone.gp_sim_mass) return def update_bones_stiffness(self, context): update_bones_prop( self, "gp_sim_stiffness", context.active_pose_bone.gp_sim_stiffness ) return def update_bones_damping(self, context): update_bones_prop(self, "gp_sim_damping", context.active_pose_bone.gp_sim_damping) return def update_bones_strength(self, context): update_bones_prop(self, "gp_sim_strength", context.active_pose_bone.gp_sim_strength) return def update_bones_influence(self, context): update_bones_prop( self, "gp_sim_influence", context.active_pose_bone.gp_sim_influence ) return def update_bones_air_dampening(self, context): update_bones_prop( self, "gp_sim_air_dampening", context.active_pose_bone.gp_sim_air_dampening ) return def update_bones_bend_damping(self, context): update_bones_prop( self, "gp_sim_bend_damping", context.active_pose_bone.gp_sim_bend_damping ) return def update_bones_use_collision(self, context): update_bones_prop( self, "gp_sim_use_collision", context.active_pose_bone.gp_sim_use_collision ) return def update_bones_limit_collision(self, context): update_bones_prop( self, "gp_sim_limit_collision", context.active_pose_bone.gp_sim_limit_collision ) return def update_bones_gravity(self, context): update_bones_prop( self, "gp_sim_gravity", context.active_pose_bone.gp_sim_gravity ) return # def update_chain_prop(self, attr_name, attr_value): prefs = bpy.context.preferences.addons["goo_physics"].preferences if self.gp_update: coll = bpy.data.collections.get("Goo Physics") if coll is not None: chains, bones = [], [] for pb in bpy.context.selected_pose_bones: if pb.gp_has_gn_physics == False and pb.gp_has_cl_physics == False: continue if prefs.apply_to_all_chains == False and pb.gp_chain_id != bpy.context.active_pose_bone.gp_chain_id: continue if pb.gp_chain_id not in chains: chains.append(pb.gp_chain_id) bones.append(pb) # Loop all bones looking to update rest of chain with changed props skip_rigs = [] for p, pb in enumerate(bones): if pb.id_data in skip_rigs: continue else: skip_rigs.append(pb.id_data) for c_pb in pb.id_data.pose.bones: if c_pb.gp_chain_id in chains: c_pb.gp_update = False setattr(c_pb, attr_name, attr_value) ob = coll.objects.get(c_pb.gp_sim_object) if ob: mod = ob.modifiers.get("GP_Nodes Sim") if mod: inputs = get_inputs_container(mod.node_group) if attr_name == "gp_chain_wind_strength": set_geo_nodes_input(mod, "Wind Strength", attr_value) if attr_name == "gp_chain_wind_noise_scale": set_geo_nodes_input(mod, "Wind Noise Scale", attr_value) if attr_name == "gp_chain_wind_noise_strength": set_geo_nodes_input(mod, "Wind Noise Strength", attr_value) if attr_name == "gp_chain_dampening": set_geo_nodes_input(mod, "Velocity Dampening", attr_value) if attr_name == "gp_chain_root_falloff": set_geo_nodes_input(mod, "Root Pin Size", attr_value) if attr_name == "gp_chain_velocity": set_geo_nodes_input(mod, "Velocity Scaler", attr_value) if attr_name == "gp_chain_gravity": set_geo_nodes_input(mod, "Gravity Strength", attr_value) if attr_name == "gp_chain_stiffness": set_geo_nodes_input(mod, "Goal Strength", attr_value) if attr_name == "gp_chain_stiff_end_fac": set_geo_nodes_input(mod, "Goal End Strength", attr_value) if attr_name == "gp_chain_stiff_vel_fac": set_geo_nodes_input(mod, "Goal Velocity Factor", attr_value) if attr_name == "gp_chain_stiff_vel_min": set_geo_nodes_input(mod, "Goal Velocity Min", attr_value) if attr_name == "gp_chain_stiff_vel_max": set_geo_nodes_input(mod, "Goal Velocity Max", attr_value) if attr_name == "gp_chain_use_collision": set_geo_nodes_input(mod, "Use Collision", attr_value) if attr_name == "gp_chain_collision_dist": set_geo_nodes_input(mod, "Collision Distance", attr_value) if attr_name == "gp_chain_collision_friction": set_geo_nodes_input(mod, "Collision Friction", attr_value) if attr_name == "gp_chain_limit_collision": if c_pb.gp_chain_limit_collision: set_geo_nodes_input(mod, "Collision Collection", bpy.data.collections.get("Goo Physics Geo Nodes Colliders")) else: set_geo_nodes_input(mod, "Collision Collection", bpy.data.collections.get("Goo Physics All Colliders")) ob.location = ob.location for mod in ob.modifiers: if mod.type == "CLOTH": mod.settings.mass = pb.gp_chain_mass mod.settings.time_scale = pb.gp_chain_speed mod.settings.air_damping = pb.gp_chain_air_dampening mod.collision_settings.use_collision = pb.gp_chain_use_collision mod.settings.effector_weights.gravity = pb.gp_chain_gravity if pb.gp_chain_limit_collision: mod.collision_settings.collection = bpy.data.collections.get("Goo Physics Cloth Colliders") else: mod.collision_settings.collection = None c_pb.gp_update = True return def update_chain_speed(self, context): update_chain_prop(self, "gp_chain_speed", context.active_pose_bone.gp_chain_speed) return def update_chain_mass(self, context): update_chain_prop(self, "gp_chain_mass", context.active_pose_bone.gp_chain_mass) return def update_chain_air_dampening(self, context): update_chain_prop( self, "gp_chain_air_dampening", context.active_pose_bone.gp_chain_air_dampening ) return def update_chain_bend_damping(self, context): update_chain_prop( self, "gp_chain_bend_damping", context.active_pose_bone.gp_chain_bend_damping ) return def update_chain_wind_strength(self, context): update_chain_prop( self, "gp_chain_wind_strength", context.active_pose_bone.gp_chain_wind_strength ) return def update_chain_wind_noise_scale(self, context): update_chain_prop( self, "gp_chain_wind_noise_scale", context.active_pose_bone.gp_chain_wind_noise_scale ) return def update_chain_wind_noise_strength(self, context): update_chain_prop( self, "gp_chain_wind_noise_strength", context.active_pose_bone.gp_chain_wind_noise_strength ) return def update_chain_dampening(self, context): update_chain_prop( self, "gp_chain_dampening", context.active_pose_bone.gp_chain_dampening ) return def update_chain_root_falloff(self, context): update_chain_prop( self, "gp_chain_root_falloff", context.active_pose_bone.gp_chain_root_falloff ) return def update_chain_velocity(self, context): update_chain_prop( self, "gp_chain_velocity", context.active_pose_bone.gp_chain_velocity ) return def update_chain_gravity(self, context): update_chain_prop( self, "gp_chain_gravity", context.active_pose_bone.gp_chain_gravity ) return def update_chain_stiffness(self, context): update_chain_prop( self, "gp_chain_stiffness", context.active_pose_bone.gp_chain_stiffness ) return def update_chain_stiff_end_fac(self, context): update_chain_prop( self, "gp_chain_stiff_end_fac", context.active_pose_bone.gp_chain_stiff_end_fac, ) return def update_chain_velocity_fac(self, context): update_chain_prop( self, "gp_chain_stiff_vel_fac", context.active_pose_bone.gp_chain_stiff_vel_fac ) return def update_chain_velocity_min(self, context): update_chain_prop( self, "gp_chain_stiff_vel_min", context.active_pose_bone.gp_chain_stiff_vel_min ) return def update_chain_velocity_max(self, context): update_chain_prop( self, "gp_chain_stiff_vel_max", context.active_pose_bone.gp_chain_stiff_vel_max ) return def update_chain_use_collision(self, context): update_chain_prop( self, "gp_chain_use_collision", context.active_pose_bone.gp_chain_use_collision ) return def update_chain_collision_dist(self, context): update_chain_prop( self, "gp_chain_collision_dist", context.active_pose_bone.gp_chain_collision_dist, ) return def update_chain_friction(self, context): update_chain_prop( self, "gp_chain_collision_friction", context.active_pose_bone.gp_chain_collision_friction, ) return def update_chain_limit_collision(self, context): update_chain_prop( self, "gp_chain_limit_collision", context.active_pose_bone.gp_chain_limit_collision, ) return # def toggle_physics_status(self, context): coll, collide_colls, control_coll, bake_coll = ensure_collections() for ob in bpy.data.objects: if ob.type == "ARMATURE": for pb in ob.pose.bones: track_cons = pb.constraints.get("GP_Track") if track_cons: track_cons.enabled = self.gp_physics_active follow_cons = pb.constraints.get("GP_Follow") if follow_cons: follow_cons.enabled = self.gp_physics_active for ob in coll.all_objects: if ob.type == "MESH": for mod in ob.modifiers: if mod.type in ["NODES", "CLOTH", "SOFT_BODY"]: mod.show_viewport = self.gp_physics_active return # # # PRESETS FUNCTIONS # def load_presets(preset_fp): presets_data = None if os.path.exists(preset_fp): presets_data = json.load(open(str(preset_fp))) items = [] if presets_data is not None: for k in presets_data.keys(): items.append( ( k, presets_data[k]["Name"], presets_data[k]["Description"], ) ) return sorted(items) def get_cl_presets(self, context): preset_fp = Path(os.path.dirname(__file__)) / "presets" / "cloth_presets.json" user_preset_fp = Path(os.path.dirname(__file__)) / "user_created_presets" / "cloth_presets.json" return load_presets(preset_fp) + load_presets(user_preset_fp) def get_sb_presets(self, context): preset_fp = Path(os.path.dirname(__file__)) / "presets" / "soft_body_presets.json" user_preset_fp = Path(os.path.dirname(__file__)) / "user_created_presets" / "soft_body_presets.json" return load_presets(preset_fp) + load_presets(user_preset_fp) def get_jg_presets(self, context): preset_fp = Path(os.path.dirname(__file__)) / "presets" / "jiggle_spring_presets.json" user_preset_fp = Path(os.path.dirname(__file__)) / "user_created_presets" / "jiggle_spring_presets.json" return load_presets(preset_fp) + load_presets(user_preset_fp) def get_gn_presets(self, context): preset_fp = Path(os.path.dirname(__file__)) / "presets" / "geo_nodes_presets.json" user_preset_fp = Path(os.path.dirname(__file__)) / "user_created_presets" / "geo_nodes_presets.json" return load_presets(preset_fp) + load_presets(user_preset_fp) def get_bm_presets(self, context): user_preset_fp = Path(os.path.dirname(__file__)) / "user_created_presets" / "bone_map_presets.json" return load_presets(user_preset_fp) # class gp_bone_props(PropertyGroup): rig_object: StringProperty(description="") rig_bone: StringProperty(description="") class gp_bone_collection(PropertyGroup): coll: CollectionProperty(type=gp_bone_props) index: IntProperty() # # PREFERENCES AND REGISTERS # class GooPhysicsPreferences(AddonPreferences): bl_idname = "goo_physics" gp_divisions: bpy.props.IntProperty( default=1, min=0, max=10, name="Bone Resolution", description="Number of extra vertices to add to each bone segment for Geo Nodes. Can help to add detail and extra points to calculate collisions.", ) gp_physics_type: bpy.props.EnumProperty( items=( ("GEO_NODES", "Geo Nodes Chain", "Collision Physics using custom Geometry Nodes Simulation"), ("SIMP_SOFTBODY", "Soft Body Chain", "Chain Physics using builtin Soft Body Simulation"), ("CLOTH", "Cloth Chain", "Chain Physics using builtin Cloth Simulation"), ("JIGGLE", "Jiggle Physics", "Jiggle Physics using builtin Soft Body Simulation"), ) ) cl_presets: bpy.props.EnumProperty( name="Cloth Chain Presets", items=get_cl_presets, ) sb_presets: bpy.props.EnumProperty( name="Soft Body Chain Presets", items=get_sb_presets, ) jg_presets: bpy.props.EnumProperty( name="Jiggle Physics Presets", items=get_jg_presets, ) gn_presets: bpy.props.EnumProperty( name="Geo Nodes Chain Presets", items=get_gn_presets, ) bm_presets: bpy.props.EnumProperty( name="Bone Map Presets", items=get_bm_presets, ) settings_menu: bpy.props.BoolProperty( default=True, ) gp_physics_active: bpy.props.BoolProperty( default=True, update=toggle_physics_status ) chain_menu: bpy.props.BoolProperty( default=True, ) bone_menu: bpy.props.BoolProperty( default=True, ) cl_time_menu: bpy.props.BoolProperty( default=True, ) cl_physical_menu: bpy.props.BoolProperty( default=True, ) cl_structure_menu: bpy.props.BoolProperty( default=True, ) cl_collision_menu: bpy.props.BoolProperty( default=True, ) sb_time_menu: bpy.props.BoolProperty( default=True, ) sb_physical_menu: bpy.props.BoolProperty( default=True, ) sb_structure_menu: bpy.props.BoolProperty( default=True, ) sb_collision_menu: bpy.props.BoolProperty( default=True, ) jg_physical_menu: bpy.props.BoolProperty( default=True, ) jg_collision_menu: bpy.props.BoolProperty( default=True, ) gn_general_menu: bpy.props.BoolProperty( default=True, ) gn_stiff_menu: bpy.props.BoolProperty( default=True, ) gn_stiff_adv_menu: bpy.props.BoolProperty( default=False, ) gn_wind_menu: bpy.props.BoolProperty( default=True, ) gn_collision_menu: bpy.props.BoolProperty( default=True, ) keep_existing_settings: bpy.props.BoolProperty( default=False, name="Keep Existing Settings", description="When readding a physics type to bones it will keep the previously set settings. Otherwise it will load in the active preset" ) has_bte: bpy.props.BoolProperty( default=False, ) apply_to_all_chains: bpy.props.BoolProperty( default=True, name="Auto Update All Selected Chains", description="Any physics settings change for the active chain will apply to all selected bone chains of the same physics mode", ) apply_to_all_bones: bpy.props.BoolProperty( default=True, name="Auto Update All Selected Bones", description="Any physics settings change for the active bone will apply to all selected bones of the same physics mode", ) precaching: bpy.props.BoolProperty( default=False, ) active_timeline_sync_frames: StringProperty( default="", ) timeline_sync_frames: StringProperty( default="", ) def draw(self, context): layout = self.layout column = layout.column(align=True) row = column.row(align=True) row.prop(self, "apply_to_all_chains") row = column.row(align=True) row.prop(self, "apply_to_all_bones") row = column.row(align=True) row.prop(self, "keep_existing_settings") row = column.row(align=True) row.prop(self, "gp_divisions") row = column.row(align=True) row.prop(self, "gp_physics_type", text="Phyics Type") # # # _classes = [ GooPhysicsPreferences ] _register, _unregister = register_classes_factory(_classes) def register(): _register() bpy.app.handlers.animation_playback_pre.append(timeline_sync_handler_playback_pre) bpy.app.handlers.animation_playback_post.append(timeline_sync_handler_playback_post) bpy.types.PoseBone.gp_chain_wind_strength = FloatProperty( default=1.0, min=0.0, max=100.0, description="Amplitude of the wind in the Z axis direction of the wind controller (the direction the arrow is pointing)", update=update_chain_wind_strength, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_wind_noise_strength = FloatProperty( default=0.1, min=0.0, max=100.0, description="Amplitude of the noise applied over time along the X/Y axis of the wind controller", update=update_chain_wind_noise_strength, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_wind_noise_scale = FloatProperty( default=1.0, min=-100.0, max=100.0, description="Frequency or speed of the wind X/Y noise", update=update_chain_wind_noise_scale, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_dampening = FloatProperty( default=0.1, min=0.0, max=1.0, description="The amount of slow down applied to the forces applied to the simulation chain", update=update_chain_dampening, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_root_falloff = FloatProperty( default=0.25, min=0.0, max=1.0, description="0-1 factor for how much the base of the simulation chain follows the motion of its parent", update=update_chain_root_falloff, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_velocity = FloatProperty( default=1.0, min=0.01, max=5.0, description="Overall scaler for the simulation forces applied to the simulation chain", update=update_chain_velocity, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_gravity = FloatProperty( default=0.02, min=-10.0, max=10.0, description="Strength of the gravity forces applied to the simulation", update=update_chain_gravity, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_stiffness = FloatProperty( default=0.25, min=0.0, max=1.0, description="The amount of stiffness or resistance to bending on the simulation chain", update=update_chain_stiffness, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_stiff_end_fac = FloatProperty( default=0.25, min=0.0, max=1.0, description="An additional factor for stiffness applied to the last bone of the chain allowing for extra overlapping motion at the end", update=update_chain_stiff_end_fac, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_stiff_vel_fac = FloatProperty( default=0.2, min=0.0, max=1.0, description="Scaling factor of chain's stiffness when moving at the max velocity. Lower value makes the chain less stiff during fast motion", update=update_chain_velocity_fac, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_stiff_vel_min = FloatProperty( default=0.1, min=0.0, max=10.0, description="Minimum velocity the chain is moving to start scaling down stiffness", update=update_chain_velocity_min, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_stiff_vel_max = FloatProperty( default=1.0, min=0.0, max=10.0, description="Maximum velocity the chain is moving to fully scale down stiffness", update=update_chain_velocity_max, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_use_collision = BoolProperty( default=True, description="Simulation tests collisions against the objects in the collision collection", update=update_chain_use_collision, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_collision_dist = FloatProperty( default=0.01, min=0.0, max=10.0, description="Extra distance to search for a collision", update=update_chain_collision_dist, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_collision_friction = FloatProperty( default=0.25, min=0.0, max=1.0, description="Scaler for the velocities applied to a chain point when it is colliding", update=update_chain_friction, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_limit_collision = BoolProperty( default=False, description="Limits the collisions of the chain to the typed collection", update=update_chain_limit_collision, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) # bpy.types.PoseBone.gp_chain_speed = FloatProperty( default=2.0, min=0.01, max=5.0, description="Simulation timescale of the chain", update=update_chain_speed, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_mass = FloatProperty( default=0.3, min=0.0, max=50000.0, description="How heavy the chain of the simulation is", update=update_chain_mass, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_air_dampening = FloatProperty( default=0.5, min=0.0, max=10.0, description="Air dampening slows down the chain physics as they fall downwards", update=update_chain_air_dampening, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_chain_bend_damping = FloatProperty( default=0.5, min=0.0, max=1000.0, description="Amount of dampening applied to the bending of the chain", update=update_chain_bend_damping, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) # bpy.types.PoseBone.gp_sim_speed = FloatProperty( default=0.8, min=0.01, max=5.0, description="Simulation timescale of the bone", update=update_bones_speed, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_sim_friction = FloatProperty( default=5.0, min=0.0, max=50.0, description="Friction of the bones simulation", update=update_bones_friction, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_sim_mass = FloatProperty( default=0.15, min=0.0, max=50000.0, description="How heavy the bone of the simulation chain is", update=update_bones_mass, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_sim_stiffness = FloatProperty( default=0.1, min=0.0, max=1.0, description="Stiffness of the bones original shape spring during simulation", update=update_bones_stiffness, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_sim_damping = FloatProperty( default=8.0, min=0.0, max=50.0, description="Amount of damping applied to the bones original shape strength", update=update_bones_damping, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_sim_strength = FloatProperty( default=0.95, min=0.0, max=1.0, description="Strength of the bones original shape during simulation", update=update_bones_strength, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_sim_influence = FloatProperty( default=1.0, min=0.0, max=1.0, description="0-1 influence of how much the bone follows the simulation", update=update_bones_influence, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_sim_air_dampening = FloatProperty( default=1.0, min=0.0, max=10.0, description="Air dampening slows down the bone physics as they fall downwards", update=update_bones_air_dampening, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_sim_bend_damping = FloatProperty( default=10.0, min=0.0, max=1000.0, description="Amount of dampening applied to the bending of the chain", update=update_bones_bend_damping, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_sim_use_collision = BoolProperty( default=True, description="Simulation tests collisions against the objects in the collision collection", update=update_bones_use_collision, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_sim_limit_collision = BoolProperty( default=False, description="Limits the collisions of the bone to the typed collection", update=update_bones_limit_collision, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_sim_gravity = FloatProperty( default=1.0, min=-10.0, max=10.0, description="Controls the amount gravity effects the simulation", update=update_bones_gravity, options={"LIBRARY_EDITABLE",}, override={"LIBRARY_OVERRIDABLE"}, ) bpy.types.PoseBone.gp_sim_object = StringProperty( default="", options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"} ) bpy.types.PoseBone.gp_chain_id = StringProperty( default="", options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"} ) bpy.types.PoseBone.gp_has_sb_physics = BoolProperty( default=False, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"} ) bpy.types.PoseBone.gp_has_gn_physics = BoolProperty( default=False, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"} ) bpy.types.PoseBone.gp_has_jg_physics = BoolProperty( default=False, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"} ) bpy.types.PoseBone.gp_has_cl_physics = BoolProperty( default=False, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"} ) bpy.types.PoseBone.gp_update = BoolProperty(default=True, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"}) bpy.types.PoseBone.gp_end_of_chain = BoolProperty(default=False, options={"LIBRARY_EDITABLE"}, override={"LIBRARY_OVERRIDABLE"}) bpy.utils.register_class(gp_bone_props) bpy.utils.register_class(gp_bone_collection) bpy.types.Object.gp_bone_coll = PointerProperty(type=gp_bone_collection) def unregister(): _unregister() bpy.app.handlers.animation_playback_pre.remove(timeline_sync_handler_playback_pre) bpy.app.handlers.animation_playback_post.remove(timeline_sync_handler_playback_post) bpy.utils.unregister_class(gp_bone_props) bpy.utils.unregister_class(gp_bone_collection) del bpy.types.Object.gp_bone_coll