srctools.vmf
Reads and writes VMF map files, providing various tools to make it easier to modify.
Core Functionality
- class srctools.vmf.VMF(
- map_info: Mapping[str, str] = ...,
- preserve_ids: bool = False,
- *,
- format_version: int | None = None,
- hammer_version: int | None = None,
- hammer_build: int | None = None,
- is_prefab: bool | None = None,
- cordon_enabled: bool | None = None,
- map_version: int | None = None,
- show_grid: bool | None = None,
- show_3d_grid: bool | None = None,
- snap_grid: bool | None = None,
- show_logic_grid: bool | None = None,
- grid_spacing: int | None = None,
- active_cam: int | None = None,
- quickhide_count: int | None = None,
- strata_inst_visibility: StrataInstanceVisibility | None = None,
Represents a VMF file, and holds counters for various IDs used.
Has functions for searching for specific entities or brushes, and converts to/from a property_parser tree.
The dictionaries by_target and by_class allow quickly getting a set of entities with the given class or targetname.
- export( ) str
- export(
- dest_file: FileWText,
- *,
- inc_version: bool = True,
- minimal: bool = False,
- disp_multiblend: bool = True,
Serialises the object’s contents into a VMF file.
If no file is given the map will be returned as a string.
By default, this will increment the map’s version - disable inc_version to suppress this.
If minimal is True, several blocks will be skipped (Viewsettings, cameras, cordons and visgroups)
disp_multiblend controls whether displacements produce their multiblend data (added in ASW), or if it is stripped.
named_cordons controls if multiple cordons may be used (post L4D), or if only a single cordon is allowed.
Common behaviours
Automatic conversion
VMFs store string values in several locations, which are commonly treated as other data types, parsed as necessary. To make this easier to deal with, several data types are automatically converted when passed to relevant functions.
- type srctools.vmf.ValidKVs
Parameters with this type automatically convert values to a string.
- srctools.vmf.conv_kv(val: ValidKVs) str
Convert a type into a string matching Valve’s syntax.
The following types are allowed:
Locations with automatic conversion include entity values, instance fixups, and output parameters.
ID management
The VMF class records IDs used by brushes, faces, entities, groups, visgroups and AI nodes. When creating new objects, they will automatically get assigned a new ID. IDs are ‘owned’ while the relevant object is alive - removing them from the VMF will still keep it reserved.
- class srctools.vmf.IDMan
This class keeps track of IDs for a particular object type. It has no public constructor.
- with VMF.allow_duplicate_ids(self)
While inside this context manager, allow all IDs to have duplicates.
IDs are still tracked, so future IDs will not overlap these.
Brushes
- class srctools.vmf.Solid(
- map: VMF,
- id: int = -1,
- sides: list[Side] = NOTHING,
- visgroup_ids=(),
- hidden: bool = False,
- group_id: int | None = None,
- vis_shown: bool = True,
- vis_auto_shown: bool = True,
- is_cordon: bool = False,
- editor_color: Vec = NOTHING,
A single brush, serving as both world brushes and brush entities.
- editor_color: Vec
The RGB colour this brush appears as in 2D views. Randomly assigned when the brush is created, but then set to the colour of the tied entity or visgroup.
If set, this brush has been hidden in some way (quick hide, cordons, visgroups). It will not be compiled into the final map.
- is_cordon: bool
If set, this brush has been generated by Hammer to seal cordoned areas. These are deleted when loading the map by Hammer and recreated on save.
- export( ) None
Generate the strings needed to define this brush.
disp_multiblend controls whether displacements produce their multiblend data (added in ASW), or if it is stripped.
include_groups specifies if visgroup/group values are included. This is not allowed inside brush entities.
- copy(
- des_id: int = -1,
- vmf_file: VMF | None = None,
- side_mapping: MutableMapping[int, int] = ...,
- keep_vis: bool = True,
Duplicate this brush.
- translate(diff: VecBase | Vec_tuple | tuple[float, float, float]) None
Move this solid by the specified vector.
- class srctools.vmf.Side(
- vmf_file: VMF,
- planes: list[Vec],
- des_id: int = -1,
- lightmap: int = 16,
- smoothing: int = 0,
- mat: str = 'tools/toolsnodraw',
- rotation: float = 0,
- uaxis: UVAxis | None = None,
- vaxis: UVAxis | None = None,
- disp_power: Literal[0, 1, 2, 3, 4] = 0,
A brush face.
- property scale
When set, modifies both the U and V axes.
- property offset
When set, modifies both the U and V axes.
- export( ) None
Generate the strings required to define this side in a VMF.
disp_multiblend controls whether displacements produce their multiblend data (added in CSGO), or if it is skipped.
- classmethod from_plane(
- vmf: VMF,
- position: VecBase | Vec_tuple | tuple[float, float, float],
- normal: VecBase | Vec_tuple | tuple[float, float, float],
- material: str = 'tools/toolsnodraw',
Generate a new brush face, aligned to the specified plane.
The normal vector points out of the face. This calculates a valid texture alignment, but does not specify an exact result.
- copy( ) Side
Duplicate this brush side.
des_id is the id which is desired for the new side. map is the VMF to add the new side to (defaults to the same map). If passed, side_mapping will be updated with an old -> new ID pair.
- translate(diff: VecBase | Vec_tuple | tuple[float, float, float]) None
Move this side by the specified vector.
A tuple can be passed in instead if desired.
- class srctools.vmf.UVAxis(x: float, y: float, z: float, offset: float = 0.0, scale: float = 0.25)
Values saved into Side.uaxis and Side.vaxis.
These define the alignment of textures on a face.
- rotate(
- angles: Angle | FrozenAngle | Matrix | FrozenMatrix,
Rotate the axis by some orientation.
This doesn’t alter texture offsets.
Creation
- VMF.make_prism( ) PrismFace
Create an axis-aligned brush connecting the two points.
A PrismFaces tuple will be returned which contains the six faces, as well as the solid. All faces will be textured with ‘mat’. If set_points is defined, explicit vertex info will be included.
- VMF.make_hollow(
- p1: Vec | FrozenVec,
- p2: Vec | FrozenVec,
- thick: float = 16,
- mat: str = 'tools/toolsnodraw',
- inner_mat: str = '',
Create 6 brushes to surround the given region.
If inner_mat is not specified, it’s set to mat.
- class srctools.vmf.PrismFace( )
Return value for
VMF.make_prism()andVMF.make_hollow().This can be indexed with an axis-aligned
Vecor 3-tuple normal to fetch a side.
Displacements
Brush faces converted to displacements add a number of additional properties to the face.
- Side.disp_power: Literal[0, 1, 2, 3, 4]
The number of subdivisions for a displacement, ranging from 0-4. If zero, the brush is not a displacement and the other values are ignored.
- Side.disp_size
Return the number of vertexes in each direction of a displacement.
- Side.disp_get_tri_verts( ) tuple[DispVertex, DispVertex, DispVertex, DispVertex, DispVertex, DispVertex]
Return the locations of the triangle vertexes.
This is a set of 6 verts, representing the two triangles in order. See 2013 SDK src/public/builddisp.cpp:896-965.
- class srctools.vmf.Vec4(x: float = 0.0, y: float = 0.0, z: float = 0.0, w: float = 0.0)
Defines a 4-dimensional vector.
- class srctools.vmf.DispFlag
Bases:
FlagPer-displacement flags, configuring collisions.
Does NOT match the file values, since those are inverted.
- COLL_NONE = 0
- COLL_PHYSICS = 1
- COLL_PLAYER_NPC = 2
- COLL_BULLET = 4
- COLL_ALL = 7
- SUBDIV = 8
- SUBDIV_COLL_ALL = 15
- class srctools.vmf.TriangleTag
Bases:
FlagTwo flags set on all displacement triangles.
If walkable, it is shallow enough to stand on. If buildable, TF2 Engineers can place buildings.
- STEEP = 0
- WALKABLE = 1
- BUILDABLE = 9
Alias:
FLAT
- class srctools.vmf.DispVertex(
- x: int,
- y: int,
- normal: ~srctools.math.Vec = NOTHING,
- distance: float = 0,
- offset: ~srctools.math.Vec = NOTHING,
- offset_norm: ~srctools.math.Vec = NOTHING,
- alpha: float = 0.0,
- triangle_a: ~srctools.vmf.TriangleTag = <TriangleTag.BUILDABLE: 9>,
- triangle_b: ~srctools.vmf.TriangleTag = <TriangleTag.BUILDABLE: 9>,
- multi_blend: ~srctools.vmf.Vec4 = Vec4(x=0.0,
- y=0.0,
- z=0.0,
- w=0.0),
- multi_alpha: ~srctools.vmf.Vec4 = Vec4(x=0.0,
- y=0.0,
- z=0.0,
- w=0.0),
- multi_colors: list[~srctools.math.Vec] | None = None,
A vertex in dislacements.
- triangle_a: TriangleTag
- triangle_b: TriangleTag
Entities
- VMF.spawn: Entity
The
worldspawnentity represents the world and stores all world brushes. This will always exist. It is also present in theentitieslist.
- VMF.add_ent(item: Entity) None
Add an entity to the map.
The entity should have been created with this VMF as a parent.
- VMF.remove_ent(item: Entity) None
Remove an entity from the map.
After this is called, the entity will no longer be exported. The object still exists, so it can be reused.
- VMF.create_ent(classname: str, **kargs: ValidKVs) Entity
Convenience method to allow creating point entities.
This constructs an entity, adds it to the map, and then returns it. A classname must be passed!
- class srctools.vmf.Entity(
- vmf_file: VMF,
- keys: Mapping[str, ValidKVs] = ...,
- fixup: Iterable[FixupValue] = (),
- ent_id: int = -1,
- outputs: Iterable[Output] = (),
- solids: Iterable[Solid] = (),
- hidden: bool = False,
- groups: Iterable[int] = (),
- vis_ids: Iterable[int] = (),
- vis_shown: bool = True,
- vis_auto_shown: bool = True,
- logical_pos: str | None = None,
- editor_color: Vec | tuple[int, int, int] = (255, 255, 255),
- comments: str = '',
A representation of either a point or brush entity.
Creation:
Entity(args)for a brand-new EntityEntity.parse(keyvalues)if reading from a VMF fileent.copy()to duplicate an existing entity.vmf.create_ent()to create an entity, then add it to the VMF file.
Supports
ent[key]operations to read and write keyvalues. To read instance$replacevalues operate onentity.fixup[var].- staticmethod parse( ) Entity
Parse a property tree into an Entity object.
_worldspawn indicates if this is the worldspawn entity, which additionally contains the entity group definitions.
- export( ) None
Generate the strings needed to create this entity.
disp_multiblend controls whether displacements produce their multiblend data (added in ASW), or if it is skipped.
_is_worldspawn is used interally to generate the special worldspawn block.
- copy(
- des_id: int = -1,
- vmf_file: VMF | None = None,
- side_mapping: MutableMapping[int, int] = ...,
- keep_vis: bool = True,
Duplicate this entity entirely, including solids and outputs.
- make_unique(unnamed_prefix: str = '') Entity
Ensure this entity is uniquely named, by adding a numeric suffix.
If the entity doesn’t start with a name, it will use the parameter.
Outputs
- for output in VMF.iter_inputs(name: str) Iterator[Output]
Loop through all
Outputswhich target the named entity.*can be used at the beginning or end of the name for a wildcard search.
- class srctools.vmf.Output(
- out: str,
- targ: Entity | str,
- inp: str,
- param: ValidKVs = '',
- delay: float = 0.0,
- *,
- times: int = -1,
- only_once: bool = False,
- inst_out: str | None = None,
- inst_in: str | None = None,
- comma_sep: bool = False,
An output from one entity pointing to another.
When parsing, either the post-L4D
0x1Bcharacter can be used, or the previous,delimiters can be used. For commas, extraneous ones will be treated as part of the parameters.- times: int
The number of times to fire before being deleted.
-1means forever, Hammer only uses-1and1.
- property only_once: bool
Instead of setting
times, this provides an interface like how Hammer does.
- inst_in: str | None
The local entity we are really triggering in instance inputs (
instance:name;Input)
- export(buffer: FileWText, ind: str = '') None
Generate the text required to define this output in the VMF.
- as_keyvalue() str
Generate the text form of the output.
This backslash-escapes characters where necessary.
- classmethod combine( ) Output
Combine two outputs into a merged form.
This is suitable for combining a
TriggerandOnTriggerpair into one, or similar values.
- staticmethod parse_name(name: str) tuple[str | None, str]
Extract the instance name from values of the form:
instance:local_name;Command
This then returns a
local_name, commandtuple. If not of this form, the first value will beNone.- Raises:
ValueError – If the command part is missing. This will crash VBSP if it tries to parse.
- srctools.vmf.SEP
Instances
func_instance entities can have fixup variables defined on them, which are stored in a number
of replace01 keys. To avoid having to deal with the details, these are automatically parsed
and stored under a fixup attribute.
- Entity.fixup
Access
$replacevariables on instances.
- class srctools.vmf.EntityFixup(
- fixup: Iterable[FixupValue] | EntityFixup = (),
A specialised mapping which keeps track of the variable indexes.
This treats variable names case-insensitively, and optionally allows writing variables with
$signs in front. The case of the first assigned name for each key is preserved.Additionally, lookups never fail - returning
""instead. Pass in a non-string default or useinto distinguish.- get(var: str) str
- get(var: str, default: str | T) str | T
Get the value of an instance
$replacevariable.If not found, the default will be returned (an empty string).
- setdefault(var: str, /, default: str = '') str
- setdefault( ) str | ValidKV_T
Return
$key, but if not present set it to the default and return that.
- values() ValuesView[str]
Provides a view over all variable values.
- substitute( ) str
Substitute the fixup variables into the provided string.
Variables are found based on the defined values, so constructions such as
val$varvalare valid (with no delimiter indicating the end of variables). Longer matches are preferred. If a match is not found, the charactersa-z,0-9and_are detected as variables, and substituted with a default.- Parameters:
text – The source text to substitue into.
default – If set, unrecognised fixups are set to this value. If not,
KeyErroris raised.allow_invert – If enabled, a variable can additionally be specified like :var`!$var` to cause it to be inverted when substituted. Valid booleans are the same as those parsed by
srctools.conv_bool.
- int(key: str, def_: int | T = 0) int | T
Return the value of an integer key.
Equivalent to
int(fixup[key]), but with a default value if missing or invalid.
- float( ) float | T
Return the value of an integer key.
Equivalent to
float(fixup[key]), but with a default value if missing or invalid.
- type srctools.vmf.FixupValue
Opaque value storing a key/value pair plus the index. Can be passed to fixups to attempt to preserve the index.
Finding Entities
Several features are provided to help locate entities in a similar way to the game.
- for entity in VMF.search(name: str) Iterator[Entity]
Yield all entities that fit this search string.
This can be the exact targetname, end-* matching, or the exact classname.
Entities added or renamed after iteration begins will not be detected. Unnamed entities will never be detected. If the name is blank, this therefore finds nothing.
Cordons
- class srctools.vmf.Cordon( )
Represents one cordon volume.
Strata Source Extensions
Strata Source adds a few additional values to preserve vertices and store settings.
- VMF.strata_viewports: list[Strata2DViewport | Strata3DViewport] | None
Records the current state of all 2D and 3D viewports. If
None, no value is saved in the file.
- class srctools.vmf.Strata2DViewport(axis: Literal['x', 'y', 'z'], u: float, v: float, zoom: float)
Represents the position of a 2D viewport in Strata Source.
In the file this is specified as a single vector, with the planar axis set to ±65536.
- classmethod from_vector( ) Strata2DViewport
Determine the appropriate axis from the position vector.
- class srctools.vmf.Strata3DViewport(position: Vec, angle: Angle)
Represents the position of a 3D viewport in Strata Source.
Changing roll does work, but should be avoided since Hammer doesn’t allow control of that axis.
- VMF.strata_instance_vis: StrataInstanceVisibility | None
Records the last state of the instance viewing mode. If
None, no value is saved in the file.