From 8e3e7c1537fcde32970069e3b7898783e8e19f33 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 11 Feb 2014 17:18:24 -0800 Subject: [PATCH 01/14] first experimental cut at overlay image --- interface/src/Application.cpp | 6 +++ interface/src/Application.h | 4 ++ interface/src/ui/ImageOverlay.cpp | 69 +++++++++++++++++++++++++++++ interface/src/ui/ImageOverlay.h | 73 +++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 interface/src/ui/ImageOverlay.cpp create mode 100644 interface/src/ui/ImageOverlay.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 004b71074b..aca67ffe5a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1870,6 +1870,9 @@ void Application::init() { _audio.init(_glWidget); + _testOverlayA.init(_glWidget, QString("./resources/images/hifi-interface-tools.svg"), QRect(100,100,62,40), QRect(0,0,62,40)); + _testOverlayB.init(_glWidget, QString("./resources/images/hifi-interface-tools.svg"), QRect(170,100,62,40), QRect(0,80,62,40)); + _rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect, _settings); connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); @@ -2997,6 +3000,9 @@ void Application::displayOverlay() { _pieMenu.render(); } + _testOverlayA.render(); // + _testOverlayB.render(); // + glPopMatrix(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index ff6e08758b..4cecc1f7d6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -71,6 +71,7 @@ #include "FileLogger.h" #include "ParticleTreeRenderer.h" #include "ControllerScriptingInterface.h" +#include "ui/ImageOverlay.h" class QAction; @@ -490,6 +491,9 @@ private: void takeSnapshot(); TouchEvent _lastTouchEvent; + + ImageOverlay _testOverlayA; + ImageOverlay _testOverlayB; }; #endif /* defined(__interface__Application__) */ diff --git a/interface/src/ui/ImageOverlay.cpp b/interface/src/ui/ImageOverlay.cpp new file mode 100644 index 0000000000..33c139089d --- /dev/null +++ b/interface/src/ui/ImageOverlay.cpp @@ -0,0 +1,69 @@ +#include "ImageOverlay.h" + +#include +#include +#include +#include + +ImageOverlay::ImageOverlay() : + _parent(NULL), + _textureID(0) +{ +} + +void ImageOverlay::init(QGLWidget* parent, const QString& filename, const QRect& drawAt, const QRect& fromImage) { + _parent = parent; + qDebug() << "ImageOverlay::init()... filename=" << filename; + _bounds = drawAt; + _fromImage = fromImage; + _textureImage = QImage(filename); + _textureID = _parent->bindTexture(_textureImage); +} + + +ImageOverlay::~ImageOverlay() { + if (_parent && _textureID) { + // do we need to call this? + //_parent->deleteTexture(_textureID); + } +} + + +void ImageOverlay::render() { +qDebug() << "ImageOverlay::render _textureID=" << _textureID << "_bounds=" << _bounds; + + + bool renderImage = false; + if (renderImage) { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, _textureID); + } + glColor4f(1.0f, 0.0f, 0.0f, 0.7f); // ??? + + float imageWidth = _textureImage.width(); + float imageHeight = _textureImage.height(); + float x = _fromImage.x() / imageWidth; + float y = _fromImage.y() / imageHeight; + float w = _fromImage.width() / imageWidth; // ?? is this what we want? not sure + float h = _fromImage.height() / imageHeight; + + qDebug() << "ImageOverlay::render x=" << x << "y=" << y << "w="< Date: Fri, 14 Feb 2014 15:37:47 -0800 Subject: [PATCH 02/14] first working version of scriptable Overlays --- examples/overlaysExample.js | 35 +++++ interface/src/Application.cpp | 13 +- interface/src/Application.h | 5 +- interface/src/ui/ImageOverlay.cpp | 136 +++++++++++++++--- interface/src/ui/ImageOverlay.h | 38 +++-- interface/src/ui/Overlays.cpp | 66 +++++++++ interface/src/ui/Overlays.h | 58 ++++++++ .../octree/src/OctreeScriptingInterface.cpp | 1 - 8 files changed, 314 insertions(+), 38 deletions(-) create mode 100644 examples/overlaysExample.js create mode 100644 interface/src/ui/Overlays.cpp create mode 100644 interface/src/ui/Overlays.h diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js new file mode 100644 index 0000000000..d297e2525d --- /dev/null +++ b/examples/overlaysExample.js @@ -0,0 +1,35 @@ +// +// overlaysExample.js +// hifi +// +// Created by Brad Hefta-Gaub on 2/14/14. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// +// This is an example script that demonstrates use of the Overlays class +// +// + + /* + _testOverlayA.init(_glWidget, QString("https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg"), + QRect(100,100,62,40), QRect(0,0,62,40)); + xColor red = { 255, 0, 0 }; + _testOverlayA.setBackgroundColor(red); + _testOverlayB.init(_glWidget, QString("https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg"), + QRect(170,100,62,40), QRect(0,80,62,40)); + */ + +var toolA = Overlays.addOverlay({ + x: 100, + y: 100, + width: 62, + height: 40, + subImage: { x: 0, y: 0, width: 62, height: 40 }, + imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg", + backgroundColor: { red: 255, green: 0, blue: 255}, + alpha: 1.0 + }); + +function scriptEnding() { + Overlays.deleteOverlay(toolA); +} +Script.scriptEnding.connect(scriptEnding); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e95f8b5f7f..4da0a35279 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -289,6 +289,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _sixenseManager.setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense)); checkVersion(); + + _overlays.init(_glWidget); // do this before scripts load + // do this as late as possible so that all required subsystems are inialized loadScripts(); @@ -1870,14 +1873,13 @@ void Application::init() { _audio.init(_glWidget); - _testOverlayA.init(_glWidget, QString("./resources/images/hifi-interface-tools.svg"), QRect(100,100,62,40), QRect(0,0,62,40)); - _testOverlayB.init(_glWidget, QString("./resources/images/hifi-interface-tools.svg"), QRect(170,100,62,40), QRect(0,80,62,40)); - _rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect, _settings); connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors())); + + } void Application::closeMirrorView() { @@ -2986,8 +2988,7 @@ void Application::displayOverlay() { _pieMenu.render(); } - _testOverlayA.render(); // - _testOverlayB.render(); // + _overlays.render(); glPopMatrix(); } @@ -4066,6 +4067,8 @@ void Application::loadScript(const QString& fileNameString) { scriptEngine->registerGlobalObject("Camera", cameraScriptable); connect(scriptEngine, SIGNAL(finished(const QString&)), cameraScriptable, SLOT(deleteLater())); + scriptEngine->registerGlobalObject("Overlays", &_overlays); + QThread* workerThread = new QThread(this); // when the worker thread is started, call our engine's run.. diff --git a/interface/src/Application.h b/interface/src/Application.h index c8541aee29..b2a66d0bf8 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -70,7 +70,7 @@ #include "FileLogger.h" #include "ParticleTreeRenderer.h" #include "ControllerScriptingInterface.h" -#include "ui/ImageOverlay.h" +#include "ui/Overlays.h" class QAction; @@ -490,8 +490,7 @@ private: TouchEvent _lastTouchEvent; - ImageOverlay _testOverlayA; - ImageOverlay _testOverlayB; + Overlays _overlays; }; #endif /* defined(__interface__Application__) */ diff --git a/interface/src/ui/ImageOverlay.cpp b/interface/src/ui/ImageOverlay.cpp index 33c139089d..b85f05f557 100644 --- a/interface/src/ui/ImageOverlay.cpp +++ b/interface/src/ui/ImageOverlay.cpp @@ -1,3 +1,11 @@ +// +// ImageOverlay.cpp +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + + #include "ImageOverlay.h" #include @@ -7,17 +15,24 @@ ImageOverlay::ImageOverlay() : _parent(NULL), - _textureID(0) + _textureID(0), + _alpha(DEFAULT_ALPHA), + _backgroundColor(DEFAULT_BACKGROUND_COLOR), + _renderImage(false), + _textureBound(false) { -} +} -void ImageOverlay::init(QGLWidget* parent, const QString& filename, const QRect& drawAt, const QRect& fromImage) { +void ImageOverlay::init(QGLWidget* parent) { + qDebug() << "ImageOverlay::init() parent=" << parent; _parent = parent; - qDebug() << "ImageOverlay::init()... filename=" << filename; + + /* + qDebug() << "ImageOverlay::init()... url=" << url; _bounds = drawAt; _fromImage = fromImage; - _textureImage = QImage(filename); - _textureID = _parent->bindTexture(_textureImage); + setImageURL(url); + */ } @@ -28,17 +43,43 @@ ImageOverlay::~ImageOverlay() { } } +void ImageOverlay::setImageURL(const QUrl& url) { + // TODO: are we creating too many QNetworkAccessManager() when multiple calls to setImageURL are made? + QNetworkAccessManager* manager = new QNetworkAccessManager(this); + connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*))); + manager->get(QNetworkRequest(url)); +} + +void ImageOverlay::replyFinished(QNetworkReply* reply) { + qDebug() << "ImageOverlay::replyFinished() reply=" << reply; + // replace our byte array with the downloaded data + QByteArray rawData = reply->readAll(); + _textureImage.loadFromData(rawData); + _renderImage = true; + + // TODO: handle setting image multiple times, how do we manage releasing the bound texture + qDebug() << "ImageOverlay::replyFinished() about to call _parent->bindTexture(_textureImage)... _parent" << _parent; + + + qDebug() << "ImageOverlay::replyFinished _textureID=" << _textureID + << "_textureImage.width()=" << _textureImage.width() + << "_textureImage.height()=" << _textureImage.height(); +} void ImageOverlay::render() { -qDebug() << "ImageOverlay::render _textureID=" << _textureID << "_bounds=" << _bounds; + //qDebug() << "ImageOverlay::render _textureID=" << _textureID << "_bounds=" << _bounds; + + if (_renderImage && !_textureBound) { + _textureID = _parent->bindTexture(_textureImage); + _textureBound = true; + } - - bool renderImage = false; - if (renderImage) { + if (_renderImage) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, _textureID); } - glColor4f(1.0f, 0.0f, 0.0f, 0.7f); // ??? + const float MAX_COLOR = 255; + glColor4f((_backgroundColor.red / MAX_COLOR), (_backgroundColor.green / MAX_COLOR), (_backgroundColor.blue / MAX_COLOR), _alpha); float imageWidth = _textureImage.width(); float imageHeight = _textureImage.height(); @@ -47,23 +88,84 @@ qDebug() << "ImageOverlay::render _textureID=" << _textureID << "_bounds=" << _b float w = _fromImage.width() / imageWidth; // ?? is this what we want? not sure float h = _fromImage.height() / imageHeight; - qDebug() << "ImageOverlay::render x=" << x << "y=" << y << "w="< #include +#include +#include +#include #include +#include #include #include #include #include "InterfaceConfig.h" -//#include "Util.h" +const xColor DEFAULT_BACKGROUND_COLOR = { 255, 255, 255 }; +const float DEFAULT_ALPHA = 0.7f; class ImageOverlay : QObject { Q_OBJECT @@ -34,9 +38,10 @@ class ImageOverlay : QObject { public: ImageOverlay(); ~ImageOverlay(); - void init(QGLWidget* parent, const QString& filename, const QRect& drawAt, const QRect& fromImage); + void init(QGLWidget* parent); void render(); +public slots: // getters int getX() const { return _bounds.x(); } int getY() const { return _bounds.y(); } @@ -47,19 +52,25 @@ public: const xColor& getBackgroundColor() const { return _backgroundColor; } float getAlpha() const { return _alpha; } const QUrl& getImageURL() const { return _imageURL; } + QScriptValue getProperties(); // setters - void setX(int x) { } - void setY(int y) { } - void setWidth(int width) { } - void setHeight(int height) { } - void setBounds(const QRect& bounds) { } - void setClipFromSource(const QRect& bounds) { } - void setBackgroundColor(const xColor& color) { } - void setAlpha(float) { } - void setImageURL(const QUrl& ) { } + void setX(int x) { _bounds.setX(x); } + void setY(int y) { _bounds.setY(y); } + void setWidth(int width) { _bounds.setWidth(width); } + void setHeight(int height) { _bounds.setHeight(height); } + void setBounds(const QRect& bounds) { _bounds = bounds; } + void setClipFromSource(const QRect& bounds) { _fromImage = bounds; } + void setBackgroundColor(const xColor& color) { _backgroundColor = color; } + void setAlpha(float alpha) { _alpha = alpha; } + void setImageURL(const QUrl& url); + void setProperties(const QScriptValue& properties); + +private slots: + void replyFinished(QNetworkReply* reply); // we actually want to hide this... private: + QUrl _imageURL; QGLWidget* _parent; QImage _textureImage; @@ -68,6 +79,9 @@ private: QRect _fromImage; // where from in the image to sample float _alpha; xColor _backgroundColor; + bool _renderImage; + bool _textureBound; }; + #endif /* defined(__interface__ImageOverlay__) */ diff --git a/interface/src/ui/Overlays.cpp b/interface/src/ui/Overlays.cpp new file mode 100644 index 0000000000..438e94ad60 --- /dev/null +++ b/interface/src/ui/Overlays.cpp @@ -0,0 +1,66 @@ +// +// Overlays.cpp +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + + +#include "Overlays.h" + +unsigned int Overlays::_nextOverlayID = 0; + +Overlays::Overlays() { +} + +Overlays::~Overlays() { +} + +void Overlays::init(QGLWidget* parent) { + qDebug() << "Overlays::init() parent=" << parent; + _parent = parent; +} + +void Overlays::render() { + foreach(ImageOverlay* thisOverlay, _imageOverlays) { + thisOverlay->render(); + } +} + +// TODO: make multi-threaded safe +unsigned int Overlays::addOverlay(const QScriptValue& properties) { + unsigned int thisID = _nextOverlayID; + _nextOverlayID++; + ImageOverlay* thisOverlay = new ImageOverlay(); + thisOverlay->init(_parent); + thisOverlay->setProperties(properties); + _imageOverlays[thisID] = thisOverlay; + return thisID; +} + +QScriptValue Overlays::getOverlayProperties(unsigned int id) { + if (!_imageOverlays.contains(id)) { + return QScriptValue(); + } + ImageOverlay* thisOverlay = _imageOverlays[id]; + return thisOverlay->getProperties(); +} + +// TODO: make multi-threaded safe +bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { + if (!_imageOverlays.contains(id)) { + return false; + } + ImageOverlay* thisOverlay = _imageOverlays[id]; + thisOverlay->setProperties(properties); + return true; +} + +// TODO: make multi-threaded safe +void Overlays::deleteOverlay(unsigned int id) { + if (_imageOverlays.contains(id)) { + _imageOverlays.erase(_imageOverlays.find(id)); + + } +} + diff --git a/interface/src/ui/Overlays.h b/interface/src/ui/Overlays.h new file mode 100644 index 0000000000..8b9f6eb8be --- /dev/null +++ b/interface/src/ui/Overlays.h @@ -0,0 +1,58 @@ +// +// Overlays.h +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__Overlays__ +#define __interface__Overlays__ + +/** +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "InterfaceConfig.h" +**/ + +#include + +#include "ImageOverlay.h" + +class Overlays : public QObject { + Q_OBJECT +public: + Overlays(); + ~Overlays(); + void init(QGLWidget* parent); + void render(); + +public slots: + /// adds an overlay with the specific properties + unsigned int addOverlay(const QScriptValue& properties); + + /// gets the current overlay properties for a specific overlay + QScriptValue getOverlayProperties(unsigned int id); + + /// edits an overlay updating only the included properties, will return the identified OverlayID in case of + /// successful edit, if the input id is for an unknown overlay this function will have no effect + bool editOverlay(unsigned int id, const QScriptValue& properties); + + /// deletes a particle + void deleteOverlay(unsigned int id); + +private: + QMap _imageOverlays; + static unsigned int _nextOverlayID; + QGLWidget* _parent; +}; + + +#endif /* defined(__interface__Overlays__) */ diff --git a/libraries/octree/src/OctreeScriptingInterface.cpp b/libraries/octree/src/OctreeScriptingInterface.cpp index 89bf5ceb62..1ed82564b6 100644 --- a/libraries/octree/src/OctreeScriptingInterface.cpp +++ b/libraries/octree/src/OctreeScriptingInterface.cpp @@ -23,7 +23,6 @@ OctreeScriptingInterface::OctreeScriptingInterface(OctreeEditPacketSender* packe } OctreeScriptingInterface::~OctreeScriptingInterface() { -qDebug() << "OctreeScriptingInterface::~OctreeScriptingInterface() this=" << this; cleanupManagedObjects(); } From f6adce255d355d0914c3604553ae8bb77a46b2ef Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Feb 2014 16:26:34 -0800 Subject: [PATCH 03/14] more work on image overlays --- examples/overlaysExample.js | 125 +++++++++++++++++++++++++++++- interface/src/ui/ImageOverlay.cpp | 106 ++++++++++++++++--------- interface/src/ui/ImageOverlay.h | 22 +++--- 3 files changed, 202 insertions(+), 51 deletions(-) diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index d297e2525d..36e88ea43c 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -18,6 +18,61 @@ QRect(170,100,62,40), QRect(0,80,62,40)); */ +var swatch1 = Overlays.addOverlay({ + x: 100, + y: 200, + width: 31, + height: 54, + subImage: { x: 39, y: 0, width: 30, height: 54 }, + imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", + backgroundColor: { red: 255, green: 0, blue: 0}, + alpha: 1 + }); + +var swatch2 = Overlays.addOverlay({ + x: 130, + y: 200, + width: 31, + height: 54, + subImage: { x: 39, y: 55, width: 30, height: 54 }, + imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", + backgroundColor: { red: 0, green: 255, blue: 0}, + alpha: 1.0 + }); + +var swatch3 = Overlays.addOverlay({ + x: 160, + y: 200, + width: 31, + height: 54, + subImage: { x: 39, y: 0, width: 30, height: 54 }, + imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", + backgroundColor: { red: 0, green: 0, blue: 255}, + alpha: 1.0 + }); + +var swatch4 = Overlays.addOverlay({ + x: 190, + y: 200, + width: 31, + height: 54, + subImage: { x: 39, y: 0, width: 30, height: 54 }, + imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", + backgroundColor: { red: 0, green: 255, blue: 255}, + alpha: 1.0 + }); + +var swatch5 = Overlays.addOverlay({ + x: 220, + y: 200, + width: 31, + height: 54, + subImage: { x: 39, y: 0, width: 30, height: 54 }, + imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", + backgroundColor: { red: 255, green: 255, blue: 0}, + alpha: 1.0 + }); + var toolA = Overlays.addOverlay({ x: 100, y: 100, @@ -25,11 +80,77 @@ var toolA = Overlays.addOverlay({ height: 40, subImage: { x: 0, y: 0, width: 62, height: 40 }, imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg", - backgroundColor: { red: 255, green: 0, blue: 255}, - alpha: 1.0 + backgroundColor: { red: 255, green: 255, blue: 255}, + alpha: 0.7, + visible: false }); +var slider = Overlays.addOverlay({ + // alternate form of expressing bounds + bounds: { x: 100, y: 300, width: 158, height: 35}, + imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/slider.png", + backgroundColor: { red: 255, green: 255, blue: 255}, + alpha: 1 + }); + +var thumb = Overlays.addOverlay({ + x: 130, + y: 309, + width: 18, + height: 17, + imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png", + backgroundColor: { red: 255, green: 255, blue: 255}, + alpha: 1 + }); + + +// 270x 109 +// 109... 109/2 = 54,1,54 +// 270... 39 to 66 = 28 x 9 swatches with +// unselected: +// 38,0,28,54 +// selected: +// 38,55,28,54 +//http://highfidelity-public.s3-us-west-1.amazonaws.com/images/swatches.svg + +// 123456789*123456789*123456789* +// 0123456789*123456789*123456789* + function scriptEnding() { Overlays.deleteOverlay(toolA); + //Overlays.deleteOverlay(toolB); + //Overlays.deleteOverlay(toolC); + Overlays.deleteOverlay(swatch1); + Overlays.deleteOverlay(swatch2); + Overlays.deleteOverlay(swatch3); + Overlays.deleteOverlay(swatch4); + Overlays.deleteOverlay(swatch5); + Overlays.deleteOverlay(thumb); + Overlays.deleteOverlay(slider); } Script.scriptEnding.connect(scriptEnding); + + +var toolAVisible = false; +var minX = 130; +var maxX = minX + 65; +var moveX = (minX + maxX)/2; +var dX = 1; +function update() { + moveX = moveX + dX; + if (moveX > maxX) { + dX = -1; + } + if (moveX < minX) { + dX = 1; + if (toolAVisible) { + toolAVisible = false; + } else { + toolAVisible = true; + } + Overlays.editOverlay(toolA, { visible: toolAVisible } ); + } + Overlays.editOverlay(thumb, { x: moveX } ); + +} +Script.willSendVisualDataCallback.connect(update); diff --git a/interface/src/ui/ImageOverlay.cpp b/interface/src/ui/ImageOverlay.cpp index b85f05f557..7024cff533 100644 --- a/interface/src/ui/ImageOverlay.cpp +++ b/interface/src/ui/ImageOverlay.cpp @@ -18,21 +18,16 @@ ImageOverlay::ImageOverlay() : _textureID(0), _alpha(DEFAULT_ALPHA), _backgroundColor(DEFAULT_BACKGROUND_COLOR), + _visible(true), _renderImage(false), - _textureBound(false) + _textureBound(false), + _wantClipFromImage(false) { } void ImageOverlay::init(QGLWidget* parent) { qDebug() << "ImageOverlay::init() parent=" << parent; _parent = parent; - - /* - qDebug() << "ImageOverlay::init()... url=" << url; - _bounds = drawAt; - _fromImage = fromImage; - setImageURL(url); - */ } @@ -43,6 +38,7 @@ ImageOverlay::~ImageOverlay() { } } +// TODO: handle setting image multiple times, how do we manage releasing the bound texture? void ImageOverlay::setImageURL(const QUrl& url) { // TODO: are we creating too many QNetworkAccessManager() when multiple calls to setImageURL are made? QNetworkAccessManager* manager = new QNetworkAccessManager(this); @@ -51,24 +47,18 @@ void ImageOverlay::setImageURL(const QUrl& url) { } void ImageOverlay::replyFinished(QNetworkReply* reply) { - qDebug() << "ImageOverlay::replyFinished() reply=" << reply; + // replace our byte array with the downloaded data QByteArray rawData = reply->readAll(); _textureImage.loadFromData(rawData); _renderImage = true; - // TODO: handle setting image multiple times, how do we manage releasing the bound texture - qDebug() << "ImageOverlay::replyFinished() about to call _parent->bindTexture(_textureImage)... _parent" << _parent; - - - qDebug() << "ImageOverlay::replyFinished _textureID=" << _textureID - << "_textureImage.width()=" << _textureImage.width() - << "_textureImage.height()=" << _textureImage.height(); } void ImageOverlay::render() { - //qDebug() << "ImageOverlay::render _textureID=" << _textureID << "_bounds=" << _bounds; - + if (!_visible) { + return; // do nothing if we're not visible + } if (_renderImage && !_textureBound) { _textureID = _parent->bindTexture(_textureImage); _textureBound = true; @@ -79,17 +69,25 @@ void ImageOverlay::render() { glBindTexture(GL_TEXTURE_2D, _textureID); } const float MAX_COLOR = 255; - glColor4f((_backgroundColor.red / MAX_COLOR), (_backgroundColor.green / MAX_COLOR), (_backgroundColor.blue / MAX_COLOR), _alpha); + glColor4f(_backgroundColor.red / MAX_COLOR, _backgroundColor.green / MAX_COLOR, _backgroundColor.blue / MAX_COLOR, _alpha); float imageWidth = _textureImage.width(); float imageHeight = _textureImage.height(); - float x = _fromImage.x() / imageWidth; - float y = _fromImage.y() / imageHeight; - float w = _fromImage.width() / imageWidth; // ?? is this what we want? not sure - float h = _fromImage.height() / imageHeight; - - //qDebug() << "ImageOverlay::render x=" << x << "y=" << y << "w="< Date: Sat, 15 Feb 2014 16:31:09 -0800 Subject: [PATCH 04/14] removed getProperties() which was not implemented --- interface/src/ui/ImageOverlay.cpp | 5 ----- interface/src/ui/ImageOverlay.h | 1 - interface/src/ui/Overlays.cpp | 10 ---------- interface/src/ui/Overlays.h | 3 --- 4 files changed, 19 deletions(-) diff --git a/interface/src/ui/ImageOverlay.cpp b/interface/src/ui/ImageOverlay.cpp index 7024cff533..6f5a0e0669 100644 --- a/interface/src/ui/ImageOverlay.cpp +++ b/interface/src/ui/ImageOverlay.cpp @@ -114,11 +114,6 @@ void ImageOverlay::render() { } } -// TODO: handle only setting the included values... -QScriptValue ImageOverlay::getProperties() { - return QScriptValue(); -} - // TODO: handle only setting the included values... void ImageOverlay::setProperties(const QScriptValue& properties) { //qDebug() << "ImageOverlay::setProperties()... properties=" << &properties; diff --git a/interface/src/ui/ImageOverlay.h b/interface/src/ui/ImageOverlay.h index 84838954b6..cad38b1071 100644 --- a/interface/src/ui/ImageOverlay.h +++ b/interface/src/ui/ImageOverlay.h @@ -45,7 +45,6 @@ public: const xColor& getBackgroundColor() const { return _backgroundColor; } float getAlpha() const { return _alpha; } const QUrl& getImageURL() const { return _imageURL; } - QScriptValue getProperties(); // setters void setVisible(bool visible) { _visible = visible; } diff --git a/interface/src/ui/Overlays.cpp b/interface/src/ui/Overlays.cpp index 438e94ad60..d5de389efc 100644 --- a/interface/src/ui/Overlays.cpp +++ b/interface/src/ui/Overlays.cpp @@ -17,7 +17,6 @@ Overlays::~Overlays() { } void Overlays::init(QGLWidget* parent) { - qDebug() << "Overlays::init() parent=" << parent; _parent = parent; } @@ -38,14 +37,6 @@ unsigned int Overlays::addOverlay(const QScriptValue& properties) { return thisID; } -QScriptValue Overlays::getOverlayProperties(unsigned int id) { - if (!_imageOverlays.contains(id)) { - return QScriptValue(); - } - ImageOverlay* thisOverlay = _imageOverlays[id]; - return thisOverlay->getProperties(); -} - // TODO: make multi-threaded safe bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { if (!_imageOverlays.contains(id)) { @@ -60,7 +51,6 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { void Overlays::deleteOverlay(unsigned int id) { if (_imageOverlays.contains(id)) { _imageOverlays.erase(_imageOverlays.find(id)); - } } diff --git a/interface/src/ui/Overlays.h b/interface/src/ui/Overlays.h index 8b9f6eb8be..4e4abe3157 100644 --- a/interface/src/ui/Overlays.h +++ b/interface/src/ui/Overlays.h @@ -38,9 +38,6 @@ public slots: /// adds an overlay with the specific properties unsigned int addOverlay(const QScriptValue& properties); - /// gets the current overlay properties for a specific overlay - QScriptValue getOverlayProperties(unsigned int id); - /// edits an overlay updating only the included properties, will return the identified OverlayID in case of /// successful edit, if the input id is for an unknown overlay this function will have no effect bool editOverlay(unsigned int id, const QScriptValue& properties); From f7f695d145f9e64d57e9adf6cf1f1e9521a99fc3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Feb 2014 17:45:42 -0800 Subject: [PATCH 05/14] add support for detecting clicked on overlays --- examples/overlaysExample.js | 155 +++++++++++++++--------------- interface/src/ui/ImageOverlay.cpp | 9 ++ interface/src/ui/Overlays.cpp | 17 +++- interface/src/ui/Overlays.h | 3 + 4 files changed, 107 insertions(+), 77 deletions(-) diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index 36e88ea43c..c1835f8957 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -9,69 +9,40 @@ // // - /* - _testOverlayA.init(_glWidget, QString("https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg"), - QRect(100,100,62,40), QRect(0,0,62,40)); - xColor red = { 255, 0, 0 }; - _testOverlayA.setBackgroundColor(red); - _testOverlayB.init(_glWidget, QString("https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg"), - QRect(170,100,62,40), QRect(0,80,62,40)); - */ +var swatchColors = new Array(); +swatchColors[0] = { red: 255, green: 0, blue: 0}; +swatchColors[1] = { red: 0, green: 255, blue: 0}; +swatchColors[2] = { red: 0, green: 0, blue: 255}; +swatchColors[3] = { red: 255, green: 255, blue: 0}; +swatchColors[4] = { red: 255, green: 0, blue: 255}; +swatchColors[5] = { red: 0, green: 255, blue: 255}; +swatchColors[6] = { red: 128, green: 128, blue: 128}; +swatchColors[7] = { red: 128, green: 0, blue: 0}; +swatchColors[8] = { red: 0, green: 240, blue: 240}; -var swatch1 = Overlays.addOverlay({ - x: 100, +var swatches = new Array(); +var numberOfSwatches = 9; +var swatchesX = 100; +var swatchesY = 200; +var selectedSwatch = 0; +for (s = 0; s < numberOfSwatches; s++) { + var imageFromX = 12 + (s * 27); + var imageFromY = 0; + if (s == selectedSwatch) { + imageFromY = 55; + } + + swatches[s] = Overlays.addOverlay({ + x: 100 + (30 * s), y: 200, width: 31, height: 54, - subImage: { x: 39, y: 0, width: 30, height: 54 }, + subImage: { x: imageFromX, y: imageFromY, width: 30, height: 54 }, imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", - backgroundColor: { red: 255, green: 0, blue: 0}, + backgroundColor: swatchColors[s], alpha: 1 }); - -var swatch2 = Overlays.addOverlay({ - x: 130, - y: 200, - width: 31, - height: 54, - subImage: { x: 39, y: 55, width: 30, height: 54 }, - imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", - backgroundColor: { red: 0, green: 255, blue: 0}, - alpha: 1.0 - }); - -var swatch3 = Overlays.addOverlay({ - x: 160, - y: 200, - width: 31, - height: 54, - subImage: { x: 39, y: 0, width: 30, height: 54 }, - imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", - backgroundColor: { red: 0, green: 0, blue: 255}, - alpha: 1.0 - }); - -var swatch4 = Overlays.addOverlay({ - x: 190, - y: 200, - width: 31, - height: 54, - subImage: { x: 39, y: 0, width: 30, height: 54 }, - imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", - backgroundColor: { red: 0, green: 255, blue: 255}, - alpha: 1.0 - }); - -var swatch5 = Overlays.addOverlay({ - x: 220, - y: 200, - width: 31, - height: 54, - subImage: { x: 39, y: 0, width: 30, height: 54 }, - imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", - backgroundColor: { red: 255, green: 255, blue: 0}, - alpha: 1.0 - }); +} var toolA = Overlays.addOverlay({ x: 100, @@ -93,8 +64,11 @@ var slider = Overlays.addOverlay({ alpha: 1 }); +var minThumbX = 130; +var maxThumbX = minThumbX + 65; +var thumbX = (minThumbX + maxThumbX) / 2; var thumb = Overlays.addOverlay({ - x: 130, + x: thumbX, y: 309, width: 18, height: 17, @@ -118,13 +92,9 @@ var thumb = Overlays.addOverlay({ function scriptEnding() { Overlays.deleteOverlay(toolA); - //Overlays.deleteOverlay(toolB); - //Overlays.deleteOverlay(toolC); - Overlays.deleteOverlay(swatch1); - Overlays.deleteOverlay(swatch2); - Overlays.deleteOverlay(swatch3); - Overlays.deleteOverlay(swatch4); - Overlays.deleteOverlay(swatch5); + for (s = 0; s < numberOfSwatches; s++) { + Overlays.deleteOverlay(swatches[s]); + } Overlays.deleteOverlay(thumb); Overlays.deleteOverlay(slider); } @@ -132,17 +102,10 @@ Script.scriptEnding.connect(scriptEnding); var toolAVisible = false; -var minX = 130; -var maxX = minX + 65; -var moveX = (minX + maxX)/2; -var dX = 1; +var count = 0; function update() { - moveX = moveX + dX; - if (moveX > maxX) { - dX = -1; - } - if (moveX < minX) { - dX = 1; + count++; + if (count % 60 == 0) { if (toolAVisible) { toolAVisible = false; } else { @@ -150,7 +113,47 @@ function update() { } Overlays.editOverlay(toolA, { visible: toolAVisible } ); } - Overlays.editOverlay(thumb, { x: moveX } ); - } Script.willSendVisualDataCallback.connect(update); + + +var movingSlider = false; +var thumbClickOffsetX = 0; +function mouseMoveEvent(event) { + if (movingSlider) { + newThumbX = event.x - thumbClickOffsetX; + if (newThumbX < minThumbX) { + newThumbX = minThumbX; + } + if (newThumbX > maxThumbX) { + newThumbX = maxThumbX; + } + Overlays.editOverlay(thumb, { x: newThumbX } ); + } +} +function mousePressEvent(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + if (clickedOverlay == thumb) { + movingSlider = true; + thumbClickOffsetX = event.x - thumbX; + } else { + for (s = 0; s < numberOfSwatches; s++) { + if (clickedOverlay == swatches[s]) { + Overlays.editOverlay(swatches[selectedSwatch], { subImage: { y: 0 } } ); + Overlays.editOverlay(swatches[s], { subImage: { y: 55 } } ); + selectedSwatch = s; + } + } + } +} + +function mouseReleaseEvent(event) { + if (movingSlider) { + movingSlider = false; + } +} + +Controller.mouseMoveEvent.connect(mouseMoveEvent); +Controller.mousePressEvent.connect(mousePressEvent); +Controller.mouseReleaseEvent.connect(mouseReleaseEvent); + diff --git a/interface/src/ui/ImageOverlay.cpp b/interface/src/ui/ImageOverlay.cpp index 6f5a0e0669..5849fdae7d 100644 --- a/interface/src/ui/ImageOverlay.cpp +++ b/interface/src/ui/ImageOverlay.cpp @@ -154,18 +154,27 @@ void ImageOverlay::setProperties(const QScriptValue& properties) { } QScriptValue subImageBounds = properties.property("subImage"); if (subImageBounds.isValid()) { + QRect oldSubImageRect = _fromImage; QRect subImageRect = _fromImage; if (subImageBounds.property("x").isValid()) { subImageRect.setX(subImageBounds.property("x").toVariant().toInt()); + } else { + subImageRect.setX(oldSubImageRect.x()); } if (subImageBounds.property("y").isValid()) { subImageRect.setY(subImageBounds.property("y").toVariant().toInt()); + } else { + subImageRect.setY(oldSubImageRect.y()); } if (subImageBounds.property("width").isValid()) { subImageRect.setWidth(subImageBounds.property("width").toVariant().toInt()); + } else { + subImageRect.setWidth(oldSubImageRect.width()); } if (subImageBounds.property("height").isValid()) { subImageRect.setHeight(subImageBounds.property("height").toVariant().toInt()); + } else { + subImageRect.setHeight(oldSubImageRect.height()); } setClipFromSource(subImageRect); } diff --git a/interface/src/ui/Overlays.cpp b/interface/src/ui/Overlays.cpp index d5de389efc..fef2e94a85 100644 --- a/interface/src/ui/Overlays.cpp +++ b/interface/src/ui/Overlays.cpp @@ -8,7 +8,7 @@ #include "Overlays.h" -unsigned int Overlays::_nextOverlayID = 0; +unsigned int Overlays::_nextOverlayID = 1; Overlays::Overlays() { } @@ -54,3 +54,18 @@ void Overlays::deleteOverlay(unsigned int id) { } } +unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { + QMapIterator i(_imageOverlays); + i.toBack(); + while (i.hasPrevious()) { + i.previous(); + unsigned int thisID = i.key(); + ImageOverlay* thisOverlay = i.value(); + if (thisOverlay->getBounds().contains(point.x, point.y, false)) { + return thisID; + } + } + return 0; // not found +} + + diff --git a/interface/src/ui/Overlays.h b/interface/src/ui/Overlays.h index 4e4abe3157..a1ced3979d 100644 --- a/interface/src/ui/Overlays.h +++ b/interface/src/ui/Overlays.h @@ -45,6 +45,9 @@ public slots: /// deletes a particle void deleteOverlay(unsigned int id); + /// returns the top most overlay at the screen point, or 0 if not overlay at that point + unsigned int getOverlayAtPoint(const glm::vec2& point); + private: QMap _imageOverlays; static unsigned int _nextOverlayID; From 37bb85fca626311d347267985ff0106278fff71a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Feb 2014 19:15:30 -0800 Subject: [PATCH 06/14] tweaks to overlays --- examples/overlaysExample.js | 8 ++++---- interface/src/ui/ImageOverlay.cpp | 1 - interface/src/ui/Overlays.cpp | 18 +++++++++++------- interface/src/ui/Overlays.h | 2 +- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index c1835f8957..778de0421e 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -32,7 +32,7 @@ for (s = 0; s < numberOfSwatches; s++) { imageFromY = 55; } - swatches[s] = Overlays.addOverlay({ + swatches[s] = Overlays.addOverlay("image", { x: 100 + (30 * s), y: 200, width: 31, @@ -44,7 +44,7 @@ for (s = 0; s < numberOfSwatches; s++) { }); } -var toolA = Overlays.addOverlay({ +var toolA = Overlays.addOverlay("image", { x: 100, y: 100, width: 62, @@ -56,7 +56,7 @@ var toolA = Overlays.addOverlay({ visible: false }); -var slider = Overlays.addOverlay({ +var slider = Overlays.addOverlay("image", { // alternate form of expressing bounds bounds: { x: 100, y: 300, width: 158, height: 35}, imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/slider.png", @@ -67,7 +67,7 @@ var slider = Overlays.addOverlay({ var minThumbX = 130; var maxThumbX = minThumbX + 65; var thumbX = (minThumbX + maxThumbX) / 2; -var thumb = Overlays.addOverlay({ +var thumb = Overlays.addOverlay("image", { x: thumbX, y: 309, width: 18, diff --git a/interface/src/ui/ImageOverlay.cpp b/interface/src/ui/ImageOverlay.cpp index 5849fdae7d..5d7d7efcc0 100644 --- a/interface/src/ui/ImageOverlay.cpp +++ b/interface/src/ui/ImageOverlay.cpp @@ -202,7 +202,6 @@ void ImageOverlay::setProperties(const QScriptValue& properties) { if (properties.property("visible").isValid()) { setVisible(properties.property("visible").toVariant().toBool()); - qDebug() << "setting visible to " << getVisible(); } } diff --git a/interface/src/ui/Overlays.cpp b/interface/src/ui/Overlays.cpp index fef2e94a85..5c19dc5529 100644 --- a/interface/src/ui/Overlays.cpp +++ b/interface/src/ui/Overlays.cpp @@ -27,13 +27,17 @@ void Overlays::render() { } // TODO: make multi-threaded safe -unsigned int Overlays::addOverlay(const QScriptValue& properties) { - unsigned int thisID = _nextOverlayID; - _nextOverlayID++; - ImageOverlay* thisOverlay = new ImageOverlay(); - thisOverlay->init(_parent); - thisOverlay->setProperties(properties); - _imageOverlays[thisID] = thisOverlay; +unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) { + unsigned int thisID = 0; + + if (type == "image") { + thisID = _nextOverlayID; + _nextOverlayID++; + ImageOverlay* thisOverlay = new ImageOverlay(); + thisOverlay->init(_parent); + thisOverlay->setProperties(properties); + _imageOverlays[thisID] = thisOverlay; + } return thisID; } diff --git a/interface/src/ui/Overlays.h b/interface/src/ui/Overlays.h index a1ced3979d..ed686dc024 100644 --- a/interface/src/ui/Overlays.h +++ b/interface/src/ui/Overlays.h @@ -36,7 +36,7 @@ public: public slots: /// adds an overlay with the specific properties - unsigned int addOverlay(const QScriptValue& properties); + unsigned int addOverlay(const QString& type, const QScriptValue& properties); /// edits an overlay updating only the included properties, will return the identified OverlayID in case of /// successful edit, if the input id is for an unknown overlay this function will have no effect From 0a9f9a7c7a77ad151aca953ccc380281105cbede Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Feb 2014 19:20:08 -0800 Subject: [PATCH 07/14] fix windows build --- interface/src/ui/ImageOverlay.h | 5 +++-- interface/src/ui/Overlays.h | 14 -------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/interface/src/ui/ImageOverlay.h b/interface/src/ui/ImageOverlay.h index cad38b1071..de2dcb7693 100644 --- a/interface/src/ui/ImageOverlay.h +++ b/interface/src/ui/ImageOverlay.h @@ -8,6 +8,9 @@ #ifndef __interface__ImageOverlay__ #define __interface__ImageOverlay__ +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + #include #include #include @@ -19,8 +22,6 @@ #include -#include "InterfaceConfig.h" - const xColor DEFAULT_BACKGROUND_COLOR = { 255, 255, 255 }; const float DEFAULT_ALPHA = 0.7f; diff --git a/interface/src/ui/Overlays.h b/interface/src/ui/Overlays.h index ed686dc024..84e4338a72 100644 --- a/interface/src/ui/Overlays.h +++ b/interface/src/ui/Overlays.h @@ -8,20 +8,6 @@ #ifndef __interface__Overlays__ #define __interface__Overlays__ -/** -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "InterfaceConfig.h" -**/ - #include #include "ImageOverlay.h" From ef11865d2490356158811d879d010a2c9dd5d31b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Feb 2014 21:13:44 -0800 Subject: [PATCH 08/14] implement text overlay support --- examples/overlaysExample.js | 21 ++++++++ interface/src/Util.h | 9 ---- interface/src/ui/ImageOverlay.cpp | 69 +----------------------- interface/src/ui/ImageOverlay.h | 32 ++--------- interface/src/ui/Overlay.cpp | 88 +++++++++++++++++++++++++++++++ interface/src/ui/Overlay.h | 64 ++++++++++++++++++++++ interface/src/ui/Overlays.cpp | 29 ++++++---- interface/src/ui/Overlays.h | 4 +- interface/src/ui/TextOverlay.cpp | 80 ++++++++++++++++++++++++++++ interface/src/ui/TextOverlay.h | 58 ++++++++++++++++++++ interface/src/ui/TextRenderer.cpp | 34 +++++++++--- interface/src/ui/TextRenderer.h | 16 +++++- 12 files changed, 382 insertions(+), 122 deletions(-) create mode 100644 interface/src/ui/Overlay.cpp create mode 100644 interface/src/ui/Overlay.h create mode 100644 interface/src/ui/TextOverlay.cpp create mode 100644 interface/src/ui/TextOverlay.h diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index 778de0421e..79cd65df68 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -44,6 +44,19 @@ for (s = 0; s < numberOfSwatches; s++) { }); } +var text = Overlays.addOverlay("text", { + x: 200, + y: 100, + width: 150, + height: 50, + backgroundColor: { red: 0, green: 0, blue: 0}, + textColor: { red: 255, green: 0, blue: 0}, + topMargin: 4, + leftMargin: 4, + alpha: 0.7, + text: "Here is some text.\nAnd a second line." + }); + var toolA = Overlays.addOverlay("image", { x: 100, y: 100, @@ -97,6 +110,7 @@ function scriptEnding() { } Overlays.deleteOverlay(thumb); Overlays.deleteOverlay(slider); + Overlays.deleteOverlay(text); } Script.scriptEnding.connect(scriptEnding); @@ -132,10 +146,14 @@ function mouseMoveEvent(event) { } } function mousePressEvent(event) { + var clickedText = false; var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); if (clickedOverlay == thumb) { movingSlider = true; thumbClickOffsetX = event.x - thumbX; + } else if (clickedOverlay == text) { + Overlays.editOverlay(text, { text: "you clicked here:\n " + event.x + "," + event.y } ); + clickedText = true; } else { for (s = 0; s < numberOfSwatches; s++) { if (clickedOverlay == swatches[s]) { @@ -145,6 +163,9 @@ function mousePressEvent(event) { } } } + if (!clickedText) { + Overlays.editOverlay(text, { text: "you didn't click here" } ); + } } function mouseReleaseEvent(event) { diff --git a/interface/src/Util.h b/interface/src/Util.h index 09d1fa0484..0c762ccd79 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -19,15 +19,6 @@ #include #include -// the standard sans serif font family -#define SANS_FONT_FAMILY "Helvetica" - -// the standard mono font family -#define MONO_FONT_FAMILY "Courier" - -// the Inconsolata font family -#define INCONSOLATA_FONT_FAMILY "Inconsolata" - void eulerToOrthonormals(glm::vec3 * angles, glm::vec3 * fwd, glm::vec3 * left, glm::vec3 * up); float azimuth_to(glm::vec3 head_pos, glm::vec3 source_pos); diff --git a/interface/src/ui/ImageOverlay.cpp b/interface/src/ui/ImageOverlay.cpp index 5d7d7efcc0..d36099cffc 100644 --- a/interface/src/ui/ImageOverlay.cpp +++ b/interface/src/ui/ImageOverlay.cpp @@ -14,23 +14,13 @@ #include ImageOverlay::ImageOverlay() : - _parent(NULL), _textureID(0), - _alpha(DEFAULT_ALPHA), - _backgroundColor(DEFAULT_BACKGROUND_COLOR), - _visible(true), _renderImage(false), _textureBound(false), _wantClipFromImage(false) { } -void ImageOverlay::init(QGLWidget* parent) { - qDebug() << "ImageOverlay::init() parent=" << parent; - _parent = parent; -} - - ImageOverlay::~ImageOverlay() { if (_parent && _textureID) { // do we need to call this? @@ -114,44 +104,9 @@ void ImageOverlay::render() { } } -// TODO: handle only setting the included values... void ImageOverlay::setProperties(const QScriptValue& properties) { - //qDebug() << "ImageOverlay::setProperties()... properties=" << &properties; - QScriptValue bounds = properties.property("bounds"); - if (bounds.isValid()) { - QRect boundsRect; - boundsRect.setX(bounds.property("x").toVariant().toInt()); - boundsRect.setY(bounds.property("y").toVariant().toInt()); - boundsRect.setWidth(bounds.property("width").toVariant().toInt()); - boundsRect.setHeight(bounds.property("height").toVariant().toInt()); - setBounds(boundsRect); - } else { - QRect oldBounds = getBounds(); - QRect newBounds = oldBounds; - - if (properties.property("x").isValid()) { - newBounds.setX(properties.property("x").toVariant().toInt()); - } else { - newBounds.setX(oldBounds.x()); - } - if (properties.property("y").isValid()) { - newBounds.setY(properties.property("y").toVariant().toInt()); - } else { - newBounds.setY(oldBounds.y()); - } - if (properties.property("width").isValid()) { - newBounds.setWidth(properties.property("width").toVariant().toInt()); - } else { - newBounds.setWidth(oldBounds.width()); - } - if (properties.property("height").isValid()) { - newBounds.setHeight(properties.property("height").toVariant().toInt()); - } else { - newBounds.setHeight(oldBounds.height()); - } - setBounds(newBounds); - //qDebug() << "set bounds to " << getBounds(); - } + Overlay::setProperties(properties); + QScriptValue subImageBounds = properties.property("subImage"); if (subImageBounds.isValid()) { QRect oldSubImageRect = _fromImage; @@ -183,26 +138,6 @@ void ImageOverlay::setProperties(const QScriptValue& properties) { if (imageURL.isValid()) { setImageURL(imageURL.toVariant().toString()); } - - QScriptValue color = properties.property("backgroundColor"); - if (color.isValid()) { - QScriptValue red = color.property("red"); - QScriptValue green = color.property("green"); - QScriptValue blue = color.property("blue"); - if (red.isValid() && green.isValid() && blue.isValid()) { - _backgroundColor.red = red.toVariant().toInt(); - _backgroundColor.green = green.toVariant().toInt(); - _backgroundColor.blue = blue.toVariant().toInt(); - } - } - - if (properties.property("alpha").isValid()) { - setAlpha(properties.property("alpha").toVariant().toFloat()); - } - - if (properties.property("visible").isValid()) { - setVisible(properties.property("visible").toVariant().toBool()); - } } diff --git a/interface/src/ui/ImageOverlay.h b/interface/src/ui/ImageOverlay.h index de2dcb7693..be7d8cf5d8 100644 --- a/interface/src/ui/ImageOverlay.h +++ b/interface/src/ui/ImageOverlay.h @@ -22,43 +22,24 @@ #include -const xColor DEFAULT_BACKGROUND_COLOR = { 255, 255, 255 }; -const float DEFAULT_ALPHA = 0.7f; +#include "Overlay.h" -class ImageOverlay : QObject { +class ImageOverlay : public Overlay { Q_OBJECT public: ImageOverlay(); ~ImageOverlay(); - void init(QGLWidget* parent); - void render(); + virtual void render(); -//public slots: // getters - bool getVisible() const { return _visible; } - int getX() const { return _bounds.x(); } - int getY() const { return _bounds.y(); } - int getWidth() const { return _bounds.width(); } - int getHeight() const { return _bounds.height(); } - const QRect& getBounds() const { return _bounds; } const QRect& getClipFromSource() const { return _fromImage; } - const xColor& getBackgroundColor() const { return _backgroundColor; } - float getAlpha() const { return _alpha; } const QUrl& getImageURL() const { return _imageURL; } // setters - void setVisible(bool visible) { _visible = visible; } - void setX(int x) { _bounds.setX(x); } - void setY(int y) { _bounds.setY(y); } - void setWidth(int width) { _bounds.setWidth(width); } - void setHeight(int height) { _bounds.setHeight(height); } - void setBounds(const QRect& bounds) { _bounds = bounds; } void setClipFromSource(const QRect& bounds) { _fromImage = bounds; _wantClipFromImage = true; } - void setBackgroundColor(const xColor& color) { _backgroundColor = color; } - void setAlpha(float alpha) { _alpha = alpha; } void setImageURL(const QUrl& url); - void setProperties(const QScriptValue& properties); + virtual void setProperties(const QScriptValue& properties); private slots: void replyFinished(QNetworkReply* reply); // we actually want to hide this... @@ -66,14 +47,9 @@ private slots: private: QUrl _imageURL; - QGLWidget* _parent; QImage _textureImage; GLuint _textureID; - QRect _bounds; // where on the screen to draw QRect _fromImage; // where from in the image to sample - float _alpha; - xColor _backgroundColor; - bool _visible; // should the overlay be drawn at all bool _renderImage; // is there an image associated with this overlay, or is it just a colored rectangle bool _textureBound; // has the texture been bound bool _wantClipFromImage; diff --git a/interface/src/ui/Overlay.cpp b/interface/src/ui/Overlay.cpp new file mode 100644 index 0000000000..fa54844477 --- /dev/null +++ b/interface/src/ui/Overlay.cpp @@ -0,0 +1,88 @@ +// +// Overlay.cpp +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + + +#include "Overlay.h" + +#include +#include +#include +#include + +Overlay::Overlay() : + _parent(NULL), + _alpha(DEFAULT_ALPHA), + _backgroundColor(DEFAULT_BACKGROUND_COLOR), + _visible(true) +{ +} + +void Overlay::init(QGLWidget* parent) { + _parent = parent; +} + + +Overlay::~Overlay() { +} + +void Overlay::setProperties(const QScriptValue& properties) { + QScriptValue bounds = properties.property("bounds"); + if (bounds.isValid()) { + QRect boundsRect; + boundsRect.setX(bounds.property("x").toVariant().toInt()); + boundsRect.setY(bounds.property("y").toVariant().toInt()); + boundsRect.setWidth(bounds.property("width").toVariant().toInt()); + boundsRect.setHeight(bounds.property("height").toVariant().toInt()); + setBounds(boundsRect); + } else { + QRect oldBounds = getBounds(); + QRect newBounds = oldBounds; + + if (properties.property("x").isValid()) { + newBounds.setX(properties.property("x").toVariant().toInt()); + } else { + newBounds.setX(oldBounds.x()); + } + if (properties.property("y").isValid()) { + newBounds.setY(properties.property("y").toVariant().toInt()); + } else { + newBounds.setY(oldBounds.y()); + } + if (properties.property("width").isValid()) { + newBounds.setWidth(properties.property("width").toVariant().toInt()); + } else { + newBounds.setWidth(oldBounds.width()); + } + if (properties.property("height").isValid()) { + newBounds.setHeight(properties.property("height").toVariant().toInt()); + } else { + newBounds.setHeight(oldBounds.height()); + } + setBounds(newBounds); + //qDebug() << "set bounds to " << getBounds(); + } + + QScriptValue color = properties.property("backgroundColor"); + if (color.isValid()) { + QScriptValue red = color.property("red"); + QScriptValue green = color.property("green"); + QScriptValue blue = color.property("blue"); + if (red.isValid() && green.isValid() && blue.isValid()) { + _backgroundColor.red = red.toVariant().toInt(); + _backgroundColor.green = green.toVariant().toInt(); + _backgroundColor.blue = blue.toVariant().toInt(); + } + } + + if (properties.property("alpha").isValid()) { + setAlpha(properties.property("alpha").toVariant().toFloat()); + } + + if (properties.property("visible").isValid()) { + setVisible(properties.property("visible").toVariant().toBool()); + } +} diff --git a/interface/src/ui/Overlay.h b/interface/src/ui/Overlay.h new file mode 100644 index 0000000000..ce63fdaba5 --- /dev/null +++ b/interface/src/ui/Overlay.h @@ -0,0 +1,64 @@ +// +// Overlay.h +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__Overlay__ +#define __interface__Overlay__ + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include +#include +#include + +#include // for xColor + +const xColor DEFAULT_BACKGROUND_COLOR = { 255, 255, 255 }; +const float DEFAULT_ALPHA = 0.7f; + +class Overlay : public QObject { + Q_OBJECT + +public: + Overlay(); + ~Overlay(); + void init(QGLWidget* parent); + virtual void render() = 0; + + // getters + bool getVisible() const { return _visible; } + int getX() const { return _bounds.x(); } + int getY() const { return _bounds.y(); } + int getWidth() const { return _bounds.width(); } + int getHeight() const { return _bounds.height(); } + const QRect& getBounds() const { return _bounds; } + const xColor& getBackgroundColor() const { return _backgroundColor; } + float getAlpha() const { return _alpha; } + + // setters + void setVisible(bool visible) { _visible = visible; } + void setX(int x) { _bounds.setX(x); } + void setY(int y) { _bounds.setY(y); } + void setWidth(int width) { _bounds.setWidth(width); } + void setHeight(int height) { _bounds.setHeight(height); } + void setBounds(const QRect& bounds) { _bounds = bounds; } + void setBackgroundColor(const xColor& color) { _backgroundColor = color; } + void setAlpha(float alpha) { _alpha = alpha; } + + virtual void setProperties(const QScriptValue& properties); + +protected: + QGLWidget* _parent; + QRect _bounds; // where on the screen to draw + float _alpha; + xColor _backgroundColor; + bool _visible; // should the overlay be drawn at all +}; + + +#endif /* defined(__interface__Overlay__) */ diff --git a/interface/src/ui/Overlays.cpp b/interface/src/ui/Overlays.cpp index 5c19dc5529..2f31e7e8c7 100644 --- a/interface/src/ui/Overlays.cpp +++ b/interface/src/ui/Overlays.cpp @@ -7,6 +7,9 @@ #include "Overlays.h" +#include "ImageOverlay.h" +#include "TextOverlay.h" + unsigned int Overlays::_nextOverlayID = 1; @@ -21,7 +24,7 @@ void Overlays::init(QGLWidget* parent) { } void Overlays::render() { - foreach(ImageOverlay* thisOverlay, _imageOverlays) { + foreach(Overlay* thisOverlay, _overlays) { thisOverlay->render(); } } @@ -36,36 +39,44 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope ImageOverlay* thisOverlay = new ImageOverlay(); thisOverlay->init(_parent); thisOverlay->setProperties(properties); - _imageOverlays[thisID] = thisOverlay; + _overlays[thisID] = thisOverlay; + } else if (type == "text") { + thisID = _nextOverlayID; + _nextOverlayID++; + TextOverlay* thisOverlay = new TextOverlay(); + thisOverlay->init(_parent); + thisOverlay->setProperties(properties); + _overlays[thisID] = thisOverlay; } + return thisID; } // TODO: make multi-threaded safe bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { - if (!_imageOverlays.contains(id)) { + if (!_overlays.contains(id)) { return false; } - ImageOverlay* thisOverlay = _imageOverlays[id]; + Overlay* thisOverlay = _overlays[id]; thisOverlay->setProperties(properties); return true; } // TODO: make multi-threaded safe void Overlays::deleteOverlay(unsigned int id) { - if (_imageOverlays.contains(id)) { - _imageOverlays.erase(_imageOverlays.find(id)); + if (_overlays.contains(id)) { + _overlays.erase(_overlays.find(id)); } } unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { - QMapIterator i(_imageOverlays); + QMapIterator i(_overlays); i.toBack(); while (i.hasPrevious()) { i.previous(); unsigned int thisID = i.key(); - ImageOverlay* thisOverlay = i.value(); - if (thisOverlay->getBounds().contains(point.x, point.y, false)) { + Overlay* thisOverlay = i.value(); + if (thisOverlay->getVisible() && thisOverlay->getBounds().contains(point.x, point.y, false)) { return thisID; } } diff --git a/interface/src/ui/Overlays.h b/interface/src/ui/Overlays.h index 84e4338a72..e39949d2c9 100644 --- a/interface/src/ui/Overlays.h +++ b/interface/src/ui/Overlays.h @@ -10,7 +10,7 @@ #include -#include "ImageOverlay.h" +#include "Overlay.h" class Overlays : public QObject { Q_OBJECT @@ -35,7 +35,7 @@ public slots: unsigned int getOverlayAtPoint(const glm::vec2& point); private: - QMap _imageOverlays; + QMap _overlays; static unsigned int _nextOverlayID; QGLWidget* _parent; }; diff --git a/interface/src/ui/TextOverlay.cpp b/interface/src/ui/TextOverlay.cpp new file mode 100644 index 0000000000..aec9f641c5 --- /dev/null +++ b/interface/src/ui/TextOverlay.cpp @@ -0,0 +1,80 @@ +// +// TextOverlay.cpp +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + + +#include +#include + +#include "TextOverlay.h" +#include "TextRenderer.h" + +TextOverlay::TextOverlay() : + _leftMargin(DEFAULT_MARGIN), + _topMargin(DEFAULT_MARGIN) +{ +} + +TextOverlay::~TextOverlay() { +} + +void TextOverlay::render() { + if (!_visible) { + return; // do nothing if we're not visible + } + + const float MAX_COLOR = 255; + glColor4f(_backgroundColor.red / MAX_COLOR, _backgroundColor.green / MAX_COLOR, _backgroundColor.blue / MAX_COLOR, _alpha); + + glBegin(GL_QUADS); + glVertex2f(_bounds.left(), _bounds.top()); + glVertex2f(_bounds.right(), _bounds.top()); + glVertex2f(_bounds.right(), _bounds.bottom()); + glVertex2f(_bounds.left(), _bounds.bottom()); + glEnd(); + + //TextRenderer(const char* family, int pointSize = -1, int weight = -1, bool italic = false, + // EffectType effect = NO_EFFECT, int effectThickness = 1); + + TextRenderer textRenderer(SANS_FONT_FAMILY, 11, 50); + const int leftAdjust = -1; // required to make text render relative to left edge of bounds + const int topAdjust = -2; // required to make text render relative to top edge of bounds + int x = _bounds.left() + _leftMargin + leftAdjust; + int y = _bounds.top() + _topMargin + topAdjust; + + glColor3f(1.0f, 1.0f, 1.0f); + QStringList lines = _text.split("\n"); + int lineOffset = 0; + foreach(QString thisLine, lines) { + if (lineOffset == 0) { + lineOffset = textRenderer.calculateHeight(qPrintable(thisLine)); + } + lineOffset += textRenderer.draw(x, y + lineOffset, qPrintable(thisLine)); + + const int lineGap = 2; + lineOffset += lineGap; + } + +} + +void TextOverlay::setProperties(const QScriptValue& properties) { + Overlay::setProperties(properties); + + QScriptValue text = properties.property("text"); + if (text.isValid()) { + setText(text.toVariant().toString()); + } + + if (properties.property("leftMargin").isValid()) { + setLeftMargin(properties.property("leftMargin").toVariant().toInt()); + } + + if (properties.property("topMargin").isValid()) { + setTopMargin(properties.property("topMargin").toVariant().toInt()); + } +} + + diff --git a/interface/src/ui/TextOverlay.h b/interface/src/ui/TextOverlay.h new file mode 100644 index 0000000000..323116eccf --- /dev/null +++ b/interface/src/ui/TextOverlay.h @@ -0,0 +1,58 @@ +// +// TextOverlay.h +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__TextOverlay__ +#define __interface__TextOverlay__ + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Overlay.h" + +const int DEFAULT_MARGIN = 10; + +class TextOverlay : public Overlay { + Q_OBJECT + +public: + TextOverlay(); + ~TextOverlay(); + virtual void render(); + + // getters + const QString& getText() const { return _text; } + int getLeftMargin() const { return _leftMargin; } + int getTopMargin() const { return _topMargin; } + + // setters + void setText(const QString& text) { _text = text; } + void setLeftMargin(int margin) { _leftMargin = margin; } + void setTopMargin(int margin) { _topMargin = margin; } + + virtual void setProperties(const QScriptValue& properties); + +private: + + QString _text; + int _leftMargin; + int _topMargin; + +}; + + +#endif /* defined(__interface__TextOverlay__) */ diff --git a/interface/src/ui/TextRenderer.cpp b/interface/src/ui/TextRenderer.cpp index 65056799e2..cacd730fd6 100644 --- a/interface/src/ui/TextRenderer.cpp +++ b/interface/src/ui/TextRenderer.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include "InterfaceConfig.h" #include "TextRenderer.h" @@ -30,10 +32,25 @@ TextRenderer::~TextRenderer() { glDeleteTextures(_allTextureIDs.size(), _allTextureIDs.constData()); } -void TextRenderer::draw(int x, int y, const char* str) { +int TextRenderer::calculateHeight(const char* str) { + int maxHeight = 0; + for (const char* ch = str; *ch != 0; ch++) { + const Glyph& glyph = getGlyph(*ch); + if (glyph.textureID() == 0) { + continue; + } + + if (glyph.bounds().height() > maxHeight) { + maxHeight = glyph.bounds().height(); + } + } + return maxHeight; +} +int TextRenderer::draw(int x, int y, const char* str) { glEnable(GL_TEXTURE_2D); + int maxHeight = 0; for (const char* ch = str; *ch != 0; ch++) { const Glyph& glyph = getGlyph(*ch); if (glyph.textureID() == 0) { @@ -41,19 +58,23 @@ void TextRenderer::draw(int x, int y, const char* str) { continue; } + if (glyph.bounds().height() > maxHeight) { + maxHeight = glyph.bounds().height(); + } + glBindTexture(GL_TEXTURE_2D, glyph.textureID()); - + int left = x + glyph.bounds().x(); int right = x + glyph.bounds().x() + glyph.bounds().width(); int bottom = y + glyph.bounds().y(); int top = y + glyph.bounds().y() + glyph.bounds().height(); - + float scale = 1.0 / IMAGE_SIZE; float ls = glyph.location().x() * scale; float rs = (glyph.location().x() + glyph.bounds().width()) * scale; float bt = glyph.location().y() * scale; float tt = (glyph.location().y() + glyph.bounds().height()) * scale; - + glBegin(GL_QUADS); glTexCoord2f(ls, bt); glVertex2f(left, bottom); @@ -64,12 +85,13 @@ void TextRenderer::draw(int x, int y, const char* str) { glTexCoord2f(ls, tt); glVertex2f(left, top); glEnd(); - + x += glyph.width(); } - glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); + + return maxHeight; } int TextRenderer::computeWidth(char ch) diff --git a/interface/src/ui/TextRenderer.h b/interface/src/ui/TextRenderer.h index ff484066d8..d6c24c1ce8 100644 --- a/interface/src/ui/TextRenderer.h +++ b/interface/src/ui/TextRenderer.h @@ -20,6 +20,16 @@ // a special "character" that renders as a solid block const char SOLID_BLOCK_CHAR = 127; +// the standard sans serif font family +#define SANS_FONT_FAMILY "Helvetica" + +// the standard mono font family +#define MONO_FONT_FAMILY "Courier" + +// the Inconsolata font family +#define INCONSOLATA_FONT_FAMILY "Inconsolata" + + class Glyph; class TextRenderer { @@ -33,7 +43,11 @@ public: const QFontMetrics& metrics() const { return _metrics; } - void draw(int x, int y, const char* str); + // returns the height of the tallest character + int calculateHeight(const char* str); + + // also returns the height of the tallest character + int draw(int x, int y, const char* str); int computeWidth(char ch); int computeWidth(const char* str); From cb1c659e2e5ef8324546aebead94e6a675378907 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Feb 2014 21:25:20 -0800 Subject: [PATCH 09/14] fix windows --- interface/src/ui/ImageOverlay.cpp | 12 +++++++----- interface/src/ui/Overlay.cpp | 7 +++++-- interface/src/ui/TextOverlay.cpp | 2 ++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/interface/src/ui/ImageOverlay.cpp b/interface/src/ui/ImageOverlay.cpp index d36099cffc..d048e7a27e 100644 --- a/interface/src/ui/ImageOverlay.cpp +++ b/interface/src/ui/ImageOverlay.cpp @@ -5,14 +5,16 @@ // Copyright (c) 2014 High Fidelity, Inc. All rights reserved. // +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include +#include +#include #include "ImageOverlay.h" -#include -#include -#include -#include - ImageOverlay::ImageOverlay() : _textureID(0), _renderImage(false), diff --git a/interface/src/ui/Overlay.cpp b/interface/src/ui/Overlay.cpp index fa54844477..4660fd6ada 100644 --- a/interface/src/ui/Overlay.cpp +++ b/interface/src/ui/Overlay.cpp @@ -5,14 +5,17 @@ // Copyright (c) 2014 High Fidelity, Inc. All rights reserved. // - -#include "Overlay.h" +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" #include #include #include #include +#include "Overlay.h" + + Overlay::Overlay() : _parent(NULL), _alpha(DEFAULT_ALPHA), diff --git a/interface/src/ui/TextOverlay.cpp b/interface/src/ui/TextOverlay.cpp index aec9f641c5..51b57c2f3f 100644 --- a/interface/src/ui/TextOverlay.cpp +++ b/interface/src/ui/TextOverlay.cpp @@ -5,6 +5,8 @@ // Copyright (c) 2014 High Fidelity, Inc. All rights reserved. // +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" #include #include From 5abf908874cfcecf08d8c86801fc7b6055475585 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 16 Feb 2014 11:36:06 -0800 Subject: [PATCH 10/14] added 3D cube overlay support --- examples/overlaysExample.js | 66 ++++++++++++++------ interface/src/Application.cpp | 5 +- interface/src/ui/Cube3DOverlay.cpp | 98 ++++++++++++++++++++++++++++++ interface/src/ui/Cube3DOverlay.h | 57 +++++++++++++++++ interface/src/ui/ImageOverlay.cpp | 4 +- interface/src/ui/ImageOverlay.h | 3 +- interface/src/ui/Overlay.cpp | 10 +-- interface/src/ui/Overlay.h | 6 +- interface/src/ui/Overlay2D.cpp | 63 +++++++++++++++++++ interface/src/ui/Overlay2D.h | 51 ++++++++++++++++ interface/src/ui/Overlays.cpp | 67 ++++++++++++++------ interface/src/ui/Overlays.h | 6 +- interface/src/ui/TextOverlay.cpp | 4 +- interface/src/ui/TextOverlay.h | 3 +- 14 files changed, 389 insertions(+), 54 deletions(-) create mode 100644 interface/src/ui/Cube3DOverlay.cpp create mode 100644 interface/src/ui/Cube3DOverlay.h create mode 100644 interface/src/ui/Overlay2D.cpp create mode 100644 interface/src/ui/Overlay2D.h diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index 79cd65df68..501f9a248e 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -39,7 +39,7 @@ for (s = 0; s < numberOfSwatches; s++) { height: 54, subImage: { x: imageFromX, y: imageFromY, width: 30, height: 54 }, imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", - backgroundColor: swatchColors[s], + color: swatchColors[s], alpha: 1 }); } @@ -49,11 +49,10 @@ var text = Overlays.addOverlay("text", { y: 100, width: 150, height: 50, - backgroundColor: { red: 0, green: 0, blue: 0}, + color: { red: 0, green: 0, blue: 0}, textColor: { red: 255, green: 0, blue: 0}, topMargin: 4, leftMargin: 4, - alpha: 0.7, text: "Here is some text.\nAnd a second line." }); @@ -64,8 +63,7 @@ var toolA = Overlays.addOverlay("image", { height: 40, subImage: { x: 0, y: 0, width: 62, height: 40 }, imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg", - backgroundColor: { red: 255, green: 255, blue: 255}, - alpha: 0.7, + color: { red: 255, green: 255, blue: 255}, visible: false }); @@ -73,7 +71,7 @@ var slider = Overlays.addOverlay("image", { // alternate form of expressing bounds bounds: { x: 100, y: 300, width: 158, height: 35}, imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/slider.png", - backgroundColor: { red: 255, green: 255, blue: 255}, + color: { red: 255, green: 255, blue: 255}, alpha: 1 }); @@ -86,22 +84,39 @@ var thumb = Overlays.addOverlay("image", { width: 18, height: 17, imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png", - backgroundColor: { red: 255, green: 255, blue: 255}, + color: { red: 255, green: 255, blue: 255}, alpha: 1 }); - -// 270x 109 -// 109... 109/2 = 54,1,54 -// 270... 39 to 66 = 28 x 9 swatches with -// unselected: -// 38,0,28,54 -// selected: -// 38,55,28,54 -//http://highfidelity-public.s3-us-west-1.amazonaws.com/images/swatches.svg -// 123456789*123456789*123456789* -// 0123456789*123456789*123456789* +// our 3D cube that moves around... +var cubePosition = { x: 2, y: 0, z: 2 }; +var cubeSize = 5; +var cubeMove = 0.1; +var minCubeX = 1; +var maxCubeX = 20; +var solidCubePosition = { x: 0, y: 5, z: 0 }; +var solidCubeSize = 2; +var minSolidCubeX = 0; +var maxSolidCubeX = 10; +var solidCubeMove = 0.05; + +var cube = Overlays.addOverlay("cube", { + position: cubePosition, + size: cubeSize, + color: { red: 255, green: 0, blue: 0}, + alpha: 1, + solid: false + }); + +var solidCube = Overlays.addOverlay("cube", { + position: solidCubePosition, + size: solidCubeSize, + color: { red: 0, green: 255, blue: 0}, + alpha: 1, + solid: true + }); + function scriptEnding() { Overlays.deleteOverlay(toolA); @@ -127,6 +142,21 @@ function update() { } Overlays.editOverlay(toolA, { visible: toolAVisible } ); } + + // move our 3D cube + cubePosition.x += cubeMove; + cubePosition.z += cubeMove; + if (cubePosition.x > maxCubeX || cubePosition.x < minCubeX) { + cubeMove = cubeMove * -1; + } + Overlays.editOverlay(cube, { position: cubePosition } ); + + solidCubePosition.x += solidCubeMove; + solidCubePosition.z += solidCubeMove; + if (solidCubePosition.x > maxSolidCubeX || solidCubePosition.x < minSolidCubeX) { + solidCubeMove = solidCubeMove * -1; + } + Overlays.editOverlay(solidCube, { position: solidCubePosition } ); } Script.willSendVisualDataCallback.connect(update); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4da0a35279..521757abab 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2842,6 +2842,9 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { // give external parties a change to hook in emit renderingInWorldInterface(); + + // render JS/scriptable overlays + _overlays.render3D(); } } @@ -2988,7 +2991,7 @@ void Application::displayOverlay() { _pieMenu.render(); } - _overlays.render(); + _overlays.render2D(); glPopMatrix(); } diff --git a/interface/src/ui/Cube3DOverlay.cpp b/interface/src/ui/Cube3DOverlay.cpp new file mode 100644 index 0000000000..dda1f64295 --- /dev/null +++ b/interface/src/ui/Cube3DOverlay.cpp @@ -0,0 +1,98 @@ +// +// Cube3DOverlay.cpp +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include + +#include "Cube3DOverlay.h" +#include "TextRenderer.h" + +const glm::vec3 DEFAULT_POSITION = glm::vec3(0.0f, 0.0f, 0.0f); +const float DEFAULT_SIZE = 1.0f; +const float DEFAULT_LINE_WIDTH = 1.0f; +const bool DEFAULT_isSolid = false; + +Cube3DOverlay::Cube3DOverlay() : + _position(DEFAULT_POSITION), + _size(DEFAULT_SIZE), + _lineWidth(DEFAULT_LINE_WIDTH), + _isSolid(DEFAULT_isSolid) +{ +} + +Cube3DOverlay::~Cube3DOverlay() { +} + +void Cube3DOverlay::render() { + if (!_visible) { + return; // do nothing if we're not visible + } + + const float MAX_COLOR = 255; + glColor4f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, _alpha); + + + glDisable(GL_LIGHTING); + glPushMatrix(); + glTranslatef(_position.x + _size * 0.5f, + _position.y + _size * 0.5f, + _position.z + _size * 0.5f); + glLineWidth(_lineWidth); + if (_isSolid) { + glutSolidCube(_size); + } else { + glutWireCube(_size); + } + glPopMatrix(); + +} + +void Cube3DOverlay::setProperties(const QScriptValue& properties) { + Overlay::setProperties(properties); + + QScriptValue position = properties.property("position"); + if (position.isValid()) { + QScriptValue x = position.property("x"); + QScriptValue y = position.property("y"); + QScriptValue z = position.property("z"); + if (x.isValid() && y.isValid() && z.isValid()) { + glm::vec3 newPosition; + newPosition.x = x.toVariant().toFloat(); + newPosition.y = y.toVariant().toFloat(); + newPosition.z = z.toVariant().toFloat(); + setPosition(newPosition); + } + } + + if (properties.property("size").isValid()) { + setSize(properties.property("size").toVariant().toFloat()); + } + + if (properties.property("lineWidth").isValid()) { + setLineWidth(properties.property("lineWidth").toVariant().toFloat()); + } + + if (properties.property("isSolid").isValid()) { + setIsSolid(properties.property("isSolid").toVariant().toBool()); + } + if (properties.property("isWire").isValid()) { + setIsSolid(!properties.property("isWire").toVariant().toBool()); + } + if (properties.property("solid").isValid()) { + setIsSolid(properties.property("solid").toVariant().toBool()); + } + if (properties.property("wire").isValid()) { + setIsSolid(!properties.property("wire").toVariant().toBool()); + } + + +} + + diff --git a/interface/src/ui/Cube3DOverlay.h b/interface/src/ui/Cube3DOverlay.h new file mode 100644 index 0000000000..ad6ba92d02 --- /dev/null +++ b/interface/src/ui/Cube3DOverlay.h @@ -0,0 +1,57 @@ +// +// Cube3DOverlay.h +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__Cube3DOverlay__ +#define __interface__Cube3DOverlay__ + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Overlay.h" + +class Cube3DOverlay : public Overlay { + Q_OBJECT + +public: + Cube3DOverlay(); + ~Cube3DOverlay(); + virtual void render(); + + // getters + const glm::vec3& getPosition() const { return _position; } + float getSize() const { return _size; } + float getLineWidth() const { return _lineWidth; } + bool getIsSolid() const { return _isSolid; } + + // setters + void setPosition(const glm::vec3& position) { _position = position; } + void setSize(float size) { _size = size; } + void setLineWidth(float lineWidth) { _lineWidth = lineWidth; } + void setIsSolid(bool isSolid) { _isSolid = isSolid; } + + virtual void setProperties(const QScriptValue& properties); + +private: + glm::vec3 _position; + float _size; + float _lineWidth; + bool _isSolid; +}; + + +#endif /* defined(__interface__Cube3DOverlay__) */ diff --git a/interface/src/ui/ImageOverlay.cpp b/interface/src/ui/ImageOverlay.cpp index d048e7a27e..178383749b 100644 --- a/interface/src/ui/ImageOverlay.cpp +++ b/interface/src/ui/ImageOverlay.cpp @@ -61,7 +61,7 @@ void ImageOverlay::render() { glBindTexture(GL_TEXTURE_2D, _textureID); } const float MAX_COLOR = 255; - glColor4f(_backgroundColor.red / MAX_COLOR, _backgroundColor.green / MAX_COLOR, _backgroundColor.blue / MAX_COLOR, _alpha); + glColor4f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, _alpha); float imageWidth = _textureImage.width(); float imageHeight = _textureImage.height(); @@ -107,7 +107,7 @@ void ImageOverlay::render() { } void ImageOverlay::setProperties(const QScriptValue& properties) { - Overlay::setProperties(properties); + Overlay2D::setProperties(properties); QScriptValue subImageBounds = properties.property("subImage"); if (subImageBounds.isValid()) { diff --git a/interface/src/ui/ImageOverlay.h b/interface/src/ui/ImageOverlay.h index be7d8cf5d8..77cac3b3c6 100644 --- a/interface/src/ui/ImageOverlay.h +++ b/interface/src/ui/ImageOverlay.h @@ -23,8 +23,9 @@ #include #include "Overlay.h" +#include "Overlay2D.h" -class ImageOverlay : public Overlay { +class ImageOverlay : public Overlay2D { Q_OBJECT public: diff --git a/interface/src/ui/Overlay.cpp b/interface/src/ui/Overlay.cpp index 4660fd6ada..c6b3902fd6 100644 --- a/interface/src/ui/Overlay.cpp +++ b/interface/src/ui/Overlay.cpp @@ -19,7 +19,7 @@ Overlay::Overlay() : _parent(NULL), _alpha(DEFAULT_ALPHA), - _backgroundColor(DEFAULT_BACKGROUND_COLOR), + _color(DEFAULT_BACKGROUND_COLOR), _visible(true) { } @@ -69,15 +69,15 @@ void Overlay::setProperties(const QScriptValue& properties) { //qDebug() << "set bounds to " << getBounds(); } - QScriptValue color = properties.property("backgroundColor"); + QScriptValue color = properties.property("color"); if (color.isValid()) { QScriptValue red = color.property("red"); QScriptValue green = color.property("green"); QScriptValue blue = color.property("blue"); if (red.isValid() && green.isValid() && blue.isValid()) { - _backgroundColor.red = red.toVariant().toInt(); - _backgroundColor.green = green.toVariant().toInt(); - _backgroundColor.blue = blue.toVariant().toInt(); + _color.red = red.toVariant().toInt(); + _color.green = green.toVariant().toInt(); + _color.blue = blue.toVariant().toInt(); } } diff --git a/interface/src/ui/Overlay.h b/interface/src/ui/Overlay.h index ce63fdaba5..4f1cdc9edb 100644 --- a/interface/src/ui/Overlay.h +++ b/interface/src/ui/Overlay.h @@ -37,7 +37,7 @@ public: int getWidth() const { return _bounds.width(); } int getHeight() const { return _bounds.height(); } const QRect& getBounds() const { return _bounds; } - const xColor& getBackgroundColor() const { return _backgroundColor; } + const xColor& getColor() const { return _color; } float getAlpha() const { return _alpha; } // setters @@ -47,7 +47,7 @@ public: void setWidth(int width) { _bounds.setWidth(width); } void setHeight(int height) { _bounds.setHeight(height); } void setBounds(const QRect& bounds) { _bounds = bounds; } - void setBackgroundColor(const xColor& color) { _backgroundColor = color; } + void setColor(const xColor& color) { _color = color; } void setAlpha(float alpha) { _alpha = alpha; } virtual void setProperties(const QScriptValue& properties); @@ -56,7 +56,7 @@ protected: QGLWidget* _parent; QRect _bounds; // where on the screen to draw float _alpha; - xColor _backgroundColor; + xColor _color; bool _visible; // should the overlay be drawn at all }; diff --git a/interface/src/ui/Overlay2D.cpp b/interface/src/ui/Overlay2D.cpp new file mode 100644 index 0000000000..0c459811c4 --- /dev/null +++ b/interface/src/ui/Overlay2D.cpp @@ -0,0 +1,63 @@ +// +// Overlay2D.cpp +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include +#include +#include + +#include "Overlay2D.h" + + +Overlay2D::Overlay2D() { +} + +Overlay2D::~Overlay2D() { +} + +void Overlay2D::setProperties(const QScriptValue& properties) { + Overlay::setProperties(properties); + + QScriptValue bounds = properties.property("bounds"); + if (bounds.isValid()) { + QRect boundsRect; + boundsRect.setX(bounds.property("x").toVariant().toInt()); + boundsRect.setY(bounds.property("y").toVariant().toInt()); + boundsRect.setWidth(bounds.property("width").toVariant().toInt()); + boundsRect.setHeight(bounds.property("height").toVariant().toInt()); + setBounds(boundsRect); + } else { + QRect oldBounds = getBounds(); + QRect newBounds = oldBounds; + + if (properties.property("x").isValid()) { + newBounds.setX(properties.property("x").toVariant().toInt()); + } else { + newBounds.setX(oldBounds.x()); + } + if (properties.property("y").isValid()) { + newBounds.setY(properties.property("y").toVariant().toInt()); + } else { + newBounds.setY(oldBounds.y()); + } + if (properties.property("width").isValid()) { + newBounds.setWidth(properties.property("width").toVariant().toInt()); + } else { + newBounds.setWidth(oldBounds.width()); + } + if (properties.property("height").isValid()) { + newBounds.setHeight(properties.property("height").toVariant().toInt()); + } else { + newBounds.setHeight(oldBounds.height()); + } + setBounds(newBounds); + //qDebug() << "set bounds to " << getBounds(); + } +} diff --git a/interface/src/ui/Overlay2D.h b/interface/src/ui/Overlay2D.h new file mode 100644 index 0000000000..3da8f8bca4 --- /dev/null +++ b/interface/src/ui/Overlay2D.h @@ -0,0 +1,51 @@ +// +// Overlay2D.h +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__Overlay2D__ +#define __interface__Overlay2D__ + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include +#include +#include + +#include // for xColor + +#include "Overlay.h" + +class Overlay2D : public Overlay { + Q_OBJECT + +public: + Overlay2D(); + ~Overlay2D(); + + // getters + int getX() const { return _bounds.x(); } + int getY() const { return _bounds.y(); } + int getWidth() const { return _bounds.width(); } + int getHeight() const { return _bounds.height(); } + const QRect& getBounds() const { return _bounds; } + + // setters + void setX(int x) { _bounds.setX(x); } + void setY(int y) { _bounds.setY(y); } + void setWidth(int width) { _bounds.setWidth(width); } + void setHeight(int height) { _bounds.setHeight(height); } + void setBounds(const QRect& bounds) { _bounds = bounds; } + + virtual void setProperties(const QScriptValue& properties); + +protected: + QRect _bounds; // where on the screen to draw +}; + + +#endif /* defined(__interface__Overlay2D__) */ diff --git a/interface/src/ui/Overlays.cpp b/interface/src/ui/Overlays.cpp index 2f31e7e8c7..b731d46b16 100644 --- a/interface/src/ui/Overlays.cpp +++ b/interface/src/ui/Overlays.cpp @@ -6,8 +6,9 @@ // -#include "Overlays.h" +#include "Cube3DOverlay.h" #include "ImageOverlay.h" +#include "Overlays.h" #include "TextOverlay.h" @@ -23,8 +24,14 @@ void Overlays::init(QGLWidget* parent) { _parent = parent; } -void Overlays::render() { - foreach(Overlay* thisOverlay, _overlays) { +void Overlays::render2D() { + foreach(Overlay* thisOverlay, _overlays2D) { + thisOverlay->render(); + } +} + +void Overlays::render3D() { + foreach(Overlay* thisOverlay, _overlays3D) { thisOverlay->render(); } } @@ -32,21 +39,36 @@ void Overlays::render() { // TODO: make multi-threaded safe unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) { unsigned int thisID = 0; + bool created = false; + bool is3D = false; + Overlay* thisOverlay = NULL; if (type == "image") { - thisID = _nextOverlayID; - _nextOverlayID++; - ImageOverlay* thisOverlay = new ImageOverlay(); + thisOverlay = new ImageOverlay(); thisOverlay->init(_parent); thisOverlay->setProperties(properties); - _overlays[thisID] = thisOverlay; + created = true; } else if (type == "text") { - thisID = _nextOverlayID; - _nextOverlayID++; - TextOverlay* thisOverlay = new TextOverlay(); + thisOverlay = new TextOverlay(); thisOverlay->init(_parent); thisOverlay->setProperties(properties); - _overlays[thisID] = thisOverlay; + created = true; + } else if (type == "cube") { + thisOverlay = new Cube3DOverlay(); + thisOverlay->init(_parent); + thisOverlay->setProperties(properties); + created = true; + is3D = true; + } + + if (created) { + thisID = _nextOverlayID; + _nextOverlayID++; + if (is3D) { + _overlays3D[thisID] = thisOverlay; + } else { + _overlays2D[thisID] = thisOverlay; + } } return thisID; @@ -54,23 +76,30 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope // TODO: make multi-threaded safe bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { - if (!_overlays.contains(id)) { - return false; + Overlay* thisOverlay = NULL; + if (_overlays2D.contains(id)) { + thisOverlay = _overlays2D[id]; + } else if (_overlays3D.contains(id)) { + thisOverlay = _overlays3D[id]; } - Overlay* thisOverlay = _overlays[id]; - thisOverlay->setProperties(properties); - return true; + if (thisOverlay) { + thisOverlay->setProperties(properties); + return true; + } + return false; } // TODO: make multi-threaded safe void Overlays::deleteOverlay(unsigned int id) { - if (_overlays.contains(id)) { - _overlays.erase(_overlays.find(id)); + if (_overlays2D.contains(id)) { + _overlays2D.erase(_overlays2D.find(id)); + } else if (_overlays3D.contains(id)) { + _overlays3D.erase(_overlays3D.find(id)); } } unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { - QMapIterator i(_overlays); + QMapIterator i(_overlays2D); i.toBack(); while (i.hasPrevious()) { i.previous(); diff --git a/interface/src/ui/Overlays.h b/interface/src/ui/Overlays.h index e39949d2c9..cfd84fd44b 100644 --- a/interface/src/ui/Overlays.h +++ b/interface/src/ui/Overlays.h @@ -18,7 +18,8 @@ public: Overlays(); ~Overlays(); void init(QGLWidget* parent); - void render(); + void render3D(); + void render2D(); public slots: /// adds an overlay with the specific properties @@ -35,7 +36,8 @@ public slots: unsigned int getOverlayAtPoint(const glm::vec2& point); private: - QMap _overlays; + QMap _overlays2D; + QMap _overlays3D; static unsigned int _nextOverlayID; QGLWidget* _parent; }; diff --git a/interface/src/ui/TextOverlay.cpp b/interface/src/ui/TextOverlay.cpp index 51b57c2f3f..edaec6849a 100644 --- a/interface/src/ui/TextOverlay.cpp +++ b/interface/src/ui/TextOverlay.cpp @@ -29,7 +29,7 @@ void TextOverlay::render() { } const float MAX_COLOR = 255; - glColor4f(_backgroundColor.red / MAX_COLOR, _backgroundColor.green / MAX_COLOR, _backgroundColor.blue / MAX_COLOR, _alpha); + glColor4f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, _alpha); glBegin(GL_QUADS); glVertex2f(_bounds.left(), _bounds.top()); @@ -63,7 +63,7 @@ void TextOverlay::render() { } void TextOverlay::setProperties(const QScriptValue& properties) { - Overlay::setProperties(properties); + Overlay2D::setProperties(properties); QScriptValue text = properties.property("text"); if (text.isValid()) { diff --git a/interface/src/ui/TextOverlay.h b/interface/src/ui/TextOverlay.h index 323116eccf..d565aeb70d 100644 --- a/interface/src/ui/TextOverlay.h +++ b/interface/src/ui/TextOverlay.h @@ -23,10 +23,11 @@ #include #include "Overlay.h" +#include "Overlay2D.h" const int DEFAULT_MARGIN = 10; -class TextOverlay : public Overlay { +class TextOverlay : public Overlay2D { Q_OBJECT public: From 7c350b3acbda71c7dcb39cb7ae3e6c6c074971da Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 16 Feb 2014 12:30:15 -0800 Subject: [PATCH 11/14] add 3D sphere overlay support --- examples/overlaysExample.js | 22 +++++++++ interface/src/ui/Base3DOverlay.cpp | 70 ++++++++++++++++++++++++++++ interface/src/ui/Base3DOverlay.h | 56 ++++++++++++++++++++++ interface/src/ui/Cube3DOverlay.cpp | 56 +--------------------- interface/src/ui/Cube3DOverlay.h | 24 +--------- interface/src/ui/Overlays.cpp | 7 +++ interface/src/ui/Sphere3DOverlay.cpp | 45 ++++++++++++++++++ interface/src/ui/Sphere3DOverlay.h | 37 +++++++++++++++ 8 files changed, 240 insertions(+), 77 deletions(-) create mode 100644 interface/src/ui/Base3DOverlay.cpp create mode 100644 interface/src/ui/Base3DOverlay.h create mode 100644 interface/src/ui/Sphere3DOverlay.cpp create mode 100644 interface/src/ui/Sphere3DOverlay.h diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index 501f9a248e..01eff71188 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -117,6 +117,20 @@ var solidCube = Overlays.addOverlay("cube", { solid: true }); +var spherePosition = { x: 5, y: 5, z: 5 }; +var sphereSize = 1; +var minSphereSize = 0.5; +var maxSphereSize = 10; +var sphereSizeChange = 0.05; + +var sphere = Overlays.addOverlay("sphere", { + position: spherePosition, + size: sphereSize, + color: { red: 0, green: 0, blue: 255}, + alpha: 1, + solid: false + }); + function scriptEnding() { Overlays.deleteOverlay(toolA); @@ -151,12 +165,20 @@ function update() { } Overlays.editOverlay(cube, { position: cubePosition } ); + // move our solid 3D cube solidCubePosition.x += solidCubeMove; solidCubePosition.z += solidCubeMove; if (solidCubePosition.x > maxSolidCubeX || solidCubePosition.x < minSolidCubeX) { solidCubeMove = solidCubeMove * -1; } Overlays.editOverlay(solidCube, { position: solidCubePosition } ); + + // adjust our 3D sphere + sphereSize += sphereSizeChange; + if (sphereSize > maxSphereSize || sphereSize < minSphereSize) { + sphereSizeChange = sphereSizeChange * -1; + } + Overlays.editOverlay(sphere, { size: sphereSize, solid: (sphereSizeChange < 0) } ); } Script.willSendVisualDataCallback.connect(update); diff --git a/interface/src/ui/Base3DOverlay.cpp b/interface/src/ui/Base3DOverlay.cpp new file mode 100644 index 0000000000..23b02a6ac6 --- /dev/null +++ b/interface/src/ui/Base3DOverlay.cpp @@ -0,0 +1,70 @@ +// +// Base3DOverlay.cpp +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include + +#include "Base3DOverlay.h" +#include "TextRenderer.h" + +const glm::vec3 DEFAULT_POSITION = glm::vec3(0.0f, 0.0f, 0.0f); +const float DEFAULT_SIZE = 1.0f; +const float DEFAULT_LINE_WIDTH = 1.0f; +const bool DEFAULT_isSolid = false; + +Base3DOverlay::Base3DOverlay() : + _position(DEFAULT_POSITION), + _size(DEFAULT_SIZE), + _lineWidth(DEFAULT_LINE_WIDTH), + _isSolid(DEFAULT_isSolid) +{ +} + +Base3DOverlay::~Base3DOverlay() { +} + +void Base3DOverlay::setProperties(const QScriptValue& properties) { + Overlay::setProperties(properties); + + QScriptValue position = properties.property("position"); + if (position.isValid()) { + QScriptValue x = position.property("x"); + QScriptValue y = position.property("y"); + QScriptValue z = position.property("z"); + if (x.isValid() && y.isValid() && z.isValid()) { + glm::vec3 newPosition; + newPosition.x = x.toVariant().toFloat(); + newPosition.y = y.toVariant().toFloat(); + newPosition.z = z.toVariant().toFloat(); + setPosition(newPosition); + } + } + + if (properties.property("size").isValid()) { + setSize(properties.property("size").toVariant().toFloat()); + } + + if (properties.property("lineWidth").isValid()) { + setLineWidth(properties.property("lineWidth").toVariant().toFloat()); + } + + if (properties.property("isSolid").isValid()) { + setIsSolid(properties.property("isSolid").toVariant().toBool()); + } + if (properties.property("isWire").isValid()) { + setIsSolid(!properties.property("isWire").toVariant().toBool()); + } + if (properties.property("solid").isValid()) { + setIsSolid(properties.property("solid").toVariant().toBool()); + } + if (properties.property("wire").isValid()) { + setIsSolid(!properties.property("wire").toVariant().toBool()); + } +} diff --git a/interface/src/ui/Base3DOverlay.h b/interface/src/ui/Base3DOverlay.h new file mode 100644 index 0000000000..264ca74326 --- /dev/null +++ b/interface/src/ui/Base3DOverlay.h @@ -0,0 +1,56 @@ +// +// Base3DOverlay.h +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__Base3DOverlay__ +#define __interface__Base3DOverlay__ + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Overlay.h" + +class Base3DOverlay : public Overlay { + Q_OBJECT + +public: + Base3DOverlay(); + ~Base3DOverlay(); + + // getters + const glm::vec3& getPosition() const { return _position; } + float getSize() const { return _size; } + float getLineWidth() const { return _lineWidth; } + bool getIsSolid() const { return _isSolid; } + + // setters + void setPosition(const glm::vec3& position) { _position = position; } + void setSize(float size) { _size = size; } + void setLineWidth(float lineWidth) { _lineWidth = lineWidth; } + void setIsSolid(bool isSolid) { _isSolid = isSolid; } + + virtual void setProperties(const QScriptValue& properties); + +protected: + glm::vec3 _position; + float _size; + float _lineWidth; + bool _isSolid; +}; + + +#endif /* defined(__interface__Base3DOverlay__) */ diff --git a/interface/src/ui/Cube3DOverlay.cpp b/interface/src/ui/Cube3DOverlay.cpp index dda1f64295..992a18e451 100644 --- a/interface/src/ui/Cube3DOverlay.cpp +++ b/interface/src/ui/Cube3DOverlay.cpp @@ -12,19 +12,8 @@ #include #include "Cube3DOverlay.h" -#include "TextRenderer.h" -const glm::vec3 DEFAULT_POSITION = glm::vec3(0.0f, 0.0f, 0.0f); -const float DEFAULT_SIZE = 1.0f; -const float DEFAULT_LINE_WIDTH = 1.0f; -const bool DEFAULT_isSolid = false; - -Cube3DOverlay::Cube3DOverlay() : - _position(DEFAULT_POSITION), - _size(DEFAULT_SIZE), - _lineWidth(DEFAULT_LINE_WIDTH), - _isSolid(DEFAULT_isSolid) -{ +Cube3DOverlay::Cube3DOverlay() { } Cube3DOverlay::~Cube3DOverlay() { @@ -53,46 +42,3 @@ void Cube3DOverlay::render() { glPopMatrix(); } - -void Cube3DOverlay::setProperties(const QScriptValue& properties) { - Overlay::setProperties(properties); - - QScriptValue position = properties.property("position"); - if (position.isValid()) { - QScriptValue x = position.property("x"); - QScriptValue y = position.property("y"); - QScriptValue z = position.property("z"); - if (x.isValid() && y.isValid() && z.isValid()) { - glm::vec3 newPosition; - newPosition.x = x.toVariant().toFloat(); - newPosition.y = y.toVariant().toFloat(); - newPosition.z = z.toVariant().toFloat(); - setPosition(newPosition); - } - } - - if (properties.property("size").isValid()) { - setSize(properties.property("size").toVariant().toFloat()); - } - - if (properties.property("lineWidth").isValid()) { - setLineWidth(properties.property("lineWidth").toVariant().toFloat()); - } - - if (properties.property("isSolid").isValid()) { - setIsSolid(properties.property("isSolid").toVariant().toBool()); - } - if (properties.property("isWire").isValid()) { - setIsSolid(!properties.property("isWire").toVariant().toBool()); - } - if (properties.property("solid").isValid()) { - setIsSolid(properties.property("solid").toVariant().toBool()); - } - if (properties.property("wire").isValid()) { - setIsSolid(!properties.property("wire").toVariant().toBool()); - } - - -} - - diff --git a/interface/src/ui/Cube3DOverlay.h b/interface/src/ui/Cube3DOverlay.h index ad6ba92d02..0033b9c43f 100644 --- a/interface/src/ui/Cube3DOverlay.h +++ b/interface/src/ui/Cube3DOverlay.h @@ -22,35 +22,15 @@ #include -#include "Overlay.h" +#include "Base3DOverlay.h" -class Cube3DOverlay : public Overlay { +class Cube3DOverlay : public Base3DOverlay { Q_OBJECT public: Cube3DOverlay(); ~Cube3DOverlay(); virtual void render(); - - // getters - const glm::vec3& getPosition() const { return _position; } - float getSize() const { return _size; } - float getLineWidth() const { return _lineWidth; } - bool getIsSolid() const { return _isSolid; } - - // setters - void setPosition(const glm::vec3& position) { _position = position; } - void setSize(float size) { _size = size; } - void setLineWidth(float lineWidth) { _lineWidth = lineWidth; } - void setIsSolid(bool isSolid) { _isSolid = isSolid; } - - virtual void setProperties(const QScriptValue& properties); - -private: - glm::vec3 _position; - float _size; - float _lineWidth; - bool _isSolid; }; diff --git a/interface/src/ui/Overlays.cpp b/interface/src/ui/Overlays.cpp index b731d46b16..902e850fc6 100644 --- a/interface/src/ui/Overlays.cpp +++ b/interface/src/ui/Overlays.cpp @@ -9,6 +9,7 @@ #include "Cube3DOverlay.h" #include "ImageOverlay.h" #include "Overlays.h" +#include "Sphere3DOverlay.h" #include "TextOverlay.h" @@ -59,6 +60,12 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope thisOverlay->setProperties(properties); created = true; is3D = true; + } else if (type == "sphere") { + thisOverlay = new Sphere3DOverlay(); + thisOverlay->init(_parent); + thisOverlay->setProperties(properties); + created = true; + is3D = true; } if (created) { diff --git a/interface/src/ui/Sphere3DOverlay.cpp b/interface/src/ui/Sphere3DOverlay.cpp new file mode 100644 index 0000000000..7fded5bedb --- /dev/null +++ b/interface/src/ui/Sphere3DOverlay.cpp @@ -0,0 +1,45 @@ +// +// Sphere3DOverlay.cpp +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include + +#include "Sphere3DOverlay.h" + +Sphere3DOverlay::Sphere3DOverlay() { +} + +Sphere3DOverlay::~Sphere3DOverlay() { +} + +void Sphere3DOverlay::render() { + if (!_visible) { + return; // do nothing if we're not visible + } + + const float MAX_COLOR = 255; + glColor4f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, _alpha); + + + glDisable(GL_LIGHTING); + glPushMatrix(); + glTranslatef(_position.x + _size * 0.5f, + _position.y + _size * 0.5f, + _position.z + _size * 0.5f); + glLineWidth(_lineWidth); + const int slices = 15; + if (_isSolid) { + glutSolidSphere(_size, slices, slices); + } else { + glutWireSphere(_size, slices, slices); + } + glPopMatrix(); + +} diff --git a/interface/src/ui/Sphere3DOverlay.h b/interface/src/ui/Sphere3DOverlay.h new file mode 100644 index 0000000000..03210866e8 --- /dev/null +++ b/interface/src/ui/Sphere3DOverlay.h @@ -0,0 +1,37 @@ +// +// Sphere3DOverlay.h +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__Sphere3DOverlay__ +#define __interface__Sphere3DOverlay__ + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Base3DOverlay.h" + +class Sphere3DOverlay : public Base3DOverlay { + Q_OBJECT + +public: + Sphere3DOverlay(); + ~Sphere3DOverlay(); + virtual void render(); +}; + + +#endif /* defined(__interface__Sphere3DOverlay__) */ From 6b410253d4bb1f66c6ece7d177695b91c6989183 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 16 Feb 2014 12:42:26 -0800 Subject: [PATCH 12/14] update comments in example --- examples/overlaysExample.js | 54 ++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index 01eff71188..217d3f40f5 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -9,6 +9,11 @@ // // + +// The "Swatches" example of this script will create 9 different image overlays, that use the color feature to +// display different colors as color swatches. The overlays can be clicked on, to change the "selectedSwatch" variable +// and update the image used for the overlay so that it appears to have a selected indicator. +// These are our colors... var swatchColors = new Array(); swatchColors[0] = { red: 255, green: 0, blue: 0}; swatchColors[1] = { red: 0, green: 255, blue: 0}; @@ -20,11 +25,17 @@ swatchColors[6] = { red: 128, green: 128, blue: 128}; swatchColors[7] = { red: 128, green: 0, blue: 0}; swatchColors[8] = { red: 0, green: 240, blue: 240}; -var swatches = new Array(); -var numberOfSwatches = 9; +// The location of the placement of these overlays var swatchesX = 100; var swatchesY = 200; + +// These will be our "overlay IDs" +var swatches = new Array(); +var numberOfSwatches = 9; var selectedSwatch = 0; + +// create the overlays, position them in a row, set their colors, and for the selected one, use a different source image +// location so that it displays the "selected" marker for (s = 0; s < numberOfSwatches; s++) { var imageFromX = 12 + (s * 27); var imageFromY = 0; @@ -44,6 +55,7 @@ for (s = 0; s < numberOfSwatches; s++) { }); } +// This will create a text overlay that when you click on it, the text will change var text = Overlays.addOverlay("text", { x: 200, y: 100, @@ -56,6 +68,7 @@ var text = Overlays.addOverlay("text", { text: "Here is some text.\nAnd a second line." }); +// This will create an image overlay, which starts out as invisible var toolA = Overlays.addOverlay("image", { x: 100, y: 100, @@ -67,6 +80,8 @@ var toolA = Overlays.addOverlay("image", { visible: false }); +// This will create a couple of image overlays that make a "slider", we will demonstrate how to trap mouse messages to +// move the slider var slider = Overlays.addOverlay("image", { // alternate form of expressing bounds bounds: { x: 100, y: 300, width: 158, height: 35}, @@ -75,6 +90,7 @@ var slider = Overlays.addOverlay("image", { alpha: 1 }); +// This is the thumb of our slider var minThumbX = 130; var maxThumbX = minThumbX + 65; var thumbX = (minThumbX + maxThumbX) / 2; @@ -89,17 +105,13 @@ var thumb = Overlays.addOverlay("image", { }); +// We will also demonstrate some 3D overlays. We will create a couple of cubes, spheres, and lines // our 3D cube that moves around... var cubePosition = { x: 2, y: 0, z: 2 }; var cubeSize = 5; var cubeMove = 0.1; var minCubeX = 1; var maxCubeX = 20; -var solidCubePosition = { x: 0, y: 5, z: 0 }; -var solidCubeSize = 2; -var minSolidCubeX = 0; -var maxSolidCubeX = 10; -var solidCubeMove = 0.05; var cube = Overlays.addOverlay("cube", { position: cubePosition, @@ -109,6 +121,11 @@ var cube = Overlays.addOverlay("cube", { solid: false }); +var solidCubePosition = { x: 0, y: 5, z: 0 }; +var solidCubeSize = 2; +var minSolidCubeX = 0; +var maxSolidCubeX = 10; +var solidCubeMove = 0.05; var solidCube = Overlays.addOverlay("cube", { position: solidCubePosition, size: solidCubeSize, @@ -132,6 +149,7 @@ var sphere = Overlays.addOverlay("sphere", { }); +// When our script shuts down, we should clean up all of our overlays function scriptEnding() { Overlays.deleteOverlay(toolA); for (s = 0; s < numberOfSwatches; s++) { @@ -140,14 +158,21 @@ function scriptEnding() { Overlays.deleteOverlay(thumb); Overlays.deleteOverlay(slider); Overlays.deleteOverlay(text); + Overlays.deleteOverlay(cube); + Overlays.deleteOverlay(solidCube); + Overlays.deleteOverlay(sphere); } Script.scriptEnding.connect(scriptEnding); var toolAVisible = false; var count = 0; + +// Our update() function is called at approximately 60fps, and we will use it to animate our various overlays function update() { count++; + + // every second or so, toggle the visibility our our blinking tool if (count % 60 == 0) { if (toolAVisible) { toolAVisible = false; @@ -183,6 +208,7 @@ function update() { Script.willSendVisualDataCallback.connect(update); +// The slider is handled in the mouse event callbacks. var movingSlider = false; var thumbClickOffsetX = 0; function mouseMoveEvent(event) { @@ -197,16 +223,24 @@ function mouseMoveEvent(event) { Overlays.editOverlay(thumb, { x: newThumbX } ); } } + +// we also handle click detection in our mousePressEvent() function mousePressEvent(event) { var clickedText = false; var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + + // If the user clicked on the thumb, handle the slider logic if (clickedOverlay == thumb) { movingSlider = true; thumbClickOffsetX = event.x - thumbX; - } else if (clickedOverlay == text) { + + } else if (clickedOverlay == text) { // if the user clicked on the text, update text with where you clicked + Overlays.editOverlay(text, { text: "you clicked here:\n " + event.x + "," + event.y } ); clickedText = true; - } else { + + } else { // if the user clicked on one of the color swatches, update the selectedSwatch + for (s = 0; s < numberOfSwatches; s++) { if (clickedOverlay == swatches[s]) { Overlays.editOverlay(swatches[selectedSwatch], { subImage: { y: 0 } } ); @@ -215,7 +249,7 @@ function mousePressEvent(event) { } } } - if (!clickedText) { + if (!clickedText) { // if you didn't click on the text, then update the text accordningly Overlays.editOverlay(text, { text: "you didn't click here" } ); } } From 78f4df912d84571a9c611ddf2504f18795e4ec84 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 16 Feb 2014 13:25:49 -0800 Subject: [PATCH 13/14] added 3D line overlay support --- examples/overlaysExample.js | 13 ++++++ interface/src/ui/Base3DOverlay.cpp | 35 ++++++---------- interface/src/ui/Base3DOverlay.h | 20 ---------- interface/src/ui/Cube3DOverlay.h | 18 +-------- interface/src/ui/Line3DOverlay.cpp | 60 ++++++++++++++++++++++++++++ interface/src/ui/Line3DOverlay.h | 34 ++++++++++++++++ interface/src/ui/Overlays.cpp | 7 ++++ interface/src/ui/Sphere3DOverlay.h | 18 +-------- interface/src/ui/Volume3DOverlay.cpp | 47 ++++++++++++++++++++++ interface/src/ui/Volume3DOverlay.h | 42 +++++++++++++++++++ 10 files changed, 220 insertions(+), 74 deletions(-) create mode 100644 interface/src/ui/Line3DOverlay.cpp create mode 100644 interface/src/ui/Line3DOverlay.h create mode 100644 interface/src/ui/Volume3DOverlay.cpp create mode 100644 interface/src/ui/Volume3DOverlay.h diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index 217d3f40f5..b57f82e7e9 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -148,6 +148,14 @@ var sphere = Overlays.addOverlay("sphere", { solid: false }); +var line3d = Overlays.addOverlay("line3d", { + position: { x: 0, y: 0, z:0 }, + end: { x: 10, y: 10, z:10 }, + color: { red: 0, green: 255, blue: 255}, + alpha: 1, + lineWidth: 5 + }); + // When our script shuts down, we should clean up all of our overlays function scriptEnding() { @@ -161,6 +169,7 @@ function scriptEnding() { Overlays.deleteOverlay(cube); Overlays.deleteOverlay(solidCube); Overlays.deleteOverlay(sphere); + Overlays.deleteOverlay(line3d); } Script.scriptEnding.connect(scriptEnding); @@ -204,6 +213,10 @@ function update() { sphereSizeChange = sphereSizeChange * -1; } Overlays.editOverlay(sphere, { size: sphereSize, solid: (sphereSizeChange < 0) } ); + + + // update our 3D line to go from origin to our avatar's position + Overlays.editOverlay(line3d, { end: MyAvatar.position } ); } Script.willSendVisualDataCallback.connect(update); diff --git a/interface/src/ui/Base3DOverlay.cpp b/interface/src/ui/Base3DOverlay.cpp index 23b02a6ac6..67e7ea25f2 100644 --- a/interface/src/ui/Base3DOverlay.cpp +++ b/interface/src/ui/Base3DOverlay.cpp @@ -15,15 +15,11 @@ #include "TextRenderer.h" const glm::vec3 DEFAULT_POSITION = glm::vec3(0.0f, 0.0f, 0.0f); -const float DEFAULT_SIZE = 1.0f; const float DEFAULT_LINE_WIDTH = 1.0f; -const bool DEFAULT_isSolid = false; Base3DOverlay::Base3DOverlay() : _position(DEFAULT_POSITION), - _size(DEFAULT_SIZE), - _lineWidth(DEFAULT_LINE_WIDTH), - _isSolid(DEFAULT_isSolid) + _lineWidth(DEFAULT_LINE_WIDTH) { } @@ -34,6 +30,18 @@ void Base3DOverlay::setProperties(const QScriptValue& properties) { Overlay::setProperties(properties); QScriptValue position = properties.property("position"); + + // if "position" property was not there, check to see if they included aliases: start, point, p1 + if (!position.isValid()) { + position = properties.property("start"); + if (!position.isValid()) { + position = properties.property("p1"); + if (!position.isValid()) { + position = properties.property("point"); + } + } + } + if (position.isValid()) { QScriptValue x = position.property("x"); QScriptValue y = position.property("y"); @@ -47,24 +55,7 @@ void Base3DOverlay::setProperties(const QScriptValue& properties) { } } - if (properties.property("size").isValid()) { - setSize(properties.property("size").toVariant().toFloat()); - } - if (properties.property("lineWidth").isValid()) { setLineWidth(properties.property("lineWidth").toVariant().toFloat()); } - - if (properties.property("isSolid").isValid()) { - setIsSolid(properties.property("isSolid").toVariant().toBool()); - } - if (properties.property("isWire").isValid()) { - setIsSolid(!properties.property("isWire").toVariant().toBool()); - } - if (properties.property("solid").isValid()) { - setIsSolid(properties.property("solid").toVariant().toBool()); - } - if (properties.property("wire").isValid()) { - setIsSolid(!properties.property("wire").toVariant().toBool()); - } } diff --git a/interface/src/ui/Base3DOverlay.h b/interface/src/ui/Base3DOverlay.h index 264ca74326..286193393c 100644 --- a/interface/src/ui/Base3DOverlay.h +++ b/interface/src/ui/Base3DOverlay.h @@ -8,20 +8,6 @@ #ifndef __interface__Base3DOverlay__ #define __interface__Base3DOverlay__ -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - #include "Overlay.h" class Base3DOverlay : public Overlay { @@ -33,23 +19,17 @@ public: // getters const glm::vec3& getPosition() const { return _position; } - float getSize() const { return _size; } float getLineWidth() const { return _lineWidth; } - bool getIsSolid() const { return _isSolid; } // setters void setPosition(const glm::vec3& position) { _position = position; } - void setSize(float size) { _size = size; } void setLineWidth(float lineWidth) { _lineWidth = lineWidth; } - void setIsSolid(bool isSolid) { _isSolid = isSolid; } virtual void setProperties(const QScriptValue& properties); protected: glm::vec3 _position; - float _size; float _lineWidth; - bool _isSolid; }; diff --git a/interface/src/ui/Cube3DOverlay.h b/interface/src/ui/Cube3DOverlay.h index 0033b9c43f..a1705d47d0 100644 --- a/interface/src/ui/Cube3DOverlay.h +++ b/interface/src/ui/Cube3DOverlay.h @@ -8,23 +8,9 @@ #ifndef __interface__Cube3DOverlay__ #define __interface__Cube3DOverlay__ -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" +#include "Volume3DOverlay.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "Base3DOverlay.h" - -class Cube3DOverlay : public Base3DOverlay { +class Cube3DOverlay : public Volume3DOverlay { Q_OBJECT public: diff --git a/interface/src/ui/Line3DOverlay.cpp b/interface/src/ui/Line3DOverlay.cpp new file mode 100644 index 0000000000..c357233329 --- /dev/null +++ b/interface/src/ui/Line3DOverlay.cpp @@ -0,0 +1,60 @@ +// +// Line3DOverlay.cpp +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include "Line3DOverlay.h" + + +Line3DOverlay::Line3DOverlay() { +} + +Line3DOverlay::~Line3DOverlay() { +} + +void Line3DOverlay::render() { + if (!_visible) { + return; // do nothing if we're not visible + } + + const float MAX_COLOR = 255; + glDisable(GL_LIGHTING); + glLineWidth(_lineWidth); + glColor4f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, _alpha); + + glBegin(GL_LINES); + glVertex3f(_position.x, _position.y, _position.z); + glVertex3f(_end.x, _end.y, _end.z); + glEnd(); + glEnable(GL_LIGHTING); +} + +void Line3DOverlay::setProperties(const QScriptValue& properties) { + Base3DOverlay::setProperties(properties); + + QScriptValue end = properties.property("end"); + // if "end" property was not there, check to see if they included aliases: endPoint, or p2 + if (!end.isValid()) { + end = properties.property("endPoint"); + if (!end.isValid()) { + end = properties.property("p2"); + } + } + if (end.isValid()) { + QScriptValue x = end.property("x"); + QScriptValue y = end.property("y"); + QScriptValue z = end.property("z"); + if (x.isValid() && y.isValid() && z.isValid()) { + glm::vec3 newEnd; + newEnd.x = x.toVariant().toFloat(); + newEnd.y = y.toVariant().toFloat(); + newEnd.z = z.toVariant().toFloat(); + setEnd(newEnd); + } + } +} diff --git a/interface/src/ui/Line3DOverlay.h b/interface/src/ui/Line3DOverlay.h new file mode 100644 index 0000000000..d52b639d59 --- /dev/null +++ b/interface/src/ui/Line3DOverlay.h @@ -0,0 +1,34 @@ +// +// Line3DOverlay.h +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__Line3DOverlay__ +#define __interface__Line3DOverlay__ + +#include "Base3DOverlay.h" + +class Line3DOverlay : public Base3DOverlay { + Q_OBJECT + +public: + Line3DOverlay(); + ~Line3DOverlay(); + virtual void render(); + + // getters + const glm::vec3& getEnd() const { return _end; } + + // setters + void setEnd(const glm::vec3& end) { _end = end; } + + virtual void setProperties(const QScriptValue& properties); + +protected: + glm::vec3 _end; +}; + + +#endif /* defined(__interface__Line3DOverlay__) */ diff --git a/interface/src/ui/Overlays.cpp b/interface/src/ui/Overlays.cpp index 902e850fc6..453367ca61 100644 --- a/interface/src/ui/Overlays.cpp +++ b/interface/src/ui/Overlays.cpp @@ -8,6 +8,7 @@ #include "Cube3DOverlay.h" #include "ImageOverlay.h" +#include "Line3DOverlay.h" #include "Overlays.h" #include "Sphere3DOverlay.h" #include "TextOverlay.h" @@ -66,6 +67,12 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope thisOverlay->setProperties(properties); created = true; is3D = true; + } else if (type == "line3d") { + thisOverlay = new Line3DOverlay(); + thisOverlay->init(_parent); + thisOverlay->setProperties(properties); + created = true; + is3D = true; } if (created) { diff --git a/interface/src/ui/Sphere3DOverlay.h b/interface/src/ui/Sphere3DOverlay.h index 03210866e8..58ed0d7776 100644 --- a/interface/src/ui/Sphere3DOverlay.h +++ b/interface/src/ui/Sphere3DOverlay.h @@ -8,23 +8,9 @@ #ifndef __interface__Sphere3DOverlay__ #define __interface__Sphere3DOverlay__ -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" +#include "Volume3DOverlay.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "Base3DOverlay.h" - -class Sphere3DOverlay : public Base3DOverlay { +class Sphere3DOverlay : public Volume3DOverlay { Q_OBJECT public: diff --git a/interface/src/ui/Volume3DOverlay.cpp b/interface/src/ui/Volume3DOverlay.cpp new file mode 100644 index 0000000000..dbc1582cc5 --- /dev/null +++ b/interface/src/ui/Volume3DOverlay.cpp @@ -0,0 +1,47 @@ +// +// Volume3DOverlay.cpp +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include + +#include "Volume3DOverlay.h" + +const float DEFAULT_SIZE = 1.0f; +const bool DEFAULT_IS_SOLID = false; + +Volume3DOverlay::Volume3DOverlay() : + _size(DEFAULT_SIZE), + _isSolid(DEFAULT_IS_SOLID) +{ +} + +Volume3DOverlay::~Volume3DOverlay() { +} + +void Volume3DOverlay::setProperties(const QScriptValue& properties) { + Base3DOverlay::setProperties(properties); + + if (properties.property("size").isValid()) { + setSize(properties.property("size").toVariant().toFloat()); + } + + if (properties.property("isSolid").isValid()) { + setIsSolid(properties.property("isSolid").toVariant().toBool()); + } + if (properties.property("isWire").isValid()) { + setIsSolid(!properties.property("isWire").toVariant().toBool()); + } + if (properties.property("solid").isValid()) { + setIsSolid(properties.property("solid").toVariant().toBool()); + } + if (properties.property("wire").isValid()) { + setIsSolid(!properties.property("wire").toVariant().toBool()); + } +} diff --git a/interface/src/ui/Volume3DOverlay.h b/interface/src/ui/Volume3DOverlay.h new file mode 100644 index 0000000000..8badbf2c33 --- /dev/null +++ b/interface/src/ui/Volume3DOverlay.h @@ -0,0 +1,42 @@ +// +// Volume3DOverlay.h +// interface +// +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__Volume3DOverlay__ +#define __interface__Volume3DOverlay__ + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include + +#include "Base3DOverlay.h" + +class Volume3DOverlay : public Base3DOverlay { + Q_OBJECT + +public: + Volume3DOverlay(); + ~Volume3DOverlay(); + + // getters + float getSize() const { return _size; } + bool getIsSolid() const { return _isSolid; } + + // setters + void setSize(float size) { _size = size; } + void setIsSolid(bool isSolid) { _isSolid = isSolid; } + + virtual void setProperties(const QScriptValue& properties); + +protected: + float _size; + bool _isSolid; +}; + + +#endif /* defined(__interface__Volume3DOverlay__) */ From d101f19e40d98c2f4c7f9f212e2048bc86b23a11 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 16 Feb 2014 13:39:01 -0800 Subject: [PATCH 14/14] removed bounds properties from Overlay so it only lives in Overlay2D --- interface/src/ui/Overlay.cpp | 36 ----------------------------------- interface/src/ui/Overlay.h | 11 ----------- interface/src/ui/Overlays.cpp | 2 +- 3 files changed, 1 insertion(+), 48 deletions(-) diff --git a/interface/src/ui/Overlay.cpp b/interface/src/ui/Overlay.cpp index c6b3902fd6..40da2253f4 100644 --- a/interface/src/ui/Overlay.cpp +++ b/interface/src/ui/Overlay.cpp @@ -33,42 +33,6 @@ Overlay::~Overlay() { } void Overlay::setProperties(const QScriptValue& properties) { - QScriptValue bounds = properties.property("bounds"); - if (bounds.isValid()) { - QRect boundsRect; - boundsRect.setX(bounds.property("x").toVariant().toInt()); - boundsRect.setY(bounds.property("y").toVariant().toInt()); - boundsRect.setWidth(bounds.property("width").toVariant().toInt()); - boundsRect.setHeight(bounds.property("height").toVariant().toInt()); - setBounds(boundsRect); - } else { - QRect oldBounds = getBounds(); - QRect newBounds = oldBounds; - - if (properties.property("x").isValid()) { - newBounds.setX(properties.property("x").toVariant().toInt()); - } else { - newBounds.setX(oldBounds.x()); - } - if (properties.property("y").isValid()) { - newBounds.setY(properties.property("y").toVariant().toInt()); - } else { - newBounds.setY(oldBounds.y()); - } - if (properties.property("width").isValid()) { - newBounds.setWidth(properties.property("width").toVariant().toInt()); - } else { - newBounds.setWidth(oldBounds.width()); - } - if (properties.property("height").isValid()) { - newBounds.setHeight(properties.property("height").toVariant().toInt()); - } else { - newBounds.setHeight(oldBounds.height()); - } - setBounds(newBounds); - //qDebug() << "set bounds to " << getBounds(); - } - QScriptValue color = properties.property("color"); if (color.isValid()) { QScriptValue red = color.property("red"); diff --git a/interface/src/ui/Overlay.h b/interface/src/ui/Overlay.h index 4f1cdc9edb..df898ec741 100644 --- a/interface/src/ui/Overlay.h +++ b/interface/src/ui/Overlay.h @@ -32,21 +32,11 @@ public: // getters bool getVisible() const { return _visible; } - int getX() const { return _bounds.x(); } - int getY() const { return _bounds.y(); } - int getWidth() const { return _bounds.width(); } - int getHeight() const { return _bounds.height(); } - const QRect& getBounds() const { return _bounds; } const xColor& getColor() const { return _color; } float getAlpha() const { return _alpha; } // setters void setVisible(bool visible) { _visible = visible; } - void setX(int x) { _bounds.setX(x); } - void setY(int y) { _bounds.setY(y); } - void setWidth(int width) { _bounds.setWidth(width); } - void setHeight(int height) { _bounds.setHeight(height); } - void setBounds(const QRect& bounds) { _bounds = bounds; } void setColor(const xColor& color) { _color = color; } void setAlpha(float alpha) { _alpha = alpha; } @@ -54,7 +44,6 @@ public: protected: QGLWidget* _parent; - QRect _bounds; // where on the screen to draw float _alpha; xColor _color; bool _visible; // should the overlay be drawn at all diff --git a/interface/src/ui/Overlays.cpp b/interface/src/ui/Overlays.cpp index 453367ca61..c35c4fc5ec 100644 --- a/interface/src/ui/Overlays.cpp +++ b/interface/src/ui/Overlays.cpp @@ -118,7 +118,7 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { while (i.hasPrevious()) { i.previous(); unsigned int thisID = i.key(); - Overlay* thisOverlay = i.value(); + Overlay2D* thisOverlay = static_cast(i.value()); if (thisOverlay->getVisible() && thisOverlay->getBounds().contains(point.x, point.y, false)) { return thisID; }