mirror of
https://github.com/lubosz/overte.git
synced 2025-04-27 00:55:42 +02:00
commit
ab8be15ce0
10 changed files with 324 additions and 24 deletions
interface/src/ui/overlays
libraries
entities-renderer/src
render-utils/src
scripts/system
|
@ -18,7 +18,7 @@
|
|||
QString const ModelOverlay::TYPE = "model";
|
||||
|
||||
ModelOverlay::ModelOverlay()
|
||||
: _model(std::make_shared<Model>(std::make_shared<Rig>())),
|
||||
: _model(std::make_shared<Model>(std::make_shared<Rig>(), nullptr, this)),
|
||||
_modelTextures(QVariantMap())
|
||||
{
|
||||
_model->init();
|
||||
|
@ -27,7 +27,7 @@ ModelOverlay::ModelOverlay()
|
|||
|
||||
ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) :
|
||||
Volume3DOverlay(modelOverlay),
|
||||
_model(std::make_shared<Model>(std::make_shared<Rig>())),
|
||||
_model(std::make_shared<Model>(std::make_shared<Rig>(), nullptr, this)),
|
||||
_modelTextures(QVariantMap()),
|
||||
_url(modelOverlay->_url),
|
||||
_updateModel(false)
|
||||
|
|
|
@ -540,7 +540,7 @@ void EntityTreeRenderer::processEraseMessage(ReceivedMessage& message, const Sha
|
|||
std::static_pointer_cast<EntityTree>(_tree)->processEraseMessage(message, sourceNode);
|
||||
}
|
||||
|
||||
ModelPointer EntityTreeRenderer::allocateModel(const QString& url, float loadingPriority) {
|
||||
ModelPointer EntityTreeRenderer::allocateModel(const QString& url, float loadingPriority, SpatiallyNestable* spatiallyNestableOverride) {
|
||||
ModelPointer model = nullptr;
|
||||
|
||||
// Only create and delete models on the thread that owns the EntityTreeRenderer
|
||||
|
@ -552,7 +552,7 @@ ModelPointer EntityTreeRenderer::allocateModel(const QString& url, float loading
|
|||
return model;
|
||||
}
|
||||
|
||||
model = std::make_shared<Model>(std::make_shared<Rig>());
|
||||
model = std::make_shared<Model>(std::make_shared<Rig>(), nullptr, spatiallyNestableOverride);
|
||||
model->setLoadingPriority(loadingPriority);
|
||||
model->init();
|
||||
model->setURL(QUrl(url));
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
void reloadEntityScripts();
|
||||
|
||||
/// if a renderable entity item needs a model, we will allocate it for them
|
||||
Q_INVOKABLE ModelPointer allocateModel(const QString& url, float loadingPriority = 0.0f);
|
||||
Q_INVOKABLE ModelPointer allocateModel(const QString& url, float loadingPriority = 0.0f, SpatiallyNestable* spatiallyNestableOverride = nullptr);
|
||||
|
||||
/// if a renderable entity item needs to update the URL of a model, we will handle that for the entity
|
||||
Q_INVOKABLE ModelPointer updateModel(ModelPointer original, const QString& newUrl);
|
||||
|
|
|
@ -504,8 +504,7 @@ ModelPointer RenderableModelEntityItem::getModel(QSharedPointer<EntityTreeRender
|
|||
if (!getModelURL().isEmpty()) {
|
||||
// If we don't have a model, allocate one *immediately*
|
||||
if (!_model) {
|
||||
_model = _myRenderer->allocateModel(getModelURL(), renderer->getEntityLoadingPriority(*this));
|
||||
_model->setSpatiallyNestableOverride(shared_from_this());
|
||||
_model = _myRenderer->allocateModel(getModelURL(), renderer->getEntityLoadingPriority(*this), this);
|
||||
_needsInitialSimulation = true;
|
||||
// If we need to change URLs, update it *after rendering* (to avoid access violations)
|
||||
} else if (QUrl(getModelURL()) != _model->getURL()) {
|
||||
|
|
|
@ -78,11 +78,12 @@ void initCollisionMaterials() {
|
|||
}
|
||||
}
|
||||
|
||||
Model::Model(RigPointer rig, QObject* parent) :
|
||||
Model::Model(RigPointer rig, QObject* parent, SpatiallyNestable* spatiallyNestableOverride) :
|
||||
QObject(parent),
|
||||
_renderGeometry(),
|
||||
_collisionGeometry(),
|
||||
_renderWatcher(_renderGeometry),
|
||||
_spatiallyNestableOverride(spatiallyNestableOverride),
|
||||
_translation(0.0f),
|
||||
_rotation(),
|
||||
_scale(1.0f, 1.0f, 1.0f),
|
||||
|
@ -133,16 +134,10 @@ void Model::setRotation(const glm::quat& rotation) {
|
|||
updateRenderItems();
|
||||
}
|
||||
|
||||
void Model::setSpatiallyNestableOverride(SpatiallyNestablePointer override) {
|
||||
_spatiallyNestableOverride = override;
|
||||
updateRenderItems();
|
||||
}
|
||||
|
||||
Transform Model::getTransform() const {
|
||||
SpatiallyNestablePointer spatiallyNestableOverride = _spatiallyNestableOverride.lock();
|
||||
if (spatiallyNestableOverride) {
|
||||
if (_spatiallyNestableOverride) {
|
||||
bool success;
|
||||
Transform transform = spatiallyNestableOverride->getTransform(success);
|
||||
Transform transform = _spatiallyNestableOverride->getTransform(success);
|
||||
if (success) {
|
||||
transform.setScale(getScale());
|
||||
return transform;
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
|
||||
static void setAbstractViewStateInterface(AbstractViewStateInterface* viewState) { _viewState = viewState; }
|
||||
|
||||
Model(RigPointer rig, QObject* parent = nullptr);
|
||||
Model(RigPointer rig, QObject* parent = nullptr, SpatiallyNestable* spatiallyNestableOverride = nullptr);
|
||||
virtual ~Model();
|
||||
|
||||
inline ModelPointer getThisPointer() const {
|
||||
|
@ -205,7 +205,6 @@ public:
|
|||
|
||||
void setTranslation(const glm::vec3& translation);
|
||||
void setRotation(const glm::quat& rotation);
|
||||
void setSpatiallyNestableOverride(SpatiallyNestablePointer ptr);
|
||||
|
||||
const glm::vec3& getTranslation() const { return _translation; }
|
||||
const glm::quat& getRotation() const { return _rotation; }
|
||||
|
@ -292,12 +291,11 @@ protected:
|
|||
|
||||
GeometryResourceWatcher _renderWatcher;
|
||||
|
||||
SpatiallyNestable* _spatiallyNestableOverride;
|
||||
|
||||
glm::vec3 _translation;
|
||||
glm::quat _rotation;
|
||||
glm::vec3 _scale;
|
||||
|
||||
SpatiallyNestableWeakPointer _spatiallyNestableOverride;
|
||||
|
||||
glm::vec3 _offset;
|
||||
|
||||
static float FAKE_DIMENSION_PLACEHOLDER;
|
||||
|
|
|
@ -853,7 +853,7 @@ function MyController(hand) {
|
|||
};
|
||||
|
||||
this.setState = function(newState, reason) {
|
||||
if (isInEditMode() && (newState !== STATE_OFF &&
|
||||
if ((isInEditMode() && this.grabbedEntity !== HMD.tabletID )&& (newState !== STATE_OFF &&
|
||||
newState !== STATE_SEARCHING &&
|
||||
newState !== STATE_OVERLAY_STYLUS_TOUCHING)) {
|
||||
return;
|
||||
|
@ -1703,7 +1703,7 @@ function MyController(hand) {
|
|||
};
|
||||
|
||||
this.isTablet = function (entityID) {
|
||||
if (entityID === HMD.tabletID) { // XXX what's a better way to know this?
|
||||
if (entityID === HMD.tabletID) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
241
scripts/system/html/users.html
Normal file
241
scripts/system/html/users.html
Normal file
|
@ -0,0 +1,241 @@
|
|||
<!--
|
||||
// users.html
|
||||
//
|
||||
// Created by Faye Li on 18 Jan 2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Users Online</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://fonts.googleapis.com/css?family=Raleway:300,400,600,700"" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-family: 'Raleway', sans-serif;
|
||||
color: white;
|
||||
background: linear-gradient(#2b2b2b, #0f212e);
|
||||
}
|
||||
|
||||
.top-bar {
|
||||
width: 100%;
|
||||
height: 90px;
|
||||
background: linear-gradient(#2b2b2b, #1e1e1e);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.top-bar .container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-left: 30px;
|
||||
margin-right: 30px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#refresh-button {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tabs li {
|
||||
display: inline-block;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.tabs li.current {
|
||||
background: rgba(255,255,255,0.15);
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-content.current {
|
||||
display: inherit;
|
||||
background: rgba(255,255,255,0.15);
|
||||
}
|
||||
|
||||
.tab-content ul {
|
||||
list-style: none;
|
||||
padding: 15px 0px 15px 15px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tab-content ul li {
|
||||
padding: 2px 0px;
|
||||
}
|
||||
|
||||
input[type=button] {
|
||||
font-family: 'Raleway';
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
text-transform: uppercase;
|
||||
vertical-align: top;
|
||||
height: 28px;
|
||||
min-width: 120px;
|
||||
padding: 0px 18px;
|
||||
margin-right: 6px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
background: linear-gradient(#343434 20%, #000 100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type=button].blue {
|
||||
color: #fff;
|
||||
background-color: #1080b8;
|
||||
background: linear-gradient(#00b4ef 20%, #1080b8 100%);
|
||||
}
|
||||
|
||||
input[type=button].blue:hover {
|
||||
background: linear-gradient(#00b4ef, #00b4ef);
|
||||
border: none;
|
||||
}
|
||||
|
||||
input[type=button].blue:active {
|
||||
background: linear-gradient(#1080b8, #1080b8);
|
||||
}
|
||||
|
||||
#friends-button {
|
||||
margin: 0px 0px 15px 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top-bar">
|
||||
<div class="container">
|
||||
<div>Users Online</div>
|
||||
<img id="refresh-button" onclick="pollUsers()" src="https://hifi-content.s3.amazonaws.com/faye/tablet-dev/refresh-icon.svg"></img>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<ul class="tabs">
|
||||
<li tab-id="tab-1" class="current">Everyone (0)</li>
|
||||
<li tab-id="tab-2">Friends (0)</li>
|
||||
</ul>
|
||||
<div id="tab-1" class="tab-content current">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<div id="tab-2" class="tab-content">
|
||||
<ul></ul>
|
||||
<input type="button" class="blue" id="friends-button" value="Add/Remove Friends">
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
||||
<script>
|
||||
var METAVERSE_API_URL = "https://metaverse.highfidelity.com/api/v1/users?status=online";
|
||||
var FRIENDS_FILTER = "&filter=friends";
|
||||
var myUsername = null;
|
||||
|
||||
function displayUsers(data, element) {
|
||||
element.empty();
|
||||
for (var i = 0; i < data.users.length; i++) {
|
||||
// Don't display users who aren't in a domain
|
||||
if (typeof data.users[i].location.root.name === "undefined") {
|
||||
console.log(data.users[i].username + "is online but not in a domain");
|
||||
$("#dev-div").append("<p>" + data.users[i].username + "is online but not in a domain</p>");
|
||||
} else {
|
||||
$("#dev-div").append("<li>" + data.users[i].username + " @ " + data.users[i].location.root.name + "</li>");
|
||||
// Don't display yourself
|
||||
if (data.users[i].username !== myUsername) {
|
||||
console.log(data.users[i].username + " @ " + data.users[i].location.root.name);
|
||||
element.append("<li>" + data.users[i].username + " @ " + data.users[i].location.root.name + "</li>");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processData(data, type) {
|
||||
var num = data.users.length;
|
||||
if (type === "everyone") {
|
||||
$(".tabs li:nth-child(1)").text("Everyone (" + num + ")");
|
||||
displayUsers(data, $("#tab-1 ul"));
|
||||
} else if (type === "friends") {
|
||||
$(".tabs li:nth-child(2)").text("Friends (" + num + ")");
|
||||
displayUsers(data, $("#tab-2 ul"));
|
||||
}
|
||||
}
|
||||
|
||||
function pollUsers() {
|
||||
$("#dev-div").append("<p>polling users..</p>");
|
||||
$.ajax({
|
||||
url: METAVERSE_API_URL,
|
||||
success: function(response) {
|
||||
console.log(response);
|
||||
$("#dev-div").append("<p>polling everyone sucess</p>");
|
||||
processData(response.data, "everyone");
|
||||
}
|
||||
});
|
||||
$.ajax({
|
||||
url: METAVERSE_API_URL + FRIENDS_FILTER,
|
||||
success: function(response) {
|
||||
console.log(response);
|
||||
$("#dev-div").append("<p>polling friends sucess</p>");
|
||||
processData(response.data, "friends");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onScriptEventReceived(event) {
|
||||
$("#dev-div").append("<p>Received a script event, its type is " + typeof event + "</p>");
|
||||
if (typeof event === "string") {
|
||||
// Parse the string into an object
|
||||
event = JSON.parse(event);
|
||||
}
|
||||
if (event.type === "sendUsername") {
|
||||
myUsername = event.data.username;
|
||||
$("#dev-div").append("<p>myUsername is " + myUsername + "</p>");
|
||||
consoloe.log("myUsername is " + myUsername);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#dev-div").append("<p>ready</p>");
|
||||
// Auto-load user lists when page loads
|
||||
pollUsers();
|
||||
|
||||
// Click listener for tabs
|
||||
$(".tabs li").click(function() {
|
||||
var tabID = $(this).attr("tab-id");
|
||||
$(".tab-content").removeClass("current");
|
||||
$("#" + tabID).addClass("current");
|
||||
$(".tabs li").removeClass("current");
|
||||
$(this).addClass("current");
|
||||
});
|
||||
|
||||
// Listen for events from hifi
|
||||
EventBridge.scriptEventReceived.connect(onScriptEventReceived);
|
||||
|
||||
// Send a ready event to hifi
|
||||
var eventObject = {"type": "ready"};
|
||||
EventBridge.emitWebEvent(JSON.stringify(eventObject));
|
||||
|
||||
// Click listener mangage friends button
|
||||
$("#friends-button").click(function() {
|
||||
// Send a manage friends event to hifi
|
||||
eventObject = {"type": "manage-friends"};
|
||||
EventBridge.emitWebEvent(JSON.stringify(eventObject));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1038,7 +1038,7 @@ SelectionDisplay = (function() {
|
|||
if (entityIntersection.intersects &&
|
||||
(!overlayIntersection.intersects || (entityIntersection.distance < overlayIntersection.distance))) {
|
||||
|
||||
if (HMD.tabletID == entityIntersection.entityID) {
|
||||
if (HMD.tabletID === entityIntersection.entityID) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
67
scripts/system/tablet-users.js
Normal file
67
scripts/system/tablet-users.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
"use strict";
|
||||
|
||||
//
|
||||
// users.js
|
||||
//
|
||||
// Created by Faye Li on 18 Jan 2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
(function() { // BEGIN LOCAL_SCOPE
|
||||
var USERS_URL = "https://hifi-content.s3.amazonaws.com/faye/tablet-dev/users.html";
|
||||
var FRIENDS_WINDOW_URL = "https://metaverse.highfidelity.com/user/friends";
|
||||
var FRIENDS_WINDOW_WIDTH = 290;
|
||||
var FRIENDS_WINDOW_HEIGHT = 500;
|
||||
var FRIENDS_WINDOW_TITLE = "Add/Remove Friends";
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
var button = tablet.addButton({
|
||||
icon: "icons/tablet-icons/people-i.svg",
|
||||
text: "Users"
|
||||
});
|
||||
|
||||
function onClicked() {
|
||||
tablet.gotoWebScreen(USERS_URL);
|
||||
}
|
||||
|
||||
function onWebEventReceived(event) {
|
||||
print("Script received a web event, its type is " + typeof event);
|
||||
if (typeof event === "string") {
|
||||
event = JSON.parse(event);
|
||||
}
|
||||
if (event.type === "ready") {
|
||||
// send username to html
|
||||
var myUsername = GlobalServices.username;
|
||||
var object = {
|
||||
"type": "sendUsername",
|
||||
"data": {"username": myUsername}
|
||||
};
|
||||
print("sending username: " + myUsername);
|
||||
tablet.emitScriptEvent(JSON.stringify(object));
|
||||
}
|
||||
if (event.type === "manage-friends") {
|
||||
// open a web overlay to metaverse friends page
|
||||
var friendsWindow = new OverlayWebWindow({
|
||||
title: FRIENDS_WINDOW_TITLE,
|
||||
width: FRIENDS_WINDOW_WIDTH,
|
||||
height: FRIENDS_WINDOW_HEIGHT,
|
||||
visible: false
|
||||
});
|
||||
friendsWindow.setURL(FRIENDS_WINDOW_URL);
|
||||
friendsWindow.setVisible(true);
|
||||
friendsWindow.raise();
|
||||
}
|
||||
}
|
||||
|
||||
button.clicked.connect(onClicked);
|
||||
tablet.webEventReceived.connect(onWebEventReceived);
|
||||
|
||||
function cleanup() {
|
||||
button.clicked.disconnect(onClicked);
|
||||
tablet.removeButton(button);
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}()); // END LOCAL_SCOPE
|
Loading…
Reference in a new issue