From 618992610534392d509307f086d7518e1f5a3e9f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Mar 2015 13:23:29 -0700 Subject: [PATCH 01/16] add type hint to FST in model packager --- interface/src/Menu.h | 2 +- interface/src/ModelPackager.cpp | 24 +++++++++------- interface/src/ModelPropertiesDialog.cpp | 37 +++++++++++++++++++++++-- interface/src/ModelPropertiesDialog.h | 1 + interface/src/ModelSelector.cpp | 10 +++++-- interface/src/ui/ModelsBrowser.cpp | 2 +- interface/src/ui/ModelsBrowser.h | 3 +- interface/src/ui/PreferencesDialog.cpp | 2 +- libraries/fbx/src/FSTReader.cpp | 2 +- libraries/fbx/src/FSTReader.h | 1 + 10 files changed, 63 insertions(+), 21 deletions(-) diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b3d2d548df..508d684c3e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -247,7 +247,7 @@ namespace MenuOption { const QString ToolWindow = "Tool Window"; const QString TransmitterDrive = "Transmitter Drive"; const QString TurnWithHead = "Turn using Head"; - const QString PackageModel = "Package Model"; + const QString PackageModel = "Package Model..."; const QString Visage = "Visage"; const QString Wireframe = "Wireframe"; } diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index f552d67a98..0cf1fdddc7 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -204,6 +204,17 @@ bool ModelPackager::zipModel() { } void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename, const FBXGeometry& geometry) { + + + // mixamo files - in the event that a mixamo file was edited by some other tool, it's likely the applicationName will + // be rewritten, so we detect the existence of several different blendshapes which indicate we're likely a mixamo file + bool likelyMixamoFile = geometry.applicationName == "mixamo.com" || + (geometry.blendshapeChannelNames.contains("BrowsDown_Right") && + geometry.blendshapeChannelNames.contains("MouthOpen") && + geometry.blendshapeChannelNames.contains("Blink_Left") && + geometry.blendshapeChannelNames.contains("Blink_Right") && + geometry.blendshapeChannelNames.contains("Squint_Right")); + if (!mapping.contains(NAME_FIELD)) { mapping.insert(NAME_FIELD, QFileInfo(filename).baseName()); } @@ -239,7 +250,7 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename joints.insert("jointLean", "Spine"); } if (!joints.contains("jointHead")) { - const char* topName = (geometry.applicationName == "mixamo.com") ? "HeadTop_End" : "HeadEnd"; + const char* topName = likelyMixamoFile ? "HeadTop_End" : "HeadEnd"; joints.insert("jointHead", geometry.jointIndices.contains(topName) ? topName : "Head"); } if (!joints.contains("jointLeftHand")) { @@ -256,15 +267,8 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename mapping.insertMulti(FREE_JOINT_FIELD, "RightForeArm"); } - // mixamo blendshapes - in the event that a mixamo file was edited by some other tool, it's likely the applicationName will - // be rewritten, so we detect the existence of several different blendshapes which indicate we're likely a mixamo file - bool likelyMixamoFile = geometry.applicationName == "mixamo.com" || - (geometry.blendshapeChannelNames.contains("BrowsDown_Right") && - geometry.blendshapeChannelNames.contains("MouthOpen") && - geometry.blendshapeChannelNames.contains("Blink_Left") && - geometry.blendshapeChannelNames.contains("Blink_Right") && - geometry.blendshapeChannelNames.contains("Squint_Right")); - + // If there are no blendshape mappings, and we detect that this is likely a mixamo file, + // then we can add the default mixamo to "faceshift" mappings if (!mapping.contains(BLENDSHAPE_FIELD) && likelyMixamoFile) { QVariantHash blendshapes; blendshapes.insertMulti("BrowsD_L", QVariantList() << "BrowsDown_Left" << 1.0); diff --git a/interface/src/ModelPropertiesDialog.cpp b/interface/src/ModelPropertiesDialog.cpp index 81fe9ce7fd..c8c5669ce7 100644 --- a/interface/src/ModelPropertiesDialog.cpp +++ b/interface/src/ModelPropertiesDialog.cpp @@ -63,7 +63,7 @@ _geometry(geometry) form->addRow("Right Eye Joint:", _rightEyeJoint = createJointBox()); form->addRow("Neck Joint:", _neckJoint = createJointBox()); } - if (_modelType == SKELETON_MODEL) { + if (_modelType == BODY_ONLY_MODEL || _modelType == HEAD_AND_BODY_MODEL) { form->addRow("Root Joint:", _rootJoint = createJointBox()); form->addRow("Lean Joint:", _leanJoint = createJointBox()); form->addRow("Head Joint:", _headJoint = createJointBox()); @@ -89,8 +89,36 @@ _geometry(geometry) reset(); } + +QString ModelPropertiesDialog::getType() const { + QString type = "unknown"; + switch(_modelType) { + case ENTITY_MODEL: + type = "entity"; + break; + + case HEAD_MODEL: + type = "head"; + break; + + case BODY_ONLY_MODEL: + type = "body"; + break; + + case HEAD_AND_BODY_MODEL: + type = "body+head"; + break; + + case ATTACHMENT_MODEL: + type = "attachment"; + break; + } + return type; +} + QVariantHash ModelPropertiesDialog::getMapping() const { QVariantHash mapping = _originalMapping; + mapping.insert(TYPE_FIELD, getType()); mapping.insert(NAME_FIELD, _name->text()); mapping.insert(TEXDIR_FIELD, _textureDirectory->text()); mapping.insert(SCALE_FIELD, QString::number(_scale->value())); @@ -121,7 +149,9 @@ QVariantHash ModelPropertiesDialog::getMapping() const { insertJointMapping(joints, "jointEyeRight", _rightEyeJoint->currentText()); insertJointMapping(joints, "jointNeck", _neckJoint->currentText()); } - if (_modelType == SKELETON_MODEL) { + + + if (_modelType == BODY_ONLY_MODEL || _modelType == HEAD_AND_BODY_MODEL) { insertJointMapping(joints, "jointRoot", _rootJoint->currentText()); insertJointMapping(joints, "jointLean", _leanJoint->currentText()); insertJointMapping(joints, "jointHead", _headJoint->currentText()); @@ -164,7 +194,8 @@ void ModelPropertiesDialog::reset() { setJointText(_rightEyeJoint, jointHash.value("jointEyeRight").toString()); setJointText(_neckJoint, jointHash.value("jointNeck").toString()); } - if (_modelType == SKELETON_MODEL) { + + if (_modelType == BODY_ONLY_MODEL || _modelType == HEAD_AND_BODY_MODEL) { setJointText(_rootJoint, jointHash.value("jointRoot").toString()); setJointText(_leanJoint, jointHash.value("jointLean").toString()); setJointText(_headJoint, jointHash.value("jointHead").toString()); diff --git a/interface/src/ModelPropertiesDialog.h b/interface/src/ModelPropertiesDialog.h index 5af4d173f1..e2335acc23 100644 --- a/interface/src/ModelPropertiesDialog.h +++ b/interface/src/ModelPropertiesDialog.h @@ -43,6 +43,7 @@ private: QComboBox* createJointBox(bool withNone = true) const; QDoubleSpinBox* createTranslationBox() const; void insertJointMapping(QVariantHash& joints, const QString& joint, const QString& name) const; + QString getType() const; ModelType _modelType; QVariantHash _originalMapping; diff --git a/interface/src/ModelSelector.cpp b/interface/src/ModelSelector.cpp index c55d77dc00..23746e0137 100644 --- a/interface/src/ModelSelector.cpp +++ b/interface/src/ModelSelector.cpp @@ -18,8 +18,9 @@ #include "ModelSelector.h" -static const QString AVATAR_HEAD_STRING = "Avatar Head"; -static const QString AVATAR_BODY_STRING = "Avatar Body"; +static const QString AVATAR_HEAD_STRING = "Avatar Head Only"; +static const QString AVATAR_BODY_STRING = "Avatar Body Only"; +static const QString AVATAR_HEAD_AND_BODY_STRING = "Avatar Body with Head"; static const QString AVATAR_ATTACHEMENT_STRING = "Avatar Attachment"; static const QString ENTITY_MODEL_STRING = "Entity Model"; @@ -36,6 +37,7 @@ ModelSelector::ModelSelector() { _modelType = new QComboBox(this); _modelType->addItem(AVATAR_HEAD_STRING); _modelType->addItem(AVATAR_BODY_STRING); + _modelType->addItem(AVATAR_HEAD_AND_BODY_STRING); _modelType->addItem(AVATAR_ATTACHEMENT_STRING); _modelType->addItem(ENTITY_MODEL_STRING); form->addRow("Model Type:", _modelType); @@ -56,7 +58,9 @@ ModelType ModelSelector::getModelType() const { if (text == AVATAR_HEAD_STRING) { return HEAD_MODEL; } else if (text == AVATAR_BODY_STRING) { - return SKELETON_MODEL; + return BODY_ONLY_MODEL; + } else if (text == AVATAR_HEAD_AND_BODY_STRING) { + return HEAD_AND_BODY_MODEL; } else if (text == AVATAR_ATTACHEMENT_STRING) { return ATTACHMENT_MODEL; } else if (text == ENTITY_MODEL_STRING) { diff --git a/interface/src/ui/ModelsBrowser.cpp b/interface/src/ui/ModelsBrowser.cpp index 070c6a85cc..96c89b332d 100644 --- a/interface/src/ui/ModelsBrowser.cpp +++ b/interface/src/ui/ModelsBrowser.cpp @@ -28,7 +28,7 @@ #include "ModelsBrowser.h" -const char* MODEL_TYPE_NAMES[] = { "entities", "heads", "skeletons", "attachments" }; +const char* MODEL_TYPE_NAMES[] = { "entities", "heads", "skeletons", "skeletons", "attachments" }; static const QString S3_URL = "http://s3.amazonaws.com/hifi-public"; static const QString PUBLIC_URL = "http://public.highfidelity.io"; diff --git a/interface/src/ui/ModelsBrowser.h b/interface/src/ui/ModelsBrowser.h index 0c8bb59c85..207a7f8c4e 100644 --- a/interface/src/ui/ModelsBrowser.h +++ b/interface/src/ui/ModelsBrowser.h @@ -21,7 +21,8 @@ class QNetworkReply; enum ModelType { ENTITY_MODEL, HEAD_MODEL, - SKELETON_MODEL, + BODY_ONLY_MODEL, + HEAD_AND_BODY_MODEL, ATTACHMENT_MODEL }; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index a07de371a2..eddf009782 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -73,7 +73,7 @@ void PreferencesDialog::openHeadModelBrowser() { } void PreferencesDialog::openBodyModelBrowser() { - ModelsBrowser modelBrowser(SKELETON_MODEL); + ModelsBrowser modelBrowser(HEAD_AND_BODY_MODEL); connect(&modelBrowser, &ModelsBrowser::selected, this, &PreferencesDialog::setSkeletonUrl); modelBrowser.browse(); } diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index f1ffe11996..623f303c43 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -77,7 +77,7 @@ void writeVariant(QBuffer& buffer, QVariantHash::const_iterator& it) { } QByteArray writeMapping(const QVariantHash& mapping) { - static const QStringList PREFERED_ORDER = QStringList() << NAME_FIELD << SCALE_FIELD << FILENAME_FIELD + static const QStringList PREFERED_ORDER = QStringList() << NAME_FIELD << TYPE_FIELD << SCALE_FIELD << FILENAME_FIELD << TEXDIR_FIELD << JOINT_FIELD << FREE_JOINT_FIELD << BLENDSHAPE_FIELD << JOINT_INDEX_FIELD; QBuffer buffer; diff --git a/libraries/fbx/src/FSTReader.h b/libraries/fbx/src/FSTReader.h index 59559dea74..7f71403a28 100644 --- a/libraries/fbx/src/FSTReader.h +++ b/libraries/fbx/src/FSTReader.h @@ -15,6 +15,7 @@ #include static const QString NAME_FIELD = "name"; +static const QString TYPE_FIELD = "type"; static const QString FILENAME_FIELD = "filename"; static const QString TEXDIR_FIELD = "texdir"; static const QString LOD_FIELD = "lod"; From baa2f947e5ddb7d42888718910a2299164d4d29b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Mar 2015 16:30:00 -0700 Subject: [PATCH 02/16] classifying FSTReader and moving ModelType into that class --- interface/src/ModelPackager.cpp | 47 ++++++---- interface/src/ModelPackager.h | 2 +- interface/src/ModelPropertiesDialog.cpp | 44 +++------- interface/src/ModelPropertiesDialog.h | 5 +- interface/src/ModelSelector.cpp | 12 +-- interface/src/ModelSelector.h | 2 +- .../scripting/WindowScriptingInterface.cpp | 2 +- interface/src/ui/AttachmentsDialog.cpp | 2 +- interface/src/ui/ModelsBrowser.cpp | 4 +- interface/src/ui/ModelsBrowser.h | 16 ++-- interface/src/ui/PreferencesDialog.cpp | 4 +- libraries/fbx/src/FSTReader.cpp | 85 +++++++++++++++++-- libraries/fbx/src/FSTReader.h | 36 +++++++- libraries/render-utils/src/GeometryCache.cpp | 2 +- libraries/shared/src/StreamUtils.cpp | 8 ++ libraries/shared/src/StreamUtils.h | 2 + 16 files changed, 184 insertions(+), 89 deletions(-) diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index 0cf1fdddc7..a06dc05160 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -85,7 +85,7 @@ bool ModelPackager::loadModel() { return false; } qDebug() << "Reading FST file : " << _modelFile.filePath(); - _mapping = readMapping(fst.readAll()); + _mapping = FSTReader::readMapping(fst.readAll()); fst.close(); _fbxInfo = QFileInfo(_modelFile.path() + "/" + _mapping.value(FILENAME_FIELD).toString()); @@ -120,6 +120,7 @@ bool ModelPackager::editProperties() { } _mapping = properties.getMapping(); + /* // Make sure that a mapping for the root joint has been specified QVariantHash joints = _mapping.value(JOINT_FIELD).toHash(); if (!joints.contains("jointRoot")) { @@ -135,6 +136,7 @@ bool ModelPackager::editProperties() { return false; } + */ return true; } @@ -183,7 +185,7 @@ bool ModelPackager::zipModel() { // Copy FST QFile fst(tempDir.path() + "/" + nameField + ".fst"); if (fst.open(QIODevice::WriteOnly)) { - fst.write(writeMapping(_mapping)); + fst.write(FSTReader::writeMapping(_mapping)); fst.close(); } else { qDebug() << "Couldn't write FST file" << fst.fileName(); @@ -205,6 +207,7 @@ bool ModelPackager::zipModel() { void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename, const FBXGeometry& geometry) { + bool isBodyType = _modelType == FSTReader::BODY_ONLY_MODEL || _modelType == FSTReader::HEAD_AND_BODY_MODEL; // mixamo files - in the event that a mixamo file was edited by some other tool, it's likely the applicationName will // be rewritten, so we detect the existence of several different blendshapes which indicate we're likely a mixamo file @@ -243,28 +246,36 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename if (!joints.contains("jointNeck")) { joints.insert("jointNeck", geometry.jointIndices.contains("jointNeck") ? "jointNeck" : "Neck"); } - if (!joints.contains("jointRoot")) { - joints.insert("jointRoot", "Hips"); - } - if (!joints.contains("jointLean")) { - joints.insert("jointLean", "Spine"); + + if (isBodyType) { + if (!joints.contains("jointRoot")) { + joints.insert("jointRoot", "Hips"); + } + if (!joints.contains("jointLean")) { + joints.insert("jointLean", "Spine"); + } + if (!joints.contains("jointLeftHand")) { + joints.insert("jointLeftHand", "LeftHand"); + } + if (!joints.contains("jointRightHand")) { + joints.insert("jointRightHand", "RightHand"); + } } + if (!joints.contains("jointHead")) { const char* topName = likelyMixamoFile ? "HeadTop_End" : "HeadEnd"; joints.insert("jointHead", geometry.jointIndices.contains(topName) ? topName : "Head"); } - if (!joints.contains("jointLeftHand")) { - joints.insert("jointLeftHand", "LeftHand"); - } - if (!joints.contains("jointRightHand")) { - joints.insert("jointRightHand", "RightHand"); - } + mapping.insert(JOINT_FIELD, joints); - if (!mapping.contains(FREE_JOINT_FIELD)) { - mapping.insertMulti(FREE_JOINT_FIELD, "LeftArm"); - mapping.insertMulti(FREE_JOINT_FIELD, "LeftForeArm"); - mapping.insertMulti(FREE_JOINT_FIELD, "RightArm"); - mapping.insertMulti(FREE_JOINT_FIELD, "RightForeArm"); + + if (isBodyType) { + if (!mapping.contains(FREE_JOINT_FIELD)) { + mapping.insertMulti(FREE_JOINT_FIELD, "LeftArm"); + mapping.insertMulti(FREE_JOINT_FIELD, "LeftForeArm"); + mapping.insertMulti(FREE_JOINT_FIELD, "RightArm"); + mapping.insertMulti(FREE_JOINT_FIELD, "RightForeArm"); + } } // If there are no blendshape mappings, and we detect that this is likely a mixamo file, diff --git a/interface/src/ModelPackager.h b/interface/src/ModelPackager.h index 2c90395e56..c681ae436f 100644 --- a/interface/src/ModelPackager.h +++ b/interface/src/ModelPackager.h @@ -35,7 +35,7 @@ private: QFileInfo _modelFile; QFileInfo _fbxInfo; - ModelType _modelType; + FSTReader::ModelType _modelType; QString _texDir; QVariantHash _mapping; diff --git a/interface/src/ModelPropertiesDialog.cpp b/interface/src/ModelPropertiesDialog.cpp index c8c5669ce7..28a50205c9 100644 --- a/interface/src/ModelPropertiesDialog.cpp +++ b/interface/src/ModelPropertiesDialog.cpp @@ -25,7 +25,7 @@ #include "ModelPropertiesDialog.h" -ModelPropertiesDialog::ModelPropertiesDialog(ModelType modelType, const QVariantHash& originalMapping, +ModelPropertiesDialog::ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping, const QString& basePath, const FBXGeometry& geometry) : _modelType(modelType), _originalMapping(originalMapping), @@ -46,8 +46,8 @@ _geometry(geometry) _scale->setMaximum(FLT_MAX); _scale->setSingleStep(0.01); - if (_modelType != ENTITY_MODEL) { - if (_modelType == ATTACHMENT_MODEL) { + if (_modelType != FSTReader::ENTITY_MODEL) { + if (_modelType == FSTReader::ATTACHMENT_MODEL) { QHBoxLayout* translation = new QHBoxLayout(); form->addRow("Translation:", translation); translation->addWidget(_translationX = createTranslationBox()); @@ -63,7 +63,7 @@ _geometry(geometry) form->addRow("Right Eye Joint:", _rightEyeJoint = createJointBox()); form->addRow("Neck Joint:", _neckJoint = createJointBox()); } - if (_modelType == BODY_ONLY_MODEL || _modelType == HEAD_AND_BODY_MODEL) { + if (_modelType == FSTReader::BODY_ONLY_MODEL || _modelType == FSTReader::HEAD_AND_BODY_MODEL) { form->addRow("Root Joint:", _rootJoint = createJointBox()); form->addRow("Lean Joint:", _leanJoint = createJointBox()); form->addRow("Head Joint:", _headJoint = createJointBox()); @@ -91,29 +91,7 @@ _geometry(geometry) QString ModelPropertiesDialog::getType() const { - QString type = "unknown"; - switch(_modelType) { - case ENTITY_MODEL: - type = "entity"; - break; - - case HEAD_MODEL: - type = "head"; - break; - - case BODY_ONLY_MODEL: - type = "body"; - break; - - case HEAD_AND_BODY_MODEL: - type = "body+head"; - break; - - case ATTACHMENT_MODEL: - type = "attachment"; - break; - } - return type; + return FSTReader::getNameFromType(_modelType); } QVariantHash ModelPropertiesDialog::getMapping() const { @@ -130,9 +108,9 @@ QVariantHash ModelPropertiesDialog::getMapping() const { } mapping.insert(JOINT_INDEX_FIELD, jointIndices); - if (_modelType != ENTITY_MODEL) { + if (_modelType != FSTReader::ENTITY_MODEL) { QVariantHash joints = mapping.value(JOINT_FIELD).toHash(); - if (_modelType == ATTACHMENT_MODEL) { + if (_modelType == FSTReader::ATTACHMENT_MODEL) { glm::vec3 pivot; if (_pivotAboutCenter->isChecked()) { pivot = (_geometry.meshExtents.minimum + _geometry.meshExtents.maximum) * 0.5f; @@ -151,7 +129,7 @@ QVariantHash ModelPropertiesDialog::getMapping() const { } - if (_modelType == BODY_ONLY_MODEL || _modelType == HEAD_AND_BODY_MODEL) { + if (_modelType == FSTReader::BODY_ONLY_MODEL || _modelType == FSTReader::HEAD_AND_BODY_MODEL) { insertJointMapping(joints, "jointRoot", _rootJoint->currentText()); insertJointMapping(joints, "jointLean", _leanJoint->currentText()); insertJointMapping(joints, "jointHead", _headJoint->currentText()); @@ -181,8 +159,8 @@ void ModelPropertiesDialog::reset() { QVariantHash jointHash = _originalMapping.value(JOINT_FIELD).toHash(); - if (_modelType != ENTITY_MODEL) { - if (_modelType == ATTACHMENT_MODEL) { + if (_modelType != FSTReader::ENTITY_MODEL) { + if (_modelType == FSTReader::ATTACHMENT_MODEL) { _translationX->setValue(_originalMapping.value(TRANSLATION_X_FIELD).toDouble()); _translationY->setValue(_originalMapping.value(TRANSLATION_Y_FIELD).toDouble()); _translationZ->setValue(_originalMapping.value(TRANSLATION_Z_FIELD).toDouble()); @@ -195,7 +173,7 @@ void ModelPropertiesDialog::reset() { setJointText(_neckJoint, jointHash.value("jointNeck").toString()); } - if (_modelType == BODY_ONLY_MODEL || _modelType == HEAD_AND_BODY_MODEL) { + if (_modelType == FSTReader::BODY_ONLY_MODEL || _modelType == FSTReader::HEAD_AND_BODY_MODEL) { setJointText(_rootJoint, jointHash.value("jointRoot").toString()); setJointText(_leanJoint, jointHash.value("jointLean").toString()); setJointText(_headJoint, jointHash.value("jointHead").toString()); diff --git a/interface/src/ModelPropertiesDialog.h b/interface/src/ModelPropertiesDialog.h index e2335acc23..11abc5ab54 100644 --- a/interface/src/ModelPropertiesDialog.h +++ b/interface/src/ModelPropertiesDialog.h @@ -15,6 +15,7 @@ #include #include +#include #include "ui/ModelsBrowser.h" @@ -28,7 +29,7 @@ class ModelPropertiesDialog : public QDialog { Q_OBJECT public: - ModelPropertiesDialog(ModelType modelType, const QVariantHash& originalMapping, + ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping, const QString& basePath, const FBXGeometry& geometry); QVariantHash getMapping() const; @@ -45,7 +46,7 @@ private: void insertJointMapping(QVariantHash& joints, const QString& joint, const QString& name) const; QString getType() const; - ModelType _modelType; + FSTReader::ModelType _modelType; QVariantHash _originalMapping; QString _basePath; FBXGeometry _geometry; diff --git a/interface/src/ModelSelector.cpp b/interface/src/ModelSelector.cpp index 23746e0137..8e130cec1a 100644 --- a/interface/src/ModelSelector.cpp +++ b/interface/src/ModelSelector.cpp @@ -52,19 +52,19 @@ QFileInfo ModelSelector::getFileInfo() const { return _modelFile; } -ModelType ModelSelector::getModelType() const { +FSTReader::ModelType ModelSelector::getModelType() const { QString text = _modelType->currentText(); if (text == AVATAR_HEAD_STRING) { - return HEAD_MODEL; + return FSTReader::HEAD_MODEL; } else if (text == AVATAR_BODY_STRING) { - return BODY_ONLY_MODEL; + return FSTReader::BODY_ONLY_MODEL; } else if (text == AVATAR_HEAD_AND_BODY_STRING) { - return HEAD_AND_BODY_MODEL; + return FSTReader::HEAD_AND_BODY_MODEL; } else if (text == AVATAR_ATTACHEMENT_STRING) { - return ATTACHMENT_MODEL; + return FSTReader::ATTACHMENT_MODEL; } else if (text == ENTITY_MODEL_STRING) { - return ENTITY_MODEL; + return FSTReader::ENTITY_MODEL; } else { Q_UNREACHABLE(); } diff --git a/interface/src/ModelSelector.h b/interface/src/ModelSelector.h index aaa35e01c3..0ac3df5963 100644 --- a/interface/src/ModelSelector.h +++ b/interface/src/ModelSelector.h @@ -29,7 +29,7 @@ public: ModelSelector(); QFileInfo getFileInfo() const; - ModelType getModelType() const; + FSTReader::ModelType getModelType() const; public slots: virtual void accept(); diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 7f4b5ddf45..6b55b645e8 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -637,7 +637,7 @@ QScriptValue WindowScriptingInterface::showBrowse(const QString& title, const QS /// \param const QString& nameFilter filter to filter filenames /// \return QScriptValue file path as a string if one was selected, otherwise `QScriptValue::NullValue` QScriptValue WindowScriptingInterface::showS3Browse(const QString& nameFilter) { - ModelsBrowser browser(ENTITY_MODEL); + ModelsBrowser browser(FSTReader::ENTITY_MODEL); if (nameFilter != "") { browser.setNameFilter(nameFilter); } diff --git a/interface/src/ui/AttachmentsDialog.cpp b/interface/src/ui/AttachmentsDialog.cpp index 58b46e5bbf..2a6ff2b2b1 100644 --- a/interface/src/ui/AttachmentsDialog.cpp +++ b/interface/src/ui/AttachmentsDialog.cpp @@ -164,7 +164,7 @@ AttachmentData AttachmentPanel::getAttachmentData() const { } void AttachmentPanel::chooseModelURL() { - ModelsBrowser modelBrowser(ATTACHMENT_MODEL, this); + ModelsBrowser modelBrowser(FSTReader::ATTACHMENT_MODEL, this); connect(&modelBrowser, SIGNAL(selected(QString)), SLOT(setModelURL(const QString&))); modelBrowser.browse(); } diff --git a/interface/src/ui/ModelsBrowser.cpp b/interface/src/ui/ModelsBrowser.cpp index 96c89b332d..91de4e36ac 100644 --- a/interface/src/ui/ModelsBrowser.cpp +++ b/interface/src/ui/ModelsBrowser.cpp @@ -71,7 +71,7 @@ static const QString propertiesIds[MODEL_METADATA_COUNT] = { "Tags" }; -ModelsBrowser::ModelsBrowser(ModelType modelsType, QWidget* parent) : +ModelsBrowser::ModelsBrowser(FSTReader::ModelType modelsType, QWidget* parent) : QWidget(parent, Qt::WindowStaysOnTopHint), _handler(new ModelHandler(modelsType)) { @@ -184,7 +184,7 @@ void ModelsBrowser::browse() { } -ModelHandler::ModelHandler(ModelType modelsType, QWidget* parent) : +ModelHandler::ModelHandler(FSTReader::ModelType modelsType, QWidget* parent) : QObject(parent), _initiateExit(false), _type(modelsType), diff --git a/interface/src/ui/ModelsBrowser.h b/interface/src/ui/ModelsBrowser.h index 207a7f8c4e..2cb3c67991 100644 --- a/interface/src/ui/ModelsBrowser.h +++ b/interface/src/ui/ModelsBrowser.h @@ -16,22 +16,16 @@ #include #include -class QNetworkReply; +#include -enum ModelType { - ENTITY_MODEL, - HEAD_MODEL, - BODY_ONLY_MODEL, - HEAD_AND_BODY_MODEL, - ATTACHMENT_MODEL -}; +class QNetworkReply; extern const char* MODEL_TYPE_NAMES[]; class ModelHandler : public QObject { Q_OBJECT public: - ModelHandler(ModelType modelsType, QWidget* parent = NULL); + ModelHandler(FSTReader::ModelType modelsType, QWidget* parent = NULL); void lockModel() { _lock.lockForRead(); } QStandardItemModel* getModel() { return &_model; } @@ -52,7 +46,7 @@ private slots: private: bool _initiateExit; - ModelType _type; + FSTReader::ModelType _type; QReadWriteLock _lock; QStandardItemModel _model; QString _nameFilter; @@ -67,7 +61,7 @@ class ModelsBrowser : public QWidget { Q_OBJECT public: - ModelsBrowser(ModelType modelsType, QWidget* parent = NULL); + ModelsBrowser(FSTReader::ModelType modelsType, QWidget* parent = NULL); QString getSelectedFile() { return _selectedFile; } signals: diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index eddf009782..4a9165ae44 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -67,13 +67,13 @@ void PreferencesDialog::setSkeletonUrl(QString modelUrl) { } void PreferencesDialog::openHeadModelBrowser() { - ModelsBrowser modelBrowser(HEAD_MODEL); + ModelsBrowser modelBrowser(FSTReader::HEAD_MODEL); connect(&modelBrowser, &ModelsBrowser::selected, this, &PreferencesDialog::setHeadUrl); modelBrowser.browse(); } void PreferencesDialog::openBodyModelBrowser() { - ModelsBrowser modelBrowser(HEAD_AND_BODY_MODEL); + ModelsBrowser modelBrowser(FSTReader::HEAD_AND_BODY_MODEL); connect(&modelBrowser, &ModelsBrowser::selected, this, &PreferencesDialog::setSkeletonUrl); modelBrowser.browse(); } diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index 623f303c43..0ae164ed5d 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -10,10 +10,11 @@ // #include +#include #include "FSTReader.h" -QVariantHash parseMapping(QIODevice* device) { +QVariantHash FSTReader::parseMapping(QIODevice* device) { QVariantHash properties; QByteArray line; @@ -48,13 +49,13 @@ QVariantHash parseMapping(QIODevice* device) { return properties; } -QVariantHash readMapping(const QByteArray& data) { +QVariantHash FSTReader::readMapping(const QByteArray& data) { QBuffer buffer(const_cast(&data)); buffer.open(QIODevice::ReadOnly); - return parseMapping(&buffer); + return FSTReader::parseMapping(&buffer); } -void writeVariant(QBuffer& buffer, QVariantHash::const_iterator& it) { +void FSTReader::writeVariant(QBuffer& buffer, QVariantHash::const_iterator& it) { QByteArray key = it.key().toUtf8() + " = "; QVariantHash hashValue = it.value().toHash(); if (hashValue.isEmpty()) { @@ -76,7 +77,7 @@ void writeVariant(QBuffer& buffer, QVariantHash::const_iterator& it) { } } -QByteArray writeMapping(const QVariantHash& mapping) { +QByteArray FSTReader::writeMapping(const QVariantHash& mapping) { static const QStringList PREFERED_ORDER = QStringList() << NAME_FIELD << TYPE_FIELD << SCALE_FIELD << FILENAME_FIELD << TEXDIR_FIELD << JOINT_FIELD << FREE_JOINT_FIELD << BLENDSHAPE_FIELD << JOINT_INDEX_FIELD; @@ -96,4 +97,76 @@ QByteArray writeMapping(const QVariantHash& mapping) { } } return buffer.data(); -} \ No newline at end of file +} + +QHash FSTReader::_typesToNames; +QString FSTReader::getNameFromType(ModelType modelType) { + if (_typesToNames.size() == 0) { + _typesToNames[ENTITY_MODEL] = "entity"; + _typesToNames[HEAD_MODEL] = "head"; + _typesToNames[BODY_ONLY_MODEL] = "body"; + _typesToNames[HEAD_AND_BODY_MODEL] = "body+head"; + _typesToNames[ATTACHMENT_MODEL] = "attachment"; + } + return _typesToNames[modelType]; +} + +QHash FSTReader::_namesToTypes; +FSTReader::ModelType FSTReader::getTypeFromName(const QString& name) { + if (_namesToTypes.size() == 0) { + _namesToTypes["entity"] = ENTITY_MODEL; + _namesToTypes["head"] = HEAD_MODEL ; + _namesToTypes["body"] = BODY_ONLY_MODEL; + _namesToTypes["body+head"] = HEAD_AND_BODY_MODEL; + _namesToTypes["attachment"] = ATTACHMENT_MODEL; + } + return _namesToTypes[name]; +} + +FSTReader::ModelType FSTReader::predictModelType(const QVariantHash& mapping) { + + QVariantHash joints; + + if (mapping.contains("joint") && mapping["joint"].type() == QVariant::Hash) { + joints = mapping["joint"].toHash(); + } + + // if the mapping includes the type hint... then we trust the mapping + if (mapping.contains(TYPE_FIELD)) { + return FSTReader::getTypeFromName(mapping[TYPE_FIELD].toString()); + } + + // check for blendshapes + bool hasBlendshapes = mapping.contains(BLENDSHAPE_FIELD); + + // a Head needs to have these minimum fields... + //joint = jointEyeLeft = EyeL = 1 + //joint = jointEyeRight = EyeR = 1 + //joint = jointNeck = Head = 1 + bool hasHeadMinimum = joints.contains("jointNeck") && joints.contains("jointEyeLeft") && joints.contains("jointEyeRight"); + + // a Body needs to have these minimum fields... + //joint = jointRoot = Hips + //joint = jointLean = Spine + //joint = jointNeck = Neck + //joint = jointHead = HeadTop_End + + bool hasBodyMinimumJoints = joints.contains("jointRoot") && joints.contains("jointLean") && joints.contains("jointNeck") + && joints.contains("jointHead"); + + bool isLikelyHead = hasBlendshapes || hasHeadMinimum; + + if (isLikelyHead && hasBodyMinimumJoints) { + return HEAD_AND_BODY_MODEL; + } + + if (isLikelyHead) { + return HEAD_MODEL; + } + + if (hasBodyMinimumJoints) { + return BODY_ONLY_MODEL; + } + + return ENTITY_MODEL; +} diff --git a/libraries/fbx/src/FSTReader.h b/libraries/fbx/src/FSTReader.h index 7f71403a28..463d9750c4 100644 --- a/libraries/fbx/src/FSTReader.h +++ b/libraries/fbx/src/FSTReader.h @@ -12,6 +12,7 @@ #ifndef hifi_FSTReader_h #define hifi_FSTReader_h +#include #include static const QString NAME_FIELD = "name"; @@ -28,10 +29,37 @@ static const QString JOINT_FIELD = "joint"; static const QString FREE_JOINT_FIELD = "freeJoint"; static const QString BLENDSHAPE_FIELD = "bs"; -/// Reads an FST mapping from the supplied data. -QVariantHash readMapping(const QByteArray& data); +class FSTReader { +public: -/// Writes an FST mapping to a byte array. -QByteArray writeMapping(const QVariantHash& mapping); + enum ModelType { + ENTITY_MODEL, + HEAD_MODEL, + BODY_ONLY_MODEL, + HEAD_AND_BODY_MODEL, + ATTACHMENT_MODEL + }; + + /// Reads an FST mapping from the supplied data. + static QVariantHash readMapping(const QByteArray& data); + + /// Writes an FST mapping to a byte array. + static QByteArray writeMapping(const QVariantHash& mapping); + + /// Predicts the type of model by examining the mapping + static ModelType predictModelType(const QVariantHash& mapping); + + static QString getTypeName(ModelType modelType); + + static QString getNameFromType(ModelType modelType); + static FSTReader::ModelType getTypeFromName(const QString& name); + +private: + static void writeVariant(QBuffer& buffer, QVariantHash::const_iterator& it); + static QVariantHash parseMapping(QIODevice* device); + + static QHash _typesToNames; + static QHash _namesToTypes; +}; #endif // hifi_FSTReader_h \ No newline at end of file diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index e60409e36f..71b73476fd 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -2132,7 +2132,7 @@ void NetworkGeometry::downloadFinished(QNetworkReply* reply) { QUrl url = reply->url(); if (url.path().toLower().endsWith(".fst")) { // it's a mapping file; parse it and get the mesh filename - _mapping = readMapping(reply->readAll()); + _mapping = FSTReader::readMapping(reply->readAll()); reply->deleteLater(); QString filename = _mapping.value("filename").toString(); if (filename.isNull()) { diff --git a/libraries/shared/src/StreamUtils.cpp b/libraries/shared/src/StreamUtils.cpp index 96967648ed..f58115d288 100644 --- a/libraries/shared/src/StreamUtils.cpp +++ b/libraries/shared/src/StreamUtils.cpp @@ -143,4 +143,12 @@ QDebug& operator<<(QDebug& dbg, const glm::mat4& m) { return dbg << " ]}"; } +QDebug& operator<<(QDebug& dbg, const QVariantHash& v) { + dbg.nospace() << "["; + for (QVariantHash::const_iterator it = v.constBegin(); it != v.constEnd(); it++) { + dbg << it.key() << ":" << it.value(); + } + return dbg << " ]"; +} + #endif // QT_NO_DEBUG_STREAM diff --git a/libraries/shared/src/StreamUtils.h b/libraries/shared/src/StreamUtils.h index b9823a6743..fd22f7c068 100644 --- a/libraries/shared/src/StreamUtils.h +++ b/libraries/shared/src/StreamUtils.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -54,6 +55,7 @@ QDebug& operator<<(QDebug& s, const glm::vec3& v); QDebug& operator<<(QDebug& s, const glm::vec4& v); QDebug& operator<<(QDebug& s, const glm::quat& q); QDebug& operator<<(QDebug& s, const glm::mat4& m); +QDebug& operator<<(QDebug& dbg, const QVariantHash& v); #endif // QT_NO_DEBUG_STREAM #endif // hifi_StreamUtils_h From 002fba8018a026f63ca2577a74c068862976a18e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Mar 2015 16:56:03 -0700 Subject: [PATCH 03/16] first cut at predicting FST type for set avatar --- interface/src/Application.cpp | 53 ++++++++++++++++++++++++++++++----- libraries/fbx/src/FSTReader.h | 2 -- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8cd36b501f..d50648e4d7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3656,17 +3656,56 @@ bool Application::askToSetAvatarUrl(const QString& url) { msgBox.exec(); return false; } - - QString message = "Would you like to use this model for part of avatar:\n" + url; + + // Download the FST file, to attempt to determine it's model type + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkRequest networkRequest = QNetworkRequest(url); + networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + QNetworkReply* reply = networkAccessManager.get(networkRequest); + qDebug() << "Downloading avatar file at " << url; + QEventLoop loop; + QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + loop.exec(); + QByteArray fstContents = reply->readAll(); + delete reply; + QVariantHash fstMapping = FSTReader::readMapping(fstContents); + + FSTReader::ModelType modelType = FSTReader::predictModelType(fstMapping); + QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Question); msgBox.setWindowTitle("Set Avatar"); - msgBox.setText(message); + QPushButton* headButton = NULL; + QPushButton* bodyButton = NULL; + QPushButton* bodyAndHeadButton = NULL; + + QString message; + QString typeInfo; + switch (modelType) { + case FSTReader::HEAD_MODEL: + message = QString("Would you like to use '") + fstMapping["name"].toString() + QString("' for your avatar head?"); + headButton = msgBox.addButton(tr("Yes"), QMessageBox::ActionRole); + break; - QPushButton* headButton = msgBox.addButton(tr("Head"), QMessageBox::ActionRole); - QPushButton* bodyButton = msgBox.addButton(tr("Body"), QMessageBox::ActionRole); - QPushButton* bodyAndHeadButton = msgBox.addButton(tr("Body + Head"), QMessageBox::ActionRole); + case FSTReader::BODY_ONLY_MODEL: + message = QString("Would you like to use '") + fstMapping["name"].toString() + QString("' for your avatar body?"); + bodyButton = msgBox.addButton(tr("Yes"), QMessageBox::ActionRole); + break; + + case FSTReader::HEAD_AND_BODY_MODEL: + message = QString("Would you like to use '") + fstMapping["name"].toString() + QString("' for your avatar?"); + bodyAndHeadButton = msgBox.addButton(tr("Yes"), QMessageBox::ActionRole); + break; + + default: + message = QString("Would you like to use '") + fstMapping["name"].toString() + QString("' for some part of your avatar head?"); + headButton = msgBox.addButton(tr("Use for Head"), QMessageBox::ActionRole); + bodyButton = msgBox.addButton(tr("Use for Body"), QMessageBox::ActionRole); + bodyAndHeadButton = msgBox.addButton(tr("Use for Body and Head"), QMessageBox::ActionRole); + break; + } + + msgBox.setText(message); msgBox.addButton(QMessageBox::Cancel); msgBox.exec(); diff --git a/libraries/fbx/src/FSTReader.h b/libraries/fbx/src/FSTReader.h index 463d9750c4..5752a224c6 100644 --- a/libraries/fbx/src/FSTReader.h +++ b/libraries/fbx/src/FSTReader.h @@ -49,8 +49,6 @@ public: /// Predicts the type of model by examining the mapping static ModelType predictModelType(const QVariantHash& mapping); - static QString getTypeName(ModelType modelType); - static QString getNameFromType(ModelType modelType); static FSTReader::ModelType getTypeFromName(const QString& name); From 3bda65f4fe9a9cd3e17daa53fa686f8ea8f0f100 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 28 Mar 2015 19:19:11 -0700 Subject: [PATCH 04/16] if installing a body, and you have no head, make your head the default head --- interface/src/Application.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6e18c45468..6e4cd5c904 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3707,6 +3707,11 @@ bool Application::askToSetAvatarUrl(const QString& url) { } else if (msgBox.clickedButton() == bodyButton) { qDebug() << "Chose to use for body: " << url; _myAvatar->setSkeletonModelURL(url); + // if the head is empty, reset it to the default head. + if (_myAvatar->getFaceModelURLString().isEmpty()) { + _myAvatar->setFaceModelURL(DEFAULT_HEAD_MODEL_URL); + UserActivityLogger::getInstance().changedModel("head", DEFAULT_HEAD_MODEL_URL.toString()); + } UserActivityLogger::getInstance().changedModel("skeleton", url); _myAvatar->sendIdentityPacket(); } else if (msgBox.clickedButton() == bodyAndHeadButton) { From 36657c94733008a3b7dfb09d6a0631363ef095da Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 30 Mar 2015 14:36:48 -0700 Subject: [PATCH 05/16] first cut at script caching --- interface/src/Application.cpp | 6 +- .../src/EntityTreeRenderer.cpp | 5 + libraries/script-engine/src/Script.cpp | 49 ++++++ libraries/script-engine/src/Script.h | 37 +++++ libraries/script-engine/src/ScriptCache.cpp | 146 ++++++++++++++++++ libraries/script-engine/src/ScriptCache.h | 46 ++++++ libraries/script-engine/src/ScriptEngine.cpp | 18 +++ libraries/script-engine/src/ScriptEngine.h | 6 +- 8 files changed, 309 insertions(+), 4 deletions(-) create mode 100644 libraries/script-engine/src/Script.cpp create mode 100644 libraries/script-engine/src/Script.h create mode 100644 libraries/script-engine/src/ScriptCache.cpp create mode 100644 libraries/script-engine/src/ScriptCache.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 97d132508a..c2ac472b9f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -76,7 +76,7 @@ #include #include #include -//#include +#include #include #include #include @@ -221,7 +221,7 @@ bool setupEssentials(int& argc, char** argv) { auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Agent, listenPort); auto geometryCache = DependencyManager::set(); - //auto scriptCache = DependencyManager::set(); + auto scriptCache = DependencyManager::set(); auto soundCache = DependencyManager::set(); auto glowEffect = DependencyManager::set(); auto faceshift = DependencyManager::set(); @@ -612,7 +612,7 @@ Application::~Application() { DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); - //DependencyManager::destroy(); + DependencyManager::destroy(); DependencyManager::destroy(); QThread* nodeThread = DependencyManager::get()->thread(); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 3faa06fc53..f98a13878d 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -148,6 +148,7 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe qDebug() << "ERROR Loading file:" << fileName; } } else { + /* QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest networkRequest = QNetworkRequest(url); networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); @@ -162,6 +163,10 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe qDebug() << "ERROR Loading file:" << url.toString(); } delete reply; + */ + auto scriptCache = DependencyManager::get(); + scriptContents = scriptCache->getScript(url); + } } diff --git a/libraries/script-engine/src/Script.cpp b/libraries/script-engine/src/Script.cpp new file mode 100644 index 0000000000..4f5d38a2e1 --- /dev/null +++ b/libraries/script-engine/src/Script.cpp @@ -0,0 +1,49 @@ +// +// Script.cpp +// libraries/script-engine/src +// +// Created by Brad Hefta-Gaub on 2015-03-30 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +/* +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "AudioRingBuffer.h" +#include "AudioFormat.h" +#include "AudioBuffer.h" +#include "AudioEditBuffer.h" +*/ + +#include "Script.h" + +Script::Script(const QUrl& url) : + Resource(url), + _isReady(false) +{ + +} + +void Script::downloadFinished(QNetworkReply* reply) { + // replace our byte array with the downloaded data + _contents = reply->readAll(); + qDebug() << "Script downloaded from:" << getURL(); + _isReady = true; + reply->deleteLater(); +} + diff --git a/libraries/script-engine/src/Script.h b/libraries/script-engine/src/Script.h new file mode 100644 index 0000000000..6cca76a8e8 --- /dev/null +++ b/libraries/script-engine/src/Script.h @@ -0,0 +1,37 @@ +// +// Script.h +// libraries/script-engine/src +// +// Created by Brad Hefta-Gaub on 2015-03-30 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_Script_h +#define hifi_Script_h + +#include +#include +#include + +#include + +class Script : public Resource { + Q_OBJECT +public: + Script(const QUrl& url); + bool isReady() const { return _isReady; } + const QString& getContents() { return _contents; } + +private: + QString _contents; + bool _isReady; + + virtual void downloadFinished(QNetworkReply* reply); +}; + +typedef QSharedPointer