void TrackMD3Angles(entity_t *e, LPCSTR key, LPCSTR value) { if (strcmpi(key, "angle") != 0) { return; } #ifdef SOF if (e->eclass->fixedsize && ( (strnicmp(e->eclass->name, "misc_", 5) == 0) || (strnicmp(e->eclass->name, "light_", 6) == 0) || (strnicmp(e->eclass->name, "m_", 2) == 0) || (strnicmp(e->eclass->name, "item_weapon_", 12)== 0) || (strnicmp(e->eclass->name, "item_ammo_", 10)== 0) ) ) #else if (e->eclass->fixedsize && strnicmp (e->eclass->name, "misc_model",10) == 0) #endif { float a = FloatForKey (e, "angle"); float b = atof(value); if (a != b) { vec3_t vAngle; vAngle[0] = vAngle[1] = 0; vAngle[2] = -a; Brush_Rotate(e->brushes.onext, vAngle, e->origin, true); vAngle[2] = b; Brush_Rotate(e->brushes.onext, vAngle, e->origin, true); #ifdef QUAKE3 // // auto assign new bounding box to model? // char *_p = ValueForKey(e, "mins"); char *_p2= ValueForKey(e, "maxs"); char *_p3= ValueForKey(e, sKEYFIELD_AUTOBOUND); // // if either key is missing then update both... (or if they do exist, but were only set by this code in the first place and therefore can be overwritten) // if ( ((strlen(_p) == 0) || (strlen(_p2) == 0)) || strlen(_p3) ) { SetKeyValue (e, sKEYFIELD_AUTOBOUND, "1"); vec3_t vMins,vMaxs; VectorSubtract(e->brushes.onext->mins, e->origin, vMins); VectorSubtract(e->brushes.onext->maxs, e->origin, vMaxs); SetKeyValue (e, "mins", va("%i %i %i", (int)vMins[0], (int)vMins[1], (int)vMins[2])); SetKeyValue (e, "maxs", va("%i %i %i", (int)vMaxs[0], (int)vMaxs[1], (int)vMaxs[2])); } #endif } } }
// Scale object bounding box void TrackMD3Scale(entity_t *e, LPCSTR key, LPCSTR value) { float oldscale,scale; if (strcmpi(key, "scale") != 0) { return; } if (e->eclass->fixedsize && ((strnicmp(e->eclass->name, "misc_",5) == 0) || (strnicmp(e->eclass->name, "light_",6) == 0))) { oldscale = FloatForKey (e, "scale"); scale = atof(value); if (oldscale != scale) // Value unchanged?????? { Brush_Scale2(e->eclass,e->brushes.onext, scale,e->origin,true); float a = FloatForKey (e, "angle"); if (a) { // Re-rotate bbox vec3_t vAngle; vAngle[0] = vAngle[1] = 0; vAngle[2] = a; Brush_Rotate(e->brushes.onext, vAngle, e->origin, true); } } } }
/* ======================================================================================================================= ======================================================================================================================= */ void TrackMD3Angles(entity_t *e, const char *key, const char *value) { if ( idStr::Icmp(key, "angle") != 0 ) { return; } if ((e->eclass->fixedsize && e->eclass->nShowFlags & ECLASS_MISCMODEL) || EntityHasModel(e)) { float a = FloatForKey(e, "angle"); float b = atof(value); if (a != b) { idVec3 vAngle; vAngle[0] = vAngle[1] = 0; vAngle[2] = -a; Brush_Rotate(e->brushes.onext, vAngle, e->origin, true); vAngle[2] = b; Brush_Rotate(e->brushes.onext, vAngle, e->origin, true); } } }
void CPlugInManager::CommitEntityHandleToMap(LPVOID vpEntity) { entity_t *pe; eclass_t *e; brush_t *b; vec3_t mins,maxs; bool has_brushes; for (int i=0 ; i < m_EntityHandles.GetSize() ; i++ ) { if (vpEntity == m_EntityHandles.GetAt(i)) { m_EntityHandles.RemoveAt(i); pe = reinterpret_cast<entity_t*>(vpEntity); // fill additional fields // straight copy from Entity_Parse // entity_t::origin GetVectorForKey (pe, "origin", pe->origin); // entity_t::eclass if (pe->brushes.onext == &pe->brushes) has_brushes = false; else has_brushes = true; e = Eclass_ForName (ValueForKey (pe, "classname"), has_brushes); pe->eclass = e; // fixedsize if (e->fixedsize) { if (pe->brushes.onext != &pe->brushes) { Sys_Printf("Warning : Fixed size entity with brushes in CPlugInManager::CommitEntityHandleToMap\n"); } // create a custom brush VectorAdd(e->mins, pe->origin, mins); VectorAdd(e->maxs, pe->origin, maxs); float a = 0; if (e->nShowFlags & ECLASS_MISCMODEL) { char* p = ValueForKey(pe, "model"); if (p != NULL && strlen(p) > 0) { vec3_t vMin, vMax; a = FloatForKey (pe, "angle"); if (GetCachedModel(pe, p, vMin, vMax)) { // create a custom brush VectorAdd (pe->md3Class->mins, pe->origin, mins); VectorAdd (pe->md3Class->maxs, pe->origin, maxs); } } } b = Brush_Create (mins, maxs, &e->texdef); if (a) { vec3_t vAngle; vAngle[0] = vAngle[1] = 0; vAngle[2] = a; Brush_Rotate(b, vAngle, pe->origin, false); } b->owner = pe; b->onext = pe->brushes.onext; b->oprev = &pe->brushes; pe->brushes.onext->oprev = b; pe->brushes.onext = b; } else { // brush entity if (pe->brushes.next == &pe->brushes) Sys_Printf ("Warning: Brush entity with no brushes in CPlugInManager::CommitEntityHandleToMap\n"); } // add brushes to the active brushes list // and build them along the way for (b=pe->brushes.onext ; b != &pe->brushes ; b=b->onext) { // convert between old brushes and brush primitive if (g_qeglobals.m_bBrushPrimitMode) { // we only filled the shift scale rot fields, needs conversion Brush_Build( b, true, true, true ); } else { // we are using old brushes Brush_Build( b ); } b->next = active_brushes.next; active_brushes.next->prev = b; b->prev = &active_brushes; active_brushes.next = b; } // handle worldspawn entities // if worldspawn has no brushes, use the new one if (!strcmp(ValueForKey (pe, "classname"), "worldspawn")) { if ( world_entity && ( world_entity->brushes.onext != &world_entity->brushes ) ) { // worldspawn already has brushes Sys_Printf ("Commiting worldspawn as func_group\n"); SetKeyValue(pe, "classname", "func_group"); // add the entity to the end of the entity list pe->next = &entities; pe->prev = entities.prev; entities.prev->next = pe; entities.prev = pe; g_qeglobals.d_num_entities++; } else { // there's a worldspawn with no brushes, we assume the map is empty if ( world_entity ) { Entity_Free( world_entity ); world_entity = pe; } else Sys_Printf("Warning : unexpected world_entity == NULL in CommitEntityHandleToMap\n"); } } else { // add the entity to the end of the entity list pe->next = &entities; pe->prev = entities.prev; entities.prev->next = pe; entities.prev = pe; g_qeglobals.d_num_entities++; } } } }
entity_t *Entity_PostParse(entity_t *ent, brush_t *pList) { bool has_brushes; eclass_t *e; brush_t *b; idVec3 mins, maxs, zero; idBounds bo; zero.Zero(); Entity_SetCurveData( ent ); if (ent->brushes.onext == &ent->brushes) { has_brushes = false; } else { has_brushes = true; } bool needsOrigin = !GetVectorForKey(ent, "origin", ent->origin); const char *pModel = ValueForKey(ent, "model"); const char *cp = ValueForKey(ent, "classname"); if (strlen(cp)) { e = Eclass_ForName(cp, has_brushes); } else { const char *cp2 = ValueForKey(ent, "name"); if (strlen(cp2)) { char buff[1024]; strcpy(buff, cp2); int len = strlen(buff); while ((isdigit(buff[len-1]) || buff[len-1] == '_') && len > 0) { buff[len-1] = '\0'; len--; } e = Eclass_ForName(buff, has_brushes); SetKeyValue(ent, "classname", buff, false); } else { e = Eclass_ForName("", has_brushes); } } idStr str; if (e->defArgs.GetString("model", "", str) && e->entityModel == NULL) { e->entityModel = gameEdit->ANIM_GetModelFromEntityDef( &e->defArgs ); } ent->eclass = e; bool hasModel = EntityHasModel(ent); if (hasModel) { ent->eclass->defArgs.GetString("model", "", str); if (str.Length()) { hasModel = false; ent->epairs.Delete("model"); } } if (e->nShowFlags & ECLASS_WORLDSPAWN) { ent->origin.Zero(); needsOrigin = false; ent->epairs.Delete( "model" ); } else if (e->nShowFlags & ECLASS_LIGHT) { if (GetVectorForKey(ent, "light_origin", ent->lightOrigin)) { GetMatrixForKey(ent, "light_rotation", ent->lightRotation); ent->trackLightOrigin = true; } else if (hasModel) { SetKeyValue(ent, "light_origin", ValueForKey(ent, "origin")); ent->lightOrigin = ent->origin; if (GetMatrixForKey(ent, "rotation", ent->lightRotation)) { SetKeyValue(ent, "light_rotation", ValueForKey(ent, "rotation")); } ent->trackLightOrigin = true; } } else if ( e->nShowFlags & ECLASS_ENV ) { // need to create an origin from the bones here idVec3 org; idAngles ang; bo.Clear(); bool hasBody = false; const idKeyValue *arg = ent->epairs.MatchPrefix( "body ", NULL ); while ( arg ) { sscanf( arg->GetValue(), "%f %f %f %f %f %f", &org.x, &org.y, &org.z, &ang.pitch, &ang.yaw, &ang.roll ); bo.AddPoint( org ); arg = ent->epairs.MatchPrefix( "body ", arg ); hasBody = true; } if (hasBody) { ent->origin = bo.GetCenter(); } } if (e->fixedsize || hasModel) // fixed size entity { if (ent->brushes.onext != &ent->brushes) { for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext) { b->entityModel = true; } } if (hasModel) { // model entity idRenderModel *modelHandle = renderModelManager->FindModel( pModel ); if ( dynamic_cast<idRenderModelPrt*>( modelHandle ) || dynamic_cast<idRenderModelLiquid*>( modelHandle ) ) { bo.Zero(); bo.ExpandSelf( 12.0f ); } else { bo = modelHandle->Bounds( NULL ); } VectorCopy(bo[0], mins); VectorCopy(bo[1], maxs); for (int i = 0; i < 3; i++) { if (mins[i] == maxs[i]) { mins[i]--; maxs[i]++; } } VectorAdd(mins, ent->origin, mins); VectorAdd(maxs, ent->origin, maxs); b = Brush_Create(mins, maxs, &e->texdef); b->modelHandle = modelHandle; float yaw = 0; bool convertAngles = GetFloatForKey(ent, "angle", &yaw); extern void Brush_Rotate(brush_t *b, idMat3 matrix, idVec3 origin, bool bBuild); extern void Brush_Rotate(brush_t *b, idVec3 rot, idVec3 origin, bool bBuild); if (convertAngles) { idVec3 rot(0, 0, yaw); Brush_Rotate(b, rot, ent->origin, false); } if (GetMatrixForKey(ent, "rotation", ent->rotation)) { idBounds bo2; bo2.FromTransformedBounds(bo, ent->origin, ent->rotation); b->owner = ent; Brush_Resize(b, bo2[0], bo2[1]); } Entity_LinkBrush(ent, b); } if (!hasModel || (ent->eclass->nShowFlags & ECLASS_LIGHT && hasModel)) { // create a custom brush if (ent->trackLightOrigin) { mins = e->mins + ent->lightOrigin; maxs = e->maxs + ent->lightOrigin; } else { mins = e->mins + ent->origin; maxs = e->maxs + ent->origin; } b = Brush_Create(mins, maxs, &e->texdef); GetMatrixForKey(ent, "rotation", ent->rotation); Entity_LinkBrush(ent, b); b->trackLightOrigin = ent->trackLightOrigin; if ( e->texdef.name == NULL ) { brushprimit_texdef_t bp; texdef_t td; td.SetName( ent->eclass->defMaterial ); Brush_SetTexture( b, &td, &bp, false ); } } } else // brush entity { if (ent->brushes.next == &ent->brushes) { printf("Warning: Brush entity with no brushes\n"); } if (!needsOrigin) { idStr cn = ValueForKey(ent, "classname"); idStr name = ValueForKey(ent, "name"); idStr model = ValueForKey(ent, "model"); if (cn.Icmp("func_static") == 0) { if (name.Icmp(model) == 0) { needsOrigin = true; } } } if (needsOrigin) { idVec3 mins, maxs, mid; int i; char text[32]; mins[0] = mins[1] = mins[2] = 999999; maxs[0] = maxs[1] = maxs[2] = -999999; // add in the origin for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext) { Brush_Build(b, true, false, false); for (i = 0; i < 3; i++) { if (b->mins[i] < mins[i]) { mins[i] = b->mins[i]; } if (b->maxs[i] > maxs[i]) { maxs[i] = b->maxs[i]; } } } for (i = 0; i < 3; i++) { ent->origin[i] = (mins[i] + ((maxs[i] - mins[i]) / 2)); } sprintf(text, "%i %i %i", (int)ent->origin[0], (int)ent->origin[1], (int)ent->origin[2]); SetKeyValue(ent, "origin", text); } if (!(e->nShowFlags & ECLASS_WORLDSPAWN)) { if (e->defArgs.FindKey("model") == NULL && (pModel == NULL || (pModel && strlen(pModel) == 0))) { SetKeyValue(ent, "model", ValueForKey(ent, "name")); } } else { DeleteKey(ent, "origin"); } } // add all the brushes to the main list if (pList) { for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext) { b->next = pList->next; pList->next->prev = b; b->prev = pList; pList->next = b; } } FixFloats(&ent->epairs); return ent; }