Descent3/editor/TriggerDialog.cpp
2024-06-15 20:12:48 +02:00

827 lines
25 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/TriggerDialog.cpp $
* $Revision: 1.1.1.1 $
* $Date: 2003-08-26 03:57:39 $
* $Author: kevinb $
*
* Trigger keypad dialog.
*
* $Log: not supported by cvs2svn $
*
* 31 6/15/99 5:33p Matt
* Fixed small stupid bug.
*
* 30 4/03/99 7:55p Matt
* Use new keypad update system instead of timer to update.
*
* 29 4/03/99 3:41p Kevin
* Put in code for "Edit Script" button
*
* 28 3/30/99 4:11p Matt
* Set world changed flag when trigger deleted.
*
* 27 3/27/99 7:10p Matt
* Strip leading & trailing spaces before check for duplicate names.
*
* 26 3/23/99 5:52p Matt
* Added clutter activators for triggers
*
* 25 3/22/99 6:59p Matt
* Fixed stupid bug: was assigning UVs to floating trigger face before
* computing normal.
*
* 24 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.
*
* 23 2/28/99 10:40p Matt
* Check for name already in use when entering a name.
*
* 22 2/11/99 8:30p Matt
*
* 21 2/02/99 11:54p Luke
* Fixed small bug (MattT on Luke's machine)
*
* 20 1/21/99 11:34a Matt
* Got rid of portal triggers. Since we don't have multi-face portals, a
* face trigger works fine for a portal. Also fixed a few editor/trigger
* bugs.
*
* 19 1/15/99 10:51a Matt
* Disable rename button if no current trigger
*
* 18 1/14/99 11:06a Matt
* Added names to triggers
*
* 17 1/08/99 2:56p Samir
* Ripped out OSIRIS1.
*
* 16 10/13/98 3:23p Matt
* Fixed a problem with the add portal trigger button being enabled when
* there was already a trigger on the portal's face. Also, fixed and
* added some asserts.
*
* 15 9/01/98 12:04p Matt
* Ripped out multi-face portal code
*
* 14 6/23/98 2:43p Matt
* Changed calls to OutrageMessageBox() & Debug_MessageBox() to deal with
* int return value (instead of bool).
*
* 13 2/04/98 6:23p Matt
* Changed object room number to indicate a terrain cell via a flag. Got
* rid of the object flag which used to indicate terrain.
*
* 12 1/23/98 5:54p Samir
* Added new style script support to triggers.
*
* 11 1/20/98 4:12p Samir
* New script housekeeping system.
*
* 10 1/15/98 7:34p Matt
* Revamped error checking when computing face normals
*
* 9 9/24/97 6:18p Samir
* Use script names instead of script id values to identify scripts.
*
* 8 9/24/97 2:58p Samir
* New ScriptSelect.
*
* 7 9/15/97 11:51a Matt
* Disable 'select by number' if no triggers
*
* 6 9/15/97 11:38a Matt
* Added better trigger selection functions
*
* 5 9/14/97 11:07p Matt
* Use new InputNumber() function
*
* 4 9/12/97 3:59p Matt
* Lots of changes to trigger dialog
*
* 3 9/08/97 10:01a Matt
* Ripped out old trigger code
*
* $NoKeywords: $
*/
#include <stdlib.h>
#include "stdafx.h"
#include "editor.h"
#include "TriggerDialog.h"
#include "trigger.h"
#include "EditLineDialog.h"
#include "render.h"
#include "trigger.h"
#include "HView.h"
#include "FindIntersection.h"
#include "erooms.h"
//@@#include "d3x.h"
#include "DallasMainDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
int Current_trigger = -1; // current editing trigger
/////////////////////////////////////////////////////////////////////////////
// CTriggerDialog dialog
CTriggerDialog::CTriggerDialog(CWnd *pParent /*=NULL*/) : CKeypadDialog(CTriggerDialog::IDD, pParent) {
//{{AFX_DATA_INIT(CTriggerDialog)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CTriggerDialog::DoDataExchange(CDataExchange *pDX) {
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTriggerDialog)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTriggerDialog, CDialog)
//{{AFX_MSG_MAP(CTriggerDialog)
ON_WM_SIZE()
ON_WM_VSCROLL()
ON_WM_HSCROLL()
ON_WM_PAINT()
ON_WM_HELPINFO()
ON_BN_CLICKED(IDC_TRIG_ADD_TO_CURFACE, OnTrigAddToCurface)
ON_BN_CLICKED(IDC_TRIG_GOTO, OnTrigGoto)
ON_BN_CLICKED(IDC_TRIG_DELETE, OnTrigDelete)
ON_BN_CLICKED(IDC_TRIG_ADD_TO_CURPORTAL, OnTrigAddToCurportal)
ON_BN_CLICKED(IDC_TRIG_ADD_FLOATING, OnTrigAddFloating)
ON_BN_CLICKED(IDC_TRIG_RENDER_FLOATING, OnTrigRenderFloating)
ON_BN_CLICKED(IDC_TRIG_ACTIV_PLAYER, OnTrigActivPlayer)
ON_BN_CLICKED(IDC_TRIG_ACTIV_PLAYER_WEAPONS, OnTrigActivPlayerWeapons)
ON_BN_CLICKED(IDC_TRIG_ACTIV_ROBOT_WEAPONS, OnTrigActivRobotWeapons)
ON_BN_CLICKED(IDC_TRIG_ACTIV_ROBOTS, OnTrigActivRobots)
ON_BN_CLICKED(IDC_TRIG_FLOAT_NARROWER, OnTrigFloatNarrower)
ON_BN_CLICKED(IDC_TRIG_FLOAT_SHORTER, OnTrigFloatShorter)
ON_BN_CLICKED(IDC_TRIG_FLOAT_TALLER, OnTrigFloatTaller)
ON_BN_CLICKED(IDC_TRIG_FLOAT_WIDER, OnTrigFloatWider)
ON_BN_CLICKED(IDC_TRIG_ONESHOT, OnTrigOneShot)
ON_BN_CLICKED(IDC_TRIG_NEXT_PORTAL, OnTrigNextPortal)
ON_BN_CLICKED(IDC_TRIG_NEXT_IN_MINE, OnTrigNextInMine)
ON_BN_CLICKED(IDC_TRIG_NEXT_IN_ROOM, OnTrigNextInRoom)
ON_BN_CLICKED(IDC_TRIG_PREV_IN_MINE, OnTrigPrevInMine)
ON_BN_CLICKED(IDC_TRIG_PREV_IN_ROOM, OnTrigPrevInRoom)
ON_BN_CLICKED(IDC_TRIG_EDIT_NAME, OnTrigEditName)
ON_BN_CLICKED(IDC_TRIG_EDIT_SCRIPT, OnTrigEditScript)
ON_BN_CLICKED(IDC_TRIG_ACTIV_CLUTTER, OnTrigActivClutter)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTriggerDialog message handlers
void CTriggerDialog::OnSize(UINT nType, int cx, int cy) {
CKeypadDialog::OnSize(nType, cx, cy);
// make sure we can see a few items in the combo box when we drop it down.
RECT rect;
CComboBox *box = (CComboBox *)GetDlgItem(IDC_TRIGGERTYPE);
if (box) {
box->GetClientRect(&rect);
box->SetWindowPos(NULL, 0, 0, rect.right - rect.left, box->GetItemHeight(0) * 10, SWP_NOMOVE | SWP_NOZORDER);
}
}
void CTriggerDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar) {
// TODO: Add your message handler code here and/or call default
CKeypadDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}
void CTriggerDialog::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar) {
// TODO: Add your message handler code here and/or call default
CKeypadDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
trigger *FindTrigger(int roomnum, int facenum);
int FindNextTrigInRoom(int roomnum, int start) {
if ((start == -1) || (Triggers[start].roomnum != roomnum))
start = 0;
else
start++;
for (int i = 0; i < Num_triggers; i++) {
int n = (start + i) % Num_triggers;
if (Triggers[n].roomnum == roomnum)
return n;
}
// Couldn't find one
return -1;
}
int FindPrevTrigInRoom(int roomnum, int start) {
if (Triggers[start].roomnum != roomnum)
start = 0;
else
start--;
for (int i = Num_triggers; i > 0; i--) {
int n = (start + i) % Num_triggers;
if (Triggers[n].roomnum == roomnum)
return n;
}
// Couldn't find one
return -1;
}
void CTriggerDialog::UpdateDialog() {
bool portal = 0, floating = 0;
static int last_curroom = -1, last_curface = -1, last_curportal = -1;
if (Current_trigger >= Num_triggers)
Current_trigger--;
// If current room/face/portal change, select current trigger from current room/face/portal
if ((ROOMNUM(Curroomp) != last_curroom) || (Curface != last_curface)) {
if (Curroomp->faces[Curface].flags & FF_HAS_TRIGGER)
Current_trigger = (FindTrigger(ROOMNUM(Curroomp), Curface) - Triggers);
} else if ((Curportal != -1) && (Curportal != last_curportal))
if (Curroomp->portals[Curportal].flags & FF_HAS_TRIGGER)
Current_trigger = (FindTrigger(ROOMNUM(Curroomp), Curroomp->portals[Curportal].portal_face) - Triggers);
last_curroom = ROOMNUM(Curroomp);
last_curface = Curface, last_curportal = Curportal;
// Enable/Disable some buttons, etc.
((CButton *)GetDlgItem(IDC_TRIG_NEXT_IN_MINE))->EnableWindow(Num_triggers > 1);
((CButton *)GetDlgItem(IDC_TRIG_PREV_IN_MINE))->EnableWindow(Num_triggers > 1);
((CButton *)GetDlgItem(IDC_TRIG_GOTO))->EnableWindow(Num_triggers > 0);
((CButton *)GetDlgItem(IDC_TRIG_DELETE))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_EDIT_SCRIPT))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_EDIT_NAME))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_ADD_TO_CURFACE))->EnableWindow(!(Curroomp->faces[Curface].flags & FF_HAS_TRIGGER));
((CButton *)GetDlgItem(IDC_TRIG_ADD_TO_CURPORTAL))
->EnableWindow((Curportal != -1) &&
!(Curroomp->faces[Curroomp->portals[Curportal].portal_face].flags & FF_HAS_TRIGGER) &&
!(Curroomp->faces[Curroomp->portals[Curportal].portal_face].flags & FF_HAS_TRIGGER));
((CButton *)GetDlgItem(IDC_TRIG_CURRENT_NUM))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_CURRENT_TYPE))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_CURRENT_ROOM))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_CURRENT_FACE))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_CURRENT_FACE))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_CURRENT_TRIG_PORTAL))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_ACTIVATORS))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_PLAYER))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_PLAYER_WEAPONS))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_ROBOT_WEAPONS))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_ROBOTS))->EnableWindow(Current_trigger != -1);
((CButton *)GetDlgItem(IDC_TRIG_ONESHOT))->EnableWindow(Current_trigger != -1);
int n = FindNextTrigInRoom(ROOMNUM(Curroomp), Current_trigger);
((CButton *)GetDlgItem(IDC_TRIG_NEXT_IN_ROOM))->EnableWindow((n != -1) && (n != Current_trigger));
((CButton *)GetDlgItem(IDC_TRIG_PREV_IN_ROOM))->EnableWindow((n != -1) && (n != Current_trigger));
// Update current trigger info
if (Current_trigger > -1) {
trigger *tp = &Triggers[Current_trigger];
room *rp = &Rooms[tp->roomnum];
face *fp = &rp->faces[tp->facenum];
portal = (fp->portal_num != -1);
floating = ((fp->flags & FF_FLOATING_TRIG) != 0);
ASSERT(!(portal && floating)); // Shouldn't be both portal and floating
PrintToDlgItem(this, IDC_TRIG_CURRENT_NAME, "Name:\t %s", tp->name[0] ? tp->name : "<none>");
PrintToDlgItem(this, IDC_TRIG_CURRENT_NUM, "Number:\t %d", Current_trigger);
PrintToDlgItem(this, IDC_TRIG_CURRENT_TYPE, "Type:\t %s", portal ? "PORTAL" : (floating ? "FLOATING" : "FACE"));
PrintToDlgItem(this, IDC_TRIG_CURRENT_ROOM, "Room:\t%d", tp->roomnum);
PrintToDlgItem(this, IDC_TRIG_CURRENT_FACE, "Face:\t%d", tp->facenum);
PrintToDlgItem(this, IDC_TRIG_CURRENT_TRIG_PORTAL, (portal) ? "Portal:\t%d" : "", fp->portal_num);
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_PLAYER))->SetCheck(tp->activator & AF_PLAYER);
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_PLAYER_WEAPONS))->SetCheck(tp->activator & AF_PLAYER_WEAPON);
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_ROBOT_WEAPONS))->SetCheck(tp->activator & AF_ROBOT_WEAPON);
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_ROBOTS))->SetCheck(tp->activator & AF_ROBOT);
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_CLUTTER))->SetCheck(tp->activator & AF_CLUTTER);
((CButton *)GetDlgItem(IDC_TRIG_ONESHOT))->SetCheck(tp->flags & TF_ONESHOT);
} else {
PrintToDlgItem(this, IDC_TRIG_CURRENT_NAME, "Name:");
PrintToDlgItem(this, IDC_TRIG_CURRENT_NUM, "Number:");
PrintToDlgItem(this, IDC_TRIG_CURRENT_TYPE, "Type:");
PrintToDlgItem(this, IDC_TRIG_CURRENT_ROOM, "Room:");
PrintToDlgItem(this, IDC_TRIG_CURRENT_FACE, "Face:");
PrintToDlgItem(this, IDC_TRIG_CURRENT_TRIG_PORTAL, "");
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_PLAYER))->SetCheck(0);
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_PLAYER_WEAPONS))->SetCheck(0);
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_ROBOT_WEAPONS))->SetCheck(0);
((CButton *)GetDlgItem(IDC_TRIG_ACTIV_ROBOTS))->SetCheck(0);
((CButton *)GetDlgItem(IDC_TRIG_ONESHOT))->SetCheck(0);
}
// Enable/disable floating trig items
((CButton *)GetDlgItem(IDC_TRIG_FLOAT_BORDER))->EnableWindow(floating);
((CButton *)GetDlgItem(IDC_TRIG_FLOAT_WIDER))->EnableWindow(floating);
((CButton *)GetDlgItem(IDC_TRIG_FLOAT_NARROWER))->EnableWindow(floating);
((CButton *)GetDlgItem(IDC_TRIG_FLOAT_TALLER))->EnableWindow(floating);
((CButton *)GetDlgItem(IDC_TRIG_FLOAT_SHORTER))->EnableWindow(floating);
// Enable/disable the portal items
((CButton *)GetDlgItem(IDC_TRIG_CURRENT_PORTAL))->EnableWindow(Curportal != -1);
((CButton *)GetDlgItem(IDC_TRIG_NEXT_PORTAL))
->EnableWindow(((Curportal == -1) && (Curroomp->num_portals > 0)) || (Curroomp->num_portals > 1));
// Update the portal number
if (Curportal != -1)
PrintToDlgItem(this, IDC_TRIG_CURRENT_PORTAL, "Current Portal:\t%d", Curportal);
else
PrintToDlgItem(this, IDC_TRIG_CURRENT_PORTAL, "Current Portal:");
}
void CTriggerDialog::OnPaint() {
CPaintDC dc(this); // device context for painting
UpdateDialog();
}
BOOL CTriggerDialog::OnInitDialog() {
CDialog::OnInitDialog();
// Check current trigger
if (Current_trigger >= Num_triggers)
Current_trigger = Num_triggers - 1;
// Update global checkboxes
(((CButton *)GetDlgItem(IDC_TRIG_RENDER_FLOATING))->SetCheck(Render_floating_triggers));
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CTriggerDialog::OnOK() {
CWnd *focus = CWnd::GetFocus();
if (focus)
focus->GetNextWindow()->SetFocus();
}
BOOL CTriggerDialog::OnHelpInfo(HELPINFO *pHelpInfo) {
// TODO: Add your message handler code here and/or call default
WinHelp(HID_TRIGGERTAB, HELP_CONTEXT);
return TRUE;
// return CDialog::OnHelpInfo(pHelpInfo);
}
void CTriggerDialog::OnTrigAddToCurface() {
ASSERT(!(Curroomp->faces[Curface].flags & FF_HAS_TRIGGER));
char name[TRIG_NAME_LEN + 1] = "";
if (!InputString(name, sizeof(name), "Trigger Name", "Enter a name for this trigger"))
return;
int activator = (Curroomp->faces[Curface].portal_num != -1) ? AF_PLAYER : AF_PLAYER_WEAPON;
Current_trigger = AddTrigger(name, ROOMNUM(Curroomp), Curface, activator, NULL);
UpdateDialog();
}
void SetCurroomFromTrigger() {
if (ROOMNUM(Curroomp) != Triggers[Current_trigger].roomnum) {
Curroomp = &Rooms[Triggers[Current_trigger].roomnum];
Curface = Curedge = Curvert = 0;
Curportal = -1;
}
Curface = Triggers[Current_trigger].facenum;
if (Curroomp->faces[Curface].portal_num != -1)
Curportal = Curroomp->faces[Curface].portal_num;
State_changed = 1;
}
void CTriggerDialog::OnTrigGoto() {
int n;
if (InputNumber(&n, "Select Trigger", "Enter trigger number to select", this)) {
if (n >= Num_triggers) {
OutrageMessageBox("Invalid trigger number.");
return;
}
Current_trigger = n;
SetCurroomFromTrigger();
UpdateDialog();
}
}
void CTriggerDialog::OnTrigDelete() {
ASSERT(Current_trigger != -1);
if (OutrageMessageBox(MBOX_YESNO, "Are you sure you want to delete the current trigger?") != IDYES)
return;
trigger *tp = &Triggers[Current_trigger];
room *rp = &Rooms[tp->roomnum];
int facenum = tp->facenum;
// Delete the trigger
DeleteTrigger(Current_trigger);
// Delete face if this was a floating trigger
if (rp->faces[facenum].flags & FF_FLOATING_TRIG) {
DeleteRoomFace(rp, facenum);
if (Curface == facenum)
Curface = (facenum + 1) % rp->num_faces;
}
if (Current_trigger == Num_triggers)
Current_trigger--;
UpdateDialog();
World_changed = 1;
}
void CTriggerDialog::OnTrigAddToCurportal() {
ASSERT(Curportal != -1);
ASSERT(!(Curroomp->faces[Curroomp->portals[Curportal].portal_face].flags & FF_HAS_TRIGGER));
char name[TRIG_NAME_LEN + 1] = "";
if (!InputString(name, sizeof(name), "Trigger Name", "Enter a name for this trigger"))
return;
Current_trigger = AddTrigger(name, ROOMNUM(Curroomp), Curroomp->portals[Curportal].portal_face, AF_PLAYER, NULL);
UpdateDialog();
}
void CTriggerDialog::UpdateKeypad(int mask) {
if (mask & (KUF_CURROOM_CHANGED + KUF_CURFACE_CHANGED + KUF_CURPORTAL_CHANGED))
UpdateDialog();
}
#include "erooms.h"
#define TRIG_PLACE_DIST 5.0
#define TRIG_DEFAULT_SIZE 10.0
void CTriggerDialog::OnTrigAddFloating() {
int facenum, vertnum;
room *rp;
face *fp;
vector center;
fvi_query fq;
fvi_info hit_info;
int fate;
if (OBJECT_OUTSIDE(Viewer_object)) {
OutrageMessageBox("Sorry, this operation does not yet work in the terrain.");
return;
}
char name[TRIG_NAME_LEN + 1] = "";
if (!InputString(name, sizeof(name), "Trigger Name", "Enter a name for this trigger"))
return;
// Get center point of new face
center = Viewer_object->pos + (Viewer_object->orient.fvec * TRIG_PLACE_DIST);
// Make sure the viewer in in the mine
if (Viewer_object->flags & OF_OUTSIDE_MINE)
goto bad_place;
// Check if position ok
fq.p0 = &Viewer_object->pos;
fq.startroom = Viewer_object->roomnum;
fq.p1 = &center;
fq.rad = 0;
fq.thisobjnum = -1;
fq.ignore_obj_list = NULL;
fq.flags = 0;
fate = fvi_FindIntersection(&fq, &hit_info);
// Bail if there's something in the way, or if the center point is outside
if ((fate != HIT_NONE) || ROOMNUM_OUTSIDE(hit_info.hit_room)) {
bad_place:;
OutrageMessageBox("You cannot place a floating trigger here.");
return;
}
// Get pointer to room the trigger is in
rp = &Rooms[hit_info.hit_room];
// Create a new face & new verts
facenum = RoomAddFaces(rp, 1);
vertnum = RoomAddVertices(rp, 4);
fp = &rp->faces[facenum];
InitRoomFace(fp, 4);
// Set the vertices for the new face
rp->verts[vertnum] =
center - (Viewer_object->orient.rvec * TRIG_DEFAULT_SIZE) + (Viewer_object->orient.uvec * TRIG_DEFAULT_SIZE);
rp->verts[vertnum + 1] =
center + (Viewer_object->orient.rvec * TRIG_DEFAULT_SIZE) + (Viewer_object->orient.uvec * TRIG_DEFAULT_SIZE);
rp->verts[vertnum + 2] =
center + (Viewer_object->orient.rvec * TRIG_DEFAULT_SIZE) - (Viewer_object->orient.uvec * TRIG_DEFAULT_SIZE);
rp->verts[vertnum + 3] =
center - (Viewer_object->orient.rvec * TRIG_DEFAULT_SIZE) - (Viewer_object->orient.uvec * TRIG_DEFAULT_SIZE);
// Set vertnums for new face
for (int i = 0; i < 4; i++)
fp->face_verts[i] = vertnum + i;
// Assign UVs and normal to new face
if (!ComputeFaceNormal(rp, facenum))
Int3(); // Get Matt
AssignDefaultUVsToRoomFace(rp, facenum);
// Set floating trig flag
fp->flags |= FF_FLOATING_TRIG;
// Add the trigger for the new face
Current_trigger = AddTrigger(name, ROOMNUM(rp), facenum, AF_PLAYER, NULL);
// Set the current room:face to the new face
SetCurroomFromTrigger();
// We're done
UpdateDialog();
}
void CTriggerDialog::OnTrigRenderFloating() {
Render_floating_triggers = (((CButton *)GetDlgItem(IDC_TRIG_RENDER_FLOATING))->GetCheck() != 0);
State_changed = 1;
}
void CTriggerDialog::OnTrigActivPlayer() {
trigger *tp = &Triggers[Current_trigger];
if (((CButton *)GetDlgItem(IDC_TRIG_ACTIV_PLAYER))->GetCheck())
tp->activator |= AF_PLAYER;
else
tp->activator &= ~AF_PLAYER;
World_changed = 1;
}
void CTriggerDialog::OnTrigActivPlayerWeapons() {
trigger *tp = &Triggers[Current_trigger];
if (((CButton *)GetDlgItem(IDC_TRIG_ACTIV_PLAYER_WEAPONS))->GetCheck())
tp->activator |= AF_PLAYER_WEAPON;
else
tp->activator &= ~AF_PLAYER_WEAPON;
World_changed = 1;
}
void CTriggerDialog::OnTrigActivRobotWeapons() {
trigger *tp = &Triggers[Current_trigger];
if (((CButton *)GetDlgItem(IDC_TRIG_ACTIV_ROBOT_WEAPONS))->GetCheck())
tp->activator |= AF_ROBOT_WEAPON;
else
tp->activator &= ~AF_ROBOT_WEAPON;
World_changed = 1;
}
void CTriggerDialog::OnTrigActivRobots() {
trigger *tp = &Triggers[Current_trigger];
if (((CButton *)GetDlgItem(IDC_TRIG_ACTIV_ROBOTS))->GetCheck())
tp->activator |= AF_ROBOT;
else
tp->activator &= ~AF_ROBOT;
World_changed = 1;
}
void ScaleFloatingTrigEdge(int roomnum, int facenum, int v0, int v1, float delta) {
room *rp = &Rooms[roomnum];
face *fp = &rp->faces[facenum];
vector *vv0, *vv1;
vector deltav;
float mag;
// Get pointers to verts
vv0 = &rp->verts[fp->face_verts[v0]];
vv1 = &rp->verts[fp->face_verts[v1]];
// Get delta vec
deltav = *vv1 - *vv0;
mag = vm_NormalizeVector(&deltav);
// Check for min size
if (mag <= delta)
return;
// Now add
*vv0 -= deltav * delta;
*vv1 += deltav * delta;
}
#define SCALE_DELTA 1.0
void CTriggerDialog::OnTrigFloatNarrower() {
ASSERT(Current_trigger != -1);
trigger *tp = &Triggers[Current_trigger];
ScaleFloatingTrigEdge(tp->roomnum, tp->facenum, 0, 1, -SCALE_DELTA);
ScaleFloatingTrigEdge(tp->roomnum, tp->facenum, 2, 3, -SCALE_DELTA);
World_changed = 1;
}
void CTriggerDialog::OnTrigFloatShorter() {
ASSERT(Current_trigger != -1);
trigger *tp = &Triggers[Current_trigger];
ScaleFloatingTrigEdge(tp->roomnum, tp->facenum, 1, 2, -SCALE_DELTA);
ScaleFloatingTrigEdge(tp->roomnum, tp->facenum, 3, 0, -SCALE_DELTA);
World_changed = 1;
}
void CTriggerDialog::OnTrigFloatTaller() {
ASSERT(Current_trigger != -1);
trigger *tp = &Triggers[Current_trigger];
ScaleFloatingTrigEdge(tp->roomnum, tp->facenum, 1, 2, SCALE_DELTA);
ScaleFloatingTrigEdge(tp->roomnum, tp->facenum, 3, 0, SCALE_DELTA);
World_changed = 1;
}
void CTriggerDialog::OnTrigFloatWider() {
ASSERT(Current_trigger != -1);
trigger *tp = &Triggers[Current_trigger];
ScaleFloatingTrigEdge(tp->roomnum, tp->facenum, 0, 1, SCALE_DELTA);
ScaleFloatingTrigEdge(tp->roomnum, tp->facenum, 2, 3, SCALE_DELTA);
World_changed = 1;
}
void CTriggerDialog::OnTrigOneShot() {
trigger *tp = &Triggers[Current_trigger];
if (((CButton *)GetDlgItem(IDC_TRIG_ONESHOT))->GetCheck())
tp->flags |= TF_ONESHOT;
else
tp->flags &= ~TF_ONESHOT;
World_changed = 1;
}
void CTriggerDialog::OnTrigNextPortal() {
if (Curroomp->num_portals) {
Curportal = (Curportal + 1) % Curroomp->num_portals;
State_changed = 1;
UpdateDialog();
}
}
void CTriggerDialog::OnTrigNextInMine() {
ASSERT(Current_trigger != -1);
Current_trigger = (Current_trigger + 1) % Num_triggers;
SetCurroomFromTrigger();
UpdateDialog();
}
void CTriggerDialog::OnTrigNextInRoom() {
int n = FindNextTrigInRoom(ROOMNUM(Curroomp), Current_trigger);
ASSERT(n != -1);
Current_trigger = n;
SetCurroomFromTrigger();
}
void CTriggerDialog::OnTrigPrevInMine() {
ASSERT(Current_trigger != -1);
if (--Current_trigger < 0)
Current_trigger += Num_triggers;
SetCurroomFromTrigger();
UpdateDialog();
}
void CTriggerDialog::OnTrigPrevInRoom() {
int n = FindPrevTrigInRoom(ROOMNUM(Curroomp), Current_trigger);
ASSERT(n != -1);
Current_trigger = n;
SetCurroomFromTrigger();
}
#include "osiris_predefs.h"
extern bool StripLeadingTrailingSpaces(char *s);
void CTriggerDialog::OnTrigEditName() {
ASSERT(Current_trigger != -1);
trigger *tp = &Triggers[Current_trigger];
char name[TRIG_NAME_LEN + 1];
strcpy(name, tp->name);
try_again:;
if (!InputString(name, sizeof(name), "Trigger Name", "Enter a new name:"))
return;
if (StripLeadingTrailingSpaces(name))
EditorMessageBox("Note: Leading and/or trailing spaces have been removed from this name (\"%s\")", name);
int n = osipf_FindTriggerName(name);
if ((n != -1) && (n != Current_trigger)) {
EditorMessageBox("Trigger %d already has this name.", n);
goto try_again;
}
strcpy(tp->name, name);
UpdateDialog();
}
void CTriggerDialog::OnTrigEditScript() {
mprintf(0, "Edit script for trigger %d\n", Current_trigger);
// Make sure Dallas is open
if (theApp.m_DallasModelessDlgPtr == NULL) {
theApp.m_DallasModelessDlgPtr = new CDallasMainDlg;
theApp.m_DallasModelessDlgPtr->Create(IDD_DALLAS_MAIN_DIALOG, this);
theApp.m_DallasModelessDlgPtr->ShowWindow(SW_SHOW);
} else
theApp.m_DallasModelessDlgPtr->ShowWindow(SW_RESTORE);
// make sure a trigger was selected
if (Current_trigger == -1)
return;
// Tell Dallas to add a new script with this trigger as the owner
theApp.m_DallasModelessDlgPtr->m_ScriptOwnerType = TRIGGER_TYPE;
theApp.m_DallasModelessDlgPtr->m_ScriptOwnerHandle = Current_trigger;
theApp.m_DallasModelessDlgPtr->PostMessage(WM_HIGHLIGHT_SCRIPTS);
}
void CTriggerDialog::OnTrigActivClutter() {
trigger *tp = &Triggers[Current_trigger];
if (((CButton *)GetDlgItem(IDC_TRIG_ACTIV_CLUTTER))->GetCheck())
tp->activator |= AF_CLUTTER;
else
tp->activator &= ~AF_CLUTTER;
World_changed = 1;
}