/* ============ Select_SetTexture Timo : bFitScale to compute scale on the plane and counteract plane / axial plane snapping Timo : brush primitive texturing the brushprimit_texdef given must be understood as a qtexture_t width=2 height=2 ( HiRes ) Timo : texture plugin, added an IPluginTexdef* parameter must be casted to an IPluginTexdef! if not NULL, get ->Copy() of it into each face or brush ( and remember to hook ) if NULL, means we have no information, ask for a default ============ */ void WINAPI Select_SetTexture( texdef_t* texdef, brushprimit_texdef_s* brushprimit_texdef, bool bFitScale, void* pPlugTexdef ) { brush_s* b; int nCount = g_ptrSelectedFaces.GetSize(); if ( nCount > 0 ) { Undo_Start( "set face textures" ); ASSERT( g_ptrSelectedFaces.GetSize() == g_ptrSelectedFaceBrushes.GetSize() ); for ( int i = 0; i < nCount; i++ ) { face_s* selFace = reinterpret_cast<face_s*>( g_ptrSelectedFaces.GetAt( i ) ); brush_s* selBrush = reinterpret_cast<brush_s*>( g_ptrSelectedFaceBrushes.GetAt( i ) ); Undo_AddBrush( selBrush ); SetFaceTexdef( selBrush, selFace, texdef, brushprimit_texdef, bFitScale, static_cast<IPluginTexdef*>( pPlugTexdef ) ); Brush_Build( selBrush, bFitScale ); Undo_EndBrush( selBrush ); } Undo_End(); } else if ( selected_brushes.next != &selected_brushes ) { Undo_Start( "set brush textures" ); for ( b = selected_brushes.next ; b != &selected_brushes ; b = b->next ) if ( !b->owner->eclass->fixedsize ) { Undo_AddBrush( b ); Brush_SetTexture( b, texdef, brushprimit_texdef, bFitScale, static_cast<IPluginTexdef*>( pPlugTexdef ) ); Undo_EndBrush( b ); } Undo_End(); } Sys_UpdateWindows( W_ALL ); }
void SI_SetTexdef_FaceList(texdef_to_face_t* texdef_face_list, bool b_SetUndoPoint, bool bFit_to_Scale) { texdef_to_face_t* texdef_to_face; bool b_isQuake2; if (g_pGameDescription->quake2) b_isQuake2 = true; else b_isQuake2 = false; if (!texdef_face_list) return; if (b_SetUndoPoint) { if(g_ptrSelectedFaces.GetSize() > 1) Sys_FPrintf(SYS_WRN, "WARNING: Undo NOT supported for multiple face selections\n"); else if( (selected_brushes.next != &selected_brushes) || (g_ptrSelectedFaces.GetSize() == 1)) { // Give something to undo to for(texdef_to_face = texdef_face_list; texdef_to_face; texdef_to_face = texdef_to_face->next) if (b_isQuake2) SetFaceTexdef_Q2(texdef_to_face->face, &texdef_to_face->orig_texdef, bFit_to_Scale); else SetFaceTexdef(texdef_to_face->face, &texdef_to_face->orig_texdef, &texdef_to_face->orig_bp_texdef, bFit_to_Scale); Undo_Start("set facelist texdefs"); if( selected_brushes.next != &selected_brushes ) Undo_AddBrushList(&selected_brushes); else Undo_AddBrush(texdef_face_list->brush); } } for(texdef_to_face = texdef_face_list; texdef_to_face; texdef_to_face = texdef_to_face->next) { if (b_isQuake2) SetFaceTexdef_Q2(texdef_to_face->face, &texdef_to_face->texdef, bFit_to_Scale); else { brushprimit_texdef_t brushprimit_texdef; FakeTexCoordsToTexMat(texdef_to_face->texdef.shift, texdef_to_face->texdef.rotate, texdef_to_face->texdef.scale, brushprimit_texdef.coords); SetFaceTexdef(texdef_to_face->face, &texdef_to_face->texdef, &brushprimit_texdef , bFit_to_Scale); } Brush_Build(texdef_to_face->brush); if(bFit_to_Scale) texdef_to_face->texdef = texdef_to_face->face->texdef; } if ( b_SetUndoPoint ) { if( (selected_brushes.next != &selected_brushes) || (g_ptrSelectedFaces.GetSize() == 1) ) { if(selected_brushes.next != &selected_brushes) Undo_EndBrushList(&selected_brushes); else Undo_EndBrush(texdef_face_list->brush); Undo_End(); // Over-write the orig_texdef list, cementing the change. for(texdef_to_face = texdef_face_list; texdef_to_face; texdef_to_face = texdef_to_face->next) { texdef_to_face->orig_texdef = texdef_to_face->texdef; texdef_to_face->orig_bp_texdef = texdef_to_face->face->brushprimit_texdef; } } } Sys_UpdateWindows (W_ALL); }
/* ============= CSG_Subtract ============= */ void CSG_Subtract (void) { brush_t *b, *s, *fragments, *nextfragment, *frag, *next, *snext; brush_t fragmentlist; int i, numfragments, numbrushes; Sys_Status ("Subtracting...\n"); if (selected_brushes.next == &selected_brushes) { Sys_Status("No brushes selected.\n"); return; } fragmentlist.next = &fragmentlist; fragmentlist.prev = &fragmentlist; numfragments = 0; numbrushes = 0; for (b = selected_brushes.next ; b != &selected_brushes ; b=next) { next = b->next; if (b->owner->eclass->fixedsize || b->modelHandle > 0) continue; // can't use texture from a fixed entity, so don't subtract // chop all fragments further up for (s = fragmentlist.next; s != &fragmentlist; s = snext) { snext = s->next; for (i=0 ; i<3 ; i++) if (b->mins[i] >= s->maxs[i] - ON_EPSILON || b->maxs[i] <= s->mins[i] + ON_EPSILON) break; if (i != 3) continue; // definately don't touch fragments = Brush_Subtract(s, b); // if the brushes did not really intersect if (fragments == s) continue; // try to merge fragments fragments = Brush_MergeListPairs(fragments, true); // add the fragments to the list for (frag = fragments; frag; frag = nextfragment) { nextfragment = frag->next; frag->next = NULL; frag->owner = s->owner; Brush_AddToList(frag, &fragmentlist); } // free the original brush Brush_Free(s); } // chop any active brushes up for (s = active_brushes.next; s != &active_brushes; s = snext) { snext = s->next; if (s->owner->eclass->fixedsize || s->pPatch || s->hiddenBrush || s->modelHandle > 0) continue; //face_t *pFace = s->brush_faces; if ( s->brush_faces->d_texture && ( s->brush_faces->d_texture->GetContentFlags()& CONTENTS_NOCSG ) ) { continue; } for (i=0 ; i<3 ; i++) if (b->mins[i] >= s->maxs[i] - ON_EPSILON || b->maxs[i] <= s->mins[i] + ON_EPSILON) break; if (i != 3) continue; // definately don't touch fragments = Brush_Subtract(s, b); // if the brushes did not really intersect if (fragments == s) continue; // Undo_AddBrush(s); // one extra brush chopped up numbrushes++; // try to merge fragments fragments = Brush_MergeListPairs(fragments, true); // add the fragments to the list for (frag = fragments; frag; frag = nextfragment) { nextfragment = frag->next; frag->next = NULL; frag->owner = s->owner; Brush_AddToList(frag, &fragmentlist); } // free the original brush Brush_Free(s); } } // move all fragments to the active brush list for (frag = fragmentlist.next; frag != &fragmentlist; frag = nextfragment) { nextfragment = frag->next; numfragments++; Brush_RemoveFromList(frag); Brush_AddToList(frag, &active_brushes); Undo_EndBrush(frag); } if (numfragments == 0) { common->Printf("Selected brush%s did not intersect with any other brushes.\n", (selected_brushes.next->next == &selected_brushes) ? "":"es"); return; } Sys_Status("done."); common->Printf(" (created %d fragment%s out of %d brush%s)\n", numfragments, (numfragments == 1)?"":"s", numbrushes, (numbrushes == 1)?"":"es"); Sys_UpdateWindows(W_ALL); }
// // ======================================================================================================================= // Map_ImportFile Timo 09/01/99:: called by CXYWnd::Paste & Map_ImportFile if Map_ImportFile ( prefab ), the buffer // may contain brushes in old format ( conversion needed ) // ======================================================================================================================= // void Map_ImportBuffer(char *buf, bool renameEntities) { entity_t *ent; brush_t *b = NULL; CPtrArray ptrs; Select_Deselect(); Undo_Start("import buffer"); g_qeglobals.d_parsed_brushes = 0; if (buf) { CMapStringToString mapStr; StartTokenParsing(buf); g_qeglobals.d_num_entities = 0; // // Timo will be used in Entity_Parse to detect if a conversion between brush // formats is needed // g_qeglobals.bNeedConvert = false; g_qeglobals.bOldBrushes = false; g_qeglobals.bPrimitBrushes = false; g_qeglobals.mapVersion = 1.0; if (GetToken(true)) { if (stricmp(token, "Version") == 0) { GetToken(false); g_qeglobals.mapVersion = atof(token); common->Printf("Map version: %1.2f\n", g_qeglobals.mapVersion); } else { UngetToken(); } } idDict RemappedNames; // since I can't use "map <string, string>"... sigh. So much for STL... while (1) { // // use the selected brushes list as it's handy ent = Entity_Parse (false, // &selected_brushes); // ent = Entity_Parse(false, &active_brushes); if (!ent) { break; } // end entity for undo Undo_EndEntity(ent); // end brushes for undo for (b = ent->brushes.onext; b && b != &ent->brushes; b = b->onext) { Undo_EndBrush(b); } if (!strcmp(ValueForKey(ent, "classname"), "worldspawn")) { // world brushes need to be added to the current world entity b = ent->brushes.onext; while (b && b != &ent->brushes) { brush_t *bNext = b->onext; Entity_UnlinkBrush(b); Entity_LinkBrush(world_entity, b); ptrs.Add(b); b = bNext; } } else { // the following bit remaps conflicting target/targetname key/value pairs CString str = ValueForKey(ent, "target"); CString strKey; CString strTarget(""); if (str.GetLength() > 0) { if (FindEntity("target", str.GetBuffer(0))) { if (!mapStr.Lookup(str, strKey)) { idStr key; UniqueTargetName(key); strKey = key; mapStr.SetAt(str, strKey); } strTarget = strKey; SetKeyValue(ent, "target", strTarget.GetBuffer(0)); } } /* * str = ValueForKey(ent, "name"); if (str.GetLength() > 0) { if * (FindEntity("name", str.GetBuffer(0))) { if (!mapStr.Lookup(str, strKey)) { * UniqueTargetName(strKey); mapStr.SetAt(str, strKey); } Entity_SetName(ent, * strKey.GetBuffer(0)); } } */ CString cstrNameOld = ValueForKey(ent, "name"); Entity_Name(ent, renameEntities); CString cstrNameNew = ValueForKey(ent, "name"); if (cstrNameOld != cstrNameNew) { RemappedNames.Set(cstrNameOld, cstrNameNew); } // // if (strTarget.GetLength() > 0) SetKeyValue(ent, "target", // strTarget.GetBuffer(0)); // add the entity to the end of the entity list // ent->next = &entities; ent->prev = entities.prev; entities.prev->next = ent; entities.prev = ent; g_qeglobals.d_num_entities++; for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext) { ptrs.Add(b); } } } // now iterate through the remapped names, and see if there are any target-connections that need remaking... // // (I could probably write this in half the size with STL, but WTF, work with what we have...) // int iNumKeyVals = RemappedNames.GetNumKeyVals(); for (int iKeyVal=0; iKeyVal < iNumKeyVals; iKeyVal++) { const idKeyValue *pKeyVal = RemappedNames.GetKeyVal( iKeyVal ); LPCSTR psOldName = pKeyVal->GetKey().c_str(); LPCSTR psNewName = pKeyVal->GetValue().c_str(); entity_t *pEntOld = FindEntity("name", psOldName); // original ent we cloned from entity_t *pEntNew = FindEntity("name", psNewName); // cloned ent if (pEntOld && pEntNew) { CString cstrTargetNameOld = ValueForKey(pEntOld, "target"); if (!cstrTargetNameOld.IsEmpty()) { // ok, this ent was targeted at another ent, so it's clone needs updating to point to // the clone of that target, so... // entity_t *pEntOldTarget = FindEntity("name", cstrTargetNameOld); if ( pEntOldTarget ) { LPCSTR psNewTargetName = RemappedNames.GetString( cstrTargetNameOld ); if (psNewTargetName && psNewTargetName[0]) { SetKeyValue(pEntNew, "target", psNewTargetName); } } } } } } // // ::ShowWindow(g_qeglobals.d_hwndEntity, FALSE); // ::LockWindowUpdate(g_qeglobals.d_hwndEntity); // g_bScreenUpdates = false; for (int i = 0; i < ptrs.GetSize(); i++) { Brush_Build(reinterpret_cast < brush_t * > (ptrs[i]), true, false); Select_Brush(reinterpret_cast < brush_t * > (ptrs[i]), true, false); } // ::LockWindowUpdate(NULL); g_bScreenUpdates = true; ptrs.RemoveAll(); // // reset the "need conversion" flag conversion to the good format done in // Map_BuildBrushData // g_qeglobals.bNeedConvert = false; Sys_UpdateWindows(W_ALL); // Sys_MarkMapModified(); mapModified = 1; Undo_End(); }
// //================ //Map_ImportFile // Timo 09/01/99 : called by CXYWnd::Paste & Map_ImportFile // if Map_ImportFile ( prefab ), the buffer may contain brushes in old format ( conversion needed ) //================ // void Map_ImportBuffer (char* buf) { entity_t* ent; brush_t* b = NULL; CPtrArray ptrs; Select_Deselect(); Undo_Start("import buffer"); g_qeglobals.d_parsed_brushes = 0; if (buf) { CMapStringToString mapStr; StartTokenParsing (buf); g_qeglobals.d_num_entities = 0; // Timo // will be used in Entity_Parse to detect if a conversion between brush formats is needed g_qeglobals.bNeedConvert = false; g_qeglobals.bOldBrushes = false; g_qeglobals.bPrimitBrushes = false; while (1) { // use the selected brushes list as it's handy //ent = Entity_Parse (false, &selected_brushes); ent = Entity_Parse (false, &active_brushes); if (!ent) break; //end entity for undo Undo_EndEntity(ent); //end brushes for undo for(b = ent->brushes.onext; b && b != &ent->brushes; b = b->onext) { Undo_EndBrush(b); } if (!strcmp(ValueForKey (ent, "classname"), "worldspawn")) { // world brushes need to be added to the current world entity b=ent->brushes.onext; while (b && b != &ent->brushes) { brush_t* bNext = b->onext; Entity_UnlinkBrush(b); Entity_LinkBrush(world_entity, b); ptrs.Add(b); b = bNext; } } else { // the following bit remaps conflicting target/targetname key/value pairs CString str = ValueForKey(ent, "target"); CString strKey; CString strTarget(""); if (str.GetLength() > 0) { if (FindEntity("target", str.GetBuffer(0))) { if (!mapStr.Lookup(str, strKey)) { UniqueTargetName(strKey); mapStr.SetAt(str, strKey); } strTarget = strKey; SetKeyValue(ent, "target", strTarget.GetBuffer(0)); } } str = ValueForKey(ent, "targetname"); if (str.GetLength() > 0) { if (FindEntity("targetname", str.GetBuffer(0))) { if (!mapStr.Lookup(str, strKey)) { UniqueTargetName(strKey); mapStr.SetAt(str, strKey); } SetKeyValue(ent, "targetname", strKey.GetBuffer(0)); } } //if (strTarget.GetLength() > 0) // SetKeyValue(ent, "target", strTarget.GetBuffer(0)); // add the entity to the end of the entity list ent->next = &entities; ent->prev = entities.prev; entities.prev->next = ent; entities.prev = ent; g_qeglobals.d_num_entities++; for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext) { ptrs.Add(b); } } } } //::ShowWindow(g_qeglobals.d_hwndEntity, FALSE); //::LockWindowUpdate(g_qeglobals.d_hwndEntity); g_bScreenUpdates = false; for (int i = 0; i < ptrs.GetSize(); i++) { Brush_Build(reinterpret_cast<brush_t*>(ptrs[i]), true, false); Select_Brush(reinterpret_cast<brush_t*>(ptrs[i]), true, false); } //::LockWindowUpdate(NULL); g_bScreenUpdates = true; ptrs.RemoveAll(); // reset the "need conversion" flag // conversion to the good format done in Map_BuildBrushData g_qeglobals.bNeedConvert=false; Sys_UpdateWindows (W_ALL); //Sys_MarkMapModified(); modified = true; Undo_End(); }