added 3D cube overlay support

This commit is contained in:
ZappoMan 2014-02-16 11:36:06 -08:00
parent cb1c659e2e
commit 5abf908874
14 changed files with 389 additions and 54 deletions

View file

@ -39,7 +39,7 @@ for (s = 0; s < numberOfSwatches; s++) {
height: 54, height: 54,
subImage: { x: imageFromX, y: imageFromY, 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", imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg",
backgroundColor: swatchColors[s], color: swatchColors[s],
alpha: 1 alpha: 1
}); });
} }
@ -49,11 +49,10 @@ var text = Overlays.addOverlay("text", {
y: 100, y: 100,
width: 150, width: 150,
height: 50, height: 50,
backgroundColor: { red: 0, green: 0, blue: 0}, color: { red: 0, green: 0, blue: 0},
textColor: { red: 255, green: 0, blue: 0}, textColor: { red: 255, green: 0, blue: 0},
topMargin: 4, topMargin: 4,
leftMargin: 4, leftMargin: 4,
alpha: 0.7,
text: "Here is some text.\nAnd a second line." text: "Here is some text.\nAnd a second line."
}); });
@ -64,8 +63,7 @@ var toolA = Overlays.addOverlay("image", {
height: 40, height: 40,
subImage: { x: 0, y: 0, 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", imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg",
backgroundColor: { red: 255, green: 255, blue: 255}, color: { red: 255, green: 255, blue: 255},
alpha: 0.7,
visible: false visible: false
}); });
@ -73,7 +71,7 @@ var slider = Overlays.addOverlay("image", {
// alternate form of expressing bounds // alternate form of expressing bounds
bounds: { x: 100, y: 300, width: 158, height: 35}, bounds: { x: 100, y: 300, width: 158, height: 35},
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/slider.png", 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 alpha: 1
}); });
@ -86,22 +84,39 @@ var thumb = Overlays.addOverlay("image", {
width: 18, width: 18,
height: 17, height: 17,
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png", 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 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* // our 3D cube that moves around...
// 0123456789*123456789*123456789* 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() { function scriptEnding() {
Overlays.deleteOverlay(toolA); Overlays.deleteOverlay(toolA);
@ -127,6 +142,21 @@ function update() {
} }
Overlays.editOverlay(toolA, { visible: toolAVisible } ); 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); Script.willSendVisualDataCallback.connect(update);

View file

@ -2842,6 +2842,9 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
// give external parties a change to hook in // give external parties a change to hook in
emit renderingInWorldInterface(); emit renderingInWorldInterface();
// render JS/scriptable overlays
_overlays.render3D();
} }
} }
@ -2988,7 +2991,7 @@ void Application::displayOverlay() {
_pieMenu.render(); _pieMenu.render();
} }
_overlays.render(); _overlays.render2D();
glPopMatrix(); glPopMatrix();
} }

View file

@ -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 <QGLWidget>
#include <SharedUtil.h>
#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());
}
}

View file

@ -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 <QGLWidget>
#include <QImage>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QRect>
#include <QScriptValue>
#include <QString>
#include <QUrl>
#include <SharedUtil.h>
#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__) */

View file

