mirror of
https://github.com/kevinbentley/Descent3.git
synced 2026-04-04 11:00:04 -04:00
Move internal level editor into main tree
This commit is contained in:
862
editor/HFile.cpp
Normal file
862
editor/HFile.cpp
Normal file
@@ -0,0 +1,862 @@
|
||||
/*
|
||||
* Descent 3
|
||||
* Copyright (C) 2024 Parallax Software
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
--- HISTORICAL COMMENTS FOLLOW ---
|
||||
|
||||
* $Logfile: /DescentIII/Main/editor/HFile.cpp $
|
||||
* $Revision: 1.1.1.1 $
|
||||
* $Date: 2003-08-26 03:57:38 $
|
||||
* $Author: kevinb $
|
||||
*
|
||||
* Handler funcs for File menu
|
||||
*
|
||||
* $Log: not supported by cvs2svn $
|
||||
*
|
||||
* 81 10/13/99 2:19p Chris
|
||||
* Added the ability to disable wind for powerups on a level
|
||||
*
|
||||
* 80 10/13/99 10:40a Chris
|
||||
* Added 'special forcefields' that have custom bounce factors
|
||||
*
|
||||
* 79 10/08/99 4:29p Chris
|
||||
* Added the forcefield and glass breaking override options
|
||||
*
|
||||
* 78 5/18/99 11:10a Matt
|
||||
* Added variable ceiling height.
|
||||
*
|
||||
* 77 4/27/99 3:24p Jeff
|
||||
* showlevelstats shows information about goals and special flags
|
||||
*
|
||||
* 76 4/21/99 1:08p Chris
|
||||
* Fixed new mines from having the always check ceiling flag
|
||||
*
|
||||
* 75 4/20/99 8:14p Chris
|
||||
* Added support for object's that hit the ceiling and for making the
|
||||
* level always check for the ceiling (inside and outside the mine)
|
||||
*
|
||||
* 74 4/18/99 5:42a Chris
|
||||
* Added the FQ_IGNORE_RENDER_THROUGH_PORTALS flag
|
||||
*
|
||||
* 73 3/22/99 6:26p Matt
|
||||
* Cleaned up error handling in cfile and editor level loads.
|
||||
*
|
||||
* 72 3/02/99 4:54p Matt
|
||||
* Fixed another stupid bug
|
||||
*
|
||||
* 71 3/02/99 4:07p Matt
|
||||
* Fixed stupid bug in duplicate room name check
|
||||
*
|
||||
* 70 3/01/99 10:39a Matt
|
||||
* Strip leading and trailing spaces from object, trigger, and room names
|
||||
* on level load and when the names are entered.
|
||||
*
|
||||
* 69 2/28/99 10:41p Matt
|
||||
* After a level is loaded, check for duplicate trigger, room, & object
|
||||
* names.
|
||||
*
|
||||
* 68 2/28/99 9:28p Matt
|
||||
* Cleaned up load level error handing and version checking.
|
||||
*
|
||||
* 67 2/21/99 12:28p Matt
|
||||
* Added terrain sound system
|
||||
*
|
||||
* 66 2/17/99 3:06p Matt
|
||||
* Updated copyrights.
|
||||
*
|
||||
* 65 2/16/99 3:47p Jason
|
||||
* added marker updates to multiplayer server stream
|
||||
*
|
||||
* 64 2/02/99 10:46a Matt
|
||||
* Only reset the wireframe view radius when loading an actual new level,
|
||||
* and not whenever a level is loading, which incudes going from the game
|
||||
* to the editor.
|
||||
*
|
||||
* 63 1/29/99 12:48p Matt
|
||||
* Rewrote the doorway system
|
||||
*
|
||||
* 62 1/21/99 11:15p Jeff
|
||||
* pulled out some structs and defines from header files and moved them
|
||||
* into seperate header files so that multiplayer dlls don't require major
|
||||
* game headers, just those new headers. Side effect is a shorter build
|
||||
* time. Also cleaned up some header file #includes that weren't needed.
|
||||
* This affected polymodel.h, object.h, player.h, vecmat.h, room.h,
|
||||
* manage.h and multi.h
|
||||
*
|
||||
* 61 1/08/99 2:56p Samir
|
||||
* Ripped out OSIRIS1.
|
||||
*
|
||||
* 60 1/04/99 6:19p Jason
|
||||
* counts number of specular faces in mine
|
||||
*
|
||||
* 59 12/18/98 5:40p Chris
|
||||
* Ambient life is now all sequenced up
|
||||
*
|
||||
* 58 10/08/98 8:14p Matt
|
||||
* Fixed stupid bug that's just started causing problems.
|
||||
*
|
||||
* 57 10/08/98 4:23p Kevin
|
||||
* Changed code to comply with memory library usage. Always use mem_malloc
|
||||
* , mem_free and mem_strdup
|
||||
*
|
||||
* 56 10/05/98 2:42a Chris
|
||||
* Level goals are relatively functional
|
||||
*
|
||||
* 55 9/24/98 5:00p Matt
|
||||
* Improved error checking for running out of rooms.
|
||||
*
|
||||
* 54 9/16/98 12:07p Chris
|
||||
* Improved BOA AABB computation with room checksums
|
||||
*
|
||||
* 53 9/10/98 3:07p Chris
|
||||
* Improved matcen sequencing code and test effect1
|
||||
*
|
||||
* 52 9/08/98 12:05p Jason
|
||||
* moved doorway.h out of room.h
|
||||
*
|
||||
* 51 8/17/98 2:16p Jason
|
||||
* fixed erroneous reporting of specular lightmap bytes
|
||||
*
|
||||
* 50 8/10/98 11:25a Jason
|
||||
* added better specular lighting
|
||||
*
|
||||
* 49 8/03/98 5:47p Chris
|
||||
* Improved the partial AABB computation
|
||||
*
|
||||
* 48 5/15/98 5:41p Jason
|
||||
* implemented volume lighting system
|
||||
*
|
||||
* 47 5/13/98 3:06p Jason
|
||||
* got rid of square-power-of-two lightmap limitations
|
||||
*
|
||||
* 46 5/13/98 12:06p Jason
|
||||
* trimmed some memory usage
|
||||
*
|
||||
* 45 4/21/98 2:40p Matt
|
||||
* Added option to show level stats
|
||||
*
|
||||
* 44 4/14/98 7:50p Matt
|
||||
* Added system to keep info for each level
|
||||
*
|
||||
* 43 2/18/98 8:43p Chris
|
||||
* Made BOA get saved with the level. It should only get built when it
|
||||
* needs to be updated.
|
||||
*
|
||||
* 42 2/04/98 1:26p Matt
|
||||
* Got rid of compile warning
|
||||
*
|
||||
* 41 2/03/98 5:01p Chris
|
||||
* UPdated the path system
|
||||
*
|
||||
* 40 1/27/98 12:01p Chris
|
||||
* Game path system now works with new, load, and save in the editor.
|
||||
* Also, the game path system is further bug proved.
|
||||
*
|
||||
* 39 1/21/98 12:32p Matt
|
||||
* Revamped viewer system
|
||||
*
|
||||
* 38 1/20/98 1:36p Matt
|
||||
* Moved mine origin to the center of the terrain
|
||||
*
|
||||
* 37 1/19/98 10:04a Matt
|
||||
* Added new object handle system
|
||||
*
|
||||
* 36 1/15/98 7:34p Matt
|
||||
* Revamped error checking when computing face normals
|
||||
*
|
||||
* 35 1/02/98 12:00p Jason
|
||||
* got rid of redundant rebuilding of min/max terrain
|
||||
*
|
||||
* 34 10/08/97 5:20p Jason
|
||||
* clear object memory when "New" is selected
|
||||
*
|
||||
* 33 10/01/97 7:49p Matt
|
||||
* Fixed bug w/ script memory freeing (as per Samir's instructions)
|
||||
*
|
||||
* 32 10/01/97 4:49p Samir
|
||||
* Free level script after loading it, since the editor doesn't need the
|
||||
* compiled program.
|
||||
*
|
||||
* 31 9/25/97 5:28p Samir
|
||||
* Even newer script code due to more changes in ObjCScript.cpp
|
||||
*
|
||||
* 30 9/24/97 2:57p Samir
|
||||
* Modified NewScript for level function.
|
||||
*
|
||||
* 29 9/22/97 5:59p Samir
|
||||
* Changed ObjCScript system, so everything is broken, but it shouldn't
|
||||
* crash the game.
|
||||
*
|
||||
* 28 9/17/97 1:24p Matt
|
||||
* Ripped out segment code
|
||||
*
|
||||
* 27 9/17/97 12:53p Samir
|
||||
* BIG SEGMENT RIPOUT
|
||||
*
|
||||
* 26 9/10/97 1:55p Samir
|
||||
* Create a default level script for a new mine.
|
||||
*
|
||||
* 25 9/09/97 2:38p Samir
|
||||
* Added include for string.h
|
||||
*
|
||||
* 24 9/09/97 1:04p Samir
|
||||
* Added code to create new script and save level script name.
|
||||
*
|
||||
* 23 9/09/97 10:44a Matt
|
||||
* Fixed a small bug, & ripped out some segment engine code
|
||||
*
|
||||
* 22 9/06/97 3:35p Matt
|
||||
* Reset cur porral when room changes
|
||||
* Ripped out some old segment engine code
|
||||
*
|
||||
* 21 8/29/97 5:21p Matt
|
||||
* Made CreateNewMine() clear the room (not segment) selected list, and
|
||||
* clear Placed_group
|
||||
*
|
||||
* 20 8/21/97 2:06p Matt
|
||||
* Clear marked room when creating a new level
|
||||
*
|
||||
* 19 8/18/97 6:59p Matt
|
||||
* Implemented Place Room/Attach room system
|
||||
*
|
||||
* 18 8/15/97 6:32p Samir
|
||||
* Took out references to default/level scripts due to newer system.
|
||||
*
|
||||
* 17 8/12/97 3:22p Samir
|
||||
* D3XReallocProgram now has two more args.
|
||||
*
|
||||
* 16 8/06/97 10:36a Samir
|
||||
* Fixed D3XReallocProgram calls.
|
||||
*
|
||||
* 15 8/04/97 4:12p Samir
|
||||
* Reset level script code every new mine.
|
||||
*
|
||||
* 14 7/24/97 2:58p Matt
|
||||
* Reset editor viewer variables when creating a new mine
|
||||
*
|
||||
* 13 7/22/97 7:07p Matt
|
||||
* Cleaned up D3EditState, moving some vars in and some out, and renaming
|
||||
* and changing a few others
|
||||
*
|
||||
* 12 7/18/97 5:42p Matt
|
||||
* Changed default level script to use CR/LF pair instead of Newline
|
||||
*
|
||||
* 11 7/17/97 7:22p Matt
|
||||
* Initialize level script when create new level
|
||||
*
|
||||
* 26 6/30/97 1:30p Jason
|
||||
* added netherspace stuff
|
||||
*
|
||||
* 25 6/24/97 3:50p Jason
|
||||
* changes for y only terrain positions
|
||||
*
|
||||
* 24 5/13/97 10:29p Matt
|
||||
* Deleted some unused code
|
||||
*
|
||||
* 23 5/13/97 12:01p Matt
|
||||
* Added support for floating segments
|
||||
*
|
||||
* 22 5/08/97 7:29p Matt
|
||||
* Made seperate viewers for mine & terrain, and cleaned up code the
|
||||
* switched between modes
|
||||
*
|
||||
* 21 5/06/97 2:30p Jason
|
||||
* added check for terrain viewer
|
||||
*
|
||||
* 20 4/25/97 2:31p Jason
|
||||
* implemented game event system
|
||||
*
|
||||
* 19 4/04/97 2:57p Matt
|
||||
* Added code to initialize all the type-specific data for an object from
|
||||
* the page for that object type. This means that we need to pass less
|
||||
* info to ObjCreate(), and that we save less info in the level save file.
|
||||
* It also makes it easy to reset all the objects when an object page has
|
||||
* changed.
|
||||
*
|
||||
* 18 4/01/97 11:00p Matt
|
||||
* Changed editor to keep a viewer object (type camera) seperate from the
|
||||
* player object. This camera, and not the player, is now moved by
|
||||
* slewing, the C key, etc. When going into the game, the viewer position
|
||||
* & orientation are copied to the player. When going back to the editor,
|
||||
* the player position is copied to the viewer, and the player object is
|
||||
* reset to its start location.
|
||||
*
|
||||
* 17 3/31/97 5:58p Matt
|
||||
* Revamped mine update flags
|
||||
*
|
||||
* 16 3/31/97 3:47p Matt
|
||||
* Added code to keep track of, render, and display current vertex.
|
||||
*
|
||||
* 15 3/21/97 5:01p Jason
|
||||
* incremental terrain improvments
|
||||
*
|
||||
*
|
||||
* 14 3/18/97 11:27a Samir
|
||||
* Reset current trigger and doorway to 0 when loading a level in.
|
||||
*
|
||||
* 13 3/17/97 2:54p Samir
|
||||
* Dont initialize initial doorways or triggers.
|
||||
*
|
||||
* 12 3/17/97 12:00p Matt
|
||||
* Reset warning segments when creating new level and loading
|
||||
* level.
|
||||
*
|
||||
* 11 3/12/97 1:14p Matt
|
||||
* Clear selected list when creating a new mine
|
||||
*
|
||||
* 10 3/12/97 12:37p Samir
|
||||
* Initialized doorways
|
||||
*
|
||||
* 9 3/05/97 3:33p Samir
|
||||
* Define initial default Doorway for mine.
|
||||
*
|
||||
* 8 3/04/97 7:12p Samir
|
||||
* Initialized a default trigger when new level
|
||||
*
|
||||
* 7 2/26/97 12:23p Matt
|
||||
* Use real funcs to create segment sides & assign uvs.
|
||||
* Deleted temp func that did the same.
|
||||
*
|
||||
* 6 2/24/97 6:00p Matt
|
||||
* Added code to set marked segment.
|
||||
* Changed code to not say that mine has changed when curside or curside
|
||||
* has changed.
|
||||
*
|
||||
* 5 2/21/97 5:23p Matt
|
||||
* Added new ResetVertices() to set Vertex_active array after level
|
||||
* loaded. Renamed old ResetVertices() to InitVertices();
|
||||
*
|
||||
* 4 2/20/97 9:56a Matt
|
||||
* Moved some general-purpose segment code from HFile.cpp to ESegments.cpp
|
||||
*
|
||||
* 3 2/11/97 6:44p Matt
|
||||
* Reset player when do a new level
|
||||
* Added new function: ResetFreeSegList()
|
||||
*
|
||||
* 2 2/10/97 5:40p Matt
|
||||
* Code to handle several File menu options
|
||||
*
|
||||
* 1 2/10/97 12:16a Matt
|
||||
*
|
||||
* $NoKeywords: $
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "descent.h"
|
||||
#include "HFile.h"
|
||||
#include "d3edit.h"
|
||||
#include "room.h"
|
||||
#include "object.h"
|
||||
#include "game.h"
|
||||
#include "LoadLevel.h"
|
||||
#include "MoveWorld.h"
|
||||
#include "ERooms.h"
|
||||
#include "trigger.h"
|
||||
#include "door.h"
|
||||
#include "selectedroom.h"
|
||||
#include "terrain.h"
|
||||
#include "player.h"
|
||||
#include "gameevent.h"
|
||||
#include "HView.h"
|
||||
#include "gamepath.h"
|
||||
#include "boa.h"
|
||||
#include "mission.h"
|
||||
#include "lighting.h"
|
||||
#include "lightmap_info.h"
|
||||
#include "lightmap.h"
|
||||
#include "special_face.h"
|
||||
#include "doorway.h"
|
||||
#include "matcen.h"
|
||||
#include "levelgoal.h"
|
||||
#include "aiambient.h"
|
||||
#include "polymodel.h"
|
||||
#include "bnode.h"
|
||||
#include "findintersection.h"
|
||||
|
||||
// Scripting stuff
|
||||
//#include "d3x.h"
|
||||
//#include "ObjScript.h"
|
||||
|
||||
//vertices for the default room created by CreateNewMine()
|
||||
vector default_room_verts[] = { { -10, 8, 20 },
|
||||
{ -5, 10, 20 },
|
||||
{ 5, 10, 20 },
|
||||
{ 10, 8, 20 },
|
||||
{ 10, -8, 20 },
|
||||
{ 5,-10, 20 },
|
||||
{ -5,-10, 20 },
|
||||
{ -10, -8, 20 },
|
||||
{ -10, 8,-20 },
|
||||
{ -5, 10,-20 },
|
||||
{ 5, 10,-20 },
|
||||
{ 10, 8,-20 },
|
||||
{ 10, -8,-20 },
|
||||
{ 5,-10,-20 },
|
||||
{ -5,-10,-20 },
|
||||
{ -10, -8,-20 } };
|
||||
|
||||
extern void AssignDefaultUVsToRoom(room *rp);
|
||||
|
||||
//Where the center of the (mine's) world is
|
||||
vector Mine_origin = {TERRAIN_WIDTH*(TERRAIN_SIZE/2), -100, TERRAIN_DEPTH*(TERRAIN_SIZE/2)};
|
||||
|
||||
//Create a default room for a new mine
|
||||
room *CreateDefaultRoom()
|
||||
{
|
||||
room *rp;
|
||||
int i;
|
||||
|
||||
//Get a pointer to our room
|
||||
rp = CreateNewRoom(16,10,0); //16 verts, 10 faces, normal room
|
||||
ASSERT(rp != NULL);
|
||||
|
||||
//Set the vertices for the room
|
||||
for (i=0;i<16;i++)
|
||||
rp->verts[i] = default_room_verts[i] + Mine_origin;
|
||||
|
||||
//Set the faces for the room
|
||||
InitRoomFace(&rp->faces[0],8);
|
||||
for (i=0;i<8;i++)
|
||||
rp->faces[0].face_verts[i] = i;
|
||||
|
||||
InitRoomFace(&rp->faces[1],8);
|
||||
for (i=0;i<8;i++)
|
||||
rp->faces[1].face_verts[i] = 15-i;
|
||||
|
||||
for (i=0;i<8;i++) {
|
||||
InitRoomFace(&rp->faces[i+2],4);
|
||||
rp->faces[i+2].face_verts[0] = i;
|
||||
rp->faces[i+2].face_verts[1] = i+8;
|
||||
rp->faces[i+2].face_verts[2] = ((i+1)%8)+8;
|
||||
rp->faces[i+2].face_verts[3] = (i+1)%8;
|
||||
}
|
||||
|
||||
//Set normals, textures and UVLs for face
|
||||
for (i=0;i<10;i++) {
|
||||
if (! ComputeFaceNormal(rp,i))
|
||||
Int3(); //this is odd. Get Matt!
|
||||
rp->faces[i].tmap = i+1;
|
||||
AssignDefaultUVsToRoomFace(rp,i);
|
||||
}
|
||||
|
||||
return rp;
|
||||
}
|
||||
|
||||
#define DEFAULT_SCRIPT "//Empty script\xd\xa"
|
||||
|
||||
//Create a new mine with one segment
|
||||
void CreateNewMine()
|
||||
{
|
||||
//Get rid of old mine
|
||||
FreeAllRooms();
|
||||
FreeAllObjects();
|
||||
|
||||
//Create a new room
|
||||
Curroomp = CreateDefaultRoom();
|
||||
ASSERT(Curroomp != NULL);
|
||||
|
||||
//Reset misc. vars
|
||||
Curface = Curedge = Curvert = 0;
|
||||
Curportal = -1;
|
||||
|
||||
//Say that this is a new mine
|
||||
New_mine = 1;
|
||||
|
||||
//Reset the view position, etc. for the wireframe view
|
||||
ResetWireframeView();
|
||||
|
||||
//Reintialize the objects
|
||||
ResetObjectList();
|
||||
|
||||
//Create the player and put him in the center of the fa
|
||||
CreatePlayerObject(ROOMNUM(Curroomp));
|
||||
|
||||
//Initialize editor viewer
|
||||
Editor_view_mode = VM_MINE;
|
||||
Editor_viewer_id = -1;
|
||||
|
||||
//Create a camera for this level
|
||||
SetEditorViewer();
|
||||
|
||||
//Look for player objects & set player starts
|
||||
FindPlayerStarts();
|
||||
|
||||
//Clear the marked room
|
||||
Markedroomp = NULL;
|
||||
|
||||
//Clear the selected segments
|
||||
ClearRoomSelectedList();
|
||||
|
||||
//Clear the placed room & group
|
||||
Placed_room = -1;
|
||||
Placed_group = NULL;
|
||||
|
||||
//Reset the triggers
|
||||
Num_triggers = 0;
|
||||
Current_trigger = -1;
|
||||
|
||||
// Reset the terrain
|
||||
ResetTerrain(1);
|
||||
|
||||
// Reset terrain sound
|
||||
ClearTerrainSound();
|
||||
|
||||
// Clear game events
|
||||
ClearAllEvents();
|
||||
|
||||
int i;
|
||||
BOA_AABB_checksum = BOA_mine_checksum = 0;
|
||||
for(i = 0; i < MAX_ROOMS; i++)
|
||||
{
|
||||
BOA_AABB_ROOM_checksum[i] = 0;
|
||||
}
|
||||
InitGamePaths();
|
||||
DestroyAllMatcens();
|
||||
// Resets the ambient life controller
|
||||
a_life.ALReset();
|
||||
Level_goals.CleanupAfterLevel();
|
||||
|
||||
BNode_ClearBNodeInfo();
|
||||
FVI_always_check_ceiling = false;
|
||||
Ceiling_height = MAX_TERRAIN_HEIGHT;
|
||||
|
||||
sound_override_force_field = -1;
|
||||
sound_override_glass_breaking = -1;
|
||||
|
||||
for(i = 0; i < MAX_FORCE_FIELD_BOUNCE_TEXTURES; i++)
|
||||
{
|
||||
force_field_bounce_texture[i] = -1;
|
||||
force_field_bounce_multiplier[i] = 1.0f;
|
||||
}
|
||||
|
||||
Level_powerups_ignore_wind = false;
|
||||
|
||||
//Init level info
|
||||
strcpy(Level_info.name,"Unnamed");
|
||||
strcpy(Level_info.designer,"Anonymous");
|
||||
strcpy(Level_info.copyright,"Copyright (c) 1999 Outrage Entertainment, Inc.");
|
||||
strcpy(Level_info.notes,"");
|
||||
}
|
||||
|
||||
#include "osiris_predefs.h"
|
||||
|
||||
//Strips leading and trailing spaces from a string
|
||||
//Returns true if spaces were stripped
|
||||
bool StripLeadingTrailingSpaces(char *s)
|
||||
{
|
||||
char *t;
|
||||
bool stripped = 0;
|
||||
|
||||
//Look for leading spaces
|
||||
t = s;
|
||||
while (*t == ' ')
|
||||
t++;
|
||||
|
||||
//Leading spaces found, so copy string over spaces
|
||||
if (t != s) {
|
||||
strcpy(s,t);
|
||||
stripped = 1;
|
||||
}
|
||||
|
||||
//Strip any trailing spaces
|
||||
for (t = s + strlen(s) - 1;(t >= s) && (*t == ' ');t--) {
|
||||
*t = 0;
|
||||
stripped = 1;
|
||||
}
|
||||
|
||||
return stripped;
|
||||
}
|
||||
|
||||
//Check for duplicate names in the level
|
||||
void CheckLevelNames()
|
||||
{
|
||||
int i;
|
||||
|
||||
//Check objects
|
||||
object *objp;
|
||||
for (i=0,objp=Objects;i<=Highest_object_index;i++,objp++) {
|
||||
if ((objp->type != OBJ_NONE) && objp->name) {
|
||||
int handle = osipf_FindObjectName(objp->name);
|
||||
if (handle != objp->handle)
|
||||
EditorMessageBox("Error: Objects %d and %d are both named \"%s\"",i,OBJNUM(ObjGet(handle)),objp->name);
|
||||
if (StripLeadingTrailingSpaces(objp->name))
|
||||
EditorMessageBox("Note: Object %d (\"%s\") had leading and/or trailing spaces in its name that have been removed.",i,objp->name);
|
||||
}
|
||||
}
|
||||
|
||||
//Check triggers
|
||||
trigger *tp;
|
||||
for (i=0,tp=Triggers;i<Num_triggers;i++,tp++) {
|
||||
if (tp->name) {
|
||||
int n = osipf_FindTriggerName(tp->name);
|
||||
if (n != i)
|
||||
EditorMessageBox("Error: Triggers %d and %d are both named \"%s\"",i,n,tp->name);
|
||||
if (StripLeadingTrailingSpaces(tp->name))
|
||||
EditorMessageBox("Note: Trigger %d (\"%s\") had leading and/or trailing spaces in its name that have been removed.",i,tp->name);
|
||||
}
|
||||
}
|
||||
|
||||
//Check rooms
|
||||
room *rp;
|
||||
for (i=0,rp=Rooms;i<=Highest_room_index;i++,rp++) {
|
||||
if (rp->used && rp->name) {
|
||||
int n = osipf_FindRoomName(rp->name);
|
||||
if (n != i)
|
||||
EditorMessageBox("Error: Rooms %d and %d are both named \"%s\"",i,n,rp->name);
|
||||
if (StripLeadingTrailingSpaces(rp->name))
|
||||
EditorMessageBox("Note: Room %d (\"%s\") had leading and/or trailing spaces in its name that have been removed.",i,rp->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Load a new level
|
||||
bool EditorLoadLevel(char *filename)
|
||||
{
|
||||
if (LoadLevel(filename)) {
|
||||
|
||||
//Check for duplicate names in the level
|
||||
CheckLevelNames();
|
||||
|
||||
New_mine = 1; //say that this is a new mine
|
||||
|
||||
//Set viewer object
|
||||
SetEditorViewer();
|
||||
|
||||
//Reset view radius
|
||||
ResetWireframeViewRad();
|
||||
|
||||
//Done
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
//Save the current level
|
||||
//Returns 1 if level saved sucessfully
|
||||
int EditorSaveLevel(char *filename)
|
||||
{
|
||||
int sucess;
|
||||
|
||||
sucess = SaveLevel(filename);
|
||||
|
||||
if (sucess)
|
||||
Mine_changed = 0;
|
||||
|
||||
return sucess;
|
||||
}
|
||||
|
||||
//Returns a pointer to enough spaces to right-justify a number that's printed after the spaces
|
||||
char *IntSpacing(int i)
|
||||
{
|
||||
static char *spaces = " ";
|
||||
|
||||
i = abs(i);
|
||||
|
||||
for (int n=1;i >= 10;n++)
|
||||
i /= 10;
|
||||
|
||||
ASSERT(n <= 20);
|
||||
|
||||
return spaces+n*2+n/2;
|
||||
}
|
||||
|
||||
extern void dump_text_to_clipboard(char *text);
|
||||
|
||||
//Shows the stats for a level in a messagebox, and copies to the clipboard
|
||||
void ShowLevelStats()
|
||||
{
|
||||
int n_rooms,n_rooms_external,n_faces,n_verts,n_objects,n_portals,n_doors,n_objects_outside;
|
||||
int n_object_faces,n_object_lightmap_faces;
|
||||
int i;
|
||||
room *rp;
|
||||
int bytes_wasted=0,spec_faces=0,lm_bytes=0;
|
||||
int total_volume_bytes=0;
|
||||
int num_redgoals=0,num_bluegoals=0,num_greengoals=0,num_yellowgoals=0;
|
||||
int num_sp1=0,num_sp2=0,num_sp3=0,num_sp4=0,num_sp5=0,num_sp6=0;
|
||||
|
||||
uint8_t lightmaps_used[MAX_LIGHTMAPS];
|
||||
|
||||
object *objp;
|
||||
#define BUF_LEN 5000
|
||||
char text_buf[BUF_LEN];
|
||||
|
||||
//Count the number of rooms, and the number of faces & points per room
|
||||
n_rooms = n_rooms_external = n_faces = n_verts = n_doors = n_portals = 0;
|
||||
for (i=0,rp=Rooms;i<=Highest_room_index;i++,rp++)
|
||||
if (rp->used) {
|
||||
n_rooms++;
|
||||
n_verts += rp->num_verts;
|
||||
n_faces += rp->num_faces;
|
||||
n_portals += rp->num_portals;
|
||||
if (rp->flags & RF_EXTERNAL)
|
||||
n_rooms_external++;
|
||||
else
|
||||
{
|
||||
// Get volume size of room
|
||||
total_volume_bytes+=GetVolumeSizeOfRoom (rp);
|
||||
}
|
||||
|
||||
for (int t=0;t<rp->num_faces;t++)
|
||||
{
|
||||
face *fp=&rp->faces[t];
|
||||
if (fp->special_handle!=BAD_SPECIAL_FACE_INDEX && GameTextures[fp->tmap].flags & TF_SPECULAR && fp->lmi_handle!=BAD_LMI_INDEX)
|
||||
spec_faces++;
|
||||
}
|
||||
|
||||
if (rp->flags & RF_DOOR)
|
||||
n_doors++;
|
||||
|
||||
if (rp->flags & RF_SPECIAL1)
|
||||
num_sp1++;
|
||||
|
||||
if (rp->flags & RF_SPECIAL2)
|
||||
num_sp2++;
|
||||
|
||||
if (rp->flags & RF_SPECIAL3)
|
||||
num_sp3++;
|
||||
|
||||
if (rp->flags & RF_SPECIAL4)
|
||||
num_sp4++;
|
||||
|
||||
if (rp->flags & RF_SPECIAL5)
|
||||
num_sp5++;
|
||||
|
||||
if (rp->flags & RF_SPECIAL6)
|
||||
num_sp6++;
|
||||
|
||||
if (rp->flags & RF_GOAL1)
|
||||
num_redgoals++;
|
||||
|
||||
if (rp->flags & RF_GOAL2)
|
||||
num_bluegoals++;
|
||||
|
||||
if (rp->flags & RF_GOAL3)
|
||||
num_greengoals++;
|
||||
|
||||
if (rp->flags & RF_GOAL4)
|
||||
num_yellowgoals++;
|
||||
|
||||
}
|
||||
|
||||
//Count the number of objects
|
||||
n_objects = n_object_faces = n_object_lightmap_faces = n_objects_outside = 0;
|
||||
for (i=0,objp=Objects;i<=Highest_object_index;i++,objp++)
|
||||
if ((objp->type != OBJ_NONE) && (objp->type != OBJ_ROOM) && (objp->render_type == RT_POLYOBJ)) {
|
||||
n_objects++;
|
||||
if (OBJECT_OUTSIDE(objp))
|
||||
n_objects_outside++;
|
||||
//Count the number of faces in this object
|
||||
poly_model *pm;
|
||||
pm = GetPolymodelPointer(objp->rtype.pobj_info.model_num);
|
||||
for (int m=0;m<pm->n_models;m++) {
|
||||
n_object_faces += pm->submodel[m].num_faces;
|
||||
if (objp->lighting_render_type == LRT_LIGHTMAPS)
|
||||
n_object_lightmap_faces += pm->submodel[m].num_faces;
|
||||
}
|
||||
}
|
||||
|
||||
memset (lightmaps_used,0,MAX_LIGHTMAPS);
|
||||
for (i=0;i<MAX_LIGHTMAP_INFOS;i++)
|
||||
{
|
||||
if (!LightmapInfo[i].used)
|
||||
continue;
|
||||
if (LightmapInfo[i].type==LMI_DYNAMIC || LightmapInfo[i].type==LMI_TERRAIN)
|
||||
continue;
|
||||
|
||||
lightmaps_used[LightmapInfo[i].lm_handle]=1;
|
||||
}
|
||||
|
||||
for (i=0;i<MAX_LIGHTMAPS;i++)
|
||||
{
|
||||
if (lightmaps_used[i])
|
||||
{
|
||||
uint16_t *data=lm_data (i);
|
||||
int w=lm_w(i);
|
||||
int h=lm_h(i);
|
||||
|
||||
for (int j=0;j<w*h;j++)
|
||||
{
|
||||
if (!(data[j] & OPAQUE_FLAG))
|
||||
{
|
||||
bytes_wasted+=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
lm_bytes+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
i = sprintf(text_buf,
|
||||
"Level Stats:\n"
|
||||
"\n"
|
||||
"%s%d Rooms (%d external)\n"
|
||||
"%s%d Faces\n"
|
||||
"%s%d Vertices\n"
|
||||
"\n"
|
||||
"%s%d Portals\n"
|
||||
"%s%d Doors\n"
|
||||
"\n"
|
||||
"%s%d Polygon Objects (%d inside, %d outside)\n"
|
||||
"%s%d Object Faces (%d with lightmaps)\n"
|
||||
"\n"
|
||||
"%s%d Total lightmap faces\n"
|
||||
"%d Total volume bytes\n"
|
||||
"%d Total bytes in lightmaps\n"
|
||||
"%d Total specular faces\n"
|
||||
"%d Bytes wasted in lightmaps\n"
|
||||
"\n"
|
||||
"%d Red Goals\n"
|
||||
"%d Blue Goals\n"
|
||||
"%d Green Goals\n"
|
||||
"%d Yellow Goals\n"
|
||||
"%d Special 1 Rooms\n"
|
||||
"%d Special 2 Rooms\n"
|
||||
"%d Special 3 Rooms\n"
|
||||
"%d Special 4 Rooms\n"
|
||||
"%d Special 5 Rooms\n"
|
||||
"%d Special 6 Rooms\n"
|
||||
,IntSpacing(n_rooms),n_rooms,n_rooms_external,IntSpacing(n_faces),n_faces,IntSpacing(n_verts),n_verts
|
||||
,IntSpacing(n_portals/2),n_portals/2,IntSpacing(n_doors),n_doors,IntSpacing(n_objects),n_objects
|
||||
,n_objects-n_objects_outside,n_objects_outside,IntSpacing(n_object_faces),n_object_faces,n_object_lightmap_faces
|
||||
,IntSpacing(n_faces+n_object_lightmap_faces),n_faces+n_object_lightmap_faces
|
||||
,total_volume_bytes
|
||||
,lm_bytes
|
||||
,spec_faces
|
||||
,bytes_wasted
|
||||
,num_redgoals
|
||||
,num_bluegoals
|
||||
,num_greengoals
|
||||
,num_yellowgoals
|
||||
,num_sp1
|
||||
,num_sp2
|
||||
,num_sp3
|
||||
,num_sp4
|
||||
,num_sp5
|
||||
,num_sp6
|
||||
);
|
||||
|
||||
ASSERT(i < BUF_LEN);
|
||||
|
||||
dump_text_to_clipboard(text_buf);
|
||||
OutrageMessageBox("%s\n\nThis info has also been posted to the clipboard.\n\nWhat other info would you like here? Let MattT know.",text_buf);
|
||||
}
|
||||
Reference in New Issue
Block a user