diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json
index 284dd344e7..3ae92651b8 100644
--- a/domain-server/resources/describe-settings.json
+++ b/domain-server/resources/describe-settings.json
@@ -247,7 +247,7 @@
"name": "standard_permissions",
"type": "table",
"label": "Domain-Wide User Permissions",
- "help": "Indicate which types of users can have which domain-wide permissions.",
+ "help": "Indicate which types of users can have which domain-wide permissions.",
"caption": "Standard Permissions",
"can_add_new_rows": false,
"groups": [
@@ -256,7 +256,7 @@
"span": 1
},
{
- "label": "Permissions ?",
+ "label": "Permissions ?",
"span": 11
}
],
@@ -337,7 +337,7 @@
},
{
"name": "id_can_get_and_set_private_user_data",
- "label": "Can Get and Set Private User Data",
+ "label": "Get and Set Private User Data",
"type": "checkbox",
"editable": true,
"default": false
@@ -392,7 +392,7 @@
"span": 1
},
{
- "label": "Permissions ?",
+ "label": "Permissions ?",
"span": 11
}
],
@@ -498,7 +498,7 @@
},
{
"name": "id_can_get_and_set_private_user_data",
- "label": "Can Get and Set Private User Data",
+ "label": "Get and Set Private User Data",
"type": "checkbox",
"editable": true,
"default": false
@@ -520,7 +520,7 @@
"span": 1
},
{
- "label": "Permissions ?",
+ "label": "Permissions ?",
"span": 11
}
],
@@ -623,7 +623,7 @@
},
{
"name": "id_can_get_and_set_private_user_data",
- "label": "Can Get and Set Private User Data",
+ "label": "Get and Set Private User Data",
"type": "checkbox",
"editable": true,
"default": false
@@ -641,7 +641,7 @@
"span": 1
},
{
- "label": "Permissions ?",
+ "label": "Permissions ?",
"span": 11
}
],
@@ -722,7 +722,7 @@
},
{
"name": "id_can_get_and_set_private_user_data",
- "label": "Can Get and Set Private User Data",
+ "label": "Get and Set Private User Data",
"type": "checkbox",
"editable": true,
"default": false
@@ -740,7 +740,7 @@
"span": 1
},
{
- "label": "Permissions ?",
+ "label": "Permissions ?",
"span": 11
}
],
@@ -821,7 +821,7 @@
},
{
"name": "id_can_get_and_set_private_user_data",
- "label": "Can Get and Set Private User Data",
+ "label": "Get and Set Private User Data",
"type": "checkbox",
"editable": true,
"default": false
@@ -839,7 +839,7 @@
"span": 1
},
{
- "label": "Permissions ?",
+ "label": "Permissions ?",
"span": 11
}
],
@@ -920,7 +920,7 @@
},
{
"name": "id_can_get_and_set_private_user_data",
- "label": "Can Get and Set Private User Data",
+ "label": "Get and Set Private User Data",
"type": "checkbox",
"editable": true,
"default": false
@@ -938,7 +938,7 @@
"span": 1
},
{
- "label": "Permissions ?",
+ "label": "Permissions ?",
"span": 11
}
],
@@ -1019,7 +1019,7 @@
},
{
"name": "id_can_get_and_set_private_user_data",
- "label": "Can Get and Set Private User Data",
+ "label": "Get and Set Private User Data",
"type": "checkbox",
"editable": true,
"default": false
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 05ddcd5bd3..fccd6b50c5 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -3857,6 +3857,11 @@ void Application::showHelp() {
//InfoView::show(INFO_HELP_PATH, false, queryString.toString());
}
+void Application::gotoTutorial() {
+ const QString TUTORIAL_ADDRESS = "file:///~/serverless/tutorial.json";
+ DependencyManager::get()->handleLookupString(TUTORIAL_ADDRESS);
+}
+
void Application::resizeEvent(QResizeEvent* event) {
resizeGL();
}
@@ -4065,7 +4070,7 @@ std::map Application::prepareServerlessDomainContents(QUrl dom
bool success = tmpTree->readFromByteArray(domainURL.toString(), data);
if (success) {
tmpTree->reaverageOctreeElements();
- tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), 0, 0, 0);
+ tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), "domain", 0, 0, 0);
}
std::map namedPaths = tmpTree->getNamedPaths();
@@ -5545,8 +5550,8 @@ bool Application::importEntities(const QString& urlOrFilename, const bool isObse
return success;
}
-QVector Application::pasteEntities(float x, float y, float z) {
- return _entityClipboard->sendEntities(&_entityEditSender, getEntities()->getTree(), x, y, z);
+QVector Application::pasteEntities(const QString& entityHostType, float x, float y, float z) {
+ return _entityClipboard->sendEntities(&_entityEditSender, getEntities()->getTree(), entityHostType, x, y, z);
}
void Application::init() {
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 684ff6bdaa..3d4e6873a8 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -375,7 +375,7 @@ signals:
void awayStateWhenFocusLostInVRChanged(bool enabled);
public slots:
- QVector pasteEntities(float x, float y, float z);
+ QVector pasteEntities(const QString& entityHostType, float x, float y, float z);
bool exportEntities(const QString& filename, const QVector& entityIDs, const glm::vec3* givenOffset = nullptr);
bool exportEntities(const QString& filename, float x, float y, float z, float scale);
bool importEntities(const QString& url, const bool isObservable = true, const qint64 callerId = -1);
@@ -425,6 +425,7 @@ public slots:
#endif
static void showHelp();
+ static void gotoTutorial();
void cycleCamera();
void cameraModeChanged();
diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp
index a1bb670837..0ed5f67ea0 100644
--- a/interface/src/Menu.cpp
+++ b/interface/src/Menu.cpp
@@ -816,6 +816,8 @@ Menu::Menu() {
addActionToQMenuAndActionHash(helpMenu, "Controls Reference", 0, qApp, SLOT(showHelp()));
+ addActionToQMenuAndActionHash(helpMenu, "Tutorial", 0, qApp, SLOT(gotoTutorial()));
+
helpMenu->addSeparator();
// Help > Release Notes
diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp
index c0a6b64421..af7ac8165b 100644
--- a/interface/src/scripting/ClipboardScriptingInterface.cpp
+++ b/interface/src/scripting/ClipboardScriptingInterface.cpp
@@ -60,10 +60,11 @@ bool ClipboardScriptingInterface::importEntities(
return retVal;
}
-QVector ClipboardScriptingInterface::pasteEntities(glm::vec3 position) {
+QVector ClipboardScriptingInterface::pasteEntities(glm::vec3 position, const QString& entityHostType) {
QVector retVal;
BLOCKING_INVOKE_METHOD(qApp, "pasteEntities",
Q_RETURN_ARG(QVector, retVal),
+ Q_ARG(const QString&, entityHostType),
Q_ARG(float, position.x),
Q_ARG(float, position.y),
Q_ARG(float, position.z));
diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h
index 9e72d9ea15..9660b2158b 100644
--- a/interface/src/scripting/ClipboardScriptingInterface.h
+++ b/interface/src/scripting/ClipboardScriptingInterface.h
@@ -117,10 +117,11 @@ public:
* Pastes the contents of the clipboard into the domain.
* @function Clipboard.pasteEntities
* @param {Vec3} position - The position to paste the clipboard contents at.
+ * @param {Entities.EntityHostType} [entityHostType="domain"] - The type of entities to create.
* @returns {Uuid[]} The IDs of the new entities that were created as a result of the paste operation. If entities couldn't
* be created then an empty array is returned.
*/
- Q_INVOKABLE QVector pasteEntities(glm::vec3 position);
+ Q_INVOKABLE QVector pasteEntities(glm::vec3 position, const QString& entityHostType = "domain");
};
#endif // hifi_ClipboardScriptingInterface_h
diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp
index f34eb85230..bc56781924 100644
--- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp
@@ -199,7 +199,7 @@ float importanceSample3DDimension(float startDim) {
return dimension;
}
-ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createParticle(uint64_t now, const Transform& baseTransform, const particle::Properties& particleProperties,
+ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createParticle(const Transform& baseTransform, const particle::Properties& particleProperties,
const ShapeType& shapeType, const GeometryResource::Pointer& geometryResource,
const TriangleInfo& triangleInfo) {
CpuParticle particle;
@@ -217,7 +217,7 @@ ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createPa
const auto& polarFinish = particleProperties.polar.finish;
particle.seed = randFloatInRange(-1.0f, 1.0f);
- particle.expiration = now + (uint64_t)(particleProperties.lifespan * USECS_PER_SECOND);
+ particle.expiration = (uint64_t)(particleProperties.lifespan * USECS_PER_SECOND);
particle.relativePosition = glm::vec3(0.0f);
particle.basePosition = baseTransform.getTranslation();
@@ -403,7 +403,7 @@ void ParticleEffectEntityRenderer::stepSimulation() {
computeTriangles(geometryResource->getHFMModel());
}
// emit particle
- _cpuParticles.push_back(createParticle(now, modelTransform, particleProperties, shapeType, geometryResource, _triangleInfo));
+ _cpuParticles.push_back(createParticle(modelTransform, particleProperties, shapeType, geometryResource, _triangleInfo));
_timeUntilNextEmit = emitInterval;
if (emitInterval < timeRemaining) {
timeRemaining -= emitInterval;
@@ -415,7 +415,7 @@ void ParticleEffectEntityRenderer::stepSimulation() {
}
// Kill any particles that have expired or are over the max size
- while (_cpuParticles.size() > particleProperties.maxParticles || (!_cpuParticles.empty() && _cpuParticles.front().expiration <= now)) {
+ while (_cpuParticles.size() > particleProperties.maxParticles || (!_cpuParticles.empty() && _cpuParticles.front().expiration == 0)) {
_cpuParticles.pop_front();
}
@@ -428,6 +428,7 @@ void ParticleEffectEntityRenderer::stepSimulation() {
}
particle.basePosition = modelTransform.getTranslation();
}
+ particle.expiration = particle.expiration >= interval ? particle.expiration - interval : 0;
particle.integrate(deltaTime);
}
_prevEmitterShouldTrail = particleProperties.emission.shouldTrail;
diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h
index cc907f2b1d..8a3d8120f5 100644
--- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h
+++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h
@@ -88,7 +88,7 @@ private:
glm::mat4 transform;
} _triangleInfo;
- static CpuParticle createParticle(uint64_t now, const Transform& baseTransform, const particle::Properties& particleProperties,
+ static CpuParticle createParticle(const Transform& baseTransform, const particle::Properties& particleProperties,
const ShapeType& shapeType, const GeometryResource::Pointer& geometryResource,
const TriangleInfo& triangleInfo);
void stepSimulation();
diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp
index 1ce19033e5..7b339c090d 100644
--- a/libraries/entities/src/EntityTree.cpp
+++ b/libraries/entities/src/EntityTree.cpp
@@ -2657,11 +2657,12 @@ QByteArray EntityTree::remapActionDataIDs(QByteArray actionData, QHash EntityTree::sendEntities(EntityEditPacketSender* packetSender, EntityTreePointer localTree,
- float x, float y, float z) {
+ const QString& entityHostType, float x, float y, float z) {
SendEntitiesOperationArgs args;
args.ourTree = this;
args.otherTree = localTree;
args.root = glm::vec3(x, y, z);
+ args.entityHostType = entityHostType;
// If this is called repeatedly (e.g., multiple pastes with the same data), the new elements will clash unless we
// use new identifiers. We need to keep a map so that we can map parent identifiers correctly.
QHash map;
@@ -2751,6 +2752,11 @@ bool EntityTree::sendEntitiesOperation(const OctreeElementPointer& element, void
EntityItemID newID = getMapped(oldID);
EntityItemProperties properties = item->getProperties();
+ properties.setEntityHostTypeFromString(args->entityHostType);
+ if (properties.getEntityHostType() == entity::HostType::AVATAR) {
+ properties.setOwningAvatarID(AVATAR_SELF_ID);
+ }
+
EntityItemID oldParentID = properties.getParentID();
if (oldParentID.isInvalidID()) { // no parent
properties.setPosition(properties.getPosition() + args->root);
diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h
index 2d5119d626..9f59080718 100644
--- a/libraries/entities/src/EntityTree.h
+++ b/libraries/entities/src/EntityTree.h
@@ -40,6 +40,7 @@ public:
class SendEntitiesOperationArgs {
public:
glm::vec3 root;
+ QString entityHostType;
EntityTree* ourTree;
EntityTreePointer otherTree;
QHash* map;
@@ -177,7 +178,7 @@ public:
static QByteArray remapActionDataIDs(QByteArray actionData, QHash& map);
QVector sendEntities(EntityEditPacketSender* packetSender, EntityTreePointer localTree,
- float x, float y, float z);
+ const QString& entityHostType, float x, float y, float z);
void entityChanged(EntityItemPointer entity);
diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h
index 8bdb777f96..148c4f8580 100644
--- a/libraries/networking/src/AddressManager.h
+++ b/libraries/networking/src/AddressManager.h
@@ -249,8 +249,9 @@ public slots:
* Takes you to a specified metaverse address.
* @function location.handleLookupString
* @param {string} address - The address to go to: a "hifi://"
address, an IP address (e.g.,
- * "127.0.0.1"
or "localhost"
), a domain name, a named path on a domain (starts with
- * "/"
), a position or position and orientation, or a user (starts with "@"
).
+ * "127.0.0.1"
or "localhost"
), a file:///
address, a domain name, a named path
+ * on a domain (starts with "/"
), a position or position and orientation, or a user (starts with
+ * "@"
).
* @param {boolean} [fromSuggestions=false] - Set to true
if the address is obtained from the "Goto" dialog.
* Helps ensure that user's location history is correctly maintained.
*/
diff --git a/libraries/shared/src/NumericalConstants.h b/libraries/shared/src/NumericalConstants.h
index 8377c48960..b7fecfa1e4 100644
--- a/libraries/shared/src/NumericalConstants.h
+++ b/libraries/shared/src/NumericalConstants.h
@@ -28,8 +28,8 @@ const float ARCSECONDS_PER_ARCMINUTE = 60.0f;
const float ARCSECONDS_PER_DEGREE = ARCMINUTES_PER_DEGREE * ARCSECONDS_PER_ARCMINUTE;
const float EPSILON = 0.000001f; //smallish positive number - used as margin of error for some computations
-const float SQUARE_ROOT_OF_2 = (float)sqrt(2.0f);
-const float SQUARE_ROOT_OF_3 = (float)sqrt(3.0f);
+const float SQUARE_ROOT_OF_2 = 1.414214f;
+const float SQUARE_ROOT_OF_3 = 1.732051f;
const float METERS_PER_DECIMETER = 0.1f;
const float METERS_PER_CENTIMETER = 0.01f;
const float METERS_PER_MILLIMETER = 0.001f;
diff --git a/scripts/communityModules/chat/FloofChat.html b/scripts/communityScripts/chat/FloofChat.html
similarity index 80%
rename from scripts/communityModules/chat/FloofChat.html
rename to scripts/communityScripts/chat/FloofChat.html
index a1e84e132f..7baac63455 100644
--- a/scripts/communityModules/chat/FloofChat.html
+++ b/scripts/communityScripts/chat/FloofChat.html
@@ -12,6 +12,7 @@
+
@@ -28,11 +29,19 @@
+
+
+
+
@@ -46,6 +55,7 @@