mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
975 lines
26 KiB
C++
975 lines
26 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/>.
|
|
*/
|
|
|
|
// PathPadDialog.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "editor.h"
|
|
#include "PathPadDialog.h"
|
|
#include "EditLineDialog.h"
|
|
#include "epath.h"
|
|
#include "object.h"
|
|
#include "room.h"
|
|
#include "FindIntersection.h"
|
|
#include "ebnode.h"
|
|
#include "boa.h"
|
|
#include "object.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPathPadDialog dialog
|
|
|
|
CPathPadDialog::CPathPadDialog(CWnd *pParent /*=NULL*/) : CKeypadDialog(CPathPadDialog::IDD, pParent) {
|
|
//{{AFX_DATA_INIT(CPathPadDialog)
|
|
// NOTE: the ClassWizard will add member initialization here
|
|
//}}AFX_DATA_INIT
|
|
}
|
|
|
|
void CPathPadDialog::DoDataExchange(CDataExchange *pDX) {
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CPathPadDialog)
|
|
// NOTE: the ClassWizard will add DDX and DDV calls here
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CPathPadDialog, CDialog)
|
|
//{{AFX_MSG_MAP(CPathPadDialog)
|
|
ON_EN_KILLFOCUS(IDC_CURRENT_NODE_EDIT, OnKillfocusCurrentNodeEdit)
|
|
ON_BN_CLICKED(IDC_PATHPAD_ADD_PATH, OnPathpadAddPath)
|
|
ON_BN_CLICKED(IDC_PATHPAD_INSERT_NODE, OnPathpadInsertNode)
|
|
ON_BN_CLICKED(IDC_PATHPAD_DELETE_NODE, OnPathpadDeleteNode)
|
|
ON_BN_CLICKED(IDC_PATHPAD_MOVE_FORWARD, OnPathpadMoveForward)
|
|
ON_BN_CLICKED(IDC_PATHPAD_MOVE_BACKWARD, OnPathpadMoveBackward)
|
|
ON_BN_CLICKED(IDC_PATHPAD_MOVE_LEFT, OnPathpadMoveLeft)
|
|
ON_BN_CLICKED(IDC_PATHPAD_MOVE_RIGHT, OnPathpadMoveRight)
|
|
ON_CBN_SELENDOK(IDC_PATHPAD_PULLDOWN, OnSelendokPathpadPulldown)
|
|
ON_BN_CLICKED(IDC_PATHPAD_CENTER_VIEW, OnPathpadCenterView)
|
|
ON_BN_CLICKED(IDC_PATHPAD_MOVE_DOWN, OnPathpadMoveDown)
|
|
ON_BN_CLICKED(IDC_PATHPAD_MOVE_UP, OnPathpadMoveUp)
|
|
ON_BN_CLICKED(IDC_PATHPAD_PREV_NODE, OnPathpadPrevNode)
|
|
ON_BN_CLICKED(IDC_PATHPAD_NEXT_NODE, OnPathpadNextNode)
|
|
ON_BN_CLICKED(IDC_DELETE_PATH, OnDeletePath)
|
|
ON_BN_CLICKED(IDC_SHOW_NODES_CHECK, OnShowNodesCheck)
|
|
ON_WM_HELPINFO()
|
|
ON_BN_CLICKED(IDC_PATH_MOVE_OBJECT_BUTTON, OnPathMoveObjectButton)
|
|
ON_BN_CLICKED(IDC_PATH_REORIENT_VIEWER_BUTTON, OnPathReorientViewerButton)
|
|
ON_EN_KILLFOCUS(IDC_PATH_INC_TEXT, OnKillfocusPathIncText)
|
|
ON_WM_PAINT()
|
|
ON_BN_CLICKED(IDC_PATH_MOVE_NODE_TO_CURRENT_OBJECT, OnPathMoveNodeToCurrentObject)
|
|
ON_BN_CLICKED(IDC_PATH_MOVE_OBJ_NO_ORIENT, OnPathMoveObjNoOrient)
|
|
ON_BN_CLICKED(IDC_PATH_VERIFY_BUTTON, OnPathVerifyButton)
|
|
ON_BN_CLICKED(IDC_AIN_AUTO_EDGE_NODE, OnAinAutoEdgeNode)
|
|
ON_BN_CLICKED(IDC_AIN_BACK, OnAinBack)
|
|
ON_BN_CLICKED(IDC_AIN_CREATE_NODE_AT_VIEWER, OnAinCreateNodeAtViewer)
|
|
ON_BN_CLICKED(IDC_AIN_CREATE_NODES, OnAinCreateNodes)
|
|
ON_CBN_SELENDOK(IDC_AIN_CURRENT_NODE, OnSelendokAinCurrentNode)
|
|
ON_BN_CLICKED(IDC_AIN_DELETE_EDGE, OnAinDeleteEdge)
|
|
ON_BN_CLICKED(IDC_AIN_DELETE_NODE, OnAinDeleteNode)
|
|
ON_BN_CLICKED(IDC_AIN_DOWN, OnAinDown)
|
|
ON_BN_CLICKED(IDC_AIN_FORWARD, OnAinForward)
|
|
ON_BN_CLICKED(IDC_AIN_INSERT_NODE_ON_EDGE, OnAinInsertNodeOnEdge)
|
|
ON_BN_CLICKED(IDC_AIN_LEFT, OnAinLeft)
|
|
ON_BN_CLICKED(IDC_AIN_MAKE_EDGE, OnAinMakeEdge)
|
|
ON_EN_KILLFOCUS(IDC_AIN_MOVE_AMOUNT, OnKillfocusAinMoveAmount)
|
|
ON_BN_CLICKED(IDC_AIN_MOVE_NODE_TO_VIEWER, OnAinMoveNodeToViewer)
|
|
ON_BN_CLICKED(IDC_AIN_MPNS, OnAinMpns)
|
|
ON_CBN_SELENDOK(IDC_AIN_OTHER_NODE, OnSelendokAinOtherNode)
|
|
ON_BN_CLICKED(IDC_AIN_RESET_ROOM_NODES, OnAinResetRoomNodes)
|
|
ON_BN_CLICKED(IDC_AIN_RIGHT, OnAinRight)
|
|
ON_BN_CLICKED(IDC_AIN_SEL_NODE_EDGES, OnAinSelNodeEdges)
|
|
ON_BN_CLICKED(IDC_AIN_SEL_ROOM, OnAinSelRoom)
|
|
ON_BN_CLICKED(IDC_AIN_UP, OnAinUp)
|
|
ON_BN_CLICKED(IDC_AIN_SEL_ROOM_AND_NEXT_ROOMS, OnAinSelRoomAndNextRooms)
|
|
ON_BN_CLICKED(IDC_AIN_VERIFY_LEVEL, OnAinVerifyLevel)
|
|
ON_BN_CLICKED(IDC_AIN_VERIFY_ROOM, OnAinVerifyRoom)
|
|
ON_BN_CLICKED(IDC_AIN_VIEW_ALL_NODES, OnAinViewAllNodes)
|
|
ON_BN_CLICKED(IDC_AIN_VIEW_NONE, OnAinViewNone)
|
|
ON_BN_CLICKED(IDC_AIN_VIEW_ROOM, OnAinViewRoom)
|
|
ON_BN_CLICKED(IDC_AIN_VIEW_ROOM_AND_NEXT_ROOMS, OnAinViewRoomAndNextRooms)
|
|
ON_CBN_SETFOCUS(IDC_AIN_CURRENT_NODE, OnSetfocusAinCurrentNode)
|
|
ON_CBN_SETFOCUS(IDC_AIN_OTHER_NODE, OnSetfocusAinOtherNode)
|
|
ON_BN_CLICKED(IDC_IENAV_BUTTON, OnIenavButton)
|
|
ON_BN_CLICKED(IDC_MVTN_BUTTON, OnMvtnButton)
|
|
ON_BN_CLICKED(IDC_AER_BUTTON, OnAerButton)
|
|
ON_BN_CLICKED(IDC_ONTVGP_BUTTON, OnOntvgpButton)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPathPadDialog message handlers
|
|
|
|
void CPathPadDialog::OnKillfocusCurrentNodeEdit() {
|
|
CEdit *ebox;
|
|
char str[20];
|
|
int curpath = D3EditState.current_path;
|
|
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_CURRENT_NODE_EDIT);
|
|
ebox->GetWindowText(str, 20);
|
|
|
|
// Do the base 1 to base 0 conversion
|
|
D3EditState.current_node = atoi(str) - 1;
|
|
|
|
if (D3EditState.current_node >= GamePaths[curpath].num_nodes)
|
|
D3EditState.current_node = GamePaths[curpath].num_nodes - 1;
|
|
else if (D3EditState.current_node < 0)
|
|
D3EditState.current_node = 0;
|
|
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathpadAddPath() {
|
|
|
|
int curnode;
|
|
char *namestr;
|
|
int pathnum;
|
|
int dup_test;
|
|
|
|
pathnum = AllocGamePath();
|
|
if (pathnum < 0) {
|
|
return;
|
|
}
|
|
|
|
CEditLineDialog dlg("Enter path name", this);
|
|
int ret = dlg.DoModal();
|
|
|
|
if (ret == IDCANCEL) {
|
|
FreeGamePath(pathnum);
|
|
return;
|
|
}
|
|
|
|
namestr = (char *)dlg.GetText();
|
|
dup_test = FindGamePathName(namestr);
|
|
if (dup_test != -1) {
|
|
OutrageMessageBox("PATH NOT CREATED: A path named %s already exists.", namestr);
|
|
FreeGamePath(pathnum);
|
|
return;
|
|
}
|
|
strcpy(GamePaths[pathnum].name, namestr);
|
|
|
|
curnode = InsertNodeIntoPath(pathnum, -1, 0);
|
|
if (curnode < 0)
|
|
return;
|
|
|
|
D3EditState.current_path = pathnum;
|
|
D3EditState.current_node = curnode;
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathpadInsertNode() {
|
|
int curpath = D3EditState.current_path;
|
|
int curnode = D3EditState.current_node;
|
|
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
curnode = InsertNodeIntoPath(curpath, curnode, 0);
|
|
if (curnode < 0)
|
|
return;
|
|
|
|
D3EditState.current_node = curnode;
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathpadDeleteNode() {
|
|
int curpath = D3EditState.current_path;
|
|
int curnode = D3EditState.current_node;
|
|
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
if (GamePaths[curpath].num_nodes == 1) {
|
|
MessageBox("This is the only node in this path. If you wish to delete this path, click the 'Delete Path' button.");
|
|
return;
|
|
}
|
|
|
|
DeleteNodeFromPath(curpath, curnode);
|
|
|
|
// If this was the ending node, move it back one
|
|
if (curnode == GamePaths[curpath].num_nodes)
|
|
D3EditState.current_node = curnode - 1;
|
|
|
|
State_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathpadMoveForward() {
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
vector delta_movement = Viewer_object->orient.fvec * D3EditState.node_movement_inc;
|
|
|
|
MovePathNode(p, n, &delta_movement);
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathpadMoveBackward() {
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
vector delta_movement = Viewer_object->orient.fvec * -D3EditState.node_movement_inc;
|
|
|
|
MovePathNode(p, n, &delta_movement);
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathpadMoveLeft() {
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
vector delta_movement = Viewer_object->orient.rvec * -D3EditState.node_movement_inc;
|
|
|
|
MovePathNode(p, n, &delta_movement);
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathpadMoveRight() {
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
vector delta_movement = Viewer_object->orient.rvec * D3EditState.node_movement_inc;
|
|
|
|
MovePathNode(p, n, &delta_movement);
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnSelendokPathpadPulldown() {
|
|
int i, cur;
|
|
char name[200];
|
|
|
|
cur = SendDlgItemMessage(IDC_PATHPAD_PULLDOWN, CB_GETCURSEL, 0, 0);
|
|
SendDlgItemMessage(IDC_PATHPAD_PULLDOWN, CB_GETLBTEXT, cur, (LPARAM)(LPCTSTR)name);
|
|
|
|
i = FindGamePathName(name);
|
|
|
|
D3EditState.current_path = i;
|
|
D3EditState.current_node = 0;
|
|
|
|
State_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathpadCenterView() {
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
game_path *gp = &GamePaths[p];
|
|
|
|
vector attempted_pos;
|
|
vector subvec = {0.0, 0.0, 0.0}; // changed for now
|
|
|
|
attempted_pos = gp->pathnodes[n].pos - subvec;
|
|
|
|
fvi_query fq;
|
|
fvi_info hit_info;
|
|
|
|
fq.p0 = &GamePaths[p].pathnodes[n].pos;
|
|
fq.startroom = GamePaths[p].pathnodes[n].roomnum;
|
|
fq.p1 = &attempted_pos;
|
|
fq.rad = 0.0f;
|
|
fq.thisobjnum = -1;
|
|
fq.ignore_obj_list = NULL;
|
|
fq.flags = FQ_TRANSPOINT | FQ_IGNORE_RENDER_THROUGH_PORTALS;
|
|
|
|
int hit = fvi_FindIntersection(&fq, &hit_info);
|
|
|
|
if (hit != HIT_NONE)
|
|
Int3(); // what does it mean that we hit something?
|
|
|
|
ObjSetPos(Viewer_object, &hit_info.hit_pnt, hit_info.hit_room, NULL, false);
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathpadMoveDown() {
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
vector delta_movement = Viewer_object->orient.uvec * -D3EditState.node_movement_inc;
|
|
|
|
MovePathNode(p, n, &delta_movement);
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathpadMoveUp() {
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
vector delta_movement = Viewer_object->orient.uvec * D3EditState.node_movement_inc;
|
|
|
|
MovePathNode(p, n, &delta_movement);
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathpadPrevNode() {
|
|
if (Num_game_paths < 1)
|
|
return;
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
n--;
|
|
|
|
if (n < 0)
|
|
n = GamePaths[p].num_nodes - 1;
|
|
|
|
D3EditState.current_node = n;
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathpadNextNode() {
|
|
if (Num_game_paths < 1)
|
|
return;
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
n++;
|
|
|
|
n %= GamePaths[p].num_nodes;
|
|
D3EditState.current_node = n;
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::UpdateDialog() {
|
|
int n = D3EditState.current_path;
|
|
char str[50];
|
|
CEdit *ebox;
|
|
|
|
SendDlgItemMessage(IDC_PATHPAD_PULLDOWN, CB_RESETCONTENT, 0, 0);
|
|
|
|
for (int i = 0; i < MAX_GAME_PATHS; i++) {
|
|
if (GamePaths[i].used)
|
|
SendDlgItemMessage(IDC_PATHPAD_PULLDOWN, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)GamePaths[i].name);
|
|
}
|
|
SendDlgItemMessage(IDC_PATHPAD_PULLDOWN, CB_SELECTSTRING, 0, (LPARAM)(LPCTSTR)GamePaths[n].name);
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_CURRENT_NODE_EDIT);
|
|
sprintf(str, "%d", D3EditState.current_node + 1);
|
|
ebox->SetWindowText(str);
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_PATH_INC_TEXT);
|
|
sprintf(str, "%f", D3EditState.node_movement_inc);
|
|
ebox->SetWindowText(str);
|
|
|
|
if (n < Num_game_paths && D3EditState.current_node < GamePaths[n].num_nodes) {
|
|
ebox = (CEdit *)GetDlgItem(IDC_PATHPAD_CUR_NODE_ROOM);
|
|
if (!ROOMNUM_OUTSIDE(GamePaths[n].pathnodes[D3EditState.current_node].roomnum))
|
|
sprintf(str, "Current Mine Room: %d", GamePaths[n].pathnodes[D3EditState.current_node].roomnum);
|
|
else
|
|
sprintf(str, "Current Terrain Cell: %d", (0x7FFFFFFF & GamePaths[n].pathnodes[D3EditState.current_node].roomnum));
|
|
ebox->SetWindowText(str);
|
|
}
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_PATHPAD_NUM_NODES);
|
|
sprintf(str, "Number of nodes: %d", GamePaths[n].num_nodes);
|
|
ebox->SetWindowText(str);
|
|
|
|
CheckDlgButton(IDC_SHOW_NODES_CHECK, Show_paths ? 1 : 0);
|
|
}
|
|
|
|
void CPathPadDialog::OnDeletePath() {
|
|
int ret;
|
|
int n = D3EditState.current_path;
|
|
|
|
if (Num_game_paths < 1)
|
|
return;
|
|
|
|
ret = MessageBox("Are you sure you want to delete this path?", GamePaths[n].name, MB_YESNO);
|
|
if (ret == IDNO)
|
|
return;
|
|
|
|
FreeGamePath(n);
|
|
|
|
D3EditState.current_path = GetNextPath(n);
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnShowNodesCheck() {
|
|
int c = IsDlgButtonChecked(IDC_SHOW_NODES_CHECK);
|
|
|
|
if (c)
|
|
Show_paths = 1;
|
|
else
|
|
Show_paths = 0;
|
|
|
|
TV_changed = 1;
|
|
}
|
|
|
|
BOOL CPathPadDialog::OnHelpInfo(HELPINFO *pHelpInfo) {
|
|
WinHelp(HID_PATHSTAB, HELP_CONTEXT);
|
|
return TRUE;
|
|
// return CDialog::OnHelpInfo(pHelpInfo);
|
|
}
|
|
|
|
void CPathPadDialog::OnPathMoveObjectButton() {
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
if (Cur_object_index != -1) // we have a selected object
|
|
{
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
game_path *gp = &GamePaths[p];
|
|
|
|
ObjSetPos(&Objects[Cur_object_index], &gp->pathnodes[n].pos, gp->pathnodes[n].roomnum, NULL, false);
|
|
|
|
matrix node_orient;
|
|
|
|
vm_VectorToMatrix(&node_orient, &gp->pathnodes[n].fvec, &gp->pathnodes[n].uvec, NULL);
|
|
ObjSetOrient(&Objects[Cur_object_index], &node_orient);
|
|
|
|
World_changed = 1;
|
|
}
|
|
}
|
|
|
|
void CPathPadDialog::OnPathReorientViewerButton() {
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
game_path *gp = &GamePaths[p];
|
|
|
|
matrix node_orient;
|
|
|
|
vm_VectorToMatrix(&node_orient, &gp->pathnodes[n].fvec, &gp->pathnodes[n].uvec, NULL);
|
|
ObjSetOrient(Viewer_object, &node_orient);
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnKillfocusPathIncText() {
|
|
CEdit *ebox;
|
|
char str[20];
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_PATH_INC_TEXT);
|
|
ebox->GetWindowText(str, 20);
|
|
|
|
// Do the base 1 to base 0 conversion
|
|
sscanf(str, "%f", &D3EditState.node_movement_inc);
|
|
|
|
if (D3EditState.node_movement_inc <= 0.0f || D3EditState.node_movement_inc > 32000.0f)
|
|
D3EditState.node_movement_inc = 1.0f;
|
|
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPaint() {
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnPathMoveNodeToCurrentObject() {
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
if (Cur_object_index != -1) // we have a selected object
|
|
{
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
game_path *gp = &GamePaths[p];
|
|
MovePathNodeToPos(p, n, &Objects[Cur_object_index].pos);
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
}
|
|
|
|
void CPathPadDialog::OnPathMoveObjNoOrient() {
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
if (Cur_object_index != -1) // we have a selected object
|
|
{
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
game_path *gp = &GamePaths[p];
|
|
|
|
ObjSetPos(&Objects[Cur_object_index], &gp->pathnodes[n].pos, gp->pathnodes[n].roomnum, NULL, false);
|
|
|
|
// matrix node_orient;
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
}
|
|
|
|
void CPathPadDialog::OnPathVerifyButton() {}
|
|
|
|
int BNode_current_id = 0;
|
|
int BNode_current_room = 0;
|
|
int BNode_other_id = 0;
|
|
int BNode_other_room = 0;
|
|
|
|
float BNode_move_amount = 1.0f;
|
|
|
|
void CPathPadDialog::OnAinAutoEdgeNode() {
|
|
EBNode_AutoEdgeNode(BNode_current_id, BNode_current_room);
|
|
EBNode_VerifyGraph();
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinBack() {
|
|
vector diff = -Viewer_object->orient.fvec * BNode_move_amount;
|
|
|
|
EBNode_Move(true, BNode_current_room, BNode_current_id, &diff);
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinCreateNodeAtViewer() {
|
|
int node = EBNode_AddNode(Viewer_object->roomnum, &Viewer_object->pos, true, true);
|
|
|
|
if (node != -1) {
|
|
World_changed = 1;
|
|
}
|
|
|
|
// EBNode_VerifyGraph();
|
|
}
|
|
|
|
void CPathPadDialog::OnAinCreateNodes() {
|
|
MakeBOA();
|
|
EBNode_MakeFirstPass();
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnSelendokAinCurrentNode() {
|
|
int cur;
|
|
char name[200];
|
|
|
|
cur = SendDlgItemMessage(IDC_AIN_CURRENT_NODE, CB_GETCURSEL, 0, 0);
|
|
SendDlgItemMessage(IDC_AIN_CURRENT_NODE, CB_GETLBTEXT, cur, (LPARAM)(LPCTSTR)name);
|
|
|
|
if (sscanf(name, "Room %d, Node %d", &BNode_current_room, &BNode_current_id) != 2) {
|
|
sscanf(name, "Region %d, Node %d", &BNode_current_room, &BNode_current_id);
|
|
BNode_current_room += Highest_room_index + 1;
|
|
}
|
|
|
|
BNode_current_id--;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinDeleteEdge() {
|
|
EBNode_RemoveEdge(BNode_current_id, BNode_current_room, BNode_other_id, BNode_other_room);
|
|
World_changed = 1;
|
|
|
|
EBNode_VerifyGraph();
|
|
}
|
|
|
|
void CPathPadDialog::OnAinDeleteNode() {
|
|
EBNode_RemoveNode(BNode_current_room, BNode_current_id);
|
|
World_changed = 1;
|
|
|
|
EBNode_VerifyGraph();
|
|
}
|
|
|
|
void CPathPadDialog::OnAinDown() {
|
|
vector diff = -Viewer_object->orient.uvec * BNode_move_amount;
|
|
|
|
EBNode_Move(true, BNode_current_room, BNode_current_id, &diff);
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinForward() {
|
|
vector diff = Viewer_object->orient.fvec * BNode_move_amount;
|
|
|
|
EBNode_Move(true, BNode_current_room, BNode_current_id, &diff);
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinInsertNodeOnEdge() {
|
|
EBNode_InsertNodeOnEdge(BNode_current_id, BNode_current_room, BNode_other_id, BNode_other_room);
|
|
EBNode_VerifyGraph();
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinLeft() {
|
|
vector diff = -Viewer_object->orient.rvec * BNode_move_amount;
|
|
|
|
EBNode_Move(true, BNode_current_room, BNode_current_id, &diff);
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinMakeEdge() {
|
|
EBNode_AddEdge(BNode_current_id, BNode_current_room, BNode_other_id, BNode_other_room);
|
|
EBNode_VerifyGraph();
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnKillfocusAinMoveAmount() {
|
|
CEdit *ebox;
|
|
char str[20];
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_AIN_MOVE_AMOUNT);
|
|
ebox->GetWindowText(str, 20);
|
|
sscanf(str, "%f", &BNode_move_amount);
|
|
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CPathPadDialog::OnAinMoveNodeToViewer() {
|
|
vector diff = Viewer_object->pos;
|
|
|
|
EBNode_Move(false, BNode_current_room, BNode_current_id, &diff);
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinMpns() {
|
|
// TODO: Add your control notification handler code here
|
|
}
|
|
|
|
void CPathPadDialog::OnSelendokAinOtherNode() {
|
|
int cur;
|
|
char name[200];
|
|
|
|
cur = SendDlgItemMessage(IDC_AIN_OTHER_NODE, CB_GETCURSEL, 0, 0);
|
|
SendDlgItemMessage(IDC_AIN_OTHER_NODE, CB_GETLBTEXT, cur, (LPARAM)(LPCTSTR)name);
|
|
|
|
if (sscanf(name, "Room %d, Node %d", &BNode_other_room, &BNode_other_id) != 2) {
|
|
sscanf(name, "Region %d, Node %d", &BNode_other_room, &BNode_other_id);
|
|
BNode_other_room += Highest_room_index + 1;
|
|
}
|
|
|
|
BNode_other_id--;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinResetRoomNodes() {
|
|
// TODO: Add your control notification handler code here
|
|
EBNode_VerifyGraph();
|
|
}
|
|
|
|
void CPathPadDialog::OnAinRight() {
|
|
vector diff = Viewer_object->orient.rvec * BNode_move_amount;
|
|
|
|
EBNode_Move(true, BNode_current_room, BNode_current_id, &diff);
|
|
World_changed = 1;
|
|
}
|
|
|
|
#define EBVIEW_ROOM 1
|
|
#define EBVIEW_ROOM_AND_NEXT_ROOMS 2
|
|
#define EBVIEW_CUR_EDGES 3
|
|
|
|
char ENode_view_type = EBVIEW_ROOM;
|
|
|
|
void CPathPadDialog::OnAinSelNodeEdges() {
|
|
ENode_view_type = EBVIEW_CUR_EDGES;
|
|
ResetNodesForComboBox(IDC_AIN_CURRENT_NODE, ENode_view_type);
|
|
ResetNodesForComboBox(IDC_AIN_OTHER_NODE, ENode_view_type);
|
|
}
|
|
|
|
void CPathPadDialog::OnAinSelRoom() {
|
|
ENode_view_type = EBVIEW_ROOM;
|
|
ResetNodesForComboBox(IDC_AIN_CURRENT_NODE, ENode_view_type);
|
|
ResetNodesForComboBox(IDC_AIN_OTHER_NODE, ENode_view_type);
|
|
}
|
|
|
|
void CPathPadDialog::OnAinSelRoomAndNextRooms() {
|
|
ENode_view_type = EBVIEW_ROOM_AND_NEXT_ROOMS;
|
|
ResetNodesForComboBox(IDC_AIN_CURRENT_NODE, ENode_view_type);
|
|
ResetNodesForComboBox(IDC_AIN_OTHER_NODE, ENode_view_type);
|
|
}
|
|
|
|
void CPathPadDialog::OnAinUp() {
|
|
vector diff = Viewer_object->orient.uvec * BNode_move_amount;
|
|
|
|
EBNode_Move(true, BNode_current_room, BNode_current_id, &diff);
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinVerifyLevel() { EBNode_VerifyGraph(); }
|
|
|
|
void CPathPadDialog::OnAinVerifyRoom() {
|
|
EBNode_ClearLevel();
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinViewAllNodes() {
|
|
EBN_draw_type = EBDRAW_LEVEL;
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinViewNone() {
|
|
EBN_draw_type = EBDRAW_NONE;
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinViewRoom() {
|
|
EBN_draw_type = EBDRAW_ROOM;
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAinViewRoomAndNextRooms() {
|
|
EBN_draw_type = EBDRAW_ROOM_AND_NEXT_ROOMS;
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::ResetNodesForComboBox(int handle, char selection_type) {
|
|
char message[25];
|
|
SendDlgItemMessage(handle, CB_RESETCONTENT, 0, 0);
|
|
bool f_add = false;
|
|
|
|
int num_next_rooms = 0;
|
|
int next_rooms[1000];
|
|
|
|
if (Viewer_object->roomnum >= 0 && Viewer_object->roomnum <= Highest_room_index &&
|
|
Rooms[Viewer_object->roomnum].used) {
|
|
if (selection_type == EBVIEW_ROOM || selection_type == EBVIEW_ROOM_AND_NEXT_ROOMS) {
|
|
for (int i = 0; i < Rooms[Viewer_object->roomnum].bn_info.num_nodes; i++) {
|
|
f_add = true;
|
|
|
|
sprintf(message, "Room %d, Node %d", Viewer_object->roomnum, i + 1);
|
|
SendDlgItemMessage(handle, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)message);
|
|
}
|
|
|
|
if (selection_type == EBVIEW_ROOM_AND_NEXT_ROOMS) {
|
|
int i;
|
|
int j;
|
|
int k;
|
|
|
|
for (i = 0; i < Rooms[Viewer_object->roomnum].num_portals; i++) {
|
|
bool f_found = false;
|
|
|
|
for (j = 0; j < num_next_rooms; j++) {
|
|
if (next_rooms[j] == Rooms[Viewer_object->roomnum].portals[i].croom) {
|
|
f_found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!f_found && Rooms[Viewer_object->roomnum].portals[i].croom >= 0 &&
|
|
!(Rooms[Rooms[Viewer_object->roomnum].portals[i].croom].flags & RF_EXTERNAL)) {
|
|
for (k = 0; k < Rooms[Rooms[Viewer_object->roomnum].portals[i].croom].bn_info.num_nodes; k++) {
|
|
sprintf(message, "Room %d, Node %d", Rooms[Viewer_object->roomnum].portals[i].croom, k + 1);
|
|
SendDlgItemMessage(handle, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (f_add) {
|
|
sprintf(message, "Room %d, Node %d", Viewer_object->roomnum, 0 + 1);
|
|
SendDlgItemMessage(handle, CB_SELECTSTRING, 0, (LPARAM)(LPCTSTR)message);
|
|
} else {
|
|
strcpy(message, "No Nodes in room");
|
|
SendDlgItemMessage(handle, CB_SELECTSTRING, 0, (LPARAM)(LPCTSTR)message);
|
|
}
|
|
}
|
|
} else if (ROOMNUM_OUTSIDE(Viewer_object->roomnum)) {
|
|
if (selection_type == EBVIEW_ROOM || selection_type == EBVIEW_ROOM_AND_NEXT_ROOMS) {
|
|
int room = BOA_INDEX(Viewer_object->roomnum);
|
|
int tr = room - Highest_room_index - 1;
|
|
bn_list *bnlist = BNode_GetBNListPtr(Viewer_object->roomnum);
|
|
|
|
for (int i = 0; i < bnlist->num_nodes; i++) {
|
|
f_add = true;
|
|
|
|
sprintf(message, "Region %d, Node %d", tr, i + 1);
|
|
SendDlgItemMessage(handle, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)message);
|
|
}
|
|
|
|
if (selection_type == EBVIEW_ROOM_AND_NEXT_ROOMS) {
|
|
int i;
|
|
int j;
|
|
int k;
|
|
|
|
for (i = 0; i < BOA_num_connect[tr]; i++) {
|
|
bool f_found = false;
|
|
|
|
for (j = 0; j < num_next_rooms; j++) {
|
|
if (next_rooms[j] == BOA_connect[tr][i].roomnum) {
|
|
f_found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!f_found && BOA_connect[tr][i].roomnum >= 0 && !(Rooms[BOA_connect[tr][i].roomnum].flags & RF_EXTERNAL)) {
|
|
for (k = 0; k < Rooms[BOA_connect[tr][i].roomnum].bn_info.num_nodes; k++) {
|
|
sprintf(message, "Room %d, Node %d", BOA_connect[tr][i].roomnum, k + 1);
|
|
SendDlgItemMessage(handle, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (f_add) {
|
|
sprintf(message, "Region %d, Node %d", tr, 0 + 1);
|
|
SendDlgItemMessage(handle, CB_SELECTSTRING, 0, (LPARAM)(LPCTSTR)message);
|
|
} else {
|
|
strcpy(message, "No Nodes in region");
|
|
SendDlgItemMessage(handle, CB_SELECTSTRING, 0, (LPARAM)(LPCTSTR)message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CPathPadDialog::OnSetfocusAinCurrentNode() { ResetNodesForComboBox(IDC_AIN_CURRENT_NODE, ENode_view_type); }
|
|
|
|
void CPathPadDialog::OnSetfocusAinOtherNode() { ResetNodesForComboBox(IDC_AIN_OTHER_NODE, ENode_view_type); }
|
|
|
|
void CPathPadDialog::OnIenavButton() {
|
|
int node = EBNode_InsertNodeOnEdge(BNode_current_id, BNode_current_room, BNode_other_id, BNode_other_room);
|
|
if (node >= 0) {
|
|
vector diff = Viewer_object->pos;
|
|
|
|
EBNode_Move(false, BNode_current_room, node, &diff);
|
|
World_changed = 1;
|
|
}
|
|
}
|
|
|
|
void CPathPadDialog::OnMvtnButton() {
|
|
vector pos;
|
|
int roomnum;
|
|
|
|
bn_list *bnlist = BNode_GetBNListPtr(BNode_current_room);
|
|
if (!bnlist)
|
|
return;
|
|
|
|
pos = bnlist->nodes[BNode_current_id].pos;
|
|
|
|
if (BNode_current_room >= 0 && BNode_current_room <= Highest_room_index) {
|
|
roomnum = BNode_current_room;
|
|
} else {
|
|
roomnum = GetTerrainRoomFromPos(&pos);
|
|
}
|
|
|
|
BNode_current_id,
|
|
|
|
ObjSetPos(Viewer_object, &pos, roomnum, NULL, false);
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnAerButton() {
|
|
bn_list *bnlist = BNode_GetBNListPtr(BNode_current_room);
|
|
if (!bnlist)
|
|
return;
|
|
|
|
for (int i = 0; i < bnlist->num_nodes; i++) {
|
|
EBNode_AutoEdgeNode(i, BNode_current_room);
|
|
}
|
|
|
|
EBNode_VerifyGraph();
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CPathPadDialog::OnOntvgpButton() {
|
|
if (Num_game_paths < 1) {
|
|
MessageBox("There are no paths to operate on.");
|
|
return;
|
|
}
|
|
|
|
if (Cur_object_index != -1) // we have a selected object
|
|
{
|
|
|
|
int p = D3EditState.current_path;
|
|
int n = D3EditState.current_node;
|
|
|
|
game_path *gp = &GamePaths[p];
|
|
|
|
gp->pathnodes[n].fvec = Viewer_object->orient.fvec;
|
|
gp->pathnodes[n].uvec = Viewer_object->orient.uvec;
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
}
|