mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 08:15:59 -10:00
The object list in orient_editor::OnInitDialog() predates props, so every prop in the mission fired the "Unknown object type" warning when the dialog opened, and props could not be selected as point-to targets. Add them to the list like qtFRED does since #7402. Co-Authored-By: Claude Fable 5 <[email protected]>
600 lines
16 KiB
C++
600 lines
16 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "FRED.h"
|
|
#include "OrientEditor.h"
|
|
#include "Management.h"
|
|
#include "globalincs/linklist.h"
|
|
#include "FREDView.h"
|
|
#include "prop/prop.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
constexpr auto INPUT_FORMAT = "%.01f";
|
|
|
|
static bool Select_set_relative = false;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// orient_editor dialog
|
|
|
|
orient_editor::orient_editor(CWnd* pParent /*=NULL*/)
|
|
: CDialog(orient_editor::IDD, pParent)
|
|
{
|
|
//{{AFX_DATA_INIT(orient_editor)
|
|
m_object_index = 0;
|
|
m_point_to = FALSE;
|
|
m_position_x = _T("");
|
|
m_position_y = _T("");
|
|
m_position_z = _T("");
|
|
m_location_x = _T("0.0");
|
|
m_location_y = _T("0.0");
|
|
m_location_z = _T("0.0");
|
|
m_orientation_p = _T("");
|
|
m_orientation_b = _T("");
|
|
m_orientation_h = _T("");
|
|
//}}AFX_DATA_INIT
|
|
|
|
set_relative = false;
|
|
|
|
Assert(query_valid_object());
|
|
auto pos = &Objects[cur_object_index].pos;
|
|
m_position_x.Format(INPUT_FORMAT, pos->xyz.x);
|
|
m_position_y.Format(INPUT_FORMAT, pos->xyz.y);
|
|
m_position_z.Format(INPUT_FORMAT, pos->xyz.z);
|
|
|
|
angles ang;
|
|
vm_extract_angles_matrix(&ang, &Objects[cur_object_index].orient);
|
|
m_orientation_p.Format(INPUT_FORMAT, to_degrees(ang.p));
|
|
m_orientation_b.Format(INPUT_FORMAT, to_degrees(ang.b));
|
|
m_orientation_h.Format(INPUT_FORMAT, to_degrees(ang.h));
|
|
}
|
|
|
|
void orient_editor::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(orient_editor)
|
|
DDX_Control(pDX, IDC_SPIN1, m_spin1);
|
|
DDX_Control(pDX, IDC_SPIN2, m_spin2);
|
|
DDX_Control(pDX, IDC_SPIN3, m_spin3);
|
|
DDX_Control(pDX, IDC_SPIN4, m_spin4);
|
|
DDX_Control(pDX, IDC_SPIN5, m_spin5);
|
|
DDX_Control(pDX, IDC_SPIN6, m_spin6);
|
|
DDX_Control(pDX, IDC_SPIN11, m_spin11);
|
|
DDX_Control(pDX, IDC_SPIN12, m_spin12);
|
|
DDX_Control(pDX, IDC_SPIN13, m_spin13);
|
|
DDX_CBIndex(pDX, IDC_OBJECT_LIST, m_object_index);
|
|
DDX_Check(pDX, IDC_POINT_TO_CHECKBOX, m_point_to);
|
|
DDX_Text(pDX, IDC_POSITION_X, m_position_x);
|
|
DDX_Text(pDX, IDC_POSITION_Y, m_position_y);
|
|
DDX_Text(pDX, IDC_POSITION_Z, m_position_z);
|
|
DDX_Text(pDX, IDC_LOCATION_X, m_location_x);
|
|
DDX_Text(pDX, IDC_LOCATION_Y, m_location_y);
|
|
DDX_Text(pDX, IDC_LOCATION_Z, m_location_z);
|
|
DDX_Text(pDX, IDC_ORIENTATION_P, m_orientation_p);
|
|
DDX_Text(pDX, IDC_ORIENTATION_B, m_orientation_b);
|
|
DDX_Text(pDX, IDC_ORIENTATION_H, m_orientation_h);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(orient_editor, CDialog)
|
|
//{{AFX_MSG_MAP(orient_editor)
|
|
ON_CBN_SELCHANGE(IDC_OBJECT_LIST, OnObjectSelected)
|
|
ON_BN_CLICKED(IDC_POINT_TO_CHECKBOX, OnPointTo)
|
|
ON_BN_CLICKED(IDC_POINT_TO_OBJECT, OnPointToObject)
|
|
ON_BN_CLICKED(IDC_POINT_TO_LOCATION, OnPointToLocation)
|
|
ON_BN_CLICKED(IDC_SET_ABSOLUTE, OnSetAbsolute)
|
|
ON_BN_CLICKED(IDC_SET_RELATIVE, OnSetRelative)
|
|
ON_WM_CLOSE()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// orient_editor message handlers
|
|
|
|
BOOL orient_editor::OnInitDialog()
|
|
{
|
|
char text[80];
|
|
int type;
|
|
CComboBox *box;
|
|
object *ptr;
|
|
|
|
CDialog::OnInitDialog();
|
|
theApp.init_window(&Object_wnd_data, this);
|
|
((CButton *) GetDlgItem(IDC_POINT_TO_OBJECT))->SetCheck(TRUE);
|
|
((CButton *) GetDlgItem(Select_set_relative ? IDC_SET_RELATIVE : IDC_SET_ABSOLUTE))->SetCheck(TRUE);
|
|
((CButton *) GetDlgItem(IDC_TRANSFORM_INDEPENDENT))->SetCheck(TRUE);
|
|
box = (CComboBox *) GetDlgItem(IDC_OBJECT_LIST);
|
|
box->ResetContent();
|
|
|
|
total = 0;
|
|
ptr = GET_FIRST(&obj_used_list);
|
|
while (ptr != END_OF_LIST(&obj_used_list)) {
|
|
int objnum = OBJ_INDEX(ptr);
|
|
|
|
if (Marked != 1 || objnum != cur_object_index) {
|
|
if ((ptr->type == OBJ_START) || (ptr->type == OBJ_SHIP)) {
|
|
box->AddString(Ships[ptr->instance].ship_name);
|
|
index[total++] = objnum;
|
|
|
|
} else if (ptr->type == OBJ_WAYPOINT) {
|
|
waypoint_stuff_name(text, ptr->instance);
|
|
box->AddString(text);
|
|
index[total++] = objnum;
|
|
|
|
} else if (ptr->type == OBJ_JUMP_NODE) {
|
|
box->AddString(jumpnode_get_by_objnum(objnum)->GetName());
|
|
index[total++] = objnum;
|
|
|
|
} else if (ptr->type == OBJ_PROP) {
|
|
if (Props[ptr->instance].has_value()) {
|
|
box->AddString(Props[ptr->instance].value().prop_name);
|
|
index[total++] = objnum;
|
|
}
|
|
|
|
} else if (ptr->type != OBJ_POINT)
|
|
Warning(LOCATION, "Unknown object type %d", ptr->type);
|
|
}
|
|
|
|
ptr = GET_NEXT(ptr);
|
|
}
|
|
|
|
type = Objects[cur_object_index].type;
|
|
if (Marked == 1 && (type == OBJ_WAYPOINT || type == OBJ_JUMP_NODE)) {
|
|
GetDlgItem(IDC_POINT_TO_CHECKBOX)->EnableWindow(FALSE);
|
|
GetDlgItem(IDC_POINT_TO_OBJECT)->EnableWindow(FALSE);
|
|
GetDlgItem(IDC_POINT_TO_LOCATION)->EnableWindow(FALSE);
|
|
GetDlgItem(IDC_OBJECT_LIST)->EnableWindow(FALSE);
|
|
GetDlgItem(IDC_LOCATION_X)->EnableWindow(FALSE);
|
|
GetDlgItem(IDC_LOCATION_Y)->EnableWindow(FALSE);
|
|
GetDlgItem(IDC_LOCATION_Z)->EnableWindow(FALSE);
|
|
GetDlgItem(IDC_ORIENTATION_P)->EnableWindow(FALSE);
|
|
GetDlgItem(IDC_ORIENTATION_B)->EnableWindow(FALSE);
|
|
GetDlgItem(IDC_ORIENTATION_H)->EnableWindow(FALSE);
|
|
m_object_index = -1;
|
|
|
|
} else {
|
|
m_object_index = 0;
|
|
}
|
|
|
|
if (Marked == 1 || (type == OBJ_WAYPOINT || type == OBJ_JUMP_NODE)) {
|
|
GetDlgItem(IDC_TRANSFORM_INDEPENDENT)->EnableWindow(FALSE);
|
|
GetDlgItem(IDC_TRANSFORM_RELATIVE)->EnableWindow(FALSE);
|
|
}
|
|
|
|
m_spin1.SetRange((short)-9999, (short)9999);
|
|
m_spin1.SetPos((int) convert(m_position_x));
|
|
m_spin2.SetRange((short)-9999, (short)9999);
|
|
m_spin2.SetPos((int) convert(m_position_y));
|
|
m_spin3.SetRange((short)-9999, (short)9999);
|
|
m_spin3.SetPos((int) convert(m_position_z));
|
|
|
|
m_spin4.SetRange((short)-9999, (short)9999);
|
|
m_spin5.SetRange((short)-9999, (short)9999);
|
|
m_spin6.SetRange((short)-9999, (short)9999);
|
|
|
|
m_spin11.SetRange((short)-180, (short)180);
|
|
m_spin11.SetPos((int)convert(m_orientation_p));
|
|
m_spin12.SetRange((short)-180, (short)180);
|
|
m_spin12.SetPos((int)convert(m_orientation_b));
|
|
m_spin13.SetRange((short)-180, (short)180);
|
|
m_spin13.SetPos((int)convert(m_orientation_h));
|
|
|
|
UpdateData(FALSE);
|
|
|
|
// now that we've set up the dialog, we might need to switch modes depending on the last used mode
|
|
// (the proper radio button was selected at the beginning of the function)
|
|
set_relative = false;
|
|
if (Select_set_relative)
|
|
OnSetRelative(); // this will toggle it from false to true
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* Checks whether the position value is close enough to the input string value that we can assume the input has not changed.
|
|
*/
|
|
bool orient_editor::is_close(float val, const CString &input_str) const
|
|
{
|
|
val = perform_input_rounding(val);
|
|
float input_val = convert(input_str);
|
|
|
|
float diff = val - input_val;
|
|
return abs(diff) < ORIENT_INPUT_THRESHOLD;
|
|
}
|
|
|
|
/**
|
|
* Checks whether the angle value is close enough to the input string value that we can assume the input has not changed.
|
|
*/
|
|
bool orient_editor::is_angle_close(float rad, const CString &input_str) const
|
|
{
|
|
float deg = perform_input_rounding(to_degrees(rad));
|
|
float input_deg = normalize_degrees(convert(input_str));
|
|
|
|
float diff = deg - input_deg;
|
|
return abs(diff) < ORIENT_INPUT_THRESHOLD;
|
|
}
|
|
|
|
bool orient_editor::query_modified()
|
|
{
|
|
auto &pos = set_relative
|
|
? vmd_zero_vector
|
|
: Objects[cur_object_index].pos;
|
|
|
|
if (!is_close(pos.xyz.x, m_position_x))
|
|
return true;
|
|
if (!is_close(pos.xyz.y, m_position_y))
|
|
return true;
|
|
if (!is_close(pos.xyz.z, m_position_z))
|
|
return true;
|
|
|
|
angles ang;
|
|
if (set_relative)
|
|
ang = vmd_zero_angles;
|
|
else
|
|
vm_extract_angles_matrix(&ang, &Objects[cur_object_index].orient);
|
|
|
|
if (!is_angle_close(ang.p, m_orientation_p))
|
|
return true;
|
|
if (!is_angle_close(ang.b, m_orientation_b))
|
|
return true;
|
|
if (!is_angle_close(ang.h, m_orientation_h))
|
|
return true;
|
|
|
|
if (((CButton *) GetDlgItem(IDC_POINT_TO_CHECKBOX))->GetCheck() == TRUE)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
void orient_editor::OnOK()
|
|
{
|
|
vec3d delta = vmd_zero_vector;
|
|
matrix m = vmd_identity_matrix;
|
|
bool change_pos = false, change_orient = false;
|
|
|
|
UpdateData(TRUE);
|
|
|
|
// save selection for future uses of this dialog
|
|
Select_set_relative = set_relative;
|
|
|
|
// position...
|
|
const vec3d &reference_pos = set_relative ? vmd_zero_vector : Objects[cur_object_index].pos;
|
|
// there's enough difference in our position that we're changing it
|
|
if (!is_close(reference_pos.xyz.x, m_position_x) || !is_close(reference_pos.xyz.y, m_position_y) || !is_close(reference_pos.xyz.z, m_position_z))
|
|
{
|
|
vec3d pos;
|
|
pos.xyz.x = convert(m_position_x);
|
|
pos.xyz.y = convert(m_position_y);
|
|
pos.xyz.z = convert(m_position_z);
|
|
|
|
if (set_relative)
|
|
vm_vec_unrotate(&delta, &pos, &Objects[cur_object_index].orient);
|
|
else
|
|
vm_vec_sub(&delta, &pos, &reference_pos);
|
|
|
|
change_pos = true;
|
|
set_modified();
|
|
}
|
|
|
|
// orientation...
|
|
angles object_ang;
|
|
vm_extract_angles_matrix(&object_ang, &Objects[cur_object_index].orient);
|
|
const angles &reference_ang = set_relative ? vmd_zero_angles : object_ang;
|
|
// there's enough difference in our orientation that we're changing it
|
|
if (!is_angle_close(reference_ang.p, m_orientation_p) || !is_angle_close(reference_ang.b, m_orientation_b) || !is_angle_close(reference_ang.h, m_orientation_h))
|
|
{
|
|
angles ang;
|
|
ang.p = fl_radians(convert(m_orientation_p));
|
|
ang.b = fl_radians(convert(m_orientation_b));
|
|
ang.h = fl_radians(convert(m_orientation_h));
|
|
|
|
if (set_relative)
|
|
{
|
|
ang.p = object_ang.p + ang.p;
|
|
ang.b = object_ang.b + ang.b;
|
|
ang.h = object_ang.h + ang.h;
|
|
}
|
|
vm_angles_2_matrix(&m, &ang);
|
|
|
|
change_orient = true;
|
|
set_modified();
|
|
}
|
|
|
|
// we're pointing to something
|
|
if (m_point_to)
|
|
set_modified();
|
|
|
|
object *origin_objp = nullptr;
|
|
vec3d origin_prev_pos = vmd_zero_vector;
|
|
matrix origin_rotation = vmd_identity_matrix;
|
|
|
|
if (Marked > 1 && ((CButton*)GetDlgItem(IDC_TRANSFORM_RELATIVE))->GetCheck() == TRUE) {
|
|
origin_objp = &Objects[cur_object_index];
|
|
origin_prev_pos = origin_objp->pos;
|
|
auto saved_orient = origin_objp->orient;
|
|
|
|
// move the origin first
|
|
if (change_pos) {
|
|
vm_vec_add2(&origin_objp->pos, &delta);
|
|
}
|
|
if (m_point_to) {
|
|
actually_point_object(origin_objp);
|
|
}
|
|
else if (change_orient) {
|
|
origin_objp->orient = m;
|
|
}
|
|
|
|
// calculate the change in orient
|
|
if (origin_objp->type != OBJ_WAYPOINT) {
|
|
vm_transpose(&saved_orient);
|
|
origin_rotation = saved_orient * origin_objp->orient;
|
|
}
|
|
}
|
|
|
|
// move and/or point all the objects
|
|
for (auto ptr = GET_FIRST(&obj_used_list); ptr != END_OF_LIST(&obj_used_list); ptr = GET_NEXT(ptr)) {
|
|
if (ptr != origin_objp && ptr->flags[Object::Object_Flags::Marked]) {
|
|
// relative to the new position of the origin
|
|
if (origin_objp) {
|
|
vec3d relative_pos, transformed_pos;
|
|
vm_vec_sub(&relative_pos, &ptr->pos, &origin_prev_pos);
|
|
vm_vec_unrotate(&transformed_pos, &relative_pos, &origin_rotation);
|
|
vm_vec_add(&ptr->pos, &transformed_pos, &origin_objp->pos);
|
|
ptr->orient = ptr->orient * origin_rotation;
|
|
}
|
|
// all objects moving independently
|
|
else {
|
|
if (change_pos) {
|
|
vm_vec_add2(&ptr->pos, &delta);
|
|
}
|
|
if (m_point_to) {
|
|
actually_point_object(ptr);
|
|
} else if (change_orient) {
|
|
ptr->orient = m;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// do post-move cleanup
|
|
if (change_pos) {
|
|
for (auto ptr = GET_FIRST(&obj_used_list); ptr != END_OF_LIST(&obj_used_list); ptr = GET_NEXT(ptr)) {
|
|
if (ptr->flags[Object::Object_Flags::Marked]) {
|
|
object_moved(ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
theApp.record_window_data(&Object_wnd_data, this);
|
|
CDialog::OnOK();
|
|
|
|
FREDDoc_ptr->autosave("object editor");
|
|
}
|
|
|
|
void orient_editor::actually_point_object(object *ptr)
|
|
{
|
|
if (ptr->type != OBJ_WAYPOINT && m_point_to) {
|
|
vec3d v, loc;
|
|
matrix m;
|
|
|
|
vm_vec_zero(&v);
|
|
loc.xyz.x = convert(m_location_x);
|
|
loc.xyz.y = convert(m_location_y);
|
|
loc.xyz.z = convert(m_location_z);
|
|
|
|
if (((CButton *) GetDlgItem(IDC_POINT_TO_OBJECT))->GetCheck() == TRUE) {
|
|
if (m_object_index >= 0) {
|
|
v = Objects[index[m_object_index]].pos;
|
|
vm_vec_sub2(&v, &ptr->pos);
|
|
}
|
|
} else if (((CButton *) GetDlgItem(IDC_POINT_TO_LOCATION))->GetCheck() == TRUE) {
|
|
vm_vec_sub(&v, &loc, &ptr->pos);
|
|
|
|
} else {
|
|
Assertion(0, "neither radio button is checked!");
|
|
return;
|
|
}
|
|
|
|
if (IS_VEC_NULL(&v)) {
|
|
return; // can't point to itself.
|
|
}
|
|
|
|
auto uvec = Point_using_uvec ? &ptr->orient.vec.uvec : nullptr;
|
|
|
|
vm_vector_2_matrix(&m, &v, uvec, nullptr);
|
|
ptr->orient = m;
|
|
}
|
|
}
|
|
|
|
float orient_editor::to_degrees(float rad)
|
|
{
|
|
float deg = fl_degrees(rad);
|
|
return normalize_degrees(deg);
|
|
}
|
|
|
|
/**
|
|
* Extract a float from the CString, being mindful of any comma separators.
|
|
*/
|
|
float orient_editor::convert(const CString &str) const
|
|
{
|
|
char buf[256];
|
|
size_t i, j, len;
|
|
|
|
string_copy(buf, str, 256 - 1);
|
|
len = strlen(buf);
|
|
for (i=j=0; i<len; i++)
|
|
if (buf[i] != ',')
|
|
buf[j++] = buf[i];
|
|
|
|
buf[j] = 0;
|
|
|
|
float val = (float)atof(buf);
|
|
|
|
// disallow input larger than INT_MAX
|
|
if (val > (float)INT_MAX) {
|
|
val = (float)INT_MAX;
|
|
}
|
|
|
|
// disallow input smaller than INT_MIN
|
|
if (val < (float)INT_MIN) {
|
|
val = (float)INT_MIN;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
/**
|
|
* Perform rounding of the float value by loading it into the input box format string and parsing it again.
|
|
* This accounts for not only decimal rounding to the precision of the input box, but also floating point rounding due to inexact fractions such as 1/10.
|
|
* See also GitHub PR #4475.
|
|
*/
|
|
float orient_editor::perform_input_rounding(float val) const
|
|
{
|
|
CString str;
|
|
str.Format(INPUT_FORMAT, val);
|
|
return convert(str);
|
|
}
|
|
|
|
void orient_editor::OnObjectSelected()
|
|
{
|
|
((CButton*)GetDlgItem(IDC_POINT_TO_OBJECT))->SetCheck(TRUE);
|
|
((CButton*)GetDlgItem(IDC_POINT_TO_LOCATION))->SetCheck(FALSE);
|
|
OnPointToObject();
|
|
}
|
|
|
|
void orient_editor::OnPointTo()
|
|
{
|
|
UpdateData(TRUE);
|
|
|
|
GetDlgItem(IDC_ORIENTATION_P)->EnableWindow(!m_point_to);
|
|
GetDlgItem(IDC_ORIENTATION_B)->EnableWindow(!m_point_to);
|
|
GetDlgItem(IDC_ORIENTATION_H)->EnableWindow(!m_point_to);
|
|
GetDlgItem(IDC_SPIN11)->EnableWindow(!m_point_to);
|
|
GetDlgItem(IDC_SPIN12)->EnableWindow(!m_point_to);
|
|
GetDlgItem(IDC_SPIN13)->EnableWindow(!m_point_to);
|
|
}
|
|
|
|
void orient_editor::OnPointToObject()
|
|
{
|
|
((CButton*)GetDlgItem(IDC_POINT_TO_CHECKBOX))->SetCheck(TRUE);
|
|
OnPointTo();
|
|
}
|
|
|
|
void orient_editor::OnPointToLocation()
|
|
{
|
|
((CButton*)GetDlgItem(IDC_POINT_TO_CHECKBOX))->SetCheck(TRUE);
|
|
OnPointTo();
|
|
}
|
|
|
|
void orient_editor::OnSetAbsolute()
|
|
{
|
|
// prevent redundant calculations if the button is clicked while selected
|
|
if (!set_relative)
|
|
return;
|
|
set_relative = false;
|
|
|
|
UpdateData(TRUE);
|
|
|
|
vec3d pos;
|
|
pos.xyz.x = convert(m_position_x);
|
|
pos.xyz.y = convert(m_position_y);
|
|
pos.xyz.z = convert(m_position_z);
|
|
|
|
angles ang;
|
|
ang.p = fl_radians(convert(m_orientation_p));
|
|
ang.b = fl_radians(convert(m_orientation_b));
|
|
ang.h = fl_radians(convert(m_orientation_h));
|
|
|
|
vm_vec_add2(&pos, &Objects[cur_object_index].pos);
|
|
|
|
angles object_ang;
|
|
vm_extract_angles_matrix(&object_ang, &Objects[cur_object_index].orient);
|
|
ang.p += object_ang.p;
|
|
ang.b += object_ang.b;
|
|
ang.h += object_ang.h;
|
|
|
|
m_position_x.Format(INPUT_FORMAT, pos.xyz.x);
|
|
m_position_y.Format(INPUT_FORMAT, pos.xyz.y);
|
|
m_position_z.Format(INPUT_FORMAT, pos.xyz.z);
|
|
|
|
m_orientation_p.Format(INPUT_FORMAT, to_degrees(ang.p));
|
|
m_orientation_b.Format(INPUT_FORMAT, to_degrees(ang.b));
|
|
m_orientation_h.Format(INPUT_FORMAT, to_degrees(ang.h));
|
|
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
void orient_editor::OnSetRelative()
|
|
{
|
|
// prevent redundant calculations if the button is clicked while selected
|
|
if (set_relative)
|
|
return;
|
|
set_relative = true;
|
|
|
|
UpdateData(TRUE);
|
|
|
|
vec3d pos;
|
|
pos.xyz.x = convert(m_position_x);
|
|
pos.xyz.y = convert(m_position_y);
|
|
pos.xyz.z = convert(m_position_z);
|
|
|
|
angles ang;
|
|
ang.p = fl_radians(convert(m_orientation_p));
|
|
ang.b = fl_radians(convert(m_orientation_b));
|
|
ang.h = fl_radians(convert(m_orientation_h));
|
|
|
|
vm_vec_sub2(&pos, &Objects[cur_object_index].pos);
|
|
|
|
angles object_ang;
|
|
vm_extract_angles_matrix(&object_ang, &Objects[cur_object_index].orient);
|
|
ang.p -= object_ang.p;
|
|
ang.b -= object_ang.b;
|
|
ang.h -= object_ang.h;
|
|
|
|
m_position_x.Format(INPUT_FORMAT, pos.xyz.x);
|
|
m_position_y.Format(INPUT_FORMAT, pos.xyz.y);
|
|
m_position_z.Format(INPUT_FORMAT, pos.xyz.z);
|
|
|
|
m_orientation_p.Format(INPUT_FORMAT, to_degrees(ang.p));
|
|
m_orientation_b.Format(INPUT_FORMAT, to_degrees(ang.b));
|
|
m_orientation_h.Format(INPUT_FORMAT, to_degrees(ang.h));
|
|
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
void orient_editor::OnCancel()
|
|
{
|
|
theApp.record_window_data(&Object_wnd_data, this);
|
|
CDialog::OnCancel();
|
|
}
|
|
|
|
void orient_editor::OnClose()
|
|
{
|
|
int z;
|
|
|
|
if (query_modified()) {
|
|
z = MessageBox("Do you want to keep your changes?", "Close", MB_ICONQUESTION | MB_YESNOCANCEL);
|
|
if (z == IDCANCEL)
|
|
return;
|
|
|
|
if (z == IDYES) {
|
|
OnOK();
|
|
return;
|
|
}
|
|
}
|
|
|
|
CDialog::OnClose();
|
|
}
|