def get_location_data_along_segment_gen(self, first_node_index, last_node_index, time_step=0.3): if self.nodes is None: return first_node = self.nodes[first_node_index] last_node = self.nodes[last_node_index] time = first_node.time end_time = last_node.time if time == end_time == 0.0: routing_surface = first_node.routing_surface_id dist = 0.0 while True: while dist < 1.0: pos = sims4.math.vector_interpolate( Vector3(*first_node.position), Vector3(*last_node.position), dist) dist += time_step yield (Transform(pos, Quaternion(*first_node.orientation)), first_node.routing_surface_id, 0.0) else: while time < end_time: (transform, routing_surface) = self.get_location_data_at_time(time) yield (transform, routing_surface, time) time += time_step
def _update_portal_location(self, locations, there_entry, there_exit, obj, other_obj, other_obj_angle_restriction): if there_entry.position == there_exit.position: return entry_in_position = there_entry.position + sims4.math.vector_normalize( there_exit.position - there_entry.position) * self.entry_offset entry_out_position = there_entry.position + sims4.math.vector_normalize( there_exit.position - there_entry.position) * self.exit_offset entry_in_position = Vector3(entry_in_position.x, there_entry.position.y, entry_in_position.z) entry_out_position = Vector3(entry_out_position.x, there_entry.position.y, entry_out_position.z) entry_angle = sims4.math.vector3_angle(there_exit.position - entry_in_position) exit_angle = sims4.math.vector3_angle(entry_in_position - there_exit.position) entry_orientation = sims4.math.angle_to_yaw_quaternion(entry_angle) exit_orientation = sims4.math.angle_to_yaw_quaternion(exit_angle) if self.angle_restriction is not None and not self._is_angle_valid( entry_orientation, obj, self.angle_restriction): return if other_obj_angle_restriction is not None and not self._is_angle_valid( exit_orientation, other_obj, other_obj_angle_restriction): return _there_in_entry = Location(entry_in_position, entry_orientation, there_entry.routing_surface) _there_out_entry = Location(entry_out_position, entry_orientation, there_entry.routing_surface) there_exit.transform = Transform(there_exit.position, exit_orientation) locations.append( (_there_in_entry, there_exit, there_exit, _there_out_entry, 0))
def on_finalize_load(self): super().on_finalize_load() portal_component = self.get_component(PORTAL_COMPONENT) if portal_component is None: return locator_manager = services.locator_manager() locators = locator_manager.get( OceanTuning.get_beach_locator_definition().id) initial_transforms = [locator.transform for locator in locators] street_instance = services.current_zone().street if street_instance is not None: for beach_data in street_instance.beaches: beach_forward = Vector3(beach_data.forward.x, 0, beach_data.forward.y) orientation = Quaternion.from_forward_vector(beach_forward) transform = Transform(translation=beach_data.position, orientation=orientation) initial_transforms.append(transform) if not initial_transforms: self._off_lot_portals_created = False return off_lot_portal_ids = [] self._create_all_transforms_and_portals_for_initial_transforms( initial_transforms, store_portal_ids=off_lot_portal_ids) self._off_lot_portals_created = bool(off_lot_portal_ids) self._lot_locator_transforms = self._get_lot_locator_transforms() if self._lot_locator_transforms: self._create_all_transforms_and_portals_for_initial_transforms( self._lot_locator_transforms, lot_transforms=True, prior_lengths=self._lot_constraint_starts_base_lengths, store_portal_ids=self._lot_portals) if self._off_lot_portals_created or self._lot_portals: services.object_manager().add_portal_to_cache(self)
def clone(self, *, transform=DEFAULT, translation=DEFAULT, orientation=DEFAULT, routing_surface=DEFAULT, parent=DEFAULT, joint_name_or_hash=DEFAULT, slot_hash=DEFAULT): if transform is DEFAULT: transform = self.transform if transform is not None: if translation is DEFAULT: translation = transform.translation if orientation is DEFAULT: orientation = transform.orientation transform = Transform(translation, orientation) if routing_surface is DEFAULT: routing_surface = self.routing_surface if parent is DEFAULT: parent = self.parent if joint_name_or_hash is DEFAULT: joint_name_or_hash = self.joint_name_or_hash if slot_hash is DEFAULT: slot_hash = self.slot_hash return type(self)(transform, routing_surface, parent, joint_name_or_hash, slot_hash)
def get_transforms_gen(self, actor, target, fallback_routing_surface=None, fgl_kwargs=None, **kwargs): reserved_space_a = get_default_reserve_space(actor.species, actor.age) reserved_space_b = get_default_reserve_space(target.species, target.age) fgl_kwargs = fgl_kwargs if fgl_kwargs is not None else {} ignored_objects = {actor.id, target.id} ignored_ids = fgl_kwargs.get('ignored_object_ids') if ignored_ids is not None: ignored_objects.update(ignored_ids) fgl_kwargs['ignored_object_ids'] = ignored_objects for (transform, jig_params) in self._get_available_transforms_gen(actor, target): actor_angle = yaw_quaternion_to_angle(transform.orientation) (translation_a, orientation_a, translation_b, orientation_b, routing_surface) = generate_jig_polygon( actor.location, transform.translation, actor_angle, target.location, Vector2.ZERO(), 0, reserved_space_a.left, reserved_space_a.right, reserved_space_a.front, reserved_space_a.back, reserved_space_b.left, reserved_space_b.right, reserved_space_b.front, reserved_space_b.back, fallback_routing_surface=fallback_routing_surface, reverse_nonreletive_sim_orientation=self. reverse_actor_sim_orientation, **fgl_kwargs) if translation_a is None: continue yield (Transform(translation_a, orientation_a), Transform(translation_b, orientation_b), routing_surface, jig_params)
def get_initial_offset(self, actor, to_state_name, from_state_name='entry'): arb = NativeArb() self.traverse(from_state_name, to_state_name, arb, from_boundary_conditions=True) offset = arb.get_initial_offset(actor) return Transform(Vector3(*offset[0]), Quaternion(*offset[1]))
def get_location_data_at_time(self, time): if self.nodes is None: return routing_surface = self.node_at_time(time).routing_surface_id translation = Vector3(*self.nodes.position_at_time(time)) translation.y = services.terrain_service.terrain_object( ).get_routing_surface_height_at(translation.x, translation.z, routing_surface) orientation = Quaternion( *self.nodes.orientation_at_time(time, self.blended_orientation)) return (Transform(translation, orientation), routing_surface)
def get_portal_locations(self, obj): locations = [] for portal_entry in self.object_portals: there_entry = portal_entry.location_entry(obj) there_exit = portal_entry.location_exit(obj) if not self._is_offset_from_object(there_entry, obj): if self._is_offset_from_object(there_exit, obj): continue if not self._is_object_routing_surface_overlap( there_entry, obj): if self._is_object_routing_surface_overlap( there_exit, obj): continue entry_angle = sims4.math.vector3_angle( there_exit.position - there_entry.position) there_entry.transform = Transform( there_entry.position, sims4.math.angle_to_yaw_quaternion(entry_angle)) exit_angle = sims4.math.vector3_angle( there_entry.position - there_exit.position) there_exit.transform = Transform( there_exit.position, sims4.math.angle_to_yaw_quaternion(exit_angle)) if portal_entry.is_bidirectional: offset_entry = self._get_offset_positions( there_entry, there_exit, entry_angle) offset_exit = self._get_offset_positions( there_exit, there_entry, exit_angle) if not self._is_object_routing_surface_overlap( offset_entry, obj ) and not self._is_object_routing_surface_overlap( offset_exit, obj): locations.append((offset_entry, offset_exit, there_exit, there_entry, 0)) locations.append( (there_entry, there_exit, None, None, 0)) else: locations.append( (there_entry, there_exit, None, None, 0)) return locations
def _get_carry_system_target(self, callback): (transform, routing_surface) = self._get_best_location(self.carry_target, self.target) transform = Transform(transform.translation, self.sim.orientation) surface_height = services.terrain_service.terrain_object( ).get_routing_surface_height_at(transform.translation.x, transform.translation.z, routing_surface) transform.translation = Vector3(transform.translation.x, surface_height, transform.translation.z) return CarrySystemTerrainTarget(self.sim, self.carry_target, True, transform, routing_surface=routing_surface, custom_event_callback=callback)
def _get_best_location(self, obj, target): routing_surface = getattr(self.target, 'provided_routing_surface', None) if routing_surface is None: routing_surface = target.routing_surface if self._transform is UNSET: if target.is_terrain: self._transform = target.transform else: (translation, orientation) = CarryingObject.get_good_location_on_floor( obj, starting_transform=target.transform, starting_routing_surface=routing_surface, additional_search_flags=FGLSearchFlag. STAY_IN_CURRENT_BLOCK) if translation is None: self._transform = None else: self._transform = Transform(translation, orientation) return (self._transform, routing_surface)
def clone(self, *, transform=DEFAULT, translation=DEFAULT, orientation=DEFAULT, routing_surface=DEFAULT, parent=DEFAULT, joint_name_or_hash=DEFAULT, slot_hash=DEFAULT): if transform is DEFAULT: if translation is DEFAULT: translation = self.transform.translation if orientation is DEFAULT: orientation = self.transform.orientation else: if transform is None: raise ValueError('Attempt to pass a None transform into a location clone.') if translation is DEFAULT: translation = transform.translation if orientation is DEFAULT: orientation = transform.orientation transform = Transform(translation, orientation) if routing_surface is DEFAULT: routing_surface = self.routing_surface if parent is DEFAULT: parent = self.parent if joint_name_or_hash is DEFAULT: joint_name_or_hash = self.joint_name_or_hash if slot_hash is DEFAULT: slot_hash = self.slot_hash return type(self)(transform, routing_surface, parent, joint_name_or_hash, slot_hash)
def _get_transform_3(p, n0, n1, n2): return Transform( p, Quaternion.from_forward_vector(n0 * 0.25 + n1 * 0.5 + n2 * 0.25))
def _get_transform_1(p, n0): return Transform(p, Quaternion.from_forward_vector(n0))
def _create_all_transforms_and_portals_for_initial_transforms( self, initial_transforms, lot_transforms=False, prior_lengths=None, store_portal_ids=None): portal_component = self.get_component(PORTAL_COMPONENT) if portal_component is None: return def _store_transforms(species, ages, interval, transforms): for age in ages: key = (species, age, interval) if key in self._constraint_starts: if prior_lengths is not None: prior_lengths[key] = len(self._constraint_starts[key]) self._constraint_starts[key].extend(transforms) else: if prior_lengths is not None: prior_lengths[key] = 0 self._constraint_starts[key] = transforms routing_surface = SurfaceIdentifier(services.current_zone_id(), 0, SurfaceType.SURFACETYPE_WORLD) edge_transforms = adjust_locations_for_coastline(initial_transforms) def _get_water_depth_at_edge(i): transform = edge_transforms[i] translation = transform.translation + transform.orientation.transform_vector( Ocean.EDGE_TEST_POINT_OFFSET) return get_water_depth(translation.x, translation.z) for (species, age_data) in OceanTuning.OCEAN_DATA.items(): required_pack = SpeciesExtended.get_required_pack(species) if required_pack is not None and not is_available_pack( required_pack): continue for age_ocean_data in age_data: ocean_data = age_ocean_data.ocean_data beach_portal = ocean_data.beach_portal_data wading_depth = ocean_data.wading_interval.lower_bound max_wading_depth = wading_depth + ocean_data.water_depth_error swim_depth = ocean_data.wading_interval.upper_bound min_swim_depth = swim_depth - ocean_data.water_depth_error transforms = adjust_locations_for_target_water_depth( wading_depth, ocean_data.water_depth_error, initial_transforms) wading_transforms = [] for i in range(len(transforms) - 1): transform = transforms[i] if transform.translation == VECTOR3_ZERO: depth = _get_water_depth_at_edge(i) if depth <= max_wading_depth: wading_transforms.append(edge_transforms[i]) wading_transforms.append(transform) else: wading_transforms.append(transform) transforms = adjust_locations_for_target_water_depth( swim_depth, ocean_data.water_depth_error, initial_transforms) portal_transforms = [] for i in range(len(transforms) - 1): transform = transforms[i] if transform.translation == VECTOR3_ZERO: depth = _get_water_depth_at_edge(i) if min_swim_depth <= depth: edge_transform = edge_transforms[i] translation = edge_transform.translation + edge_transform.orientation.transform_vector( Ocean.EDGE_PORTAL_BACKSET) portal_transforms.append( Transform(translation, edge_transform.orientation)) else: portal_transforms.append(transform) _store_transforms(species, age_ocean_data.ages, WaterDepthIntervals.WET, edge_transforms.copy()) _store_transforms(species, age_ocean_data.ages, WaterDepthIntervals.WADE, wading_transforms) _store_transforms(species, age_ocean_data.ages, WaterDepthIntervals.SWIM, portal_transforms) if beach_portal is None: pass else: if lot_transforms: portal_transforms = self._reorient_lot_transforms( portal_transforms) portal_creation_mask = SpeciesExtended.get_portal_flag( species) for portal_transform in portal_transforms: portal_location = Location( portal_transform, routing_surface=routing_surface) portal_ids = portal_component.add_custom_portal( OceanPoint(portal_location), beach_portal, portal_creation_mask) add_portals = [] remove_portals = [] for portal_id in portal_ids: portal_instance = portal_component.get_portal_by_id( portal_id) if portal_instance is not None: location = None if portal_id == portal_instance.there: location = portal_instance.there_entry elif portal_id == portal_instance.back: location = portal_instance.back_exit if location and build_buy.is_location_natural_ground( location.position, location.routing_surface.secondary_id): add_portals.append(portal_id) else: remove_portals.append(portal_id) if remove_portals: portal_component.remove_custom_portals( remove_portals) if add_portals and store_portal_ids is not None: store_portal_ids.extend(add_portals)
def get_difference_transform(transform_a, transform_b): v = transform_b.translation - transform_a.translation a_q_i = invert_quaternion(transform_a.orientation) q = Quaternion.concatenate(transform_b.orientation, a_q_i) v_prime = Quaternion.transform_vector(a_q_i, v) return Transform(v_prime, q)
def _get_transform_2(p, n0, n1): return Transform(p, Quaternion.from_forward_vector(n0 * 0.5 + n1 * 0.5))
def _get_bone_transform(self): joint_transform = get_joint_transform_from_rig(self._owner.rig, self._bone_name) offset_from_joint = joint_transform.transform_point(self._bone_offset) final_transform = Transform.concatenate(Transform(offset_from_joint), self._owner.transform) return final_transform