+
+vmf_map *vmf_init( const char *path )
+{
+ vmf_map *map = csr_calloc( sizeof( vmf_map ) );
+ map->root = vdf_open_file( path );
+
+ if( !map->root )
+ {
+ free( map );
+ return NULL;
+ }
+
+ vdf_kv_append( map->root, "csr_path", path );
+
+ // Prepare instances
+ vmf_load_all_instances( map, map->root );
+
+ // Other resources
+ vmf_index_models( map );
+ return map;
+}
+
+void vmf_free( vmf_map *map )
+{
+ for( int i = 0; i < csr_sb_count( map->cache ); i ++ )
+ {
+ if( map->cache[i].root )
+ vdf_free_r( map->cache[i].root );
+
+ free( map->cache[i].name );
+ }
+
+ for( int i = 1; i < csr_sb_count( map->models ); i ++ )
+ {
+ free( map->models[i].str );
+ mdl_free( &map->models[i].mdl );
+ }
+
+ vdf_free_r( map->root );
+ csr_sb_free( map->models );
+ csr_sb_free( map->cache );
+ free( map );
+}
+
+void vmf_entity_transform( vdf_node *ent, m4x3f mat )
+{
+ v3f angles = {0.f,0.f,0.f};
+ v3f offset = {0.f,0.f,0.f};
+ float scale;
+
+ // Parse
+ scale = kv_get_float( ent, "uniformscale", 1.f );
+ kv_float_array( ent, "angles", 3, angles );
+ kv_float_array( ent, "origin", 3, offset );
+
+ // Translation
+ m4x3_translate( mat, offset );
+
+ // Make rotation ( Pitch yaw roll // YZX. Source->OpenGL ordering a lil messed up )
+ m4x3_rotate_z( mat, csr_rad( angles[1] ) );
+ m4x3_rotate_y( mat, csr_rad( angles[0] ) );
+ m4x3_rotate_x( mat, csr_rad( angles[2] ) );
+
+ // Scale
+ m4x3_scale( mat, scale );
+}
+
+int vmf_visgroup_id( vdf_node *root, const char *name )
+{
+ vdf_node *dict = vdf_next( root, "visgroups", NULL );
+
+ if( dict )
+ {
+ vdf_foreach( dict, "visgroup", group )
+ {
+ if( !strcmp( kv_get( group, "name", "" ), name ) )
+ {
+ return kv_get_int( group, "visgroupid", 0 );
+ }
+ }
+ }
+
+ return -1;
+}
+
+int vmf_visgroup_match( vdf_node *ent, u32 target )
+{
+ vdf_node *editor = vdf_next( ent, "editor", NULL );
+
+ if( editor )
+ {
+ kv_foreach( editor, "visgroupid", groupe )
+ {
+ if( target == atoi( groupe ) )
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#endif