rtx: add mass-patching, fix #275

This commit is contained in:
Ivan Avdeev 2021-12-11 12:40:57 -08:00
parent 803889e54f
commit b0e3ebfc32
2 changed files with 98 additions and 59 deletions

View File

@ -6,6 +6,7 @@
#include "eiface.h" // ARRAYSIZE #include "eiface.h" // ARRAYSIZE
#include "xash3d_mathlib.h" #include "xash3d_mathlib.h"
#include <string.h> #include <string.h>
#include <ctype.h>
xvk_map_entities_t g_map_entities; xvk_map_entities_t g_map_entities;
@ -52,10 +53,35 @@ static unsigned parseEntPropInt(const char* value, int *out, unsigned bit) {
return (1 == sscanf(value, "%d", out)) ? bit : 0; return (1 == sscanf(value, "%d", out)) ? bit : 0;
} }
static unsigned parseEntPropIntArray(const char* value, int_array_t *out, unsigned bit) {
unsigned retval = 0;
out->num = 0;
while (*value) {
int i = 0;
if (0 == sscanf(value, "%d", &i))
break;
if (out->num == MAX_INT_ARRAY_SIZE)
break;
retval |= bit;
out->values[out->num++] = i;
while (*value && isdigit(*value)) ++value;
while (*value && isspace(*value)) ++value;
}
if (*value) {
gEngine.Con_Printf(S_ERROR "Error parsing mapents patch IntArray (wrong format? too many entries (max=%d)), portion not parsed: %s\n", MAX_INT_ARRAY_SIZE, value);
}
return retval;
}
static unsigned parseEntPropString(const char* value, string *out, unsigned bit) { static unsigned parseEntPropString(const char* value, string *out, unsigned bit) {
const int len = Q_strlen(value); const int len = Q_strlen(value);
if (len >= sizeof(string)) if (len >= sizeof(string))
gEngine.Con_Printf(S_ERROR, "Map entity value '%s' is too long, max length is %d\n", gEngine.Con_Printf(S_ERROR "Map entity value '%s' is too long, max length is %d\n",
value, sizeof(string)); value, sizeof(string));
Q_strncpy(*out, value, sizeof(*out)); Q_strncpy(*out, value, sizeof(*out));
return bit; return bit;
@ -285,9 +311,12 @@ static void readWorldspawn( const entity_props_t *props ) {
static void addPatchSurface( const entity_props_t *props, uint32_t have_fields ) { static void addPatchSurface( const entity_props_t *props, uint32_t have_fields ) {
const model_t* const map = gEngine.pfnGetModelByIndex( 1 ); const model_t* const map = gEngine.pfnGetModelByIndex( 1 );
const int num_surfaces = map->numsurfaces; const int num_surfaces = map->numsurfaces;
for (int i = 0; i < props->_xvk_surface_id.num; ++i) {
const int index = props->_xvk_surface_id.values[i];
xvk_patch_surface_t *psurf = NULL; xvk_patch_surface_t *psurf = NULL;
if (props->_xvk_surface_id < 0 || props->_xvk_surface_id >= num_surfaces) { if (index < 0 || index >= num_surfaces) {
gEngine.Con_Printf(S_ERROR "Incorrect patch for surface_index %d where numsurfaces=%d\n", props->_xvk_surface_id, num_surfaces); gEngine.Con_Printf(S_ERROR "Incorrect patch for surface_index %d where numsurfaces=%d\n", index, num_surfaces);
return; return;
} }
@ -300,16 +329,16 @@ static void addPatchSurface( const entity_props_t *props, uint32_t have_fields )
} }
} }
psurf = g_map_entities.patch.surfaces + props->_xvk_surface_id; psurf = g_map_entities.patch.surfaces + index;
if (have_fields & Field__xvk_texture) { if (have_fields & Field__xvk_texture) {
if (props->_xvk_texture[0] == '\0') { if (props->_xvk_texture[0] == '\0') {
gEngine.Con_Reportf("Patch: surface %d removed\n", props->_xvk_surface_id); gEngine.Con_Reportf("Patch: surface %d removed\n", index);
psurf->flags = Patch_Surface_Delete; psurf->flags = Patch_Surface_Delete;
return; return;
} else { } else {
const int tex_id = VK_FindTexture( props->_xvk_texture ); const int tex_id = VK_FindTexture( props->_xvk_texture );
gEngine.Con_Reportf("Patch for surface %d with texture \"%s\" -> %d\n", props->_xvk_surface_id, props->_xvk_texture, tex_id); gEngine.Con_Reportf("Patch for surface %d with texture \"%s\" -> %d\n", index, props->_xvk_texture, tex_id);
psurf->tex_id = tex_id; psurf->tex_id = tex_id;
// Find texture_t for this index // Find texture_t for this index
@ -328,13 +357,14 @@ static void addPatchSurface( const entity_props_t *props, uint32_t have_fields )
if (have_fields & Field__light) { if (have_fields & Field__light) {
VectorCopy(props->_light, psurf->emissive); VectorCopy(props->_light, psurf->emissive);
psurf->flags |= Patch_Surface_Emissive; psurf->flags |= Patch_Surface_Emissive;
gEngine.Con_Reportf("Patch for surface %d: assign emissive %f %f %f\n", props->_xvk_surface_id, gEngine.Con_Reportf("Patch for surface %d: assign emissive %f %f %f\n", index,
psurf->emissive[0], psurf->emissive[0],
psurf->emissive[1], psurf->emissive[1],
psurf->emissive[2] psurf->emissive[2]
); );
} }
} }
}
int findLightEntityWithIndex( int index ) { int findLightEntityWithIndex( int index ) {
// TODO could do binary search (entities are sorted by index) but why // TODO could do binary search (entities are sorted by index) but why
@ -347,7 +377,8 @@ int findLightEntityWithIndex( int index ) {
} }
static void addPatchEntity( const entity_props_t *props, uint32_t have_fields ) { static void addPatchEntity( const entity_props_t *props, uint32_t have_fields ) {
const int light_index = findLightEntityWithIndex( props->_xvk_ent_id ); for (int i = 0; i < props->_xvk_ent_id.num; ++i) {
const int light_index = findLightEntityWithIndex( props->_xvk_ent_id.values[i] );
if (light_index < 0) { if (light_index < 0) {
gEngine.Con_Printf(S_ERROR "Patch light entity with index=%d not found\n", props->_xvk_ent_id); gEngine.Con_Printf(S_ERROR "Patch light entity with index=%d not found\n", props->_xvk_ent_id);
return; return;
@ -360,7 +391,8 @@ static void addPatchEntity( const entity_props_t *props, uint32_t have_fields )
return; return;
} }
fillLightFromProps(g_map_entities.lights + light_index, props, have_fields, true, props->_xvk_ent_id); fillLightFromProps(g_map_entities.lights + light_index, props, have_fields, true, props->_xvk_ent_id.values[i]);
}
} }
static void parseEntities( char *string, int *count ) { static void parseEntities( char *string, int *count ) {

View File

@ -15,9 +15,9 @@
X(10, string, targetname, String) \ X(10, string, targetname, String) \
X(11, string, target, String) \ X(11, string, target, String) \
X(12, int, style, Int) \ X(12, int, style, Int) \
X(13, int, _xvk_surface_id, Int) \ X(13, int_array_t, _xvk_surface_id, IntArray) \
X(14, string, _xvk_texture, String) \ X(14, string, _xvk_texture, String) \
X(15, int, _xvk_ent_id, Int) \ X(15, int_array_t, _xvk_ent_id, IntArray) \
X(16, float, _xvk_radius, Float) \ X(16, float, _xvk_radius, Float) \
typedef enum { typedef enum {
@ -29,6 +29,13 @@ typedef enum {
Ignored, Ignored,
} class_name_e; } class_name_e;
#define MAX_INT_ARRAY_SIZE 64
typedef struct {
int num;
int values[MAX_INT_ARRAY_SIZE];
} int_array_t;
typedef struct { typedef struct {
#define DECLARE_FIELD(num, type, name, kind) type name; #define DECLARE_FIELD(num, type, name, kind) type name;
ENT_PROP_LIST(DECLARE_FIELD) ENT_PROP_LIST(DECLARE_FIELD)