|
@@ -10,137 +10,108 @@ typedef struct {
|
|
|
Stack *temp;
|
|
|
StringView shader;
|
|
|
struct Material *mat;
|
|
|
- StringView key;
|
|
|
+ int depth;
|
|
|
} MaterialContext;
|
|
|
|
|
|
-#if 0
|
|
|
-static const char * const ignore_params[] = {
|
|
|
- "$surfaceprop", "$surfaceprop2", "$tooltexture",
|
|
|
- "%tooltexture", "%keywords", "%compilewater", "%detailtype",
|
|
|
- "%compilenolight", "%compilepassbullets",
|
|
|
- "replace", /* TODO implement */
|
|
|
- 0
|
|
|
-};
|
|
|
-#endif
|
|
|
-
|
|
|
-#if 0
|
|
|
-static ParserCallbackResult materialReadShader(ParserState *state, StringView s);
|
|
|
-static ParserCallbackResult materialReadKeyOrSection(ParserState *state, StringView s);
|
|
|
-static ParserCallbackResult materialReadValue(ParserState *state, StringView s);
|
|
|
-static ParserCallbackResult materialEnd(ParserState *state, StringView s);
|
|
|
-
|
|
|
-static ParserCallbackResult materialOpenShader(ParserState *state, StringView s) {
|
|
|
- MaterialContext *ctx = state->user_data;
|
|
|
- ctx->shader = s;
|
|
|
+static VMFAction materialReadKeyValue(MaterialContext *ctx, const VMFKeyValue *kv) {
|
|
|
+ if (kv->value.length > 127)
|
|
|
+ return VMFAction_SemanticError;
|
|
|
|
|
|
- state->callbacks.string = materialReadKeyOrSection;
|
|
|
- state->callbacks.curlyOpen = parserError;
|
|
|
+ char value[128];
|
|
|
+ memcpy(value, kv->value.str, kv->value.length);
|
|
|
+ value[kv->value.length] = '\0';
|
|
|
|
|
|
- return Parser_Continue;
|
|
|
+ if (strncasecmp("$basetexture", kv->key.str, kv->key.length) == 0) {
|
|
|
+ ctx->mat->base_texture[0] = textureGet(value, ctx->collection, ctx->temp);
|
|
|
+ } else if (strncasecmp("include", kv->key.str, kv->key.length) == 0) {
|
|
|
+ char *vmt = strstr(value, ".vmt");
|
|
|
+ if (vmt)
|
|
|
+ *vmt = '\0';
|
|
|
+ if (strstr(value, "materials/") == value)
|
|
|
+ *ctx->mat = *materialGet(value + 10, ctx->collection, ctx->temp);
|
|
|
+ }
|
|
|
+
|
|
|
+ return VMFAction_Continue;
|
|
|
}
|
|
|
|
|
|
-static ParserCallbackResult materialReadShader(ParserState *state, StringView s) {
|
|
|
- MaterialContext *ctx = state->user_data;
|
|
|
- ctx->shader = s;
|
|
|
+static VMFAction materialParserCallback(VMFState *state, VMFEntryType entry, const VMFKeyValue *kv);
|
|
|
+static VMFAction materialShaderCallback(VMFState *state, VMFEntryType entry, const VMFKeyValue *kv);
|
|
|
+static VMFAction materialPatchCallback(VMFState *state, VMFEntryType entry, const VMFKeyValue *kv);
|
|
|
|
|
|
- PRINTF("Material shader %.*s", PRI_SVV(ctx->shader));
|
|
|
+static VMFAction materialPatchCallback(VMFState *state, VMFEntryType entry, const VMFKeyValue *kv) {
|
|
|
+ //PRINTF("Entry %d (%.*s -> %.*s)", entry, PRI_SVV(kv->key), PRI_SVV(kv->value));
|
|
|
+ MaterialContext *ctx = state->user_data;
|
|
|
|
|
|
- state->callbacks.string = parserError;
|
|
|
- state->callbacks.curlyOpen = materialOpenShader;
|
|
|
- return Parser_Continue;
|
|
|
-}
|
|
|
+ VMFAction retval = VMFAction_SemanticError;
|
|
|
+
|
|
|
+ switch (entry) {
|
|
|
+ case VMFEntryType_KeyValue:
|
|
|
+ retval = materialReadKeyValue(ctx, kv);
|
|
|
+ break;
|
|
|
+ case VMFEntryType_SectionOpen:
|
|
|
+ ++ctx->depth;
|
|
|
+ retval = VMFAction_Continue;
|
|
|
+ break;
|
|
|
+ case VMFEntryType_SectionClose:
|
|
|
+ --ctx->depth;
|
|
|
+ retval = ctx->depth == 0 ? VMFAction_Exit : VMFAction_Continue;
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
-static ParserCallbackResult materialReadKeyOrSection(ParserState *state, StringView s) {
|
|
|
- MaterialContext *ctx = state->user_data;
|
|
|
- ctx->key = s;
|
|
|
- state->callbacks.string = materialReadValue;
|
|
|
- state->callbacks.curlyClose = state->callbacks.curlyOpen = parserError;
|
|
|
- return Parser_Continue;
|
|
|
+ return retval;
|
|
|
}
|
|
|
|
|
|
-static ParserCallbackResult materialReadValue(ParserState *state, StringView s) {
|
|
|
+static VMFAction materialShaderCallback(VMFState *state, VMFEntryType entry, const VMFKeyValue *kv) {
|
|
|
+ //PRINTF("Entry %d (%.*s -> %.*s)", entry, PRI_SVV(kv->key), PRI_SVV(kv->value));
|
|
|
MaterialContext *ctx = state->user_data;
|
|
|
|
|
|
- if (s.length > 127)
|
|
|
- return Parser_Error;
|
|
|
-
|
|
|
- char value[128];
|
|
|
- memcpy(value, s.str, s.length);
|
|
|
- value[s.length] = '\0';
|
|
|
-
|
|
|
- if (strncasecmp("$basetexture", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- ctx->mat->base_texture[0] = textureGet(value, ctx->collection, ctx->temp);
|
|
|
- } else if (strncasecmp("$basetexture2", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- ctx->mat->base_texture[1] = textureGet(value, ctx->collection, ctx->temp);
|
|
|
- } else if (strncasecmp("$basetexturetransform", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$basetexturetransform2", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$detail", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- //output->detail = textureGet(ctx.value, ctx->collection, ctx->temp);
|
|
|
- } else if (strncasecmp("$detailscale", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$detailblendfactor", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$detailblendmode", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$parallaxmap", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$parallaxmapscale", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$bumpmap", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- /* output->bump = textureGet(ctx.value, ctx->collection, ctx->temp); */
|
|
|
- } else if (strncasecmp("$envmap", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- /* output->envmap = textureGet(ctx.value, ctx->collection, ctx->temp); */
|
|
|
- } else if (strncasecmp("$fogenable", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$fogcolor", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$alphatest", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$translucent", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$envmapcontrast", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$envmapsaturation", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$envmaptint", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$normalmapalphaenvmapmask", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$envmapmask", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$nodiffusebumplighting", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$AlphaTestReference", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$basealphaenvmapmask", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$selfillum", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("$reflectivity", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- } else if (strncasecmp("include", ctx->key.str, ctx->key.length) == 0) {
|
|
|
- char *vmt = strstr(value, ".vmt");
|
|
|
- if (vmt)
|
|
|
- *vmt = '\0';
|
|
|
- if (strstr(value, "materials/") == value)
|
|
|
- *ctx->mat = *materialGet(value + 10, ctx->collection, ctx->temp);
|
|
|
- } else {
|
|
|
- PRINTF("Material shader:%.*s, unknown param %.*s = %s",
|
|
|
- ctx->shader.length, ctx->shader.str, ctx->key.length, ctx->key.str, value);
|
|
|
+ VMFAction retval = VMFAction_SemanticError;
|
|
|
+
|
|
|
+ switch (entry) {
|
|
|
+ case VMFEntryType_KeyValue:
|
|
|
+ // Ignore any nested settings for no
|
|
|
+ retval = (ctx->depth == 1) ? materialReadKeyValue(ctx, kv) : VMFAction_Continue;
|
|
|
+ break;
|
|
|
+ case VMFEntryType_SectionOpen:
|
|
|
+ ++ctx->depth;
|
|
|
+ retval = VMFAction_Continue;
|
|
|
+ break;
|
|
|
+ case VMFEntryType_SectionClose:
|
|
|
+ --ctx->depth;
|
|
|
+ retval = ctx->depth == 0 ? VMFAction_Exit : VMFAction_Continue;
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
- state->callbacks.string = materialReadKeyOrSection;
|
|
|
- state->callbacks.curlyClose = materialEnd;
|
|
|
- state->callbacks.curlyOpen = parserError;
|
|
|
- return Parser_Continue;
|
|
|
+ return retval;
|
|
|
}
|
|
|
|
|
|
-static ParserCallbackResult materialEnd(ParserState *state, StringView s) {
|
|
|
- (void)(s);
|
|
|
+static VMFAction materialParserCallback(VMFState *state, VMFEntryType entry, const VMFKeyValue *kv) {
|
|
|
+ //PRINTF("Entry %d (%.*s -> %.*s)", entry, PRI_SVV(kv->key), PRI_SVV(kv->value));
|
|
|
MaterialContext *ctx = state->user_data;
|
|
|
|
|
|
- if (!ctx->mat->base_texture[0]) {
|
|
|
- PRINTF("Material with ctx->shader %.*s doesn't have base texture", ctx->shader.length, ctx->shader.str);
|
|
|
- ctx->mat->shader = MaterialShader_LightmappedAverageColor;
|
|
|
- // HACK to notice these materials
|
|
|
- ctx->mat->average_color = aVec3f(1.f, 0.f, 1.f);
|
|
|
- } else {
|
|
|
- ctx->mat->shader = MaterialShader_LightmappedGeneric;
|
|
|
- ctx->mat->average_color = ctx->mat->base_texture[0]->avg_color;
|
|
|
+ VMFAction retval = VMFAction_SemanticError;
|
|
|
+
|
|
|
+ switch (entry) {
|
|
|
+ case VMFEntryType_KeyValue:
|
|
|
+ break;
|
|
|
+ case VMFEntryType_SectionOpen:
|
|
|
+ ++ctx->depth;
|
|
|
+ if (strncasecmp("patch", kv->key.str, kv->key.length) == 0) {
|
|
|
+ state->callback = materialPatchCallback;
|
|
|
+ } else {
|
|
|
+ ctx->shader = kv->key;
|
|
|
+ state->callback = materialShaderCallback;
|
|
|
+ }
|
|
|
+ retval = VMFAction_Continue;
|
|
|
+ break;
|
|
|
+ case VMFEntryType_SectionClose:
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
- return Parser_Exit;
|
|
|
+ return retval;
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
static int materialLoad(struct IFile *file, struct ICollection *coll, struct Material *output, struct Stack *tmp) {
|
|
|
- (void)file;
|
|
|
- (void)coll;
|
|
|
- (void)output;
|
|
|
- (void)tmp;
|
|
|
- return 0;
|
|
|
-#if 0
|
|
|
char *buffer = stackAlloc(tmp, file->size);
|
|
|
|
|
|
if (!buffer) {
|
|
@@ -148,31 +119,40 @@ static int materialLoad(struct IFile *file, struct ICollection *coll, struct Mat
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- if (file->size != file->read(file, 0, file->size, buffer)) return 0;
|
|
|
+ if (file->size != file->read(file, 0, file->size, buffer))
|
|
|
+ return 0;
|
|
|
|
|
|
MaterialContext ctx = {
|
|
|
.collection = coll,
|
|
|
.temp = tmp,
|
|
|
- .mat = output
|
|
|
+ .mat = output,
|
|
|
+ .depth = 0,
|
|
|
};
|
|
|
|
|
|
- ParserState parser = {
|
|
|
+ VMFState parser_state = {
|
|
|
.user_data = &ctx,
|
|
|
- .callbacks = {
|
|
|
- .curlyOpen = parserError,
|
|
|
- .curlyClose = parserError,
|
|
|
- .string = materialReadShader
|
|
|
- }
|
|
|
+ .data = { .str = buffer, .length = file->size },
|
|
|
+ .callback = materialParserCallback
|
|
|
};
|
|
|
|
|
|
- StringView buf_sv = { .str = buffer, .length = file->size };
|
|
|
+ const int success = VMFResult_Success == vmfParse(&parser_state);
|
|
|
+
|
|
|
+ if (success) {
|
|
|
+ if (!ctx.mat->base_texture[0]) {
|
|
|
+ PRINTF("Material with ctx.shader %.*s doesn't have base texture", ctx.shader.length, ctx.shader.str);
|
|
|
+ ctx.mat->shader = MaterialShader_LightmappedAverageColor;
|
|
|
+ // HACK to notice these materials
|
|
|
+ ctx.mat->average_color = aVec3f(1.f, 0.f, 1.f);
|
|
|
+ } else {
|
|
|
+ ctx.mat->shader = MaterialShader_LightmappedGeneric;
|
|
|
+ ctx.mat->average_color = ctx.mat->base_texture[0]->avg_color;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- int success = ParseResult_Success == parserParse(&parser, buf_sv);
|
|
|
|
|
|
stackFreeUpToPosition(tmp, buffer);
|
|
|
|
|
|
return success;
|
|
|
-#endif
|
|
|
}
|
|
|
|
|
|
const struct Material *materialGet(const char *name, struct ICollection *collection, struct Stack *tmp) {
|