def __init__(self): """Constructs global for PIP. """ Node.reset_counter() Curve.reset_counter() Sign.reset_counter() SpawnPoint.reset_counter() Semaphore.reset_counter() MapPoint.reset_counter() TriggerPoint.reset_counter() Intersection.reset_counter()
def get_as_section(): """Gets global prefab information represented with SectionData structure class. :return: packed globals as section data :rtype: io_scs_tools.internals.structure.SectionData """ section = _SectionData("Global") section.props.append(("NodeCount", Node.get_global_node_count())) section.props.append(("TerrainPointCount", Node.get_global_tp_count())) section.props.append( ("TerrainPointVariantCount", Node.get_global_tp_variant_count())) section.props.append(("NavCurveCount", Curve.get_global_curve_count())) section.props.append(("SignCount", Sign.get_global_sign_count())) section.props.append( ("SpawnPointCount", SpawnPoint.get_global_spawn_point_count())) section.props.append( ("SemaphoreCount", Semaphore.get_global_semaphore_count())) section.props.append( ("MapPointCount", MapPoint.get_global_map_point_count())) section.props.append(("TriggerPointCount", TriggerPoint.get_global_trigger_point_count())) section.props.append(("IntersectionCount", Intersection.get_global_intersection_count())) return section
def __get_curve__(pip_curves, index, locator_name): """Gets curve class instance entry from given input dictonary. If the entry is not present, entry is firstly created in dictionary and then returned. :param pip_curves: input dictionary of curve class instances :type pip_curves: dict[int, io_scs_tools.exp.pip.curve.Curve] :param index: index of curve we are looking for :type index: int :param locator_name: start locator name :type locator_name: str :return: curve class instance :rtype: io_scs_tools.exp.pip.curve.Curve """ if index not in pip_curves: pip_curves[index] = Curve(index, _tokenize_name(locator_name), locator_name) return pip_curves[index]
def get_as_section(): """Gets global prefab information represented with SectionData structure class. :return: packed globals as section data :rtype: io_scs_tools.internals.structure.SectionData """ section = _SectionData("Global") section.props.append(("NodeCount", Node.get_global_node_count())) section.props.append(("TerrainPointCount", Node.get_global_tp_count())) section.props.append(("TerrainPointVariantCount", Node.get_global_tp_variant_count())) section.props.append(("NavCurveCount", Curve.get_global_curve_count())) section.props.append(("SignCount", Sign.get_global_sign_count())) section.props.append(("SpawnPointCount", SpawnPoint.get_global_spawn_point_count())) section.props.append(("SemaphoreCount", Semaphore.get_global_semaphore_count())) section.props.append(("MapPointCount", MapPoint.get_global_map_point_count())) section.props.append(("TriggerPointCount", TriggerPoint.get_global_trigger_point_count())) section.props.append(("IntersectionCount", Intersection.get_global_intersection_count())) return section
def execute(dirpath, filename, name_suffix, prefab_locator_list, offset_matrix, used_parts, used_terrain_points): """Exports PIP file from given locator list. :param prefab_locator_list: :type prefab_locator_list: list of bpy.types.Object :param dirpath: directory export path :type dirpath: str :param filename: name of PIP file :type filename: str :param name_suffix: file name suffix :type name_suffix: str :param offset_matrix: offset matrix for locators :type offset_matrix: mathutils.Matrix :param used_parts: parts transitional structure for storing used parts inside this PIP export :type used_parts: io_scs_tools.exp.transition_structs.parts.PartsTrans :param used_terrain_points: terrain points transitional structure for accessing terrain points stored during PIM export :type used_terrain_points: io_scs_tools.exp.transition_structs.terrain_points.TerrainPntsTrans :return: True if successfull; otherwise False :rtype: bool """ # CLEANUP CONNECTIONS DATA _connections_group_wrapper.cleanup_on_export() print("\n************************************") print("** SCS PIP Exporter **") print("** (c)2015 SCS Software **") print("************************************\n") (control_node_locs, nav_point_locs, sign_locs, spawn_point_locs, semaphore_locs, map_point_locs, trigger_point_locs) = __sort_locators_by_type__(prefab_locator_list) pip_header = Header(2, filename) pip_global = Globall() pip_nodes = OrderedDict() """:type: dict[int,Node]""" pip_curves = OrderedDict() """:type: dict[int, Curve]""" pip_signs = [] """:type: list[Sign]""" pip_spawn_points = [] """:type: list[SpawnPoint]""" pip_semaphores = [] """:type: list[Semaphore]""" pip_map_points = OrderedDict() """:type: dict[str, MapPoint]""" pip_trigger_points = OrderedDict() """:type: dict[str, TriggerPoint]""" pip_intersections = [OrderedDict(), OrderedDict(), OrderedDict()] """:type: list[dict[str, list[Intersection]]]""" # nodes creation for locator in control_node_locs.values(): locator_scs_props = locator.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" curr_node_i = int(locator_scs_props.locator_prefab_con_node_index) if curr_node_i not in pip_nodes: pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * locator.matrix_world) rot = Quaternion(rot) * Vector((0, 0, -1)) # create node with position and direction cn = Node(curr_node_i, pos, rot) # add terrain points terrain_points = used_terrain_points.get(curr_node_i) for variant_i in terrain_points: # ensure variant entry for no terrain points case cn.ensure_variant(variant_i) for tp_entry in terrain_points[variant_i]: cn.add_terrain_point(tp_entry.position, tp_entry.normal, variant_i) pip_nodes[curr_node_i] = cn else: lprint("W Multiple Control Nodes with same index detected, only one per index will be exported!\n\t " "Check Control Nodes in SCS Game Object with Root: %r", (filename,)) # curves creation curves_dict = _connections_group_wrapper.get_curves(nav_point_locs.values()) for key, curve_entry in curves_dict.items(): loc0 = nav_point_locs[curves_dict[key].start] loc0_scs_props = loc0.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" loc1 = nav_point_locs[curves_dict[key].end] loc1_scs_props = loc1.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" # create curve and set properties curve = __get_curve__(pip_curves, curve_entry.index, loc0.name) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * loc0.matrix_world) curve.set_start(pos, rot) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * loc1.matrix_world) curve.set_end(pos, rot) curve.set_input_boundaries(loc0_scs_props) curve.set_output_boundaries(loc1_scs_props) curve.set_flags(loc0.scs_props, True) curve.set_flags(loc1.scs_props, False) curve.set_semaphore_id(int(loc0_scs_props.locator_prefab_np_traffic_semaphore)) curve.set_traffic_rule(loc0_scs_props.locator_prefab_np_traffic_rule) # set next/prev curves for next_key in curve_entry.next_curves: next_curve = __get_curve__(pip_curves, curves_dict[next_key].index, curves_dict[next_key].start) assert curve.add_next_curve(next_curve) for prev_key in curve_entry.prev_curves: prev_curve = __get_curve__(pip_curves, curves_dict[prev_key].index, curves_dict[prev_key].start) assert curve.add_prev_curve(prev_curve) # sync nodes input lanes boundary_node_i = curve.get_input_node_index() if 0 <= boundary_node_i < _PL_consts.PREFAB_NODE_COUNT_MAX: if boundary_node_i in pip_nodes: assert pip_nodes[boundary_node_i].set_input_lane(curve.get_input_lane_index(), curve.get_index()) else: lprint("E None existing Boundary Node with index: %s used in Navigation Point: %r", (boundary_node_i, loc0.name,)) # sync nodes output lanes boundary_node_i = curve.get_output_node_index() if 0 <= boundary_node_i < _PL_consts.PREFAB_NODE_COUNT_MAX: if boundary_node_i in pip_nodes: assert pip_nodes[boundary_node_i].set_output_lane(curve.get_output_lane_index(), curve.get_index()) else: lprint("E None existing Boundary Node with index: %s used in Navigation Point: %r", (boundary_node_i, loc1.name,)) Curve.prepare_curves(pip_curves.values()) # signs creation for locator in sign_locs.values(): locator_scs_props = locator.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" # create sign and set properties sign = Sign(locator.name, used_parts.ensure_part(locator)) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * locator.matrix_world) sign.set_position(pos) sign.set_rotation(rot) if ":" in locator_scs_props.locator_prefab_sign_model: sign.set_model(locator_scs_props.locator_prefab_sign_model.split(":")[1].strip()) else: lprint("W Invalid Sign Model: %r on locator: %r", (locator_scs_props.locator_prefab_sign_model, locator.name)) pip_signs.append(sign) # spawn points creation for locator in spawn_point_locs.values(): locator_scs_props = locator.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" # create spawn point and set properties spawn_point = SpawnPoint(locator.name) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * locator.matrix_world) spawn_point.set_position(pos) spawn_point.set_rotation(rot) spawn_point.set_type(int(locator_scs_props.locator_prefab_spawn_type)) pip_spawn_points.append(spawn_point) # semaphores creation for locator in semaphore_locs.values(): locator_scs_props = locator.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" # create semaphore and set properties semaphore = Semaphore(int(locator_scs_props.locator_prefab_tsem_type)) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * locator.matrix_world) semaphore.set_position(pos) semaphore.set_rotation(rot) semaphore.set_semaphore_id(int(locator_scs_props.locator_prefab_tsem_id)) if ":" in locator_scs_props.locator_prefab_tsem_profile: semaphore.set_profile(locator_scs_props.locator_prefab_tsem_profile.split(":")[1].strip()) else: lprint("W Invalid Profile: %r on Traffic Semaphore locator: %r", (locator_scs_props.locator_prefab_tsem_profile, locator.name)) semaphore.set_intervals((locator_scs_props.locator_prefab_tsem_gs, locator_scs_props.locator_prefab_tsem_os1, locator_scs_props.locator_prefab_tsem_rs, locator_scs_props.locator_prefab_tsem_os2)) semaphore.set_cycle(locator_scs_props.locator_prefab_tsem_cyc_delay) pip_semaphores.append(semaphore) # map points creation for locator in map_point_locs.values(): locator_scs_props = locator.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" # create map point and set properties map_point = __get_map_point__(pip_map_points, locator.name) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * locator.matrix_world) map_point.set_position(pos) map_point.set_flags(locator_scs_props) for neighbour_name in _connections_group_wrapper.get_neighbours(locator): assert map_point.add_neighbour(__get_map_point__(pip_map_points, neighbour_name)) MapPoint.calc_segment_extensions(pip_map_points.values()) MapPoint.test_map_points(pip_map_points.values()) MapPoint.auto_generate_map_points(pip_map_points, pip_nodes) # trigger points creation for locator in trigger_point_locs.values(): locator_scs_props = locator.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" # create trigger point and set properties trigger_point = __get_trigger_point__(pip_trigger_points, locator.name) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * locator.matrix_world) trigger_point.set_position(pos) if ":" in locator_scs_props.locator_prefab_tp_action: trigger_point.set_action(locator_scs_props.locator_prefab_tp_action.split(":")[1].strip()) else: lprint("W Invalid Action: %r on Trigger Point locator: %r", (locator_scs_props.locator_prefab_tp_action, locator.name)) trigger_point.set_trigger_range(locator_scs_props.locator_prefab_tp_range) trigger_point.set_reset_delay(locator_scs_props.locator_prefab_tp_reset_delay) trigger_point.set_flags(locator_scs_props) for neighbour_name in _connections_group_wrapper.get_neighbours(locator): assert trigger_point.add_neighbour(__get_trigger_point__(pip_trigger_points, neighbour_name)) TriggerPoint.prepare_trigger_points(pip_trigger_points.values()) # intersections creation for c0_i, c0 in enumerate(sorted(pip_curves.values())): for c1_i, c1 in enumerate(sorted(pip_curves.values())): if c1_i <= c0_i: # only search each pair of curves once continue # get the intersection point and curves coefficient positions intersect_p, c0_pos, c1_pos = Intersection.get_intersection(c0, c1) if intersect_p: intersect_p_str = str(intersect_p) # Format: '<Vector (0.0000, 0.0000, 0.0000)>' is_start = c0_pos == 0 and c0_pos == c1_pos is_end = c1_pos == 1 and c0_pos == c1_pos is_split_sharp = False if is_start: inter_type = 0 # fork elif is_end: inter_type = 1 # joint else: inter_type = 2 # cross # if there is indication of cross intersection filter out intersections with common fork and joint # NOTE: this condition might not be sufficient, so if anyone will have problems, # this is the point that has to be improved if Intersection.have_common_fork(c0, c1) or Intersection.have_common_joint(c0, c1): continue # calculate radius for the same directions on curves forward_radius = Intersection.get_intersection_radius(c0, c1, c0_pos, c1_pos, 1, 1) backward_radius = Intersection.get_intersection_radius(c0, c1, c0_pos, c1_pos, -1, -1) final_radius = max(forward_radius, backward_radius) # special calculations only for cross intersections if inter_type == 2: # calculate radius also for opposite directions final_radius = max(final_radius, Intersection.get_intersection_radius(c0, c1, c0_pos, c1_pos, 1, -1)) final_radius = max(final_radius, Intersection.get_intersection_radius(c0, c1, c0_pos, c1_pos, -1, 1)) # calculate position of intersection point on curves with better precision c0_pos = c0.get_closest_point(intersect_p) c1_pos = c1.get_closest_point(intersect_p) # calculate if split cross intersection is too sharp for allowing of smother traffic flow c0_dir = c0.get_curve_tangent_at_position(c0_pos) c1_dir = c1.get_curve_tangent_at_position(c1_pos) is_split_sharp = c0_dir.dot(c1_dir) >= _PL_consts.CURVE_SPLIT_CROSS_DOT lprint("D Found cross intersection point: %r", (intersect_p,)) # creating intersection class instances intersection = Intersection(c0.get_index(), c0.get_ui_name(), c0_pos * c0.get_length()) intersection1 = Intersection(c1.get_index(), c1.get_ui_name(), c1_pos * c1.get_length()) # init list of intersections for current intersecting point if intersect_p_str not in pip_intersections[inter_type]: pip_intersections[inter_type][intersect_p_str] = [] # append intersections to list and calculate new siblings new_siblings = 2 if intersection not in pip_intersections[inter_type][intersect_p_str]: pip_intersections[inter_type][intersect_p_str].append(intersection) else: del intersection new_siblings -= 1 if intersection1 not in pip_intersections[inter_type][intersect_p_str]: pip_intersections[inter_type][intersect_p_str].append(intersection1) else: del intersection1 new_siblings -= 1 # always set flags on first entry in current intersection point list # this way siblings count is getting updated properly pip_intersections[inter_type][intersect_p_str][0].set_flags(is_start, is_end, is_split_sharp, new_siblings) # update radius on all of intersection in the same intersecting point for inter in pip_intersections[inter_type][intersect_p_str]: inter.set_radius(pip_intersections[inter_type][intersect_p_str][0].get_radius()) inter.set_radius(final_radius) # create container pip_container = [pip_header.get_as_section(), pip_global.get_as_section()] for node in pip_nodes.values(): pip_container.append(node.get_as_section()) for curve_key in sorted(pip_curves): pip_container.append(pip_curves[curve_key].get_as_section()) for sign in pip_signs: pip_container.append(sign.get_as_section()) for spawn_point in pip_spawn_points: pip_container.append(spawn_point.get_as_section()) for semaphore in pip_semaphores: pip_container.append(semaphore.get_as_section()) for map_point in pip_map_points.values(): pip_container.append(map_point.get_as_section()) for trigger_point in pip_trigger_points.values(): pip_container.append(trigger_point.get_as_section()) for inter_type in range(3): for intersect_p_str in pip_intersections[inter_type]: for intersection in pip_intersections[inter_type][intersect_p_str]: pip_container.append(intersection.get_as_section()) # write to file ind = " " pip_filepath = path.join(dirpath, str(filename + ".pip" + name_suffix)) result = _pix_container.write_data_to_file(pip_container, pip_filepath, ind) return result
def execute(dirpath, filename, prefab_locator_list, offset_matrix, used_terrain_points): """Exports PIP file from given locator list. :param prefab_locator_list: :type prefab_locator_list: list of bpy.types.Object :param dirpath: directory export path :type dirpath: str :param filename: name of PIP file :type filename: str :param offset_matrix: offset matrix for locators :type offset_matrix: mathutils.Matrix :param used_terrain_points: terrain points transitional structure for accessing terrain points stored during PIM export :type used_terrain_points: io_scs_tools.exp.transition_structs.terrain_points.TerrainPntsTrans :return: True if successfull; otherwise False :rtype: bool """ # CLEANUP CONNECTIONS DATA _connections_group_wrapper.cleanup_on_export() print("\n************************************") print("** SCS PIP Exporter **") print("** (c)2015 SCS Software **") print("************************************\n") (control_node_locs, nav_point_locs, sign_locs, spawn_point_locs, semaphore_locs, map_point_locs, trigger_point_locs) = __sort_locators_by_type__(prefab_locator_list) pip_header = Header(2, filename) pip_global = Globall() pip_nodes = OrderedDict() """:type: dict[int,Node]""" pip_curves = OrderedDict() """:type: dict[int, Curve]""" pip_signs = [] """:type: list[Sign]""" pip_spawn_points = [] """:type: list[SpawnPoint]""" pip_semaphores = [] """:type: list[Semaphore]""" pip_map_points = OrderedDict() """:type: dict[str, MapPoint]""" pip_trigger_points = OrderedDict() """:type: dict[str, TriggerPoint]""" pip_intersections = [OrderedDict(), OrderedDict(), OrderedDict()] """:type: list[dict[str, list[Intersection]]]""" # nodes creation for locator in control_node_locs.values(): locator_scs_props = locator.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" curr_node_i = int(locator_scs_props.locator_prefab_con_node_index) if curr_node_i not in pip_nodes: pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * locator.matrix_world) rot = Quaternion(rot) * Vector((0, 0, -1)) # create node with position and direction cn = Node(curr_node_i, pos, rot) # add terrain points terrain_points = used_terrain_points.get(curr_node_i) for variant_i in terrain_points: # ensure variant entry for no terrain points case cn.ensure_variant(variant_i) for tp_entry in terrain_points[variant_i]: cn.add_terrain_point(tp_entry.position, tp_entry.normal, variant_i) pip_nodes[curr_node_i] = cn else: lprint("W Multiple Control Nodes with same index detected, only one per index will be exported!\n\t " "Check Control Nodes in SCS Game Object with Root: %r", (filename,)) # curves creation curves_dict = _connections_group_wrapper.get_curves(nav_point_locs.values()) for key, curve_entry in curves_dict.items(): loc0 = nav_point_locs[curves_dict[key].start] loc0_scs_props = loc0.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" loc1 = nav_point_locs[curves_dict[key].end] loc1_scs_props = loc1.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" # create curve and set properties curve = __get_curve__(pip_curves, curve_entry.index, loc0.name) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * loc0.matrix_world) curve.set_start(pos, rot) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * loc1.matrix_world) curve.set_end(pos, rot) curve.set_input_boundaries(loc0_scs_props) curve.set_output_boundaries(loc1_scs_props) curve.set_flags(loc0.scs_props, True) curve.set_flags(loc1.scs_props, False) curve.set_semaphore_id(int(loc0_scs_props.locator_prefab_np_traffic_semaphore)) curve.set_traffic_rule(loc1_scs_props.locator_prefab_np_traffic_rule) # set next/prev curves for next_key in curve_entry.next_curves: next_curve = __get_curve__(pip_curves, curves_dict[next_key].index, curves_dict[next_key].start) assert curve.add_next_curve(next_curve) for prev_key in curve_entry.prev_curves: prev_curve = __get_curve__(pip_curves, curves_dict[prev_key].index, curves_dict[prev_key].start) assert curve.add_prev_curve(prev_curve) # sync nodes input lanes boundary_node_i = curve.get_input_node_index() if 0 <= boundary_node_i < _PL_consts.PREFAB_NODE_COUNT_MAX: if boundary_node_i in pip_nodes: assert pip_nodes[boundary_node_i].set_input_lane(curve.get_input_lane_index(), curve.get_index()) else: lprint("E None existing Boundary Node with index: %s used in Navigation Point: %r", (boundary_node_i, loc0.name,)) # sync nodes output lanes boundary_node_i = curve.get_output_node_index() if 0 <= boundary_node_i < _PL_consts.PREFAB_NODE_COUNT_MAX: if boundary_node_i in pip_nodes: assert pip_nodes[boundary_node_i].set_output_lane(curve.get_output_lane_index(), curve.get_index()) else: lprint("E None existing Boundary Node with index: %s used in Navigation Point: %r", (boundary_node_i, loc1.name,)) Curve.prepare_curves(pip_curves.values()) # signs creation for locator in sign_locs.values(): locator_scs_props = locator.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" # create sign and set properties sign = Sign(locator.name, locator_scs_props.scs_part) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * locator.matrix_world) sign.set_position(pos) sign.set_rotation(rot) if ":" in locator_scs_props.locator_prefab_sign_model: sign.set_model(locator_scs_props.locator_prefab_sign_model.split(":")[1].strip()) else: lprint("W Invalid Sign Model: %r on locator: %r", (locator_scs_props.locator_prefab_sign_model, locator.name)) pip_signs.append(sign) # spawn points creation for locator in spawn_point_locs.values(): locator_scs_props = locator.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" # create spawn point and set properties spawn_point = SpawnPoint(locator.name) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * locator.matrix_world) spawn_point.set_position(pos) spawn_point.set_rotation(rot) spawn_point.set_type(int(locator_scs_props.locator_prefab_spawn_type)) pip_spawn_points.append(spawn_point) # semaphores creation for locator in semaphore_locs.values(): locator_scs_props = locator.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" # create semaphore and set properties semaphore = Semaphore(int(locator_scs_props.locator_prefab_tsem_type)) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * locator.matrix_world) semaphore.set_position(pos) semaphore.set_rotation(rot) semaphore.set_semaphore_id(int(locator_scs_props.locator_prefab_tsem_id)) if ":" in locator_scs_props.locator_prefab_tsem_profile: semaphore.set_profile(locator_scs_props.locator_prefab_tsem_profile.split(":")[1].strip()) else: lprint("W Invalid Profile: %r on Traffic Semaphore locator: %r", (locator_scs_props.locator_prefab_tsem_profile, locator.name)) semaphore.set_intervals((locator_scs_props.locator_prefab_tsem_gs, locator_scs_props.locator_prefab_tsem_os1, locator_scs_props.locator_prefab_tsem_rs, locator_scs_props.locator_prefab_tsem_os2)) semaphore.set_cycle(locator_scs_props.locator_prefab_tsem_cyc_delay) pip_semaphores.append(semaphore) # map points creation for locator in map_point_locs.values(): locator_scs_props = locator.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" # create map point and set properties map_point = __get_map_point__(pip_map_points, locator.name) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * locator.matrix_world) map_point.set_position(pos) map_point.set_flags(locator_scs_props) for neighbour_name in _connections_group_wrapper.get_neighbours(locator): assert map_point.add_neighbour(__get_map_point__(pip_map_points, neighbour_name)) MapPoint.test_map_points(pip_map_points.values()) MapPoint.auto_generate_map_points(pip_map_points, pip_nodes) # trigger points creation for locator in trigger_point_locs.values(): locator_scs_props = locator.scs_props """:type: io_scs_tools.properties.object.ObjectSCSTools""" # create trigger point and set properties trigger_point = __get_trigger_point__(pip_trigger_points, locator.name) pos, rot, scale = _get_scs_transformation_components(offset_matrix.inverted() * locator.matrix_world) trigger_point.set_position(pos) if ":" in locator_scs_props.locator_prefab_tp_action: trigger_point.set_action(locator_scs_props.locator_prefab_tp_action.split(":")[1].strip()) else: lprint("W Invalid Action: %r on Trigger Point locator: %r", (locator_scs_props.locator_prefab_tp_action, locator.name)) trigger_point.set_trigger_range(locator_scs_props.locator_prefab_tp_range) trigger_point.set_reset_delay(locator_scs_props.locator_prefab_tp_reset_delay) trigger_point.set_flags(locator_scs_props) for neighbour_name in _connections_group_wrapper.get_neighbours(locator): assert trigger_point.add_neighbour(__get_trigger_point__(pip_trigger_points, neighbour_name)) TriggerPoint.prepare_trigger_points(pip_trigger_points.values()) # intersections creation for c0_i, c0 in enumerate(sorted(pip_curves.values())): for c1_i, c1 in enumerate(sorted(pip_curves.values())): if c1_i <= c0_i: # only search each pair of curves once continue # get the intersection point and curves coefficient positions intersect_p, c0_pos, c1_pos = Intersection.get_intersection(c0, c1) if intersect_p: intersect_p_str = str(intersect_p) # Format: '<Vector (0.0000, 0.0000, 0.0000)>' is_start = c0_pos == 0 and c0_pos == c1_pos is_end = c1_pos == 1 and c0_pos == c1_pos if is_start: inter_type = 0 # fork elif is_end: inter_type = 1 # joint else: inter_type = 2 # cross # if there is indication of cross intersection filter out intersections with common fork and joint # NOTE: this condition might not be sufficient, so if anyone will have problems, # this is the point that has to be improved if Intersection.have_common_fork(c0, c1) or Intersection.have_common_joint(c0, c1): continue # calculate radius for the same directions on curves forward_radius = Intersection.get_intersection_radius(c0, c1, c0_pos, c1_pos, 1, 1) backward_radius = Intersection.get_intersection_radius(c0, c1, c0_pos, c1_pos, -1, -1) final_radius = max(forward_radius, backward_radius) # special calculations only for cross intersections if inter_type == 2: # calculate radius also for opposite directions final_radius = max(final_radius, Intersection.get_intersection_radius(c0, c1, c0_pos, c1_pos, 1, -1)) final_radius = max(final_radius, Intersection.get_intersection_radius(c0, c1, c0_pos, c1_pos, -1, 1)) # calculate position of intersection point on curves with better precision c0_pos = c0.get_closest_point(intersect_p) c1_pos = c1.get_closest_point(intersect_p) lprint("D Found cross intersection point: %r", (intersect_p,)) # creating intersection class instances intersection = Intersection(c0.get_index(), c0.get_ui_name(), c0_pos * c0.get_length()) intersection1 = Intersection(c1.get_index(), c1.get_ui_name(), c1_pos * c1.get_length()) # init list of intersections for current intersecting point if intersect_p_str not in pip_intersections[inter_type]: pip_intersections[inter_type][intersect_p_str] = [] # append intersections to list and calculate new siblings new_siblings = 2 if intersection not in pip_intersections[inter_type][intersect_p_str]: pip_intersections[inter_type][intersect_p_str].append(intersection) else: del intersection new_siblings -= 1 if intersection1 not in pip_intersections[inter_type][intersect_p_str]: pip_intersections[inter_type][intersect_p_str].append(intersection1) else: del intersection1 new_siblings -= 1 # always set flags on first entry in current intersection point list # this way siblings count is getting updated properly pip_intersections[inter_type][intersect_p_str][0].set_flags(is_start, is_end, new_siblings) # update radius on all of intersection in the same intersecting point for inter in pip_intersections[inter_type][intersect_p_str]: inter.set_radius(pip_intersections[inter_type][intersect_p_str][0].get_radius()) inter.set_radius(final_radius) # create container pip_container = [pip_header.get_as_section(), pip_global.get_as_section()] for node in pip_nodes.values(): pip_container.append(node.get_as_section()) for curve_key in sorted(pip_curves): pip_container.append(pip_curves[curve_key].get_as_section()) for sign in pip_signs: pip_container.append(sign.get_as_section()) for spawn_point in pip_spawn_points: pip_container.append(spawn_point.get_as_section()) for semaphore in pip_semaphores: pip_container.append(semaphore.get_as_section()) for map_point in pip_map_points.values(): pip_container.append(map_point.get_as_section()) for trigger_point in pip_trigger_points.values(): pip_container.append(trigger_point.get_as_section()) for inter_type in range(3): for intersect_p_str in pip_intersections[inter_type]: for intersection in pip_intersections[inter_type][intersect_p_str]: pip_container.append(intersection.get_as_section()) # write to file ind = " " pip_filepath = path.join(dirpath, str(filename + ".pip")) result = _pix_container.write_data_to_file(pip_container, pip_filepath, ind) return result