History

Move ModelPropertiesDialog to own file

Atlante45 committed 11 years ago

Commit 8bb974f1 parent f1460e52 files · +327 −0Browse files

Showing the changes to interface/src/ModelPropertiesDialog.cpp (1 of 2 files). Show all

Unified · Split

interface/src/ModelPropertiesDialog.cpp+244−0
@@ -0,0 +1,244 @@
1+//
2+// ModelPropertiesDialog.cpp
3+//
4+//
5+// Created by Clement on 3/10/15.
6+// Copyright 2015 High Fidelity, Inc.
7+//
8+// Distributed under the Apache License, Version 2.0.
9+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10+//
11+
12+#include <QCheckBox>
13+#include <QComboBox>
14+#include <QDialogButtonBox>
15+#include <QDoubleSpinBox>
16+#include <QFileDialog>
17+#include <QFormLayout>
18+#include <QLineEdit>
19+#include <QMessageBox>
20+#include <QPushButton>
21+
22+#include <GLMHelpers.h>
23+
24+#include "ModelPropertiesDialog.h"
25+
26+
27+ModelPropertiesDialog::ModelPropertiesDialog(ModelType modelType, const QVariantHash& originalMapping,
28+ const QString& basePath, const FBXGeometry& geometry) :
29+_modelType(modelType),
30+_originalMapping(originalMapping),
31+_basePath(basePath),
32+_geometry(geometry)
33+{
34+ setWindowTitle("Set Model Properties");
35+
36+ QFormLayout* form = new QFormLayout();
37+ setLayout(form);
38+
39+ form->addRow("Name:", _name = new QLineEdit());
40+
41+ form->addRow("Texture Directory:", _textureDirectory = new QPushButton());
42+ connect(_textureDirectory, SIGNAL(clicked(bool)), SLOT(chooseTextureDirectory()));
43+
44+ form->addRow("Scale:", _scale = new QDoubleSpinBox());
45+ _scale->setMaximum(FLT_MAX);
46+ _scale->setSingleStep(0.01);
47+
48+ if (_modelType != ENTITY_MODEL) {
49+ if (_modelType == ATTACHMENT_MODEL) {
50+ QHBoxLayout* translation = new QHBoxLayout();
51+ form->addRow("Translation:", translation);
52+ translation->addWidget(_translationX = createTranslationBox());
53+ translation->addWidget(_translationY = createTranslationBox());
54+ translation->addWidget(_translationZ = createTranslationBox());
55+ form->addRow("Pivot About Center:", _pivotAboutCenter = new QCheckBox());
56+ form->addRow("Pivot Joint:", _pivotJoint = createJointBox());
57+ connect(_pivotAboutCenter, SIGNAL(toggled(bool)), SLOT(updatePivotJoint()));
58+ _pivotAboutCenter->setChecked(true);
59+
60+ } else {
61+ form->addRow("Left Eye Joint:", _leftEyeJoint = createJointBox());
62+ form->addRow("Right Eye Joint:", _rightEyeJoint = createJointBox());
63+ form->addRow("Neck Joint:", _neckJoint = createJointBox());
64+ }
65+ if (_modelType == SKELETON_MODEL) {
66+ form->addRow("Root Joint:", _rootJoint = createJointBox());
67+ form->addRow("Lean Joint:", _leanJoint = createJointBox());
68+ form->addRow("Head Joint:", _headJoint = createJointBox());
69+ form->addRow("Left Hand Joint:", _leftHandJoint = createJointBox());
70+ form->addRow("Right Hand Joint:", _rightHandJoint = createJointBox());
71+
72+ form->addRow("Free Joints:", _freeJoints = new QVBoxLayout());
73+ QPushButton* newFreeJoint = new QPushButton("New Free Joint");
74+ _freeJoints->addWidget(newFreeJoint);
75+ connect(newFreeJoint, SIGNAL(clicked(bool)), SLOT(createNewFreeJoint()));
76+ }
77+ }
78+
79+ QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok |
80+ QDialogButtonBox::Cancel | QDialogButtonBox::Reset);
81+ connect(buttons, SIGNAL(accepted()), SLOT(accept()));
82+ connect(buttons, SIGNAL(rejected()), SLOT(reject()));
83+ connect(buttons->button(QDialogButtonBox::Reset), SIGNAL(clicked(bool)), SLOT(reset()));
84+
85+ form->addRow(buttons);
86+
87+ // reset to initialize the fields
88+ reset();
89+}
90+
91+QVariantHash ModelPropertiesDialog::getMapping() const {
92+ QVariantHash mapping = _originalMapping;
93+ mapping.insert(NAME_FIELD, _name->text());
94+ mapping.insert(TEXDIR_FIELD, _textureDirectory->text());
95+ mapping.insert(SCALE_FIELD, QString::number(_scale->value()));
96+
97+ // update the joint indices
98+ QVariantHash jointIndices;
99+ for (int i = 0; i < _geometry.joints.size(); i++) {
100+ jointIndices.insert(_geometry.joints.at(i).name, QString::number(i));
101+ }
102+ mapping.insert(JOINT_INDEX_FIELD, jointIndices);
103+
104+ if (_modelType != ENTITY_MODEL) {
105+ QVariantHash joints = mapping.value(JOINT_FIELD).toHash();
106+ if (_modelType == ATTACHMENT_MODEL) {
107+ glm::vec3 pivot;
108+ if (_pivotAboutCenter->isChecked()) {
109+ pivot = (_geometry.meshExtents.minimum + _geometry.meshExtents.maximum) * 0.5f;
110+
111+ } else if (_pivotJoint->currentIndex() != 0) {
112+ pivot = extractTranslation(_geometry.joints.at(_pivotJoint->currentIndex() - 1).transform);
113+ }
114+ mapping.insert(TRANSLATION_X_FIELD, -pivot.x * _scale->value() + _translationX->value());
115+ mapping.insert(TRANSLATION_Y_FIELD, -pivot.y * _scale->value() + _translationY->value());
116+ mapping.insert(TRANSLATION_Z_FIELD, -pivot.z * _scale->value() + _translationZ->value());
117+
118+ } else {
119+ insertJointMapping(joints, "jointEyeLeft", _leftEyeJoint->currentText());
120+ insertJointMapping(joints, "jointEyeRight", _rightEyeJoint->currentText());
121+ insertJointMapping(joints, "jointNeck", _neckJoint->currentText());
122+ }
123+ if (_modelType == SKELETON_MODEL) {
124+ insertJointMapping(joints, "jointRoot", _rootJoint->currentText());
125+ insertJointMapping(joints, "jointLean", _leanJoint->currentText());
126+ insertJointMapping(joints, "jointHead", _headJoint->currentText());
127+ insertJointMapping(joints, "jointLeftHand", _leftHandJoint->currentText());
128+ insertJointMapping(joints, "jointRightHand", _rightHandJoint->currentText());
129+
130+ mapping.remove(FREE_JOINT_FIELD);
131+ for (int i = 0; i < _freeJoints->count() - 1; i++) {
132+ QComboBox* box = static_cast<QComboBox*>(_freeJoints->itemAt(i)->widget()->layout()->itemAt(0)->widget());
133+ mapping.insertMulti(FREE_JOINT_FIELD, box->currentText());
134+ }
135+ }
136+ mapping.insert(JOINT_FIELD, joints);
137+ }
138+
139+ return mapping;
140+}
141+
142+static void setJointText(QComboBox* box, const QString& text) {
143+ box->setCurrentIndex(qMax(box->findText(text), 0));
144+}
145+
146+void ModelPropertiesDialog::reset() {
147+ _name->setText(_originalMapping.value(NAME_FIELD).toString());
148+ _textureDirectory->setText(_originalMapping.value(TEXDIR_FIELD).toString());
149+ _scale->setValue(_originalMapping.value(SCALE_FIELD).toDouble());
150+
151+ QVariantHash jointHash = _originalMapping.value(JOINT_FIELD).toHash();
152+
153+ if (_modelType != ENTITY_MODEL) {
154+ if (_modelType == ATTACHMENT_MODEL) {
155+ _translationX->setValue(_originalMapping.value(TRANSLATION_X_FIELD).toDouble());
156+ _translationY->setValue(_originalMapping.value(TRANSLATION_Y_FIELD).toDouble());
157+ _translationZ->setValue(_originalMapping.value(TRANSLATION_Z_FIELD).toDouble());
158+ _pivotAboutCenter->setChecked(true);
159+ _pivotJoint->setCurrentIndex(0);
160+
161+ } else {
162+ setJointText(_leftEyeJoint, jointHash.value("jointEyeLeft").toString());
163+ setJointText(_rightEyeJoint, jointHash.value("jointEyeRight").toString());
164+ setJointText(_neckJoint, jointHash.value("jointNeck").toString());
165+ }
166+ if (_modelType == SKELETON_MODEL) {
167+ setJointText(_rootJoint, jointHash.value("jointRoot").toString());
168+ setJointText(_leanJoint, jointHash.value("jointLean").toString());
169+ setJointText(_headJoint, jointHash.value("jointHead").toString());
170+ setJointText(_leftHandJoint, jointHash.value("jointLeftHand").toString());
171+ setJointText(_rightHandJoint, jointHash.value("jointRightHand").toString());
172+
173+ while (_freeJoints->count() > 1) {
174+ delete _freeJoints->itemAt(0)->widget();
175+ }
176+ foreach (const QVariant& joint, _originalMapping.values(FREE_JOINT_FIELD)) {
177+ QString jointName = joint.toString();
178+ if (_geometry.jointIndices.contains(jointName)) {
179+ createNewFreeJoint(jointName);
180+ }
181+ }
182+ }
183+ }
184+}
185+
186+void ModelPropertiesDialog::chooseTextureDirectory() {
187+ QString directory = QFileDialog::getExistingDirectory(this, "Choose Texture Directory",
188+ _basePath + "/" + _textureDirectory->text());
189+ if (directory.isEmpty()) {
190+ return;
191+ }
192+ if (!directory.startsWith(_basePath)) {
193+ QMessageBox::warning(NULL, "Invalid texture directory", "Texture directory must be child of base path.");
194+ return;
195+ }
196+ _textureDirectory->setText(directory.length() == _basePath.length() ? "." : directory.mid(_basePath.length() + 1));
197+}
198+
199+void ModelPropertiesDialog::updatePivotJoint() {
200+ _pivotJoint->setEnabled(!_pivotAboutCenter->isChecked());
201+}
202+
203+void ModelPropertiesDialog::createNewFreeJoint(const QString& joint) {
204+ QWidget* freeJoint = new QWidget();
205+ QHBoxLayout* freeJointLayout = new QHBoxLayout();
206+ freeJointLayout->setContentsMargins(QMargins());
207+ freeJoint->setLayout(freeJointLayout);
208+ QComboBox* jointBox = createJointBox(false);
209+ jointBox->setCurrentText(joint);
210+ freeJointLayout->addWidget(jointBox, 1);
211+ QPushButton* deleteJoint = new QPushButton("Delete");
212+ freeJointLayout->addWidget(deleteJoint);
213+ freeJoint->connect(deleteJoint, SIGNAL(clicked(bool)), SLOT(deleteLater()));
214+ _freeJoints->insertWidget(_freeJoints->count() - 1, freeJoint);
215+}
216+
217+QComboBox* ModelPropertiesDialog::createJointBox(bool withNone) const {
218+ QComboBox* box = new QComboBox();
219+ if (withNone) {
220+ box->addItem("(none)");
221+ }
222+ foreach (const FBXJoint& joint, _geometry.joints) {
223+ if (joint.isSkeletonJoint || !_geometry.hasSkeletonJoints) {
224+ box->addItem(joint.name);
225+ }
226+ }
227+ return box;
228+}
229+
230+QDoubleSpinBox* ModelPropertiesDialog::createTranslationBox() const {
231+ QDoubleSpinBox* box = new QDoubleSpinBox();
232+ const double MAX_TRANSLATION = 1000000.0;
233+ box->setMinimum(-MAX_TRANSLATION);
234+ box->setMaximum(MAX_TRANSLATION);
235+ return box;
236+}
237+
238+void ModelPropertiesDialog::insertJointMapping(QVariantHash& joints, const QString& joint, const QString& name) const {
239+ if (_geometry.jointIndices.contains(name)) {
240+ joints.insert(joint, name);
241+ } else {
242+ joints.remove(joint);
243+ }
244+}