예제 #1
0
//
// =======================================================================================================================
//    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();
}
예제 #2
0
 /*
 =======================================================================================================================
	Map_LoadFile
 =======================================================================================================================
 */
void Map_LoadFile(const char *filename) {
	entity_t *ent;
	CWaitDlg dlg;
	idStr fileStr, status;
	idMapFile mapfile;

	Sys_BeginWait();
	Select_Deselect();

	dlg.AllowCancel( true );
	idStr( filename ).ExtractFileName( fileStr );
	sprintf( status, "Loading %s...", fileStr.c_str() );
	dlg.SetWindowText( status );
	sprintf( status, "Reading file %s...", fileStr.c_str() );
	dlg.SetText( status );

	// SetInspectorMode(W_CONSOLE);
	fileStr = filename;
	fileStr.BackSlashesToSlashes();

	common->Printf( "Map_LoadFile: %s\n", fileStr.c_str() );

	Map_Free();

	g_qeglobals.d_parsed_brushes = 0;
	strcpy( currentmap, filename );

	if(mapfile.Parse(filename, true, true)) {
		g_qeglobals.bNeedConvert = false;
		g_qeglobals.bOldBrushes = false;
		g_qeglobals.bPrimitBrushes = false;
		g_qeglobals.mapVersion = 1.0;

		long lastUpdate = 0;
		int count = mapfile.GetNumEntities();
		for (int i = 0; i < count; i++) {
			idMapEntity *mapent = mapfile.GetEntity(i);
			if (mapent) {
				idStr classname = mapent->epairs.GetString("classname");
				// Update 20 times a second
				if ( (GetTickCount() - lastUpdate) > 50 ) {
					lastUpdate = GetTickCount();
					sprintf(status, "Loading entity %i (%s)...", i, classname.c_str());
					dlg.SetText(status);
				}
				if ( dlg.CancelPressed() ) {
					Sys_Status("Map load cancelled.\n");
					Map_New();
					return;
				}
				if (classname == "worldspawn") {
					world_entity = EntityFromMapEntity(mapent, &dlg);
					Entity_PostParse(world_entity, &active_brushes);
				} else {
					ent = EntityFromMapEntity(mapent, &dlg);
					Entity_PostParse(ent, &active_brushes);
					Entity_Name(ent, true);
					// 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++;
				}
			}
		}
	}

	if (!world_entity) {
		Sys_Status("No worldspawn in map.\n");
		Map_New();
		return;
	}

	common->Printf("--- LoadMapFile ---\n");
	common->Printf("%s\n", fileStr.c_str());

	common->Printf("%5i brushes\n", g_qeglobals.d_parsed_brushes);
	common->Printf("%5i entities\n", g_qeglobals.d_num_entities);

	dlg.SetText("Restoring Between");
	Map_RestoreBetween();

	dlg.SetText("Building Brush Data");
	common->Printf("Map_BuildAllDisplayLists\n");
	Map_BuildBrushData();

	//
	// reset the "need conversion" flag conversion to the good format done in
	// Map_BuildBrushData
	//
	g_qeglobals.bNeedConvert = false;

	// move the view to a start position
	ent = AngledEntity();

	g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;

	if (ent) {
		GetVectorForKey(ent, "origin", g_pParentWnd->GetCamera()->Camera().origin);
		GetVectorForKey(ent, "origin", g_pParentWnd->GetXYWnd()->GetOrigin());
		g_pParentWnd->GetCamera()->Camera().angles[YAW] = FloatForKey(ent, "angle");
	}
	else {
		g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
		VectorCopy(vec3_origin, g_pParentWnd->GetCamera()->Camera().origin);
		VectorCopy(vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin());
	}

	Map_RegionOff();

	mapModified = 0;

	if (GetFileAttributes(filename) & FILE_ATTRIBUTE_READONLY) {
		fileStr += " (read only) ";
	}
	Sys_SetTitle(fileStr);

	Texture_ShowInuse();

	if (g_pParentWnd->GetCamera()->GetRenderMode()) {
		g_pParentWnd->GetCamera()->BuildRendererState();
	}

	Sys_EndWait();
	Sys_UpdateWindows(W_ALL);
}
예제 #3
0
/*
 =======================================================================================================================
    Entity_Create Creates a new entity out of the selected_brushes list. If the entity class is fixed size, the brushes
    are only used to find a midpoint. Otherwise, the brushes have their ownership transfered to the new entity.
 =======================================================================================================================
 */
entity_t *Entity_Create(eclass_t *c, bool forceFixed)
{
    entity_t	*e;
    brush_t		*b;
    idVec3		mins, maxs, origin;
    char		text[32];
    texdef_t td;
    brushprimit_texdef_t bp;

    // check to make sure the brushes are ok
    for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
    {
        if (b->owner != world_entity)
        {
            Sys_Status("Entity NOT created, brushes not all from world\n");
            Sys_Beep();
            return NULL;
        }
    }

    idStr str;
    if (c->defArgs.GetString("model", "", str) && c->entityModel == NULL)
    {
        c->entityModel = gameEdit->ANIM_GetModelFromEntityDef( &c->defArgs );
    }

    // create it
    e = Entity_New();
    e->brushes.onext = e->brushes.oprev = &e->brushes;
    e->eclass = c;
    e->epairs.Copy(c->args);
    SetKeyValue(e, "classname", c->name);
    Entity_Name(e, false);

    // add the entity to the entity list
    Entity_AddToList(e, &entities);

    if (c->fixedsize)
    {
        //
        // just use the selection for positioning b = selected_brushes.next; for (i=0 ;
        // i<3 ; i++) { e->origin[i] = b->mins[i] - c->mins[i]; }
        //
        Select_GetMid(e->origin);
        VectorCopy(e->origin, origin);

        // create a custom brush
        VectorAdd(c->mins, e->origin, mins);
        VectorAdd(c->maxs, e->origin, maxs);

        b = Brush_Create(mins, maxs, &c->texdef);

        Entity_LinkBrush(e, b);

        if (c->defMaterial.Length())
        {
            td.SetName(c->defMaterial);
            Brush_SetTexture(b, &td, &bp, false);
        }


        // delete the current selection
        Select_Delete();

        // select the new brush
        b->next = b->prev = &selected_brushes;
        selected_brushes.next = selected_brushes.prev = b;

        Brush_Build(b);
    }
    else
    {

        Select_GetMid(origin);

        // change the selected brushes over to the new entity
        for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
        {
            Entity_UnlinkBrush(b);
            Entity_LinkBrush(e, b);
            Brush_Build(b); // so the key brush gets a name
            if (c->defMaterial.Length())
            {
                td.SetName(c->defMaterial);
                Brush_SetTexture(b, &td, &bp, false);
            }

        }

        //for (int i = 0; i < 3; i++) {
        //	origin[i] = vMin[i] + vMax[i] * 0.5;
        //}

        if (!forceFixed)
        {
            SetKeyValue(e, "model", ValueForKey(e, "name"));
        }
    }

    sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
    SetKeyValue(e, "origin", text);
    VectorCopy(origin, e->origin);

    Sys_UpdateWindows(W_ALL);
    return e;
}