From dd02bae5b32bb6de15f6b7c92a8abf11ebabce00 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 15 Apr 2014 16:11:00 -0700 Subject: [PATCH 01/56] First cut at improved undo --- libraries/voxels/src/VoxelTreeCommands.cpp | 84 +++++++++++++++++----- libraries/voxels/src/VoxelTreeCommands.h | 4 ++ 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/libraries/voxels/src/VoxelTreeCommands.cpp b/libraries/voxels/src/VoxelTreeCommands.cpp index f0f092fd04..75b38667ec 100644 --- a/libraries/voxels/src/VoxelTreeCommands.cpp +++ b/libraries/voxels/src/VoxelTreeCommands.cpp @@ -17,8 +17,37 @@ AddVoxelCommand::AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditP QUndoCommand("Add Voxel", parent), _tree(tree), _packetSender(packetSender), - _voxel(voxel) + _voxel(voxel), + _oldTree(NULL) { + VoxelTreeElement* element = _tree->getVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + if (element) { + if (element->hasContent() && element->isLeaf()) { + // Do nothing, everything is in order + } else { + _oldTree = new VoxelTree(); + _tree->copySubTreeIntoNewTree(element, _oldTree, true); + } + } else { + glm::vec3 point(_voxel.x + _voxel.s / 2.0f, + _voxel.y + _voxel.s / 2.0f, + _voxel.z + _voxel.s / 2.0f); + OctreeElement* element = _tree->getElementEnclosingPoint(point, Octree::Lock); + if (element) { + VoxelTreeElement* node = static_cast(element); + _voxel.x = node->getCorner().x; + _voxel.y = node->getCorner().y; + _voxel.z = node->getCorner().z; + _voxel.s = node->getScale(); + _voxel.red = node->getColor()[0]; + _voxel.green = node->getColor()[1]; + _voxel.blue = node->getColor()[2]; + } + } +} + +AddVoxelCommand::~AddVoxelCommand() { + delete _oldTree; } void AddVoxelCommand::redo() { @@ -31,11 +60,17 @@ void AddVoxelCommand::redo() { } void AddVoxelCommand::undo() { - if (_tree) { - _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); + if (_oldTree) { + OctreeElement* element = _tree->getOrCreateChildElementAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + qDebug() << _voxel.x << " " << _voxel.y << " " << _voxel.z << " " << _voxel.s; + _tree->copyFromTreeIntoSubTree(_oldTree, element); + } else { + if (_tree) { + _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + } + if (_packetSender) { + _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); + } } } @@ -43,24 +78,37 @@ DeleteVoxelCommand::DeleteVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, Voxe QUndoCommand("Delete Voxel", parent), _tree(tree), _packetSender(packetSender), - _voxel(voxel) + _voxel(voxel), + _oldTree(NULL) { } +DeleteVoxelCommand::~DeleteVoxelCommand() { + delete _oldTree; +} + void DeleteVoxelCommand::redo() { - if (_tree) { - _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); + if (_oldTree) { + + } else { + if (_tree) { + _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + } + if (_packetSender) { + _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); + } } } void DeleteVoxelCommand::undo() { - if (_tree) { - _tree->createVoxel(_voxel.x, _voxel.y, _voxel.z, _voxel.s, _voxel.red, _voxel.green, _voxel.blue); + if (_oldTree) { + + } else { + if (_tree) { + _tree->createVoxel(_voxel.x, _voxel.y, _voxel.z, _voxel.s, _voxel.red, _voxel.green, _voxel.blue); + } + if (_packetSender) { + _packetSender->queueVoxelEditMessages(PacketTypeVoxelSet, 1, &_voxel); + } } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelSet, 1, &_voxel); - } -} +} \ No newline at end of file diff --git a/libraries/voxels/src/VoxelTreeCommands.h b/libraries/voxels/src/VoxelTreeCommands.h index 4f2610577e..c3b23e7201 100644 --- a/libraries/voxels/src/VoxelTreeCommands.h +++ b/libraries/voxels/src/VoxelTreeCommands.h @@ -23,6 +23,7 @@ class VoxelTree; class AddVoxelCommand : public QUndoCommand { public: AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender = NULL, QUndoCommand* parent = NULL); + ~AddVoxelCommand(); virtual void redo(); virtual void undo(); @@ -31,11 +32,13 @@ private: VoxelTree* _tree; VoxelEditPacketSender* _packetSender; VoxelDetail _voxel; + VoxelTree* _oldTree; }; class DeleteVoxelCommand : public QUndoCommand { public: DeleteVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender = NULL, QUndoCommand* parent = NULL); + ~DeleteVoxelCommand(); virtual void redo(); virtual void undo(); @@ -44,6 +47,7 @@ private: VoxelTree* _tree; VoxelEditPacketSender* _packetSender; VoxelDetail _voxel; + VoxelTree* _oldTree; }; #endif // hifi_VoxelTreeCommands_h From 4afea2d2289a237c9d8bb647f3c571bf7c0a0da2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 16 Apr 2014 09:55:12 -0700 Subject: [PATCH 02/56] Remove chat window docking --- interface/resources/images/pin.svg | 98 ------------------------ interface/resources/images/pinned.svg | 106 -------------------------- interface/src/ui/ChatWindow.cpp | 13 ---- interface/src/ui/ChatWindow.h | 1 - interface/ui/chatWindow.ui | 16 ---- 5 files changed, 234 deletions(-) delete mode 100644 interface/resources/images/pin.svg delete mode 100644 interface/resources/images/pinned.svg diff --git a/interface/resources/images/pin.svg b/interface/resources/images/pin.svg deleted file mode 100644 index ec968a1ec1..0000000000 --- a/interface/resources/images/pin.svg +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - image/svg+xml - - Slice 1 - - - - - Slice 1 - Created with Sketch (http://www.bohemiancoding.com/sketch) - - - - - - - - diff --git a/interface/resources/images/pinned.svg b/interface/resources/images/pinned.svg deleted file mode 100644 index bda6f0e747..0000000000 --- a/interface/resources/images/pinned.svg +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - image/svg+xml - - Slice 1 - - - - - Slice 1 - Created with Sketch (http://www.bohemiancoding.com/sketch) - - - - - - - - - diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 635f1f3d10..c190169c43 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -323,16 +323,3 @@ void ChatWindow::scrollToBottom() { QScrollBar* verticalScrollBar = ui->messagesScrollArea->verticalScrollBar(); verticalScrollBar->setSliderPosition(verticalScrollBar->maximum()); } - -void ChatWindow::togglePinned() { - QMainWindow* mainWindow = Application::getInstance()->getWindow(); - mainWindow->removeDockWidget(this); - if (ui->togglePinnedButton->isChecked()) { - mainWindow->addDockWidget(ui->togglePinnedButton->isChecked() ? Qt::RightDockWidgetArea : Qt::NoDockWidgetArea, this); - } - if (!this->toggleViewAction()->isChecked()) { - this->toggleViewAction()->trigger(); - } - this->setFloating(!ui->togglePinnedButton->isChecked()); - setTitleBarWidget(ui->togglePinnedButton->isChecked()?new QWidget():titleBar); -} diff --git a/interface/src/ui/ChatWindow.h b/interface/src/ui/ChatWindow.h index 6a807f9b81..536ac17799 100644 --- a/interface/src/ui/ChatWindow.h +++ b/interface/src/ui/ChatWindow.h @@ -65,7 +65,6 @@ private: private slots: void connected(); void timeout(); - void togglePinned(); #ifdef HAVE_QXMPP void error(QXmppClient::Error error); void participantsChanged(); diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index 0372e00c09..1d06a1e99b 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -251,22 +251,6 @@ QPushButton:pressed { - - togglePinnedButton - clicked() - ChatWindow - togglePinned() - - - 390 - 42 - - - 550 - 42 - - - closeButton clicked() From cb1408d26d4048c712522de54cdb776fb02fd0a3 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 16 Apr 2014 10:01:35 -0700 Subject: [PATCH 03/56] Update chat window to use new Frameless Dialog The new dialog class needed to be updated to handle windows in different positions and windows that don't delete on close. --- interface/src/Menu.cpp | 19 +- interface/src/ui/ChatWindow.cpp | 38 +-- interface/src/ui/ChatWindow.h | 16 +- interface/src/ui/FramelessDialog.cpp | 72 +++-- interface/src/ui/FramelessDialog.h | 10 +- interface/src/ui/PreferencesDialog.cpp | 2 +- interface/ui/chatWindow.ui | 387 ++++++++++++------------- 7 files changed, 267 insertions(+), 277 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 272dc39eb3..508eaf61c3 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1060,23 +1060,22 @@ void Menu::showMetavoxelEditor() { void Menu::showChat() { QMainWindow* mainWindow = Application::getInstance()->getWindow(); if (!_chatWindow) { - mainWindow->addDockWidget(Qt::RightDockWidgetArea, _chatWindow = new ChatWindow()); + _chatWindow = new ChatWindow(mainWindow); } - if (!_chatWindow->toggleViewAction()->isChecked()) { - const QRect& windowGeometry = mainWindow->geometry(); - _chatWindow->move(windowGeometry.topRight().x() - _chatWindow->width(), - windowGeometry.topRight().y() + (windowGeometry.height() / 2) - (_chatWindow->height() / 2)); - - _chatWindow->resize(0, _chatWindow->height()); - _chatWindow->toggleViewAction()->trigger(); + if (_chatWindow->isHidden()) { + _chatWindow->show(); } } void Menu::toggleChat() { #ifdef HAVE_QXMPP _chatAction->setEnabled(XmppClient::getInstance().getXMPPClient().isConnected()); - if (!_chatAction->isEnabled() && _chatWindow && _chatWindow->toggleViewAction()->isChecked()) { - _chatWindow->toggleViewAction()->trigger(); + if (!_chatAction->isEnabled() && _chatWindow) { + if (_chatWindow->isHidden()) { + _chatWindow->show(); + } else { + _chatWindow->hide(); + } } #endif } diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index c190169c43..1f0f884f30 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -12,12 +12,10 @@ #include #include #include -#include #include #include #include #include -#include #include "Application.h" #include "FlowLayout.h" @@ -32,18 +30,16 @@ const int NUM_MESSAGES_TO_TIME_STAMP = 20; const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?))://\\S+)"); -ChatWindow::ChatWindow() : +ChatWindow::ChatWindow(QWidget* parent) : + FramelessDialog(parent, 0, POSITION_RIGHT), ui(new Ui::ChatWindow), numMessagesAfterLastTimeStamp(0), _mousePressed(false), _mouseStartPosition() { - ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, false); - // remove the title bar (see the Qt docs on setTitleBarWidget), but we keep it for undocking - // - titleBar = titleBarWidget(); - setTitleBarWidget(new QWidget()); + ui->setupUi(this); FlowLayout* flowLayout = new FlowLayout(0, 4, 4); ui->usersWidget->setLayout(flowLayout); @@ -89,41 +85,23 @@ ChatWindow::~ChatWindow() { delete ui; } -void ChatWindow::mousePressEvent(QMouseEvent *e) { - if (e->button() == Qt::LeftButton && isFloating()) { - _mousePressed = true; - _mouseStartPosition = e->pos(); - } -} - -void ChatWindow::mouseMoveEvent(QMouseEvent *e) { - if (_mousePressed) { - move(mapToParent(e->pos() - _mouseStartPosition)); - } -} - -void ChatWindow::mouseReleaseEvent( QMouseEvent *e ) { - if ( e->button() == Qt::LeftButton ) { - _mousePressed = false; - } -} - void ChatWindow::keyPressEvent(QKeyEvent* event) { - QDockWidget::keyPressEvent(event); if (event->key() == Qt::Key_Escape) { hide(); + } else { + FramelessDialog::keyPressEvent(event); } } void ChatWindow::showEvent(QShowEvent* event) { - QDockWidget::showEvent(event); + FramelessDialog::showEvent(event); if (!event->spontaneous()) { - activateWindow(); ui->messagePlainTextEdit->setFocus(); } } bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { + FramelessDialog::eventFilter(sender, event); if (sender == ui->messagePlainTextEdit) { if (event->type() != QEvent::KeyPress) { return false; diff --git a/interface/src/ui/ChatWindow.h b/interface/src/ui/ChatWindow.h index 536ac17799..399c9e917c 100644 --- a/interface/src/ui/ChatWindow.h +++ b/interface/src/ui/ChatWindow.h @@ -17,6 +17,7 @@ #include #include +#include "FramelessDialog.h" #ifdef HAVE_QXMPP @@ -29,23 +30,19 @@ namespace Ui { class ChatWindow; } -class ChatWindow : public QDockWidget { +class ChatWindow : public FramelessDialog { Q_OBJECT public: - ChatWindow(); + ChatWindow(QWidget* parent); ~ChatWindow(); - virtual void keyPressEvent(QKeyEvent *event); - virtual void showEvent(QShowEvent* event); - - virtual void mousePressEvent(QMouseEvent *e); - virtual void mouseMoveEvent(QMouseEvent *e); - virtual void mouseReleaseEvent(QMouseEvent *e); - protected: bool eventFilter(QObject* sender, QEvent* event); + virtual void keyPressEvent(QKeyEvent *event); + virtual void showEvent(QShowEvent* event); + private: #ifdef HAVE_QXMPP QString getParticipantName(const QString& participant); @@ -56,7 +53,6 @@ private: void scrollToBottom(); Ui::ChatWindow* ui; - QWidget* titleBar; int numMessagesAfterLastTimeStamp; QDateTime lastMessageStamp; bool _mousePressed; diff --git a/interface/src/ui/FramelessDialog.cpp b/interface/src/ui/FramelessDialog.cpp index 18e3bca89a..816c45b38a 100644 --- a/interface/src/ui/FramelessDialog.cpp +++ b/interface/src/ui/FramelessDialog.cpp @@ -14,8 +14,13 @@ const int RESIZE_HANDLE_WIDTH = 7; -FramelessDialog::FramelessDialog(QWidget *parent, Qt::WindowFlags flags) : -QDialog(parent, flags | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint) { +FramelessDialog::FramelessDialog(QWidget *parent, Qt::WindowFlags flags, Position position) : + QDialog(parent, flags | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint), + _position(position), + _selfHidden(false), + _isResizing(false), + _resizeInitialWidth(0) { + setAttribute(Qt::WA_DeleteOnClose); // handle rezize and move events @@ -29,29 +34,37 @@ bool FramelessDialog::eventFilter(QObject* sender, QEvent* event) { switch (event->type()) { case QEvent::Move: if (sender == parentWidget()) { - // move to upper left corner on app move - move(parentWidget()->geometry().topLeft()); + resizeAndPosition(false); } break; case QEvent::Resize: if (sender == parentWidget()) { - // keep full app height on resizing the app - setFixedHeight(parentWidget()->size().height()); + resizeAndPosition(false); } break; case QEvent::WindowStateChange: if (parentWidget()->isMinimized()) { - setHidden(true); - } else { + if (isVisible()) { + _selfHidden = true; + setHidden(true); + } + } else if (_selfHidden) { + _selfHidden = false; setHidden(false); } break; case QEvent::ApplicationDeactivate: // hide on minimize and focus lost - setHidden(true); + if (isVisible()) { + _selfHidden = true; + setHidden(true); + } break; case QEvent::ApplicationActivate: - setHidden(false); + if (_selfHidden) { + _selfHidden = false; + setHidden(false); + } break; default: break; @@ -70,21 +83,38 @@ void FramelessDialog::setStyleSheetFile(const QString& fileName) { } void FramelessDialog::showEvent(QShowEvent* event) { - // move to upper left corner - move(parentWidget()->geometry().topLeft()); + resizeAndPosition(); +} +void FramelessDialog::resizeAndPosition(bool resizeParent) { // keep full app height setFixedHeight(parentWidget()->size().height()); // resize parrent if width is smaller than this dialog - if (parentWidget()->size().width() < size().width()) { + if (resizeParent && parentWidget()->size().width() < size().width()) { parentWidget()->resize(size().width(), parentWidget()->size().height()); } + + if (_position == POSITION_LEFT) { + // move to upper left corner + move(parentWidget()->geometry().topLeft()); + } else if (_position == POSITION_RIGHT) { + // move to upper right corner + QPoint pos = parentWidget()->geometry().topRight(); + pos.setX(pos.x() - size().width()); + move(pos); + } } + void FramelessDialog::mousePressEvent(QMouseEvent* mouseEvent) { - if (abs(mouseEvent->pos().x() - size().width()) < RESIZE_HANDLE_WIDTH && mouseEvent->button() == Qt::LeftButton) { - _isResizing = true; - QApplication::setOverrideCursor(Qt::SizeHorCursor); + if (mouseEvent->button() == Qt::LeftButton) { + bool hitLeft = _position == POSITION_LEFT && abs(mouseEvent->pos().x() - size().width()) < RESIZE_HANDLE_WIDTH; + bool hitRight = _position == POSITION_RIGHT && mouseEvent->pos().x() < RESIZE_HANDLE_WIDTH; + if (hitLeft || hitRight) { + _isResizing = true; + _resizeInitialWidth = size().width(); + QApplication::setOverrideCursor(Qt::SizeHorCursor); + } } } @@ -95,6 +125,14 @@ void FramelessDialog::mouseReleaseEvent(QMouseEvent* mouseEvent) { void FramelessDialog::mouseMoveEvent(QMouseEvent* mouseEvent) { if (_isResizing) { - resize(mouseEvent->pos().x(), size().height()); + if (_position == POSITION_LEFT) { + resize(mouseEvent->pos().x(), size().height()); + } else if (_position == POSITION_RIGHT) { + setUpdatesEnabled(false); + resize(_resizeInitialWidth - mouseEvent->pos().x(), size().height()); + resizeAndPosition(); + _resizeInitialWidth = size().width(); + setUpdatesEnabled(true); + } } } diff --git a/interface/src/ui/FramelessDialog.h b/interface/src/ui/FramelessDialog.h index db9f6dfd6c..22666cca63 100644 --- a/interface/src/ui/FramelessDialog.h +++ b/interface/src/ui/FramelessDialog.h @@ -19,7 +19,10 @@ class FramelessDialog : public QDialog { Q_OBJECT public: - FramelessDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0); + enum Position { POSITION_LEFT, POSITION_RIGHT }; + + FramelessDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0, + Position position = POSITION_LEFT); void setStyleSheetFile(const QString& fileName); protected: @@ -31,7 +34,12 @@ protected: bool eventFilter(QObject* sender, QEvent* event); private: + void resizeAndPosition(bool resizeParent = true); + bool _isResizing; + int _resizeInitialWidth; + bool _selfHidden; ///< true when the dialog itself because of a window event (deactivation or minimization) + Position _position; }; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index a14e80e62f..cb998e783a 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -19,7 +19,7 @@ const int SCROLL_PANEL_BOTTOM_MARGIN = 30; const int OK_BUTTON_RIGHT_MARGIN = 30; const int BUTTONS_TOP_MARGIN = 24; -PreferencesDialog::PreferencesDialog(QWidget* parent, Qt::WindowFlags flags) : FramelessDialog(parent, flags) { +PreferencesDialog::PreferencesDialog(QWidget* parent, Qt::WindowFlags flags) : FramelessDialog(parent, flags, POSITION_LEFT) { ui.setupUi(this); setStyleSheetFile("styles/preferences.qss"); diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index 1d06a1e99b..78757ded38 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -1,13 +1,13 @@ ChatWindow - + 0 0 400 - 608 + 440 @@ -16,127 +16,95 @@ 238 - - font-family: Helvetica, Arial, sans-serif; - - - QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable - - - Qt::NoDockWidgetArea - Chat - - - - 0 - - - 8 - - - 8 - - - 8 - - - 8 - - - - - - 0 - 0 - - - - Connecting to XMPP... - - - Qt::AlignCenter - - - - - - - - - - 0 - 0 - - - - font-weight: bold; color: palette(shadow); margin-bottom: 4px; - - - online now: - - - - - - - - 0 - 0 - - - - - 16 - 16 - - - - Qt::NoFocus - - - - - - - ../resources/images/pin.svg - ../resources/images/pinned.svg../resources/images/pin.svg - - - true - - - true - - - false - - - true - - - - - - - - 0 - 0 - - - - - 16 - 16 - - - - Qt::NoFocus - - - QPushButton { + + font-family: Helvetica, Arial, sans-serif; + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + 8 + + + 8 + + + 8 + + + 8 + + + + + + 0 + 0 + + + + Connecting to XMPP... + + + Qt::AlignCenter + + + + + + + + + + 0 + 0 + + + + font-weight: bold; color: palette(shadow); margin-bottom: 4px; + + + online now: + + + + + + + + 0 + 0 + + + + + 16 + 16 + + + + Qt::NoFocus + + + QPushButton { background-color: rgba( 0, 0, 0, 0% ); border: none; image: url(../resources/images/close.svg) @@ -148,102 +116,105 @@ QPushButton:pressed { border: none; image: url(../resources/images/close_down.svg) } - - - - - - true - - - - - - - - - - - - margin-top: 12px; - - - Qt::ScrollBarAlwaysOff - - - true - - - - - 0 - 0 - 382 - 16 - + + + + + + true + + + + + + + + + + + + margin-top: 12px; + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 382 + 16 + + + + + 0 + 0 + + + + margin-top: 0px; + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + - + 0 0 - - margin-top: 0px; + + + 0 + 60 + + + + border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px; + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + QAbstractScrollArea::AdjustToContents + + + true - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - 0 - 0 - - - - - 0 - 60 - - - - border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px; - - - QFrame::NoFrame - - - Qt::ScrollBarAlwaysOff - - - QAbstractScrollArea::AdjustToContents - - - true - - - - - + + + + + messagePlainTextEdit + dockWidgetContents messagePlainTextEdit From 8aee81ae7ca2b36dc40e6003311861ed1c0473a2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 16 Apr 2014 10:02:54 -0700 Subject: [PATCH 04/56] Update username in chat to use correct line height --- interface/src/ui/ChatMessageArea.cpp | 13 +++++++-- interface/src/ui/ChatMessageArea.h | 7 ++++- interface/src/ui/ChatWindow.cpp | 40 +++++++++++++++++++++++----- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/interface/src/ui/ChatMessageArea.cpp b/interface/src/ui/ChatMessageArea.cpp index f15b788990..929ad85d87 100644 --- a/interface/src/ui/ChatMessageArea.cpp +++ b/interface/src/ui/ChatMessageArea.cpp @@ -9,11 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Application.h" #include "ChatMessageArea.h" #include #include -ChatMessageArea::ChatMessageArea() : QTextBrowser() { +ChatMessageArea::ChatMessageArea(bool useFixedHeight) : QTextBrowser(), _useFixedHeight(useFixedHeight) { connect(document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, this, &ChatMessageArea::updateLayout); } @@ -34,7 +35,15 @@ void ChatMessageArea::setHtml(const QString& html) { } void ChatMessageArea::updateLayout() { - setFixedHeight(document()->size().height()); + if (_useFixedHeight) { + setFixedHeight(document()->size().height()); + updateGeometry(); + emit sizeChanged(size()); + } +} + +void ChatMessageArea::setSize(const QSize& size) { + setFixedHeight(size.height()); updateGeometry(); } diff --git a/interface/src/ui/ChatMessageArea.h b/interface/src/ui/ChatMessageArea.h index 1c49c60b08..48cfc01aec 100644 --- a/interface/src/ui/ChatMessageArea.h +++ b/interface/src/ui/ChatMessageArea.h @@ -19,14 +19,19 @@ const int CHAT_MESSAGE_LINE_HEIGHT = 130; class ChatMessageArea : public QTextBrowser { Q_OBJECT public: - ChatMessageArea(); + ChatMessageArea(bool useFixedHeight = true); virtual void setHtml(const QString& html); public slots: void updateLayout(); + void setSize(const QSize& size); + +signals: + void sizeChanged(QSize newSize); protected: virtual void wheelEvent(QWheelEvent* event); + bool _useFixedHeight; }; diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 1f0f884f30..c194e35fc1 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -240,13 +240,32 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { return; } - QLabel* userLabel = new QLabel(getParticipantName(message.from())); - userLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - userLabel->setStyleSheet("padding: 2px; font-weight: bold"); - userLabel->setAlignment(Qt::AlignTop | Qt::AlignRight); + // Create username label + ChatMessageArea* userLabel = new ChatMessageArea(false); + userLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + userLabel->setWordWrapMode(QTextOption::NoWrap); + userLabel->setLineWrapMode(QTextEdit::NoWrap); + userLabel->setTextInteractionFlags(Qt::NoTextInteraction); + userLabel->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + userLabel->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + userLabel->setReadOnly(true); + userLabel->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); - ChatMessageArea* messageArea = new ChatMessageArea(); + userLabel->setStyleSheet("padding: 2px;" + "font-weight: bold;" + "background-color: rgba(0, 0, 0, 0%);" + "border: 0;"); + QTextBlockFormat format; + format.setLineHeight(130, QTextBlockFormat::ProportionalHeight); + QTextCursor cursor = userLabel->textCursor(); + cursor.setBlockFormat(format); + cursor.insertText(getParticipantName(message.from())); + + userLabel->setAlignment(Qt::AlignRight); + + // Create message area + ChatMessageArea* messageArea = new ChatMessageArea(true); messageArea->setOpenLinks(true); messageArea->setOpenExternalLinks(true); messageArea->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); @@ -262,10 +281,11 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { "background-color: rgba(0, 0, 0, 0%);" "border: 0;"); + // Update background if this is a message from the current user bool fromSelf = getParticipantName(message.from()) == AccountManager::getInstance().getUsername(); if (fromSelf) { - userLabel->setStyleSheet(userLabel->styleSheet() + "; background-color: #e1e8ea"); - messageArea->setStyleSheet(messageArea->styleSheet() + "; background-color: #e1e8ea"); + userLabel->setStyleSheet(userLabel->styleSheet() + "background-color: #e1e8ea"); + messageArea->setStyleSheet(messageArea->styleSheet() + "background-color: #e1e8ea"); } messageArea->setHtml(message.body().replace(regexLinks, "\\1")); @@ -274,6 +294,12 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { ui->messagesGridLayout->addWidget(userLabel, ui->messagesGridLayout->rowCount(), 0); ui->messagesGridLayout->addWidget(messageArea, ui->messagesGridLayout->rowCount() - 1, 1); + // Force the height of the username area to match the height of the message area + connect(messageArea, &ChatMessageArea::sizeChanged, userLabel, &ChatMessageArea::setSize); + + // Force initial height to match message area + userLabel->setFixedHeight(messageArea->size().height()); + ui->messagesGridLayout->parentWidget()->updateGeometry(); Application::processEvents(); From bfb879d3e6a545f28cc66cd58f554464d828525e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 16 Apr 2014 10:03:22 -0700 Subject: [PATCH 05/56] Update chat textbox to use correct line height --- interface/src/ui/ChatWindow.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index c194e35fc1..e26c0bcb94 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -48,11 +48,23 @@ ChatWindow::ChatWindow(QWidget* parent) : ui->messagesGridLayout->setColumnStretch(1, 3); ui->messagePlainTextEdit->installEventFilter(this); + ui->messagePlainTextEdit->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); + + QTextCursor cursor(ui->messagePlainTextEdit->textCursor()); + + cursor.movePosition(QTextCursor::Start); + + QTextBlockFormat format = cursor.blockFormat(); + format.setLineHeight(130, QTextBlockFormat::ProportionalHeight); + + cursor.setBlockFormat(format); + + ui->messagePlainTextEdit->setTextCursor(cursor); if (!AccountManager::getInstance().isLoggedIn()) { ui->connectingToXMPPLabel->setText(tr("You must be logged in to chat with others.")); } - + #ifdef HAVE_QXMPP const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient(); if (xmppClient.isConnected()) { From e8b6b7ab4de72f6c09dcba9735c66548531f9979 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 16 Apr 2014 13:22:22 -0700 Subject: [PATCH 06/56] Update style of chat message links --- interface/src/ui/ChatWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index e26c0bcb94..c943607d71 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -300,6 +300,7 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { messageArea->setStyleSheet(messageArea->styleSheet() + "background-color: #e1e8ea"); } + messageArea->document()->setDefaultStyleSheet("a { text-decoration: none; font-weight: bold; color: #267077;}"); messageArea->setHtml(message.body().replace(regexLinks, "\\1")); bool atBottom = isAtBottom(); From 23d68d538c8bda8c7a82d95ecd9d1201800ab1ad Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 16 Apr 2014 14:05:38 -0700 Subject: [PATCH 07/56] Fix bug where multiple user/location popups appear --- interface/src/ui/ChatWindow.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index c943607d71..2849d0c748 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -113,7 +113,6 @@ void ChatWindow::showEvent(QShowEvent* event) { } bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { - FramelessDialog::eventFilter(sender, event); if (sender == ui->messagePlainTextEdit) { if (event->type() != QEvent::KeyPress) { return false; @@ -135,14 +134,14 @@ bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { } return true; } - } else { - if (event->type() != QEvent::MouseButtonRelease) { - return false; + } else if (event->type() == QEvent::MouseButtonRelease) { + QVariant userVar = sender->property("user"); + if (userVar.isValid()) { + Menu::getInstance()->goToUser("@" + userVar.toString()); + return true; } - QString user = sender->property("user").toString(); - Menu::getInstance()->goToUser(user); } - return false; + return FramelessDialog::eventFilter(sender, event); } #ifdef HAVE_QXMPP From 606a48d555642bb1aa3cdd1b2e7435d7376d56f7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 09:36:17 -0700 Subject: [PATCH 08/56] Fix issue with pref dialog disappearing With the frameless dialog being updated to support different types of window, the pref dialog was no longer able to rely on it to keep itself open in certain cases. The window flags were also updated to update after a "browse" call rather than in the slot so that it would still execute in the case of cancelled selection. --- interface/src/ui/PreferencesDialog.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 0f2216407f..550c616fc1 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -38,26 +38,34 @@ void PreferencesDialog::accept() { void PreferencesDialog::setHeadUrl(QString modelUrl) { ui.faceURLEdit->setText(modelUrl); - setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); } void PreferencesDialog::setSkeletonUrl(QString modelUrl) { ui.skeletonURLEdit->setText(modelUrl); - setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); } void PreferencesDialog::openHeadModelBrowser() { setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint); + show(); + ModelsBrowser modelBrowser(Head); connect(&modelBrowser, &ModelsBrowser::selected, this, &PreferencesDialog::setHeadUrl); modelBrowser.browse(); + + setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); + show(); } void PreferencesDialog::openBodyModelBrowser() { setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint); + show(); + ModelsBrowser modelBrowser(Skeleton); connect(&modelBrowser, &ModelsBrowser::selected, this, &PreferencesDialog::setSkeletonUrl); modelBrowser.browse(); + + setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); + show(); } void PreferencesDialog::openSnapshotLocationBrowser() { From c1fa6b41e45bb9d4442afc2eee10cdded63ef919 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 13:19:36 -0700 Subject: [PATCH 09/56] Update chat window to use vertical layout --- interface/src/ui/ChatWindow.cpp | 55 +++++++++------------------------ interface/ui/chatWindow.ui | 10 +++--- 2 files changed, 18 insertions(+), 47 deletions(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 2849d0c748..ae5dd0185c 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -44,9 +44,6 @@ ChatWindow::ChatWindow(QWidget* parent) : FlowLayout* flowLayout = new FlowLayout(0, 4, 4); ui->usersWidget->setLayout(flowLayout); - ui->messagesGridLayout->setColumnStretch(0, 1); - ui->messagesGridLayout->setColumnStretch(1, 3); - ui->messagePlainTextEdit->installEventFilter(this); ui->messagePlainTextEdit->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); @@ -172,8 +169,8 @@ void ChatWindow::addTimeStamp() { bool atBottom = isAtBottom(); - ui->messagesGridLayout->addWidget(timeLabel, ui->messagesGridLayout->rowCount(), 0, 1, 2); - ui->messagesGridLayout->parentWidget()->updateGeometry(); + ui->messagesVBoxLayout->addWidget(timeLabel); + ui->messagesVBoxLayout->parentWidget()->updateGeometry(); Application::processEvents(); numMessagesAfterLastTimeStamp = 0; @@ -251,29 +248,8 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { return; } - // Create username label - ChatMessageArea* userLabel = new ChatMessageArea(false); - userLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); - userLabel->setWordWrapMode(QTextOption::NoWrap); - userLabel->setLineWrapMode(QTextEdit::NoWrap); - userLabel->setTextInteractionFlags(Qt::NoTextInteraction); - userLabel->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - userLabel->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - userLabel->setReadOnly(true); - userLabel->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); - - userLabel->setStyleSheet("padding: 2px;" - "font-weight: bold;" - "background-color: rgba(0, 0, 0, 0%);" - "border: 0;"); - - QTextBlockFormat format; - format.setLineHeight(130, QTextBlockFormat::ProportionalHeight); - QTextCursor cursor = userLabel->textCursor(); - cursor.setBlockFormat(format); - cursor.insertText(getParticipantName(message.from())); - - userLabel->setAlignment(Qt::AlignRight); + // Update background if this is a message from the current user + bool fromSelf = getParticipantName(message.from()) == AccountManager::getInstance().getUsername(); // Create message area ChatMessageArea* messageArea = new ChatMessageArea(true); @@ -289,30 +265,27 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { "padding-left: 2px;" "padding-top: 2px;" "padding-right: 20px;" + "margin: 0px;" + "color: #333333;" + "font-size: 14pt;" "background-color: rgba(0, 0, 0, 0%);" "border: 0;"); - // Update background if this is a message from the current user - bool fromSelf = getParticipantName(message.from()) == AccountManager::getInstance().getUsername(); + QString userLabel = getParticipantName(message.from()); if (fromSelf) { - userLabel->setStyleSheet(userLabel->styleSheet() + "background-color: #e1e8ea"); + userLabel = "" + userLabel + ": "; messageArea->setStyleSheet(messageArea->styleSheet() + "background-color: #e1e8ea"); + } else { + userLabel = "" + userLabel + ": "; } messageArea->document()->setDefaultStyleSheet("a { text-decoration: none; font-weight: bold; color: #267077;}"); - messageArea->setHtml(message.body().replace(regexLinks, "\\1")); + messageArea->setHtml(userLabel + message.body().replace(regexLinks, "\\1")); bool atBottom = isAtBottom(); - ui->messagesGridLayout->addWidget(userLabel, ui->messagesGridLayout->rowCount(), 0); - ui->messagesGridLayout->addWidget(messageArea, ui->messagesGridLayout->rowCount() - 1, 1); - // Force the height of the username area to match the height of the message area - connect(messageArea, &ChatMessageArea::sizeChanged, userLabel, &ChatMessageArea::setSize); - - // Force initial height to match message area - userLabel->setFixedHeight(messageArea->size().height()); - - ui->messagesGridLayout->parentWidget()->updateGeometry(); + ui->messagesVBoxLayout->addWidget(messageArea); + ui->messagesVBoxLayout->parentWidget()->updateGeometry(); Application::processEvents(); if (atBottom || fromSelf) { diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index 78757ded38..b516418f8c 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -159,7 +159,10 @@ QPushButton:pressed { margin-top: 0px; - + + + 0 + 0 @@ -172,9 +175,6 @@ QPushButton:pressed { 0 - - 0 - @@ -213,8 +213,6 @@ QPushButton:pressed { - messagePlainTextEdit - dockWidgetContents messagePlainTextEdit From 7a25d0661f5ff48818090e5ae004e6efffad3dba Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 13:20:00 -0700 Subject: [PATCH 10/56] Update style of chat messages --- interface/src/ui/ChatWindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index ae5dd0185c..78c667f41e 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -162,10 +162,10 @@ void ChatWindow::addTimeStamp() { if (!timeString.isEmpty()) { QLabel* timeLabel = new QLabel(timeString); timeLabel->setStyleSheet("color: palette(shadow);" - "background-color: palette(highlight);" + "background-color: white;" "padding: 4px;"); timeLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - timeLabel->setAlignment(Qt::AlignHCenter); + timeLabel->setAlignment(Qt::AlignLeft); bool atBottom = isAtBottom(); @@ -235,6 +235,7 @@ void ChatWindow::participantsChanged() { "padding-bottom: 2px;" "padding-left: 2px;" "border: 1px solid palette(shadow);" + "font-size: 14pt;" "font-weight: bold"); userLabel->setProperty("user", participantName); userLabel->setCursor(Qt::PointingHandCursor); From 3ee613b9d581bcb2e1aebd123aa13c97ddb32b4e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 13:20:17 -0700 Subject: [PATCH 11/56] Add right margin to user list area in chat --- interface/ui/chatWindow.ui | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index b516418f8c..34e6c6aeaf 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -128,7 +128,13 @@ QPushButton:pressed { - + + + #usersWidget { + margin-right: 20px; +} + + From 48a75616446a9b57cb280e806e15ba7593505679 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 13:38:13 -0700 Subject: [PATCH 12/56] Fix chat messages not being html escaped --- interface/src/ui/ChatWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 78c667f41e..5d3c5e5a75 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -281,7 +281,7 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { } messageArea->document()->setDefaultStyleSheet("a { text-decoration: none; font-weight: bold; color: #267077;}"); - messageArea->setHtml(userLabel + message.body().replace(regexLinks, "\\1")); + messageArea->setHtml(userLabel + message.body().toHtmlEscaped().replace(regexLinks, "\\1")); bool atBottom = isAtBottom(); From e2954f8614c018ddf594e08dd29122b4d18fcfb6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 13:49:10 -0700 Subject: [PATCH 13/56] Fix color and size of font in timestamp chat messages --- interface/src/ui/ChatWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 5d3c5e5a75..ad59222202 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -161,8 +161,9 @@ void ChatWindow::addTimeStamp() { timeString.chop(1); if (!timeString.isEmpty()) { QLabel* timeLabel = new QLabel(timeString); - timeLabel->setStyleSheet("color: palette(shadow);" + timeLabel->setStyleSheet("color: #333333;" "background-color: white;" + "font-size: 14pt;" "padding: 4px;"); timeLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); timeLabel->setAlignment(Qt::AlignLeft); From f2112c665abc15ed0038af79cda1b7ca2e62f509 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 14:02:21 -0700 Subject: [PATCH 14/56] Disallow rich text from being pasted into the chat area --- interface/ui/chatWindow.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index 34e6c6aeaf..d63542bf7b 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -214,6 +214,9 @@ QPushButton:pressed { true + + false + From e1e9c11189d57383a98fc5381d5ee8e708300511 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 15:18:40 -0700 Subject: [PATCH 15/56] Add Menu slot to open urls --- interface/src/Menu.cpp | 11 +++++++++++ interface/src/Menu.h | 1 + 2 files changed, 12 insertions(+) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9de6dfad3b..ad765c0e8e 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -906,6 +906,17 @@ void Menu::goToUser(const QString& user) { connect(manager, &LocationManager::multipleDestinationsFound, this, &Menu::multipleDestinationsDecision); } +/// Open a url, shortcutting any "hifi" scheme URLs to the local application. +void Menu::openUrl(const QUrl& url) { + if (url.scheme() == "hifi") { + QString path = url.toString(QUrl::RemoveScheme); + path = path.remove(QRegExp("^:?/*")); + goTo(path); + } else { + QDesktopServices::openUrl(url); + } +} + void Menu::multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData) { QMessageBox msgBox; msgBox.setText("Both user and location exists with same name"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 40ed8efdc7..ff27810df5 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -153,6 +153,7 @@ public slots: void goTo(); void goToUser(const QString& user); void pasteToVoxel(); + void openUrl(const QUrl& url); void toggleLoginMenuItem(); From 795ddbc7bf9d9b4cda49c89a2e37ff2dca56fb87 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 15:19:13 -0700 Subject: [PATCH 16/56] Update ChatMessageArea to open urls via Menu::openUrl --- interface/src/ui/ChatMessageArea.cpp | 4 ++++ interface/src/ui/ChatWindow.cpp | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/ChatMessageArea.cpp b/interface/src/ui/ChatMessageArea.cpp index 929ad85d87..1e16a8a2db 100644 --- a/interface/src/ui/ChatMessageArea.cpp +++ b/interface/src/ui/ChatMessageArea.cpp @@ -15,8 +15,12 @@ #include ChatMessageArea::ChatMessageArea(bool useFixedHeight) : QTextBrowser(), _useFixedHeight(useFixedHeight) { + setOpenLinks(false); + connect(document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, this, &ChatMessageArea::updateLayout); + connect(this, &QTextBrowser::anchorClicked, + Menu::getInstance(), &Menu::openUrl); } void ChatMessageArea::setHtml(const QString& html) { diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index ad59222202..e1ee30b4b9 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -255,8 +255,6 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { // Create message area ChatMessageArea* messageArea = new ChatMessageArea(true); - messageArea->setOpenLinks(true); - messageArea->setOpenExternalLinks(true); messageArea->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); messageArea->setTextInteractionFlags(Qt::TextBrowserInteraction); messageArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); From 4f236c6bf45cc58ca60bf7d4b7a4a288d28cf7b9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 15:20:12 -0700 Subject: [PATCH 17/56] Add hifi link handling in chat for usernames and locations --- interface/src/ui/ChatWindow.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index e1ee30b4b9..9679e73132 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -29,6 +29,7 @@ const int NUM_MESSAGES_TO_TIME_STAMP = 20; const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?))://\\S+)"); +const QRegularExpression regexHifiLinks("\\s([#@]\\S+)"); ChatWindow::ChatWindow(QWidget* parent) : FramelessDialog(parent, 0, POSITION_RIGHT), @@ -280,7 +281,10 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { } messageArea->document()->setDefaultStyleSheet("a { text-decoration: none; font-weight: bold; color: #267077;}"); - messageArea->setHtml(userLabel + message.body().toHtmlEscaped().replace(regexLinks, "\\1")); + QString messageText = message.body().toHtmlEscaped(); + messageText = messageText.replace(regexLinks, "\\1"); + messageText = messageText.replace(regexHifiLinks, "\\1"); + messageArea->setHtml(userLabel + messageText); bool atBottom = isAtBottom(); From 6437f76ed2488e02341e56f43fd04bb496a099bd Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 15:50:40 -0700 Subject: [PATCH 18/56] Update username/location match in chat to be more lenient --- interface/src/ui/ChatWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 9679e73132..c459a6d426 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -29,7 +29,7 @@ const int NUM_MESSAGES_TO_TIME_STAMP = 20; const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?))://\\S+)"); -const QRegularExpression regexHifiLinks("\\s([#@]\\S+)"); +const QRegularExpression regexHifiLinks("([#@]\\S+)"); ChatWindow::ChatWindow(QWidget* parent) : FramelessDialog(parent, 0, POSITION_RIGHT), From 3c9b6264a8354f514324f6a97992a67b01ad924a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 19:51:25 -0700 Subject: [PATCH 19/56] Add emoticons to chat --- interface/resources/images/cool.svg | 8 ++++++++ interface/resources/images/grin.svg | 8 ++++++++ interface/resources/images/happy.svg | 8 ++++++++ interface/resources/images/sad.svg | 8 ++++++++ interface/resources/images/smiley.svg | 8 ++++++++ interface/resources/images/tongue.svg | 8 ++++++++ interface/resources/images/wink.svg | 8 ++++++++ interface/src/ui/ChatWindow.cpp | 19 ++++++++++++++++++- interface/src/ui/ChatWindow.h | 1 + 9 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 interface/resources/images/cool.svg create mode 100644 interface/resources/images/grin.svg create mode 100644 interface/resources/images/happy.svg create mode 100644 interface/resources/images/sad.svg create mode 100644 interface/resources/images/smiley.svg create mode 100644 interface/resources/images/tongue.svg create mode 100644 interface/resources/images/wink.svg diff --git a/interface/resources/images/cool.svg b/interface/resources/images/cool.svg new file mode 100644 index 0000000000..2e8348108a --- /dev/null +++ b/interface/resources/images/cool.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/interface/resources/images/grin.svg b/interface/resources/images/grin.svg new file mode 100644 index 0000000000..8e36a16555 --- /dev/null +++ b/interface/resources/images/grin.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/interface/resources/images/happy.svg b/interface/resources/images/happy.svg new file mode 100644 index 0000000000..fe31d01991 --- /dev/null +++ b/interface/resources/images/happy.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/interface/resources/images/sad.svg b/interface/resources/images/sad.svg new file mode 100644 index 0000000000..0029bfded5 --- /dev/null +++ b/interface/resources/images/sad.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/interface/resources/images/smiley.svg b/interface/resources/images/smiley.svg new file mode 100644 index 0000000000..1b0e707bf6 --- /dev/null +++ b/interface/resources/images/smiley.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/interface/resources/images/tongue.svg b/interface/resources/images/tongue.svg new file mode 100644 index 0000000000..35361d2b2b --- /dev/null +++ b/interface/resources/images/tongue.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/interface/resources/images/wink.svg b/interface/resources/images/wink.svg new file mode 100644 index 0000000000..b1aef4823d --- /dev/null +++ b/interface/resources/images/wink.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index c459a6d426..06608ef5e4 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -31,12 +31,14 @@ const int NUM_MESSAGES_TO_TIME_STAMP = 20; const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?))://\\S+)"); const QRegularExpression regexHifiLinks("([#@]\\S+)"); + ChatWindow::ChatWindow(QWidget* parent) : FramelessDialog(parent, 0, POSITION_RIGHT), ui(new Ui::ChatWindow), numMessagesAfterLastTimeStamp(0), _mousePressed(false), - _mouseStartPosition() + _mouseStartPosition(), + _emoticonMap() { setAttribute(Qt::WA_DeleteOnClose, false); @@ -63,6 +65,14 @@ ChatWindow::ChatWindow(QWidget* parent) : ui->connectingToXMPPLabel->setText(tr("You must be logged in to chat with others.")); } + _emoticonMap.insert(new QRegularExpression(QRegExp::escape(":)")), new QString("../resources/images/smiley.svg")); + _emoticonMap.insert(new QRegularExpression(QRegExp::escape(":D")), new QString("../resources/images/happy.svg")); + _emoticonMap.insert(new QRegularExpression(QRegExp::escape("B)")), new QString("../resources/images/cool.svg")); + _emoticonMap.insert(new QRegularExpression(QRegExp::escape(":O")), new QString("../resources/images/grin.svg")); + _emoticonMap.insert(new QRegularExpression(QRegExp::escape(":(")), new QString("../resources/images/sad.svg")); + _emoticonMap.insert(new QRegularExpression(QRegExp::escape(":P")), new QString("../resources/images/tongue.svg")); + _emoticonMap.insert(new QRegularExpression(QRegExp::escape(";)")), new QString("../resources/images/wink.svg")); + #ifdef HAVE_QXMPP const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient(); if (xmppClient.isConnected()) { @@ -284,6 +294,13 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { QString messageText = message.body().toHtmlEscaped(); messageText = messageText.replace(regexLinks, "\\1"); messageText = messageText.replace(regexHifiLinks, "\\1"); + + QMapIterator it(_emoticonMap); + while (it.hasNext()) { + it.next(); + messageText.replace(*it.key(), ""); + } + messageArea->setHtml(userLabel + messageText); bool atBottom = isAtBottom(); diff --git a/interface/src/ui/ChatWindow.h b/interface/src/ui/ChatWindow.h index 399c9e917c..3dce35b1b2 100644 --- a/interface/src/ui/ChatWindow.h +++ b/interface/src/ui/ChatWindow.h @@ -57,6 +57,7 @@ private: QDateTime lastMessageStamp; bool _mousePressed; QPoint _mouseStartPosition; + QMap _emoticonMap; private slots: void connected(); From c0ae2fd7ae5b100af15a69f892205736271adc06 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 17 Apr 2014 19:53:59 -0700 Subject: [PATCH 20/56] Add QDesktopServices header to Menu.cpp --- interface/src/Menu.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ad765c0e8e..5ff74f0ad9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include From 378afdf117fb2617232b636311b34dcd27a3e2d9 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 23 Apr 2014 10:35:24 -0700 Subject: [PATCH 21/56] More undo work --- libraries/voxels/src/VoxelTree.cpp | 2 +- libraries/voxels/src/VoxelTreeCommands.cpp | 26 ++++------------------ 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index bb9de72e9d..3a77382a84 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -42,7 +42,7 @@ void VoxelTree::deleteVoxelAt(float x, float y, float z, float s) { } VoxelTreeElement* VoxelTree::getVoxelAt(float x, float y, float z, float s) const { - return (VoxelTreeElement*)getOctreeElementAt(x, y, z, s); + return static_cast(getOctreeElementAt(x, y, z, s)); } void VoxelTree::createVoxel(float x, float y, float z, float s, diff --git a/libraries/voxels/src/VoxelTreeCommands.cpp b/libraries/voxels/src/VoxelTreeCommands.cpp index 75b38667ec..46837aa23e 100644 --- a/libraries/voxels/src/VoxelTreeCommands.cpp +++ b/libraries/voxels/src/VoxelTreeCommands.cpp @@ -22,27 +22,8 @@ AddVoxelCommand::AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditP { VoxelTreeElement* element = _tree->getVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); if (element) { - if (element->hasContent() && element->isLeaf()) { - // Do nothing, everything is in order - } else { - _oldTree = new VoxelTree(); - _tree->copySubTreeIntoNewTree(element, _oldTree, true); - } - } else { - glm::vec3 point(_voxel.x + _voxel.s / 2.0f, - _voxel.y + _voxel.s / 2.0f, - _voxel.z + _voxel.s / 2.0f); - OctreeElement* element = _tree->getElementEnclosingPoint(point, Octree::Lock); - if (element) { - VoxelTreeElement* node = static_cast(element); - _voxel.x = node->getCorner().x; - _voxel.y = node->getCorner().y; - _voxel.z = node->getCorner().z; - _voxel.s = node->getScale(); - _voxel.red = node->getColor()[0]; - _voxel.green = node->getColor()[1]; - _voxel.blue = node->getColor()[2]; - } + _oldTree = new VoxelTree(); + _tree->copySubTreeIntoNewTree(element, _oldTree, true); } } @@ -62,8 +43,9 @@ void AddVoxelCommand::redo() { void AddVoxelCommand::undo() { if (_oldTree) { OctreeElement* element = _tree->getOrCreateChildElementAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - qDebug() << _voxel.x << " " << _voxel.y << " " << _voxel.z << " " << _voxel.s; + qDebug() << "undo(): " << _voxel.x << " " << _voxel.y << " " << _voxel.z << " " << _voxel.s; _tree->copyFromTreeIntoSubTree(_oldTree, element); + qDebug() << "done"; } else { if (_tree) { _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); From 9bea70ac54d3a11fd76bf7e77a30556993f86973 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 23 Apr 2014 10:49:22 -0700 Subject: [PATCH 22/56] Revert "Add emoticons to chat" This reverts commit 3c9b6264a8354f514324f6a97992a67b01ad924a. --- interface/resources/images/cool.svg | 8 -------- interface/resources/images/grin.svg | 8 -------- interface/resources/images/happy.svg | 8 -------- interface/resources/images/sad.svg | 8 -------- interface/resources/images/smiley.svg | 8 -------- interface/resources/images/tongue.svg | 8 -------- interface/resources/images/wink.svg | 8 -------- interface/src/ui/ChatWindow.cpp | 19 +------------------ interface/src/ui/ChatWindow.h | 1 - 9 files changed, 1 insertion(+), 75 deletions(-) delete mode 100644 interface/resources/images/cool.svg delete mode 100644 interface/resources/images/grin.svg delete mode 100644 interface/resources/images/happy.svg delete mode 100644 interface/resources/images/sad.svg delete mode 100644 interface/resources/images/smiley.svg delete mode 100644 interface/resources/images/tongue.svg delete mode 100644 interface/resources/images/wink.svg diff --git a/interface/resources/images/cool.svg b/interface/resources/images/cool.svg deleted file mode 100644 index 2e8348108a..0000000000 --- a/interface/resources/images/cool.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/interface/resources/images/grin.svg b/interface/resources/images/grin.svg deleted file mode 100644 index 8e36a16555..0000000000 --- a/interface/resources/images/grin.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/interface/resources/images/happy.svg b/interface/resources/images/happy.svg deleted file mode 100644 index fe31d01991..0000000000 --- a/interface/resources/images/happy.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/interface/resources/images/sad.svg b/interface/resources/images/sad.svg deleted file mode 100644 index 0029bfded5..0000000000 --- a/interface/resources/images/sad.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/interface/resources/images/smiley.svg b/interface/resources/images/smiley.svg deleted file mode 100644 index 1b0e707bf6..0000000000 --- a/interface/resources/images/smiley.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/interface/resources/images/tongue.svg b/interface/resources/images/tongue.svg deleted file mode 100644 index 35361d2b2b..0000000000 --- a/interface/resources/images/tongue.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/interface/resources/images/wink.svg b/interface/resources/images/wink.svg deleted file mode 100644 index b1aef4823d..0000000000 --- a/interface/resources/images/wink.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 06608ef5e4..c459a6d426 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -31,14 +31,12 @@ const int NUM_MESSAGES_TO_TIME_STAMP = 20; const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?))://\\S+)"); const QRegularExpression regexHifiLinks("([#@]\\S+)"); - ChatWindow::ChatWindow(QWidget* parent) : FramelessDialog(parent, 0, POSITION_RIGHT), ui(new Ui::ChatWindow), numMessagesAfterLastTimeStamp(0), _mousePressed(false), - _mouseStartPosition(), - _emoticonMap() + _mouseStartPosition() { setAttribute(Qt::WA_DeleteOnClose, false); @@ -65,14 +63,6 @@ ChatWindow::ChatWindow(QWidget* parent) : ui->connectingToXMPPLabel->setText(tr("You must be logged in to chat with others.")); } - _emoticonMap.insert(new QRegularExpression(QRegExp::escape(":)")), new QString("../resources/images/smiley.svg")); - _emoticonMap.insert(new QRegularExpression(QRegExp::escape(":D")), new QString("../resources/images/happy.svg")); - _emoticonMap.insert(new QRegularExpression(QRegExp::escape("B)")), new QString("../resources/images/cool.svg")); - _emoticonMap.insert(new QRegularExpression(QRegExp::escape(":O")), new QString("../resources/images/grin.svg")); - _emoticonMap.insert(new QRegularExpression(QRegExp::escape(":(")), new QString("../resources/images/sad.svg")); - _emoticonMap.insert(new QRegularExpression(QRegExp::escape(":P")), new QString("../resources/images/tongue.svg")); - _emoticonMap.insert(new QRegularExpression(QRegExp::escape(";)")), new QString("../resources/images/wink.svg")); - #ifdef HAVE_QXMPP const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient(); if (xmppClient.isConnected()) { @@ -294,13 +284,6 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { QString messageText = message.body().toHtmlEscaped(); messageText = messageText.replace(regexLinks, "\\1"); messageText = messageText.replace(regexHifiLinks, "\\1"); - - QMapIterator it(_emoticonMap); - while (it.hasNext()) { - it.next(); - messageText.replace(*it.key(), ""); - } - messageArea->setHtml(userLabel + messageText); bool atBottom = isAtBottom(); diff --git a/interface/src/ui/ChatWindow.h b/interface/src/ui/ChatWindow.h index 3dce35b1b2..399c9e917c 100644 --- a/interface/src/ui/ChatWindow.h +++ b/interface/src/ui/ChatWindow.h @@ -57,7 +57,6 @@ private: QDateTime lastMessageStamp; bool _mousePressed; QPoint _mouseStartPosition; - QMap _emoticonMap; private slots: void connected(); From 359c14e3191333e8d4300b56c64cf529d3b2175f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 11:48:42 -0700 Subject: [PATCH 23/56] cleanup: remove unused Avatar::_mode The mode, if it is required, should probably eventually live in AvatarDAta since it will be determined by whatever engine is running the avatar (script or interface) and then broadcast to the rest of the world. When we need it we'll add it back in the right place. --- interface/src/avatar/Avatar.cpp | 13 ++----------- interface/src/avatar/Avatar.h | 8 -------- interface/src/avatar/MyAvatar.cpp | 10 +--------- interface/src/avatar/MyAvatar.h | 1 - 4 files changed, 3 insertions(+), 29 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index fe685b89f8..5173caa051 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -47,7 +47,6 @@ Avatar::Avatar() : AvatarData(), _skeletonModel(this), _bodyYawDelta(0.0f), - _mode(AVATAR_MODE_STANDING), _velocity(0.0f, 0.0f, 0.0f), _thrust(0.0f, 0.0f, 0.0f), _leanScale(0.5f), @@ -138,19 +137,11 @@ void Avatar::simulate(float deltaTime) { head->simulate(deltaTime, false, _shouldRenderBillboard); } - // use speed and angular velocity to determine walking vs. standing - float speed = glm::length(_velocity); - if (speed + fabs(_bodyYawDelta) > 0.2) { - _mode = AVATAR_MODE_WALKING; - } else { - _mode = AVATAR_MODE_INTERACTING; - } - // update position by velocity, and subtract the change added earlier for gravity _position += _velocity * deltaTime; // Zero thrust out now that we've added it to velocity in this frame - _thrust = glm::vec3(0, 0, 0); + _thrust = glm::vec3(0.0f); // update animation for display name fade in/out if ( _displayNameTargetAlpha != _displayNameAlpha) { @@ -166,7 +157,7 @@ void Avatar::simulate(float deltaTime) { // Fading in _displayNameAlpha = 1 - (1 - _displayNameAlpha) * coef; } - _displayNameAlpha = abs(_displayNameAlpha - _displayNameTargetAlpha) < 0.01? _displayNameTargetAlpha : _displayNameAlpha; + _displayNameAlpha = abs(_displayNameAlpha - _displayNameTargetAlpha) < 0.01f ? _displayNameTargetAlpha : _displayNameAlpha; } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ecf1be4899..39cc174e69 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -46,13 +46,6 @@ enum DriveKeys { MAX_DRIVE_KEYS }; -enum AvatarMode { - AVATAR_MODE_STANDING = 0, - AVATAR_MODE_WALKING, - AVATAR_MODE_INTERACTING, - NUM_AVATAR_MODES -}; - enum ScreenTintLayer { SCREEN_TINT_BEFORE_LANDSCAPE = 0, SCREEN_TINT_BEFORE_AVATARS, @@ -164,7 +157,6 @@ signals: protected: SkeletonModel _skeletonModel; float _bodyYawDelta; - AvatarMode _mode; glm::vec3 _velocity; glm::vec3 _thrust; float _leanScale; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e1d7463aa3..de0c507272 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -269,17 +269,9 @@ void MyAvatar::simulate(float deltaTime) { // update the euler angles setOrientation(orientation); - const float WALKING_SPEED_THRESHOLD = 0.2f; - // use speed and angular velocity to determine walking vs. standing - float speed = glm::length(_velocity); - if (speed + fabs(_bodyYawDelta) > WALKING_SPEED_THRESHOLD) { - _mode = AVATAR_MODE_WALKING; - } else { - _mode = AVATAR_MODE_INTERACTING; - } - // update moving flag based on speed const float MOVING_SPEED_THRESHOLD = 0.01f; + float speed = glm::length(_velocity); _moving = speed > MOVING_SPEED_THRESHOLD; // If a move target is set, update position explicitly diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 71c74f7c91..f6c83c7ac4 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -54,7 +54,6 @@ public: void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; } // getters - AvatarMode getMode() const { return _mode; } float getLeanScale() const { return _leanScale; } float getElapsedTimeStopped() const { return _elapsedTimeStopped; } float getElapsedTimeMoving() const { return _elapsedTimeMoving; } From 37a5d9130f6ae6050cdfc47adb15083f0f2c7664 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 11:55:28 -0700 Subject: [PATCH 24/56] move _thrust from Avatar to MyAvatar --- interface/src/avatar/Avatar.cpp | 4 ---- interface/src/avatar/Avatar.h | 1 - interface/src/avatar/MyAvatar.cpp | 3 ++- interface/src/avatar/MyAvatar.h | 1 + 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 5173caa051..2df1fd2302 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -48,7 +48,6 @@ Avatar::Avatar() : _skeletonModel(this), _bodyYawDelta(0.0f), _velocity(0.0f, 0.0f, 0.0f), - _thrust(0.0f, 0.0f, 0.0f), _leanScale(0.5f), _scale(1.0f), _worldUpDirection(DEFAULT_UP_DIRECTION), @@ -140,9 +139,6 @@ void Avatar::simulate(float deltaTime) { // update position by velocity, and subtract the change added earlier for gravity _position += _velocity * deltaTime; - // Zero thrust out now that we've added it to velocity in this frame - _thrust = glm::vec3(0.0f); - // update animation for display name fade in/out if ( _displayNameTargetAlpha != _displayNameAlpha) { // the alpha function is diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 39cc174e69..805a60d425 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -158,7 +158,6 @@ protected: SkeletonModel _skeletonModel; float _bodyYawDelta; glm::vec3 _velocity; - glm::vec3 _thrust; float _leanScale; float _scale; glm::vec3 _worldUpDirection; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index de0c507272..33a1127a64 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -59,6 +59,7 @@ MyAvatar::MyAvatar() : _elapsedTimeSinceCollision(0.0f), _lastCollisionPosition(0, 0, 0), _speedBrakes(false), + _thrust(0.0f), _isThrustOn(false), _thrustMultiplier(1.0f), _moveTarget(0,0,0), @@ -316,7 +317,7 @@ void MyAvatar::simulate(float deltaTime) { head->simulate(deltaTime, true); // Zero thrust out now that we've added it to velocity in this frame - _thrust = glm::vec3(0.0f); + _thrust *= glm::vec3(0.0f); // now that we're done stepping the avatar forward in time, compute new collisions if (_collisionFlags != 0) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index f6c83c7ac4..5cdb13682f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -122,6 +122,7 @@ private: float _elapsedTimeSinceCollision; glm::vec3 _lastCollisionPosition; bool _speedBrakes; + glm::vec3 _thrust; bool _isThrustOn; float _thrustMultiplier; glm::vec3 _moveTarget; From 951d5004e121947b4379ccd951368a5b85046d48 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 23 Apr 2014 11:57:43 -0700 Subject: [PATCH 25/56] Add ChatInputArea with custom paste --- interface/src/ui/ChatMessageArea.h | 4 ++++ interface/ui/chatWindow.ui | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/ChatMessageArea.h b/interface/src/ui/ChatMessageArea.h index 48cfc01aec..b726a31d76 100644 --- a/interface/src/ui/ChatMessageArea.h +++ b/interface/src/ui/ChatMessageArea.h @@ -33,6 +33,10 @@ protected: virtual void wheelEvent(QWheelEvent* event); bool _useFixedHeight; + void insertFromMimeData(const QMimeData* source) { + insertPlainText(source->text()); + }; + }; #endif // hifi_ChatMessageArea_h diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index d63542bf7b..28aa6a2390 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -186,7 +186,7 @@ QPushButton:pressed { - + 0 @@ -223,6 +223,13 @@ QPushButton:pressed { + + + ChatInputArea + QTextEdit +
ui/ChatInputArea.h
+
+
messagePlainTextEdit messagesScrollArea From 39c193a679c56dd565d9307ac51c9a3bcfe9f962 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 12:15:15 -0700 Subject: [PATCH 26/56] remove unused getElapsedTime*() methods --- interface/src/avatar/MyAvatar.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 5cdb13682f..592e1172af 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -55,8 +55,6 @@ public: // getters float getLeanScale() const { return _leanScale; } - float getElapsedTimeStopped() const { return _elapsedTimeStopped; } - float getElapsedTimeMoving() const { return _elapsedTimeMoving; } const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } glm::vec3 getGravity() const { return _gravity; } @@ -117,14 +115,17 @@ private: float _driveKeys[MAX_DRIVE_KEYS]; glm::vec3 _gravity; float _distanceToNearestAvatar; // How close is the nearest avatar? + + // motion stuff float _elapsedTimeMoving; // Timers to drive camera transitions when moving float _elapsedTimeStopped; float _elapsedTimeSinceCollision; glm::vec3 _lastCollisionPosition; bool _speedBrakes; - glm::vec3 _thrust; + glm::vec3 _thrust; // final acceleration for the current frame bool _isThrustOn; float _thrustMultiplier; + glm::vec3 _moveTarget; glm::vec3 _lastBodyPenetration; int _moveTargetStepCounter; From 203dac054ad734ff630eb7b974f408473d4332af Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 12:19:48 -0700 Subject: [PATCH 27/56] remove unused MoveTarget stuff from MyAvatar --- interface/src/avatar/MyAvatar.cpp | 22 ---------------------- interface/src/avatar/MyAvatar.h | 2 -- 2 files changed, 24 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 33a1127a64..77698ea823 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -62,9 +62,7 @@ MyAvatar::MyAvatar() : _thrust(0.0f), _isThrustOn(false), _thrustMultiplier(1.0f), - _moveTarget(0,0,0), _lastBodyPenetration(0.0f), - _moveTargetStepCounter(0), _lookAtTargetAvatar(), _shouldRender(true), _billboardValid(false), @@ -98,11 +96,6 @@ void MyAvatar::reset() { setOrientation(glm::quat(glm::vec3(0.0f))); } -void MyAvatar::setMoveTarget(const glm::vec3 moveTarget) { - _moveTarget = moveTarget; - _moveTargetStepCounter = 0; -} - void MyAvatar::update(float deltaTime) { Head* head = getHead(); head->relaxLean(deltaTime); @@ -275,21 +268,6 @@ void MyAvatar::simulate(float deltaTime) { float speed = glm::length(_velocity); _moving = speed > MOVING_SPEED_THRESHOLD; - // If a move target is set, update position explicitly - const float MOVE_FINISHED_TOLERANCE = 0.1f; - const float MOVE_SPEED_FACTOR = 2.0f; - const int MOVE_TARGET_MAX_STEPS = 250; - if ((glm::length(_moveTarget) > EPSILON) && (_moveTargetStepCounter < MOVE_TARGET_MAX_STEPS)) { - if (glm::length(_position - _moveTarget) > MOVE_FINISHED_TOLERANCE) { - _position += (_moveTarget - _position) * (deltaTime * MOVE_SPEED_FACTOR); - _moveTargetStepCounter++; - } else { - // Move completed - _moveTarget = glm::vec3(0,0,0); - _moveTargetStepCounter = 0; - } - } - updateChatCircle(deltaTime); _position += _velocity * deltaTime; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 592e1172af..ab6181120e 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -126,9 +126,7 @@ private: bool _isThrustOn; float _thrustMultiplier; - glm::vec3 _moveTarget; glm::vec3 _lastBodyPenetration; - int _moveTargetStepCounter; QWeakPointer _lookAtTargetAvatar; glm::vec3 _targetAvatarPosition; bool _shouldRender; From 5fd585aab1c7206c749b7fd44b66e65e663c477d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 23 Apr 2014 12:26:59 -0700 Subject: [PATCH 28/56] Fix error with cursor format getting reset when sending chat message --- interface/src/ui/ChatWindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index c459a6d426..d967e2305d 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -128,7 +128,9 @@ bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { message.setBody(messageText); XmppClient::getInstance().getXMPPClient().sendPacket(message); #endif - ui->messagePlainTextEdit->document()->clear(); + QTextCursor cursor = ui->messagePlainTextEdit->textCursor(); + cursor.select(QTextCursor::Document); + cursor.removeSelectedText(); } return true; } From 95357a7c35063b8a44171ac9fd6e301aeb9e83da Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 23 Apr 2014 12:30:40 -0700 Subject: [PATCH 29/56] Update chat input area to use a 14pt font --- interface/ui/chatWindow.ui | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index 28aa6a2390..b1448091c4 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -199,6 +199,12 @@ QPushButton:pressed { 60 + + + Helvetica,Arial,sans-serif + 14 + + border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px; From 96ca53740008bf025f7781de87d12a9c86035c6e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 13:44:25 -0700 Subject: [PATCH 30/56] removing unused motion-state timers --- interface/src/avatar/MyAvatar.cpp | 15 --------------- interface/src/avatar/MyAvatar.h | 3 --- 2 files changed, 18 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 77698ea823..1de9b74c89 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -54,9 +54,6 @@ MyAvatar::MyAvatar() : _shouldJump(false), _gravity(0.0f, -1.0f, 0.0f), _distanceToNearestAvatar(std::numeric_limits::max()), - _elapsedTimeMoving(0.0f), - _elapsedTimeStopped(0.0f), - _elapsedTimeSinceCollision(0.0f), _lastCollisionPosition(0, 0, 0), _speedBrakes(false), _thrust(0.0f), @@ -139,17 +136,6 @@ void MyAvatar::simulate(float deltaTime) { glm::quat orientation = getOrientation(); - // Update movement timers - _elapsedTimeSinceCollision += deltaTime; - const float VELOCITY_MOVEMENT_TIMER_THRESHOLD = 0.2f; - if (glm::length(_velocity) < VELOCITY_MOVEMENT_TIMER_THRESHOLD) { - _elapsedTimeMoving = 0.0f; - _elapsedTimeStopped += deltaTime; - } else { - _elapsedTimeStopped = 0.0f; - _elapsedTimeMoving += deltaTime; - } - if (_scale != _targetScale) { float scale = (1.0f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale; setScale(scale); @@ -798,7 +784,6 @@ void MyAvatar::applyHardCollision(const glm::vec3& penetration, float elasticity // cancel out the velocity component in the direction of penetration float penetrationLength = glm::length(penetration); if (penetrationLength > EPSILON) { - _elapsedTimeSinceCollision = 0.0f; glm::vec3 direction = penetration / penetrationLength; _velocity -= glm::dot(_velocity, direction) * direction * (1.0f + elasticity); _velocity *= glm::clamp(1.0f - damping, 0.0f, 1.0f); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index ab6181120e..b713f1c223 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -117,9 +117,6 @@ private: float _distanceToNearestAvatar; // How close is the nearest avatar? // motion stuff - float _elapsedTimeMoving; // Timers to drive camera transitions when moving - float _elapsedTimeStopped; - float _elapsedTimeSinceCollision; glm::vec3 _lastCollisionPosition; bool _speedBrakes; glm::vec3 _thrust; // final acceleration for the current frame From 10265a4a3e0d48fdccd66eb23059bdd1f2896905 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 14:37:24 -0700 Subject: [PATCH 31/56] temp disable of screen flash for avatar collisions --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1de9b74c89..17ff79c443 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -820,7 +820,7 @@ void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTim std::min(COLLISION_LOUDNESS * velocityTowardCollision, 1.0f), frequency * (1.0f + velocityTangentToCollision / velocityTowardCollision), std::min(velocityTangentToCollision / velocityTowardCollision * NOISE_SCALING, 1.0f), - 1.0f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision, true); + 1.0f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision, false); } } From d56a4e169e726ea67f55b890fa57dfba9c1928d9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 23 Apr 2014 15:24:21 -0700 Subject: [PATCH 32/56] Add ChatInputArea --- interface/src/ui/ChatInputArea.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 interface/src/ui/ChatInputArea.h diff --git a/interface/src/ui/ChatInputArea.h b/interface/src/ui/ChatInputArea.h new file mode 100644 index 0000000000..264a9932c6 --- /dev/null +++ b/interface/src/ui/ChatInputArea.h @@ -0,0 +1,28 @@ +// +// ChatInputArea.h +// interface/src/ui +// +// Created by Ryan Huffman on 4/11/14. +// Copyright 2014 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_ChatInputArea_h +#define hifi_ChatInputArea_h + +#include + +class ChatInputArea : public QTextEdit { + Q_OBJECT +public: + ChatInputArea(QWidget* parent) : QTextEdit(parent) { }; + +protected: + void insertFromMimeData(const QMimeData* source) { + insertPlainText(source->text()); + }; +}; + +#endif // hifi_ChatInputArea_h From 1774f6c9bdcddf9219afacd478a9ed8bc1856e96 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 23 Apr 2014 15:37:28 -0700 Subject: [PATCH 33/56] Add threshold to auto scroll --- interface/src/ui/ChatWindow.cpp | 10 +++++----- interface/src/ui/ChatWindow.h | 8 +++++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index d967e2305d..e0802c6bc5 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -171,7 +171,7 @@ void ChatWindow::addTimeStamp() { timeLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); timeLabel->setAlignment(Qt::AlignLeft); - bool atBottom = isAtBottom(); + bool atBottom = isNearBottom(); ui->messagesVBoxLayout->addWidget(timeLabel); ui->messagesVBoxLayout->parentWidget()->updateGeometry(); @@ -288,7 +288,7 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { messageText = messageText.replace(regexHifiLinks, "\\1"); messageArea->setHtml(userLabel + messageText); - bool atBottom = isAtBottom(); + bool atBottom = isNearBottom(); ui->messagesVBoxLayout->addWidget(messageArea); ui->messagesVBoxLayout->parentWidget()->updateGeometry(); @@ -308,13 +308,13 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { #endif -bool ChatWindow::isAtBottom() { +bool ChatWindow::isNearBottom() { QScrollBar* verticalScrollBar = ui->messagesScrollArea->verticalScrollBar(); - return verticalScrollBar->sliderPosition() == verticalScrollBar->maximum(); + return verticalScrollBar->value() >= verticalScrollBar->maximum() - Ui::AUTO_SCROLL_THRESHOLD; } // Scroll chat message area to bottom. void ChatWindow::scrollToBottom() { QScrollBar* verticalScrollBar = ui->messagesScrollArea->verticalScrollBar(); - verticalScrollBar->setSliderPosition(verticalScrollBar->maximum()); + verticalScrollBar->setValue(verticalScrollBar->maximum()); } diff --git a/interface/src/ui/ChatWindow.h b/interface/src/ui/ChatWindow.h index 399c9e917c..104fbe1746 100644 --- a/interface/src/ui/ChatWindow.h +++ b/interface/src/ui/ChatWindow.h @@ -27,6 +27,12 @@ #endif namespace Ui { + + +// Maximum amount the chat can be scrolled up in order to auto scroll. +const int AUTO_SCROLL_THRESHOLD = 20; + + class ChatWindow; } @@ -49,7 +55,7 @@ private: #endif void startTimerForTimeStamps(); void addTimeStamp(); - bool isAtBottom(); + bool isNearBottom(); void scrollToBottom(); Ui::ChatWindow* ui; From 0cba95e7ad1f8550eec37743af415ba2b03f80a7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 23 Apr 2014 15:37:49 -0700 Subject: [PATCH 34/56] Reorder property initialization in FramelessDialog --- interface/src/ui/FramelessDialog.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/FramelessDialog.cpp b/interface/src/ui/FramelessDialog.cpp index 816c45b38a..4919e99db6 100644 --- a/interface/src/ui/FramelessDialog.cpp +++ b/interface/src/ui/FramelessDialog.cpp @@ -16,10 +16,10 @@ const int RESIZE_HANDLE_WIDTH = 7; FramelessDialog::FramelessDialog(QWidget *parent, Qt::WindowFlags flags, Position position) : QDialog(parent, flags | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint), - _position(position), - _selfHidden(false), _isResizing(false), - _resizeInitialWidth(0) { + _resizeInitialWidth(0), + _selfHidden(false), + _position(position) { setAttribute(Qt::WA_DeleteOnClose); From b0e1eab7ed19b1967d9514d8d35495024b3ea863 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 23 Apr 2014 16:15:51 -0700 Subject: [PATCH 35/56] Fix chat input textbox to use native scrollbar The border around the textedit was causing QT to use a non-native scrollbar. Moving the box into a frame that contains the border styling fixes this. --- interface/ui/chatWindow.ui | 85 ++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 21 deletions(-) diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index b1448091c4..4d223b2665 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -186,9 +186,9 @@ QPushButton:pressed { - + - + 0 0 @@ -196,33 +196,77 @@ QPushButton:pressed { 0 - 60 + 78 - - - Helvetica,Arial,sans-serif - 14 - - - border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px; + #chatFrame { +border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px; +} QFrame::NoFrame - - Qt::ScrollBarAlwaysOff + + QFrame::Raised - - QAbstractScrollArea::AdjustToContents - - - true - - - false + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 60 + + + + + Helvetica,Arial,sans-serif + 14 + + + + + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + QAbstractScrollArea::AdjustToContents + + + true + + + false + + + + @@ -237,7 +281,6 @@ QPushButton:pressed { - messagePlainTextEdit messagesScrollArea From 9bdcfe6d041fcf192b1e20597e118f6f130a5c79 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 24 Apr 2014 11:01:12 -0700 Subject: [PATCH 36/56] Undo now fully support local subtrees --- examples/editVoxels.js | 2 - libraries/voxels/src/VoxelTree.cpp | 7 + libraries/voxels/src/VoxelTree.h | 1 + libraries/voxels/src/VoxelTreeCommands.cpp | 130 +++++++++++++----- libraries/voxels/src/VoxelTreeCommands.h | 2 - .../voxels/src/VoxelsScriptingInterface.cpp | 36 ++--- 6 files changed, 115 insertions(+), 63 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 12c571b09c..453ac28649 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -1088,7 +1088,6 @@ function keyPressEvent(event) { red: colors[whichColor].red, green: colors[whichColor].green, blue: colors[whichColor].blue }; - Voxels.eraseVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s); Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue); setAudioPosition(); initialVoxelSound.playRandom(); @@ -1394,7 +1393,6 @@ function checkControllers() { if (Vec3.length(Vec3.subtract(fingerTipPosition,lastFingerAddVoxel)) > (FINGERTIP_VOXEL_SIZE / 2)) { newColor = { red: colors[whichColor].red, green: colors[whichColor].green, blue: colors[whichColor].blue }; - Voxels.eraseVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE); Voxels.setVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE, newColor.red, newColor.green, newColor.blue); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 3a77382a84..aeb877ef78 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -45,6 +45,13 @@ VoxelTreeElement* VoxelTree::getVoxelAt(float x, float y, float z, float s) cons return static_cast(getOctreeElementAt(x, y, z, s)); } +VoxelTreeElement* VoxelTree::getEnclosingVoxelAt(float x, float y, float z, float s) const { + unsigned char* octalCode = pointToOctalCode(x,y,z,s); + OctreeElement* node = nodeForOctalCode(_rootNode, octalCode, NULL); + + return static_cast(node); +} + void VoxelTree::createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue, bool destructive) { diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index e0bc1d9a47..2992815787 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -30,6 +30,7 @@ public: void deleteVoxelAt(float x, float y, float z, float s); VoxelTreeElement* getVoxelAt(float x, float y, float z, float s) const; + VoxelTreeElement* getEnclosingVoxelAt(float x, float y, float z, float s) const; void createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue, bool destructive = false); diff --git a/libraries/voxels/src/VoxelTreeCommands.cpp b/libraries/voxels/src/VoxelTreeCommands.cpp index 46837aa23e..d1dc0f3560 100644 --- a/libraries/voxels/src/VoxelTreeCommands.cpp +++ b/libraries/voxels/src/VoxelTreeCommands.cpp @@ -13,22 +13,56 @@ #include "VoxelTreeCommands.h" + + +struct SendVoxelsOperationArgs { + const unsigned char* newBaseOctCode; + VoxelEditPacketSender* packetSender; +}; + +bool sendVoxelsOperation(OctreeElement* element, void* extraData) { + VoxelTreeElement* voxel = (VoxelTreeElement*)element; + SendVoxelsOperationArgs* args = (SendVoxelsOperationArgs*)extraData; + if (voxel->isColored()) { + const unsigned char* nodeOctalCode = voxel->getOctalCode(); + unsigned char* codeColorBuffer = NULL; + int codeLength = 0; + int bytesInCode = 0; + int codeAndColorLength; + + // If the newBase is NULL, then don't rebase + if (args->newBaseOctCode) { + codeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true); + codeLength = numberOfThreeBitSectionsInCode(codeColorBuffer); + bytesInCode = bytesRequiredForCodeLength(codeLength); + codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; + } else { + codeLength = numberOfThreeBitSectionsInCode(nodeOctalCode); + bytesInCode = bytesRequiredForCodeLength(codeLength); + codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; + codeColorBuffer = new unsigned char[codeAndColorLength]; + memcpy(codeColorBuffer, nodeOctalCode, bytesInCode); + } + + // copy the colors over + codeColorBuffer[bytesInCode + RED_INDEX] = voxel->getColor()[RED_INDEX]; + codeColorBuffer[bytesInCode + GREEN_INDEX] = voxel->getColor()[GREEN_INDEX]; + codeColorBuffer[bytesInCode + BLUE_INDEX] = voxel->getColor()[BLUE_INDEX]; + args->packetSender->queueVoxelEditMessage(PacketTypeVoxelSetDestructive, + codeColorBuffer, codeAndColorLength); + + delete[] codeColorBuffer; + } + return true; // keep going +} + + AddVoxelCommand::AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender, QUndoCommand* parent) : QUndoCommand("Add Voxel", parent), _tree(tree), _packetSender(packetSender), - _voxel(voxel), - _oldTree(NULL) + _voxel(voxel) { - VoxelTreeElement* element = _tree->getVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - if (element) { - _oldTree = new VoxelTree(); - _tree->copySubTreeIntoNewTree(element, _oldTree, true); - } -} - -AddVoxelCommand::~AddVoxelCommand() { - delete _oldTree; } void AddVoxelCommand::redo() { @@ -41,18 +75,11 @@ void AddVoxelCommand::redo() { } void AddVoxelCommand::undo() { - if (_oldTree) { - OctreeElement* element = _tree->getOrCreateChildElementAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - qDebug() << "undo(): " << _voxel.x << " " << _voxel.y << " " << _voxel.z << " " << _voxel.s; - _tree->copyFromTreeIntoSubTree(_oldTree, element); - qDebug() << "done"; - } else { - if (_tree) { - _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); - } + if (_tree) { + _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + } + if (_packetSender) { + _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); } } @@ -63,6 +90,26 @@ DeleteVoxelCommand::DeleteVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, Voxe _voxel(voxel), _oldTree(NULL) { + _tree->lockForRead(); + VoxelTreeElement* element = _tree->getEnclosingVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + if (element->getScale() == _voxel.s) { + if (!element->hasContent() && !element->isLeaf()) { + _oldTree = new VoxelTree(); + _tree->copySubTreeIntoNewTree(element, _oldTree, false); + } else { + _voxel.red = element->getColor()[0]; + _voxel.green = element->getColor()[1]; + _voxel.blue = element->getColor()[2]; + } + } else if (element->hasContent() && element->isLeaf()) { + _voxel.red = element->getColor()[0]; + _voxel.green = element->getColor()[1]; + _voxel.blue = element->getColor()[2]; + } else { + _voxel.s = 0.0f; + qDebug() << "No element for delete."; + } + _tree->unlock(); } DeleteVoxelCommand::~DeleteVoxelCommand() { @@ -70,21 +117,38 @@ DeleteVoxelCommand::~DeleteVoxelCommand() { } void DeleteVoxelCommand::redo() { - if (_oldTree) { - - } else { - if (_tree) { - _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); - } + if (_voxel.s == 0) { + return; + } + + if (_tree) { + _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); } + if (_packetSender) { + _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); } } void DeleteVoxelCommand::undo() { + if (_voxel.s == 0) { + return; + } + if (_oldTree) { - + VoxelTreeElement* element = _oldTree->getVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + if (element) { + if (_tree) { + _tree->lockForWrite(); + _oldTree->copySubTreeIntoNewTree(element, _tree, false); + _tree->unlock(); + } + if (_packetSender) { + SendVoxelsOperationArgs args; + args.newBaseOctCode = NULL; + args.packetSender = _packetSender; + _oldTree->recurseTreeWithOperation(sendVoxelsOperation, &args); + _packetSender->releaseQueuedMessages(); + } + } } else { if (_tree) { _tree->createVoxel(_voxel.x, _voxel.y, _voxel.z, _voxel.s, _voxel.red, _voxel.green, _voxel.blue); diff --git a/libraries/voxels/src/VoxelTreeCommands.h b/libraries/voxels/src/VoxelTreeCommands.h index c3b23e7201..8df1f0dc14 100644 --- a/libraries/voxels/src/VoxelTreeCommands.h +++ b/libraries/voxels/src/VoxelTreeCommands.h @@ -23,7 +23,6 @@ class VoxelTree; class AddVoxelCommand : public QUndoCommand { public: AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender = NULL, QUndoCommand* parent = NULL); - ~AddVoxelCommand(); virtual void redo(); virtual void undo(); @@ -32,7 +31,6 @@ private: VoxelTree* _tree; VoxelEditPacketSender* _packetSender; VoxelDetail _voxel; - VoxelTree* _oldTree; }; class DeleteVoxelCommand : public QUndoCommand { diff --git a/libraries/voxels/src/VoxelsScriptingInterface.cpp b/libraries/voxels/src/VoxelsScriptingInterface.cpp index 08dcfd3f47..15503db454 100644 --- a/libraries/voxels/src/VoxelsScriptingInterface.cpp +++ b/libraries/voxels/src/VoxelsScriptingInterface.cpp @@ -76,32 +76,16 @@ void VoxelsScriptingInterface::setVoxel(float x, float y, float z, float scale, if (_tree) { if (_undoStack) { AddVoxelCommand* addCommand = new AddVoxelCommand(_tree, - addVoxelDetail, - getVoxelPacketSender()); - - VoxelTreeElement* deleteVoxelElement = _tree->getVoxelAt(addVoxelDetail.x, addVoxelDetail.y, addVoxelDetail.z, addVoxelDetail.s); - if (deleteVoxelElement) { - nodeColor color; - memcpy(&color, &deleteVoxelElement->getColor(), sizeof(nodeColor)); - VoxelDetail deleteVoxelDetail = {addVoxelDetail.x, - addVoxelDetail.y, - addVoxelDetail.z, - addVoxelDetail.s, - color[0], - color[1], - color[2]}; - DeleteVoxelCommand* delCommand = new DeleteVoxelCommand(_tree, - deleteVoxelDetail, - getVoxelPacketSender()); - _undoStack->beginMacro(addCommand->text()); - // As QUndoStack automatically executes redo() on push, we don't need to execute the command ourselves. - _undoStack->push(delCommand); - _undoStack->push(addCommand); - _undoStack->endMacro(); - } else { - // As QUndoStack automatically executes redo() on push, we don't need to execute the command ourselves. - _undoStack->push(addCommand); - } + addVoxelDetail, + getVoxelPacketSender()); + DeleteVoxelCommand* deleteCommand = new DeleteVoxelCommand(_tree, + addVoxelDetail, + getVoxelPacketSender()); + _undoStack->beginMacro(addCommand->text()); + // As QUndoStack automatically executes redo() on push, we don't need to execute the command ourselves. + _undoStack->push(deleteCommand); + _undoStack->push(addCommand); + _undoStack->endMacro(); } else { // queue the destructive add queueVoxelAdd(PacketTypeVoxelSetDestructive, addVoxelDetail); From f07a418a2708a19dc69c9583aa9c7cd2123c3453 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 24 Apr 2014 11:07:49 -0700 Subject: [PATCH 37/56] namechange CollisionFlags --> CollisionGroups --- interface/src/Menu.cpp | 10 +++++----- interface/src/avatar/Avatar.cpp | 16 ++++++++-------- interface/src/avatar/Avatar.h | 4 ++-- interface/src/avatar/MyAvatar.cpp | 18 +++++++----------- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 84b17fddca..74df3e4f63 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -505,7 +505,7 @@ void Menu::loadSettings(QSettings* settings) { // MyAvatar caches some menu options, so we have to update them whenever we load settings. // TODO: cache more settings in MyAvatar that are checked with very high frequency. MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - myAvatar->updateCollisionFlags(); + myAvatar->updateCollisionGroups(); if (lockedSettings) { Application::getInstance()->unlockSettings(); @@ -1368,13 +1368,13 @@ void Menu::addAvatarCollisionSubMenu(QMenu* overMenu) { Application* appInstance = Application::getInstance(); QObject* avatar = appInstance->getAvatar(); addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithEnvironment, - 0, false, avatar, SLOT(updateCollisionFlags())); + 0, false, avatar, SLOT(updateCollisionGroups())); addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithAvatars, - 0, true, avatar, SLOT(updateCollisionFlags())); + 0, true, avatar, SLOT(updateCollisionGroups())); addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithVoxels, - 0, false, avatar, SLOT(updateCollisionFlags())); + 0, false, avatar, SLOT(updateCollisionGroups())); addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithParticles, - 0, true, avatar, SLOT(updateCollisionFlags())); + 0, true, avatar, SLOT(updateCollisionGroups())); } QAction* Menu::getActionFromName(const QString& menuName, QMenu* menu) { diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 2df1fd2302..b060c3421a 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -54,7 +54,7 @@ Avatar::Avatar() : _mouseRayOrigin(0.0f, 0.0f, 0.0f), _mouseRayDirection(0.0f, 0.0f, 0.0f), _moving(false), - _collisionFlags(0), + _collisionGroups(0), _initialized(false), _shouldRenderBillboard(true) { @@ -550,7 +550,7 @@ bool Avatar::findCollisions(const QVector& shapes, CollisionList& } bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions) { - if (_collisionFlags & COLLISION_GROUP_PARTICLES) { + if (_collisionGroups & COLLISION_GROUP_PARTICLES) { return false; } bool collided = false; @@ -740,19 +740,19 @@ void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, glEnd(); } -void Avatar::updateCollisionFlags() { - _collisionFlags = 0; +void Avatar::updateCollisionGroups() { + _collisionGroups = 0; if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithEnvironment)) { - _collisionFlags |= COLLISION_GROUP_ENVIRONMENT; + _collisionGroups |= COLLISION_GROUP_ENVIRONMENT; } if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) { - _collisionFlags |= COLLISION_GROUP_AVATARS; + _collisionGroups |= COLLISION_GROUP_AVATARS; } if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithVoxels)) { - _collisionFlags |= COLLISION_GROUP_VOXELS; + _collisionGroups |= COLLISION_GROUP_VOXELS; } if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithParticles)) { - _collisionFlags |= COLLISION_GROUP_PARTICLES; + _collisionGroups |= COLLISION_GROUP_PARTICLES; } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 805a60d425..6106b9f39c 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -149,7 +149,7 @@ public: void updateShapePositions(); public slots: - void updateCollisionFlags(); + void updateCollisionGroups(); signals: void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision); @@ -166,7 +166,7 @@ protected: float _stringLength; bool _moving; ///< set when position is changing - uint32_t _collisionFlags; + uint32_t _collisionGroups; // protected methods... glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 17ff79c443..9f70f41631 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -284,7 +284,7 @@ void MyAvatar::simulate(float deltaTime) { _thrust *= glm::vec3(0.0f); // now that we're done stepping the avatar forward in time, compute new collisions - if (_collisionFlags != 0) { + if (_collisionGroups != 0) { Camera* myCamera = Application::getInstance()->getCamera(); float radius = getSkeletonHeight() * COLLISION_RADIUS_SCALE; @@ -292,15 +292,15 @@ void MyAvatar::simulate(float deltaTime) { radius = myCamera->getAspectRatio() * (myCamera->getNearClip() / cos(myCamera->getFieldOfView() / 2.0f)); radius *= COLLISION_RADIUS_SCALAR; } - if (_collisionFlags) { + if (_collisionGroups) { updateShapePositions(); - if (_collisionFlags & COLLISION_GROUP_ENVIRONMENT) { + if (_collisionGroups & COLLISION_GROUP_ENVIRONMENT) { updateCollisionWithEnvironment(deltaTime, radius); } - if (_collisionFlags & COLLISION_GROUP_VOXELS) { + if (_collisionGroups & COLLISION_GROUP_VOXELS) { updateCollisionWithVoxels(deltaTime, radius); } - if (_collisionFlags & COLLISION_GROUP_AVATARS) { + if (_collisionGroups & COLLISION_GROUP_AVATARS) { updateCollisionWithAvatars(deltaTime); } } @@ -408,17 +408,13 @@ void MyAvatar::renderDebugBodyPoints() { glTranslatef(position.x, position.y, position.z); glutSolidSphere(0.15, 10, 10); glPopMatrix(); - - } // virtual void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) { - // don't render if we've been asked to disable local rendering - if (!_shouldRender) { - return; // exit early + if (_shouldRender) { + Avatar::render(cameraPosition, renderMode); } - Avatar::render(cameraPosition, renderMode); } void MyAvatar::renderHeadMouse() const { From 1844eb2c9e7302ba8835fd2ae091617894ab6f7a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 24 Apr 2014 11:12:01 -0700 Subject: [PATCH 38/56] Pre CR tweaks --- libraries/voxels/src/VoxelTreeCommands.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libraries/voxels/src/VoxelTreeCommands.cpp b/libraries/voxels/src/VoxelTreeCommands.cpp index d1dc0f3560..a35096b5c7 100644 --- a/libraries/voxels/src/VoxelTreeCommands.cpp +++ b/libraries/voxels/src/VoxelTreeCommands.cpp @@ -21,7 +21,7 @@ struct SendVoxelsOperationArgs { }; bool sendVoxelsOperation(OctreeElement* element, void* extraData) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; + VoxelTreeElement* voxel = static_cast(element); SendVoxelsOperationArgs* args = (SendVoxelsOperationArgs*)extraData; if (voxel->isColored()) { const unsigned char* nodeOctalCode = voxel->getOctalCode(); @@ -117,19 +117,20 @@ DeleteVoxelCommand::~DeleteVoxelCommand() { } void DeleteVoxelCommand::redo() { - if (_voxel.s == 0) { + if (_voxel.s == 0.0f) { return; } if (_tree) { - _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); } + _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + } if (_packetSender) { _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); } } void DeleteVoxelCommand::undo() { - if (_voxel.s == 0) { + if (_voxel.s == 0.0f) { return; } @@ -157,4 +158,4 @@ void DeleteVoxelCommand::undo() { _packetSender->queueVoxelEditMessages(PacketTypeVoxelSet, 1, &_voxel); } } -} \ No newline at end of file +} From 73d0674565038eb80c2782ab01db9a2937cd8d0a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 24 Apr 2014 11:19:08 -0700 Subject: [PATCH 39/56] expose MyAvatar.collisionGroups to JS --- interface/src/avatar/Avatar.h | 6 +++++- libraries/shared/src/CollisionInfo.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 6106b9f39c..a1ff817b02 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -63,6 +63,7 @@ class Texture; class Avatar : public AvatarData { Q_OBJECT + Q_PROPERTY(quint32 collisionGroups READ getCollisionGroups WRITE setCollisionGroups) public: Avatar(); @@ -148,6 +149,9 @@ public: virtual float getBoundingRadius() const; void updateShapePositions(); + quint32 getCollisionGroups() const { return _collisionGroups; } + void setCollisionGroups(quint32 collisionGroups) { _collisionGroups = (collisionGroups & VALID_COLLISION_GROUPS); } + public slots: void updateCollisionGroups(); @@ -166,7 +170,7 @@ protected: float _stringLength; bool _moving; ///< set when position is changing - uint32_t _collisionGroups; + quint32 _collisionGroups; // protected methods... glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h index 7db965fe64..510728daa6 100644 --- a/libraries/shared/src/CollisionInfo.h +++ b/libraries/shared/src/CollisionInfo.h @@ -27,6 +27,7 @@ const quint32 COLLISION_GROUP_ENVIRONMENT = 1U << 0; const quint32 COLLISION_GROUP_AVATARS = 1U << 1; const quint32 COLLISION_GROUP_VOXELS = 1U << 2; const quint32 COLLISION_GROUP_PARTICLES = 1U << 3; +const quint32 VALID_COLLISION_GROUPS = 0x0f; // CollisionInfo contains details about the collision between two things: BodyA and BodyB. // The assumption is that the context that analyzes the collision knows about BodyA but From ad0f0118bcb879f7f2534ef597d9d306b0b9b6f4 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Thu, 24 Apr 2014 15:01:37 -0600 Subject: [PATCH 40/56] fixes for new versioning: --- interface/src/Application.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4adb2f772a..4d9c70aeda 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3520,10 +3520,9 @@ void Application::parseVersionXml() { QString operatingSystem("ubuntu"); #endif - QString releaseDate; - QString releaseNotes; QString latestVersion; QUrl downloadUrl; + QString releaseNotes("Unavailable"); QObject* sender = QObject::sender(); QXmlStreamReader xml(qobject_cast(sender)); @@ -3531,21 +3530,15 @@ void Application::parseVersionXml() { QXmlStreamReader::TokenType token = xml.readNext(); if (token == QXmlStreamReader::StartElement) { - if (xml.name() == "ReleaseDate") { - xml.readNext(); - releaseDate = xml.text().toString(); - } - if (xml.name() == "ReleaseNotes") { - xml.readNext(); - releaseNotes = xml.text().toString(); - } - if (xml.name() == "Version") { - xml.readNext(); - latestVersion = xml.text().toString(); - } + xml.readNext(); if (xml.name() == operatingSystem) { xml.readNext(); - downloadUrl = QUrl(xml.text().toString()); + if (xml.name() == "version") { + latestVersion = xml.text().toString(); + } + if (xml.name() == "url") { + downloadUrl = xml.text().toString(); + } } } } From 27002a94069b5ec13fecd49c12aada8c83ce7318 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Thu, 24 Apr 2014 15:10:37 -0600 Subject: [PATCH 41/56] Casting to QUrl --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4d9c70aeda..20cab975a4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3537,7 +3537,7 @@ void Application::parseVersionXml() { latestVersion = xml.text().toString(); } if (xml.name() == "url") { - downloadUrl = xml.text().toString(); + downloadUrl = QUrl(xml.text().toString()); } } } From 0a7a5031ee05b6ca657cc82109e0abd5f9c11c78 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 24 Apr 2014 14:17:10 -0700 Subject: [PATCH 42/56] expose COLLISION_GOUP_* constants to JS --- libraries/script-engine/src/ScriptEngine.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 2e92567fe7..b923427307 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -230,8 +231,13 @@ void ScriptEngine::init() { registerGlobalObject("Voxels", &_voxelsScriptingInterface); - QScriptValue treeScaleValue = _engine.newVariant(QVariant(TREE_SCALE)); - _engine.globalObject().setProperty("TREE_SCALE", treeScaleValue); + // constants + QScriptValue globalObject = _engine.globalObject(); + globalObject.setProperty("TREE_SCALE", _engine.newVariant(QVariant(TREE_SCALE))); + globalObject.setProperty("COLLISION_GROUP_ENVIRONMENT", _engine.newVariant(QVariant(COLLISION_GROUP_ENVIRONMENT))); + globalObject.setProperty("COLLISION_GROUP_AVATARS", _engine.newVariant(QVariant(COLLISION_GROUP_AVATARS))); + globalObject.setProperty("COLLISION_GROUP_VOXELS", _engine.newVariant(QVariant(COLLISION_GROUP_VOXELS))); + globalObject.setProperty("COLLISION_GROUP_PARTICLES", _engine.newVariant(QVariant(COLLISION_GROUP_PARTICLES))); // let the VoxelPacketSender know how frequently we plan to call it _voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(SCRIPT_DATA_CALLBACK_USECS); @@ -561,4 +567,4 @@ void ScriptEngine::include(const QString& includeFile) { qDebug() << "Uncaught exception at (" << includeFile << ") line" << line << ":" << result.toString(); emit errorMessage("Uncaught exception at (" + includeFile + ") line" + QString::number(line) + ":" + result.toString()); } -} \ No newline at end of file +} From ccad0aed9e68e993360cbadfb404c6f20bf01001 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 24 Apr 2014 14:54:01 -0700 Subject: [PATCH 43/56] Move ChatInputArea code in header to .cpp --- interface/src/ui/ChatInputArea.cpp | 19 +++++++++++++++++++ interface/src/ui/ChatInputArea.h | 7 +++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 interface/src/ui/ChatInputArea.cpp diff --git a/interface/src/ui/ChatInputArea.cpp b/interface/src/ui/ChatInputArea.cpp new file mode 100644 index 0000000000..3e8fc84fe2 --- /dev/null +++ b/interface/src/ui/ChatInputArea.cpp @@ -0,0 +1,19 @@ +// +// ChatInputArea.cpp +// interface/src/ui +// +// Created by Ryan Huffman on 4/24/14. +// Copyright 2014 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 "ChatInputArea.h" + +ChatInputArea::ChatInputArea(QWidget* parent) : QTextEdit(parent) { +}; + +void ChatInputArea::insertFromMimeData(const QMimeData* source) { + insertPlainText(source->text()); +}; diff --git a/interface/src/ui/ChatInputArea.h b/interface/src/ui/ChatInputArea.h index 264a9932c6..31d1584df7 100644 --- a/interface/src/ui/ChatInputArea.h +++ b/interface/src/ui/ChatInputArea.h @@ -13,16 +13,15 @@ #define hifi_ChatInputArea_h #include +#include class ChatInputArea : public QTextEdit { Q_OBJECT public: - ChatInputArea(QWidget* parent) : QTextEdit(parent) { }; + ChatInputArea(QWidget* parent); protected: - void insertFromMimeData(const QMimeData* source) { - insertPlainText(source->text()); - }; + void insertFromMimeData(const QMimeData* source); }; #endif // hifi_ChatInputArea_h From 7b0981202848064059ccbcf691d077612a625aa8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 24 Apr 2014 14:54:26 -0700 Subject: [PATCH 44/56] Remove insertFromMimeData override in ChatMessageArea --- interface/src/ui/ChatMessageArea.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/interface/src/ui/ChatMessageArea.h b/interface/src/ui/ChatMessageArea.h index b726a31d76..57199538fd 100644 --- a/interface/src/ui/ChatMessageArea.h +++ b/interface/src/ui/ChatMessageArea.h @@ -32,11 +32,6 @@ signals: protected: virtual void wheelEvent(QWheelEvent* event); bool _useFixedHeight; - - void insertFromMimeData(const QMimeData* source) { - insertPlainText(source->text()); - }; - }; #endif // hifi_ChatMessageArea_h From b69fa73dfae82a38ab52327f9a763698e84b0df8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 24 Apr 2014 14:54:57 -0700 Subject: [PATCH 45/56] Unsplit a line in FramelessDialog --- interface/src/ui/FramelessDialog.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/ui/FramelessDialog.h b/interface/src/ui/FramelessDialog.h index 22666cca63..828602a5db 100644 --- a/interface/src/ui/FramelessDialog.h +++ b/interface/src/ui/FramelessDialog.h @@ -21,8 +21,7 @@ class FramelessDialog : public QDialog { public: enum Position { POSITION_LEFT, POSITION_RIGHT }; - FramelessDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0, - Position position = POSITION_LEFT); + FramelessDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0, Position position = POSITION_LEFT); void setStyleSheetFile(const QString& fileName); protected: From f4c98a8fa4597832a1419107de1487d0e1edf14e Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Thu, 24 Apr 2014 16:21:49 -0600 Subject: [PATCH 46/56] Fixing xml parsing --- interface/src/Application.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 20cab975a4..8fdd41ca47 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3526,22 +3526,24 @@ void Application::parseVersionXml() { QObject* sender = QObject::sender(); QXmlStreamReader xml(qobject_cast(sender)); - while (!xml.atEnd() && !xml.hasError()) { - QXmlStreamReader::TokenType token = xml.readNext(); - - if (token == QXmlStreamReader::StartElement) { - xml.readNext(); - if (xml.name() == operatingSystem) { - xml.readNext(); - if (xml.name() == "version") { + + while(!xml.atEnd() && !xml.hasError()) { + if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == operatingSystem) { + while(!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == operatingSystem)) { + if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "version") { + xml.readNext(); latestVersion = xml.text().toString(); } - if (xml.name() == "url") { + if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "url") { + xml.readNext(); downloadUrl = QUrl(xml.text().toString()); } + xml.readNext(); } } + xml.readNext(); } + if (!shouldSkipVersion(latestVersion) && applicationVersion() != latestVersion) { new UpdateDialog(_glWidget, releaseNotes, latestVersion, downloadUrl); } From a21991c5c24e36cfcd5089f7247020a43902444d Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Thu, 24 Apr 2014 16:22:34 -0600 Subject: [PATCH 47/56] Fixing xml parsing --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8fdd41ca47..ab505ede93 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3527,9 +3527,9 @@ void Application::parseVersionXml() { QXmlStreamReader xml(qobject_cast(sender)); - while(!xml.atEnd() && !xml.hasError()) { + while (!xml.atEnd() && !xml.hasError()) { if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == operatingSystem) { - while(!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == operatingSystem)) { + while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == operatingSystem)) { if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "version") { xml.readNext(); latestVersion = xml.text().toString(); From 0b5c1b0a9a0d82fbd4fa2e0d685c15ad1bf24de8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 24 Apr 2014 15:43:03 -0700 Subject: [PATCH 48/56] add MyAvatar::_motionBehaviors (for obeyGravity) Also reconcile Menu checkable set vs script-set collision groups. --- interface/src/Application.cpp | 2 +- interface/src/Menu.cpp | 6 +++--- interface/src/Menu.h | 2 +- interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/MyAvatar.cpp | 26 ++++++++++++++++++++++++-- interface/src/avatar/MyAvatar.h | 11 +++++++++++ 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3ae4720351..e9c208bace 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -861,7 +861,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_G: if (isShifted) { - Menu::getInstance()->triggerOption(MenuOption::Gravity); + Menu::getInstance()->triggerOption(MenuOption::ObeyGravity); } break; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 74df3e4f63..4aeb4dd203 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -186,9 +186,9 @@ Menu::Menu() : QAction::PreferencesRole); addDisabledActionAndSeparator(editMenu, "Physics"); - addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::Gravity, Qt::SHIFT | Qt::Key_G, false); - - + QObject* avatar = appInstance->getAvatar(); + addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::ObeyGravity, Qt::SHIFT | Qt::Key_G, true, + avatar, SLOT(updateMotionBehaviorFlags())); addAvatarCollisionSubMenu(editMenu); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index a1e6cded2a..8b2368d22f 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -313,7 +313,7 @@ namespace MenuOption { const QString GoTo = "Go To..."; const QString GoToDomain = "Go To Domain..."; const QString GoToLocation = "Go To Location..."; - const QString Gravity = "Use Gravity"; + const QString ObeyGravity = "Obey Gravity"; const QString HandsCollideWithSelf = "Collide With Self"; const QString HeadMouse = "Head Mouse"; const QString IncreaseAvatarSize = "Increase Avatar Size"; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index a1ff817b02..bcf3487e09 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -150,7 +150,7 @@ public: void updateShapePositions(); quint32 getCollisionGroups() const { return _collisionGroups; } - void setCollisionGroups(quint32 collisionGroups) { _collisionGroups = (collisionGroups & VALID_COLLISION_GROUPS); } + virtual void setCollisionGroups(quint32 collisionGroups) { _collisionGroups = (collisionGroups & VALID_COLLISION_GROUPS); } public slots: void updateCollisionGroups(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9f70f41631..467b1f2613 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -59,6 +59,7 @@ MyAvatar::MyAvatar() : _thrust(0.0f), _isThrustOn(false), _thrustMultiplier(1.0f), + _motionBehaviors(0), _lastBodyPenetration(0.0f), _lookAtTargetAvatar(), _shouldRender(true), @@ -123,7 +124,7 @@ void MyAvatar::update(float deltaTime) { head->setAudioLoudness(audio->getLastInputLoudness()); head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness()); - if (Menu::getInstance()->isOptionChecked(MenuOption::Gravity)) { + if (_motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY) { setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition())); } else { setGravity(glm::vec3(0.0f, 0.0f, 0.0f)); @@ -1134,7 +1135,28 @@ void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { setPosition(newPosition); emit transformChanged(); } - +} + +void MyAvatar::updateMotionBehaviors() { + _motionBehaviors = 0; + if (Menu::getInstance()->isOptionChecked(MenuOption::ObeyGravity)) { + _motionBehaviors |= AVATAR_MOTION_OBEY_GRAVITY; + } +} + +void MyAvatar::setCollisionGroups(quint32 collisionGroups) { + Avatar::setCollisionGroups(collisionGroups & VALID_COLLISION_GROUPS); + Menu* menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::CollideWithEnvironment, (bool)(_collisionGroups & COLLISION_GROUP_ENVIRONMENT)); + menu->setIsOptionChecked(MenuOption::CollideWithAvatars, (bool)(_collisionGroups & COLLISION_GROUP_AVATARS)); + menu->setIsOptionChecked(MenuOption::CollideWithVoxels, (bool)(_collisionGroups & COLLISION_GROUP_VOXELS)); + menu->setIsOptionChecked(MenuOption::CollideWithParticles, (bool)(_collisionGroups & COLLISION_GROUP_PARTICLES)); +} + +void MyAvatar::setMotionBehaviors(quint32 flags) { + _motionBehaviors = flags; + Menu* menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::ObeyGravity, (bool)(_motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY)); } void MyAvatar::applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index b713f1c223..9b6b13568f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -25,9 +25,12 @@ enum AvatarHandState NUM_HAND_STATES }; +const quint32 AVATAR_MOTION_OBEY_GRAVITY = 1U << 0; + class MyAvatar : public Avatar { Q_OBJECT Q_PROPERTY(bool shouldRenderLocally READ getShouldRenderLocally WRITE setShouldRenderLocally) + Q_PROPERTY(quint32 motionBehaviors READ getMotionBehaviors WRITE setMotionBehaviors) public: MyAvatar(); @@ -88,6 +91,10 @@ public: virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); + virtual void setCollisionGroups(quint32 collisionGroups); + void setMotionBehaviors(quint32 flags); + quint32 getMotionBehaviors() const { return _motionBehaviors; } + void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration); public slots: @@ -104,6 +111,8 @@ public slots: glm::vec3 getThrust() { return _thrust; }; void setThrust(glm::vec3 newThrust) { _thrust = newThrust; } + void updateMotionBehaviors(); + signals: void transformChanged(); @@ -123,6 +132,8 @@ private: bool _isThrustOn; float _thrustMultiplier; + quint32 _motionBehaviors; + glm::vec3 _lastBodyPenetration; QWeakPointer _lookAtTargetAvatar; glm::vec3 _targetAvatarPosition; From d88897ccc707be1e2624c951ae41adcc2d48bd4e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 24 Apr 2014 15:55:34 -0700 Subject: [PATCH 49/56] Add error box when going to user/location that doesn't exist --- interface/src/Application.h | 1 + interface/src/avatar/MyAvatar.cpp | 3 +++ interface/src/location/LocationManager.cpp | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/interface/src/Application.h b/interface/src/Application.h index fb48acb721..6bb2bf4c81 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -16,6 +16,7 @@ #include #include +#include #include #include #include diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 317f408aa7..b8a45aacd5 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -1178,6 +1179,8 @@ void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { coordinateItems[2].toFloat()) - newOrientation * IDENTITY_FRONT * DISTANCE_TO_USER; setPosition(newPosition); emit transformChanged(); + } else { + QMessageBox::warning(Application::getInstance()->getWindow(), "", "That user or location could not be found."); } } diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 8009551b6c..f80c331df4 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "Application.h" #include "LocationManager.h" @@ -118,6 +120,8 @@ void LocationManager::checkForMultipleDestinations() { Application::getInstance()->getAvatar()->goToLocationFromResponse(_placeData); return; } + + QMessageBox::warning(Application::getInstance()->getWindow(), "", "That user or location could not be found."); } } From 01637e80377b43f84ce08d5faf714d7715fe0ba0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 24 Apr 2014 17:37:48 -0700 Subject: [PATCH 50/56] Fix error introduced with gettimeofday removing + spelling mistake --- interface/src/Audio.cpp | 6 +++--- interface/src/Audio.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index c182f6e842..68e38615bf 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -644,10 +644,10 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { const int NUM_INITIAL_PACKETS_DISCARD = 3; const int STANDARD_DEVIATION_SAMPLE_COUNT = 500; - _timeSinceLastRecieved.start(); _totalPacketsReceived++; - double timeDiff = (double)_timeSinceLastRecieved.nsecsElapsed() / 1000000.0; // ns to ms + double timeDiff = (double)_timeSinceLastReceived.nsecsElapsed() / 1000000.0; // ns to ms + _timeSinceLastReceived.start(); // Discard first few received packets for computing jitter (often they pile up on start) if (_totalPacketsReceived > NUM_INITIAL_PACKETS_DISCARD) { @@ -1265,7 +1265,7 @@ bool Audio::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo) // setup a procedural audio output device _proceduralAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); - _timeSinceLastRecieved.start(); + _timeSinceLastReceived.start(); // setup spatial audio ringbuffer int numFrameSamples = _outputFormat.sampleRate() * _desiredOutputFormat.channelCount(); diff --git a/interface/src/Audio.h b/interface/src/Audio.h index e1b8a7dddc..277c606d4b 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -129,7 +129,7 @@ private: QString _outputAudioDeviceName; StDev _stdev; - QElapsedTimer _timeSinceLastRecieved; + QElapsedTimer _timeSinceLastReceived; float _averagedLatency; float _measuredJitter; int16_t _jitterBufferSamples; From cf7fe2306bafa1c2710ba7942c1fff19c4931277 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 24 Apr 2014 18:10:51 -0700 Subject: [PATCH 51/56] Fix audio jitter --- interface/src/ui/PreferencesDialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 550c616fc1..7a70b743bd 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -184,6 +184,7 @@ void PreferencesDialog::savePreferences() { Menu::getInstance()->setMaxVoxelPacketsPerSecond(ui.maxVoxelsPPSSpin->value()); Menu::getInstance()->setAudioJitterBufferSamples(ui.audioJitterSpin->value()); + Application::getInstance()->getAudio()->setJitterBufferSamples(ui.audioJitterSpin->value()); Application::getInstance()->resizeGL(Application::getInstance()->getGLWidget()->width(), Application::getInstance()->getGLWidget()->height()); From afb12bcd70f1a388822ca4d54c4d3dfd5d339e71 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 24 Apr 2014 19:12:23 -0700 Subject: [PATCH 52/56] add swissArmyJetpack.js --- examples/swissArmyJetpack.js | 142 +++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 examples/swissArmyJetpack.js diff --git a/examples/swissArmyJetpack.js b/examples/swissArmyJetpack.js new file mode 100644 index 0000000000..9bb5bea267 --- /dev/null +++ b/examples/swissArmyJetpack.js @@ -0,0 +1,142 @@ +// +// swissArmyJetpack.js +// examples +// +// Created by Andrew Meadows 2014.04.24 +// Copyright 2014 High Fidelity, Inc. +// +// This is a work in progress. It will eventually be able to move the avatar around, +// toggle collision groups, modify avatar movement options, and other stuff (maybe trigger animations). +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var numberOfButtons = 3; + +var enabledColors = new Array(); +enabledColors[0] = { red: 255, green: 0, blue: 0}; +enabledColors[1] = { red: 0, green: 255, blue: 0}; +enabledColors[2] = { red: 0, green: 0, blue: 255}; + +var disabledColors = new Array(); +disabledColors[0] = { red: 90, green: 75, blue: 75}; +disabledColors[1] = { red: 75, green: 90, blue: 75}; +disabledColors[2] = { red: 75, green: 90, blue: 90}; + +var buttons = new Array(); +var labels = new Array(); + +var labelContents = new Array(); +labelContents[0] = "Collide with Avatars"; +labelContents[1] = "Collide with Voxels"; +labelContents[2] = "Collide with Particles"; +var groupBits = 0; + +var buttonStates = new Array(); + +var disabledOffsetT = 0; +var enabledOffsetT = 55; + +var buttonX = 50; +var buttonY = 200; +var buttonWidth = 30; +var buttonHeight = 54; +var textX = buttonX + buttonWidth + 10; + +for (i = 0; i < numberOfButtons; i++) { + var offsetS = 12 + var offsetT = disabledOffsetT; + + buttons[i] = Overlays.addOverlay("image", { + //x: buttonX + (buttonWidth * i), + x: buttonX, + y: buttonY + (buttonHeight * i), + width: buttonWidth, + height: buttonHeight, + subImage: { x: offsetS, y: offsetT, width: buttonWidth, height: buttonHeight }, + imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", + color: disabledColors[i], + alpha: 1, + }); + + labels[i] = Overlays.addOverlay("text", { + x: textX, + y: buttonY + (buttonHeight * i) + 12, + width: 150, + height: 50, + color: { red: 0, green: 0, blue: 0}, + textColor: { red: 255, green: 0, blue: 0}, + topMargin: 4, + leftMargin: 4, + text: labelContents[i] + }); + + buttonStates[i] = false; +} + +function updateButton(i, enabled) { + var offsetY = disabledOffsetT; + var buttonColor = disabledColors[i]; + groupBits + if (enabled) { + offsetY = enabledOffsetT; + buttonColor = enabledColors[i]; + if (i == 0) { + groupBits |= COLLISION_GROUP_AVATARS; + } else if (i == 1) { + groupBits |= COLLISION_GROUP_VOXELS; + } else if (i == 2) { + groupBits |= COLLISION_GROUP_PARTICLES; + } + } else { + if (i == 0) { + groupBits &= ~COLLISION_GROUP_AVATARS; + } else if (i == 1) { + groupBits &= ~COLLISION_GROUP_VOXELS; + } else if (i == 2) { + groupBits &= ~COLLISION_GROUP_PARTICLES; + } + } + MyAvatar.collisionGroups = groupBits; + + Overlays.editOverlay(buttons[i], { subImage: { y: offsetY } } ); + Overlays.editOverlay(buttons[i], { color: buttonColor } ); + buttonStates[i] = enabled; +} + +// When our script shuts down, we should clean up all of our overlays +function scriptEnding() { + for (i = 0; i < numberOfButtons; i++) { + print("adebug deleting overlay " + i); + Overlays.deleteOverlay(buttons[i]); + Overlays.deleteOverlay(labels[i]); + } +} +Script.scriptEnding.connect(scriptEnding); + + +// Our update() function is called at approximately 60fps, and we will use it to animate our various overlays +function update(deltaTime) { + if (groupBits != MyAvatar.collisionGroups) { + groupBits = MyAvatar.collisionGroups; + updateButton(0, groupBits & COLLISION_GROUP_AVATARS); + updateButton(1, groupBits & COLLISION_GROUP_VOXELS); + updateButton(2, groupBits & COLLISION_GROUP_PARTICLES); + } +} +Script.update.connect(update); + + +// we also handle click detection in our mousePressEvent() +function mousePressEvent(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + for (i = 0; i < numberOfButtons; i++) { + if (clickedOverlay == buttons[i]) { + var enabled = !(buttonStates[i]); + updateButton(i, enabled); + } + } +} +Controller.mousePressEvent.connect(mousePressEvent); + From 6acdf9cd6cd98c728a89e249f9bc3743c6845412 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 25 Apr 2014 11:21:02 -0700 Subject: [PATCH 53/56] fix issues with bad timestamps --- libraries/octree/src/OctreeSceneStats.cpp | 39 +++++++++++++++++++---- libraries/shared/src/SharedUtil.cpp | 4 ++- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index ad8702adc2..e7d34680a7 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -820,11 +820,7 @@ const char* OctreeSceneStats::getItemValue(Item item) { void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec) { - _incomingPacket++; - _incomingBytes += packet.size(); - if (!wasStatsPacket) { - _incomingWastedBytes += (MAX_PACKET_SIZE - packet.size()); - } + const bool wantExtraDebugging = false; int numBytesPacketHeader = numBytesForPacketHeader(packet); const unsigned char* dataAt = reinterpret_cast(packet.data()) + numBytesPacketHeader; @@ -842,12 +838,43 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); int flightTime = arrivedAt - sentAt + nodeClockSkewUsec; + + if (wantExtraDebugging) { + qDebug() << "sentAt:" << sentAt << " usecs"; + qDebug() << "arrivedAt:" << arrivedAt << " usecs"; + qDebug() << "nodeClockSkewUsec:" << nodeClockSkewUsec << " usecs"; + qDebug() << "flightTime:" << flightTime << " usecs"; + } + + // Guard against possible corrupted packets... with bad timestamps + const int MAX_RESONABLE_FLIGHT_TIME = 200 * USECS_PER_SECOND; // 200 seconds is more than enough time for a packet to arrive + const int MIN_RESONABLE_FLIGHT_TIME = 0; + if (flightTime > MAX_RESONABLE_FLIGHT_TIME || flightTime < MIN_RESONABLE_FLIGHT_TIME) { + qDebug() << "ignoring unreasonable packet... flightTime:" << flightTime; + return; // ignore any packets that are unreasonable + } + + // Guard against possible corrupted packets... with bad sequence numbers + const int MAX_RESONABLE_SEQUENCE_OFFSET = 2000; + const int MIN_RESONABLE_SEQUENCE_OFFSET = -2000; + int sequenceOffset = (sequence - _incomingLastSequence); + if (sequenceOffset > MAX_RESONABLE_SEQUENCE_OFFSET || sequenceOffset < MIN_RESONABLE_SEQUENCE_OFFSET) { + qDebug() << "ignoring unreasonable packet... sequence:" << sequence << "_incomingLastSequence:" << _incomingLastSequence; + return; // ignore any packets that are unreasonable + } + + // track packets here... + _incomingPacket++; + _incomingBytes += packet.size(); + if (!wasStatsPacket) { + _incomingWastedBytes += (MAX_PACKET_SIZE - packet.size()); + } + const int USECS_PER_MSEC = 1000; float flightTimeMsecs = flightTime / USECS_PER_MSEC; _incomingFlightTimeAverage.updateAverage(flightTimeMsecs); // track out of order and possibly lost packets... - const bool wantExtraDebugging = false; if (sequence == _incomingLastSequence) { if (wantExtraDebugging) { qDebug() << "last packet duplicate got:" << sequence << "_incomingLastSequence:" << _incomingLastSequence; diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index bbb73cae4c..0a9f8df3f7 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -40,10 +40,12 @@ void initialiseUsecTimestampNow() { if (initialised) { qDebug() << "[WARNING] Double initialisation of usecTimestampNow()."; return; - } + } TIME_REFERENCE = QDateTime::currentMSecsSinceEpoch() * 1000; // ms to usec + timestampTimer.start(); initialised = true; + qDebug() << "[INFO] usecTimestampNow() initialized."; } void usecTimestampNowForceClockSkew(int clockSkew) { From 8b4a91004020c8fa2ff0bb38a89ff0f884b2fda2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 25 Apr 2014 12:19:18 -0700 Subject: [PATCH 54/56] Fix timestamp timer not fired --- assignment-client/src/main.cpp | 2 -- domain-server/src/main.cpp | 2 -- interface/src/main.cpp | 1 - libraries/shared/src/SharedUtil.cpp | 25 ++++++++++--------------- libraries/shared/src/SharedUtil.h | 1 - 5 files changed, 10 insertions(+), 21 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 7132b5c38a..5e103cf767 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -17,8 +17,6 @@ #include "AssignmentClientMonitor.h" int main(int argc, char* argv[]) { - initialiseUsecTimestampNow(); - #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); #endif diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 871c16a215..1d9e837f0a 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -23,8 +23,6 @@ #include "DomainServer.h" int main(int argc, char* argv[]) { - initialiseUsecTimestampNow(); - #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); #endif diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 6f9dc5e3bd..2bb0633f24 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -16,7 +16,6 @@ #include int main(int argc, const char * argv[]) { - initialiseUsecTimestampNow(); QElapsedTimer startupTime; startupTime.start(); diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index bbb73cae4c..c65b7505ee 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -30,27 +30,22 @@ #include "OctalCode.h" #include "SharedUtil.h" - -static qint64 TIME_REFERENCE = 0; // in usec -static QElapsedTimer timestampTimer; static int usecTimestampNowAdjust = 0; // in usec - -void initialiseUsecTimestampNow() { - static bool initialised = false; - if (initialised) { - qDebug() << "[WARNING] Double initialisation of usecTimestampNow()."; - return; - } - - TIME_REFERENCE = QDateTime::currentMSecsSinceEpoch() * 1000; // ms to usec - initialised = true; -} - void usecTimestampNowForceClockSkew(int clockSkew) { ::usecTimestampNowAdjust = clockSkew; } quint64 usecTimestampNow() { + static bool usecTimestampNowIsInitialized = false; + static qint64 TIME_REFERENCE = 0; // in usec + static QElapsedTimer timestampTimer; + + if (!usecTimestampNowIsInitialized) { + TIME_REFERENCE = QDateTime::currentMSecsSinceEpoch() * 1000; // ms to usec + timestampTimer.start(); + usecTimestampNowIsInitialized = true; + } + // usec nsec to usec usec return TIME_REFERENCE + timestampTimer.nsecsElapsed() / 1000 + ::usecTimestampNowAdjust; } diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 54d599070d..4a3fe2a129 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -60,7 +60,6 @@ static const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND; const int BITS_IN_BYTE = 8; -void initialiseUsecTimestampNow(); quint64 usecTimestampNow(); void usecTimestampNowForceClockSkew(int clockSkew); From 8e12c0d8e5ca45bd32f24a3392f6521ab5dbb8c4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 25 Apr 2014 13:22:18 -0700 Subject: [PATCH 55/56] pass the owner scope to auth requests --- libraries/networking/src/AccountManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index d1e4edf2ea..278923026d 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -282,10 +282,13 @@ void AccountManager::requestAccessToken(const QString& login, const QString& pas QUrl grantURL = _authURL; grantURL.setPath("/oauth/token"); + const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner"; + QByteArray postData; postData.append("grant_type=password&"); postData.append("username=" + login + "&"); - postData.append("password=" + password); + postData.append("password=" + password + "&"); + postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE); request.setUrl(grantURL); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); From 3143e10bd85029d0adc0136b7251c5fcb8fe09b6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 25 Apr 2014 13:33:59 -0700 Subject: [PATCH 56/56] CR --- libraries/octree/src/Octree.cpp | 13 +++++++++++++ libraries/octree/src/Octree.h | 8 ++++++++ libraries/voxels/src/VoxelTree.cpp | 5 +---- libraries/voxels/src/VoxelTree.h | 7 +++++++ libraries/voxels/src/VoxelTreeCommands.cpp | 2 +- 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index ebfb954bd8..5e812c06c3 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -542,6 +542,19 @@ OctreeElement* Octree::getOctreeElementAt(float x, float y, float z, float s) co return node; } +OctreeElement* Octree::getOctreeEnclosingElementAt(float x, float y, float z, float s) const { + unsigned char* octalCode = pointToOctalCode(x,y,z,s); + OctreeElement* node = nodeForOctalCode(_rootNode, octalCode, NULL); + + delete[] octalCode; // cleanup memory +#ifdef HAS_AUDIT_CHILDREN + if (node) { + node->auditChildren("Octree::getOctreeElementAt()"); + } +#endif // def HAS_AUDIT_CHILDREN + return node; +} + OctreeElement* Octree::getOrCreateChildElementAt(float x, float y, float z, float s) { return getRoot()->getOrCreateChildElementAt(x, y, z, s); diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 0b9f1657ee..a11e73ab04 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -210,7 +210,15 @@ public: void reaverageOctreeElements(OctreeElement* startNode = NULL); void deleteOctreeElementAt(float x, float y, float z, float s); + + /// Find the voxel at position x,y,z,s + /// \return pointer to the OctreeElement or NULL if none at x,y,z,s. OctreeElement* getOctreeElementAt(float x, float y, float z, float s) const; + + /// Find the voxel at position x,y,z,s + /// \return pointer to the OctreeElement or to the smallest enclosing parent if none at x,y,z,s. + OctreeElement* getOctreeEnclosingElementAt(float x, float y, float z, float s) const; + OctreeElement* getOrCreateChildElementAt(float x, float y, float z, float s); void recurseTreeWithOperation(RecurseOctreeOperation operation, void* extraData = NULL); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index aeb877ef78..b1ddf2e5b0 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -46,10 +46,7 @@ VoxelTreeElement* VoxelTree::getVoxelAt(float x, float y, float z, float s) cons } VoxelTreeElement* VoxelTree::getEnclosingVoxelAt(float x, float y, float z, float s) const { - unsigned char* octalCode = pointToOctalCode(x,y,z,s); - OctreeElement* node = nodeForOctalCode(_rootNode, octalCode, NULL); - - return static_cast(node); + return static_cast(getOctreeEnclosingElementAt(x, y, z, s)); } void VoxelTree::createVoxel(float x, float y, float z, float s, diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 2992815787..eb24c182b2 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -29,8 +29,15 @@ public: VoxelTreeElement* getRoot() { return (VoxelTreeElement*)_rootNode; } void deleteVoxelAt(float x, float y, float z, float s); + + /// Find the voxel at position x,y,z,s + /// \return pointer to the VoxelTreeElement or NULL if none at x,y,z,s. VoxelTreeElement* getVoxelAt(float x, float y, float z, float s) const; + + /// Find the voxel at position x,y,z,s + /// \return pointer to the VoxelTreeElement or to the smallest enclosing parent if none at x,y,z,s. VoxelTreeElement* getEnclosingVoxelAt(float x, float y, float z, float s) const; + void createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue, bool destructive = false); diff --git a/libraries/voxels/src/VoxelTreeCommands.cpp b/libraries/voxels/src/VoxelTreeCommands.cpp index a35096b5c7..39e08d3bc2 100644 --- a/libraries/voxels/src/VoxelTreeCommands.cpp +++ b/libraries/voxels/src/VoxelTreeCommands.cpp @@ -22,7 +22,7 @@ struct SendVoxelsOperationArgs { bool sendVoxelsOperation(OctreeElement* element, void* extraData) { VoxelTreeElement* voxel = static_cast(element); - SendVoxelsOperationArgs* args = (SendVoxelsOperationArgs*)extraData; + SendVoxelsOperationArgs* args = static_cast(extraData); if (voxel->isColored()) { const unsigned char* nodeOctalCode = voxel->getOctalCode(); unsigned char* codeColorBuffer = NULL;