srctools.bsp

Read and write parts of Source BSP files.

Data from a read BSP is lazily parsed when each section is accessed.

class srctools.bsp.BSP_LUMPS(
value,
names=None,
*,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)

Bases: Enum

All the lumps in a BSP file.

The values represent the order lumps appear in the index. Some indexes were reused, so they have aliases.

ENTITIES = 0

self.ents

PLANES = 1

self.planes

TEXDATA = 2
VERTEXES = 3

self.vertexes

VISIBILITY = 4
NODES = 5

self.nodes

TEXINFO = 6

self.texinfo

FACES = 7

self.faces

LIGHTING = 8
OCCLUSION = 9
LEAFS = 10

self.leafs

FACEIDS = 11
EDGES = 12
SURFEDGES = 13

self.surfedges

MODELS = 14

self.bmodels

WORLDLIGHTS = 15
LEAFFACES = 16
LEAFBRUSHES = 17
BRUSHES = 18

self.brushes

BRUSHSIDES = 19
AREAS = 20
AREAPORTALS = 21
PORTALS = 22

Aliases: UNUSED0, PROPCOLLISION

CLUSTERS = 23

Aliases: UNUSED1, PROPHULLS

PORTALVERTS = 24

Aliases: UNUSED2, PROPHULLVERTS

CLUSTERPORTALS = 25

Aliases: UNUSED3, PROPTRIS

DISPINFO = 26
ORIGINALFACES = 27

self.orig_faces

PHYSDISP = 28
PHYSCOLLIDE = 29
VERTNORMALS = 30
VERTNORMALINDICES = 31
DISP_LIGHTMAP_ALPHAS = 32
DISP_VERTS = 33
DISP_LIGHTMAP_SAMPLE_POSITIONS = 34
GAME_LUMP = 35
LEAFWATERDATA = 36

self.water_leaf_info

PRIMITIVES = 37

self.primitives

PRIMVERTS = 38
PRIMINDICES = 39
PAKFILE = 40

self.pakfile

CLIPPORTALVERTS = 41
CUBEMAPS = 42

self.cubemaps

TEXDATA_STRING_DATA = 43
TEXDATA_STRING_TABLE = 44

self.textures

OVERLAYS = 45

self.overlays

LEAFMINDISTTOWATER = 46
FACE_MACRO_TEXTURE_INFO = 47
DISP_TRIS = 48
PROP_BLOB = 49

Alias: PHYSCOLLIDESURFACE

WATEROVERLAYS = 50
LEAF_AMBIENT_INDEX_HDR = 51

Alias: LIGHTMAPPAGES

LEAF_AMBIENT_INDEX = 52

Alias: LIGHTMAPPAGEINFOS

LIGHTING_HDR = 53
WORLDLIGHTS_HDR = 54
LEAF_AMBIENT_LIGHTING_HDR = 55
LEAF_AMBIENT_LIGHTING = 56
XZIPPAKFILE = 57
FACES_HDR = 58

self.hdr_faces

MAP_FLAGS = 59
OVERLAY_FADES = 60
OVERLAY_SYSTEM_LEVELS = 61
PHYSLEVEL = 62
DISP_MULTIBLEND = 63
class srctools.bsp.VERSIONS(
value,
names=None,
*,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)

Bases: Enum

The BSP version numbers for various games.

VER_17 = 17
VER_18 = 18
VER_19 = 19

Aliases: HL2, CS_SOURCE, DOF_SOURCE

VER_20 = 20

Aliases: HL2_EP1, HL2_EP2, HL2_LC, GARYS_MOD, TF2, PORTAL, L4D, ZENO_CLASH, DARK_MESSIAH, VINDICTUS, THE_SHIP, BLACK_MESA, BLOODY_GOOD_TIME

VER_21 = 21

Aliases: L4D2, ALIEN_SWARM, PORTAL_2, CS_GO, DEAR_ESTHER, STANLEY_PARABLE

VER_22 = 22

Aliases: INFRA, DOTA2

VER_29 = 29
CONTAGION = 23
CHAOSSOURCE = 25
DESOLATION_OLD = 42
VITAMINSOURCE = 43
class srctools.bsp.GameVersion(
value,
names=None,
*,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)

Bases: Enum

Identifies specific games which we need to detect and specially handle.

