/
Manifest
/
Real_Texture
Обзор
Документация
Войти
/
Manifest
/
Real_Texture
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
ToolsPythonForSequenceInUE/Readme_HideEnv.txt
308 строк
14 KB
m.samodurov
init commit for The Invaders
17 фев 2026, 04:57
17 фев 2026, 04:57
4a668d4
Код
Авторство
О чём код?
0. Удаление уровней из level_visibility_track 1. Hiding уровней 2. Очищать все копии перед применением скрипта (и Actor_for_Copy) import unreal import re import math "======================================================================================================" "=================================РЕДАКТИРУЕМЫЕ ПАРАМЕТРЫ==============================================" "======================================================================================================" max_distance = 10000 # В Сантиметрах. Default = 10000. Ограничение по дефолту в 10000 см (100 метров) для Occlusion Culling extent_scale = 1.0 # В десятичных от процента (1.5 = 50%). Default = 1. Коэффициент искусственного увеличения BoxExtent объектов в камере padding_degrees_for_FoV = 0 # В радианах. Default = 0. Добавление падинга по горизонтали и вертикали duration = 10 # В Секундах. Default = 10. Длительность DEBUG-пирамиды. Таймер отсчитывается в stat fps только. Не в ран-тайме всё время висит "Папки для игнорирования в Outliner'е; Запись через r" # TODO: Символ \d+ равносилен регулярке *; IGNORE_FOLDERS = \ [ r"sq\d+_sh\d+_light", #r"Decals", #<- Если надо убрать декали? r"ProxyGeo", r"River", r"City", r"light", ] "Имена объектов (любых) для игнорирования в Outliner'е" IGNORE_NAMES = \ [ "cheba_2_BP", "gena_2_BP", "lariska_BP", "shapoklyak_BP", "galya" ] "Классы объектов по типу для игнорирования в Outliner'е" IGNORE_CLASSES = \ ( unreal.SkeletalMeshActor, #unreal.DecalActor, #<- Если надо убрать декали? unreal.CineCameraActor, unreal.GroupActor, unreal.GeometryCache, ) "======================================================================================================" "=================================ВСПОМОГАТЕЛЬНЫЕ И ОСНОВНЫЕ ФУНКЦИИ===================================" "Вспомогательная функция приведения к единичному вектору, ибо UE не имеет норм функции" def normalize_vector(vec): length = vec.length() if length > 0: return vec / length return vec # Если длина 0, возвращаем оригинал (или Vector(0,0,0) можно, пока хз) "Вспомогательная функция для [DEBUG] Occlusion Culling'а" def draw_camera_frustum(camera, horizontal_fov_deg, aspect_ratio, max_distance=10000, duration=10.0): world = camera.get_world() cam_location = camera.get_actor_location() cam_rotation = camera.get_actor_rotation() horizontal_fov = math.radians(horizontal_fov_deg) vertical_fov = horizontal_fov / aspect_ratio yaw_rad = math.radians(cam_rotation.yaw) pitch_rad = math.radians(cam_rotation.pitch) def get_dir_vector(yaw_offset, pitch_offset): yaw = yaw_rad + yaw_offset pitch = pitch_rad + pitch_offset vec = (unreal.Vector ( math.cos(pitch) * math.cos(yaw), math.cos(pitch) * math.sin(yaw), math.sin(pitch) )) return normalize_vector(vec) half_h_fov = horizontal_fov / 2 half_v_fov = vertical_fov / 2 corners = \ [ get_dir_vector(-half_h_fov, half_v_fov), # верхний левый get_dir_vector( half_h_fov, half_v_fov), # верхний правый get_dir_vector(-half_h_fov, -half_v_fov), # нижний левый get_dir_vector( half_h_fov, -half_v_fov), # нижний правый ] line_color = unreal.LinearColor(1, 0, 0, 1) #цвет линии thickness = 2.0 for corner_dir in corners: end_point = cam_location + corner_dir * max_distance unreal.SystemLibrary.draw_debug_line(world, cam_location, end_point, line_color, duration, thickness) for i in range(4): start = cam_location + corners[i] * max_distance end = cam_location + corners[(i + 1) % 4] * max_distance unreal.SystemLibrary.draw_debug_line(world, start, end, line_color, duration, thickness) """ Вспомогательная функция Occlusion Culling для проверки попадания Bounding Box (AABB по 8 точкам) актора в пределы поля зрения камеры (упрощённый frustum check/project_world_to_screen). Ограничен max_distance """ def is_actor_in_frustum(actor, camera, horizontal_fov_deg, aspect_ratio, max_distance=10000): # Получаем BBox и transform камеры origin, box_extent = actor.get_actor_bounds(False) cam_transform = camera.get_actor_transform() # Увеличиваем размер Bounding Box'а (искусственно) box_extent *= extent_scale # Перевод FOV в радианы horizontal_fov = math.radians(horizontal_fov_deg) vertical_fov = horizontal_fov / aspect_ratio # Добавляем небольшой запас к FOV по padding fov_padding = math.radians(padding_degrees_for_FoV) # ← Плюс падинг horizontal_fov += fov_padding vertical_fov += fov_padding # Проверяем все 8 углов BBox'а for x in [-1, 1]: for y in [-1, 1]: for z in [-1, 1]: corner = origin + unreal.Vector(x * box_extent.x, y * box_extent.y, z * box_extent.z) # Преобразуем в локальные координаты камеры local_pos = unreal.MathLibrary.inverse_transform_location(cam_transform, corner) # За камерой — игнорируем if local_pos.x < 0: continue # Дальность больше допустимой - игнорируем distance = local_pos.length() if distance > max_distance: continue # Углы между направлением камеры и точкой hor_angle = abs(math.atan2(local_pos.y, local_pos.x)) vert_angle = abs(math.atan2(local_pos.z, local_pos.x)) # Внутри frustum — значит актор видим if hor_angle < horizontal_fov / 2 and vert_angle < vertical_fov / 2: return True return False "Основная функция дублирования видимых объектов" # TODO: распидорасить на функции def DublicateEnv(): "======================================================================================================" unreal.log_warning("Начало скрипта дублирования") "======================================================================================================" editor_world = unreal.get_editor_subsystem(unreal.UnrealEditorSubsystem).get_editor_world() actor_subsystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem) level_editor_subsystem = unreal.get_editor_subsystem(unreal.LevelEditorSubsystem) sub_levels = unreal.EditorLevelUtils.get_levels(editor_world) visible_level_paths = set() for level in sub_levels: level_package_name = level.get_package().get_name() streaming_level = unreal.GameplayStatics.get_streaming_level(editor_world, level_package_name) if streaming_level and streaming_level.is_level_visible(): visible_level_paths.add(level_package_name) unreal.log(f"Обнаружено видимых уровней: {list(visible_level_paths)}") active_level = level_editor_subsystem.get_current_level() if not active_level: unreal.log_error("Активный уровень не определяется. Пиши Максу") quit() active_level_path = active_level.get_package().get_name() unreal.log(f"Активный уровень: {active_level_path}") if active_level_path not in visible_level_paths: unreal.log_warning("Активный уровень не является видимым. Выбери уровень в Levels.") quit() # Преобразование уровня в LevelStreaming для дальнейшей работы с RootActor (Actor_for_Group) active_streaming_level = None for subLevel in sub_levels: subLevelPackageName = subLevel.get_package().get_name() streamingLevel = unreal.GameplayStatics.get_streaming_level(editor_world, subLevelPackageName) if streamingLevel and streamingLevel.is_level_visible() and (active_level_path == subLevelPackageName): active_streaming_level = streamingLevel all_actors = \ [ actor for actor in actor_subsystem.get_all_level_actors() if actor.get_level().get_package().get_name() in visible_level_paths ] camera = next((a for a in all_actors if isinstance(a, unreal.CineCameraActor)), None) if not camera: unreal.log_error("Камера не найдена") quit() unreal.log(f"Найдена камера: {camera.get_name()}") camera_component = camera.get_cine_camera_component() horizontal_fov = camera_component.get_horizontal_field_of_view() aspect_ratio = camera_component.aspect_ratio existing_root_actor = next((a for a in all_actors if a.get_actor_label() == "Actor_for_Copy"), None) if existing_root_actor: unreal.log_error("Actor_for_Copy уже существует") quit() root_actor = actor_subsystem.spawn_actor_from_class(unreal.Actor, unreal.Vector(0, 0, 0)) if not root_actor: unreal.log_error("Не удалось создать Actor_for_Copy") quit() root_actor.set_actor_label("Actor_for_Copy") unreal.EditorLevelUtils.move_actors_to_level([root_actor], active_streaming_level) unreal.log(f"Создан актор: {root_actor.get_actor_label()}") for actor in all_actors: actor_level_path = actor.get_level().get_package().get_name() if actor.get_actor_label() in IGNORE_NAMES: continue folder_path = str(actor.get_folder_path()) if any(re.match(pattern, folder_path) for pattern in IGNORE_FOLDERS): continue actor_class_name = actor.get_class().get_name() if any( ( (isinstance(ignore_class, type) and isinstance(actor, ignore_class)) or (isinstance(ignore_class, str) and actor_class_name == ignore_class) for ignore_class in IGNORE_CLASSES )): continue if actor_level_path in visible_level_paths and not isinstance(actor, unreal.CineCameraActor): if not is_actor_in_frustum(actor, camera, horizontal_fov, aspect_ratio, max_distance): continue #draw_camera_frustum(camera, horizontal_fov, aspect_ratio, max_distance=10000, duration=10) # TODO: <-[DEBUG]-пирамида duplicated_actor = actor_subsystem.duplicate_actor(actor, editor_world) if duplicated_actor: duplicated_actor.set_actor_label(actor.get_actor_label() + "_copy") unreal.EditorLevelUtils.move_actors_to_level([duplicated_actor], active_streaming_level) (duplicated_actor.attach_to_actor ( root_actor, unreal.Name(""), unreal.AttachmentRule.KEEP_WORLD, unreal.AttachmentRule.KEEP_WORLD, unreal.AttachmentRule.KEEP_WORLD, False )) else: unreal.log_warning(f"Не удалось дублировать актор: {actor.get_name()}") "======================================================================================================" unreal.log_warning("Конец скрипта дублирования") "======================================================================================================" "Основная функция удаления/скрытия уровней" # TODO: в процессе def HideLevelsTrack(): "======================================================================================================" unreal.log_warning("Начало скрипта удаления/скрытия уровней") "======================================================================================================" # Получаем активный Level Sequence level_sequence = unreal.LevelSequenceEditorBlueprintLibrary.get_current_level_sequence() if not level_sequence: unreal.log_error("Нет активного Level Sequence!") else: unreal.log("Очищаем Level Visibility треки...") # Получаем мастер-треки напрямую из секвенции (не из MovieScene) master_tracks = level_sequence.get_tracks() for track in master_tracks: if isinstance(track, unreal.MovieSceneLevelVisibilityTrack): unreal.log(f"Обрабатываем трек: {track.get_display_name()}") for section in track.get_sections(): section.set_editor_property("level_names", []) unreal.log(f"Очищена секция {section.get_name()} в треке {track.get_display_name()}") "======================================================================================================" unreal.log_warning("Конец скрипта удаления/скрытия уровней") "======================================================================================================" def main(): #DublicateEnv() # Вызов функции HideLevelsTrack() if __name__ == "__main__": main()