@ -61,7 +61,7 @@ void ImageOverlay::render() {
glBindTexture(GL_TEXTURE_2D, _textureID); glBindTexture(GL_TEXTURE_2D, _textureID);
} }
const float MAX_COLOR = 255; 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 imageWidth = _textureImage.width();
float imageHeight = _textureImage.height(); float imageHeight = _textureImage.height();
@ -107,7 +107,7 @@ void ImageOverlay::render() {
} }
void ImageOverlay::setProperties(const QScriptValue& properties) { void ImageOverlay::setProperties(const QScriptValue& properties) {
Overlay::setProperties(properties); Overlay2D::setProperties(properties);
QScriptValue subImageBounds = properties.property("subImage"); QScriptValue subImageBounds = properties.property("subImage");
if (subImageBounds.isValid()) { if (subImageBounds.isValid()) {

View file

@ -23,8 +23,9 @@
#include <SharedUtil.h> #include <SharedUtil.h>
#include "Overlay.h" #include "Overlay.h"
#include "Overlay2D.h"
class ImageOverlay : public Overlay { class ImageOverlay : public Overlay2D {
Q_OBJECT Q_OBJECT
public: public:

View file

@ -19,7 +19,7 @@
Overlay::Overlay() : Overlay::Overlay() :
_parent(NULL), _parent(NULL),
_alpha(DEFAULT_ALPHA), _alpha(DEFAULT_ALPHA),
_backgroundColor(DEFAULT_BACKGROUND_COLOR), _color(DEFAULT_BACKGROUND_COLOR),
_visible(true) _visible(true)
{ {
} }
@ -69,15 +69,15 @@ void Overlay::setProperties(const QScriptValue& properties) {
//qDebug() << "set bounds to " << getBounds(); //qDebug() << "set bounds to " << getBounds();
} }
QScriptValue color = properties.property("backgroundColor"); QScriptValue color = properties.property("color");
if (color.isValid()) { if (color.isValid()) {
QScriptValue red = color.property("red"); QScriptValue red = color.property("red");
QScriptValue green = color.property("green"); QScriptValue green = color.property("green");
QScriptValue blue = color.property("blue"); QScriptValue blue = color.property("blue");
if (red.isValid() && green.isValid() && blue.isValid()) { if (red.isValid() && green.isValid() && blue.isValid()) {
_backgroundColor.red = red.toVariant().toInt(); _color.red = red.toVariant().toInt();
_backgroundColor.green = green.toVariant().toInt(); _color.green = green.toVariant().toInt();
_backgroundColor.blue = blue.toVariant().toInt(); _color.blue = blue.toVariant().toInt();
} }
} }

View file

@ -37,7 +37,7 @@ public:
int getWidth() const { return _bounds.width(); } int getWidth() const { return _bounds.width(); }
int getHeight() const { return _bounds.height(); } int getHeight() const { return _bounds.height(); }
const QRect& getBounds() const { return _bounds; } const QRect& getBounds() const { return _bounds; }
const xColor& getBackgroundColor() const { return _backgroundColor; } const xColor& getColor() const { return _color; }
float getAlpha() const { return _alpha; } float getAlpha() const { return _alpha; }
// setters // setters
@ -47,7 +47,7 @@ public:
void setWidth(int width) { _bounds.setWidth(width); } void setWidth(int width) { _bounds.setWidth(width); }
void setHeight(int height) { _bounds.setHeight(height); } void setHeight(int height) { _bounds.setHeight(height); }
void setBounds(const QRect& bounds) { _bounds = bounds; } 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; } void setAlpha(float alpha) { _alpha = alpha; }
virtual void setProperties(const QScriptValue& properties); virtual void setProperties(const QScriptValue& properties);
@ -56,7 +56,7 @@ protected:
QGLWidget* _parent; QGLWidget* _parent;
QRect _bounds; // where on the screen to draw QRect _bounds; // where on the screen to draw
float _alpha; float _alpha;
xColor _backgroundColor; xColor _color;
bool _visible; // should the overlay be drawn at all bool _visible; // should the overlay be drawn at all
}; };

View file

@ -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 <QSvgRenderer>
#include <QPainter>
#include <QGLWidget>
#include <SharedUtil.h>
#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();
}
}

View file

@ -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 <QGLWidget>
#include <QRect>
#include <QScriptValue>
#include <QString>
#include <SharedUtil.h> // 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__) */

View file