NORMAL = 'normal'
L4D2 = 'l4d2'
VITAMINSOURCE = 'vitaminsource'
class srctools.bsp.BSP(
filename: str | _os.PathLike[str],
version: VERSIONS | GameVersion | None = None,
)

A BSP file.

game_ver: GameVersion

A srctools-specific version to identify some games with unique handling.

map_revision: int
lump_layout: LumpDataLayout
version: VERSIONS | int

The version ID in the file.

pakfile: ParsedLump[ZipFile]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

ents: ParsedLump[VMF]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

textures: ParsedLump[List[str]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

texinfo: ParsedLump[List[TexInfo]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

cubemaps: ParsedLump[List[Cubemap]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

overlays: ParsedLump[List[Overlay]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

bmodels: ParsedLump[WeakKeyDictionary[Entity, BModel]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

brushes: ParsedLump[List[Brush]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

visleafs: ParsedLump[List[VisLeaf]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

water_leaf_info: ParsedLump[List[LeafWaterInfo]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

nodes: ParsedLump[List[VisTree]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

visibility: ParsedLump[Visibility | None]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

vertexes: ParsedLump[List[Vec]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

surfedges: ParsedLump[List[Edge]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

planes: ParsedLump[List[Plane]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

faces: ParsedLump[List[Face]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

orig_faces: ParsedLump[List[Face]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

hdr_faces: ParsedLump[List[Face]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

primitives: ParsedLump[List[Primitive]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

props: ParsedLump[List[StaticProp]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

detail_props: ParsedLump[List[DetailProp]]

Allows access to parsed versions of lumps.

When accessed, the corresponding lump is parsed into an object tree. The lump is then cleared of data. When the BSP is saved, the lump data is then constructed.

If the lump name is bytes, it’s a game lump identifier.

property is_vitamin: bool

Vitaminsource has a lot of structure changes.

read(
expected_version: VERSIONS | GameVersion | None = None,
) None

Load all data.

save(filename: str | None = None) None

Write the BSP back into the given file.

read_header() None

No longer used.

read_game_lumps() None

No longer used.

replace_lump(
new_name: str,
lump: BSP_LUMPS | Lump,
new_data: bytes,
) None

Write out the BSP file, replacing a lump with the given bytes.

Deprecated:

simply assign to the .data attribute of the lump.

get_lump(lump: BSP_LUMPS) bytes

Return the contents of the given lump.

get_game_lump(lump_id: bytes) bytes

Get a given game-lump, given the 4-character byte ID.

create_texinfo(
mat: str,
*,
copy_from: TexInfo,
fsys: FileSystem,
) TexInfo
create_texinfo(
mat: str,
*,
copy_from: TexInfo,
reflectivity: AnyVec,
width: int,
height: int,
) TexInfo
create_texinfo(
mat: str,
s_off: AnyVec = FrozenVec(),
s_shift: float = -99999.0,
t_off: AnyVec = FrozenVec(),
t_shift: float = -99999.0,
lightmap_s_off: AnyVec = FrozenVec(),
lightmap_s_shift: float = -99999.0,
lightmap_t_off: AnyVec = FrozenVec(),
lightmap_t_shift: float = -99999.0,
flags: SurfFlags = SurfFlags.NONE,
*,
fsys: FileSystem,
) TexInfo
create_texinfo(
mat: str,
s_off: AnyVec = FrozenVec(),
s_shift: float = -99999.0,
t_off: AnyVec = FrozenVec(),
t_shift: float = -99999.0,
lightmap_s_off: AnyVec = FrozenVec(),
lightmap_s_shift: float = -99999.0,
lightmap_t_off: AnyVec = FrozenVec(),
lightmap_t_shift: float = -99999.0,
flags: SurfFlags = SurfFlags.NONE,
*,
reflectivity: AnyVec,
width: int,
height: int,
) TexInfo

Create or find a texinfo entry with the specified values.

The s/t offset and shift values control the texture positioning. The defaults are those used for overlays, but for brushes all must be specified. Alternatively copy_from can be provided an existing texinfo to copy from, if a texture is being swapped out.

In the BSP each material also stores its texture size and reflectivity. If the material has not been used yet, these must either be specified manually or a filesystem provided for the VMT and VTFs to be read from.

is_cordoned_heuristic() bool

Guess to see if the map uses cordons.

There’s no definite flag, but we can guess based on the shape of the geometry. Cordoning causes a brush almost the map size units to be created, then the cordon regions carved out of it. So the overall map size will be very close to the max range.

This isn’t certain, since users could manually create brushes this large, but that’s not too likely.

is_potentially_visible(
leaf1: VisLeaf,
leaf2: VisLeaf,
) Tuple[bool, bool]

Check if the first leaf can potentially see and hear the second.

Always returns True if visibility data has not been computed (self.visibility is None).

set_potentially_visible(
leaf1: VisLeaf,
leaf2: VisLeaf,
visible: bool | None = None,
audible: bool | None = None,
) None

Override whether the first leaf can see/hear the second.

If either bool is None that value is left unaltered.

read_texture_names() Iterator[str]

Iterate through all brush textures in the map.

packfile() Iterator[ZipFile]

A context manager to allow editing the packed content.

When successfully exited, the zip will be rewritten to the BSP file.

read_ent_data() VMF

Deprecated function to parse the entdata lump.

Use BSP.ents directly.

static write_ent_data(
vmf: VMF,
use_comma_sep: bool | None = None,
*,
_show_dep: bool = True,
) bytes

Generate the entity data lump.

Deprecated:

Read and write BSP.ents instead.

Parameters:
  • vmf – This accepts a VMF file like that returned from read_ent_data(). Brushes are ignored, so the VMF must use *xx model references.

  • use_comma_sep – This is used to force using either commas, or 0x1D in I/O.

static_prop_models() Iterator[str]

Yield all model filenames used in static props.

static_props() Iterator[StaticProp]

Read in the Static Props lump.

Deprecated, use bsp.props.

write_static_props(
props: List[StaticProp],
) None

Remake the static prop lump.

Deprecated, bsp.props is stored and resaved.

vis_tree() VisTree

Parse the visleaf data, and return the root node.

class srctools.bsp.Lump(
type: BSP_LUMPS,
version: int,
data: bytes = b'',
is_compressed: bool = False,
)

Represents a lump header in a BSP file.

type: BSP_LUMPS
version: int
data: bytes
is_compressed: bool
class srctools.bsp.GameLump(
id: bytes,
flags: int,
version: int,
data: bytes = b'',
)

Represents a game lump.

These are designed to be game-specific.

id: bytes
flags: int
version: int
data: bytes
ST: ClassVar[Struct] = <_struct.Struct object>
property is_compressed: bool

This flag indicates if the lump was compressed.

class srctools.bsp.StaticProp(
model: str,
origin: ~srctools.math.Vec,
angles: ~srctools.math.Angle = NOTHING,
scaling: ~srctools.math.Vec | float = NOTHING,
visleafs: ~typing.Set[~srctools.bsp.VisLeaf] = NOTHING,
solidity: int = 6,
flags: ~srctools.bsp.StaticPropFlags = <StaticPropFlags.NONE: 0>,
skin: int = 0,
min_fade: float = 0.0,
max_fade: float = 0.0,
lighting: ~srctools.math.Vec = NOTHING,
fade_scale: float = -1.0,
min_dx_level: int = 0,
max_dx_level: int = 0,
min_cpu_level: int = 0,
max_cpu_level: int = 0,
min_gpu_level: int = 0,
max_gpu_level: int = 0,
tint: ~srctools.math.Vec = NOTHING,
renderfx: int = 255,
disable_on_xbox: bool = False,
lightmap_x: int = 32,
lightmap_y: int = 32,
)

Represents a prop_static in the BSP.

Different features were added in different versions.

  • v5+ allows fade_scale.

  • v6 and v7 allow min/max DXLevel.

  • v8+ allows min/max GPU and CPU levels.

  • v7+ allows model tinting, and renderfx.

  • v9+ allows disabling on XBox 360.

  • v10+ adds 4 unknown bytes (float?), and an expanded flags section.

  • v11+ adds uniform scaling.

model: str
origin: Vec
angles: Angle
scaling: Vec | float
visleafs: Set[VisLeaf]
solidity: int
flags: StaticPropFlags
skin: int
min_fade: float
max_fade: float
lighting: Vec
fade_scale: float
min_dx_level: int
max_dx_level: int
min_cpu_level: int
max_cpu_level: int
min_gpu_level: int
max_gpu_level: int
tint: Vec
renderfx: int
disable_on_xbox: bool
lightmap_x: int
lightmap_y: int
class srctools.bsp.StaticPropFlags(
value,
names=None,
*,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)

Bases: Flag

Bitflags specified for static props.

NONE = 0
DOES_FADE = 1
HAS_LIGHTING_ORIGIN = 2
NO_FLASHLIGHT = 4

Alias: DISABLE_DRAW

This was nodraw in earlier versions, but it now prevents projected textures from affecting the prop.

IGNORE_NORMALS = 8
NO_SHADOW = 16
SCREEN_SPACE_FADE = 32

Use screen space fading. Obsolete since at least ASW.

NO_PER_VERTEX_LIGHTING = 64
NO_SELF_SHADOWING = 128
NO_SHADOW_DEPTH = 256

Alias: NO_LIGHTMAP

Disable affecting projected texture lighting. In games supporting lightmapped props (TF2), this instead, disables per-luxel lighting.

BOUNCED_LIGHTING = 1024

Bounce lighting off the prop.

value_prim

Return the data for the original flag byte.

value_sec

Return the data for the secondary flag byte.

class srctools.bsp.DetailProp(
origin: Vec,
angles: Angle,
orientation: DetailPropOrientation,
leaf: int,
lighting: Tuple[int, int, int, int],
light_styles: Tuple[int, int],
sway_amount: int,
)

A detail prop, automatically placed on surfaces.

This is a base class, use one of the subclasses only.

origin: Vec
angles: Angle
orientation: DetailPropOrientation
leaf: int
lighting: Tuple[int, int, int, int]
sway_amount: int
class srctools.bsp.DetailPropModel(
origin: Vec,
angles: Angle,
orientation: DetailPropOrientation,
leaf: int,
lighting: Tuple[int, int, int, int],
light_styles: Tuple[int, int],
sway_amount: int,
model: str,
)

A MDL detail prop.

model: str
class srctools.bsp.DetailPropOrientation(
value,
names=None,
*,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)

Bases: Enum

The kind of orientation for detail props.

NORMAL = 0
SCREEN_ALIGNED = 1
SCREEN_ALIGNED_VERTICAL = 2
class srctools.bsp.DetailPropShape(
origin: Vec,
angles: Angle,
orientation: DetailPropOrientation,
leaf: int,
lighting: Tuple[int, int, int, int],
light_styles: Tuple[int, int],
sway_amount: int,
sprite_scale: float,
dims_upper_left: Tuple[float, float],
dims_lower_right: Tuple[float, float],
texcoord_upper_left: Tuple[float, float],
texcoord_lower_right: Tuple[float, float],
is_cross: bool,
shape_angle: int,
shape_size: int,
)

A shape-type detail prop, rendered as a triangle or cross shape.

is_cross: bool
shape_angle: int
shape_size: int
class srctools.bsp.DetailPropSprite(
origin: Vec,
angles: Angle,
orientation: DetailPropOrientation,
leaf: int,
lighting: Tuple[int, int, int, int],
light_styles: Tuple[int, int],
sway_amount: int,
sprite_scale: float,
dims_upper_left: Tuple[float, float],
dims_lower_right: Tuple[float, float],
texcoord_upper_left: Tuple[float, float],
texcoord_lower_right: Tuple[float, float],
)

A sprite-type detail prop.

sprite_scale: float
dims_upper_left: Tuple[float, float]
dims_lower_right: Tuple[float, float]
texcoord_upper_left: Tuple[float, float]
texcoord_lower_right: Tuple[float, float]
class srctools.bsp.TexData(
mat: str,
reflectivity: Vec,
width: int,
height: int,
)

Represents some additional infomation for textures.

Usually does not need to be constructed directly. Use BSP.create_texinfo() or TexInfo.set() to create this along with the texinfo.

mat: str
reflectivity: Vec
width: int
height: int
classmethod from_material(
fsys: FileSystem,
mat_name: str,
) TexData

Given a filesystem, parse the specified material and compute the texture values.

class srctools.bsp.TexInfo(
s_off: Vec,
s_shift: float,
t_off: Vec,
t_shift: float,
lightmap_s_off: Vec,
lightmap_s_shift: float,
lightmap_t_off: Vec,
lightmap_t_shift: float,
flags: SurfFlags,
info: TexData,
)

Represents texture positioning / scaling info.

Overlays don’t use the offset/shifts, setting them to (0, 0, 0) and -99999.0 respectively.

s_off: Vec
s_shift: float
t_off: Vec
t_shift: float
lightmap_s_off: Vec
lightmap_s_shift: float
lightmap_t_off: Vec
lightmap_t_shift: float
flags: SurfFlags
property mat: str

The material used for this texinfo.

property reflectivity: Vec

The reflectivity of the texture.

property tex_size: Tuple[int, int]

The size of the texture.

set(
bsp: BSP,
mat: str,
*,
fsys: FileSystem,
) None
set(
bsp: BSP,
mat: str,
reflectivity: Vec,
width: int,
height: int,
) None

Set the material used for this texinfo.

If it is not already used in the BSP, some additional info is required. This can either be parsed from the VMT and VTF, or provided directly.

class srctools.bsp.Cubemap(origin: Vec, size: int = 0)

A env_cubemap positioned in the map.

The position is integral, and the size can be zero for the default or a positive number for different powers of 2.

origin: Vec
size: int
property resolution: int

Return the actual image size.

class srctools.bsp.Overlay(
id: int,
origin: Vec,
normal: Vec,
texture: TexInfo,
face_count: int,
faces: List[int] = NOTHING,
render_order: int = 0,
u_min: float = 0.0,
u_max: float = 1.0,
v_min: float = 0.0,
v_max: float = 1.0,
uv1: Vec = NOTHING,
uv2: Vec = NOTHING,
uv3: Vec = NOTHING,
uv4: Vec = NOTHING,
fade_min_sq: float = -1.0,
fade_max_sq: float = 0.0,
min_cpu: int = 0,
max_cpu: int = 0,
min_gpu: int = 0,
max_gpu: int = 0,
)

An overlay embedded in the map.

id: int
origin: Vec
normal: Vec
texture: TexInfo
face_count: int
faces: List[int]
render_order: int
u_min: float
u_max: float
v_min: float
v_max: float
uv1: Vec
uv2: Vec
uv3: Vec
uv4: Vec
fade_min_sq: float
fade_max_sq: float
min_cpu: int
max_cpu: int
min_gpu: int
max_gpu: int
class srctools.bsp.VisTree(
plane: Plane,
mins: Vec,
maxes: Vec,
faces: List[Face],
area_ind: int,
child_neg: VisTree | VisLeaf = None,
child_pos: VisTree | VisLeaf = None,
)

A tree node in the visleaf/BSP data.

Each of these is a plane splitting the map in two, which then has a child tree or visleaf on either side.

plane: Plane
mins: Vec
maxes: Vec
faces: List[Face]
area_ind: int
child_neg: VisTree | VisLeaf
child_pos: VisTree | VisLeaf
property plane_norm: Vec

Deprecated alias for tree.plane.normal.

property plane_dist: float

Deprecated alias for tree.plane.dist.

test_point(
point: Vec,
) VisLeaf | None

Test the given point against us, returning the hit leaf or None.

iter_leafs() Iterator[VisLeaf]

Iterate over all child leafs, recursively.

class srctools.bsp.VisLeaf(
contents: BSPContents,
cluster_id: int,
area: int,
flags: VisLeafFlags,
mins: Vec,
maxes: Vec,
faces: List[Face],
brushes: List[Brush],
water_id: int,
ambient: bytes = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
min_water_dist: int = 65535,
)

A leaf in the visleaf/BSP data.

The bounds are defined implicitly by the parent node planes.

contents: BSPContents
cluster_id: int
area: int
flags: VisLeafFlags
mins: Vec
maxes: Vec
faces: List[Face]
brushes: List[Brush]
water_id: int
min_water_dist: int
test_point(
point: Vec,
) VisLeaf | None

Test the given point against us, returning ourselves or None.

class srctools.bsp.VisLeafFlags(
value,
names=None,
*,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)

Bases: Flag

Visleaf flags.

NONE = 0
SKY_3D = 1
SKY_2D = 4
RADIAL = 2
HAS_DETAIL_OBJECTS = 8

Alias: _BIT_4

_BIT_5 = 16
_BIT_6 = 32
_BIT_7 = 64
class srctools.bsp.LeafWaterInfo(
surface_z: float,
min_z: float,
surface_texinfo: TexInfo,
)

Additional data about water volumes.

surface_z: float
min_z: float
surface_texinfo: TexInfo
class srctools.bsp.Visibility(
potentially_visible: List[bytearray],
potentially_audible: List[bytearray],
)

The visibility data produced by VVIS.

Visleafs each have a “cluster” ID. For every pair of cluster IDs, this indicates if the first can see the second, and whether they can hear each other.

potentially_visible: List[bytearray]
potentially_audible: List[bytearray]
class srctools.bsp.BModel(
mins: Vec,
maxes: Vec,
origin: Vec,
node: VisTree,
faces: List[Face],
phys_keyvalues: Keyvalues | None = None,
phys_solids: List[bytes] = NOTHING,
)

A brush model definition, used for the world entity along with all other brush ents.

mins: Vec
maxes: Vec
origin: Vec
node: VisTree
faces: List[Face]
phys_keyvalues: Keyvalues | None
clear_physics() None

Delete the physics data for this brush model, and set the visleafs to non-solid.

This is useful to optimise if the entity is known to not be solid to physics objects.

class srctools.bsp.Plane(
normal: Vec,
dist,
type: PlaneType = NOTHING,
)

A plane.

normal: Vec
dist: float
type: PlaneType
class srctools.bsp.PlaneType(
value,
names=None,
*,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)

Bases: Enum

The orientation of a plane.

X = 0
Y = 1
Z = 2
ANY_X = 3
ANY_Y = 4
ANY_Z = 5
from_normal = <bound method PlaneType.from_normal of <enum 'PlaneType'>>
class srctools.bsp.Primitive(
is_tristrip: bool,
indexed_verts: List[int],
verts: List[Vec],
)

A ‘primitive’ surface (AKA t-junction, waterverts).

These are generated to stitch together T-junction faces.

is_tristrip: bool
indexed_verts: List[int]
verts: List[Vec]
class srctools.bsp.Face(
plane: Plane,
same_dir_as_plane: bool,
on_node: bool,
edges: List[Edge],
texinfo: TexInfo | None,
dispinfo_ind: int,
surf_fog_volume_id: int,
light_styles: bytes,
lightmap_off: int,
area: float,
lightmap_mins: Tuple[int, int],
lightmap_size: Tuple[int, int],
orig_face: Face | None,
primitives: List[Primitive],
dynamic_shadows: bool,
smoothing_groups: int,
hammer_id: int | None,
vitamin_flags: int,
)

A brush face definition.

plane: Plane
same_dir_as_plane: bool
on_node: bool
edges: List[Edge]
texinfo: TexInfo | None
surf_fog_volume_id: int
light_styles: bytes
area: float
lightmap_mins: Tuple[int, int]
lightmap_size: Tuple[int, int]
orig_face: Face | None
primitives: List[Primitive]
dynamic_shadows: bool
smoothing_groups: int
hammer_id: int | None

The original ID of the Hammer face.

vitamin_flags: int

VitaminSource-specific flags.

class srctools.bsp.Edge(a: Vec, b: Vec)

A pair of vertexes defining an edge of a face.

The face on the other side of the edge has a RevEdge instead, which shares these vectors.

opposite: Edge
property a: Vec
property b: Vec
key() Tuple[object, ...]

A key to match the edge with.

class srctools.bsp.RevEdge(ed: Edge)

The edge on the opposite side from the original.

This is implicitly created when an Edge is.

property a: Vec

This is a proxy for our opposite’s B vec.

property b: Vec

This is a proxy for our opposite’s A vec.

class srctools.bsp.Brush(
contents: BSPContents,
sides: List[BrushSide],
)

A brush definition.

contents: BSPContents
sides: List[BrushSide]
class srctools.bsp.BrushSide(
plane: Plane,
texinfo: TexInfo,
dispinfo: int,
is_bevel_plane: bool,
unknown_bevel_bits: int = 0,
)

A side of the original brush geometry which the map is constructed from.

This matches the original VMF.

plane: Plane
texinfo: TexInfo
is_bevel_plane: bool
srctools.bsp.BrushContents

alias of BSPContents