mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 18:50:00 +02:00
Merge pull request #4477 from ZappoMan/dragDropLinkAvatars
MVP Task: Support for Drag/Drop link avatars
This commit is contained in:
commit
0dc61ce3b8
4 changed files with 157 additions and 55 deletions
|
@ -873,8 +873,10 @@ void Application::controlledBroadcastToNodes(const QByteArray& packet, const Nod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::importSVOFromURL(QUrl url) {
|
bool Application::importSVOFromURL(const QString& urlString) {
|
||||||
|
QUrl url(urlString);
|
||||||
emit svoImportRequested(url.url());
|
emit svoImportRequested(url.url());
|
||||||
|
return true; // assume it's accepted
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::event(QEvent* event) {
|
bool Application::event(QEvent* event) {
|
||||||
|
@ -887,12 +889,9 @@ bool Application::event(QEvent* event) {
|
||||||
QUrl url = fileEvent->url();
|
QUrl url = fileEvent->url();
|
||||||
|
|
||||||
if (!url.isEmpty()) {
|
if (!url.isEmpty()) {
|
||||||
if (url.scheme() == HIFI_URL_SCHEME) {
|
QString urlString = url.toString();
|
||||||
DependencyManager::get<AddressManager>()->handleLookupString(fileEvent->url().toString());
|
if (canAcceptURL(urlString)) {
|
||||||
} else if (url.path().toLower().endsWith(SVO_EXTENSION)) {
|
return acceptURL(urlString);
|
||||||
emit svoImportRequested(url.url());
|
|
||||||
} else if (url.path().toLower().endsWith(JS_EXTENSION)) {
|
|
||||||
askToLoadScript(url.toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1453,40 +1452,15 @@ void Application::wheelEvent(QWheelEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::dropEvent(QDropEvent *event) {
|
void Application::dropEvent(QDropEvent *event) {
|
||||||
QString snapshotPath;
|
|
||||||
const QMimeData *mimeData = event->mimeData();
|
const QMimeData *mimeData = event->mimeData();
|
||||||
bool atLeastOneFileAccepted = false;
|
bool atLeastOneFileAccepted = false;
|
||||||
foreach (QUrl url, mimeData->urls()) {
|
foreach (QUrl url, mimeData->urls()) {
|
||||||
auto lower = url.path().toLower();
|
QString urlString = url.toString();
|
||||||
if (lower.endsWith(SNAPSHOT_EXTENSION)) {
|
if (canAcceptURL(urlString)) {
|
||||||
snapshotPath = url.toLocalFile();
|
if (acceptURL(urlString)) {
|
||||||
|
|
||||||
|
|
||||||
SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath);
|
|
||||||
if (snapshotData) {
|
|
||||||
if (!snapshotData->getDomain().isEmpty()) {
|
|
||||||
DependencyManager::get<NodeList>()->getDomainHandler().setHostnameAndPort(snapshotData->getDomain());
|
|
||||||
}
|
|
||||||
|
|
||||||
_myAvatar->setPosition(snapshotData->getLocation());
|
|
||||||
_myAvatar->setOrientation(snapshotData->getOrientation());
|
|
||||||
atLeastOneFileAccepted = true;
|
atLeastOneFileAccepted = true;
|
||||||
break; // don't process further files
|
break;
|
||||||
} else {
|
|
||||||
QMessageBox msgBox;
|
|
||||||
msgBox.setText("No location details were found in the file "
|
|
||||||
+ snapshotPath + ", try dragging in an authentic Hifi snapshot.");
|
|
||||||
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
||||||
msgBox.exec();
|
|
||||||
}
|
}
|
||||||
} else if (lower.endsWith(SVO_EXTENSION)) {
|
|
||||||
emit svoImportRequested(url.url());
|
|
||||||
event->acceptProposedAction();
|
|
||||||
atLeastOneFileAccepted = true;
|
|
||||||
} else if (lower.endsWith(JS_EXTENSION)) {
|
|
||||||
askToLoadScript(url.url());
|
|
||||||
atLeastOneFileAccepted = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1495,6 +1469,29 @@ void Application::dropEvent(QDropEvent *event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Application::acceptSnapshot(const QString& urlString) {
|
||||||
|
QUrl url(urlString);
|
||||||
|
QString snapshotPath = url.toLocalFile();
|
||||||
|
|
||||||
|
SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath);
|
||||||
|
if (snapshotData) {
|
||||||
|
if (!snapshotData->getDomain().isEmpty()) {
|
||||||
|
DependencyManager::get<NodeList>()->getDomainHandler().setHostnameAndPort(snapshotData->getDomain());
|
||||||
|
}
|
||||||
|
|
||||||
|
_myAvatar->setPosition(snapshotData->getLocation());
|
||||||
|
_myAvatar->setOrientation(snapshotData->getOrientation());
|
||||||
|
} else {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText("No location details were found in the file "
|
||||||
|
+ snapshotPath + ", try dragging in an authentic Hifi snapshot.");
|
||||||
|
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.exec();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Application::sendPingPackets() {
|
void Application::sendPingPackets() {
|
||||||
QByteArray pingPacket = DependencyManager::get<NodeList>()->constructPingPacket();
|
QByteArray pingPacket = DependencyManager::get<NodeList>()->constructPingPacket();
|
||||||
controlledBroadcastToNodes(pingPacket, NodeSet()
|
controlledBroadcastToNodes(pingPacket, NodeSet()
|
||||||
|
@ -3598,7 +3595,109 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
||||||
workerThread->start();
|
workerThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
void Application::initializeAcceptedFiles() {
|
||||||
|
if (_acceptedExtensions.size() == 0) {
|
||||||
|
_acceptedExtensions[SNAPSHOT_EXTENSION] = &Application::acceptSnapshot;
|
||||||
|
_acceptedExtensions[SVO_EXTENSION] = &Application::importSVOFromURL;
|
||||||
|
_acceptedExtensions[JS_EXTENSION] = &Application::askToLoadScript;
|
||||||
|
_acceptedExtensions[FST_EXTENSION] = &Application::askToSetAvatarUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Application::canAcceptURL(const QString& urlString) {
|
||||||
|
initializeAcceptedFiles();
|
||||||
|
|
||||||
|
QUrl url(urlString);
|
||||||
|
if (urlString.startsWith(HIFI_URL_SCHEME)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
QHashIterator<QString, AcceptURLMethod> i(_acceptedExtensions);
|
||||||
|
QString lowerPath = url.path().toLower();
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
if (lowerPath.endsWith(i.key())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Application::acceptURL(const QString& urlString) {
|
||||||
|
initializeAcceptedFiles();
|
||||||
|
|
||||||
|
if (urlString.startsWith(HIFI_URL_SCHEME)) {
|
||||||
|
// this is a hifi URL - have the AddressManager handle it
|
||||||
|
QMetaObject::invokeMethod(DependencyManager::get<AddressManager>().data(), "handleLookupString",
|
||||||
|
Qt::AutoConnection, Q_ARG(const QString&, urlString));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
QUrl url(urlString);
|
||||||
|
QHashIterator<QString, AcceptURLMethod> i(_acceptedExtensions);
|
||||||
|
QString lowerPath = url.path().toLower();
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
if (lowerPath.endsWith(i.key())) {
|
||||||
|
AcceptURLMethod method = i.value();
|
||||||
|
(this->*method)(urlString);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Application::askToSetAvatarUrl(const QString& url) {
|
||||||
|
QUrl realUrl(url);
|
||||||
|
if (realUrl.isLocalFile()) {
|
||||||
|
QString message = "You can not use local files for avatar components.";
|
||||||
|
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText(message);
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString message = "Would you like to use this model for part of avatar:\n" + url;
|
||||||
|
QMessageBox msgBox;
|
||||||
|
|
||||||
|
msgBox.setIcon(QMessageBox::Question);
|
||||||
|
msgBox.setWindowTitle("Set Avatar");
|
||||||
|
msgBox.setText(message);
|
||||||
|
|
||||||
|
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);
|
||||||
|
msgBox.addButton(QMessageBox::Cancel);
|
||||||
|
|
||||||
|
msgBox.exec();
|
||||||
|
|
||||||
|
if (msgBox.clickedButton() == headButton) {
|
||||||
|
qDebug() << "Chose to use for head: " << url;
|
||||||
|
_myAvatar->setFaceModelURL(url);
|
||||||
|
UserActivityLogger::getInstance().changedModel("head", url);
|
||||||
|
_myAvatar->sendIdentityPacket();
|
||||||
|
} else if (msgBox.clickedButton() == bodyButton) {
|
||||||
|
qDebug() << "Chose to use for body: " << url;
|
||||||
|
_myAvatar->setSkeletonModelURL(url);
|
||||||
|
UserActivityLogger::getInstance().changedModel("skeleton", url);
|
||||||
|
_myAvatar->sendIdentityPacket();
|
||||||
|
} else if (msgBox.clickedButton() == bodyAndHeadButton) {
|
||||||
|
qDebug() << "Chose to use for body + head: " << url;
|
||||||
|
_myAvatar->setFaceModelURL(QString());
|
||||||
|
_myAvatar->setSkeletonModelURL(url);
|
||||||
|
UserActivityLogger::getInstance().changedModel("skeleton", url);
|
||||||
|
_myAvatar->sendIdentityPacket();
|
||||||
|
} else {
|
||||||
|
qDebug() << "Declined to use the avatar: " << url;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
||||||
QMessageBox::StandardButton reply;
|
QMessageBox::StandardButton reply;
|
||||||
QString message = "Would you like to run this script:\n" + scriptFilenameOrURL;
|
QString message = "Would you like to run this script:\n" + scriptFilenameOrURL;
|
||||||
reply = QMessageBox::question(getWindow(), "Run Script", message, QMessageBox::Yes|QMessageBox::No);
|
reply = QMessageBox::question(getWindow(), "Run Script", message, QMessageBox::Yes|QMessageBox::No);
|
||||||
|
@ -3609,6 +3708,7 @@ void Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Declined to run the script: " << scriptFilenameOrURL;
|
qDebug() << "Declined to run the script: " << scriptFilenameOrURL;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded,
|
ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded,
|
||||||
|
|
|
@ -96,6 +96,7 @@ static const float NODE_KILLED_BLUE = 0.0f;
|
||||||
static const QString SNAPSHOT_EXTENSION = ".jpg";
|
static const QString SNAPSHOT_EXTENSION = ".jpg";
|
||||||
static const QString SVO_EXTENSION = ".svo";
|
static const QString SVO_EXTENSION = ".svo";
|
||||||
static const QString JS_EXTENSION = ".js";
|
static const QString JS_EXTENSION = ".js";
|
||||||
|
static const QString FST_EXTENSION = ".fst";
|
||||||
|
|
||||||
static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees
|
static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees
|
||||||
static const float BILLBOARD_DISTANCE = 5.56f; // meters
|
static const float BILLBOARD_DISTANCE = 5.56f; // meters
|
||||||
|
@ -127,6 +128,8 @@ class Application;
|
||||||
#endif
|
#endif
|
||||||
#define qApp (static_cast<Application*>(QCoreApplication::instance()))
|
#define qApp (static_cast<Application*>(QCoreApplication::instance()))
|
||||||
|
|
||||||
|
typedef bool (Application::* AcceptURLMethod)(const QString &);
|
||||||
|
|
||||||
class Application : public QApplication, public AbstractViewStateInterface, AbstractScriptingServicesInterface {
|
class Application : public QApplication, public AbstractViewStateInterface, AbstractScriptingServicesInterface {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -221,7 +224,7 @@ public:
|
||||||
float getFieldOfView() { return _fieldOfView.get(); }
|
float getFieldOfView() { return _fieldOfView.get(); }
|
||||||
void setFieldOfView(float fov) { _fieldOfView.set(fov); }
|
void setFieldOfView(float fov) { _fieldOfView.set(fov); }
|
||||||
|
|
||||||
void importSVOFromURL(QUrl url);
|
bool importSVOFromURL(const QString& urlString);
|
||||||
|
|
||||||
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
|
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
|
||||||
void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); }
|
void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); }
|
||||||
|
@ -306,6 +309,10 @@ public:
|
||||||
|
|
||||||
QString getScriptsLocation();
|
QString getScriptsLocation();
|
||||||
void setScriptsLocation(const QString& scriptsLocation);
|
void setScriptsLocation(const QString& scriptsLocation);
|
||||||
|
|
||||||
|
void initializeAcceptedFiles();
|
||||||
|
bool canAcceptURL(const QString& url);
|
||||||
|
bool acceptURL(const QString& url);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
@ -341,7 +348,9 @@ public slots:
|
||||||
void loadDialog();
|
void loadDialog();
|
||||||
void loadScriptURLDialog();
|
void loadScriptURLDialog();
|
||||||
void toggleLogDialog();
|
void toggleLogDialog();
|
||||||
void askToLoadScript(const QString& scriptFilenameOrURL);
|
bool acceptSnapshot(const QString& urlString);
|
||||||
|
bool askToSetAvatarUrl(const QString& url);
|
||||||
|
bool askToLoadScript(const QString& scriptFilenameOrURL);
|
||||||
ScriptEngine* loadScript(const QString& scriptFilename = QString(), bool isUserLoaded = true,
|
ScriptEngine* loadScript(const QString& scriptFilename = QString(), bool isUserLoaded = true,
|
||||||
bool loadScriptFromEditor = false, bool activateMainWindow = false);
|
bool loadScriptFromEditor = false, bool activateMainWindow = false);
|
||||||
void scriptFinished(const QString& scriptName);
|
void scriptFinished(const QString& scriptName);
|
||||||
|
@ -595,6 +604,8 @@ private:
|
||||||
|
|
||||||
QWidget* _fullscreenMenuWidget = new QWidget();
|
QWidget* _fullscreenMenuWidget = new QWidget();
|
||||||
int _menuBarHeight;
|
int _menuBarHeight;
|
||||||
|
|
||||||
|
QHash<QString, AcceptURLMethod> _acceptedExtensions;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Application_h
|
#endif // hifi_Application_h
|
||||||
|
|
|
@ -170,8 +170,8 @@ void GLCanvas::wheelEvent(QWheelEvent* event) {
|
||||||
void GLCanvas::dragEnterEvent(QDragEnterEvent* event) {
|
void GLCanvas::dragEnterEvent(QDragEnterEvent* event) {
|
||||||
const QMimeData* mimeData = event->mimeData();
|
const QMimeData* mimeData = event->mimeData();
|
||||||
foreach (QUrl url, mimeData->urls()) {
|
foreach (QUrl url, mimeData->urls()) {
|
||||||
auto lower = url.path().toLower();
|
auto urlString = url.toString();
|
||||||
if (lower.endsWith(SNAPSHOT_EXTENSION) || lower.endsWith(SVO_EXTENSION) || lower.endsWith(JS_EXTENSION)) {
|
if (Application::getInstance()->canAcceptURL(urlString)) {
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,22 +32,13 @@ void DataWebPage::javaScriptConsoleMessage(const QString& message, int lineNumbe
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataWebPage::acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, QWebPage::NavigationType type) {
|
bool DataWebPage::acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, QWebPage::NavigationType type) {
|
||||||
|
QString urlString = request.url().toString();
|
||||||
if (!request.url().toString().startsWith(HIFI_URL_SCHEME)) {
|
if (Application::getInstance()->canAcceptURL(urlString)) {
|
||||||
if (request.url().path().toLower().endsWith(SVO_EXTENSION)) {
|
if (Application::getInstance()->acceptURL(urlString)) {
|
||||||
Application::getInstance()->importSVOFromURL(request.url());
|
return false; // we handled it, so QWebPage doesn't need to handle it
|
||||||
return false;
|
|
||||||
} else if (request.url().path().toLower().endsWith(JS_EXTENSION)) {
|
|
||||||
Application::getInstance()->askToLoadScript(request.url().toString());
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// this is a hifi URL - have the AddressManager handle it
|
|
||||||
QMetaObject::invokeMethod(DependencyManager::get<AddressManager>().data(), "handleLookupString",
|
|
||||||
Qt::AutoConnection, Q_ARG(const QString&, request.url().toString()));
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DataWebPage::userAgentForUrl(const QUrl& url) const {
|
QString DataWebPage::userAgentForUrl(const QUrl& url) const {
|
||||||
|
|
Loading…
Reference in a new issue