@ -6,8 +6,9 @@
// //
#include "Overlays.h" #include "Cube3DOverlay.h"
#include "ImageOverlay.h" #include "ImageOverlay.h"
#include "Overlays.h"
#include "TextOverlay.h" #include "TextOverlay.h"
@ -23,8 +24,14 @@ void Overlays::init(QGLWidget* parent) {
_parent = parent; _parent = parent;
} }
void Overlays::render() { void Overlays::render2D() {
foreach(Overlay* thisOverlay, _overlays) { foreach(Overlay* thisOverlay, _overlays2D) {
thisOverlay->render();
}
}
void Overlays::render3D() {
foreach(Overlay* thisOverlay, _overlays3D) {
thisOverlay->render(); thisOverlay->render();
} }
} }
@ -32,21 +39,36 @@ void Overlays::render() {
// TODO: make multi-threaded safe // TODO: make multi-threaded safe
unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) { unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) {
unsigned int thisID = 0; unsigned int thisID = 0;
bool created = false;
bool is3D = false;
Overlay* thisOverlay = NULL;
if (type == "image") { if (type == "image") {
thisID = _nextOverlayID; thisOverlay = new ImageOverlay();
_nextOverlayID++;
ImageOverlay* thisOverlay = new ImageOverlay();
thisOverlay->init(_parent); thisOverlay->init(_parent);
thisOverlay->setProperties(properties); thisOverlay->setProperties(properties);
_overlays[thisID] = thisOverlay; created = true;
} else if (type == "text") { } else if (type == "text") {
thisID = _nextOverlayID; thisOverlay = new TextOverlay();
_nextOverlayID++;
TextOverlay* thisOverlay = new TextOverlay();
thisOverlay->init(_parent); thisOverlay->init(_parent);
thisOverlay->setProperties(properties); 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; return thisID;
@ -54,23 +76,30 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope
// TODO: make multi-threaded safe // TODO: make multi-threaded safe
bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {
if (!_overlays.contains(id)) { Overlay* thisOverlay = NULL;
return false; if (_overlays2D.contains(id)) {
thisOverlay = _overlays2D[id];
} else if (_overlays3D.contains(id)) {
thisOverlay = _overlays3D[id];
} }
Overlay* thisOverlay = _overlays[id]; if (thisOverlay) {
thisOverlay->setProperties(properties); thisOverlay->setProperties(properties);
return true; return true;
}
return false;
} }
// TODO: make multi-threaded safe // TODO: make multi-threaded safe
void Overlays::deleteOverlay(unsigned int id) { void Overlays::deleteOverlay(unsigned int id) {
if (_overlays.contains(id)) { if (_overlays2D.contains(id)) {
_overlays.erase(_overlays.find(id)); _overlays2D.erase(_overlays2D.find(id));
} else if (_overlays3D.contains(id)) {
_overlays3D.erase(_overlays3D.find(id));
} }
} }
unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) {
QMapIterator<unsigned int, Overlay*> i(_overlays); QMapIterator<unsigned int, Overlay*> i(_overlays2D);
i.toBack(); i.toBack();
while (i.hasPrevious()) { while (i.hasPrevious()) {
i.previous(); i.previous();

View file

@ -18,7 +18,8 @@ public:
Overlays(); Overlays();
~Overlays(); ~Overlays();
void init(QGLWidget* parent); void init(QGLWidget* parent);
void render(); void render3D();
void render2D();
public slots: public slots:
/// adds an overlay with the specific properties /// adds an overlay with the specific properties
@ -35,7 +36,8 @@ public slots:
unsigned int getOverlayAtPoint(const glm::vec2& point); unsigned int getOverlayAtPoint(const glm::vec2& point);
private: private:
QMap<unsigned int, Overlay*> _overlays; QMap<unsigned int, Overlay*> _overlays2D;
QMap<unsigned int, Overlay*> _overlays3D;
static unsigned int _nextOverlayID; static unsigned int _nextOverlayID;
QGLWidget* _parent; QGLWidget* _parent;
}; };

View file

@ -29,7 +29,7 @@ void TextOverlay::render() {
} }
const float MAX_COLOR = 255; 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); glBegin(GL_QUADS);
glVertex2f(_bounds.left(), _bounds.top()); glVertex2f(_bounds.left(), _bounds.top());
@ -63,7 +63,7 @@ void TextOverlay::render() {
} }
void TextOverlay::setProperties(const QScriptValue& properties) { void TextOverlay::setProperties(const QScriptValue& properties) {
Overlay::setProperties(properties); Overlay2D::setProperties(properties);
QScriptValue text = properties.property("text"); QScriptValue text = properties.property("text");
if (text.isValid()) { if (text.isValid()) {

View file

@ -23,10 +23,11 @@
#include <SharedUtil.h> #include <SharedUtil.h>
#include "Overlay.h" #include "Overlay.h"
#include "Overlay2D.h"
const int DEFAULT_MARGIN = 10; const int DEFAULT_MARGIN = 10;
class TextOverlay : public Overlay { class TextOverlay : public Overlay2D {
Q_OBJECT Q_OBJECT
public: public: