From 1e7b7fb9b802eeed346f61acf1531b29c0475c7d Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Sat, 16 Nov 2024 21:44:24 +0300 Subject: [PATCH] Better infodecal handing --- .../bsp/entities/abstract_entity_handlers.py | 14 ++++++- .../bsp/entities/base_entity_handler.py | 39 ++++++++++++++++++- .../bsp/entities/sof_entity_handler.py | 1 + 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/blender_bindings/source1/bsp/entities/abstract_entity_handlers.py b/blender_bindings/source1/bsp/entities/abstract_entity_handlers.py index d4ea82d1..ea9c5d1b 100644 --- a/blender_bindings/source1/bsp/entities/abstract_entity_handlers.py +++ b/blender_bindings/source1/bsp/entities/abstract_entity_handlers.py @@ -75,6 +75,7 @@ def __init__(self, bsp_file: BSPFile, parent_collection, self._entites = self._bsp.get_lump('LUMP_ENTITIES').entities self._handled_paths = [] self._entity_by_name_cache = {} + self._world_geometry_name = "" def load_entities(self, settings: BSPOptions): entity_lump = self._bsp.get_lump('LUMP_ENTITIES') @@ -152,13 +153,19 @@ def _load_brush_model(self, model_id, model_name): remapped = dict(zip(vertex_ids, tmp2)) material_lookup_table = {} - for texture_info in sorted(set(material_ids)): - texture_info = bsp_textures_info[texture_info] + skippable_materials = set() + for texture_info_id in sorted(set(material_ids)): + texture_info = bsp_textures_info[texture_info_id] texture_data = bsp_textures_data[texture_info.texture_data_id] material_name = self._get_string(texture_data.name_id) material_name = strip_patch_coordinates.sub("", material_name) material = get_or_create_material(path_stem(material_name), material_name) material_lookup_table[texture_data.name_id] = add_material(material, mesh_obj) + material_file = self.content_manager.find_file(TinyPath("materials") / (material_name + ".vmt")) + if material_file: + vmt = VMT(material_file, material_name, self.content_manager) + if vmt.get_int("$abovewater", 1) == 0: + skippable_materials.add(texture_info_id) uvs_per_face = [] luvs_per_face = [] @@ -166,6 +173,9 @@ def _load_brush_model(self, model_id, model_name): for map_face in bsp_faces[model.first_face:model.first_face + model.face_count]: if map_face.disp_info_id != -1: continue + if map_face.tex_info_id in skippable_materials: + continue + uvs = {} luvs = {} face = [] diff --git a/blender_bindings/source1/bsp/entities/base_entity_handler.py b/blender_bindings/source1/bsp/entities/base_entity_handler.py index e598e081..4e0e1ea2 100644 --- a/blender_bindings/source1/bsp/entities/base_entity_handler.py +++ b/blender_bindings/source1/bsp/entities/base_entity_handler.py @@ -289,6 +289,7 @@ def handle_trigger_once(self, entity: trigger_once, entity_raw: dict): def handle_worldspawn(self, entity: worldspawn, entity_raw: dict): world = self._load_brush_model(0, 'world_geometry') + self._world_geometry_name = world.name self._set_entity_data(world, {'entity': entity_raw}) self.parent_collection.objects.link(world) try: @@ -773,11 +774,47 @@ def handle_infodecal(self, entity: infodecal, entity_raw: dict): mesh_data = obj.data mesh_data.from_pydata(verts, [], [[0, 1, 2, 3]]) + origin = Vector(entity.origin) + if self._world_geometry_name != "": + world_geometry = bpy.data.objects[self._world_geometry_name] + depsgraph = bpy.context.evaluated_depsgraph_get() + world_geometry_eval = world_geometry.evaluated_get(depsgraph) + closest_distance = 1.70141e+38 + closest_hit = None + ray_directions = [ + Vector((0, 0, -1)), # Down + Vector((0, 0, 1)), # Up + Vector((0, -1, 0)), # Backward + Vector((0, 1, 0)), # Forward + Vector((-1, 0, 0)), # Left + Vector((1, 0, 0)), # Right + ] + + for direction in ray_directions: + scaled_origin = origin * self.scale + hit, location, normal, index = world_geometry_eval.ray_cast(scaled_origin, direction, distance=closest_distance, + depsgraph=depsgraph) + + if hit: + distance = (scaled_origin - location).length + if distance < closest_distance: + closest_distance = distance + closest_hit = (location, normal) + + if closest_hit: + location, normal = closest_hit + + target_direction = -normal + rotation = target_direction.to_track_quat('Y', 'Z').to_euler() + obj.rotation_euler = rotation + + origin += (normal * 0.01) / self.scale + uv_data = mesh_data.uv_layers.new().data material = get_or_create_material(path_stem(material_name), material_name) add_material(material, obj) - self._set_location_and_scale(obj, entity.origin) + self._set_location_and_scale(obj, origin) self._set_entity_data(obj, {'entity': entity_raw}) self._put_into_collection('infodecal', obj) diff --git a/blender_bindings/source1/bsp/entities/sof_entity_handler.py b/blender_bindings/source1/bsp/entities/sof_entity_handler.py index 7565d6f1..480618c8 100644 --- a/blender_bindings/source1/bsp/entities/sof_entity_handler.py +++ b/blender_bindings/source1/bsp/entities/sof_entity_handler.py @@ -159,6 +159,7 @@ def handle_worldspawn(self, entity: Base, entity_raw: dict): world = self._load_brush_model(0, 'world_geometry') if not world: return + self._world_geometry_name = world.name self._set_entity_data(world, {'entity': entity_raw}) self.parent_collection.objects.link(world)