def create_put_down_in_slot_type_constraint(sim, target, slot_types_and_costs): constraints = [] for (slot_type, cost) in slot_types_and_costs: if cost is None: pass slot_manifest_entry = SlotManifestEntry(target, PostureSpecVariable.ANYTHING, slot_type) slot_manifest = SlotManifest((slot_manifest_entry, )) posture_state_spec_stand = PostureStateSpec( STAND_POSTURE_MANIFEST, slot_manifest, PostureSpecVariable.ANYTHING) posture_constraint_stand = Constraint( debug_name='PutDownInSlotTypeConstraint_Stand', posture_state_spec=posture_state_spec_stand, cost=cost) constraints.append(posture_constraint_stand) posture_state_spec_sit = PostureStateSpec(SIT_POSTURE_MANIFEST, slot_manifest, PostureSpecVariable.ANYTHING) posture_constraint_sit = Constraint( debug_name='PutDownInSlotTypeConstraint_Sit', posture_state_spec=posture_state_spec_sit, cost=cost) constraints.append(posture_constraint_sit) if not constraints: return Nowhere() final_constraint = create_constraint_set(constraints) return final_constraint
def generate_constraint(self, build_convex=DEFAULT): self._distance_map = [None] * self._map_divisions self._connection_map = [None] * self._map_divisions self._connection_index = 0 self._collect_segments() vertices = self._render_vertices() segments = self._simplify_geometry(vertices) if build_convex is DEFAULT: build_convex = self.build_convex if build_convex: try: convex_segments = list(self.maximal_convex(vertices)) except RuntimeError as ex: logger.error('{}: {}'.format( ex, ','.join(str(v) for v in vertices))) self._constraint_convex = Nowhere() return simple_convex = self._simplify_geometry(convex_segments) maximal_convex_polygon = self._make_compound_polygon( [simple_convex]) self._constraint_convex = Constraint( debug_name='LineOfSightConvex', routing_surface=self._routing_surface, geometry=sims4.geometry.RestrictedPolygon( maximal_convex_polygon, [])) else: maximal_convex_polygon = None self._constraint_convex = Nowhere() convex_polygons = self._concave_to_convex(segments) cp = self._make_compound_polygon(convex_polygons) self._constraint = Constraint( debug_name='LineOfSight', routing_surface=self._routing_surface, geometry=sims4.geometry.RestrictedPolygon(cp, []))
def push_dismount_affordance(self, sim, final_location, depend_on_si=None): if sim.posture.is_vehicle: constraint = sim.posture_state.posture_constraint else: constraint = self._create_drive_posture_constraint( self.drive_affordance.provided_posture_type) radius = max( self.owner.routing_component.object_radius * self.object_radius_dismount_multiplier, self.ideal_route_radius) circle_constraint = None wading_interval = TunedInterval(0.1, 0.1) (min_water_depth, max_water_depth) = OceanTuning.make_depth_bounds_safe_for_surface( sim.routing_surface, wading_interval) if not (min_water_depth is None and max_water_depth is None): water_constraint = Constraint(min_water_depth=min_water_depth, max_water_depth=max_water_depth) if water_constraint.is_location_water_depth_valid(final_location): constraint = constraint.intersect(water_constraint) else: large_radius = max(self.minimum_route_distance, radius) circle_constraint = Circle( final_location.transform.translation, large_radius, sim.routing_surface, ideal_radius=self.ideal_route_radius, los_reference_point=DEFAULT) water_constraint = water_constraint.intersect( circle_constraint) if water_constraint.is_any_geometry_water_depth_valid(): constraint = constraint.intersect(water_constraint) else: constraint = constraint.intersect(circle_constraint) circle_constraint = None if circle_constraint is None: circle_constraint = Circle(final_location.transform.translation, radius, sim.routing_surface, ideal_radius=self.ideal_route_radius, los_reference_point=DEFAULT) constraint = constraint.intersect(circle_constraint) proxy_obj = services.terrain_service.TerrainService.create_surface_proxy_from_location( final_location) constraint = constraint.intersect(circle_constraint) return self._push_affordance( sim, interactions.utils.satisfy_constraint_interaction. SatisfyConstraintSuperInteraction, proxy_obj, depend_on_si=depend_on_si, constraint_to_satisfy=constraint, name_override='DismountVehicle')
def create_constraint(self, sim, target=None, target_position=DEFAULT, routing_surface=DEFAULT, **kwargs): if target is None: target = sim if routing_surface is DEFAULT: routing_surface = target.intended_routing_surface plex_service = services.get_plex_service() zone_id = services.current_zone_id() if not plex_service.is_zone_a_plex(zone_id): return self.non_plex_constraint.constraint level = routing_surface.secondary_id polygons = plex_service.get_plex_polygons(level) if not polygons: return Nowhere('PlexConstraint: plex {} not on level {}', zone_id, level) compound_polygon = CompoundPolygon(polygons) restricted_polygon = RestrictedPolygon(compound_polygon, []) constraint = Constraint( geometry=restricted_polygon, routing_surface=routing_surface, debug_name='Plex zone id: {}, level: {}'.format(zone_id, level)) return constraint
def _cache_mobile_posture_constraint(cls): if cls._posture_at_none_constraint is None: cls._posture_at_none_posture_state_spec = create_body_posture_state_spec( cls.get_provided_postures(), body_target=None) cls._posture_at_none_constraint = Constraint( debug_name='{}@None'.format(cls.name), posture_state_spec=cls._posture_at_none_posture_state_spec)
def routing_debug_generate_routing_goals_from_geometry( *args, obj: OptionalTargetParam = None, _connection=None): output = sims4.commands.Output(_connection) obj = get_optional_target(obj, _connection=_connection) if obj is None: return False routing_component = obj.get_component(ROUTING_COMPONENT) if routing_component is None: return False total_string = ''.join(args) polygon_strs = find_substring_in_repr(total_string, POLYGON_STR, POLYGON_END_PARAM) if not polygon_strs: output('No valid polygons. must start with {} and end with {}'.format( POLYGON_STR, POLYGON_END_PARAM)) return constraints = [] routing_surface = routing.SurfaceIdentifier( services.current_zone_id(), 0, routing.SurfaceType.SURFACETYPE_OBJECT) for poly_str in polygon_strs: point_list = extract_floats(poly_str) if not point_list or len(point_list) % 2 != 0: output('Point list is not valid length. Too few or one too many.') return vertices = [] for index in range(0, len(point_list), 2): vertices.append( sims4.math.Vector3(point_list[index], 0.0, point_list[index + 1])) polygon = sims4.geometry.Polygon(vertices) geometry = RestrictedPolygon(polygon, []) constraints.append( Constraint(geometry=geometry, routing_surface=routing_surface)) constraint_set = create_constraint_set(constraints) if not postures.posture_graph.enable_debug_goals_visualization: sims4.commands.execute('debugvis.goals.enable', _connection) handles = constraint_set.get_connectivity_handles(obj) handles_str = 'Handles: {}'.format(len(handles)) sims4.commands.output(handles_str, _connection) all_goals = [] for handle in handles: goal_list = handle.get_goals() goals_str = '\tGoals: {}'.format(len(goal_list)) sims4.commands.output(goals_str, _connection) all_goals.extend(goal_list) if postures.posture_graph.enable_debug_goals_visualization: for constraint in constraints: with debugvis.Context( 'goal_scoring', routing_surface=constraint.routing_surface) as layer: for polygon in constraint.geometry.polygon: layer.add_polygon( polygon, routing_surface=constraint.routing_surface) for goal in all_goals: position = goal.location.transform.translation layer.add_point(position, routing_surface=constraint.routing_surface)
def _create_drive_posture_constraint(self, posture_type): posture_manifest = PostureManifest() entry = PostureManifestEntry(AnimationParticipant.ACTOR, posture_type.name, posture_type.family_name, MATCH_ANY, MATCH_NONE, MATCH_NONE, MATCH_ANY, None) posture_manifest.add(entry) posture_manifest = posture_manifest.intern() posture_state_spec = PostureStateSpec(posture_manifest, SlotManifest(), PostureSpecVariable.ANYTHING) return Constraint(posture_state_spec=posture_state_spec, debug_name='VehiclePostureConstraint')
class GoHereSuperInteraction(TerrainSuperInteraction): __qualname__ = 'GoHereSuperInteraction' POSTURE_MANIFEST = PostureManifest( (PostureManifestEntry(None, 'stand', '', 'FullBody', MATCH_ANY, MATCH_ANY, MATCH_NONE), )).intern() POSTURE_STATE_SPEC = PostureStateSpec(POSTURE_MANIFEST, SlotManifest().intern(), None) CONSTRAINT = Constraint(debug_name='GoHere', posture_state_spec=POSTURE_STATE_SPEC, allow_small_intersections=True) _ignores_spawn_point_footprints = True @classmethod def _test(cls, target, context, **kwargs): (position, surface) = cls._get_position_and_surface(target, context) if position is None: return TestResult(False, 'Cannot go here without a pick or target.') routing_location = routing.Location(position, sims4.math.Quaternion.IDENTITY(), surface) if not routing.test_connectivity_permissions_for_handle( routing.connectivity.Handle(routing_location), context.sim.routing_context): return TestResult(False, 'Cannot GoHere! Unroutable area.') return TestResult.TRUE @classmethod def potential_interactions(cls, target, context, **kwargs): (position, surface) = cls._get_position_and_surface(target, context) if position is not None and context is not None and context.sim is not None: main_group = context.sim.get_visible_group() if main_group is not None and not main_group.is_solo: group_constraint = next( iter(main_group.get_constraint(context.sim))) if group_constraint is not None and group_constraint.routing_surface == surface: while True: for constraint in group_constraint: group_geometry = constraint.geometry while group_geometry is not None and group_geometry.contains_point( position): yield AffordanceObjectPair(cls, target, cls, None, ignore_party=True, **kwargs) return if cls._can_rally(context): for aop in cls.get_rallyable_aops_gen(target, context, **kwargs): yield aop yield cls.generate_aop(target, context, **kwargs)
def create_put_down_in_slot_type_constraint(sim, carry_target, slot_types_and_costs, target=None): constraints = [] for (slot_type, cost) in slot_types_and_costs: if cost is None: continue if target is not None and target is not carry_target: slot_manifest_entry = SlotManifestEntry( carry_target, PostureSpecVariable.INTERACTION_TARGET, slot_type) else: slot_manifest_entry = SlotManifestEntry( carry_target, PostureSpecVariable.ANYTHING, slot_type) slot_manifest = SlotManifest((slot_manifest_entry, )) posture_state_spec_stand = PostureStateSpec( STAND_POSTURE_MANIFEST, slot_manifest, PostureSpecVariable.ANYTHING) posture_constraint_stand = Constraint( debug_name='PutDownInSlotTypeConstraint_Stand', posture_state_spec=posture_state_spec_stand, cost=cost) constraints.append(posture_constraint_stand) posture_state_spec_sit = PostureStateSpec(SIT_POSTURE_MANIFEST, slot_manifest, PostureSpecVariable.ANYTHING) posture_constraint_sit = Constraint( debug_name='PutDownInSlotTypeConstraint_Sit', posture_state_spec=posture_state_spec_sit, cost=cost) constraints.append(posture_constraint_sit) if not constraints: return Nowhere( 'Carry Target has no slot types or costs tuned for put down: {} Sim:{}', carry_target, sim) final_constraint = create_constraint_set(constraints) return final_constraint
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) sim = self._context.sim self._routing_surface = routing.SurfaceIdentifier( self._routing_surface.primary_id, self._routing_surface.secondary_id, routing.SurfaceType.SURFACETYPE_POOL) position = self._target.position if self._target is not None else sim.position level = self._routing_surface.secondary_id self._start_constraint = None self._master_depth_constraint = None self._waypoint_constraints = [] self.keep_away_constraint = None self._location_is_pool = build_buy.is_location_pool(position, level) if self._location_is_pool: pool_block_id = build_buy.get_block_id(sim.zone_id, position, level - 1) pool = pool_utils.get_pool_by_block_id(pool_block_id) if pool is not None: pool_edge_constraints = pool.get_edge_constraint( constraint_width=self.constraint_width, inward_dir=True, return_constraint_list=True) pool_edge_constraints = [ constraint.generate_geometry_only_constraint() for constraint in pool_edge_constraints ] if self.keep_away_from_edges is not None: bb_polys = build_buy.get_pool_polys( pool_block_id, level - 1) if len(bb_polys) > 0: bb_poly = bb_polys[0] _WaypointGeneratorPool._push_poly_inward( bb_poly, self.keep_away_from_edges) bb_poly.reverse() keep_away_geom = sims4.geometry.RestrictedPolygon( sims4.geometry.Polygon(bb_poly), ()) self.keep_away_constraint = Constraint( routing_surface=pool.provided_routing_surface, geometry=keep_away_geom) else: logger.error( f'Pool Waypoint Generator: Pool polygon data unexpectedly empty while ${sim} was routing on a pool with id ${pool_block_id}.', owner='jmorrow') for i in range(len(pool_edge_constraints)): pool_edge_constraints[i] = pool_edge_constraints[ i].intersect(self.keep_away_constraint) self._start_constraint = create_constraint_set( pool_edge_constraints) self._waypoint_constraints = pool_edge_constraints
def get_edge_constraint(self, constraint_width=1.0, inward_dir=False, return_constraint_list=False, los_reference_point=DEFAULT, sim=None): edges = self.get_edges() polygons = [] for (start, stop) in edges: along = sims4.math.vector_normalize(stop - start) inward = sims4.math.vector3_rotate_axis_angle(along, sims4.math.PI/2, sims4.math.Vector3.Y_AXIS()) if inward_dir: polygon = sims4.geometry.Polygon([start, start + constraint_width*inward, stop + constraint_width*inward, stop]) else: polygon = sims4.geometry.Polygon([start, stop, stop - constraint_width*inward, start - constraint_width*inward]) polygons.append(polygon) routing_surface = self.routing_surface if return_constraint_list: constraint_list = [] for polygon in polygons: restricted_polygon = sims4.geometry.RestrictedPolygon(polygon, ()) constraint = Constraint(routing_surface=routing_surface, geometry=restricted_polygon, los_reference_point=los_reference_point, posture_state_spec=STAND_AT_NONE_POSTURE_STATE_SPEC) constraint_list.append(constraint) return constraint_list else: geometry = sims4.geometry.RestrictedPolygon(sims4.geometry.CompoundPolygon(polygons), ()) constraint = Constraint(routing_surface=routing_surface, geometry=geometry, posture_state_spec=STAND_AT_NONE_POSTURE_STATE_SPEC) return constraint
def _generate_cluster(self, position, objects): radius = self._get_cluster_radius(position, objects) los = LineOfSight(radius, self.line_of_sight_constraint.map_divisions, self.line_of_sight_constraint.simplification_ratio, self.line_of_sight_constraint.boundary_epsilon) routing_surface = next(iter(objects)).routing_surface los.generate(position, routing_surface, build_convex=True) valid_objects = [] rejects = [] if los.constraint_convex.geometry is not None: for obj in objects: for polygon in los.constraint_convex.geometry.polygon: while test_point_in_polygon( obj.lineofsight_component.default_position, polygon): valid_objects.append(obj) break rejects.append(obj) else: rejects = objects if not valid_objects: (rejected_ne, rejected_nw, rejected_se, rejected_sw) = ([], [], [], []) for reject in rejects: reject_position = reject.lineofsight_component.default_position if reject_position.x >= position.x and reject_position.z >= position.z: rejected_ne.append(reject) elif reject_position.z >= position.z: rejected_nw.append(reject) elif reject_position.x < position.x and reject_position.z < position.z: rejected_sw.append(reject) else: rejected_se.append(reject) return (rejected_ne, rejected_nw, rejected_se, rejected_sw) convex_hull_poly = self._get_cluster_polygon(position, valid_objects) convex_hull_constraint = Constraint( debug_name='ClusterConvexHull', routing_surface=routing_surface, allow_small_intersections=True, geometry=sims4.geometry.RestrictedPolygon(convex_hull_poly, [])) cluster_constraint = los.constraint_convex.intersect( convex_hull_constraint) if cluster_constraint.valid: cluster = ObjectCluster(position, cluster_constraint, valid_objects, routing_surface) self._clusters.append(cluster) return [rejects]
def polygon_intersection(*args, _connection=None): output = sims4.commands.Output(_connection) total_string = ''.join(args) polygon_strs = find_substring_in_repr(total_string, POLYGON_STR, POLYGON_END_PARAM) if not polygon_strs: output('No valid polygons. must start with {} and end with {}'.format( POLYGON_STR, POLYGON_END_PARAM)) return constraints = [] for poly_str in polygon_strs: point_list = extract_floats(poly_str) if not point_list or len(point_list) % 2 != 0: output('Point list is not valid length. Too few or one too many.') return vertices = [] for index in range(0, len(point_list), 2): vertices.append( sims4.math.Vector3(point_list[index], 0.0, point_list[index + 1])) polygon = sims4.geometry.Polygon(vertices) geometry = sims4.geometry.RestrictedPolygon(polygon, []) constraint = Constraint(geometry=geometry, routing_surface=routing.SurfaceIdentifier( services.current_zone_id(), 0, routing.SurfaceType.SURFACETYPE_WORLD)) constraints.append(constraint) intersection = ANYWHERE for constraint in constraints: new_intersection = intersection.intersect(constraint) if not new_intersection.valid: output( 'Constraint intersection failed. Drawing incompatible geometry. {}' .format(new_intersection)) if intersection.geometry is not None: draw_geometry_in_string(str(intersection.geometry), _connection=_connection) draw_geometry_in_string(str(constraint.geometry), _connection=_connection) return intersection = new_intersection if intersection.valid: draw_geometry_in_string(str(intersection.geometry), _connection=_connection) output('Intersection valid. Drawing Polygon.')
def get_water_constraint(self, min_water_depth=None, max_water_depth=None): water_constraint_key = (min_water_depth, max_water_depth) if water_constraint_key in self._water_constraint: return self._water_constraint[water_constraint_key] if self._context.sim is not None: (min_water_depth, max_water_depth) = OceanTuning.make_depth_bounds_safe_for_surface_and_sim(self._routing_surface, self._context.sim, min_water_depth, max_water_depth) if self._target is not None: if self._target is not self._context.sim: (min_water_depth, max_water_depth) = OceanTuning.make_depth_bounds_safe_for_surface_and_sim(self._routing_surface, self._target, min_water_depth, max_water_depth) if self.is_for_vehicle: wading_interval = TunedInterval(0.1, 0.1) (min_water_depth, max_water_depth) = OceanTuning.make_depth_bounds_safe_for_surface(self._routing_surface, wading_interval, min_water_depth, max_water_depth) if min_water_depth is None and max_water_depth is None: constraint = ANYWHERE else: constraint = Constraint(min_water_depth=min_water_depth, max_water_depth=max_water_depth) self._water_constraint[water_constraint_key] = constraint return constraint
def get_inventory_access_constraint( self, sim, is_put, carry_target, use_owner_as_target_for_resolver=False): carry_posture = self.owner.posture_state.get_carry_posture( carry_target) if carry_posture is not None: posture_manifest = carry_posture.get_provided_postures( species=sim.species) if sim.species != Species.DOG: posture_manifest = posture_manifest.__class__( e for e in posture_manifest if e.specific != 'swim') posture_manifest = posture_manifest.replace_actor( for_actor=self.owner) posture_state_spec = create_body_posture_state_spec( posture_manifest) return Constraint(posture_state_spec=posture_state_spec) return STAND_OR_SIT_CONSTRAINT
def get_start_constraint(self): constraint = self.get_water_constraint() sim = self._context.sim supported_postures = self._target.provided_mobile_posture_types if self._target.footprint_polygon.contains( sim.position ) and sim.posture.posture_type in supported_postures and sim.level == self._target.level: return constraint transform = self._target.transform corners = [ transform.transform_point(sims4.math.Vector3( corner.x, 0, corner.z)) for corner in self.get_corners() ] corners.reverse() geometry = sims4.geometry.RestrictedPolygon( sims4.geometry.CompoundPolygon(sims4.geometry.Polygon(corners)), ()) return constraint.intersect( Constraint(geometry=geometry, debug_name='FootprintConstraint', routing_surface=self._routing_surface))
def _constraint_gen(cls, *args, **kwargs): yield Constraint(debug_name='PickUpObjectSuperInteraction({})'.format(cls.si_to_push), posture_state_spec=CARRY_TARGET_POSTURE_STATE_SPEC)
def _create_constraint_set(self, sim, timeline): orient = sims4.math.Quaternion.IDENTITY() positions = services.current_zone().lot.corners position = positions[0] routing_surface = self._privacy.constraint.get_world_routing_surface( force_world=True) if self._privacy._routing_surface_only: routing_surfaces = (routing_surface, ) else: routing_surfaces = self._privacy.constraint.get_all_valid_routing_surfaces( ) goals = [] center_pos = services.current_zone().lot.position for pos in positions: plex_service = services.get_plex_service() if plex_service.is_active_zone_a_plex(): towards_center_vec = sims4.math.vector_normalize(center_pos - pos) pos = pos + towards_center_vec * self.PLEX_LOT_CORNER_ADJUSTMENT pos.y = services.terrain_service.terrain_object( ).get_routing_surface_height_at(pos.x, pos.z, routing_surface) if not sims4.geometry.test_point_in_compound_polygon( pos, self._privacy.constraint.geometry.polygon): for surface in routing_surfaces: goals.append( routing.Goal(routing.Location(pos, orient, surface))) obj_pos = self._privacy.central_object.position for offset in self._privacy.additional_exit_offsets: goals.append( routing.Goal( routing.Location(obj_pos + Vector3(offset.x, 0, offset.y), orient, surface))) if not goals: return Nowhere( 'BuildAndForceSatisfyShooConstraintInteraction, Could not generate goals to exit a privacy region, Sim: {} Privacy Region: {}', sim, self._privacy.constraint.geometry.polygon) yield route = routing.Route(sim.routing_location, goals, routing_context=sim.routing_context) plan_primitive = PlanRoute(route, sim, reserve_final_location=False, interaction=self) yield from element_utils.run_child(timeline, plan_primitive) max_distance = self._privacy._max_line_of_sight_radius * self._privacy._max_line_of_sight_radius * 4 nodes = [] path = plan_primitive.path while path is not None: nodes.extend(path.nodes) path = path.next_path if nodes: previous_node = nodes[0] for node in nodes: node_vector = sims4.math.Vector3(node.position[0], node.position[1], node.position[2]) if not sims4.geometry.test_point_in_compound_polygon( node_vector, self._privacy.constraint.geometry.polygon): position = node_vector if node.portal_id != 0: continue circle_constraint = interactions.constraints.Circle( position, self.TRIVIAL_SHOO_RADIUS, node.routing_surface_id) if circle_constraint.intersect( self._privacy.constraint).valid: continue break previous_node = node position2 = sims4.math.Vector3(previous_node.position[0], previous_node.position[1], previous_node.position[2]) if (position - position2).magnitude_2d_squared() > max_distance: position = self._find_close_position(position, position2) elif (position - sim.position).magnitude_2d_squared() > max_distance: position = self._find_close_position(position, sim.position) p1 = position p2 = self._privacy.central_object.position forward = sims4.math.vector_normalize(p1 - p2) radius_min = 0 radius_max = self._privacy.shoo_constraint_radius angle = sims4.math.PI (cone_geometry, cost_functions) = build_weighted_cone(position, forward, radius_min, radius_max, angle, ideal_radius_min=0, ideal_radius_max=0, ideal_angle=1) subtracted_cone_polygon_list = [] for cone_polygon in cone_geometry.polygon: for privacy_polygon in self._privacy.constraint.geometry.polygon: subtracted_cone_polygons = cone_polygon.subtract( privacy_polygon) if subtracted_cone_polygons: subtracted_cone_polygon_list.extend( subtracted_cone_polygons) compound_subtracted_cone_polygon = sims4.geometry.CompoundPolygon( subtracted_cone_polygon_list) subtracted_cone_geometry = sims4.geometry.RestrictedPolygon( compound_subtracted_cone_polygon, []) subtracted_cone_constraint = Constraint( geometry=subtracted_cone_geometry, scoring_functions=cost_functions, routing_surface=routing_surface, debug_name='ShooedSimsCone', multi_surface=True, los_reference_point=position) point_cost = 5 point_constraint = interactions.constraints.Position( position, routing_surface=routing_surface, multi_surface=True) point_constraint = point_constraint.generate_constraint_with_cost( point_cost) constraints = (subtracted_cone_constraint, point_constraint) return interactions.constraints.create_constraint_set( constraints, debug_name='ShooPositions') yield
def _constraint_gen(cls, inst, sim, target, participant_type=ParticipantType.Actor): inst_or_cls = inst if inst is not None else cls if participant_type == ParticipantType.Actor and cls.relocate_main_group and (inst is None or inst.pipeline_progress < PipelineProgress.RUNNING): for constraint in super(SuperInteraction, inst_or_cls)._constraint_gen(sim, target, participant_type=participant_type): yield constraint return if inst is None or inst.social_group is None or not inst.social_group.constraint_initialized: for constraint in super(SuperInteraction, inst_or_cls)._constraint_gen(sim, target, participant_type=participant_type): yield constraint if inst is not None and inst.is_finishing: return actor = None if inst is not None: actor = inst.sim target = inst.target_sim if participant_type == ParticipantType.Actor: actor = sim if sim is not None and participant_type == ParticipantType.TargetSim: target = sim if target is None or not target.is_sim: return if actor is not None and actor is not target: (fallback_position, fallback_routing_surface) = get_fallback_social_constraint_position(actor, target, inst) else: fallback_position = None if fallback_position is None: if inst is not None: yield Constraint(allow_geometry_intersections=False) return if inst is not None: picked_object = inst.picked_object else: picked_object = None fallback_constraint = cls._social_group_type.make_constraint_default(actor, target, fallback_position, fallback_routing_surface, participant_type=participant_type, picked_object=picked_object, participant_slot_overrides=inst_or_cls._social_group_participant_slot_overrides) priority = inst.priority if inst is not None else None if sim.si_state.is_compatible_constraint(fallback_constraint, priority=priority, to_exclude=inst) and target.is_sim and target.si_state.is_compatible_constraint(fallback_constraint, priority=priority, to_exclude=inst): yield fallback_constraint else: yield Constraint(allow_geometry_intersections=False) return if participant_type == ParticipantType.TargetSim: if not cls.acquire_targets_as_resource: yield Anywhere() return if inst is not None: (target_si, test_result) = inst.get_target_si() if not test_result: yield Nowhere() return if target_si is not None: target_si_target = target_si.get_participant(ParticipantType.TargetSim) for constraint in target_si.constraint_gen(sim, target_si_target, participant_type=ParticipantType.Actor): yield constraint return for constraint in super(SuperInteraction, cls)._constraint_gen(sim, target, participant_type=participant_type): yield constraint if inst is not None: if inst.social_group is not None: yield inst.social_group.get_constraint(sim) else: logger.error('Attempt to get constraint from Social interaction and no constraint exists: {}', inst, owner='maxr') yield Anywhere() return elif participant_type == ParticipantType.Actor: for constraint in super(SuperInteraction, inst_or_cls)._constraint_gen(sim, target, participant_type=participant_type): yield constraint if inst is not None: if inst.social_group is not None and participant_type == ParticipantType.Actor: yield inst.social_group.get_constraint(sim)
def __init__(self, sim, current_posture_state, posture_spec, var_map, invalid_expected=False, body_state_spec_only=False, carry_posture_overrides=frozendict(), is_throwaway=False): def _get_default_carry_aspect(track): if track in carry_posture_overrides: return carry_posture_overrides[track] return postures.create_posture( CarryPostureStaticTuning.POSTURE_CARRY_NOTHING, sim, None, track=track) self._constraint_intersection = None self._constraint_intersection_dirty = True self._spec = posture_spec self._sim_ref = sim.ref() self._linked_posture_state = None self._valid = True self._constraints = {} self._invalid_expected = invalid_expected self.body_state_spec_only = body_state_spec_only self._posture_constraint = None self._posture_constraint_strict = None body_index = BODY_INDEX body_posture_type_index = BODY_POSTURE_TYPE_INDEX body_target_index = BODY_TARGET_INDEX spec_body = posture_spec[body_index] self.body_target = spec_body[body_target_index] if current_posture_state is None or spec_body[ body_posture_type_index] != current_posture_state.body.posture_type or spec_body[ body_target_index] != current_posture_state.body.target: animation_context = None if current_posture_state is not None: if not current_posture_state.body.mobile: if not spec_body[body_posture_type_index].mobile: animation_context = current_posture_state.body.animation_context self._aspect_body = postures.create_posture( spec_body[body_posture_type_index], self.sim, self.body_target, animation_context=animation_context, is_throwaway=is_throwaway) else: self._aspect_body = current_posture_state.body posture_manifest = self._aspect_body.get_provided_postures( surface_target=self.surface_target, concrete=True) posture_manifest = posture_manifest.get_constraint_version(self.sim) posture_state_spec = PostureStateSpec( posture_manifest, SlotManifest(), self._aspect_body.target or PostureSpecVariable.ANYTHING) self.body_posture_state_constraint = Constraint( debug_name='PostureStateManifestConstraint', posture_state_spec=posture_state_spec) if body_state_spec_only: self._constraints[None] = self.body_posture_state_constraint return body_slot_constraint = self._aspect_body.slot_constraint if not (body_slot_constraint is not None and (self._aspect_body.is_vehicle and current_posture_state is not None) and current_posture_state.body.is_vehicle): body_posture_constraint = self.body_posture_state_constraint.intersect( body_slot_constraint) else: body_posture_constraint = self.body_posture_state_constraint self._constraints[None] = body_posture_constraint if current_posture_state is not None: curr_spec_carry_target = current_posture_state.get_posture_spec( var_map)[CARRY_INDEX][CARRY_TARGET_INDEX] spec_carry = posture_spec[CARRY_INDEX] spec_carry_target = spec_carry[CARRY_TARGET_INDEX] if current_posture_state is not None and spec_carry_target != curr_spec_carry_target: if spec_carry_target is None: current_carry_target = var_map.get(curr_spec_carry_target) current_carry_track = current_posture_state.get_carry_track( current_carry_target) if current_carry_track == PostureTrack.RIGHT: self._aspect_carry_right = _get_default_carry_aspect( PostureTrack.RIGHT) self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_left = _get_default_carry_aspect( PostureTrack.LEFT) self._aspect_carry_right = current_posture_state.right else: spec_carry_posture_type = spec_carry[CARRY_POSTURE_TYPE_INDEX] if spec_carry_target not in var_map: raise KeyError( 'spec_carry_target {} not in var_map:{}. Sim posture state {} and carry aspects {}, ' .format(spec_carry_target, var_map, current_posture_state, current_posture_state.carry_aspects)) if spec_carry_posture_type not in var_map: carry_target = var_map[spec_carry_target] aop = posture_specs.get_carry_posture_aop( sim, carry_target) if aop is None: raise RuntimeError( 'Sim {} failed to find carry posture aop for carry target {}.' .format(sim, carry_target)) carry_posture_type = aop.affordance._carry_posture_type if carry_posture_type is None: raise KeyError var_map += { PostureSpecVariable.POSTURE_TYPE_CARRY_OBJECT: carry_posture_type } carry_target = var_map[spec_carry_target] carry_posture_type = var_map[spec_carry_posture_type] if spec_carry[CARRY_HAND_INDEX] in var_map: hand = var_map[spec_carry[CARRY_HAND_INDEX]] else: for hand in sim.posture_state.get_free_hands(): if hand in carry_target.get_allowed_hands(sim): break else: raise RuntimeError('No allowable free hand was empty.') new_carry_aspect = postures.create_posture( carry_posture_type, self.sim, carry_target, track=hand_to_track(hand), is_throwaway=is_throwaway) if hand == Hand.LEFT: self._aspect_carry_left = new_carry_aspect if current_posture_state is not None: self._aspect_carry_right = current_posture_state.right else: self._aspect_carry_right = _get_default_carry_aspect( PostureTrack.RIGHT) elif hand == Hand.RIGHT: self._aspect_carry_right = new_carry_aspect if current_posture_state is not None: self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_right = _get_default_carry_aspect( PostureTrack.LEFT) else: raise RuntimeError( 'Invalid value specified for hand: {}'.format(hand)) elif current_posture_state is not None: self._aspect_carry_left = current_posture_state.left self._aspect_carry_right = current_posture_state.right elif spec_carry_target is not None: carry_target = var_map[spec_carry_target] spec_carry_posture_type = spec_carry[CARRY_POSTURE_TYPE_INDEX] carry_posture_type = var_map.get(spec_carry_posture_type) if carry_posture_type is None: aop = get_carry_posture_aop(sim, carry_target) if aop is None and invalid_expected: return carry_posture_type = aop.affordance._carry_posture_type if spec_carry[CARRY_HAND_INDEX] in var_map: hand = var_map[spec_carry[CARRY_HAND_INDEX]] else: allowed_hands = carry_target.get_allowed_hands(sim) hand = allowed_hands[0] new_carry_aspect = postures.create_posture( carry_posture_type, self.sim, carry_target, track=hand_to_track(hand), is_throwaway=is_throwaway) if hand == Hand.LEFT: self._aspect_carry_left = new_carry_aspect self._aspect_carry_right = _get_default_carry_aspect( PostureTrack.RIGHT) else: self._aspect_carry_right = new_carry_aspect self._aspect_carry_left = _get_default_carry_aspect( PostureTrack.LEFT) else: self._aspect_carry_left = _get_default_carry_aspect( PostureTrack.LEFT) self._aspect_carry_right = _get_default_carry_aspect( PostureTrack.RIGHT)
def get_spawn_point_ignore_constraint(self): objects_to_ignore = set() for spawn_point in self._spawner_data.values(): objects_to_ignore.add(spawn_point.spawn_point_id) return Constraint(objects_to_ignore=objects_to_ignore)
class PostureState: __qualname__ = 'PostureState' def _get_default_carry_aspect(self, track): return postures.create_posture(HoldNothing.CARRY_NOTHING_POSTURE_TYPE, self.sim, None, track=track) def __init__(self, sim, current_posture_state, posture_spec, var_map, invalid_expected=False, body_state_spec_only=False): self._constraint_intersection = None self._constraint_intersection_dirty = True self._spec = posture_spec self._sim_ref = sim.ref() self._linked_posture_state = None self._valid = True self._constraints = {} self._invalid_expected = invalid_expected self.body_state_spec_only = body_state_spec_only self._posture_constraint = None self._posture_constraint_strict = None body_index = BODY_INDEX body_posture_type_index = BODY_POSTURE_TYPE_INDEX body_target_index = BODY_TARGET_INDEX spec_body = posture_spec[body_index] self.body_target = spec_body[body_target_index] if current_posture_state is None or spec_body[body_posture_type_index] != current_posture_state.body.posture_type or spec_body[body_target_index] != current_posture_state.body.target: animation_context = None if current_posture_state is not None and not current_posture_state.body.mobile and not spec_body[body_posture_type_index].mobile: animation_context = current_posture_state.body.animation_context self._aspect_body = postures.create_posture(spec_body[body_posture_type_index], self.sim, self.body_target, animation_context=animation_context) else: self._aspect_body = current_posture_state.body posture_manifest = self._aspect_body.get_provided_postures(surface_target=self.surface_target, concrete=True) posture_manifest = posture_manifest.get_constraint_version(self.sim) posture_state_spec = PostureStateSpec(posture_manifest, SlotManifest(), self._aspect_body.target or PostureSpecVariable.ANYTHING) self.body_posture_state_constraint = Constraint(debug_name='PostureStateManifestConstraint', posture_state_spec=posture_state_spec) if body_state_spec_only: self._constraints[self] = self.body_posture_state_constraint return body_slot_constraint = self._aspect_body.slot_constraint if body_slot_constraint is not None: body_posture_constraint = self.body_posture_state_constraint.intersect(body_slot_constraint) else: body_posture_constraint = self.body_posture_state_constraint self._constraints[self] = body_posture_constraint if current_posture_state is not None: curr_spec_carry_target = current_posture_state.get_posture_spec(var_map)[CARRY_INDEX][CARRY_TARGET_INDEX] spec_carry = posture_spec[CARRY_INDEX] spec_carry_target = spec_carry[CARRY_TARGET_INDEX] if current_posture_state is not None and spec_carry_target != curr_spec_carry_target: if spec_carry_target is None: current_carry_target = var_map.get(curr_spec_carry_target) current_carry_track = current_posture_state.get_carry_track(current_carry_target) if current_carry_track == PostureTrack.RIGHT: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.RIGHT) self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_left = self._get_default_carry_aspect(PostureTrack.LEFT) self._aspect_carry_right = current_posture_state.right spec_carry_posture_type = spec_carry[CARRY_POSTURE_TYPE_INDEX] if spec_carry_target not in var_map: raise KeyError if spec_carry_posture_type not in var_map: aop = posture_specs.get_carry_posture_aop(sim, var_map[spec_carry_target]) carry_posture_type = aop.affordance._carry_posture_type if carry_posture_type is None: raise KeyError var_map += {PostureSpecVariable.POSTURE_TYPE_CARRY_OBJECT: carry_posture_type} carry_target = var_map[spec_carry_target] carry_posture_type = var_map[spec_carry_posture_type] if spec_carry[CARRY_HAND_INDEX] in var_map: hand = var_map[spec_carry[CARRY_HAND_INDEX]] else: for hand in sim.posture_state.get_free_hands(): while hand in carry_target.allowed_hands: break raise RuntimeError('No allowable free hand was empty.') new_carry_aspect = postures.create_posture(carry_posture_type, self.sim, carry_target, track=self.hand_to_track(hand)) if hand == Hand.LEFT: self._aspect_carry_left = new_carry_aspect if current_posture_state is not None: self._aspect_carry_right = current_posture_state.right else: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.RIGHT) if hand == Hand.RIGHT: self._aspect_carry_right = new_carry_aspect if current_posture_state is not None: self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.LEFT) raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) else: raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) elif hand == Hand.RIGHT: self._aspect_carry_right = new_carry_aspect if current_posture_state is not None: self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.LEFT) raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) else: raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) else: spec_carry_posture_type = spec_carry[CARRY_POSTURE_TYPE_INDEX] if spec_carry_target not in var_map: raise KeyError if spec_carry_posture_type not in var_map: aop = posture_specs.get_carry_posture_aop(sim, var_map[spec_carry_target]) carry_posture_type = aop.affordance._carry_posture_type if carry_posture_type is None: raise KeyError var_map += {PostureSpecVariable.POSTURE_TYPE_CARRY_OBJECT: carry_posture_type} carry_target = var_map[spec_carry_target] carry_posture_type = var_map[spec_carry_posture_type] if spec_carry[CARRY_HAND_INDEX] in var_map: hand = var_map[spec_carry[CARRY_HAND_INDEX]] else: for hand in sim.posture_state.get_free_hands(): while hand in carry_target.allowed_hands: break raise RuntimeError('No allowable free hand was empty.') new_carry_aspect = postures.create_posture(carry_posture_type, self.sim, carry_target, track=self.hand_to_track(hand)) if hand == Hand.LEFT: self._aspect_carry_left = new_carry_aspect if current_posture_state is not None: self._aspect_carry_right = current_posture_state.right else: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.RIGHT) if hand == Hand.RIGHT: self._aspect_carry_right = new_carry_aspect if current_posture_state is not None: self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.LEFT) raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) else: raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) elif hand == Hand.RIGHT: self._aspect_carry_right = new_carry_aspect if current_posture_state is not None: self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.LEFT) raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) else: raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) elif current_posture_state is not None: self._aspect_carry_left = current_posture_state.left self._aspect_carry_right = current_posture_state.right elif spec_carry_target is not None: carry_target = var_map[spec_carry_target] spec_carry_posture_type = spec_carry[CARRY_POSTURE_TYPE_INDEX] carry_posture_type = var_map.get(spec_carry_posture_type) if carry_posture_type is None: aop = get_carry_posture_aop(sim, carry_target) if aop is None and invalid_expected: return carry_posture_type = aop.affordance._carry_posture_type if spec_carry[CARRY_HAND_INDEX] in var_map: hand = var_map[spec_carry[CARRY_HAND_INDEX]] else: hand = carry_target.allowed_hands[0] new_carry_aspect = postures.create_posture(carry_posture_type, self.sim, carry_target, track=self.hand_to_track(hand)) if hand == Hand.LEFT: self._aspect_carry_left = new_carry_aspect self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.RIGHT) else: self._aspect_carry_right = new_carry_aspect self._aspect_carry_left = self._get_default_carry_aspect(PostureTrack.LEFT) else: self._aspect_carry_left = self._get_default_carry_aspect(PostureTrack.LEFT) self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.RIGHT) def __repr__(self): return standard_repr(self, *self.aspects) @property def valid(self): return self._valid and bool(self.constraint_intersection) @property def spec(self): return self._spec def get_posture_spec(self, var_map): if not var_map: return self._spec.clone() carry_target = var_map.get(PostureSpecVariable.CARRY_TARGET) or var_map.get(PostureSpecVariable.INTERACTION_TARGET) if carry_target is not None and carry_target.definition is not carry_target and carry_target.carryable_component is not None: carry_posture = self.get_carry_posture(carry_target) else: carry_posture = None if carry_posture is not None: if PostureSpecVariable.HAND in var_map: required_hand = PostureState.track_to_hand(carry_posture.track) if required_hand != var_map[PostureSpecVariable.HAND]: return source_carry = PostureAspectCarry((PostureSpecVariable.POSTURE_TYPE_CARRY_OBJECT, PostureSpecVariable.CARRY_TARGET, PostureSpecVariable.HAND)) else: source_carry = PostureAspectCarry((PostureSpecVariable.POSTURE_TYPE_CARRY_NOTHING, None, PostureSpecVariable.HAND)) surface_spec = self._spec[SURFACE_INDEX] surface_target = surface_spec[SURFACE_TARGET_INDEX] if surface_target is not None: var_map_surface_target = var_map.get(PostureSpecVariable.SURFACE_TARGET, None) if var_map_surface_target is None or surface_target == var_map_surface_target: var_map_carry_target = var_map.get(PostureSpecVariable.CARRY_TARGET, PostureSpecVariable.CARRY_TARGET) if carry_target is not None and (carry_posture is None and carry_target.definition is not carry_target) and not carry_target.is_surface(include_parts=True): surface_spec = PostureAspectSurface((surface_target, PostureSpecVariable.SLOT, PostureSpecVariable.CARRY_TARGET)) spec = self._spec.clone(carry=source_carry, surface=surface_spec) if spec._validate_surface(var_map) and (var_map_carry_target is None or var_map_carry_target.parent is surface_target): return spec surface_spec = PostureAspectSurface((surface_target, PostureSpecVariable.SLOT, None)) spec = self._spec.clone(carry=source_carry, surface=surface_spec) if spec._validate_surface(var_map): return spec surface_spec = PostureAspectSurface((surface_target, None, None)) spec = self._spec.clone(carry=source_carry, surface=surface_spec) if spec._validate_surface(var_map): return spec surface_spec = PostureAspectSurface((None, None, None)) spec = self._spec.clone(carry=source_carry, surface=surface_spec) if spec._validate_surface(var_map): return spec def _get_posture_constraint(self, strict=False): posture_state_constraint = self.body_posture_state_constraint posture_state_constraint = posture_state_constraint.get_holster_version() if posture_state_constraint.valid and not self.body_state_spec_only: carry_left_constraint = carry.create_carry_constraint(self.left.target, Hand.LEFT, strict=strict) posture_state_constraint = posture_state_constraint.intersect(carry_left_constraint) if posture_state_constraint.valid: carry_right_constraint = carry.create_carry_constraint(self.right.target, Hand.RIGHT, strict=strict) posture_state_constraint = posture_state_constraint.intersect(carry_right_constraint) return posture_state_constraint @property def posture_constraint(self): if self._posture_constraint is None: self._posture_constraint = self._get_posture_constraint() return self._posture_constraint @property def posture_constraint_strict(self): if self._posture_constraint_strict is None: self._posture_constraint_strict = self._get_posture_constraint(strict=True) return self._posture_constraint_strict @property def sim(self): if self._sim_ref is not None: return self._sim_ref() @property def linked_posture_state(self): return self._linked_posture_state @linked_posture_state.setter def linked_posture_state(self, posture_state): self._set_linked_posture_state(posture_state) posture_state._set_linked_posture_state(self) self.body.linked_posture = posture_state.body def _set_linked_posture_state(self, posture_state): self._linked_posture_state = posture_state @property def body(self): return self._aspect_body @property def left(self): return self._aspect_carry_left @property def right(self): return self._aspect_carry_right @property def aspects(self): if self.body_state_spec_only: return () return (self.body, self.left, self.right) @property def carry_aspects(self): return (self.left, self.right) @property def surface_target(self): surface = self._spec[SURFACE_INDEX][SURFACE_TARGET_INDEX] if (surface is None or self.body.mobile) and self.body.target is not None and self.body.target.is_surface(): return self.body.target return surface @property def carry_targets(self): return (self.left.target, self.right.target) def get_aspect(self, track): if track == PostureTrack.BODY: return self.body if track == PostureTrack.LEFT: return self.left if track == PostureTrack.RIGHT: return self.right @property def has_geometry(self): raise RuntimeError('[bhill] This function is believed to be dead code and is scheduled for pruning. If this exception has been raised, the code is not dead and this exception should be removed.') constraint_insteraction = self.constraint_intersection if constraint_insteraction is not None: for constraint in constraint_insteraction: while constraint.geometry is not None: return True return False def add_constraint(self, handle, constraint): if not constraint.valid: logger.error('Attempt to add an invalid constraint {} to posture_state {}.', constraint, self, owner='bhill', trigger_breakpoint=True) test_constraint = self.constraint_intersection.intersect(constraint) if not (self._invalid_expected or test_constraint.valid): logger.warn('Attempt to add a constraint to {} which is incompatible with already-registered constraints: {} + {}.', self, constraint, self.constraint_intersection) self._constraints[handle] = constraint self._constraint_intersection_dirty = True def remove_constraint(self, handle): if handle in self._constraints: del self._constraints[handle] self._constraint_intersection_dirty = True self._constraint_intersection = None @property def constraint_intersection(self): if self._constraint_intersection_dirty: intersection = Anywhere() for constraint in set(self._constraints.values()): new_intersection = intersection.intersect(constraint) if not self._invalid_expected and not new_intersection.valid: logger.error('Invalid constraint intersection for PostureState:{}', self) intersection = new_intersection break intersection = new_intersection self._constraint_intersection_dirty = False self._constraint_intersection = intersection return self._constraint_intersection def compatible_with(self, constraint): intersection = self.constraint_intersection if not intersection.valid: return False intersection = constraint.intersect(intersection) if not intersection.valid: return False return True def compatible_with_pre_resolve(self, constraint): for constraint_existing in self._constraints.values(): while constraint_existing is constraint: return True return self.compatible_with(constraint) def get_slot_info(self): surface = self._spec[SURFACE_INDEX] return (surface[SURFACE_TARGET_INDEX], surface[SURFACE_SLOT_TYPE_INDEX]) def is_source_interaction(self, si): if si is not None: for aspect in self.aspects: while aspect.source_interaction is si: return True return False def is_source_or_owning_interaction(self, si): return self.get_source_or_owned_posture_for_si(si) is not None def is_carry_source_or_owning_interaction(self, si): return self.get_source_or_owned_posture_for_si(si, carry_only=True) is not None def get_source_or_owned_posture_for_si(self, si, carry_only=False): if self.left.source_interaction is si or si in self.left.owning_interactions: return self.left if self.right.source_interaction is si or si in self.right.owning_interactions: return self.right if carry_only: return if self.body.source_interaction is si or si in self.body.owning_interactions: return self.body def _hand_to_track(self, hand) -> PostureTrack: raise RuntimeError('[bhill] This function is believed to be dead code and is scheduled for pruning. If this exception has been raised, the code is not dead and this exception should be removed.') if hand == Hand.LEFT: return PostureTrack.LEFT return PostureTrack.RIGHT def _track_to_hand(self, track) -> Hand: raise RuntimeError('[bhill] This function is believed to be dead code and is scheduled for pruning. If this exception has been raised, the code is not dead and this exception should be removed.') if track == PostureTrack.LEFT: return Hand.LEFT return Hand.RIGHT @property def connectivity_handles(self): if self.body.target is not None: return self.body.target.connectivity_handles def kickstart_gen(self, timeline): for aspect in self.aspects: yield aspect.kickstart_gen(timeline, self) self._valid = True def on_reset(self, reset_reason): for aspect in self.aspects: aspect.reset() self._valid = False def _carrying(self, track, **kwargs): posture = self.left if track == PostureTrack.LEFT else self.right return self._carrying_posture(posture, **kwargs) def _carrying_posture(self, posture, ignore_target=None, only_target=None): if posture is not None and posture.is_active_carry: if ignore_target is None and only_target is None: return True target = posture.target def target_is(other): if target is None: return False if isinstance(other, int): return target.definition.id == other if isinstance(other, Definition): return target.definition == other return target is other if ignore_target is None or not target_is(ignore_target): if only_target is None or target_is(only_target): return True return False def get_carry_state(self, target=None, override_posture=None): if override_posture is not None: if override_posture.track == PostureTrack.LEFT: carry_state = (self._carrying_posture(override_posture, ignore_target=target), self._carrying(PostureTrack.RIGHT, ignore_target=target)) else: carry_state = (self._carrying(PostureTrack.LEFT, ignore_target=target), self._carrying_posture(override_posture, ignore_target=target)) else: carry_state = (self._carrying(PostureTrack.LEFT, ignore_target=target), self._carrying(PostureTrack.RIGHT, ignore_target=target)) return carry_state def get_carry_track(self, target): if target is None: return if self._carrying(PostureTrack.LEFT, only_target=target): return PostureTrack.LEFT if self._carrying(PostureTrack.RIGHT, only_target=target): return PostureTrack.RIGHT def is_carrying(self, target): if self.get_carry_track(target) is not None: return True return False def get_carry_posture(self, target): if self.left.target is target: return self.left if self.right.target is target: return self.right def get_posture_for_si(self, si): for posture in self.aspects: while posture is not None and posture.source_interaction == si: return posture def get_other_carry_posture(self, target): track = self.get_carry_track(target) if track is None: return if track is PostureTrack.LEFT: result = self.get_aspect(PostureTrack.RIGHT) else: result = self.get_aspect(PostureTrack.LEFT) if result is not None and result.target is not None: return result def get_free_carry_track(self, obj=None) -> PostureTrack: if obj is not None and obj.carryable_component is None: logger.error('Obj {} has no carryable component.', obj, owner='tastle') return allowed_hands = obj.carryable_component.allowed_hands if obj is not None else (Hand.RIGHT, Hand.LEFT) if self.sim.handedness == Hand.RIGHT: preferred_track = PostureTrack.RIGHT unpreferred_track = PostureTrack.LEFT else: preferred_track = PostureTrack.LEFT unpreferred_track = PostureTrack.RIGHT if self.track_to_hand(preferred_track) in allowed_hands and not self._carrying(preferred_track): return preferred_track if self.track_to_hand(unpreferred_track) in allowed_hands and not self._carrying(unpreferred_track): return unpreferred_track def get_free_hands(self): if not self._carrying(PostureTrack.RIGHT): if not self._carrying(PostureTrack.LEFT): return (Hand.RIGHT, Hand.LEFT) return (Hand.RIGHT,) if not self._carrying(PostureTrack.LEFT): return (Hand.LEFT,) return () @staticmethod def hand_to_track(hand) -> PostureTrack: if hand == Hand.LEFT: return PostureTrack.LEFT return PostureTrack.RIGHT @staticmethod def track_to_hand(track) -> Hand: if track == PostureTrack.LEFT: return Hand.LEFT return Hand.RIGHT
def _create_constraint_set(self, sim, timeline): orient = sims4.math.Quaternion.IDENTITY() positions = services.current_zone().lot.corners position = positions[0] goals = [] for pos in positions: while not sims4.geometry.test_point_in_compound_polygon( pos, self._privacy.constraint.geometry.polygon): goals.append( routing.Goal( routing.Location(pos, orient, sim.routing_surface))) if not goals: return Nowhere() route = routing.Route(sim.routing_location, goals, routing_context=sim.routing_context) plan_primitive = PlanRoute(route, sim, reserve_final_location=False) yield element_utils.run_child(timeline, plan_primitive) max_distance = self._privacy._max_line_of_sight_radius * self._privacy._max_line_of_sight_radius * 4 nodes = plan_primitive.path.nodes if nodes: previous_node = nodes[0] for node in nodes: node_vector = sims4.math.Vector3(node.position[0], node.position[1], node.position[2]) if not sims4.geometry.test_point_in_compound_polygon( node_vector, self._privacy.constraint.geometry.polygon): position = node_vector if node.portal_id != 0: pass circle_constraint = interactions.constraints.Circle( position, self.TRIVIAL_SHOO_RADIUS, node.routing_surface_id) if circle_constraint.intersect( self._privacy.constraint).valid: pass break previous_node = node position2 = sims4.math.Vector3(previous_node.position[0], previous_node.position[1], previous_node.position[2]) if (position - position2).magnitude_2d_squared() > max_distance: position = self._find_close_position(position, position2) elif (position - sim.position).magnitude_2d_squared() > max_distance: position = self._find_close_position(position, sim.position) p1 = position p2 = self._privacy.central_object.position forward = sims4.math.vector_normalize(p1 - p2) radius_min = 0 radius_max = self._privacy._SHOO_CONSTRAINT_RADIUS angle = sims4.math.PI (cone_geometry, scoring_functions) = build_weighted_cone(position, forward, radius_min, radius_max, angle, ideal_radius_min=0, ideal_radius_max=0, ideal_angle=1) subtracted_cone_polygon_list = [] for cone_polygon in cone_geometry.polygon: for privacy_polygon in self._privacy.constraint.geometry.polygon: subtracted_cone_polygons = cone_polygon.subtract( privacy_polygon) while subtracted_cone_polygons: subtracted_cone_polygon_list.extend( subtracted_cone_polygons) compound_subtracted_cone_polygon = sims4.geometry.CompoundPolygon( subtracted_cone_polygon_list) subtracted_cone_geometry = sims4.geometry.RestrictedPolygon( compound_subtracted_cone_polygon, []) subtracted_cone_constraint = Constraint( geometry=subtracted_cone_geometry, scoring_functions=scoring_functions, routing_surface=sim.routing_surface, debug_name='ShooedSimsCone', los_reference_point=position) point_cost = 5 point_constraint = interactions.constraints.Position( position, routing_surface=sim.routing_surface) point_constraint = point_constraint.generate_constraint_with_cost( point_cost) constraints = (subtracted_cone_constraint, point_constraint) return interactions.constraints.create_constraint_set( constraints, debug_name='ShooPositions')
def __init__(self, sim, current_posture_state, posture_spec, var_map, invalid_expected=False, body_state_spec_only=False): self._constraint_intersection = None self._constraint_intersection_dirty = True self._spec = posture_spec self._sim_ref = sim.ref() self._linked_posture_state = None self._valid = True self._constraints = {} self._invalid_expected = invalid_expected self.body_state_spec_only = body_state_spec_only self._posture_constraint = None self._posture_constraint_strict = None body_index = BODY_INDEX body_posture_type_index = BODY_POSTURE_TYPE_INDEX body_target_index = BODY_TARGET_INDEX spec_body = posture_spec[body_index] self.body_target = spec_body[body_target_index] if current_posture_state is None or spec_body[body_posture_type_index] != current_posture_state.body.posture_type or spec_body[body_target_index] != current_posture_state.body.target: animation_context = None if current_posture_state is not None and not current_posture_state.body.mobile and not spec_body[body_posture_type_index].mobile: animation_context = current_posture_state.body.animation_context self._aspect_body = postures.create_posture(spec_body[body_posture_type_index], self.sim, self.body_target, animation_context=animation_context) else: self._aspect_body = current_posture_state.body posture_manifest = self._aspect_body.get_provided_postures(surface_target=self.surface_target, concrete=True) posture_manifest = posture_manifest.get_constraint_version(self.sim) posture_state_spec = PostureStateSpec(posture_manifest, SlotManifest(), self._aspect_body.target or PostureSpecVariable.ANYTHING) self.body_posture_state_constraint = Constraint(debug_name='PostureStateManifestConstraint', posture_state_spec=posture_state_spec) if body_state_spec_only: self._constraints[self] = self.body_posture_state_constraint return body_slot_constraint = self._aspect_body.slot_constraint if body_slot_constraint is not None: body_posture_constraint = self.body_posture_state_constraint.intersect(body_slot_constraint) else: body_posture_constraint = self.body_posture_state_constraint self._constraints[self] = body_posture_constraint if current_posture_state is not None: curr_spec_carry_target = current_posture_state.get_posture_spec(var_map)[CARRY_INDEX][CARRY_TARGET_INDEX] spec_carry = posture_spec[CARRY_INDEX] spec_carry_target = spec_carry[CARRY_TARGET_INDEX] if current_posture_state is not None and spec_carry_target != curr_spec_carry_target: if spec_carry_target is None: current_carry_target = var_map.get(curr_spec_carry_target) current_carry_track = current_posture_state.get_carry_track(current_carry_target) if current_carry_track == PostureTrack.RIGHT: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.RIGHT) self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_left = self._get_default_carry_aspect(PostureTrack.LEFT) self._aspect_carry_right = current_posture_state.right spec_carry_posture_type = spec_carry[CARRY_POSTURE_TYPE_INDEX] if spec_carry_target not in var_map: raise KeyError if spec_carry_posture_type not in var_map: aop = posture_specs.get_carry_posture_aop(sim, var_map[spec_carry_target]) carry_posture_type = aop.affordance._carry_posture_type if carry_posture_type is None: raise KeyError var_map += {PostureSpecVariable.POSTURE_TYPE_CARRY_OBJECT: carry_posture_type} carry_target = var_map[spec_carry_target] carry_posture_type = var_map[spec_carry_posture_type] if spec_carry[CARRY_HAND_INDEX] in var_map: hand = var_map[spec_carry[CARRY_HAND_INDEX]] else: for hand in sim.posture_state.get_free_hands(): while hand in carry_target.allowed_hands: break raise RuntimeError('No allowable free hand was empty.') new_carry_aspect = postures.create_posture(carry_posture_type, self.sim, carry_target, track=self.hand_to_track(hand)) if hand == Hand.LEFT: self._aspect_carry_left = new_carry_aspect if current_posture_state is not None: self._aspect_carry_right = current_posture_state.right else: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.RIGHT) if hand == Hand.RIGHT: self._aspect_carry_right = new_carry_aspect if current_posture_state is not None: self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.LEFT) raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) else: raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) elif hand == Hand.RIGHT: self._aspect_carry_right = new_carry_aspect if current_posture_state is not None: self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.LEFT) raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) else: raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) else: spec_carry_posture_type = spec_carry[CARRY_POSTURE_TYPE_INDEX] if spec_carry_target not in var_map: raise KeyError if spec_carry_posture_type not in var_map: aop = posture_specs.get_carry_posture_aop(sim, var_map[spec_carry_target]) carry_posture_type = aop.affordance._carry_posture_type if carry_posture_type is None: raise KeyError var_map += {PostureSpecVariable.POSTURE_TYPE_CARRY_OBJECT: carry_posture_type} carry_target = var_map[spec_carry_target] carry_posture_type = var_map[spec_carry_posture_type] if spec_carry[CARRY_HAND_INDEX] in var_map: hand = var_map[spec_carry[CARRY_HAND_INDEX]] else: for hand in sim.posture_state.get_free_hands(): while hand in carry_target.allowed_hands: break raise RuntimeError('No allowable free hand was empty.') new_carry_aspect = postures.create_posture(carry_posture_type, self.sim, carry_target, track=self.hand_to_track(hand)) if hand == Hand.LEFT: self._aspect_carry_left = new_carry_aspect if current_posture_state is not None: self._aspect_carry_right = current_posture_state.right else: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.RIGHT) if hand == Hand.RIGHT: self._aspect_carry_right = new_carry_aspect if current_posture_state is not None: self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.LEFT) raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) else: raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) elif hand == Hand.RIGHT: self._aspect_carry_right = new_carry_aspect if current_posture_state is not None: self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.LEFT) raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) else: raise RuntimeError('Invalid value specified for hand: {}'.format(hand)) elif current_posture_state is not None: self._aspect_carry_left = current_posture_state.left self._aspect_carry_right = current_posture_state.right elif spec_carry_target is not None: carry_target = var_map[spec_carry_target] spec_carry_posture_type = spec_carry[CARRY_POSTURE_TYPE_INDEX] carry_posture_type = var_map.get(spec_carry_posture_type) if carry_posture_type is None: aop = get_carry_posture_aop(sim, carry_target) if aop is None and invalid_expected: return carry_posture_type = aop.affordance._carry_posture_type if spec_carry[CARRY_HAND_INDEX] in var_map: hand = var_map[spec_carry[CARRY_HAND_INDEX]] else: hand = carry_target.allowed_hands[0] new_carry_aspect = postures.create_posture(carry_posture_type, self.sim, carry_target, track=self.hand_to_track(hand)) if hand == Hand.LEFT: self._aspect_carry_left = new_carry_aspect self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.RIGHT) else: self._aspect_carry_right = new_carry_aspect self._aspect_carry_left = self._get_default_carry_aspect(PostureTrack.LEFT) else: self._aspect_carry_left = self._get_default_carry_aspect(PostureTrack.LEFT) self._aspect_carry_right = self._get_default_carry_aspect(PostureTrack.RIGHT)
from animation.posture_manifest import MATCH_ANY, MATCH_NONE, PostureManifestEntry, PostureManifest from interactions.constraints import Constraint, create_constraint_set from postures.posture_state_spec import create_body_posture_state_spec STAND_POSTURE_MANIFEST = PostureManifest((PostureManifestEntry(None, '', 'stand', 'FullBody', MATCH_ANY, MATCH_ANY, MATCH_ANY), PostureManifestEntry(None, '', 'stand', 'UpperBody', MATCH_ANY, MATCH_ANY, MATCH_ANY))).intern() STAND_NO_SURFACE_POSTURE_MANIFEST = PostureManifest((PostureManifestEntry(None, '', 'stand', 'FullBody', MATCH_ANY, MATCH_ANY, MATCH_NONE), PostureManifestEntry(None, '', 'stand', 'UpperBody', MATCH_ANY, MATCH_ANY, MATCH_NONE))).intern() STAND_NO_CARRY_NO_SURFACE_POSTURE_MANIFEST = PostureManifest((PostureManifestEntry(None, '', 'stand', 'FullBody', MATCH_NONE, MATCH_NONE, MATCH_NONE), PostureManifestEntry(None, '', 'stand', 'UpperBody', MATCH_NONE, MATCH_NONE, MATCH_NONE))).intern() STAND_POSTURE_STATE_SPEC = create_body_posture_state_spec(STAND_POSTURE_MANIFEST) STAND_NO_SURFACE_STATE_SPEC = create_body_posture_state_spec(STAND_NO_SURFACE_POSTURE_MANIFEST) STAND_NO_CARRY_NO_SURFACE_STATE_SPEC = create_body_posture_state_spec(STAND_NO_CARRY_NO_SURFACE_POSTURE_MANIFEST) STAND_CONSTRAINT = Constraint(debug_name = 'Stand', posture_state_spec = STAND_POSTURE_STATE_SPEC) STAND_NO_SURFACE_CONSTRAINT = Constraint(debug_name = 'Stand-NoSurface', posture_state_spec = STAND_NO_SURFACE_STATE_SPEC) STAND_NO_CARRY_NO_SURFACE_CONSTRAINT = Constraint(debug_name = 'Stand-NoCarryNoSurface', posture_state_spec = STAND_NO_CARRY_NO_SURFACE_STATE_SPEC) STAND_CONSTRAINT_OUTER_PENALTY = Constraint(debug_name = 'Stand', posture_state_spec = STAND_POSTURE_STATE_SPEC, ignore_outer_penalty_threshold = 1.0) STAND_AT_NONE_POSTURE_STATE_SPEC = create_body_posture_state_spec(STAND_POSTURE_MANIFEST, body_target = None) STAND_AT_NONE_CONSTRAINT = Constraint(debug_name = 'Stand@None', posture_state_spec = STAND_AT_NONE_POSTURE_STATE_SPEC) SIT_POSTURE_MANIFEST = PostureManifest((PostureManifestEntry(None, '', 'sit', 'FullBody', MATCH_ANY, MATCH_ANY, MATCH_ANY), PostureManifestEntry(None, '', 'sit', 'UpperBody', MATCH_ANY, MATCH_ANY, MATCH_ANY))).intern() SIT_NO_CARRY_NO_SURFACE_MANIFEST = PostureManifest((PostureManifestEntry(None, '', 'sit', 'FullBody', MATCH_NONE, MATCH_NONE, MATCH_NONE), PostureManifestEntry(None, '', 'sit', 'UpperBody', MATCH_NONE, MATCH_NONE, MATCH_NONE))).intern() SIT_POSTURE_STATE_SPEC = create_body_posture_state_spec(SIT_POSTURE_MANIFEST) SIT_NO_CARRY_NO_SURFACE_STATE_SPEC = create_body_posture_state_spec(SIT_NO_CARRY_NO_SURFACE_MANIFEST) SIT_CONSTRAINT = Constraint(debug_name = 'Sit', posture_state_spec = SIT_POSTURE_STATE_SPEC) SIT_NO_CARRY_NO_SURFACE_CONSTRAINT = Constraint(debug_name = 'SitNoCarryNoSurface', posture_state_spec = SIT_NO_CARRY_NO_SURFACE_STATE_SPEC) SIT_INTIMATE_POSTURE_MANIFEST = PostureManifest((PostureManifestEntry(None, 'sitIntimate', '', 'FullBody', MATCH_NONE, MATCH_NONE, MATCH_NONE), PostureManifestEntry(None, 'sitIntimate', '', 'UpperBody', MATCH_NONE, MATCH_NONE, MATCH_NONE))).intern() SIT_INTIMATE_POSTURE_STATE_SPEC = create_body_posture_state_spec(SIT_INTIMATE_POSTURE_MANIFEST) SIT_INTIMATE_CONSTRAINT = Constraint(debug_name = 'SitIntimate', posture_state_spec = SIT_INTIMATE_POSTURE_STATE_SPEC) STAND_OR_SIT_POSTURE_MANIFEST = PostureManifest(list(STAND_POSTURE_MANIFEST) + list(SIT_POSTURE_MANIFEST)).intern() STAND_OR_SIT_CONSTRAINT = create_constraint_set((STAND_CONSTRAINT, SIT_CONSTRAINT), debug_name = 'Stand-or-Sit') STAND_OR_SIT_CONSTRAINT_OUTER_PENALTY = create_constraint_set((STAND_CONSTRAINT_OUTER_PENALTY, SIT_CONSTRAINT), debug_name = 'Stand-or-Sit-Outer-Penalty')
class PostureState: def __init__(self, sim, current_posture_state, posture_spec, var_map, invalid_expected=False, body_state_spec_only=False, carry_posture_overrides=frozendict(), is_throwaway=False): def _get_default_carry_aspect(track): if track in carry_posture_overrides: return carry_posture_overrides[track] return postures.create_posture( CarryPostureStaticTuning.POSTURE_CARRY_NOTHING, sim, None, track=track) self._constraint_intersection = None self._constraint_intersection_dirty = True self._spec = posture_spec self._sim_ref = sim.ref() self._linked_posture_state = None self._valid = True self._constraints = {} self._invalid_expected = invalid_expected self.body_state_spec_only = body_state_spec_only self._posture_constraint = None self._posture_constraint_strict = None body_index = BODY_INDEX body_posture_type_index = BODY_POSTURE_TYPE_INDEX body_target_index = BODY_TARGET_INDEX spec_body = posture_spec[body_index] self.body_target = spec_body[body_target_index] if current_posture_state is None or spec_body[ body_posture_type_index] != current_posture_state.body.posture_type or spec_body[ body_target_index] != current_posture_state.body.target: animation_context = None if current_posture_state is not None: if not current_posture_state.body.mobile: if not spec_body[body_posture_type_index].mobile: animation_context = current_posture_state.body.animation_context self._aspect_body = postures.create_posture( spec_body[body_posture_type_index], self.sim, self.body_target, animation_context=animation_context, is_throwaway=is_throwaway) else: self._aspect_body = current_posture_state.body posture_manifest = self._aspect_body.get_provided_postures( surface_target=self.surface_target, concrete=True) posture_manifest = posture_manifest.get_constraint_version(self.sim) posture_state_spec = PostureStateSpec( posture_manifest, SlotManifest(), self._aspect_body.target or PostureSpecVariable.ANYTHING) self.body_posture_state_constraint = Constraint( debug_name='PostureStateManifestConstraint', posture_state_spec=posture_state_spec) if body_state_spec_only: self._constraints[None] = self.body_posture_state_constraint return body_slot_constraint = self._aspect_body.slot_constraint if not (body_slot_constraint is not None and (self._aspect_body.is_vehicle and current_posture_state is not None) and current_posture_state.body.is_vehicle): body_posture_constraint = self.body_posture_state_constraint.intersect( body_slot_constraint) else: body_posture_constraint = self.body_posture_state_constraint self._constraints[None] = body_posture_constraint if current_posture_state is not None: curr_spec_carry_target = current_posture_state.get_posture_spec( var_map)[CARRY_INDEX][CARRY_TARGET_INDEX] spec_carry = posture_spec[CARRY_INDEX] spec_carry_target = spec_carry[CARRY_TARGET_INDEX] if current_posture_state is not None and spec_carry_target != curr_spec_carry_target: if spec_carry_target is None: current_carry_target = var_map.get(curr_spec_carry_target) current_carry_track = current_posture_state.get_carry_track( current_carry_target) if current_carry_track == PostureTrack.RIGHT: self._aspect_carry_right = _get_default_carry_aspect( PostureTrack.RIGHT) self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_left = _get_default_carry_aspect( PostureTrack.LEFT) self._aspect_carry_right = current_posture_state.right else: spec_carry_posture_type = spec_carry[CARRY_POSTURE_TYPE_INDEX] if spec_carry_target not in var_map: raise KeyError( 'spec_carry_target {} not in var_map:{}. Sim posture state {} and carry aspects {}, ' .format(spec_carry_target, var_map, current_posture_state, current_posture_state.carry_aspects)) if spec_carry_posture_type not in var_map: carry_target = var_map[spec_carry_target] aop = posture_specs.get_carry_posture_aop( sim, carry_target) if aop is None: raise RuntimeError( 'Sim {} failed to find carry posture aop for carry target {}.' .format(sim, carry_target)) carry_posture_type = aop.affordance._carry_posture_type if carry_posture_type is None: raise KeyError var_map += { PostureSpecVariable.POSTURE_TYPE_CARRY_OBJECT: carry_posture_type } carry_target = var_map[spec_carry_target] carry_posture_type = var_map[spec_carry_posture_type] if spec_carry[CARRY_HAND_INDEX] in var_map: hand = var_map[spec_carry[CARRY_HAND_INDEX]] else: for hand in sim.posture_state.get_free_hands(): if hand in carry_target.get_allowed_hands(sim): break else: raise RuntimeError('No allowable free hand was empty.') new_carry_aspect = postures.create_posture( carry_posture_type, self.sim, carry_target, track=hand_to_track(hand), is_throwaway=is_throwaway) if hand == Hand.LEFT: self._aspect_carry_left = new_carry_aspect if current_posture_state is not None: self._aspect_carry_right = current_posture_state.right else: self._aspect_carry_right = _get_default_carry_aspect( PostureTrack.RIGHT) elif hand == Hand.RIGHT: self._aspect_carry_right = new_carry_aspect if current_posture_state is not None: self._aspect_carry_left = current_posture_state.left else: self._aspect_carry_right = _get_default_carry_aspect( PostureTrack.LEFT) else: raise RuntimeError( 'Invalid value specified for hand: {}'.format(hand)) elif current_posture_state is not None: self._aspect_carry_left = current_posture_state.left self._aspect_carry_right = current_posture_state.right elif spec_carry_target is not None: carry_target = var_map[spec_carry_target] spec_carry_posture_type = spec_carry[CARRY_POSTURE_TYPE_INDEX] carry_posture_type = var_map.get(spec_carry_posture_type) if carry_posture_type is None: aop = get_carry_posture_aop(sim, carry_target) if aop is None and invalid_expected: return carry_posture_type = aop.affordance._carry_posture_type if spec_carry[CARRY_HAND_INDEX] in var_map: hand = var_map[spec_carry[CARRY_HAND_INDEX]] else: allowed_hands = carry_target.get_allowed_hands(sim) hand = allowed_hands[0] new_carry_aspect = postures.create_posture( carry_posture_type, self.sim, carry_target, track=hand_to_track(hand), is_throwaway=is_throwaway) if hand == Hand.LEFT: self._aspect_carry_left = new_carry_aspect self._aspect_carry_right = _get_default_carry_aspect( PostureTrack.RIGHT) else: self._aspect_carry_right = new_carry_aspect self._aspect_carry_left = _get_default_carry_aspect( PostureTrack.LEFT) else: self._aspect_carry_left = _get_default_carry_aspect( PostureTrack.LEFT) self._aspect_carry_right = _get_default_carry_aspect( PostureTrack.RIGHT) def __repr__(self): return standard_repr(self, *self.aspects) @property def valid(self): return self._valid and bool(self.constraint_intersection) @property def spec(self): return self._spec def get_posture_spec(self, var_map): if not var_map: return self._spec.clone() carry_target = var_map.get(PostureSpecVariable.CARRY_TARGET) if carry_target is not None and carry_target.definition is not carry_target: carry_posture = self.get_carry_posture(carry_target) else: carry_posture = None if carry_posture is not None: if PostureSpecVariable.HAND in var_map: required_hand = track_to_hand(carry_posture.track) if required_hand != var_map[PostureSpecVariable.HAND]: return source_carry = PostureAspectCarry( (PostureSpecVariable.POSTURE_TYPE_CARRY_OBJECT, PostureSpecVariable.CARRY_TARGET, PostureSpecVariable.HAND)) else: source_carry = PostureAspectCarry( (PostureSpecVariable.POSTURE_TYPE_CARRY_NOTHING, None, PostureSpecVariable.HAND)) surface_spec = self._spec[SURFACE_INDEX] surface_target = surface_spec[SURFACE_TARGET_INDEX] if surface_target is not None: var_map_surface_target = var_map.get( PostureSpecVariable.SURFACE_TARGET, None) if var_map_surface_target is None or surface_target == var_map_surface_target: if carry_target is not None and carry_posture is None and carry_target.definition is not carry_target: surface_spec = PostureAspectSurface( (surface_target, PostureSpecVariable.SLOT, PostureSpecVariable.CARRY_TARGET)) spec = self._spec.clone(carry=source_carry, surface=surface_spec) if spec._validate_surface( var_map) and carry_target.parent is surface_target: return spec interaction_target = var_map.get( PostureSpecVariable.INTERACTION_TARGET, PostureSpecVariable.INTERACTION_TARGET) if interaction_target is not None: surface_spec = PostureAspectSurface( (surface_target, PostureSpecVariable.SLOT, PostureSpecVariable.SLOT_TARGET)) spec = self._spec.clone(carry=source_carry, surface=surface_spec) if spec._validate_surface(var_map) and not isinstance( interaction_target, PostureSpecVariable ) and interaction_target.parent is surface_target: return spec surface_spec = PostureAspectSurface( (surface_target, PostureSpecVariable.SLOT, None)) spec = self._spec.clone(carry=source_carry, surface=surface_spec) if spec._validate_surface(var_map): return spec surface_spec = PostureAspectSurface((surface_target, None, None)) spec = self._spec.clone(carry=source_carry, surface=surface_spec) if spec._validate_surface(var_map): return spec else: surface_spec = PostureAspectSurface((None, None, None)) spec = self._spec.clone(carry=source_carry, surface=surface_spec) if spec._validate_surface(var_map): return spec else: surface_spec = PostureAspectSurface((None, None, None)) spec = self._spec.clone(carry=source_carry, surface=surface_spec) if spec._validate_surface(var_map): return spec def _get_posture_constraint(self, strict=False): posture_state_constraint = self.body_posture_state_constraint posture_state_constraint = posture_state_constraint.get_holster_version( ) if posture_state_constraint.valid: if not self.body_state_spec_only: carry_left_constraint = create_carry_constraint( self.left.target, Hand.LEFT, strict=strict) posture_state_constraint = posture_state_constraint.intersect( carry_left_constraint) if posture_state_constraint.valid: carry_right_constraint = create_carry_constraint( self.right.target, Hand.RIGHT, strict=strict) posture_state_constraint = posture_state_constraint.intersect( carry_right_constraint) return posture_state_constraint @property def posture_constraint(self): if self._posture_constraint is None: self._posture_constraint = self._get_posture_constraint() return self._posture_constraint @property def posture_constraint_strict(self): if self._posture_constraint_strict is None: self._posture_constraint_strict = self._get_posture_constraint( strict=True) return self._posture_constraint_strict @property def sim(self): if self._sim_ref is not None: return self._sim_ref() @property def linked_posture_state(self): return self._linked_posture_state @linked_posture_state.setter def linked_posture_state(self, posture_state): self._set_linked_posture_state(posture_state) posture_state._set_linked_posture_state(self) self.body.linked_posture = posture_state.body def _set_linked_posture_state(self, posture_state): self._linked_posture_state = posture_state @property def body(self): return self._aspect_body @property def left(self): return self._aspect_carry_left @property def right(self): return self._aspect_carry_right @property def aspects(self): if self.body_state_spec_only: return () return (self.body, self.left, self.right) @property def carry_aspects(self): return (self.left, self.right) @property def surface_target(self): surface = self._spec[SURFACE_INDEX][SURFACE_TARGET_INDEX] if ( surface is None or self.body.mobile ) and self.body.target is not None and self.body.target.is_surface(): return self.body.target return surface @property def carry_targets(self): return (self.left.target, self.right.target) def get_aspect(self, track): if track == PostureTrack.BODY: return self.body if track == PostureTrack.LEFT: return self.left elif track == PostureTrack.RIGHT: return self.right def add_constraint(self, handle, constraint): if not self._invalid_expected: if not constraint.valid: logger.warn( 'Attempt to add an invalid constraint {} to posture_state {}.', constraint, self, owner='bhill', trigger_breakpoint=True) test_constraint = self.constraint_intersection.intersect( constraint) if not test_constraint.valid: logger.warn( 'Attempt to add a constraint to {} which is incompatible with already-registered constraints: {} + {}.', self, constraint, self.constraint_intersection) self._constraints[handle] = constraint self._constraint_intersection_dirty = True def remove_constraint(self, handle): if handle in self._constraints: del self._constraints[handle] self._constraint_intersection_dirty = True self._constraint_intersection = None @property def constraint_intersection(self): if self._constraint_intersection_dirty or self._constraint_intersection is None: intersection = Anywhere() for constraint in set(self._constraints.values()): new_intersection = intersection.intersect(constraint) if not self._invalid_expected: if not new_intersection.valid: indent_text = ' ' logger.error( 'Invalid constraint intersection for PostureState: {}.\n A: {} \n A Geometry: {} B: {} \n B Geometry: {}', self, intersection, intersection.get_geometry_text(indent_text), constraint, constraint.get_geometry_text(indent_text)) intersection = new_intersection break intersection = new_intersection self._constraint_intersection_dirty = False self._constraint_intersection = intersection return self._constraint_intersection def compatible_with(self, constraint): intersection = self.constraint_intersection if not intersection.valid: return False else: intersection = constraint.intersect(intersection) if not intersection.valid: return False return True def compatible_with_pre_resolve(self, constraint): for constraint_existing in self._constraints.values(): if constraint_existing is constraint: return True return self.compatible_with(constraint) def get_slot_info(self): surface = self._spec[SURFACE_INDEX] return (surface[SURFACE_TARGET_INDEX], surface[SURFACE_SLOT_TYPE_INDEX]) def is_source_interaction(self, si): if si is not None: for aspect in self.aspects: if aspect.source_interaction is si: return True return False def is_source_or_owning_interaction(self, si): return self.get_source_or_owned_posture_for_si(si) is not None def is_carry_source_or_owning_interaction(self, si): return self.get_source_or_owned_posture_for_si( si, carry_only=True) is not None def get_source_or_owned_posture_for_si(self, si, carry_only=False): if self.left.source_interaction is si or si in self.left.owning_interactions: return self.left if self.right.source_interaction is si or si in self.right.owning_interactions: return self.right if carry_only: return elif self.body.source_interaction is si or si in self.body.owning_interactions: return self.body @property def connectivity_handles(self): if self.body.target is not None: return self.body.target.connectivity_handles def kickstart_gen(self, timeline, routing_surface, target_override=None): for aspect in self.aspects: yield from aspect.kickstart_gen(timeline, self, routing_surface, target_override=target_override) self._valid = True def on_reset(self, reset_reason): for aspect in self.aspects: aspect.reset() self._valid = False def _carrying(self, track, **kwargs): posture = self.left if track == PostureTrack.LEFT else self.right return self._carrying_posture(posture, **kwargs) def _carrying_posture(self, posture, ignore_target=None, only_target=None): if posture.is_active_carry: if ignore_target is None and only_target is None: return True else: target = posture.target def target_is(other): if target is None: return False if isinstance(other, Tag): return target.has_tag(other) if isinstance(other, int): return target.definition.id == other if isinstance(other, Definition): return target.definition is other return target is other if not (ignore_target is None or not target_is(ignore_target) ) and (only_target is None or target_is(only_target)): return True return False def get_carry_state(self, target=None, override_posture=None): if override_posture is not None: if override_posture.track == PostureTrack.LEFT: carry_state = (self._carrying_posture(override_posture, ignore_target=target), self._carrying(PostureTrack.RIGHT, ignore_target=target)) else: carry_state = (self._carrying(PostureTrack.LEFT, ignore_target=target), self._carrying_posture(override_posture, ignore_target=target)) else: carry_state = (self._carrying(PostureTrack.LEFT, ignore_target=target), self._carrying(PostureTrack.RIGHT, ignore_target=target)) return carry_state def get_carry_track(self, target): if target is None: return if self._carrying(PostureTrack.LEFT, only_target=target): return PostureTrack.LEFT elif self._carrying(PostureTrack.RIGHT, only_target=target): return PostureTrack.RIGHT def is_carrying(self, target): if self.get_carry_track(target) is not None: return True return False def get_carry_posture(self, target): if self.left.target is target: return self.left elif self.right.target is target: return self.right def get_posture_for_si(self, si): for posture in self.aspects: if posture is not None: if posture.source_interaction == si: return posture def get_other_carry_posture(self, target): track = self.get_carry_track(target) if track is None: return else: if track is PostureTrack.LEFT: result = self.get_aspect(PostureTrack.RIGHT) else: result = self.get_aspect(PostureTrack.LEFT) if result is not None and result.target is not None: return result def get_free_carry_track(self, obj=None) -> PostureTrack: if obj is not None and obj.carryable_component is None: logger.error('Obj {} has no carryable component.', obj, owner='tastle') return if obj is None: allowed_hands = (Hand.RIGHT, Hand.LEFT) else: allowed_hands = obj.get_allowed_hands(self.sim) preferred_hand = self.sim.get_preferred_hand() if preferred_hand == Hand.RIGHT: preferred_track = PostureTrack.RIGHT unpreferred_track = PostureTrack.LEFT else: preferred_track = PostureTrack.LEFT unpreferred_track = PostureTrack.RIGHT if track_to_hand( preferred_track ) in allowed_hands and not self._carrying(preferred_track): return preferred_track elif track_to_hand( unpreferred_track ) in allowed_hands and not self._carrying(unpreferred_track): return unpreferred_track def get_free_hands(self): if not self._carrying(PostureTrack.RIGHT): if not self._carrying(PostureTrack.LEFT): return (Hand.RIGHT, Hand.LEFT) return (Hand.RIGHT, ) elif not self._carrying(PostureTrack.LEFT): return (Hand.LEFT, ) return ()