Improve inner workings of overlay API.

More stuff is known to the C++, and a panel object in JavaScript can be
gotten by ID from another thread.
This commit is contained in:
Zander Otavka 2015-08-04 14:04:13 -07:00
parent 055133b82e
commit 22453aa3ce
5 changed files with 110 additions and 50 deletions

View file

@ -60,9 +60,9 @@
}
var overlay = new overlayTypes[type]();
overlay._id = id;
var panelID = Overlays.getAttachedPanel(id)
if (panelID && panelID in panels) {
panels[panelID].addChild(overlay);
var attachedPanel = findPanel(Overlays.getAttachedPanel(id))
if (attachedPanel) {
attachedPanel.addChild(overlay);
}
overlays[id] = overlay;
return overlay;
@ -79,7 +79,7 @@
//
function findOverlay(id, knownOverlaysOnly, searchList) {
if (id > 0) {
knownOverlaysOnly = Boolean(knownOverlaysOnly) || Boolean(searchList);
knownOverlaysOnly = Boolean(knownOverlaysOnly);
searchList = searchList || overlays;
var foundOverlay = searchList[id];
if (foundOverlay) {
@ -92,6 +92,47 @@
return null;
}
//
// Create a new JavaScript object for a panel of given ID.
//
function makePanelFromId(id) {
if (!Overlays.isAddedPanel(id)) {
return null;
}
var panel = new FloatingUIPanel();
panel._id = id;
var attachedPanel = findPanel(Overlays.getAttachedPanel(id))
if (attachedPanel) {
attachedPanel.addChild(panel);
}
overlays[id] = overlay;
return overlay;
}
//
// Get or create an overlay object from the id.
//
// @param knownOverlaysOnly (Optional: Boolean)
// If true, a new object will not be created.
// @param searchList (Optional: Object)
// Map of overlay id's and overlay objects. Can be generated with
// `OverlayManager.makeSearchList`.
//
function findPanel(id, knownPanelsOnly, searchList) {
if (id > 0) {
knownPanelsOnly = Boolean(knownPanelsOnly);
searchList = searchList || panels;
var foundPanel = searchList[id];
if (foundPanel) {
return foundPanel;
}
if (!knownPanelsOnly) {
return makePanelFromId(id);
}
}
return null;
}
//
// Perform global scoped operations on overlays, such as finding by ray intersection.
@ -206,7 +247,6 @@
} else {
this._id = 0;
}
this._attachedPanelPointer = null;
};
that.prototype.constructor = that;
@ -219,7 +259,7 @@
Object.defineProperty(that.prototype, "attachedPanel", {
get: function() {
return this._attachedPanelPointer;
return findPanel(Overlays.getAttachedPanel(this._id));
}
});
@ -343,7 +383,6 @@
this._children = [];
this._visible = Boolean(params.visible);
panels[this._id] = this;
this._attachedPanelPointer = null;
};
that.prototype.constructor = that;
@ -384,7 +423,7 @@
Object.defineProperty(that.prototype, "attachedPanel", {
get: function() {
return this._attachedPanelPointer;
return findPanel(Overlays.getAttachedPanel(this._id));
}
});
@ -395,23 +434,12 @@
});
that.prototype.addChild = function(child) {
if (child instanceof Overlay && child.isPanelAttachable()) {
if (child instanceof Overlay && child.isPanelAttachable() ||
child instanceof FloatingUIPanel) {
Overlays.setAttachedPanel(child._id, this._id);
} else if (child instanceof FloatingUIPanel) {
child.setProperties({
anchorPosition: {
bind: "panel",
value: this._id
},
offsetRotation: {
bind: "panel",
value: this._id
}
});
} else {
throw new that.AddChildException("Given child is not panel attachable.");
}
child._attachedPanelPointer = this;
child.visible = this.visible;
this._children.push(child);
return child;
@ -420,19 +448,9 @@
that.prototype.removeChild = function(child) {
var i = this._children.indexOf(child);
if (i >= 0) {
if (child instanceof Overlay) {
if (child instanceof Overlay || child instanceof FloatingUIPanel) {
Overlays.setAttachedPanel(child._id, 0);
} else if (child instanceof FloatingUIPanel) {
child.setProperties({
anchorPosition: {
bind: "myAvatar"
},
offsetRotation: {
bind: "myAvatar"
}
});
}
child._attachedPanelPointer = null;
this._children.splice(i, 1);
}
};
@ -465,11 +483,6 @@
function onPanelDeleted(id) {
if (id in panels) {
// Overlays will automatically delete all child overlays, but not all child panels. We
// have to do that ourselves.
panels[id]._children.forEach(function(child) {
child.destroy();
});
if (panels[id].attachedPanel) {
panels[id].attachedPanel.removeChild(panels[id]);
}

View file

@ -49,6 +49,14 @@ void FloatingUIPanel::setOffsetRotation(const glm::quat& rotation) {
});
}
void FloatingUIPanel::setAttachedPanel(unsigned int panelID) {
if (panelID) {
attachAnchorToPanel(panelID);
attachRotationToPanel(panelID);
}
_attachedPanel = panelID;
}
void FloatingUIPanel::addChild(unsigned int childId) {
if (!_children.contains(childId)) {
_children.append(childId);
@ -99,11 +107,7 @@ void FloatingUIPanel::setProperties(const QScriptValue &properties) {
});
}
} else if (bindTypeString == "panel") {
FloatingUIPanel::Pointer panel = Application::getInstance()->getOverlays()
.getPanel(value.toVariant().toUInt());
setAnchorPosition([panel]() -> glm::vec3 {
return panel->getPosition();
});
attachAnchorToPanel(value.toVariant().toUInt());
} else if (bindTypeString == "vec3") {
QScriptValue x = value.property("x");
QScriptValue y = value.property("y");
@ -140,11 +144,7 @@ void FloatingUIPanel::setProperties(const QScriptValue &properties) {
});
}
} else if (bindTypeString == "panel") {
FloatingUIPanel::Pointer panel = Application::getInstance()->getOverlays()
.getPanel(value.toVariant().toUInt());
setOffsetRotation([panel]() -> glm::quat {
return panel->getRotation();
});
attachRotationToPanel(value.toVariant().toUInt());
} else if (bindTypeString == "quat") {
QScriptValue x = value.property("x");
QScriptValue y = value.property("y");
@ -195,3 +195,17 @@ void FloatingUIPanel::setProperties(const QScriptValue &properties) {
}
}
}
void FloatingUIPanel::attachAnchorToPanel(unsigned int panelID) {
FloatingUIPanel::Pointer panel = Application::getInstance()->getOverlays().getPanel(panelID);
setAnchorPosition([panel]() -> glm::vec3 {
return panel->getPosition();
});
}
void FloatingUIPanel::attachRotationToPanel(unsigned int panelID) {
FloatingUIPanel::Pointer panel = Application::getInstance()->getOverlays().getPanel(panelID);
setOffsetRotation([panel]() -> glm::quat {
return panel->getRotation();
});
}

View file

@ -32,6 +32,7 @@ public:
glm::quat getFacingRotation() const { return _facingRotation; }
glm::vec3 getPosition() const;
glm::quat getRotation() const;
unsigned int getAttachedPanel() const { return _attachedPanel; }
void setAnchorPosition(const std::function<glm::vec3()>& func) { _anchorPosition = func; }
void setAnchorPosition(const glm::vec3& position);
@ -39,6 +40,7 @@ public:
void setOffsetRotation(const glm::quat& rotation);
void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; }
void setFacingRotation(const glm::quat& rotation) { _facingRotation = rotation; }
void setAttachedPanel(unsigned int panelID);
const QList<unsigned int>& getChildren() { return _children; }
void addChild(unsigned int childId);
@ -52,10 +54,14 @@ private:
static std::function<glm::vec3()> const AVATAR_POSITION;
static std::function<glm::quat()> const AVATAR_ORIENTATION;
void attachAnchorToPanel(unsigned int panelID);
void attachRotationToPanel(unsigned int panelID);
std::function<glm::vec3()> _anchorPosition{AVATAR_POSITION};
std::function<glm::quat()> _offsetRotation{AVATAR_ORIENTATION};
glm::vec3 _offsetPosition{0, 0, 0};
glm::quat _facingRotation{1, 0, 0, 0};
unsigned int _attachedPanel{0};
QScriptEngine* _scriptEngine;
QList<unsigned int> _children;
};

View file

@ -277,6 +277,8 @@ unsigned int Overlays::getAttachedPanel(unsigned int childId) const {
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlay);
if (attachable) {
return _panels.key(attachable->getAttachedPanel());
} else if (_panels.contains(childId)) {
return getPanel(childId)->getAttachedPanel();
}
return 0;
}
@ -286,7 +288,7 @@ void Overlays::setAttachedPanel(unsigned int childId, unsigned int panelId) {
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlay);
if (attachable) {
if (_panels.contains(panelId)) {
auto panel = _panels[panelId];
auto panel = getPanel(panelId);
panel->addChild(childId);
attachable->setAttachedPanel(panel);
} else {
@ -296,6 +298,19 @@ void Overlays::setAttachedPanel(unsigned int childId, unsigned int panelId) {
attachable->setAttachedPanel(nullptr);
}
}
} else if (_panels.contains(childId)) {
auto child = getPanel(childId);
if (_panels.contains(panelId)) {
auto panel = getPanel(panelId);
panel->addChild(childId);
child->setAttachedPanel(panelId);
} else {
auto panel = getPanel(child->getAttachedPanel());
if (panel) {
panel->removeChild(childId);
child->setAttachedPanel(0);
}
}
}
}
@ -538,7 +553,7 @@ void Overlays::editPanel(unsigned int panelId, const QScriptValue& properties) {
OverlayPropertyResult Overlays::getPanelProperty(unsigned int panelId, const QString& property) {
OverlayPropertyResult result;
if (_panels.contains(panelId)) {
FloatingUIPanel::Pointer thisPanel = _panels[panelId];
FloatingUIPanel::Pointer thisPanel = getPanel(panelId);
QReadLocker lock(&_lock);
result.value = thisPanel->getProperty(property);
}
@ -559,8 +574,14 @@ void Overlays::deletePanel(unsigned int panelId) {
}
while (!panelToDelete->getChildren().isEmpty()) {
deleteOverlay(panelToDelete->popLastChild());
unsigned int childId = panelToDelete->popLastChild();
deleteOverlay(childId);
deletePanel(childId);
}
emit panelDeleted(panelId);
}
bool Overlays::isAddedOverlay(unsigned int id) {
return _overlaysHUD.contains(id) || _overlaysWorld.contains(id);
}

View file

@ -125,6 +125,12 @@ public slots:
/// deletes a panel and all child overlays
void deletePanel(unsigned int panelId);
/// return true if there is an overlay with that id else false
bool isAddedOverlay(unsigned int id);
/// return true if there is a panel with that id else false
bool isAddedPanel(unsigned int id) { return _panels.contains(id); }
signals:
void overlayDeleted(unsigned int id);
void panelDeleted(unsigned int id);