mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
a23c6a42a3
``` git grep -l mem_malloc | xargs perl -i -lpe 's{\((char) \*\)mem_malloc\((\S+)\)}{mem_rmalloc<$1>($2)}' ```
1465 lines
43 KiB
C++
1465 lines
43 KiB
C++
/*
|
|
* 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/editorView.cpp $
|
|
* $Revision: 1.1.1.1 $
|
|
* $Date: 2003-08-26 03:57:37 $
|
|
* $Author: kevinb $
|
|
*
|
|
* Main Editor View which contains the different views of the mine
|
|
*
|
|
* $Log: not supported by cvs2svn $
|
|
*
|
|
* 72 10/14/99 4:21p Matt
|
|
* Added code to remove duplicate faces from a room.
|
|
*
|
|
* 71 10/07/99 3:12p Matt
|
|
* Added a function to flip the view 180 degrees.
|
|
*
|
|
* 70 9/15/99 1:55p Matt
|
|
* Added the option to allow rooms or groups placed on the terrain to
|
|
* either align with the terrain or with gravity.
|
|
*
|
|
* 69 9/07/99 12:10p Matt
|
|
* Added a function to propagate a texture to all adjacent coplanar faces
|
|
* in a room.
|
|
*
|
|
* 68 8/24/99 4:24p Matt
|
|
* Added a function to rotate a placed room by 45 degrees.
|
|
*
|
|
* 67 5/08/99 6:39p Matt
|
|
* Added a function to delete a face and all faces connected to it.
|
|
*
|
|
* 66 5/08/99 1:38a Matt
|
|
* Fixed typo.
|
|
*
|
|
* 65 4/30/99 6:52p Matt
|
|
* Added a function to merge an object's geometry into a room.
|
|
*
|
|
* 64 4/28/99 12:51a Matt
|
|
* Added some funtions to edit face geometry.
|
|
*
|
|
* 63 4/19/99 12:10a Matt
|
|
* Added a menu item to delete a vertex from a face.
|
|
*
|
|
* 62 4/06/99 10:23a Matt
|
|
*
|
|
* 61 3/31/99 12:58p Matt
|
|
* Added snap-point-to-face
|
|
*
|
|
* 60 3/29/99 6:46p Matt
|
|
* Added menu item to fix/remove degenerate faces
|
|
*
|
|
* 59 3/27/99 7:10p Matt
|
|
* Strip leading & trailing spaces before check for duplicate names.
|
|
*
|
|
* 58 3/23/99 11:15p Matt
|
|
* Added message when rooms combined.
|
|
*
|
|
* 57 3/23/99 5:12p Matt
|
|
* Added function to combine rooms.
|
|
*
|
|
* 56 3/01/99 10:39p Matt
|
|
* Added menu options to set & clear room center points
|
|
*
|
|
* 55 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.
|
|
*
|
|
* 54 2/28/99 10:40p Matt
|
|
* Check for name already in use when entering a name.
|
|
*
|
|
* 53 2/28/99 6:31p Matt
|
|
* Disable z-buffer button if OpenGL is being used in the editor.
|
|
*
|
|
* 52 2/03/99 1:10p Matt
|
|
* Changed the paletted room current faces to be stored in a separate
|
|
* array, instead of in the room structure.
|
|
*
|
|
* 51 1/25/99 11:12a Matt
|
|
* If the marked face is deleted, reset it.
|
|
*
|
|
* 50 1/21/99 11:15p Jeff
|
|
* pulled out some structs and defines from header files and moved them
|
|
* into separate 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
|
|
*
|
|
* 49 1/15/99 10:50a Matt
|
|
* Added rename room to Room menu & added shortcut key
|
|
*
|
|
* 48 12/30/98 6:49p Matt
|
|
* When un-placing a door, free the room that the placed door was using
|
|
*
|
|
* 47 12/23/98 10:53a Matt
|
|
* Added functions to create a face
|
|
*
|
|
* 46 10/05/98 9:45a Matt
|
|
* Use windows function to get cursor position instead of ddio function.
|
|
*
|
|
* 45 10/03/98 11:21p Matt
|
|
* Added system to separately control outline mode for mine, terrain, sky,
|
|
* & objects
|
|
*
|
|
* 44 10/03/98 8:31p Matt
|
|
* Added Join Rooms Exact function.
|
|
*
|
|
* 43 9/18/98 1:27p Jason
|
|
* cleaned up renderer initting
|
|
*
|
|
* 42 9/09/98 4:07p Matt
|
|
* Added Smooth Bridge function
|
|
*
|
|
* 41 9/08/98 6:12p Matt
|
|
* Added code to check for and fix duplicate and unused points.
|
|
*
|
|
* 40 9/08/98 12:06p Jason
|
|
* added ReInit openGL button
|
|
*
|
|
* 39 9/07/98 10:58p Matt
|
|
* Added snap point to point.
|
|
*
|
|
* 38 9/04/98 3:34p Matt
|
|
* Added groovy vertex snap code
|
|
*
|
|
* 37 9/04/98 12:29p Matt
|
|
* Added marked edge & vertex in the editor
|
|
*
|
|
* 36 8/31/98 4:36p Matt
|
|
* Added status message
|
|
*
|
|
* 35 6/25/98 7:15p Matt
|
|
* Added a function to delete a pair of portals.
|
|
*
|
|
* 34 6/23/98 2:45p Matt
|
|
* Added option when propagating to all faces in a room to only do so to
|
|
* ones with the same texture.
|
|
*
|
|
* 33 6/08/98 12:28p Matt
|
|
* Added a function to triangulate a face
|
|
*
|
|
* 32 5/22/98 4:47p Matt
|
|
* Added menu item to propagate a texture to all the faces in a room.
|
|
*
|
|
* 31 4/27/98 6:41p Matt
|
|
* Added code to join all adjacent faces between two rooms
|
|
*
|
|
* 30 4/16/98 11:50a Matt
|
|
* Made snap code work for placed groups.
|
|
*
|
|
* 29 2/16/98 1:27p Matt
|
|
* Added function to snap the placed room to a vertex/edge on the base
|
|
* room/face
|
|
*
|
|
* 28 2/11/98 12:39p Matt
|
|
* Implemented Delete Face menu item.
|
|
*
|
|
* 27 1/29/98 2:15p Samir
|
|
* Implemented ObjectListModeless and Toolbar button.
|
|
*
|
|
* 26 1/27/98 6:15p Samir
|
|
* Added Object toolbar button.
|
|
*
|
|
* 25 1/20/98 4:08p Matt
|
|
* Added function to swap current and marked room:face. Added some
|
|
* addition error checking to bridge function.
|
|
*
|
|
* 24 1/06/98 12:39p Matt
|
|
* Added some error checking
|
|
*
|
|
* 23 11/05/97 7:13p Matt
|
|
* Added join rooms function
|
|
*
|
|
* 22 10/03/97 3:37p Matt
|
|
* Added menu item to place a building on the terrain
|
|
*
|
|
* 21 9/24/97 3:22p Matt
|
|
* Added Drop Room function
|
|
*
|
|
* 20 9/17/97 1:24p Matt
|
|
* Ripped out segment code
|
|
*
|
|
* 19 9/17/97 11:21a Matt
|
|
* Ripped out segment code
|
|
*
|
|
* 18 9/16/97 4:09p Jason
|
|
* implemented software zbuffer
|
|
*
|
|
* 17 9/14/97 11:06p Matt
|
|
* Fixed up Room menu
|
|
*
|
|
* 16 9/11/97 5:46p Jason
|
|
* first pass at getting doors to work with room engine
|
|
*
|
|
* 15 8/29/97 3:37p Samir
|
|
* Took out segment tab constant.
|
|
*
|
|
* 14 8/22/97 9:32a Matt
|
|
* Don't allow place room to a face that already has a room on it.
|
|
*
|
|
* 13 8/21/97 6:00p Matt
|
|
* Added delete current room function
|
|
*
|
|
* 12 8/19/97 5:58p Samir
|
|
* OLE additions
|
|
*
|
|
* 11 8/19/97 10:54a Matt
|
|
* Added remove placed room option
|
|
*
|
|
* 10 8/18/97 6:59p Matt
|
|
* Implemented Place Room/Attach room system
|
|
*
|
|
* 9 8/04/97 12:52p Matt
|
|
* Added hooks for mark & bridge
|
|
*
|
|
* 8 8/01/97 6:10p Matt
|
|
* Added hooks for attach room
|
|
*
|
|
* 7 7/28/97 11:29a Samir
|
|
* Fixed editor->game goofiness. Isolated GrWnd creation and destruction
|
|
* to a couple of functions.
|
|
*
|
|
* 6 7/25/97 6:16p Samir
|
|
* Fixed the tile-cascade switching/default madness.
|
|
*
|
|
* 5 7/22/97 7:07p Matt
|
|
* Cleaned up D3EditState, moving some vars in and some out, and renaming
|
|
* and changing a few others
|
|
*
|
|
* 4 7/22/97 10:33a Matt
|
|
* Added functions for new room menu
|
|
*
|
|
* 29 6/30/97 1:29p Jason
|
|
* added netherspace stuff
|
|
*
|
|
* 28 6/03/97 4:55p Mark
|
|
*
|
|
* 28 6/3/97 4:38p Jeff
|
|
* Added Context Sensitive Help for Keypads
|
|
*
|
|
* 27 5/27/97 3:30p Matt
|
|
* Added editor button to toggle lighting
|
|
*
|
|
* 26 5/08/97 7:29p Matt
|
|
* Made separate viewers for mine & terrain, and cleaned up code the
|
|
* switched between modes
|
|
*
|
|
* 25 5/06/97 3:49p Matt
|
|
* Unlink/relink viewer object when switching between mine and terrain
|
|
* views
|
|
*
|
|
* 24 5/06/97 1:17p Jason
|
|
* checked in for matt
|
|
*
|
|
* 23 4/03/97 1:17p Matt
|
|
* Took out support for toolbar movement mode toggle button, now that that
|
|
* function has been moved to the object keypad.
|
|
*
|
|
* 22 4/02/97 8:07p Matt
|
|
* Added variable & button to toggle object move state
|
|
*
|
|
* 21 3/31/97 5:57p Matt
|
|
* Revamped mine update flags
|
|
*
|
|
* 20 3/21/97 5:02p Jason
|
|
* make player_object switch the OF_OVER_TERRAIN flag to on when changing
|
|
* to terrain view...temporary
|
|
*
|
|
* 19 3/17/97 7:41p Samir
|
|
* Fixed editor interface problems with updating triggers and doorways in
|
|
* keypads when loading new levels (must fix some more).
|
|
*
|
|
* 18 3/13/97 6:12p Jason
|
|
* set default height above terrain
|
|
*
|
|
* 17 3/07/97 4:54p Jason
|
|
* made editor save position of terrain/mine when switching between modes
|
|
*
|
|
*
|
|
* 16 3/07/97 4:18p Jason
|
|
* implemented terrain functionality in the editor
|
|
*
|
|
* 15 2/28/97 6:37p Matt
|
|
* Added variable & toggle button for box selection mode
|
|
*
|
|
* 14 2/20/97 1:30p Samir
|
|
* Defined main_view.
|
|
*
|
|
* 13 2/11/97 1:42p Samir
|
|
* Moved file opening and closing to editorDoc where it should be.
|
|
*
|
|
* 12 2/10/97 5:40p Matt
|
|
* Code to handle several File menu options
|
|
*
|
|
* 11 2/07/97 7:41p Matt
|
|
* Hooked in next & prev segment & side funcs
|
|
*
|
|
* 10 1/23/97 4:09p Samir
|
|
* Added stuff for toggling wireframe, texture windows, tiling or
|
|
* cascading
|
|
*
|
|
* 9 1/21/97 12:51p Samir
|
|
* GrWnds created based on D3EditState info
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "editor.h"
|
|
|
|
#include "editorDoc.h"
|
|
#include "editorView.h"
|
|
#include "MainFrm.h"
|
|
#include "TextureDialog.h"
|
|
#include "EditLineDialog.h"
|
|
#include "RoomKeypadDialog.h"
|
|
#include "game.h"
|
|
|
|
#include "d3edit.h"
|
|
#include "mono.h"
|
|
|
|
#include "render.h"
|
|
#include "HRoom.h"
|
|
#include "HFile.h"
|
|
#include "erooms.h"
|
|
#include "args.h"
|
|
|
|
#include "terrain.h"
|
|
|
|
#include "mem.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CEditorView
|
|
|
|
IMPLEMENT_DYNCREATE(CEditorView, CView)
|
|
|
|
BEGIN_MESSAGE_MAP(CEditorView, CView)
|
|
//{{AFX_MSG_MAP(CEditorView)
|
|
ON_WM_SIZE()
|
|
ON_WM_DESTROY()
|
|
ON_COMMAND(ID_BUTTON_OUTLINE, OnButtonOutline)
|
|
ON_UPDATE_COMMAND_UI(ID_BUTTON_OUTLINE, OnUpdateButtonOutline)
|
|
ON_UPDATE_COMMAND_UI(ID_VIEW_TEXTUREMINE, OnUpdateViewTexturemine)
|
|
ON_COMMAND(ID_VIEW_TEXTUREMINE, OnViewTexturemine)
|
|
ON_UPDATE_COMMAND_UI(ID_VIEW_WIREFRAMEMINE, OnUpdateViewWireframemine)
|
|
ON_COMMAND(ID_VIEW_WIREFRAMEMINE, OnViewWireframemine)
|
|
ON_WM_PARENTNOTIFY()
|
|
ON_COMMAND(ID_WINDOW_TILE, OnWindowTile)
|
|
ON_COMMAND(ID_WINDOW_CASCADE, OnWindowCascade)
|
|
ON_COMMAND(ID_BUTTON_WINDOWSELECTION, OnButtonWindowSelection)
|
|
ON_UPDATE_COMMAND_UI(ID_BUTTON_WINDOWSELECTION, OnUpdateButtonWindowSelection)
|
|
ON_COMMAND(ID_BUTTON_LIGHTING, OnButtonLighting)
|
|
ON_UPDATE_COMMAND_UI(ID_BUTTON_LIGHTING, OnUpdateButtonLighting)
|
|
ON_WM_HELPINFO()
|
|
ON_COMMAND(ID_ROOM_ADD, OnRoomAdd)
|
|
ON_COMMAND(ID_ROOM_GRABTEXTURE, OnRoomGrabTexture)
|
|
ON_COMMAND(ID_ROOM_NEXTFACE, OnRoomNextFace)
|
|
ON_COMMAND(ID_ROOM_PREVIOUSFACE, OnRoomPreviousFace)
|
|
ON_COMMAND(ID_ROOM_SELECTBYNUMBER, OnRoomSelectByNumber)
|
|
ON_COMMAND(ID_ROOM_ATTACHROOM, OnRoomAttachRoom)
|
|
ON_COMMAND(ID_ROOM_BUILDBRIDGE, OnRoomBuildBridge)
|
|
ON_COMMAND(ID_ROOM_MARK, OnRoomMark)
|
|
ON_COMMAND(ID_ROOM_PLACEROOM, OnRoomPlaceRoom)
|
|
ON_UPDATE_COMMAND_UI(ID_ROOM_ATTACHROOM, OnUpdateRoomAttachRoom)
|
|
ON_COMMAND(ID_ROOM_UNPLACEROOM, OnRoomUnPlaceRoom)
|
|
ON_UPDATE_COMMAND_UI(ID_ROOM_UNPLACEROOM, OnUpdateRoomUnPlaceRoom)
|
|
ON_COMMAND(ID_ROOM_DELETE, OnRoomDelete)
|
|
ON_COMMAND(ID_ROOM_SELECTFACEBYNUMBER, OnRoomSelectFaceByNumber)
|
|
ON_COMMAND(ID_ROOM_SAVECURRENTROOM, OnRoomSaveCurrentRoom)
|
|
ON_COMMAND(ID_ZBUTTON, OnZbutton)
|
|
ON_UPDATE_COMMAND_UI(ID_ZBUTTON, OnUpdateZbutton)
|
|
ON_COMMAND(ID_ROOM_DROPROOM, OnRoomDropRoom)
|
|
ON_COMMAND(ID_ROOM_PLACETERRAINROOM, OnRoomPlaceTerrainRoom)
|
|
ON_COMMAND(ID_ROOM_JOINROOMS, OnRoomJoinRooms)
|
|
ON_COMMAND(ID_ROOM_SWAPMAKEDANDCURRENTROOMFACE, OnRoomSwapMarkedAndCurrentRoomFace)
|
|
ON_COMMAND(ID_ROOM_DELETEFACE, OnRoomDeleteFace)
|
|
ON_COMMAND(ID_ROOM_SNAPPLACEDROOM, OnRoomSnapPlacedRoom)
|
|
ON_UPDATE_COMMAND_UI(ID_ROOM_SNAPPLACEDROOM, OnUpdateRoomSnapPlacedRoom)
|
|
ON_COMMAND(ID_ROOM_JOIN_ADJACENT_FACES, OnRoomJoinAdjacentFaces)
|
|
ON_COMMAND(ID_ROOM_PROPAGATETOALL, OnRoomPropagateToAll)
|
|
ON_COMMAND(ID_ROOM_SPLITFACE, OnRoomSplitFace)
|
|
ON_COMMAND(ID_ROOM_DELETEPORTAL, OnRoomDeletePortal)
|
|
ON_COMMAND(ID_ROOM_SNAPPOINTTOEDGE, OnRoomSnapPointToEdge)
|
|
ON_COMMAND(ID_ROOM_UNDOSNAP, OnRoomUndoSnap)
|
|
ON_UPDATE_COMMAND_UI(ID_ROOM_UNDOSNAP, OnUpdateRoomUndoSnap)
|
|
ON_COMMAND(ID_ROOM_SNAPPOINTTOPOINT, OnRoomSnapPointToPoint)
|
|
ON_COMMAND(ID_REINIT_OPENGL, OnReinitOpengl)
|
|
ON_UPDATE_COMMAND_UI(ID_REINIT_OPENGL, OnUpdateReinitOpengl)
|
|
ON_COMMAND(ID_FILE_REMOVEEXTRAPOINTS, OnFileRemoveExtraPoints)
|
|
ON_COMMAND(ID_ROOM_BUILDSMOOTHBRIDGE, OnRoomBuildSmoothBridge)
|
|
ON_COMMAND(ID_ROOM_JOINROOMSEXACT, OnRoomJoinRoomsExact)
|
|
ON_COMMAND(ID_ROOM_STARTNEWFACE, OnRoomStartNewFace)
|
|
ON_COMMAND(ID_ROOM_FINISHNEWFACE, OnRoomFinishNewFace)
|
|
ON_COMMAND(ID_ROOM_ADDVERTTONEWFACE, OnRoomAddVertToNewFace)
|
|
ON_COMMAND(ID_ROOM_RENAMEROOM, OnRoomRenameRoom)
|
|
ON_COMMAND(ID_ROOM_SETCENTERFROMVIEWER, OnRoomSetCenterFromViewer)
|
|
ON_COMMAND(ID_ROOM_CLEARCENTERPOINT, OnRoomClearCenterPoint)
|
|
ON_UPDATE_COMMAND_UI(ID_ROOM_CLEARCENTERPOINT, OnUpdateRoomClearCenterPoint)
|
|
ON_UPDATE_COMMAND_UI(ID_ROOM_SETCENTERFROMVIEWER, OnUpdateRoomSetCenterFromViewer)
|
|
ON_COMMAND(ID_ROOM_COMBINE, OnRoomCombine)
|
|
ON_COMMAND(ID_FILE_FIXDEGENERATEFACES, OnFileFixDegenerateFaces)
|
|
ON_COMMAND(ID_ROOM_SNAPPOINTTOFACE, OnRoomSnapPointToFace)
|
|
ON_COMMAND(ID_ROOM_LINKTONEWEXTERNAL, OnRoomLinkToNewExternal)
|
|
ON_COMMAND(ID_ROOM_DELETEVERT, OnRoomDeleteVert)
|
|
ON_COMMAND(ID_ROOM_FACE_ADDVERTTOEDGE, OnRoomFaceAddVertToEdge)
|
|
ON_COMMAND(ID_ROOM_FACE_MOVEVERTONEDGE, OnRoomFaceMoveVertOnEdge)
|
|
ON_COMMAND(ID_ROOM_FACE_SPLITFACE, OnRoomFaceSplitFace)
|
|
ON_COMMAND(ID_ROOM_FACE_DELETEVERTONEDGE, OnRoomFaceDeleteVertOnEdge)
|
|
ON_COMMAND(ID_ROOM_MERGEOBJECTINTOROOM, OnRoomMergeObjectIntoRoom)
|
|
ON_COMMAND(ID_ROOM_DELETECONNECTEDFACES, OnRoomDeleteConnectedFaces)
|
|
ON_COMMAND(ID_ROOM_ROTATEPLACEDROOM45DEGREES, OnRoomRotatePlacedRoom45Degrees)
|
|
ON_COMMAND(ID_ROOM_PROPAGATETOADJACENTCOPLANARFACES, OnRoomPropagateToAdjacentCoplanarFaces)
|
|
ON_COMMAND(ID_VIEW_FLIP, OnViewFlip)
|
|
ON_COMMAND(ID_FILE_REMOVEDUPLICATEFACESFROMCURRENTROOM, OnFileRemoveDuplicateFacesFromCurrentRoom)
|
|
//}}AFX_MSG_MAP
|
|
// Standard printing commands
|
|
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
|
|
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
|
|
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
|
|
|
|
END_MESSAGE_MAP()
|
|
|
|
// ON_COMMAND(ID_FILE_SAVE, OnFileSave)
|
|
// ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CEditorView construction/destruction
|
|
|
|
CEditorView::CEditorView() {
|
|
// TODO: add construction code here
|
|
m_grwndCreated = FALSE;
|
|
m_grwndActive = FALSE;
|
|
}
|
|
|
|
CEditorView::~CEditorView() {}
|
|
|
|
BOOL CEditorView::PreCreateWindow(CREATESTRUCT &cs) {
|
|
// TODO: Modify the Window class or styles here by modifying
|
|
// the CREATESTRUCT cs
|
|
|
|
m_grwndActive = TRUE; // This should be moved to OnCreate or something like it
|
|
|
|
return CView::PreCreateWindow(cs);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CEditorView printing
|
|
|
|
BOOL CEditorView::OnPreparePrinting(CPrintInfo *pInfo) {
|
|
// default preparation
|
|
return DoPreparePrinting(pInfo);
|
|
}
|
|
|
|
void CEditorView::OnBeginPrinting(CDC * /*pDC*/, CPrintInfo * /*pInfo*/) {
|
|
// TODO: add extra initialization before printing
|
|
}
|
|
|
|
void CEditorView::OnEndPrinting(CDC * /*pDC*/, CPrintInfo * /*pInfo*/) {
|
|
// TODO: add cleanup after printing
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// OLE Server support
|
|
|
|
// The following command handler provides the standard keyboard
|
|
// user interface to cancel an in-place editing session. Here,
|
|
// the server (not the container) causes the deactivation.
|
|
void CEditorView::OnCancelEditSrvr() { GetDocument()->OnDeactivateUI(FALSE); }
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CEditorView drawing
|
|
|
|
void CEditorView::OnDraw(CDC *pDC) {
|
|
CEditorDoc *pDoc = GetDocument();
|
|
ASSERT_VALID(pDoc);
|
|
|
|
// TODO: add draw code for native data here
|
|
if (!theApp.paused()) {
|
|
if (theApp.wireframe_view)
|
|
m_grwndWireframe.Render();
|
|
if (theApp.textured_view)
|
|
m_grwndTexture.Render();
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CEditorView diagnostics
|
|
|
|
#ifdef _DEBUG
|
|
void CEditorView::AssertValid() const { CView::AssertValid(); }
|
|
|
|
void CEditorView::Dump(CDumpContext &dc) const { CView::Dump(dc); }
|
|
|
|
CEditorDoc *CEditorView::GetDocument() // non-debug version is inline
|
|
{
|
|
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CEditorDoc)));
|
|
return (CEditorDoc *)m_pDocument;
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CEditorView message handlers
|
|
|
|
void CEditorView::OnInitialUpdate() {
|
|
CView::OnInitialUpdate();
|
|
|
|
// TODO: Add your specialized code here and/or call the base class
|
|
theApp.main_view = this;
|
|
|
|
CWnd *wnd = GetParent();
|
|
|
|
wnd->Invalidate(FALSE);
|
|
|
|
mprintf(0, "CEditorView::OnInitialUpdate.\n");
|
|
}
|
|
|
|
void CEditorView::OnSize(UINT nType, int cx, int cy) {
|
|
CView::OnSize(nType, cx, cy);
|
|
|
|
// TODO: Add your message handler code here
|
|
// ReCreate wireframe and texture screen/windows
|
|
if (!m_grwndActive)
|
|
return;
|
|
|
|
KillChildViews();
|
|
|
|
if (cx && cy) {
|
|
CreateChildViews();
|
|
}
|
|
}
|
|
|
|
void CEditorView::OnDestroy() {
|
|
theApp.main_view = NULL;
|
|
CView::OnDestroy();
|
|
}
|
|
|
|
void CEditorView::DeactivateView() {
|
|
KillChildViews();
|
|
m_grwndActive = FALSE; // Tell system that this view should not function
|
|
}
|
|
|
|
void CEditorView::ActivateView() {
|
|
CreateChildViews();
|
|
m_grwndActive = TRUE; // This view is active and functional
|
|
}
|
|
|
|
/* Since this code is shared by a couple of functions, and is critical that the code
|
|
is the same for both functions, I place all the code here.
|
|
*/
|
|
void CEditorView::KillChildViews() {
|
|
if (m_grwndCreated) {
|
|
if (theApp.wireframe_view)
|
|
m_grwndWireframe.DestroyWindow();
|
|
if (theApp.textured_view)
|
|
m_grwndTexture.DestroyWindow();
|
|
m_grwndCreated = FALSE;
|
|
}
|
|
}
|
|
|
|
void CEditorView::CreateChildViews() {
|
|
RECT view_rect, wire_rect, texture_rect;
|
|
|
|
if (m_grwndCreated)
|
|
return;
|
|
|
|
GetClientRect(&view_rect);
|
|
SetRect(&texture_rect, 0, 0, 0, 0);
|
|
|
|
// if we tile windows, then texture window will be reset to default width, height
|
|
// wireframe window will be sized depending on the existance of the texture view.
|
|
if (D3EditState.texscr_visible) {
|
|
if (D3EditState.tile_views)
|
|
SetRect(&texture_rect, view_rect.left, view_rect.top, view_rect.left + CALC_PIXELS_WITH_ASPECTX(TEXSCREEN_WIDTH),
|
|
view_rect.top + CALC_PIXELS_WITH_ASPECTY(TEXSCREEN_HEIGHT));
|
|
else
|
|
SetRect(&texture_rect, D3EditState.texscr_x, D3EditState.texscr_y, D3EditState.texscr_x + D3EditState.texscr_w,
|
|
D3EditState.texscr_y + D3EditState.texscr_h);
|
|
m_grwndTexture.Create(texture_rect, !D3EditState.tile_views, this);
|
|
}
|
|
|
|
if (D3EditState.wirescr_visible) {
|
|
if (D3EditState.tile_views)
|
|
SetRect(&wire_rect, view_rect.left, view_rect.top + texture_rect.bottom + 2, view_rect.right, view_rect.bottom);
|
|
else
|
|
SetRect(&wire_rect, D3EditState.wirescr_x, D3EditState.wirescr_y, D3EditState.wirescr_x + D3EditState.wirescr_w,
|
|
D3EditState.wirescr_y + D3EditState.wirescr_h);
|
|
m_grwndWireframe.Create(wire_rect, !D3EditState.tile_views, this);
|
|
}
|
|
|
|
m_grwndCreated = TRUE;
|
|
}
|
|
|
|
#include "ddio.h"
|
|
|
|
void CEditorView::OnButtonOutline() {
|
|
CMenu popup;
|
|
|
|
if (popup.CreatePopupMenu())
|
|
if (!SetupPopup(&popup))
|
|
Int3();
|
|
|
|
POINT pnt;
|
|
GetCursorPos(&pnt);
|
|
|
|
if (!popup.TrackPopupMenu(TPM_LEFTALIGN, pnt.x - 20, pnt.y - 10, this, NULL))
|
|
mprintf(0, "TrackPopupMenu error!\n");
|
|
|
|
// Outline_mode ^= OM_ON;
|
|
// EditorStatus("Outline mode turned %s",OUTLINE_ON(0)?"ON":"OFF");
|
|
// State_changed = 1;
|
|
}
|
|
|
|
void CEditorView::OnUpdateButtonOutline(CCmdUI *pCmdUI) { pCmdUI->SetCheck(OUTLINE_ON(0)); }
|
|
|
|
void CEditorView::OnUpdateViewTexturemine(CCmdUI *pCmdUI) { pCmdUI->SetCheck(D3EditState.texscr_visible); }
|
|
|
|
void CEditorView::OnViewTexturemine() {
|
|
RECT texture_rect;
|
|
|
|
D3EditState.texscr_visible = !D3EditState.texscr_visible;
|
|
|
|
if (!D3EditState.texscr_visible) {
|
|
if (D3EditState.tile_views) {
|
|
DeactivateView();
|
|
ActivateView();
|
|
} else if (theApp.textured_view)
|
|
m_grwndTexture.DestroyWindow();
|
|
} else {
|
|
if (D3EditState.tile_views) { // for tiling, reinit the views.
|
|
DeactivateView();
|
|
ActivateView();
|
|
} else {
|
|
SetRect(&texture_rect, D3EditState.texscr_x, D3EditState.texscr_y, D3EditState.texscr_x + D3EditState.texscr_w,
|
|
D3EditState.texscr_y + D3EditState.texscr_h);
|
|
m_grwndTexture.Create(texture_rect, TRUE, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CEditorView::OnUpdateViewWireframemine(CCmdUI *pCmdUI) { pCmdUI->SetCheck(D3EditState.wirescr_visible); }
|
|
|
|
void CEditorView::OnViewWireframemine() {
|
|
RECT wire_rect;
|
|
|
|
D3EditState.wirescr_visible = !D3EditState.wirescr_visible;
|
|
|
|
if (!D3EditState.wirescr_visible) {
|
|
if (D3EditState.tile_views) {
|
|
DeactivateView();
|
|
ActivateView();
|
|
} else if (theApp.wireframe_view)
|
|
m_grwndWireframe.DestroyWindow();
|
|
} else {
|
|
if (D3EditState.tile_views) { // for tiling, reinit the views
|
|
DeactivateView();
|
|
ActivateView();
|
|
} else {
|
|
SetRect(&wire_rect, D3EditState.wirescr_x, D3EditState.wirescr_y, D3EditState.wirescr_x + D3EditState.wirescr_w,
|
|
D3EditState.wirescr_y + D3EditState.wirescr_h);
|
|
m_grwndWireframe.Create(wire_rect, TRUE, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
// We do this so that we can tell if the texture or wireframe views were closed by the user
|
|
//
|
|
void CEditorView::OnParentNotify(UINT message, LPARAM lParam) {
|
|
CView::OnParentNotify(message, lParam);
|
|
|
|
// Is the texture or wireframe window closing?
|
|
switch (message) {
|
|
case WM_CREATE:
|
|
if (HIWORD(lParam) == IDC_TEXTURE_WND) {
|
|
GetParent()->GetMenu()->CheckMenuItem(ID_VIEW_TEXTUREMINE, MF_BYCOMMAND | MF_CHECKED);
|
|
} else if (HIWORD(lParam) == IDC_WIREFRAME_WND) {
|
|
GetParent()->GetMenu()->CheckMenuItem(ID_VIEW_WIREFRAMEMINE, MF_BYCOMMAND | MF_CHECKED);
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
if (HIWORD(lParam) == IDC_TEXTURE_WND) {
|
|
GetParent()->GetMenu()->CheckMenuItem(ID_VIEW_TEXTUREMINE, MF_BYCOMMAND | MF_UNCHECKED);
|
|
} else if (HIWORD(lParam) == IDC_WIREFRAME_WND) {
|
|
GetParent()->GetMenu()->CheckMenuItem(ID_VIEW_WIREFRAMEMINE, MF_BYCOMMAND | MF_UNCHECKED);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// window menu options
|
|
|
|
void CEditorView::OnWindowTile() {
|
|
// TODO: Add your command handler code here
|
|
D3EditState.tile_views = 1;
|
|
((CMainFrame *)GetParentFrame())->DockKeypad(TRUE);
|
|
DeactivateView();
|
|
ActivateView();
|
|
}
|
|
|
|
void CEditorView::OnWindowCascade() {
|
|
// TODO: Add your command handler code here
|
|
D3EditState.tile_views = 0;
|
|
((CMainFrame *)GetParentFrame())->DockKeypad(FALSE);
|
|
DeactivateView();
|
|
ActivateView();
|
|
}
|
|
|
|
void CEditorView::OnButtonWindowSelection() {
|
|
D3EditState.box_selection_mode = -(D3EditState.box_selection_mode - IN_WINDOW - ACROSS_EDGE);
|
|
EditorStatus("Box selection set to %s", (D3EditState.box_selection_mode == IN_WINDOW) ? "IN WINDOW" : "ACROSS EDGE");
|
|
}
|
|
|
|
void CEditorView::OnUpdateButtonWindowSelection(CCmdUI *pCmdUI) {
|
|
pCmdUI->SetCheck(D3EditState.box_selection_mode == ACROSS_EDGE);
|
|
}
|
|
|
|
void CEditorView::OnButtonLighting() {
|
|
Lighting_on = !Lighting_on;
|
|
EditorStatus("Lighting turned %s", Lighting_on ? "ON" : "OFF");
|
|
State_changed = 1;
|
|
}
|
|
|
|
void CEditorView::OnUpdateButtonLighting(CCmdUI *pCmdUI) { pCmdUI->SetCheck(Lighting_on); }
|
|
|
|
BOOL CEditorView::OnHelpInfo(HELPINFO *pHelpInfo) {
|
|
// TODO: Add your message handler code here and/or call default
|
|
switch (D3EditState.keypad_current) {
|
|
case TAB_TEXTURE_KEYPAD:
|
|
WinHelp(HID_TEXTURETAB, HELP_CONTEXT);
|
|
break;
|
|
|
|
case TAB_OBJECTS_KEYPAD:
|
|
WinHelp(HID_OBJECTTAB, HELP_CONTEXT);
|
|
break;
|
|
|
|
case TAB_LIGHTING_KEYPAD:
|
|
WinHelp(HID_LIGHTINGTAB, HELP_CONTEXT);
|
|
break;
|
|
|
|
case TAB_PATHS_KEYPAD:
|
|
WinHelp(HID_PATHSTAB, HELP_CONTEXT);
|
|
break;
|
|
|
|
case TAB_TRIGGER_KEYPAD:
|
|
WinHelp(HID_TRIGGERTAB, HELP_CONTEXT);
|
|
break;
|
|
|
|
case TAB_DOORWAY_KEYPAD:
|
|
WinHelp(HID_DOORWAYTAB, HELP_CONTEXT);
|
|
break;
|
|
|
|
case TAB_TERRAIN_KEYPAD:
|
|
WinHelp(HID_TERRAINTAB, HELP_CONTEXT);
|
|
break;
|
|
|
|
case TAB_MEGACELL_KEYPAD:
|
|
WinHelp(HID_MEGACELLTAB, HELP_CONTEXT);
|
|
break;
|
|
|
|
case TAB_ROOM_KEYPAD:
|
|
WinHelp(HID_ROOMTAB, HELP_CONTEXT);
|
|
break;
|
|
|
|
default:
|
|
WinHelp(HID_DEFAULT, HELP_CONTEXT);
|
|
// return CView::OnHelpInfo(pHelpInfo);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void CEditorView::OnRoomAdd() { AddRoom(); }
|
|
|
|
void CEditorView::OnRoomDelete() {
|
|
if (OutrageMessageBox(MBOX_YESNO, "Are you sure you want to delete Room %d?", ROOMNUM(Curroomp)) != IDYES)
|
|
return;
|
|
|
|
DeleteRoomFromMine(Curroomp);
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CEditorView::OnRoomGrabTexture() { theApp.main_frame->m_TextureDialog->OnTexpadGrab(); }
|
|
|
|
void CEditorView::OnRoomNextFace() {
|
|
SelectNextFace();
|
|
|
|
EditorStatus("Face %d selected.", Curface);
|
|
}
|
|
|
|
void CEditorView::OnRoomPreviousFace() {
|
|
SelectPrevFace();
|
|
|
|
EditorStatus("Face %d selected.", Curface);
|
|
}
|
|
|
|
void CEditorView::OnRoomSelectByNumber() {
|
|
int n;
|
|
|
|
if (InputNumber(&n, "Select Room", "Enter room number to select", this)) {
|
|
|
|
if ((n > Highest_room_index) || !Rooms[n].used) {
|
|
OutrageMessageBox("Invalid room number.");
|
|
return;
|
|
}
|
|
|
|
Curroomp = &Rooms[n];
|
|
Curface = Curedge = Curvert = 0;
|
|
Curportal = -1;
|
|
|
|
EditorStatus("Room %d selected.", n);
|
|
|
|
State_changed = 1;
|
|
}
|
|
}
|
|
|
|
void CEditorView::OnRoomPlaceRoom() {
|
|
if (D3EditState.current_room == -1) {
|
|
OutrageMessageBox("You must have a current room for this operation");
|
|
return;
|
|
}
|
|
|
|
if (Curroomp->faces[Curface].portal_num != -1) {
|
|
OutrageMessageBox("There's already a connection at the current room:face.");
|
|
return;
|
|
}
|
|
|
|
PlaceRoom(Curroomp, Curface, D3EditState.current_room, Current_faces[D3EditState.current_room - FIRST_PALETTE_ROOM],
|
|
-1);
|
|
}
|
|
|
|
void CEditorView::OnRoomAttachRoom() {
|
|
ASSERT(Placed_room != -1);
|
|
|
|
AttachRoom();
|
|
}
|
|
|
|
void CEditorView::OnRoomBuildBridge() {
|
|
if ((Markedroomp == NULL) || (Markedface == -1)) {
|
|
OutrageMessageBox("You must have a marked face to use this function.");
|
|
return;
|
|
}
|
|
|
|
if ((Markedroomp == Curroomp) && (Markedface == Curface)) {
|
|
OutrageMessageBox("The marked room:face must be different from the current room:face.");
|
|
return;
|
|
}
|
|
|
|
BuildBridge(Curroomp, Curface, Markedroomp, Markedface);
|
|
}
|
|
|
|
void CEditorView::OnRoomJoinRooms() {
|
|
if ((Markedroomp == NULL) || (Markedface == -1)) {
|
|
OutrageMessageBox("You must have a marked face to use this function.");
|
|
return;
|
|
}
|
|
|
|
JoinRooms(Curroomp, Curface, Markedroomp, Markedface);
|
|
}
|
|
|
|
void CEditorView::OnRoomMark() { SetMarkedRoom(); }
|
|
|
|
void CEditorView::OnUpdateRoomAttachRoom(CCmdUI *pCmdUI) { pCmdUI->Enable(Placed_room != -1); }
|
|
|
|
void CEditorView::OnRoomUnPlaceRoom() {
|
|
if (Placed_door != -1) {
|
|
FreeRoom(&Rooms[Placed_room]);
|
|
Placed_door = -1;
|
|
}
|
|
|
|
Placed_room = -1;
|
|
Placed_group = NULL;
|
|
|
|
State_changed = 1;
|
|
}
|
|
|
|
void CEditorView::OnUpdateRoomUnPlaceRoom(CCmdUI *pCmdUI) {
|
|
if (Placed_room != -1) {
|
|
pCmdUI->SetText((Placed_door != -1) ? "Un-place Door" : "Un-place Room");
|
|
pCmdUI->Enable(1);
|
|
} else if (Placed_group != NULL) {
|
|
pCmdUI->SetText("Un-place Group");
|
|
pCmdUI->Enable(1);
|
|
} else
|
|
pCmdUI->Enable(0);
|
|
}
|
|
|
|
void CEditorView::OnRoomSelectFaceByNumber() {
|
|
int n;
|
|
|
|
if (InputNumber(&n, "Select Face", "Enter face number to select", this)) {
|
|
|
|
if (n >= Curroomp->num_faces) {
|
|
OutrageMessageBox("Invalid face number.");
|
|
return;
|
|
}
|
|
|
|
Curface = n;
|
|
Curedge = Curvert = 0;
|
|
|
|
EditorStatus("Face %d selected.", Curface);
|
|
|
|
State_changed = 1;
|
|
}
|
|
}
|
|
|
|
void CEditorView::OnRoomSaveCurrentRoom() { theApp.main_frame->m_RoomDialog->OnSaveRoomLocally(); }
|
|
|
|
void CEditorView::OnZbutton() {
|
|
// TODO: Add your command handler code here
|
|
Use_software_zbuffer = !Use_software_zbuffer;
|
|
// tex_SetZBufferState (Use_software_zbuffer); // LGT: not defined
|
|
State_changed = 1;
|
|
}
|
|
|
|
void CEditorView::OnUpdateZbutton(CCmdUI *pCmdUI) {
|
|
static bool first_time = 1, opengl;
|
|
if (first_time) {
|
|
first_time = 0;
|
|
opengl = (FindArg("-WindowGL") != 0);
|
|
}
|
|
|
|
pCmdUI->Enable(!opengl);
|
|
pCmdUI->SetCheck(opengl || Use_software_zbuffer);
|
|
}
|
|
|
|
void CEditorView::OnRoomDropRoom() {
|
|
if (D3EditState.current_room == -1) {
|
|
OutrageMessageBox("You must have a current room for this operation");
|
|
return;
|
|
}
|
|
|
|
DropRoom(Curroomp, Curface, D3EditState.current_room);
|
|
}
|
|
|
|
void CEditorView::OnRoomPlaceTerrainRoom() {
|
|
int cellnum;
|
|
|
|
if (D3EditState.current_room == -1) {
|
|
OutrageMessageBox("You must have a current room for this operation");
|
|
return;
|
|
}
|
|
|
|
if (Current_faces[D3EditState.current_room - FIRST_PALETTE_ROOM] == -1) {
|
|
OutrageMessageBox("You must have a face selected on the current room for this operation");
|
|
return;
|
|
}
|
|
|
|
if (Num_terrain_selected != 1) {
|
|
OutrageMessageBox("You must have one and only one cell selected this operation");
|
|
return;
|
|
} else {
|
|
for (cellnum = 0; cellnum < TERRAIN_WIDTH * TERRAIN_DEPTH; cellnum++)
|
|
if (TerrainSelected[cellnum])
|
|
break;
|
|
|
|
ASSERT(cellnum != TERRAIN_WIDTH * TERRAIN_DEPTH);
|
|
}
|
|
|
|
int result = OutrageMessageBox(MBOX_YESNOCANCEL, "Do you want to align to the terrain? NO will align with gravity.");
|
|
|
|
if (result == IDCANCEL)
|
|
return;
|
|
|
|
PlaceExternalRoom(cellnum, D3EditState.current_room, Current_faces[D3EditState.current_room - FIRST_PALETTE_ROOM],
|
|
(result == IDYES));
|
|
}
|
|
|
|
void CEditorView::OnRoomSwapMarkedAndCurrentRoomFace() {
|
|
if (Markedroomp == NULL)
|
|
return;
|
|
|
|
room *troomp = Markedroomp;
|
|
int tface = Markedface, tedge = Markededge, tvert = Markedvert;
|
|
|
|
Markedroomp = Curroomp;
|
|
Markedface = Curface;
|
|
Markededge = Curedge;
|
|
Markedvert = Curvert;
|
|
|
|
Curroomp = troomp;
|
|
Curface = tface;
|
|
Curedge = tedge;
|
|
Curvert = tvert;
|
|
|
|
State_changed = 1;
|
|
|
|
EditorStatus("Current room:face set to %d:%d; marked room:face set to %d:%d", ROOMNUM(Curroomp), Curface,
|
|
ROOMNUM(Markedroomp), Markedface);
|
|
}
|
|
|
|
void CEditorView::OnRoomDeleteFace() {
|
|
if (Curroomp->faces[Curface].portal_num != -1) {
|
|
OutrageMessageBox("You cannot delete a face that is part of a portal.");
|
|
return;
|
|
}
|
|
|
|
if (Curroomp->num_faces == 1) {
|
|
OutrageMessageBox("You cannot delete the only face in a room.");
|
|
return;
|
|
}
|
|
|
|
if (OutrageMessageBox(MBOX_YESNO, "Are you sure you want to delete Face %d from Room %d?", Curface,
|
|
ROOMNUM(Curroomp)) != IDYES)
|
|
return;
|
|
|
|
DeleteRoomFace(Curroomp, Curface);
|
|
|
|
EditorStatus("Face %d deleted from room %d.", ROOMNUM(Curroomp), Curface);
|
|
|
|
if (Curface == Curroomp->num_faces)
|
|
Curface--;
|
|
|
|
if (Markedface == Curroomp->num_faces)
|
|
Markedface--;
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CEditorView::OnRoomSnapPlacedRoom() {
|
|
ASSERT((Placed_room != -1) || (Placed_group != NULL));
|
|
|
|
if ((Curroomp != Placed_baseroomp) || (Curface != Placed_baseface)) {
|
|
OutrageMessageBox("The current room & face must be the same as the base room & face for this operation.");
|
|
return;
|
|
}
|
|
|
|
SnapRoom(Curvert);
|
|
}
|
|
|
|
void CEditorView::OnUpdateRoomSnapPlacedRoom(CCmdUI *pCmdUI) {
|
|
pCmdUI->Enable(((Placed_room != -1) || (Placed_group != NULL)) && (Placed_baseroomp != NULL));
|
|
|
|
if (Placed_room != -1) {
|
|
pCmdUI->SetText((Placed_door != -1) ? "Snap Placed Door" : "Snap Placed Room");
|
|
pCmdUI->Enable(1);
|
|
} else if (Placed_group != NULL) {
|
|
pCmdUI->SetText("Snap Placed Group");
|
|
pCmdUI->Enable(1);
|
|
} else
|
|
pCmdUI->Enable(0);
|
|
}
|
|
|
|
void CEditorView::OnRoomJoinAdjacentFaces() {
|
|
if (Markedroomp == NULL) {
|
|
OutrageMessageBox("You must have a Marked Room for this operation.");
|
|
return;
|
|
}
|
|
|
|
if (Markedroomp == Curroomp) {
|
|
OutrageMessageBox("The Marked room cannot be the same as the Current room for this operation.");
|
|
return;
|
|
}
|
|
|
|
JoinAllAdjacentFaces(Curroomp, Markedroomp);
|
|
}
|
|
|
|
void CEditorView::OnRoomPropagateToAll() {
|
|
int answer;
|
|
|
|
answer = OutrageMessageBox(
|
|
MBOX_YESNOCANCEL,
|
|
"Propagate only to faces with the same texture?\n(Answering No will propagate to all faces in the room.)");
|
|
|
|
if (answer == IDCANCEL)
|
|
return;
|
|
|
|
PropagateToAllFaces(Curroomp, Curface, (answer == IDYES));
|
|
}
|
|
|
|
void CEditorView::OnRoomSplitFace() {
|
|
if (OutrageMessageBox(MBOX_YESNO, "Are you sure you want to triangulate the current face?") == IDYES)
|
|
TriangulateFace(Curroomp, Curface, Curvert);
|
|
}
|
|
|
|
void CEditorView::OnRoomDeletePortal() {
|
|
if (Curportal == -1) {
|
|
OutrageMessageBox("You must have a current portal for this operation.");
|
|
return;
|
|
}
|
|
|
|
if (OutrageMessageBox(MBOX_YESNO, "Are you sure you want to delete portal %d from room %d (& its connecting portal)?",
|
|
Curportal, ROOMNUM(Curroomp)) == IDYES) {
|
|
DeletePortalPair(Curroomp, Curportal);
|
|
Curportal = -1;
|
|
}
|
|
}
|
|
|
|
void CEditorView::OnRoomSnapPointToEdge() {
|
|
if (Markedroomp == NULL) {
|
|
OutrageMessageBox("You must have a marked vertex to use this function.");
|
|
return;
|
|
}
|
|
|
|
SnapPointToEdge(
|
|
Markedroomp, Markedroomp->faces[Markedface].face_verts[Markedvert],
|
|
&Curroomp->verts[Curroomp->faces[Curface].face_verts[Curedge]],
|
|
&Curroomp->verts[Curroomp->faces[Curface].face_verts[(Curedge + 1) % Curroomp->faces[Curface].num_verts]]);
|
|
}
|
|
|
|
void CEditorView::OnRoomUndoSnap() { UndoSnap(); }
|
|
|
|
void CEditorView::OnUpdateRoomUndoSnap(CCmdUI *pCmdUI) { pCmdUI->Enable(Snap_roomnum != -1); }
|
|
|
|
void CEditorView::OnRoomSnapPointToPoint() {
|
|
if (Markedroomp == NULL) {
|
|
OutrageMessageBox("You must have a marked vertex to use this function.");
|
|
return;
|
|
}
|
|
|
|
SnapPointToPoint(Markedroomp, Markedroomp->faces[Markedface].face_verts[Markedvert], Curroomp,
|
|
Curroomp->faces[Curface].face_verts[Curvert]);
|
|
}
|
|
|
|
void CEditorView::OnReinitOpengl() {
|
|
// TODO: Add your command handler code here
|
|
if (FindArg("-WindowGL")) {
|
|
EditorStatus("Reinitting OpenGL");
|
|
rend_Close();
|
|
rend_Init(RENDERER_OPENGL, Descent, &Render_preferred_state);
|
|
} else {
|
|
EditorStatus("OpenGL command line argument not set.");
|
|
}
|
|
}
|
|
|
|
void CEditorView::OnUpdateReinitOpengl(CCmdUI *pCmdUI) {}
|
|
|
|
void CEditorView::OnFileRemoveExtraPoints() { RemoveAllDuplicateAndUnusedPoints(); }
|
|
|
|
void CEditorView::OnRoomBuildSmoothBridge() {
|
|
if ((Markedroomp == NULL) || (Markedface == -1)) {
|
|
OutrageMessageBox("You must have a marked face to use this function.");
|
|
return;
|
|
}
|
|
|
|
if ((Markedroomp == Curroomp) && (Markedface == Curface)) {
|
|
OutrageMessageBox("The marked room:face must be different from the current room:face.");
|
|
return;
|
|
}
|
|
|
|
BuildSmoothBridge(Markedroomp, Markedface, Curroomp, Curface);
|
|
}
|
|
|
|
void CEditorView::OnRoomJoinRoomsExact() {
|
|
if ((Markedroomp == NULL) || (Markedface == -1)) {
|
|
OutrageMessageBox("You must have a marked face to use this function.");
|
|
return;
|
|
}
|
|
|
|
JoinRoomsExact(Curroomp, Curface, Markedroomp, Markedface);
|
|
}
|
|
|
|
#define POPUP_OUTLINE_ON 0x60
|
|
#define POPUP_OUTLINE_MINE 0x61
|
|
#define POPUP_OUTLINE_TERRAIN 0x62
|
|
#define POPUP_OUTLINE_SKY 0x63
|
|
#define POPUP_OUTLINE_OBJECTS 0x64
|
|
|
|
bool CEditorView::SetupPopup(CMenu *popup) {
|
|
bool ret;
|
|
ret = true;
|
|
int grayed = (Outline_mode & OM_ON) ? 0 : MF_GRAYED;
|
|
|
|
if (!popup->AppendMenu((Outline_mode & OM_ON) ? MF_CHECKED : MF_UNCHECKED, POPUP_OUTLINE_ON, "On"))
|
|
ret = false;
|
|
if (!popup->AppendMenu(grayed + ((Outline_mode & OM_MINE) ? MF_CHECKED : MF_UNCHECKED), POPUP_OUTLINE_MINE, "Mine"))
|
|
ret = false;
|
|
if (!popup->AppendMenu(grayed + ((Outline_mode & OM_TERRAIN) ? MF_CHECKED : MF_UNCHECKED), POPUP_OUTLINE_TERRAIN,
|
|
"Terrain"))
|
|
ret = false;
|
|
if (!popup->AppendMenu(grayed + ((Outline_mode & OM_SKY) ? MF_CHECKED : MF_UNCHECKED), POPUP_OUTLINE_SKY, "Sky"))
|
|
ret = false;
|
|
if (!popup->AppendMenu(grayed + ((Outline_mode & OM_OBJECTS) ? MF_CHECKED : MF_UNCHECKED), POPUP_OUTLINE_OBJECTS,
|
|
"Objects"))
|
|
ret = false;
|
|
|
|
return ret;
|
|
}
|
|
|
|
BOOL CEditorView::OnCommand(WPARAM wParam, LPARAM lParam) {
|
|
int old_outline_mode = Outline_mode;
|
|
|
|
if (HIWORD(wParam) == 0) {
|
|
switch (LOWORD(wParam)) {
|
|
case POPUP_OUTLINE_ON:
|
|
Outline_mode ^= OM_ON;
|
|
EditorStatus("Outline mode turned %s", OUTLINE_ON(0) ? "ON" : "OFF");
|
|
break;
|
|
case POPUP_OUTLINE_MINE:
|
|
Outline_mode ^= OM_MINE;
|
|
EditorStatus("Mine outline turned %s", OUTLINE_ON(OM_MINE) ? "ON" : "OFF");
|
|
break;
|
|
case POPUP_OUTLINE_TERRAIN:
|
|
Outline_mode ^= OM_TERRAIN;
|
|
EditorStatus("Terrain outline turned %s", OUTLINE_ON(OM_TERRAIN) ? "ON" : "OFF");
|
|
break;
|
|
case POPUP_OUTLINE_SKY:
|
|
Outline_mode ^= OM_SKY;
|
|
EditorStatus("Sky outline turned %s", OUTLINE_ON(OM_SKY) ? "ON" : "OFF");
|
|
break;
|
|
case POPUP_OUTLINE_OBJECTS:
|
|
Outline_mode ^= OM_OBJECTS;
|
|
EditorStatus("Object outline turned %s", OUTLINE_ON(OM_OBJECTS) ? "ON" : "OFF");
|
|
break;
|
|
}
|
|
}
|
|
|
|
State_changed = (Outline_mode != old_outline_mode);
|
|
|
|
return CView::OnCommand(wParam, lParam);
|
|
}
|
|
|
|
void CEditorView::OnRoomStartNewFace() { StartNewFace(); }
|
|
|
|
void CEditorView::OnRoomFinishNewFace() { EndNewFace(); }
|
|
|
|
void CEditorView::OnRoomAddVertToNewFace() { AddNewFaceVert(); }
|
|
|
|
#include "osiris_predefs.h"
|
|
extern bool StripLeadingTrailingSpaces(char *s);
|
|
|
|
void RenameRoom() {
|
|
char tempname[ROOM_NAME_LEN + 1] = "";
|
|
|
|
if (Curroomp->name) {
|
|
ASSERT(strlen(Curroomp->name) <= ROOM_NAME_LEN);
|
|
strcpy(tempname, Curroomp->name);
|
|
}
|
|
|
|
try_again:;
|
|
if (!InputString(tempname, ROOM_NAME_LEN, "Room Name", "Enter a new name:"))
|
|
return;
|
|
|
|
if (StripLeadingTrailingSpaces(tempname))
|
|
EditorMessageBox("Note: Leading and/or trailing spaces have been removed from this name (\"%s\")", tempname);
|
|
|
|
int n = osipf_FindRoomName(tempname);
|
|
if ((n != -1) && (n != ROOMNUM(Curroomp))) {
|
|
EditorMessageBox("Room %d already has this name.", n);
|
|
goto try_again;
|
|
}
|
|
|
|
if (Curroomp->name) {
|
|
mem_free(Curroomp->name);
|
|
Curroomp->name = NULL;
|
|
}
|
|
|
|
if (strlen(tempname)) {
|
|
Curroomp->name = mem_rmalloc<char>(strlen(tempname) + 1);
|
|
strcpy(Curroomp->name, tempname);
|
|
}
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CEditorView::OnRoomRenameRoom() { RenameRoom(); }
|
|
|
|
void CEditorView::OnUpdateRoomSetCenterFromViewer(CCmdUI *pCmdUI) { pCmdUI->Enable(!OBJECT_OUTSIDE(Viewer_object)); }
|
|
|
|
void CEditorView::OnRoomSetCenterFromViewer() {
|
|
ASSERT(!OBJECT_OUTSIDE(Viewer_object));
|
|
|
|
if (Viewer_object->roomnum != ROOMNUM(Curroomp)) {
|
|
EditorMessageBox("The viewer must be in the current room for this operation.");
|
|
return;
|
|
}
|
|
|
|
room *rp = &Rooms[Viewer_object->roomnum];
|
|
|
|
rp->path_pnt = Viewer_object->pos;
|
|
rp->flags |= RF_MANUAL_PATH_PNT;
|
|
|
|
EditorStatus("Center point set for room %d", ROOMNUM(Curroomp));
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CEditorView::OnUpdateRoomClearCenterPoint(CCmdUI *pCmdUI) {
|
|
pCmdUI->Enable((Editor_view_mode == VM_MINE) && ((Curroomp->flags & RF_MANUAL_PATH_PNT) != 0));
|
|
}
|
|
|
|
void CEditorView::OnRoomClearCenterPoint() {
|
|
ASSERT(Curroomp->flags & RF_MANUAL_PATH_PNT);
|
|
|
|
Curroomp->flags &= ~RF_MANUAL_PATH_PNT;
|
|
|
|
EditorStatus("Center point cleared for room %d", ROOMNUM(Curroomp));
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CEditorView::OnRoomCombine() {
|
|
if (Markedroomp == NULL) {
|
|
OutrageMessageBox("You must have a Marked Room for this operation.");
|
|
return;
|
|
}
|
|
|
|
int marked_roomnum = ROOMNUM(Markedroomp);
|
|
|
|
if (CombineRooms(Curroomp, Markedroomp))
|
|
EditorStatus("Room %d merged into room %d\n", marked_roomnum, ROOMNUM(Curroomp));
|
|
}
|
|
|
|
void FixDegenerateFaces();
|
|
|
|
void CEditorView::OnFileFixDegenerateFaces() { FixDegenerateFaces(); }
|
|
|
|
void CEditorView::OnRoomSnapPointToFace() {
|
|
if (Markedroomp == NULL) {
|
|
OutrageMessageBox("You must have a marked vertex to use this function.");
|
|
return;
|
|
}
|
|
|
|
SnapPointToFace(Markedroomp, Markedroomp->faces[Markedface].face_verts[Markedvert],
|
|
&Curroomp->verts[Curroomp->faces[Curface].face_verts[Curedge]], &Curroomp->faces[Curface].normal);
|
|
}
|
|
|
|
#define MARK_TEXTURE 1
|
|
|
|
void CEditorView::OnRoomLinkToNewExternal() {
|
|
void LinkToExternalRoom(room * rp, int nfaces, int *facenums);
|
|
int n = 0, facelist[MAX_FACES_PER_ROOM];
|
|
|
|
for (int i = 0; i < Curroomp->num_faces; i++) {
|
|
if ((Curroomp->faces[i].portal_num == -1) && (Curroomp->faces[i].tmap == MARK_TEXTURE))
|
|
facelist[n++] = i;
|
|
}
|
|
|
|
if (n) {
|
|
if (OutrageMessageBox(MBOX_YESNO, "Do you want to create a new room linked to the %d selected faces in room %d?", n,
|
|
ROOMNUM(Curroomp)) != IDYES)
|
|
return;
|
|
|
|
LinkToExternalRoom(Curroomp, n, facelist);
|
|
} else
|
|
OutrageMessageBox("You have no faces selected in room %d.\n\nTo select a face, texture it with Texture %d, \"%s\".",
|
|
ROOMNUM(Curroomp), MARK_TEXTURE, GameTextures[MARK_TEXTURE].name);
|
|
}
|
|
|
|
void CEditorView::OnRoomDeleteVert() {
|
|
if (Curroomp->faces[Curface].num_verts <= 3) {
|
|
OutrageMessageBox("You cannot delete a vertex from a face with three or fewer vertices.");
|
|
return;
|
|
}
|
|
|
|
if (OutrageMessageBox(MBOX_YESNO, "Are you sure you want to delete vertex %d (%d) from room %d face %d?", Curvert,
|
|
Curroomp->faces[Curface].face_verts[Curvert], ROOMNUM(Curroomp), Curface) == IDYES) {
|
|
DeletePointFromFace(Curroomp, Curface, Curvert);
|
|
Curvert = 0;
|
|
}
|
|
}
|
|
|
|
void CEditorView::OnRoomFaceAddVertToEdge() {
|
|
void SplitEdge(room * rp, int facenum, int edgenum, float position);
|
|
|
|
char buf[10] = "0.5";
|
|
|
|
if (InputString(buf, sizeof(buf), "New point position",
|
|
"Please enter the position of the new point, from 0.0 to 1.0")) {
|
|
SplitEdge(Curroomp, Curface, Curedge, atof(buf));
|
|
Curvert = Curedge + 1;
|
|
}
|
|
}
|
|
|
|
void CEditorView::OnRoomFaceMoveVertOnEdge() {
|
|
void MoveVert(room * rp, int facenum, int vertnum, float new_position);
|
|
|
|
char buf[10] = "0.5";
|
|
|
|
if (InputString(buf, sizeof(buf), "New point position",
|
|
"Please enter the new position of the point, from 0.0 to 1.0")) {
|
|
MoveVert(Curroomp, Curface, Curvert, atof(buf));
|
|
}
|
|
}
|
|
|
|
void CEditorView::OnRoomFaceSplitFace() {
|
|
void SplitFace(room * rp, int facenum, int v0, int v1);
|
|
|
|
if ((Curroomp != Markedroomp) || (Curface != Markedface)) {
|
|
OutrageMessageBox("Cannot split face: the Marked & Current faces must be the same for this operation.");
|
|
return;
|
|
}
|
|
|
|
int n_faces = Curroomp->num_faces;
|
|
|
|
SplitFace(Curroomp, Curface, Curvert, Markedvert);
|
|
|
|
Curface = n_faces - 1;
|
|
Curedge = Curvert = 0;
|
|
Markedroomp = NULL;
|
|
}
|
|
|
|
void CEditorView::OnRoomFaceDeleteVertOnEdge() {
|
|
void DeleteVert(room * rp, int facenum, int vertnum);
|
|
|
|
DeleteVert(Curroomp, Curface, Curvert);
|
|
}
|
|
|
|
void CEditorView::OnRoomMergeObjectIntoRoom() {
|
|
if (MergeObjectIntoRoom(Curroomp, Cur_object_index))
|
|
Cur_object_index = -1;
|
|
}
|
|
|
|
void CEditorView::OnRoomDeleteConnectedFaces() {
|
|
if (OutrageMessageBox(
|
|
MBOX_YESNO,
|
|
"This function will delete all faces connected to room %d face %d. This could be very dangerous.\n\n"
|
|
"Are you sure you want to continue?",
|
|
ROOMNUM(Curroomp), Curface) != IDYES)
|
|
return;
|
|
|
|
DeleteAllConnectedFaces(Curroomp, Curface);
|
|
|
|
Curface = 0;
|
|
|
|
if (Markedroomp == Curroomp)
|
|
Markedroomp = NULL;
|
|
}
|
|
|
|
void CEditorView::OnRoomRotatePlacedRoom45Degrees() {
|
|
Placed_room_angle += 65536 / 8;
|
|
|
|
ComputePlacedRoomMatrix();
|
|
|
|
State_changed = 1;
|
|
}
|
|
|
|
void CEditorView::OnRoomPropagateToAdjacentCoplanarFaces() {
|
|
extern void PropagateToConnectedFaces(room * rp, int facenum);
|
|
|
|
PropagateToConnectedFaces(Curroomp, Curface);
|
|
}
|
|
|
|
void CEditorView::OnViewFlip() {
|
|
Viewer_object->orient.fvec = -Viewer_object->orient.fvec;
|
|
Viewer_object->orient.rvec = -Viewer_object->orient.rvec;
|
|
|
|
Viewer_moved = 1;
|
|
}
|
|
|
|
void CEditorView::OnFileRemoveDuplicateFacesFromCurrentRoom() { RemoveDuplicateFaces(Curroomp); }
|