mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
Merge branch 'protocol_changes' into zoneProps
This commit is contained in:
commit
c72f22e4ee
65 changed files with 1553 additions and 1325 deletions
|
@ -816,6 +816,7 @@ void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
|
|||
void AudioMixer::setupEntityQuery() {
|
||||
_entityViewer.init();
|
||||
EntityTreePointer entityTree = _entityViewer.getTree();
|
||||
entityTree->setIsServer(true);
|
||||
DependencyManager::registerInheritance<SpatialParentFinder, AssignmentParentFinder>();
|
||||
DependencyManager::set<AssignmentParentFinder>(entityTree);
|
||||
|
||||
|
|
|
@ -1081,6 +1081,7 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) {
|
|||
void AvatarMixer::setupEntityQuery() {
|
||||
_entityViewer.init();
|
||||
EntityTreePointer entityTree = _entityViewer.getTree();
|
||||
entityTree->setIsServer(true);
|
||||
DependencyManager::registerInheritance<SpatialParentFinder, AssignmentParentFinder>();
|
||||
DependencyManager::set<AssignmentParentFinder>(entityTree);
|
||||
|
||||
|
|
|
@ -67,8 +67,6 @@
|
|||
* @property {boolean} lookAtSnappingEnabled=true - <code>true</code> if the avatar's eyes snap to look at another avatar's
|
||||
* eyes when the other avatar is in the line of sight and also has <code>lookAtSnappingEnabled == true</code>.
|
||||
* @property {string} skeletonModelURL - The avatar's FST file.
|
||||
* @property {AttachmentData[]} attachmentData - Information on the avatar's attachments.
|
||||
* <p class="important">Deprecated: This property is deprecated and will be removed. Use avatar entities instead.</p>
|
||||
* @property {string[]} jointNames - The list of joints in the current avatar model. <em>Read-only.</em>
|
||||
* @property {Uuid} sessionUUID - Unique ID of the avatar in the domain. <em>Read-only.</em>
|
||||
* @property {Mat4} sensorToWorldMatrix - The scale, rotation, and translation transform from the user's real world to the
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include <AudioInjectorManager.h>
|
||||
#include <EntityTree.h>
|
||||
#include <ResourceCache.h>
|
||||
#include <ScriptCache.h>
|
||||
#include <SoundCache.h>
|
||||
#include <plugins/PluginManager.h>
|
||||
#include <EntityEditFilters.h>
|
||||
#include <NetworkingConstants.h>
|
||||
|
@ -49,6 +51,9 @@ EntityServer::EntityServer(ReceivedMessage& message) :
|
|||
DependencyManager::set<ModelFormatRegistry>(); // ModelFormatRegistry must be defined before ModelCache. See the ModelCache ctor
|
||||
DependencyManager::set<ModelCache>();
|
||||
|
||||
DependencyManager::set<SoundCache>();
|
||||
DependencyManager::set<AudioInjectorManager>();
|
||||
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListenerForTypes({ PacketType::EntityAdd,
|
||||
PacketType::EntityClone,
|
||||
|
@ -71,6 +76,8 @@ EntityServer::~EntityServer() {
|
|||
void EntityServer::aboutToFinish() {
|
||||
DependencyManager::get<ResourceManager>()->cleanup();
|
||||
|
||||
DependencyManager::destroy<AudioInjectorManager>();
|
||||
DependencyManager::destroy<SoundCache>();
|
||||
DependencyManager::destroy<AssignmentDynamicFactory>();
|
||||
|
||||
OctreeServer::aboutToFinish();
|
||||
|
@ -90,6 +97,7 @@ OctreePointer EntityServer::createTree() {
|
|||
EntityTreePointer tree = std::make_shared<EntityTree>(true);
|
||||
tree->createRootElement();
|
||||
tree->addNewlyCreatedHook(this);
|
||||
tree->setIsEntityServer(true);
|
||||
if (!_entitySimulation) {
|
||||
SimpleEntitySimulationPointer simpleSimulation { new SimpleEntitySimulation() };
|
||||
simpleSimulation->setEntityTree(tree);
|
||||
|
|
|
@ -316,6 +316,7 @@ void EntityScriptServer::run() {
|
|||
entityScriptingInterface->setEntityTree(_entityViewer.getTree());
|
||||
|
||||
auto treePtr = _entityViewer.getTree();
|
||||
treePtr->setIsServer(true);
|
||||
DependencyManager::set<AssignmentParentFinder>(treePtr);
|
||||
|
||||
if (!_entitySimulation) {
|
||||
|
|
|
@ -316,7 +316,6 @@ static const QString JS_EXTENSION = ".js";
|
|||
static const QString FST_EXTENSION = ".fst";
|
||||
static const QString FBX_EXTENSION = ".fbx";
|
||||
static const QString OBJ_EXTENSION = ".obj";
|
||||
static const QString AVA_JSON_EXTENSION = ".ava.json";
|
||||
static const QString WEB_VIEW_TAG = "noDownload=true";
|
||||
static const QString ZIP_EXTENSION = ".zip";
|
||||
static const QString CONTENT_ZIP_EXTENSION = ".content.zip";
|
||||
|
@ -365,7 +364,6 @@ static const QString TESTER_FILE = "/sdcard/_hifi_test_device.txt";
|
|||
const std::vector<std::pair<QString, Application::AcceptURLMethod>> Application::_acceptedExtensions {
|
||||
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
||||
{ SVO_JSON_EXTENSION, &Application::importSVOFromURL },
|
||||
{ AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl },
|
||||
{ JSON_EXTENSION, &Application::importJSONFromURL },
|
||||
{ JS_EXTENSION, &Application::askToLoadScript },
|
||||
{ FST_EXTENSION, &Application::askToSetAvatarUrl },
|
||||
|
@ -7838,74 +7836,6 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Application::askToWearAvatarAttachmentUrl(const QString& url) {
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkRequest networkRequest = QNetworkRequest(url);
|
||||
networkRequest.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::OVERTE_USER_AGENT);
|
||||
QNetworkReply* reply = networkAccessManager.get(networkRequest);
|
||||
int requestNumber = ++_avatarAttachmentRequest;
|
||||
connect(reply, &QNetworkReply::finished, [this, reply, url, requestNumber]() {
|
||||
|
||||
if (requestNumber != _avatarAttachmentRequest) {
|
||||
// this request has been superseded by another more recent request
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
QNetworkReply::NetworkError networkError = reply->error();
|
||||
if (networkError == QNetworkReply::NoError) {
|
||||
// download success
|
||||
QByteArray contents = reply->readAll();
|
||||
|
||||
QJsonParseError jsonError;
|
||||
auto doc = QJsonDocument::fromJson(contents, &jsonError);
|
||||
if (jsonError.error == QJsonParseError::NoError) {
|
||||
|
||||
auto jsonObject = doc.object();
|
||||
|
||||
// retrieve optional name field from JSON
|
||||
QString name = tr("Unnamed Attachment");
|
||||
auto nameValue = jsonObject.value("name");
|
||||
if (nameValue.isString()) {
|
||||
name = nameValue.toString();
|
||||
}
|
||||
|
||||
auto avatarAttachmentConfirmationTitle = tr("Avatar Attachment Confirmation");
|
||||
auto avatarAttachmentConfirmationMessage = tr("Would you like to wear '%1' on your avatar?").arg(name);
|
||||
ModalDialogListener* dlg = OffscreenUi::asyncQuestion(avatarAttachmentConfirmationTitle,
|
||||
avatarAttachmentConfirmationMessage,
|
||||
QMessageBox::Ok | QMessageBox::Cancel);
|
||||
QObject::connect(dlg, &ModalDialogListener::response, this, [=] (QVariant answer) {
|
||||
QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr);
|
||||
if (static_cast<QMessageBox::StandardButton>(answer.toInt()) == QMessageBox::Yes) {
|
||||
// add attachment to avatar
|
||||
auto myAvatar = getMyAvatar();
|
||||
assert(myAvatar);
|
||||
auto attachmentDataVec = myAvatar->getAttachmentData();
|
||||
AttachmentData attachmentData;
|
||||
attachmentData.fromJson(jsonObject);
|
||||
attachmentDataVec.push_back(attachmentData);
|
||||
myAvatar->setAttachmentData(attachmentDataVec);
|
||||
} else {
|
||||
qCDebug(interfaceapp) << "User declined to wear the avatar attachment";
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// json parse error
|
||||
auto avatarAttachmentParseErrorString = tr("Error parsing attachment JSON from url: \"%1\"");
|
||||
displayAvatarAttachmentWarning(avatarAttachmentParseErrorString.arg(url));
|
||||
}
|
||||
} else {
|
||||
// download failure
|
||||
auto avatarAttachmentDownloadErrorString = tr("Error downloading attachment JSON from url: \"%1\"");
|
||||
displayAvatarAttachmentWarning(avatarAttachmentDownloadErrorString.arg(url));
|
||||
}
|
||||
reply->deleteLater();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
static const QString CONTENT_SET_NAME_QUERY_PARAM = "name";
|
||||
|
||||
void Application::replaceDomainContent(const QString& url, const QString& itemName) {
|
||||
|
@ -7984,11 +7914,6 @@ bool Application::askToReplaceDomainContent(const QString& url) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void Application::displayAvatarAttachmentWarning(const QString& message) const {
|
||||
auto avatarAttachmentWarningTitle = tr("Avatar Attachment Failure");
|
||||
OffscreenUi::asyncWarning(avatarAttachmentWarningTitle, message);
|
||||
}
|
||||
|
||||
void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const QString& name) const {
|
||||
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet(SYSTEM_TABLET);
|
||||
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||
|
|
|
@ -546,9 +546,6 @@ private slots:
|
|||
bool askToSetAvatarUrl(const QString& url);
|
||||
bool askToLoadScript(const QString& scriptFilenameOrURL);
|
||||
|
||||
bool askToWearAvatarAttachmentUrl(const QString& url);
|
||||
void displayAvatarAttachmentWarning(const QString& message) const;
|
||||
|
||||
bool askToReplaceDomainContent(const QString& url);
|
||||
|
||||
void setSessionUUID(const QUuid& sessionUUID) const;
|
||||
|
@ -800,8 +797,6 @@ private:
|
|||
bool _reticleClickPressed { false };
|
||||
bool _keyboardFocusWaitingOnRenderable { false };
|
||||
|
||||
int _avatarAttachmentRequest = 0;
|
||||
|
||||
bool _settingsLoaded { false };
|
||||
|
||||
bool _captureMouse { false };
|
||||
|
|
|
@ -222,8 +222,6 @@ void AvatarBookmarks::updateAvatarEntities(const QVariantList &avatarEntities) {
|
|||
* @property {number} avatarScale - The target scale of the avatar.
|
||||
* @property {Array<Object<"properties",Entities.EntityProperties>>} [avatarEntites] - The avatar entities included with the
|
||||
* bookmark.
|
||||
* @property {AttachmentData[]} [attachments] - The attachments included with the bookmark.
|
||||
* <p class="important">Deprecated: Use avatar entities instead.
|
||||
*/
|
||||
|
||||
void AvatarBookmarks::loadBookmark(const QString& bookmarkName) {
|
||||
|
@ -266,8 +264,6 @@ void AvatarBookmarks::loadBookmarkInternal(const QString& bookmarkName) {
|
|||
myAvatar->clearWornAvatarEntities();
|
||||
const float& qScale = bookmark.value(ENTRY_AVATAR_SCALE, 1.0f).toFloat();
|
||||
myAvatar->setAvatarScale(qScale);
|
||||
QList<QVariant> attachments = bookmark.value(ENTRY_AVATAR_ATTACHMENTS, QList<QVariant>()).toList();
|
||||
myAvatar->setAttachmentsVariant(attachments);
|
||||
QVariantList avatarEntities = bookmark.value(ENTRY_AVATAR_ENTITIES, QVariantList()).toList();
|
||||
addAvatarEntities(avatarEntities);
|
||||
emit bookmarkLoaded(bookmarkName);
|
||||
|
@ -335,7 +331,6 @@ QVariantMap AvatarBookmarks::getAvatarDataToBookmark() {
|
|||
const QString& avatarIcon = QString("");
|
||||
const QVariant& avatarScale = myAvatar->getAvatarScale();
|
||||
|
||||
// If Avatar attachments ever change, this is where to update them, when saving remember to also append to AVATAR_BOOKMARK_VERSION
|
||||
QVariantMap bookmark;
|
||||
bookmark.insert(ENTRY_VERSION, AVATAR_BOOKMARK_VERSION);
|
||||
bookmark.insert(ENTRY_AVATAR_URL, avatarUrl);
|
||||
|
|
|
@ -66,8 +66,7 @@ public slots:
|
|||
void saveBookmark(const QString& bookmarkName);
|
||||
|
||||
/*@jsdoc
|
||||
* Loads an avatar bookmark, setting your avatar model, scale, and avatar entities (or attachments if an old bookmark) to
|
||||
* those in the bookmark.
|
||||
* Loads an avatar bookmark, setting your avatar model, scale, and avatar entities to those in the bookmark.
|
||||
* @function AvatarBookmarks.loadBookmark
|
||||
* @param {string} bookmarkName - The name of the avatar bookmark to load (case sensitive).
|
||||
*/
|
||||
|
@ -104,8 +103,7 @@ public slots:
|
|||
|
||||
signals:
|
||||
/*@jsdoc
|
||||
* Triggered when an avatar bookmark is loaded, setting your avatar model, scale, and avatar entities (or attachments if an
|
||||
* old bookmark) to those in the bookmark.
|
||||
* Triggered when an avatar bookmark is loaded, setting your avatar model, scale, and avatar entities to those in the bookmark.
|
||||
* @function AvatarBookmarks.bookmarkLoaded
|
||||
* @param {string} bookmarkName - The name of the avatar bookmark loaded.
|
||||
* @returns {Signal}
|
||||
|
@ -155,7 +153,6 @@ private:
|
|||
const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json";
|
||||
const QString ENTRY_AVATAR_URL = "avatarUrl";
|
||||
const QString ENTRY_AVATAR_ICON = "avatarIcon";
|
||||
const QString ENTRY_AVATAR_ATTACHMENTS = "attachments";
|
||||
const QString ENTRY_AVATAR_ENTITIES = "avatarEntites";
|
||||
const QString ENTRY_AVATAR_SCALE = "avatarScale";
|
||||
const QString ENTRY_VERSION = "version";
|
||||
|
|
|
@ -272,12 +272,6 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
auto hfmModel = getSkeletonModel()->getHFMModel();
|
||||
qApp->loadAvatarScripts(hfmModel.scripts);
|
||||
_shouldLoadScripts = false;
|
||||
}
|
||||
// Load and convert old attachments to avatar entities
|
||||
if (_oldAttachmentData.size() > 0) {
|
||||
setAttachmentData(_oldAttachmentData);
|
||||
_oldAttachmentData.clear();
|
||||
_attachmentData.clear();
|
||||
}
|
||||
});
|
||||
connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady);
|
||||
|
@ -371,10 +365,6 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
setWorldPosition(dummyAvatar.getWorldPosition());
|
||||
setWorldOrientation(dummyAvatar.getWorldOrientation());
|
||||
|
||||
if (!dummyAvatar.getAttachmentData().isEmpty()) {
|
||||
setAttachmentData(dummyAvatar.getAttachmentData());
|
||||
}
|
||||
|
||||
auto headData = dummyAvatar.getHeadData();
|
||||
if (headData && _headData) {
|
||||
// blendshapes
|
||||
|
@ -501,11 +491,6 @@ glm::quat MyAvatar::getOrientationOutbound() const {
|
|||
return (slerp(_smoothOrientationInitial, _smoothOrientationTarget, interp));
|
||||
}
|
||||
|
||||
// virtual
|
||||
void MyAvatar::simulateAttachments(float deltaTime) {
|
||||
// don't update attachments here, do it in harvestResultsFromPhysicsSimulation()
|
||||
}
|
||||
|
||||
QByteArray MyAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) {
|
||||
CameraMode mode = qApp->getCamera().getMode();
|
||||
_globalPosition = getWorldPosition();
|
||||
|
@ -982,8 +967,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
|
|||
}
|
||||
|
||||
// we've achived our final adjusted position and rotation for the avatar
|
||||
// and all of its joints, now update our attachements.
|
||||
Avatar::simulateAttachments(deltaTime);
|
||||
// and all of its joints, now update our children.
|
||||
relayJointDataToChildren();
|
||||
if (applyGrabChanges()) {
|
||||
_cauterizationNeedsUpdate = true;
|
||||
|
@ -2175,65 +2159,6 @@ void MyAvatar::loadAvatarEntityDataFromSettings() {
|
|||
});
|
||||
}
|
||||
|
||||
void MyAvatar::saveAttachmentData(const AttachmentData& attachment) const {
|
||||
Settings settings;
|
||||
settings.beginGroup("savedAttachmentData");
|
||||
settings.beginGroup(_skeletonModel->getURL().toString());
|
||||
settings.beginGroup(attachment.modelURL.toString());
|
||||
settings.setValue("jointName", attachment.jointName);
|
||||
|
||||
settings.beginGroup(attachment.jointName);
|
||||
settings.setValue("translation_x", attachment.translation.x);
|
||||
settings.setValue("translation_y", attachment.translation.y);
|
||||
settings.setValue("translation_z", attachment.translation.z);
|
||||
glm::vec3 eulers = safeEulerAngles(attachment.rotation);
|
||||
settings.setValue("rotation_x", eulers.x);
|
||||
settings.setValue("rotation_y", eulers.y);
|
||||
settings.setValue("rotation_z", eulers.z);
|
||||
settings.setValue("scale", attachment.scale);
|
||||
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
AttachmentData MyAvatar::loadAttachmentData(const QUrl& modelURL, const QString& jointName) const {
|
||||
Settings settings;
|
||||
settings.beginGroup("savedAttachmentData");
|
||||
settings.beginGroup(_skeletonModel->getURL().toString());
|
||||
settings.beginGroup(modelURL.toString());
|
||||
|
||||
AttachmentData attachment;
|
||||
attachment.modelURL = modelURL;
|
||||
if (jointName.isEmpty()) {
|
||||
attachment.jointName = settings.value("jointName").toString();
|
||||
} else {
|
||||
attachment.jointName = jointName;
|
||||
}
|
||||
settings.beginGroup(attachment.jointName);
|
||||
if (settings.contains("translation_x")) {
|
||||
attachment.translation.x = loadSetting(settings, "translation_x", 0.0f);
|
||||
attachment.translation.y = loadSetting(settings, "translation_y", 0.0f);
|
||||
attachment.translation.z = loadSetting(settings, "translation_z", 0.0f);
|
||||
glm::vec3 eulers;
|
||||
eulers.x = loadSetting(settings, "rotation_x", 0.0f);
|
||||
eulers.y = loadSetting(settings, "rotation_y", 0.0f);
|
||||
eulers.z = loadSetting(settings, "rotation_z", 0.0f);
|
||||
attachment.rotation = glm::quat(eulers);
|
||||
attachment.scale = loadSetting(settings, "scale", 1.0f);
|
||||
} else {
|
||||
attachment = AttachmentData();
|
||||
}
|
||||
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
|
||||
return attachment;
|
||||
}
|
||||
|
||||
bool MyAvatar::isMyAvatarURLProtected() const {
|
||||
return !ScriptPermissions::isCurrentScriptAllowed(ScriptPermissions::Permission::SCRIPT_PERMISSION_GET_AVATAR_URL);
|
||||
}
|
||||
|
@ -2994,171 +2919,6 @@ SharedSoundPointer MyAvatar::getCollisionSound() {
|
|||
return _collisionSound;
|
||||
}
|
||||
|
||||
void MyAvatar::attach(const QString& modelURL, const QString& jointName,
|
||||
const glm::vec3& translation, const glm::quat& rotation,
|
||||
float scale, bool isSoft,
|
||||
bool allowDuplicates, bool useSaved) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "attach",
|
||||
Q_ARG(const QString&, modelURL),
|
||||
Q_ARG(const QString&, jointName),
|
||||
Q_ARG(const glm::vec3&, translation),
|
||||
Q_ARG(const glm::quat&, rotation),
|
||||
Q_ARG(float, scale),
|
||||
Q_ARG(bool, isSoft),
|
||||
Q_ARG(bool, allowDuplicates),
|
||||
Q_ARG(bool, useSaved)
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring attach() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
AttachmentData data;
|
||||
data.modelURL = modelURL;
|
||||
data.jointName = jointName;
|
||||
data.translation = translation;
|
||||
data.rotation = rotation;
|
||||
data.scale = scale;
|
||||
data.isSoft = isSoft;
|
||||
EntityItemProperties properties;
|
||||
attachmentDataToEntityProperties(data, properties);
|
||||
DependencyManager::get<EntityScriptingInterface>()->addEntity(properties, true);
|
||||
emit attachmentsChanged();
|
||||
}
|
||||
|
||||
void MyAvatar::detachOne(const QString& modelURL, const QString& jointName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "detachOne",
|
||||
Q_ARG(const QString&, modelURL),
|
||||
Q_ARG(const QString&, jointName)
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring detachOne() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
QUuid entityID;
|
||||
if (findAvatarEntity(modelURL, jointName, entityID)) {
|
||||
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(entityID);
|
||||
}
|
||||
emit attachmentsChanged();
|
||||
}
|
||||
|
||||
void MyAvatar::detachAll(const QString& modelURL, const QString& jointName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "detachAll",
|
||||
Q_ARG(const QString&, modelURL),
|
||||
Q_ARG(const QString&, jointName)
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring detachAll() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
QUuid entityID;
|
||||
while (findAvatarEntity(modelURL, jointName, entityID)) {
|
||||
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(entityID);
|
||||
}
|
||||
emit attachmentsChanged();
|
||||
}
|
||||
|
||||
void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "setAttachmentData",
|
||||
Q_ARG(const QVector<AttachmentData>&, attachmentData));
|
||||
return;
|
||||
}
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring setAttachmentData() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<EntityItemProperties> newEntitiesProperties;
|
||||
for (auto& data : attachmentData) {
|
||||
QUuid entityID;
|
||||
EntityItemProperties properties;
|
||||
if (findAvatarEntity(data.modelURL.toString(), data.jointName, entityID)) {
|
||||
properties = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
|
||||
}
|
||||
attachmentDataToEntityProperties(data, properties);
|
||||
newEntitiesProperties.push_back(properties);
|
||||
}
|
||||
|
||||
// clear any existing wearables
|
||||
clearWornAvatarEntities();
|
||||
|
||||
for (auto& properties : newEntitiesProperties) {
|
||||
DependencyManager::get<EntityScriptingInterface>()->addEntity(properties, true);
|
||||
}
|
||||
emit attachmentsChanged();
|
||||
}
|
||||
|
||||
QVector<AttachmentData> MyAvatar::getAttachmentData() const {
|
||||
QVector<AttachmentData> attachmentData;
|
||||
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp) << "Ignoring getAttachmentData() because don't have canRezAvatarEntities permission on domain";
|
||||
return attachmentData;
|
||||
}
|
||||
|
||||
QList<QUuid> avatarEntityIDs;
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
avatarEntityIDs = _packedAvatarEntityData.keys();
|
||||
});
|
||||
for (const auto& entityID : avatarEntityIDs) {
|
||||
auto properties = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
|
||||
AttachmentData data = entityPropertiesToAttachmentData(properties);
|
||||
attachmentData.append(data);
|
||||
}
|
||||
return attachmentData;
|
||||
}
|
||||
|
||||
QVariantList MyAvatar::getAttachmentsVariant() const {
|
||||
QVariantList result;
|
||||
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp)
|
||||
<< "Ignoring getAttachmentsVariant() because don't have canRezAvatarEntities permission on domain";
|
||||
return result;
|
||||
}
|
||||
|
||||
for (const auto& attachment : getAttachmentData()) {
|
||||
result.append(attachment.toVariant());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void MyAvatar::setAttachmentsVariant(const QVariantList& variant) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "setAttachmentsVariant",
|
||||
Q_ARG(const QVariantList&, variant));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
||||
qCDebug(interfaceapp)
|
||||
<< "Ignoring setAttachmentsVariant() because don't have canRezAvatarEntities permission on domain";
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<AttachmentData> newAttachments;
|
||||
newAttachments.reserve(variant.size());
|
||||
for (const auto& attachmentVar : variant) {
|
||||
AttachmentData attachment;
|
||||
if (attachment.fromVariant(attachmentVar)) {
|
||||
newAttachments.append(attachment);
|
||||
}
|
||||
}
|
||||
setAttachmentData(newAttachments);
|
||||
}
|
||||
|
||||
bool MyAvatar::findAvatarEntity(const QString& modelURL, const QString& jointName, QUuid& entityID) {
|
||||
QList<QUuid> avatarEntityIDs;
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
|
@ -3174,34 +2934,6 @@ bool MyAvatar::findAvatarEntity(const QString& modelURL, const QString& jointNam
|
|||
return false;
|
||||
}
|
||||
|
||||
AttachmentData MyAvatar::entityPropertiesToAttachmentData(const EntityItemProperties& properties) const {
|
||||
AttachmentData data;
|
||||
data.modelURL = properties.getModelURL();
|
||||
data.translation = properties.getLocalPosition();
|
||||
data.rotation = properties.getLocalRotation();
|
||||
data.isSoft = properties.getRelayParentJoints();
|
||||
int jointIndex = (int)properties.getParentJointIndex();
|
||||
if (jointIndex > -1 && jointIndex < getJointNames().size()) {
|
||||
data.jointName = getJointNames()[jointIndex];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void MyAvatar::attachmentDataToEntityProperties(const AttachmentData& data, EntityItemProperties& properties) {
|
||||
QString url = data.modelURL.toString();
|
||||
properties.setName(QFileInfo(url).baseName());
|
||||
properties.setType(EntityTypes::Model);
|
||||
properties.setParentID(AVATAR_SELF_ID);
|
||||
properties.setLocalPosition(data.translation);
|
||||
properties.setLocalRotation(data.rotation);
|
||||
if (!data.isSoft) {
|
||||
properties.setParentJointIndex(getJointIndex(data.jointName));
|
||||
} else {
|
||||
properties.setRelayParentJoints(true);
|
||||
}
|
||||
properties.setModelURL(url);
|
||||
}
|
||||
|
||||
void MyAvatar::initHeadBones() {
|
||||
int neckJointIndex = -1;
|
||||
if (_skeletonModel->isLoaded()) {
|
||||
|
@ -3444,22 +3176,6 @@ void MyAvatar::preDisplaySide(const RenderArgs* renderArgs) {
|
|||
if (shouldDrawHead != _prevShouldDrawHead) {
|
||||
_cauterizationNeedsUpdate = true;
|
||||
_skeletonModel->setEnableCauterization(!shouldDrawHead);
|
||||
|
||||
for (int i = 0; i < _attachmentData.size(); i++) {
|
||||
if (_attachmentData[i].jointName.compare("Head", Qt::CaseInsensitive) == 0 ||
|
||||
_attachmentData[i].jointName.compare("Neck", Qt::CaseInsensitive) == 0 ||
|
||||
_attachmentData[i].jointName.compare("LeftEye", Qt::CaseInsensitive) == 0 ||
|
||||
_attachmentData[i].jointName.compare("RightEye", Qt::CaseInsensitive) == 0 ||
|
||||
_attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 ||
|
||||
_attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) {
|
||||
uint8_t modelRenderTagBits = shouldDrawHead ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_SECONDARY_VIEW;
|
||||
|
||||
_attachmentModels[i]->setTagMask(modelRenderTagBits);
|
||||
_attachmentModels[i]->setGroupCulled(false);
|
||||
_attachmentModels[i]->setCanCastShadow(true);
|
||||
_attachmentModels[i]->setVisibleInScene(true, qApp->getMain3DScene());
|
||||
}
|
||||
}
|
||||
}
|
||||
_prevShouldDrawHead = shouldDrawHead;
|
||||
}
|
||||
|
|
|
@ -141,8 +141,6 @@ class MyAvatar : public Avatar {
|
|||
* @property {boolean} lookAtSnappingEnabled=true - <code>true</code> if the avatar's eyes snap to look at another avatar's
|
||||
* eyes when the other avatar is in the line of sight and also has <code>lookAtSnappingEnabled == true</code>.
|
||||
* @property {string} skeletonModelURL - The avatar's FST file.
|
||||
* @property {AttachmentData[]} attachmentData - Information on the avatar's attachments.
|
||||
* <p class="important">Deprecated: This property is deprecated and will be removed. Use avatar entities instead.</p>
|
||||
* @property {string[]} jointNames - The list of joints in the current avatar model. <em>Read-only.</em>
|
||||
* @property {Uuid} sessionUUID - Unique ID of the avatar in the domain. <em>Read-only.</em>
|
||||
* @property {Mat4} sensorToWorldMatrix - The scale, rotation, and translation transform from the user's real world to the
|
||||
|
@ -326,17 +324,10 @@ class MyAvatar : public Avatar {
|
|||
* @borrows Avatar.getJointIndex as getJointIndex
|
||||
* @borrows Avatar.getJointNames as getJointNames
|
||||
* @borrows Avatar.setBlendshape as setBlendshape
|
||||
* @borrows Avatar.getAttachmentsVariant as getAttachmentsVariant
|
||||
* @borrows Avatar.setAttachmentsVariant as setAttachmentsVariant
|
||||
* @borrows Avatar.updateAvatarEntity as updateAvatarEntity
|
||||
* @borrows Avatar.clearAvatarEntity as clearAvatarEntity
|
||||
* @borrows Avatar.setForceFaceTrackerConnected as setForceFaceTrackerConnected
|
||||
* @borrows Avatar.setSkeletonModelURL as setSkeletonModelURL
|
||||
* @borrows Avatar.getAttachmentData as getAttachmentData
|
||||
* @borrows Avatar.setAttachmentData as setAttachmentData
|
||||
* @borrows Avatar.attach as attach
|
||||
* @borrows Avatar.detachOne as detachOne
|
||||
* @borrows Avatar.detachAll as detachAll
|
||||
* @comment Avatar.getAvatarEntityData as getAvatarEntityData - Don't borrow because implementation is different.
|
||||
* @comment Avatar.setAvatarEntityData as setAvatarEntityData - Don't borrow because implementation is different.
|
||||
* @borrows Avatar.getSensorToWorldMatrix as getSensorToWorldMatrix
|
||||
|
@ -590,8 +581,6 @@ public:
|
|||
static void registerMetaTypes(ScriptEnginePointer engine);
|
||||
void registerProperties(ScriptEnginePointer engine);
|
||||
|
||||
virtual void simulateAttachments(float deltaTime) override;
|
||||
|
||||
AudioListenerMode getAudioListenerModeHead() const { return FROM_HEAD; }
|
||||
AudioListenerMode getAudioListenerModeCamera() const { return FROM_CAMERA; }
|
||||
AudioListenerMode getAudioListenerModeCustom() const { return CUSTOM; }
|
||||
|
@ -1073,9 +1062,6 @@ public:
|
|||
void loadData();
|
||||
void loadAvatarEntityDataFromSettings();
|
||||
|
||||
void saveAttachmentData(const AttachmentData& attachment) const;
|
||||
AttachmentData loadAttachmentData(const QUrl& modelURL, const QString& jointName = QString()) const;
|
||||
|
||||
// Set what driving keys are being pressed to control thrust levels
|
||||
void clearDriveKeys();
|
||||
void setDriveKey(DriveKeys key, float val);
|
||||
|
@ -1822,12 +1808,6 @@ public:
|
|||
float computeStandingHeightMode(const controller::Pose& head);
|
||||
glm::quat computeAverageHeadRotation(const controller::Pose& head);
|
||||
|
||||
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
|
||||
virtual QVector<AttachmentData> getAttachmentData() const override;
|
||||
|
||||
virtual QVariantList getAttachmentsVariant() const override;
|
||||
virtual void setAttachmentsVariant(const QVariantList& variant) override;
|
||||
|
||||
glm::vec3 getNextPosition() { return _goToPending ? _goToPosition : getWorldPosition(); }
|
||||
void prepareAvatarEntityDataForReload();
|
||||
|
||||
|
@ -2610,16 +2590,6 @@ signals:
|
|||
*/
|
||||
void sensorToWorldScaleChanged(float sensorToWorldScale);
|
||||
|
||||
/*@jsdoc
|
||||
* Triggered when the a model is attached to or detached from one of the avatar's joints using one of
|
||||
* {@link MyAvatar.attach|attach}, {@link MyAvatar.detachOne|detachOne}, {@link MyAvatar.detachAll|detachAll}, or
|
||||
* {@link MyAvatar.setAttachmentData|setAttachmentData}.
|
||||
* @function MyAvatar.attachmentsChanged
|
||||
* @returns {Signal}
|
||||
* @deprecated This signal is deprecated and will be removed. Use avatar entities instead.
|
||||
*/
|
||||
void attachmentsChanged();
|
||||
|
||||
/*@jsdoc
|
||||
* Triggered when the avatar's size changes. This can be due to the user changing the size of their avatar or the domain
|
||||
* limiting the size of their avatar.
|
||||
|
@ -2701,18 +2671,7 @@ private:
|
|||
void setScriptedMotorFrame(QString frame);
|
||||
void setScriptedMotorMode(QString mode);
|
||||
|
||||
// Attachments
|
||||
virtual void attach(const QString& modelURL, const QString& jointName = QString(),
|
||||
const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(),
|
||||
float scale = 1.0f, bool isSoft = false,
|
||||
bool allowDuplicates = false, bool useSaved = true) override;
|
||||
|
||||
virtual void detachOne(const QString& modelURL, const QString& jointName = QString()) override;
|
||||
virtual void detachAll(const QString& modelURL, const QString& jointName = QString()) override;
|
||||
|
||||
// Attachments/Avatar Entity
|
||||
void attachmentDataToEntityProperties(const AttachmentData& data, EntityItemProperties& properties);
|
||||
AttachmentData entityPropertiesToAttachmentData(const EntityItemProperties& properties) const;
|
||||
// Avatar Entities
|
||||
bool findAvatarEntity(const QString& modelURL, const QString& jointName, QUuid& entityID);
|
||||
void addAvatarEntitiesToTree();
|
||||
|
||||
|
|
|
@ -316,7 +316,6 @@ void OtherAvatar::simulate(float deltaTime, bool inView) {
|
|||
{
|
||||
PROFILE_RANGE(simulation, "misc");
|
||||
measureMotionDerivatives(deltaTime);
|
||||
simulateAttachments(deltaTime);
|
||||
updatePalms();
|
||||
}
|
||||
{
|
||||
|
@ -384,7 +383,7 @@ void OtherAvatar::debugJointData() const {
|
|||
}
|
||||
|
||||
void OtherAvatar::handleChangedAvatarEntityData() {
|
||||
PerformanceTimer perfTimer("attachments");
|
||||
PerformanceTimer perfTimer("avatarEntities");
|
||||
|
||||
// AVATAR ENTITY UPDATE FLOW
|
||||
// - if queueEditEntityMessage() sees "AvatarEntity" HostType it calls _myAvatar->storeAvatarEntityDataPayload()
|
||||
|
|
|
@ -20,14 +20,10 @@
|
|||
#include "HMDToolsDialog.h"
|
||||
#include "TestingDialog.h"
|
||||
|
||||
class AnimationsDialog;
|
||||
class AttachmentsDialog;
|
||||
class CachesSizeDialog;
|
||||
class LodToolsDialog;
|
||||
class OctreeStatsDialog;
|
||||
class ScriptEditorWindow;
|
||||
class TestingDialog;
|
||||
class QMessageBox;
|
||||
class DomainConnectionDialog;
|
||||
|
||||
class DialogsManager : public QObject, public Dependency {
|
||||
|
@ -77,10 +73,6 @@ private:
|
|||
template<typename T>
|
||||
void maybeCreateDialog(QPointer<T>& member);
|
||||
|
||||
QPointer<AnimationsDialog> _animationsDialog;
|
||||
QPointer<AttachmentsDialog> _attachmentsDialog;
|
||||
QPointer<CachesSizeDialog> _cachesSizeDialog;
|
||||
QPointer<QMessageBox> _ircInfoBox;
|
||||
QPointer<HMDToolsDialog> _hmdToolsDialog;
|
||||
QPointer<LodToolsDialog> _lodToolsDialog;
|
||||
QPointer<OctreeStatsDialog> _octreeStatsDialog;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <NetworkingConstants.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
const char* MODEL_TYPE_NAMES[] = { "entities", "heads", "skeletons", "skeletons", "attachments" };
|
||||
const char* MODEL_TYPE_NAMES[] = { "entities", "heads", "skeletons", "skeletons" };
|
||||
|
||||
static const QString S3_URL = NetworkingConstants::HF_PUBLIC_CDN_URL;
|
||||
static const QString PUBLIC_URL = "http://public.overte.org"; // Changed to Overte but not entirely sure what to do with this yet.
|
||||
|
|
|
@ -132,9 +132,11 @@ void AudioInjector::restart() {
|
|||
|
||||
bool AudioInjector::inject(bool(AudioInjectorManager::*injection)(const AudioInjectorPointer&)) {
|
||||
AudioInjectorOptions options;
|
||||
uint32_t numBytes;
|
||||
withWriteLock([&] {
|
||||
_state = AudioInjectorState::NotFinished;
|
||||
options = _options;
|
||||
numBytes = _audioData->getNumBytes();
|
||||
});
|
||||
|
||||
int byteOffset = 0;
|
||||
|
@ -142,6 +144,7 @@ bool AudioInjector::inject(bool(AudioInjectorManager::*injection)(const AudioInj
|
|||
int numChannels = options.ambisonic ? 4 : (options.stereo ? 2 : 1);
|
||||
byteOffset = (int)(AudioConstants::SAMPLE_RATE * options.secondOffset * numChannels);
|
||||
byteOffset *= AudioConstants::SAMPLE_SIZE;
|
||||
byteOffset = byteOffset % numBytes;
|
||||
}
|
||||
_currentSendOffset = byteOffset;
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <VariantMapToScriptValue.h>
|
||||
#include <DebugDraw.h>
|
||||
#include <shared/Camera.h>
|
||||
#include <SoftAttachmentModel.h>
|
||||
#include <render/TransitionStage.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include "ModelEntityItem.h"
|
||||
|
@ -52,7 +51,6 @@ const float DISPLAYNAME_BACKGROUND_ALPHA = 0.4f;
|
|||
const glm::vec3 HAND_TO_PALM_OFFSET(0.0f, 0.12f, 0.08f);
|
||||
const float Avatar::MYAVATAR_LOADING_PRIORITY = (float)M_PI; // Entity priority is computed as atan2(maxDim, distance) which is <= PI / 2
|
||||
const float Avatar::OTHERAVATAR_LOADING_PRIORITY = MYAVATAR_LOADING_PRIORITY - EPSILON;
|
||||
const float Avatar::ATTACHMENT_LOADING_PRIORITY = OTHERAVATAR_LOADING_PRIORITY - EPSILON;
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar) {
|
||||
|
@ -651,19 +649,6 @@ void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& sc
|
|||
_skeletonModel->setVisibleInScene(_isMeshVisible, scene);
|
||||
|
||||
processMaterials();
|
||||
bool attachmentRenderingNeedsUpdate = false;
|
||||
for (auto& attachmentModel : _attachmentModels) {
|
||||
attachmentModel->addToScene(scene, transaction);
|
||||
attachmentModel->setTagMask(render::hifi::TAG_ALL_VIEWS);
|
||||
attachmentModel->setGroupCulled(true);
|
||||
attachmentModel->setCanCastShadow(true);
|
||||
attachmentModel->setVisibleInScene(_isMeshVisible, scene);
|
||||
attachmentRenderingNeedsUpdate = true;
|
||||
}
|
||||
|
||||
if (attachmentRenderingNeedsUpdate) {
|
||||
updateAttachmentRenderIDs();
|
||||
}
|
||||
|
||||
_mustFadeIn = true;
|
||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelAddedToScene(getSessionUUID(), NestableType::Avatar, _skeletonModel);
|
||||
|
@ -688,11 +673,6 @@ void Avatar::fadeOut(render::Transaction& transaction, KillAvatarReason reason)
|
|||
|
||||
void Avatar::fade(render::Transaction& transaction, render::Transition::Type type) {
|
||||
transaction.resetTransitionOnItem(_renderItemID, type);
|
||||
for (auto& attachmentModel : _attachmentModels) {
|
||||
for (auto itemId : attachmentModel->fetchRenderItemIDs()) {
|
||||
transaction.resetTransitionOnItem(itemId, type, _renderItemID);
|
||||
}
|
||||
}
|
||||
_lastFadeRequested = type;
|
||||
}
|
||||
|
||||
|
@ -704,9 +684,6 @@ void Avatar::removeFromScene(AvatarSharedPointer self, const render::ScenePointe
|
|||
transaction.removeItem(_renderItemID);
|
||||
render::Item::clearID(_renderItemID);
|
||||
_skeletonModel->removeFromScene(scene, transaction);
|
||||
for (auto& attachmentModel : _attachmentModels) {
|
||||
attachmentModel->removeFromScene(scene, transaction);
|
||||
}
|
||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelRemovedFromScene(getSessionUUID(), NestableType::Avatar, _skeletonModel);
|
||||
}
|
||||
|
||||
|
@ -866,8 +843,6 @@ bool Avatar::getEnableMeshVisible() const {
|
|||
void Avatar::fixupModelsInScene(const render::ScenePointer& scene) {
|
||||
bool canTryFade{ false };
|
||||
|
||||
_attachmentsToDelete.clear();
|
||||
|
||||
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
||||
// fix them up in the scene
|
||||
render::Transaction transaction;
|
||||
|
@ -885,27 +860,9 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) {
|
|||
canTryFade = true;
|
||||
_isAnimatingScale = true;
|
||||
}
|
||||
bool attachmentRenderingNeedsUpdate = false;
|
||||
for (auto attachmentModel : _attachmentModels) {
|
||||
if (attachmentModel->isRenderable() && attachmentModel->needsFixupInScene()) {
|
||||
attachmentModel->removeFromScene(scene, transaction);
|
||||
attachmentModel->addToScene(scene, transaction);
|
||||
|
||||
attachmentModel->setTagMask(render::hifi::TAG_ALL_VIEWS);
|
||||
attachmentModel->setGroupCulled(true);
|
||||
attachmentModel->setCanCastShadow(true);
|
||||
attachmentModel->setVisibleInScene(_isMeshVisible, scene);
|
||||
attachmentRenderingNeedsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_needMeshVisibleSwitch) {
|
||||
_skeletonModel->setVisibleInScene(_isMeshVisible, scene);
|
||||
for (auto attachmentModel : _attachmentModels) {
|
||||
if (attachmentModel->isRenderable()) {
|
||||
attachmentModel->setVisibleInScene(_isMeshVisible, scene);
|
||||
}
|
||||
}
|
||||
updateRenderItem(transaction);
|
||||
_needMeshVisibleSwitch = false;
|
||||
}
|
||||
|
@ -916,17 +873,6 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) {
|
|||
_mustFadeIn = false;
|
||||
}
|
||||
|
||||
for (auto attachmentModelToRemove : _attachmentsToRemove) {
|
||||
attachmentModelToRemove->removeFromScene(scene, transaction);
|
||||
attachmentRenderingNeedsUpdate = true;
|
||||
}
|
||||
_attachmentsToDelete.insert(_attachmentsToDelete.end(), _attachmentsToRemove.begin(), _attachmentsToRemove.end());
|
||||
_attachmentsToRemove.clear();
|
||||
|
||||
if (attachmentRenderingNeedsUpdate) {
|
||||
updateAttachmentRenderIDs();
|
||||
}
|
||||
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
|
@ -934,48 +880,6 @@ bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
void Avatar::simulateAttachments(float deltaTime) {
|
||||
assert(_attachmentModels.size() == _attachmentModelsTexturesLoaded.size());
|
||||
PerformanceTimer perfTimer("attachments");
|
||||
for (int i = 0; i < (int)_attachmentModels.size(); i++) {
|
||||
const AttachmentData& attachment = _attachmentData.at(i);
|
||||
auto& model = _attachmentModels.at(i);
|
||||
bool texturesLoaded = _attachmentModelsTexturesLoaded.at(i);
|
||||
|
||||
// Watch for texture loading
|
||||
if (!texturesLoaded && model->getGeometry() && model->getGeometry()->areTexturesLoaded()) {
|
||||
_attachmentModelsTexturesLoaded[i] = true;
|
||||
model->updateRenderItems();
|
||||
}
|
||||
|
||||
int jointIndex = getJointIndex(attachment.jointName);
|
||||
glm::vec3 jointPosition;
|
||||
glm::quat jointRotation;
|
||||
if (attachment.isSoft) {
|
||||
// soft attachments do not have transform offsets
|
||||
model->setTransformNoUpdateRenderItems(Transform(getWorldOrientation() * Quaternions::Y_180, glm::vec3(1.0), getWorldPosition()));
|
||||
model->simulate(deltaTime);
|
||||
model->updateRenderItems();
|
||||
} else {
|
||||
if (_skeletonModel->getJointPositionInWorldFrame(jointIndex, jointPosition) &&
|
||||
_skeletonModel->getJointRotationInWorldFrame(jointIndex, jointRotation)) {
|
||||
model->setTransformNoUpdateRenderItems(Transform(jointRotation * attachment.rotation, glm::vec3(1.0), jointPosition + jointRotation * attachment.translation * getModelScale()));
|
||||
float scale = getModelScale() * attachment.scale;
|
||||
model->setScaleToFit(true, model->getNaturalDimensions() * scale, true); // hack to force rescale
|
||||
model->setSnapModelToCenter(false); // hack to force resnap
|
||||
model->setSnapModelToCenter(true);
|
||||
model->simulate(deltaTime);
|
||||
model->updateRenderItems();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_ancestorChainRenderableVersion != _lastAncestorChainRenderableVersion) {
|
||||
_lastAncestorChainRenderableVersion = _ancestorChainRenderableVersion;
|
||||
updateDescendantRenderIDs();
|
||||
}
|
||||
}
|
||||
|
||||
float Avatar::getBoundingRadius() const {
|
||||
return getBounds().getLargestDimension() / 2.0f;
|
||||
}
|
||||
|
@ -1631,58 +1535,6 @@ void Avatar::updateFitBoundingBox() {
|
|||
}
|
||||
}
|
||||
|
||||
// create new model, can return an instance of a SoftAttachmentModel rather then Model
|
||||
static std::shared_ptr<Model> allocateAttachmentModel(bool isSoft, const Rig& rigOverride, bool isCauterized) {
|
||||
if (isSoft) {
|
||||
// cast to std::shared_ptr<Model>
|
||||
std::shared_ptr<SoftAttachmentModel> softModel = std::make_shared<SoftAttachmentModel>(nullptr, rigOverride);
|
||||
if (isCauterized) {
|
||||
softModel->flagAsCauterized();
|
||||
}
|
||||
return std::dynamic_pointer_cast<Model>(softModel);
|
||||
} else {
|
||||
return std::make_shared<Model>();
|
||||
}
|
||||
}
|
||||
|
||||
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "setAttachmentData",
|
||||
Q_ARG(const QVector<AttachmentData>, attachmentData));
|
||||
return;
|
||||
}
|
||||
|
||||
auto oldAttachmentData = _attachmentData;
|
||||
AvatarData::setAttachmentData(attachmentData);
|
||||
|
||||
// if number of attachments has been reduced, remove excess models.
|
||||
while ((int)_attachmentModels.size() > attachmentData.size()) {
|
||||
auto attachmentModel = _attachmentModels.back();
|
||||
_attachmentModels.pop_back();
|
||||
_attachmentModelsTexturesLoaded.pop_back();
|
||||
_attachmentsToRemove.push_back(attachmentModel);
|
||||
}
|
||||
|
||||
for (int i = 0; i < attachmentData.size(); i++) {
|
||||
if (i == (int)_attachmentModels.size()) {
|
||||
// if number of attachments has been increased, we need to allocate a new model
|
||||
_attachmentModels.push_back(allocateAttachmentModel(attachmentData[i].isSoft, _skeletonModel->getRig(), isMyAvatar()));
|
||||
_attachmentModelsTexturesLoaded.push_back(false);
|
||||
} else if (i < oldAttachmentData.size() && oldAttachmentData[i].isSoft != attachmentData[i].isSoft) {
|
||||
// if the attachment has changed type, we need to re-allocate a new one.
|
||||
_attachmentsToRemove.push_back(_attachmentModels[i]);
|
||||
_attachmentModels[i] = allocateAttachmentModel(attachmentData[i].isSoft, _skeletonModel->getRig(), isMyAvatar());
|
||||
_attachmentModelsTexturesLoaded[i] = false;
|
||||
}
|
||||
// If the model URL has changd, we need to wait for the textures to load
|
||||
if (_attachmentModels[i]->getURL() != attachmentData[i].modelURL) {
|
||||
_attachmentModelsTexturesLoaded[i] = false;
|
||||
}
|
||||
_attachmentModels[i]->setLoadingPriority(ATTACHMENT_LOADING_PRIORITY);
|
||||
_attachmentModels[i]->setURL(attachmentData[i].modelURL);
|
||||
}
|
||||
}
|
||||
|
||||
int Avatar::parseDataFromBuffer(const QByteArray& buffer) {
|
||||
PerformanceTimer perfTimer("unpack");
|
||||
if (!_initialized) {
|
||||
|
@ -2102,11 +1954,6 @@ uint32_t Avatar::appendSubMetaItems(render::ItemIDs& subItems) {
|
|||
return _subItemLock.resultWithReadLock<uint32_t>([&] {
|
||||
uint32_t total = 0;
|
||||
|
||||
if (_attachmentRenderIDs.size() > 0) {
|
||||
subItems.insert(subItems.end(), _attachmentRenderIDs.begin(), _attachmentRenderIDs.end());
|
||||
total += (uint32_t)_attachmentRenderIDs.size();
|
||||
}
|
||||
|
||||
if (_descendantRenderIDs.size() > 0) {
|
||||
subItems.insert(subItems.end(), _descendantRenderIDs.begin(), _descendantRenderIDs.end());
|
||||
total += (uint32_t)_descendantRenderIDs.size();
|
||||
|
@ -2116,18 +1963,6 @@ uint32_t Avatar::appendSubMetaItems(render::ItemIDs& subItems) {
|
|||
});
|
||||
}
|
||||
|
||||
void Avatar::updateAttachmentRenderIDs() {
|
||||
_subItemLock.withWriteLock([&] {
|
||||
_attachmentRenderIDs.clear();
|
||||
for (auto& attachmentModel : _attachmentModels) {
|
||||
if (attachmentModel && attachmentModel->isRenderable()) {
|
||||
auto& metaSubItems = attachmentModel->fetchRenderItemIDs();
|
||||
_attachmentRenderIDs.insert(_attachmentRenderIDs.end(), metaSubItems.begin(), metaSubItems.end());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Avatar::updateDescendantRenderIDs() {
|
||||
_subItemLock.withWriteLock([&] {
|
||||
auto oldRenderingDescendantEntityIDs = _renderingDescendantEntityIDs;
|
||||
|
|
|
@ -157,7 +157,6 @@ public:
|
|||
void init();
|
||||
void removeAvatarEntitiesFromTree();
|
||||
virtual void simulate(float deltaTime, bool inView) = 0;
|
||||
virtual void simulateAttachments(float deltaTime);
|
||||
|
||||
virtual void render(RenderArgs* renderArgs);
|
||||
|
||||
|
@ -344,7 +343,6 @@ public:
|
|||
Q_INVOKABLE glm::quat jointToWorldRotation(const glm::quat& rotation, const int jointIndex = -1) const;
|
||||
|
||||
Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
|
||||
|
||||
void updateDisplayNameAlpha(bool showDisplayName);
|
||||
virtual void setSessionDisplayName(const QString& sessionDisplayName) override { }; // no-op
|
||||
|
@ -650,10 +648,6 @@ protected:
|
|||
mutable bool _modelJointsCached { false };
|
||||
|
||||
glm::vec3 _skeletonOffset;
|
||||
std::vector<std::shared_ptr<Model>> _attachmentModels;
|
||||
std::vector<bool> _attachmentModelsTexturesLoaded;
|
||||
std::vector<std::shared_ptr<Model>> _attachmentsToRemove;
|
||||
std::vector<std::shared_ptr<Model>> _attachmentsToDelete;
|
||||
|
||||
float _bodyYawDelta { 0.0f }; // degrees/sec
|
||||
float _seatedBodyYawDelta{ 0.0f }; // degrees/renderframe
|
||||
|
@ -753,7 +747,6 @@ protected:
|
|||
|
||||
static const float MYAVATAR_LOADING_PRIORITY;
|
||||
static const float OTHERAVATAR_LOADING_PRIORITY;
|
||||
static const float ATTACHMENT_LOADING_PRIORITY;
|
||||
|
||||
LoadingStatus _loadingStatus { LoadingStatus::NoModel };
|
||||
|
||||
|
@ -773,12 +766,9 @@ protected:
|
|||
VectorOfIDs _grabsToDelete; // deleted grab IDs -- changes needed to entities or physics
|
||||
|
||||
ReadWriteLockable _subItemLock;
|
||||
void updateAttachmentRenderIDs();
|
||||
render::ItemIDs _attachmentRenderIDs;
|
||||
void updateDescendantRenderIDs();
|
||||
render::ItemIDs _descendantRenderIDs;
|
||||
std::unordered_set<EntityItemID> _renderingDescendantEntityIDs;
|
||||
uint32_t _lastAncestorChainRenderableVersion { 0 };
|
||||
};
|
||||
|
||||
#endif // hifi_Avatar_h
|
||||
|
|
|
@ -58,8 +58,6 @@
|
|||
* when the other avatar is in the line of sight and also has <code>lookAtSnappingEnabled == true</code>.
|
||||
*
|
||||
* @property {string} skeletonModelURL - The avatar's FST file.
|
||||
* @property {AttachmentData[]} attachmentData - Information on the avatar's attachments.
|
||||
* <p class="important">Deprecated: This property is deprecated and will be removed. Use avatar entities instead.</p>
|
||||
* @property {string[]} jointNames - The list of joints in the avatar model.
|
||||
*
|
||||
* @property {number} audioLoudness - The instantaneous loudness of the audio input that the avatar is injecting into the
|
||||
|
|
|
@ -73,17 +73,10 @@ static const float DEFAULT_AVATAR_DENSITY = 1000.0f; // density of water
|
|||
STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager) {
|
||||
auto scriptEngine = manager->engine().get();
|
||||
|
||||
registerAvatarTypes(scriptEngine);
|
||||
scriptRegisterMetaType<RayToAvatarIntersectionResult, RayToAvatarIntersectionResultToScriptValue, RayToAvatarIntersectionResultFromScriptValue>(scriptEngine);
|
||||
scriptRegisterMetaType<AvatarEntityMap, AvatarEntityMapToScriptValue, AvatarEntityMapFromScriptValue>(scriptEngine);
|
||||
}));
|
||||
|
||||
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) {
|
||||
auto scriptEngine = manager->engine().get();
|
||||
|
||||
registerAvatarPrototypes(scriptEngine);
|
||||
});
|
||||
|
||||
size_t AvatarDataPacket::maxFaceTrackerInfoSize(size_t numBlendshapeCoefficients) {
|
||||
return FACE_TRACKER_INFO_SIZE + numBlendshapeCoefficients * sizeof(float);
|
||||
}
|
||||
|
@ -2027,7 +2020,6 @@ void AvatarData::processAvatarIdentity(QDataStream& packetStream, bool& identity
|
|||
Identity identity;
|
||||
|
||||
packetStream
|
||||
>> identity.attachmentData
|
||||
>> identity.displayName
|
||||
>> identity.sessionDisplayName
|
||||
>> identity.identityFlags
|
||||
|
@ -2068,11 +2060,6 @@ void AvatarData::processAvatarIdentity(QDataStream& packetStream, bool& identity
|
|||
}
|
||||
};
|
||||
|
||||
if (identity.attachmentData != _attachmentData) {
|
||||
setAttachmentData(identity.attachmentData);
|
||||
identityChanged = true;
|
||||
}
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
qCDebug(avatars) << __FUNCTION__
|
||||
<< "identity.uuid:" << identity.uuid
|
||||
|
@ -2319,7 +2306,6 @@ QByteArray AvatarData::identityByteArray(bool setIsReplicated) const {
|
|||
|
||||
identityStream << getSessionUUID()
|
||||
<< (udt::SequenceNumber::Type) _identitySequenceNumber
|
||||
<< _attachmentData
|
||||
<< _displayName
|
||||
<< getSessionDisplayNameForTransport() // depends on _sessionDisplayName
|
||||
<< identityFlags;
|
||||
|
@ -2353,86 +2339,6 @@ void AvatarData::setDisplayName(const QString& displayName) {
|
|||
markIdentityDataChanged();
|
||||
}
|
||||
|
||||
QVector<AttachmentData> AvatarData::getAttachmentData() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVector<AttachmentData> result;
|
||||
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getAttachmentData",
|
||||
Q_RETURN_ARG(QVector<AttachmentData>, result));
|
||||
return result;
|
||||
}
|
||||
return _attachmentData;
|
||||
}
|
||||
|
||||
void AvatarData::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setAttachmentData", Q_ARG(const QVector<AttachmentData>&, attachmentData));
|
||||
return;
|
||||
}
|
||||
_attachmentData = attachmentData;
|
||||
markIdentityDataChanged();
|
||||
}
|
||||
|
||||
void AvatarData::attach(const QString& modelURL, const QString& jointName,
|
||||
const glm::vec3& translation, const glm::quat& rotation,
|
||||
float scale, bool isSoft,
|
||||
bool allowDuplicates, bool useSaved) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "attach", Q_ARG(const QString&, modelURL), Q_ARG(const QString&, jointName),
|
||||
Q_ARG(const glm::vec3&, translation), Q_ARG(const glm::quat&, rotation),
|
||||
Q_ARG(float, scale), Q_ARG(bool, isSoft),
|
||||
Q_ARG(bool, allowDuplicates), Q_ARG(bool, useSaved));
|
||||
return;
|
||||
}
|
||||
QVector<AttachmentData> attachmentData = getAttachmentData();
|
||||
if (!allowDuplicates) {
|
||||
foreach (const AttachmentData& data, attachmentData) {
|
||||
if (data.modelURL == modelURL && (jointName.isEmpty() || data.jointName == jointName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
AttachmentData data;
|
||||
data.modelURL = modelURL;
|
||||
data.jointName = jointName;
|
||||
data.translation = translation;
|
||||
data.rotation = rotation;
|
||||
data.scale = scale;
|
||||
data.isSoft = isSoft;
|
||||
attachmentData.append(data);
|
||||
setAttachmentData(attachmentData);
|
||||
}
|
||||
|
||||
void AvatarData::detachOne(const QString& modelURL, const QString& jointName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "detachOne", Q_ARG(const QString&, modelURL), Q_ARG(const QString&, jointName));
|
||||
return;
|
||||
}
|
||||
QVector<AttachmentData> attachmentData = getAttachmentData();
|
||||
for (QVector<AttachmentData>::iterator it = attachmentData.begin(); it != attachmentData.end(); ++it) {
|
||||
if (it->modelURL == modelURL && (jointName.isEmpty() || it->jointName == jointName)) {
|
||||
attachmentData.erase(it);
|
||||
setAttachmentData(attachmentData);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarData::detachAll(const QString& modelURL, const QString& jointName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "detachAll", Q_ARG(const QString&, modelURL), Q_ARG(const QString&, jointName));
|
||||
return;
|
||||
}
|
||||
QVector<AttachmentData> attachmentData = getAttachmentData();
|
||||
for (QVector<AttachmentData>::iterator it = attachmentData.begin(); it != attachmentData.end(); ) {
|
||||
if (it->modelURL == modelURL && (jointName.isEmpty() || it->jointName == jointName)) {
|
||||
it = attachmentData.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
setAttachmentData(attachmentData);
|
||||
}
|
||||
|
||||
int AvatarData::sendAvatarDataPacket(bool sendAll) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
|
@ -2495,149 +2401,6 @@ int AvatarData::sendIdentityPacket() {
|
|||
return identityData.size();
|
||||
}
|
||||
|
||||
static const QString JSON_ATTACHMENT_URL = QStringLiteral("modelUrl");
|
||||
static const QString JSON_ATTACHMENT_JOINT_NAME = QStringLiteral("jointName");
|
||||
static const QString JSON_ATTACHMENT_TRANSFORM = QStringLiteral("transform");
|
||||
static const QString JSON_ATTACHMENT_IS_SOFT = QStringLiteral("isSoft");
|
||||
|
||||
QJsonObject AttachmentData::toJson() const {
|
||||
QJsonObject result;
|
||||
if (modelURL.isValid() && !modelURL.isEmpty()) {
|
||||
result[JSON_ATTACHMENT_URL] = modelURL.toString();
|
||||
}
|
||||
if (!jointName.isEmpty()) {
|
||||
result[JSON_ATTACHMENT_JOINT_NAME] = jointName;
|
||||
}
|
||||
// FIXME the transform constructor that takes rot/scale/translation
|
||||
// doesn't return the correct value for isIdentity()
|
||||
Transform transform;
|
||||
transform.setRotation(rotation);
|
||||
transform.setScale(scale);
|
||||
transform.setTranslation(translation);
|
||||
if (!transform.isIdentity()) {
|
||||
result[JSON_ATTACHMENT_TRANSFORM] = Transform::toJson(transform);
|
||||
}
|
||||
result[JSON_ATTACHMENT_IS_SOFT] = isSoft;
|
||||
return result;
|
||||
}
|
||||
|
||||
void AttachmentData::fromJson(const QJsonObject& json) {
|
||||
if (json.contains(JSON_ATTACHMENT_URL)) {
|
||||
const QString modelURLTemp = json[JSON_ATTACHMENT_URL].toString();
|
||||
if (modelURLTemp != modelURL.toString()) {
|
||||
modelURL = modelURLTemp;
|
||||
}
|
||||
}
|
||||
|
||||
if (json.contains(JSON_ATTACHMENT_JOINT_NAME)) {
|
||||
const QString jointNameTemp = json[JSON_ATTACHMENT_JOINT_NAME].toString();
|
||||
if (jointNameTemp != jointName) {
|
||||
jointName = jointNameTemp;
|
||||
}
|
||||
}
|
||||
|
||||
if (json.contains(JSON_ATTACHMENT_TRANSFORM)) {
|
||||
Transform transform = Transform::fromJson(json[JSON_ATTACHMENT_TRANSFORM]);
|
||||
translation = transform.getTranslation();
|
||||
rotation = transform.getRotation();
|
||||
scale = transform.getScale().x;
|
||||
}
|
||||
|
||||
if (json.contains(JSON_ATTACHMENT_IS_SOFT)) {
|
||||
isSoft = json[JSON_ATTACHMENT_IS_SOFT].toBool();
|
||||
}
|
||||
}
|
||||
|
||||
bool AttachmentData::operator==(const AttachmentData& other) const {
|
||||
return modelURL == other.modelURL && jointName == other.jointName && translation == other.translation &&
|
||||
rotation == other.rotation && scale == other.scale && isSoft == other.isSoft;
|
||||
}
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, const AttachmentData& attachment) {
|
||||
return out << attachment.modelURL << attachment.jointName <<
|
||||
attachment.translation << attachment.rotation << attachment.scale << attachment.isSoft;
|
||||
}
|
||||
|
||||
QDataStream& operator>>(QDataStream& in, AttachmentData& attachment) {
|
||||
return in >> attachment.modelURL >> attachment.jointName >>
|
||||
attachment.translation >> attachment.rotation >> attachment.scale >> attachment.isSoft;
|
||||
}
|
||||
|
||||
void AttachmentDataObject::setModelURL(const QString& modelURL) {
|
||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
||||
data.modelURL = modelURL;
|
||||
Q_ASSERT(engine());
|
||||
thisObject() = engine()->toScriptValue(data);
|
||||
}
|
||||
|
||||
QString AttachmentDataObject::getModelURL() const {
|
||||
return scriptvalue_cast<AttachmentData>(thisObject()).modelURL.toString();
|
||||
}
|
||||
|
||||
void AttachmentDataObject::setJointName(const QString& jointName) {
|
||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
||||
data.jointName = jointName;
|
||||
Q_ASSERT(engine());
|
||||
thisObject() = engine()->toScriptValue(data);
|
||||
}
|
||||
|
||||
QString AttachmentDataObject::getJointName() const {
|
||||
return scriptvalue_cast<AttachmentData>(thisObject()).jointName;
|
||||
}
|
||||
|
||||
void AttachmentDataObject::setTranslation(const glm::vec3& translation) {
|
||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
||||
data.translation = translation;
|
||||
Q_ASSERT(engine());
|
||||
thisObject() = engine()->toScriptValue(data);
|
||||
}
|
||||
|
||||
glm::vec3 AttachmentDataObject::getTranslation() const {
|
||||
return scriptvalue_cast<AttachmentData>(thisObject()).translation;
|
||||
}
|
||||
|
||||
void AttachmentDataObject::setRotation(const glm::quat& rotation) {
|
||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
||||
data.rotation = rotation;
|
||||
Q_ASSERT(engine());
|
||||
thisObject() = engine()->toScriptValue(data);
|
||||
}
|
||||
|
||||
glm::quat AttachmentDataObject::getRotation() const {
|
||||
return scriptvalue_cast<AttachmentData>(thisObject()).rotation;
|
||||
}
|
||||
|
||||
void AttachmentDataObject::setScale(float scale) {
|
||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
||||
data.scale = scale;
|
||||
Q_ASSERT(engine());
|
||||
thisObject() = engine()->toScriptValue(data);
|
||||
}
|
||||
|
||||
float AttachmentDataObject::getScale() const {
|
||||
return scriptvalue_cast<AttachmentData>(thisObject()).scale;
|
||||
}
|
||||
|
||||
void AttachmentDataObject::setIsSoft(bool isSoft) {
|
||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
||||
data.isSoft = isSoft;
|
||||
Q_ASSERT(engine());
|
||||
thisObject() = engine()->toScriptValue(data);
|
||||
}
|
||||
|
||||
bool AttachmentDataObject::getIsSoft() const {
|
||||
return scriptvalue_cast<AttachmentData>(thisObject()).isSoft;
|
||||
}
|
||||
|
||||
void registerAvatarTypes(ScriptEngine* engine) {
|
||||
scriptRegisterSequenceMetaType<QVector<AttachmentData> >(engine);
|
||||
}
|
||||
|
||||
void registerAvatarPrototypes(ScriptEngine* engine) {
|
||||
engine->setDefaultPrototype(qMetaTypeId<AttachmentData>(), engine->newQObject(
|
||||
new AttachmentDataObject(), ScriptEngine::ScriptOwnership));
|
||||
}
|
||||
|
||||
void AvatarData::setRecordingBasis(std::shared_ptr<Transform> recordingBasis) {
|
||||
if (!recordingBasis) {
|
||||
recordingBasis = std::make_shared<Transform>();
|
||||
|
@ -2670,7 +2433,6 @@ static const QString JSON_AVATAR_HEAD_MODEL = QStringLiteral("headModel");
|
|||
static const QString JSON_AVATAR_BODY_MODEL = QStringLiteral("bodyModel");
|
||||
static const QString JSON_AVATAR_DISPLAY_NAME = QStringLiteral("displayName");
|
||||
// It isn't meaningful to persist sessionDisplayName.
|
||||
static const QString JSON_AVATAR_ATTACHMENTS = QStringLiteral("attachments");
|
||||
static const QString JSON_AVATAR_ENTITIES = QStringLiteral("attachedEntities");
|
||||
static const QString JSON_AVATAR_SCALE = QStringLiteral("scale");
|
||||
static const QString JSON_AVATAR_VERSION = QStringLiteral("version");
|
||||
|
@ -2838,24 +2600,11 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) {
|
|||
setTargetScale((float)json[JSON_AVATAR_SCALE].toDouble());
|
||||
}
|
||||
|
||||
QVector<AttachmentData> attachments;
|
||||
if (json.contains(JSON_AVATAR_ATTACHMENTS) && json[JSON_AVATAR_ATTACHMENTS].isArray()) {
|
||||
QJsonArray attachmentsJson = json[JSON_AVATAR_ATTACHMENTS].toArray();
|
||||
for (auto attachmentJson : attachmentsJson) {
|
||||
AttachmentData attachment;
|
||||
attachment.fromJson(attachmentJson.toObject());
|
||||
attachments.push_back(attachment);
|
||||
}
|
||||
}
|
||||
if (attachments != getAttachmentData()) {
|
||||
setAttachmentData(attachments);
|
||||
}
|
||||
|
||||
if (json.contains(JSON_AVATAR_ENTITIES) && json[JSON_AVATAR_ENTITIES].isArray()) {
|
||||
QJsonArray attachmentsJson = json[JSON_AVATAR_ENTITIES].toArray();
|
||||
for (auto attachmentJson : attachmentsJson) {
|
||||
if (attachmentJson.isObject()) {
|
||||
QVariantMap entityData = attachmentJson.toObject().toVariantMap();
|
||||
QJsonArray avatarEntitiesJSON = json[JSON_AVATAR_ENTITIES].toArray();
|
||||
for (auto avatarEntityJSON : avatarEntitiesJSON) {
|
||||
if (avatarEntityJSON.isObject()) {
|
||||
QVariantMap entityData = avatarEntityJSON.toObject().toVariantMap();
|
||||
QUuid id = entityData.value("id").toUuid();
|
||||
QByteArray data = QByteArray::fromBase64(entityData.value("properties").toByteArray());
|
||||
updateAvatarEntity(id, data);
|
||||
|
@ -2970,30 +2719,6 @@ glm::vec3 AvatarData::getAbsoluteJointTranslationInObjectFrame(int index) const
|
|||
return glm::vec3();
|
||||
}
|
||||
|
||||
/*@jsdoc
|
||||
* Information on an attachment worn by the avatar.
|
||||
* @typedef {object} AttachmentData
|
||||
* @property {string} modelUrl - The URL of the glTF, FBX, or OBJ model file. glTF models may be in JSON or binary format
|
||||
* (".gltf" or ".glb" URLs respectively).
|
||||
* @property {string} jointName - The name of the joint that the attachment is parented to.
|
||||
* @property {Vec3} translation - The offset from the joint that the attachment is positioned at.
|
||||
* @property {Vec3} rotation - The rotation applied to the model relative to the joint orientation.
|
||||
* @property {number} scale - The scale applied to the attachment model.
|
||||
* @property {boolean} soft - If <code>true</code> and the model has a skeleton, the bones of the attached model's skeleton are
|
||||
* rotated to fit the avatar's current pose. If <code>true</code>, the <code>translation</code>, <code>rotation</code>, and
|
||||
* <code>scale</code> parameters are ignored.
|
||||
*/
|
||||
QVariant AttachmentData::toVariant() const {
|
||||
QVariantMap result;
|
||||
result["modelUrl"] = modelURL;
|
||||
result["jointName"] = jointName;
|
||||
result["translation"] = vec3ToQMap(translation);
|
||||
result["rotation"] = vec3ToQMap(glm::degrees(safeEulerAngles(rotation)));
|
||||
result["scale"] = scale;
|
||||
result["soft"] = isSoft;
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::vec3 variantToVec3(const QVariant& var) {
|
||||
auto map = var.toMap();
|
||||
glm::vec3 result;
|
||||
|
@ -3003,52 +2728,6 @@ glm::vec3 variantToVec3(const QVariant& var) {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool AttachmentData::fromVariant(const QVariant& variant) {
|
||||
bool isValid = false;
|
||||
auto map = variant.toMap();
|
||||
if (map.contains("modelUrl")) {
|
||||
auto urlString = map["modelUrl"].toString();
|
||||
modelURL = urlString;
|
||||
isValid = true;
|
||||
}
|
||||
if (map.contains("jointName")) {
|
||||
jointName = map["jointName"].toString();
|
||||
}
|
||||
if (map.contains("translation")) {
|
||||
translation = variantToVec3(map["translation"]);
|
||||
}
|
||||
if (map.contains("rotation")) {
|
||||
rotation = glm::quat(glm::radians(variantToVec3(map["rotation"])));
|
||||
}
|
||||
if (map.contains("scale")) {
|
||||
scale = map["scale"].toFloat();
|
||||
}
|
||||
if (map.contains("soft")) {
|
||||
isSoft = map["soft"].toBool();
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
|
||||
QVariantList AvatarData::getAttachmentsVariant() const {
|
||||
QVariantList result;
|
||||
for (const auto& attachment : getAttachmentData()) {
|
||||
result.append(attachment.toVariant());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void AvatarData::setAttachmentsVariant(const QVariantList& variant) {
|
||||
QVector<AttachmentData> newAttachments;
|
||||
newAttachments.reserve(variant.size());
|
||||
for (const auto& attachmentVar : variant) {
|
||||
AttachmentData attachment;
|
||||
if (attachment.fromVariant(attachmentVar)) {
|
||||
newAttachments.append(attachment);
|
||||
}
|
||||
}
|
||||
setAttachmentData(newAttachments);
|
||||
}
|
||||
|
||||
void AvatarData::storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& data) {
|
||||
bool changed = false;
|
||||
_avatarEntitiesLock.withWriteLock([&] {
|
||||
|
|
|
@ -451,7 +451,6 @@ Q_DECLARE_METATYPE(KillAvatarReason);
|
|||
|
||||
class QDataStream;
|
||||
|
||||
class AttachmentData;
|
||||
class Transform;
|
||||
using TransformPointer = std::shared_ptr<Transform>;
|
||||
|
||||
|
@ -523,8 +522,6 @@ class AvatarData : public QObject, public SpatiallyNestable {
|
|||
* @property {boolean} lookAtSnappingEnabled=true - <code>true</code> if the avatar's eyes snap to look at another avatar's
|
||||
* eyes when the other avatar is in the line of sight and also has <code>lookAtSnappingEnabled == true</code>.
|
||||
* @property {string} skeletonModelURL - The avatar's FST file.
|
||||
* @property {AttachmentData[]} attachmentData - Information on the avatar's attachments.
|
||||
* <p class="important">Deprecated: This property is deprecated and will be removed. Use avatar entities instead.</p>
|
||||
* @property {string[]} jointNames - The list of joints in the current avatar model. <em>Read-only.</em>
|
||||
* @property {Uuid} sessionUUID - Unique ID of the avatar in the domain. <em>Read-only.</em>
|
||||
* @property {Mat4} sensorToWorldMatrix - The scale, rotation, and translation transform from the user's real world to the
|
||||
|
@ -580,7 +577,6 @@ class AvatarData : public QObject, public SpatiallyNestable {
|
|||
Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged)
|
||||
Q_PROPERTY(bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged)
|
||||
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged)
|
||||
Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData)
|
||||
|
||||
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
||||
|
||||
|
@ -1145,27 +1141,6 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); }
|
||||
|
||||
|
||||
/*@jsdoc
|
||||
* Gets information about the models currently attached to your avatar.
|
||||
* @function Avatar.getAttachmentsVariant
|
||||
* @returns {AttachmentData[]} Information about all models attached to your avatar.
|
||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
||||
*/
|
||||
// FIXME: Can this name be improved? Can it be deprecated?
|
||||
Q_INVOKABLE virtual QVariantList getAttachmentsVariant() const;
|
||||
|
||||
/*@jsdoc
|
||||
* Sets all models currently attached to your avatar. For example, if you retrieve attachment data using
|
||||
* {@link MyAvatar.getAttachmentsVariant} or {@link Avatar.getAttachmentsVariant}, make changes to it, and then want to
|
||||
* update your avatar's attachments per the changed data.
|
||||
* @function Avatar.setAttachmentsVariant
|
||||
* @param {AttachmentData[]} variant - The attachment data defining the models to have attached to your avatar.
|
||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
||||
*/
|
||||
// FIXME: Can this name be improved? Can it be deprecated?
|
||||
Q_INVOKABLE virtual void setAttachmentsVariant(const QVariantList& variant);
|
||||
|
||||
virtual void storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& payload);
|
||||
|
||||
/*@jsdoc
|
||||
|
@ -1209,7 +1184,6 @@ public:
|
|||
const HeadData* getHeadData() const { return _headData; }
|
||||
|
||||
struct Identity {
|
||||
QVector<AttachmentData> attachmentData;
|
||||
QString displayName;
|
||||
QString sessionDisplayName;
|
||||
bool isReplicated;
|
||||
|
@ -1254,109 +1228,6 @@ public:
|
|||
}
|
||||
virtual bool isCertifyFailed() const { return _verificationFailed; }
|
||||
|
||||
/*@jsdoc
|
||||
* Gets information about the models currently attached to your avatar.
|
||||
* @function Avatar.getAttachmentData
|
||||
* @returns {AttachmentData[]} Information about all models attached to your avatar.
|
||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
||||
* @example <caption>Report the URLs of all current attachments.</caption>
|
||||
* var attachments = MyAvatar.getaAttachmentData();
|
||||
* for (var i = 0; i < attachments.length; i++) {
|
||||
* print(attachments[i].modelURL);
|
||||
* }
|
||||
*
|
||||
* // Note: If using from the Avatar API, replace "MyAvatar" with "Avatar".
|
||||
*/
|
||||
Q_INVOKABLE virtual QVector<AttachmentData> getAttachmentData() const;
|
||||
|
||||
/*@jsdoc
|
||||
* Sets all models currently attached to your avatar. For example, if you retrieve attachment data using
|
||||
* {@link MyAvatar.getAttachmentData} or {@link Avatar.getAttachmentData}, make changes to it, and then want to update your avatar's attachments per the
|
||||
* changed data. You can also remove all attachments by using setting <code>attachmentData</code> to <code>null</code>.
|
||||
* @function Avatar.setAttachmentData
|
||||
* @param {AttachmentData[]} attachmentData - The attachment data defining the models to have attached to your avatar. Use
|
||||
* <code>null</code> to remove all attachments.
|
||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
||||
* @example <caption>Remove a hat attachment if your avatar is wearing it.</caption>
|
||||
* var hatURL = "https://apidocs.overte.org/examples/cowboy-hat.fbx";
|
||||
* var attachments = MyAvatar.getAttachmentData();
|
||||
*
|
||||
* for (var i = 0; i < attachments.length; i++) {
|
||||
* if (attachments[i].modelURL === hatURL) {
|
||||
* attachments.splice(i, 1);
|
||||
* MyAvatar.setAttachmentData(attachments);
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // Note: If using from the Avatar API, replace all occurrences of "MyAvatar" with "Avatar".
|
||||
*/
|
||||
Q_INVOKABLE virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
|
||||
|
||||
/*@jsdoc
|
||||
* Attaches a model to your avatar. For example, you can give your avatar a hat to wear, a guitar to hold, or a surfboard to
|
||||
* stand on.
|
||||
* @function Avatar.attach
|
||||
* @param {string} modelURL - The URL of the glTF, FBX, or OBJ model to attach. glTF models may be in JSON or binary format
|
||||
* (".gltf" or ".glb" URLs respectively).
|
||||
* @param {string} [jointName=""] - The name of the avatar joint (see {@link MyAvatar.getJointNames} or
|
||||
* {@link Avatar.getJointNames}) to attach the model to.
|
||||
* @param {Vec3} [translation=Vec3.ZERO] - The offset to apply to the model relative to the joint position.
|
||||
* @param {Quat} [rotation=Quat.IDENTITY] - The rotation to apply to the model relative to the joint orientation.
|
||||
* @param {number} [scale=1.0] - The scale to apply to the model.
|
||||
* @param {boolean} [isSoft=false] - If the model has a skeleton, set this to <code>true</code> so that the bones of the
|
||||
* attached model's skeleton are rotated to fit the avatar's current pose. <code>isSoft</code> is used, for example,
|
||||
* to have clothing that moves with the avatar.
|
||||
* <p>If <code>true</code>, the <code>translation</code>, <code>rotation</code>, and <code>scale</code> parameters are
|
||||
* ignored.</p>
|
||||
* @param {boolean} [allowDuplicates=false] - If <code>true</code> then more than one copy of any particular model may be
|
||||
* attached to the same joint; if <code>false</code> then the same model cannot be attached to the same joint.
|
||||
* @param {boolean} [useSaved=true] - <em>Not used.</em>
|
||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
||||
* @example <caption>Attach a cowboy hat to your avatar's head.</caption>
|
||||
* var attachment = {
|
||||
* modelURL: "https://apidocs.overte.org/examples/cowboy-hat.fbx",
|
||||
* jointName: "Head",
|
||||
* translation: {"x": 0, "y": 0.25, "z": 0},
|
||||
* rotation: {"x": 0, "y": 0, "z": 0, "w": 1},
|
||||
* scale: 0.01,
|
||||
* isSoft: false
|
||||
* };
|
||||
*
|
||||
* MyAvatar.attach(attachment.modelURL,
|
||||
* attachment.jointName,
|
||||
* attachment.translation,
|
||||
* attachment.rotation,
|
||||
* attachment.scale,
|
||||
* attachment.isSoft);
|
||||
*
|
||||
* // Note: If using from the Avatar API, replace "MyAvatar" with "Avatar".
|
||||
*/
|
||||
Q_INVOKABLE virtual void attach(const QString& modelURL, const QString& jointName = QString(),
|
||||
const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(),
|
||||
float scale = 1.0f, bool isSoft = false,
|
||||
bool allowDuplicates = false, bool useSaved = true);
|
||||
|
||||
/*@jsdoc
|
||||
* Detaches the most recently attached instance of a particular model from either a specific joint or any joint.
|
||||
* @function Avatar.detachOne
|
||||
* @param {string} modelURL - The URL of the model to detach.
|
||||
* @param {string} [jointName=""] - The name of the joint to detach the model from. If <code>""</code>, then the most
|
||||
* recently attached model is removed from which ever joint it was attached to.
|
||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
||||
*/
|
||||
Q_INVOKABLE virtual void detachOne(const QString& modelURL, const QString& jointName = QString());
|
||||
|
||||
/*@jsdoc
|
||||
* Detaches all instances of a particular model from either a specific joint or all joints.
|
||||
* @function Avatar.detachAll
|
||||
* @param {string} modelURL - The URL of the model to detach.
|
||||
* @param {string} [jointName=""] - The name of the joint to detach the model from. If <code>""</code>, then the model is
|
||||
* detached from all joints.
|
||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
||||
*/
|
||||
Q_INVOKABLE virtual void detachAll(const QString& modelURL, const QString& jointName = QString());
|
||||
|
||||
QString getSkeletonModelURLFromScript() const;
|
||||
void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); }
|
||||
|
||||
|
@ -1732,8 +1603,6 @@ protected:
|
|||
mutable HeadData* _headData { nullptr };
|
||||
|
||||
QUrl _skeletonModelURL;
|
||||
QVector<AttachmentData> _attachmentData;
|
||||
QVector<AttachmentData> _oldAttachmentData;
|
||||
QString _displayName;
|
||||
QString _sessionDisplayName { };
|
||||
bool _lookAtSnappingEnabled { true };
|
||||
|
@ -1899,66 +1768,6 @@ Q_DECLARE_METATYPE(AvatarData*)
|
|||
QJsonValue toJsonValue(const JointData& joint);
|
||||
JointData jointDataFromJsonValue(const QJsonValue& q);
|
||||
|
||||
class AttachmentData {
|
||||
public:
|
||||
QUrl modelURL;
|
||||
QString jointName;
|
||||
glm::vec3 translation;
|
||||
glm::quat rotation;
|
||||
float scale { 1.0f };
|
||||
bool isSoft { false };
|
||||
|
||||
bool isValid() const { return modelURL.isValid(); }
|
||||
|
||||
bool operator==(const AttachmentData& other) const;
|
||||
|
||||
QJsonObject toJson() const;
|
||||
void fromJson(const QJsonObject& json);
|
||||
|
||||
QVariant toVariant() const;
|
||||
bool fromVariant(const QVariant& variant);
|
||||
};
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, const AttachmentData& attachment);
|
||||
QDataStream& operator>>(QDataStream& in, AttachmentData& attachment);
|
||||
|
||||
Q_DECLARE_METATYPE(AttachmentData)
|
||||
Q_DECLARE_METATYPE(QVector<AttachmentData>)
|
||||
|
||||
/// Scriptable wrapper for attachments.
|
||||
class AttachmentDataObject : public QObject, protected Scriptable {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString modelURL READ getModelURL WRITE setModelURL)
|
||||
Q_PROPERTY(QString jointName READ getJointName WRITE setJointName)
|
||||
Q_PROPERTY(glm::vec3 translation READ getTranslation WRITE setTranslation)
|
||||
Q_PROPERTY(glm::quat rotation READ getRotation WRITE setRotation)
|
||||
Q_PROPERTY(float scale READ getScale WRITE setScale)
|
||||
Q_PROPERTY(bool isSoft READ getIsSoft WRITE setIsSoft)
|
||||
|
||||
public:
|
||||
|
||||
Q_INVOKABLE void setModelURL(const QString& modelURL);
|
||||
Q_INVOKABLE QString getModelURL() const;
|
||||
|
||||
Q_INVOKABLE void setJointName(const QString& jointName);
|
||||
Q_INVOKABLE QString getJointName() const;
|
||||
|
||||
Q_INVOKABLE void setTranslation(const glm::vec3& translation);
|
||||
Q_INVOKABLE glm::vec3 getTranslation() const;
|
||||
|
||||
Q_INVOKABLE void setRotation(const glm::quat& rotation);
|
||||
Q_INVOKABLE glm::quat getRotation() const;
|
||||
|
||||
Q_INVOKABLE void setScale(float scale);
|
||||
Q_INVOKABLE float getScale() const;
|
||||
|
||||
Q_INVOKABLE void setIsSoft(bool scale);
|
||||
Q_INVOKABLE bool getIsSoft() const;
|
||||
};
|
||||
|
||||
void registerAvatarTypes(ScriptEngine* engine);
|
||||
void registerAvatarPrototypes(ScriptEngine* engine);
|
||||
|
||||
class RayToAvatarIntersectionResult {
|
||||
public:
|
||||
bool intersects { false };
|
||||
|
|
|
@ -200,7 +200,7 @@ bool ScriptAvatarData::getLookAtSnappingEnabled() const {
|
|||
//
|
||||
|
||||
//
|
||||
// ATTACHMENT AND JOINT PROPERTIES
|
||||
// JOINT PROPERTIES
|
||||
// START
|
||||
//
|
||||
QString ScriptAvatarData::getSkeletonModelURLFromScript() const {
|
||||
|
@ -285,15 +285,8 @@ QStringList ScriptAvatarData::getJointNames() const {
|
|||
return QStringList();
|
||||
}
|
||||
}
|
||||
QVector<AttachmentData> ScriptAvatarData::getAttachmentData() const {
|
||||
if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) {
|
||||
return sharedAvatarData->getAttachmentData();
|
||||
} else {
|
||||
return QVector<AttachmentData>();
|
||||
}
|
||||
}
|
||||
//
|
||||
// ATTACHMENT AND JOINT PROPERTIES
|
||||
// JOINT PROPERTIES
|
||||
// END
|
||||
//
|
||||
|
||||
|
|
|
@ -50,10 +50,9 @@ class ScriptAvatarData : public QObject {
|
|||
Q_PROPERTY(bool lookAtSnappingEnabled READ getLookAtSnappingEnabled NOTIFY lookAtSnappingChanged)
|
||||
|
||||
//
|
||||
// ATTACHMENT AND JOINT PROPERTIES
|
||||
// JOINT PROPERTIES
|
||||
//
|
||||
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged)
|
||||
Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData)
|
||||
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
||||
|
||||
//
|
||||
|
@ -104,7 +103,7 @@ public:
|
|||
bool getLookAtSnappingEnabled() const;
|
||||
|
||||
//
|
||||
// ATTACHMENT AND JOINT PROPERTIES
|
||||
// JOINT PROPERTIES
|
||||
//
|
||||
QString getSkeletonModelURLFromScript() const;
|
||||
|
||||
|
@ -204,15 +203,6 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE QStringList getJointNames() const;
|
||||
|
||||
/*@jsdoc
|
||||
* Gets information about the models currently attached to the avatar.
|
||||
* @function ScriptAvatar.getAttachmentData
|
||||
* @returns {AttachmentData[]} Information about all models attached to the avatar, or <code>[]</code> if the avatar data
|
||||
* aren't available.
|
||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
||||
*/
|
||||
Q_INVOKABLE QVector<AttachmentData> getAttachmentData() const;
|
||||
|
||||
#if DEV_BUILD || PR_BUILD
|
||||
Q_INVOKABLE AvatarEntityMap getAvatarEntities() const;
|
||||
#endif
|
||||
|
|
|
@ -454,7 +454,6 @@ bool EntityRenderer::addToScene(const ScenePointer& scene, Transaction& transact
|
|||
transaction.resetItem(_renderItemID, renderPayload);
|
||||
onAddToScene(_entity);
|
||||
updateInScene(scene, transaction);
|
||||
_entity->bumpAncestorChainRenderableVersion();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -462,7 +461,6 @@ void EntityRenderer::removeFromScene(const ScenePointer& scene, Transaction& tra
|
|||
onRemoveFromScene(_entity);
|
||||
transaction.removeItem(_renderItemID);
|
||||
Item::clearID(_renderItemID);
|
||||
_entity->bumpAncestorChainRenderableVersion();
|
||||
}
|
||||
|
||||
void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& transaction) {
|
||||
|
|
|
@ -1261,7 +1261,6 @@ void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
|||
if (!_hasModel) {
|
||||
if (model) {
|
||||
model->removeFromScene(scene, transaction);
|
||||
entity->bumpAncestorChainRenderableVersion();
|
||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
||||
modelRemovedFromScene(entity->getEntityItemID(), NestableType::Entity, model);
|
||||
withWriteLock([&] { _model.reset(); });
|
||||
|
@ -1391,7 +1390,6 @@ void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
|||
makeStatusGetters(entity, statusGetters);
|
||||
using namespace std::placeholders;
|
||||
model->addToScene(scene, transaction, statusGetters, std::bind(&ModelEntityRenderer::metaBlendshapeOperator, _renderItemID, _1, _2, _3, _4));
|
||||
entity->bumpAncestorChainRenderableVersion();
|
||||
processMaterials();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ include_hifi_library_headers(image)
|
|||
include_hifi_library_headers(ktx)
|
||||
include_hifi_library_headers(material-networking)
|
||||
include_hifi_library_headers(procedural)
|
||||
link_hifi_libraries(shared shaders networking octree avatars graphics model-networking script-engine)
|
||||
link_hifi_libraries(audio shared shaders networking octree avatars graphics model-networking script-engine)
|
||||
|
||||
if (WIN32)
|
||||
add_compile_definitions(_USE_MATH_DEFINES)
|
||||
|
|
|
@ -2969,10 +2969,6 @@ void EntityItem::setVisible(bool value) {
|
|||
_needsRenderUpdate |= changed;
|
||||
_visible = value;
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
bumpAncestorChainRenderableVersion();
|
||||
}
|
||||
}
|
||||
|
||||
bool EntityItem::isVisibleInSecondaryCamera() const {
|
||||
|
|
|
@ -723,6 +723,16 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_GIZMO_TYPE, gizmoType);
|
||||
changedProperties += _ring.getChangedProperties();
|
||||
|
||||
// Sound
|
||||
CHECK_PROPERTY_CHANGE(PROP_SOUND_URL, soundURL);
|
||||
CHECK_PROPERTY_CHANGE(PROP_SOUND_VOLUME, volume);
|
||||
CHECK_PROPERTY_CHANGE(PROP_SOUND_TIME_OFFSET, timeOffset);
|
||||
CHECK_PROPERTY_CHANGE(PROP_SOUND_PITCH, pitch);
|
||||
CHECK_PROPERTY_CHANGE(PROP_SOUND_PLAYING, playing);
|
||||
CHECK_PROPERTY_CHANGE(PROP_SOUND_LOOP, loop);
|
||||
CHECK_PROPERTY_CHANGE(PROP_SOUND_POSITIONAL, positional);
|
||||
CHECK_PROPERTY_CHANGE(PROP_SOUND_LOCAL_ONLY, localOnly);
|
||||
|
||||
return changedProperties;
|
||||
}
|
||||
|
||||
|
@ -917,6 +927,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
* @see {@link Entities.EntityProperties-PolyVox|EntityProperties-PolyVox}
|
||||
* @see {@link Entities.EntityProperties-ProceduralParticleEffect|EntityProperties-ProceduralParticleEffect}
|
||||
* @see {@link Entities.EntityProperties-Shape|EntityProperties-Shape}
|
||||
* @see {@link Entities.EntityProperties-Sound|EntityProperties-Sound}
|
||||
* @see {@link Entities.EntityProperties-Sphere|EntityProperties-Sphere}
|
||||
* @see {@link Entities.EntityProperties-Text|EntityProperties-Text}
|
||||
* @see {@link Entities.EntityProperties-Web|EntityProperties-Web}
|
||||
|
@ -1424,6 +1435,35 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
* });
|
||||
*/
|
||||
|
||||
/*@jsdoc
|
||||
* The <code>"Sound"</code> {@link Entities.EntityType|EntityType} plays a sound from a URL. It has properties in addition to
|
||||
* the common {@link Entities.EntityProperties|EntityProperties}.
|
||||
*
|
||||
* @typedef {object} Entities.EntityProperties-Sound
|
||||
* @property {string} soundURL="" - The URL of the sound to play, as a wav, mp3, or raw file. Supports stereo and ambisonic.
|
||||
* Note: ambisonic sounds can only play as <code>localOnly</code>.
|
||||
* @property {boolean} playing=true - Whether or not the sound should play.
|
||||
* @property {number} volume=1.0 - The volume of the sound, from <code>0</code> to <code>1</code>.
|
||||
* @property {number} pitch=1.0 - The relative sample rate at which to resample the sound, within +/- 2 octaves.
|
||||
* @property {number} timeOffset=0.0 - The time (in seconds) at which to start playback within the sound file. If looping,
|
||||
* this only affects the first loop.
|
||||
* @property {boolean} loop=true - Whether or not to loop the sound.
|
||||
* @property {boolean} positional=true - Whether or not the volume of the sound should decay with distance.
|
||||
* @property {boolean} localOnly=false - Whether or not the sound should play locally for everyone (unsynced), or synchronously
|
||||
* for everyone via the Entity Mixer.
|
||||
* @example <caption>Create a Sound entity.</caption>
|
||||
* var entity = Entities.addEntity({
|
||||
* type: "Sound",
|
||||
* soundURL: "https://themushroomkingdom.net/sounds/wav/lm/lm_gold_mouse.wav",
|
||||
* positional: true,
|
||||
* volume: 0.75,
|
||||
* localOnly: true,
|
||||
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.75, z: -4 })),
|
||||
* rotation: MyAvatar.orientation,
|
||||
* lifetime: 300 // Delete after 5 minutes.
|
||||
* });
|
||||
*/
|
||||
|
||||
/*@jsdoc
|
||||
* The <code>"Sphere"</code> {@link Entities.EntityType|EntityType} is the same as the <code>"Shape"</code>
|
||||
* {@link Entities.EntityType|EntityType} except that its <code>shape</code> value is always set to <code>"Sphere"</code>
|
||||
|
@ -2066,6 +2106,18 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
_ring.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
}
|
||||
|
||||
// Sound only
|
||||
if (_type == EntityTypes::Sound) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOUND_URL, soundURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOUND_VOLUME, volume);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOUND_TIME_OFFSET, timeOffset);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOUND_PITCH, pitch);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOUND_PLAYING, playing);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOUND_LOOP, loop);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOUND_POSITIONAL, positional);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOUND_LOCAL_ONLY, localOnly);
|
||||
}
|
||||
|
||||
/*@jsdoc
|
||||
* The axis-aligned bounding box of an entity.
|
||||
* @typedef {object} Entities.BoundingBox
|
||||
|
@ -2409,6 +2461,16 @@ void EntityItemProperties::copyFromScriptValue(const ScriptValue& object, bool h
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(gizmoType, GizmoType);
|
||||
_ring.copyFromScriptValue(object, namesSet, _defaultSettings);
|
||||
|
||||
// Sound
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(soundURL, QString, setSoundURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(volume, float, setVolume);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(timeOffset, float, setTimeOffset);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(pitch, float, setPitch);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(playing, bool, setPlaying);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(loop, bool, setLoop);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(positional, bool, setPositional);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localOnly, bool, setLocalOnly);
|
||||
|
||||
// Handle conversions from old 'textures' property to "imageURL"
|
||||
if (namesSet.contains("textures")) {
|
||||
ScriptValue V = object.property("textures");
|
||||
|
@ -2707,6 +2769,16 @@ void EntityItemProperties::merge(const EntityItemProperties& other) {
|
|||
COPY_PROPERTY_IF_CHANGED(gizmoType);
|
||||
_ring.merge(other._ring);
|
||||
|
||||
// Sound
|
||||
COPY_PROPERTY_IF_CHANGED(soundURL);
|
||||
COPY_PROPERTY_IF_CHANGED(volume);
|
||||
COPY_PROPERTY_IF_CHANGED(timeOffset);
|
||||
COPY_PROPERTY_IF_CHANGED(pitch);
|
||||
COPY_PROPERTY_IF_CHANGED(playing);
|
||||
COPY_PROPERTY_IF_CHANGED(loop);
|
||||
COPY_PROPERTY_IF_CHANGED(positional);
|
||||
COPY_PROPERTY_IF_CHANGED(localOnly);
|
||||
|
||||
_lastEdited = usecTimestampNow();
|
||||
}
|
||||
|
||||
|
@ -3162,6 +3234,16 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
|
|||
ADD_GROUP_PROPERTY_TO_MAP(PROP_MAJOR_TICK_MARKS_COLOR, Ring, ring, MajorTickMarksColor, majorTickMarksColor);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_MINOR_TICK_MARKS_COLOR, Ring, ring, MinorTickMarksColor, minorTickMarksColor);
|
||||
}
|
||||
|
||||
// Sound
|
||||
ADD_PROPERTY_TO_MAP(PROP_SOUND_URL, SoundURL, soundURL, QString);
|
||||
ADD_PROPERTY_TO_MAP_WITH_RANGE(PROP_SOUND_VOLUME, Volume, volume, float, 0.0f, 1.0f);
|
||||
ADD_PROPERTY_TO_MAP(PROP_SOUND_TIME_OFFSET, TimeOffset, timeOffset, float);
|
||||
ADD_PROPERTY_TO_MAP_WITH_RANGE(PROP_SOUND_PITCH, Pitch, pitch, float, 1.0f / 16.0f, 16.0f);
|
||||
ADD_PROPERTY_TO_MAP(PROP_SOUND_PLAYING, Playing, playing, bool);
|
||||
ADD_PROPERTY_TO_MAP(PROP_SOUND_LOOP, Loop, loop, bool);
|
||||
ADD_PROPERTY_TO_MAP(PROP_SOUND_POSITIONAL, Positional, positional, bool);
|
||||
ADD_PROPERTY_TO_MAP(PROP_SOUND_LOCAL_ONLY, LocalOnly, localOnly, bool);
|
||||
});
|
||||
|
||||
auto iter = _propertyInfos.find(propertyName);
|
||||
|
@ -3627,6 +3709,17 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
|
|||
_staticRing.appendToEditPacket(packetData, requestedProperties, propertyFlags,
|
||||
propertiesDidntFit, propertyCount, appendState);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Sound) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_URL, properties.getSoundURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_VOLUME, properties.getVolume());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_TIME_OFFSET, properties.getTimeOffset());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_PITCH, properties.getPitch());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_PLAYING, properties.getPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_LOOP, properties.getLoop());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_POSITIONAL, properties.getPositional());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_LOCAL_ONLY, properties.getLocalOnly());
|
||||
}
|
||||
}
|
||||
|
||||
if (propertyCount > 0) {
|
||||
|
@ -4103,6 +4196,17 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
properties.getRing().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Sound) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOUND_URL, QString, setSoundURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOUND_VOLUME, float, setVolume);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOUND_TIME_OFFSET, float, setTimeOffset);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOUND_PITCH, float, setPitch);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOUND_PLAYING, bool, setPlaying);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOUND_LOOP, bool, setLoop);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOUND_POSITIONAL, bool, setPositional);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOUND_LOCAL_ONLY, bool, setLocalOnly);
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
@ -4444,6 +4548,16 @@ void EntityItemProperties::markAllChanged() {
|
|||
// Gizmo
|
||||
_gizmoTypeChanged = true;
|
||||
_ring.markAllChanged();
|
||||
|
||||
// Sound
|
||||
_soundURLChanged = true;
|
||||
_volumeChanged = true;
|
||||
_timeOffsetChanged = true;
|
||||
_pitchChanged = true;
|
||||
_playingChanged = true;
|
||||
_loopChanged = true;
|
||||
_positionalChanged = true;
|
||||
_localOnlyChanged = true;
|
||||
}
|
||||
|
||||
// The minimum bounding box for the entity.
|
||||
|
@ -5177,6 +5291,32 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
}
|
||||
getRing().listChangedProperties(out);
|
||||
|
||||
// Sound
|
||||
if (soundURLChanged()) {
|
||||
out += "soundURL";
|
||||
}
|
||||
if (volumeChanged()) {
|
||||
out += "volume";
|
||||
}
|
||||
if (timeOffsetChanged()) {
|
||||
out += "timeOffset";
|
||||
}
|
||||
if (pitchChanged()) {
|
||||
out += "pitch";
|
||||
}
|
||||
if (playingChanged()) {
|
||||
out += "playing";
|
||||
}
|
||||
if (loopChanged()) {
|
||||
out += "loop";
|
||||
}
|
||||
if (positionalChanged()) {
|
||||
out += "positional";
|
||||
}
|
||||
if (localOnlyChanged()) {
|
||||
out += "localOnly";
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "PolyVoxEntityItem.h"
|
||||
#include "GridEntityItem.h"
|
||||
#include "GizmoEntityItem.h"
|
||||
#include "SoundEntityItem.h"
|
||||
#include "LightEntityItem.h"
|
||||
#include "ZoneEntityItem.h"
|
||||
|
||||
|
@ -128,6 +129,8 @@ class EntityItemProperties {
|
|||
friend class LightEntityItem;
|
||||
friend class ZoneEntityItem;
|
||||
friend class MaterialEntityItem;
|
||||
friend class SoundEntityItem;
|
||||
|
||||
public:
|
||||
static bool blobToProperties(ScriptEngine& scriptEngine, const QByteArray& blob, EntityItemProperties& properties);
|
||||
static void propertiesToBlob(ScriptEngine& scriptEngine, const QUuid& myAvatarID, const EntityItemProperties& properties,
|
||||
|
@ -423,6 +426,16 @@ public:
|
|||
DEFINE_PROPERTY_REF_ENUM(PROP_GIZMO_TYPE, GizmoType, gizmoType, GizmoType, GizmoType::RING);
|
||||
DEFINE_PROPERTY_GROUP(Ring, ring, RingGizmoPropertyGroup);
|
||||
|
||||
// Sound
|
||||
DEFINE_PROPERTY_REF(PROP_SOUND_URL, SoundURL, soundURL, QString, "");
|
||||
DEFINE_PROPERTY(PROP_SOUND_VOLUME, Volume, volume, float, 1.0f);
|
||||
DEFINE_PROPERTY(PROP_SOUND_TIME_OFFSET, TimeOffset, timeOffset, float, 0.0f);
|
||||
DEFINE_PROPERTY(PROP_SOUND_PITCH, Pitch, pitch, float, 1.0f);
|
||||
DEFINE_PROPERTY(PROP_SOUND_PLAYING, Playing, playing, bool, true);
|
||||
DEFINE_PROPERTY(PROP_SOUND_LOOP, Loop, loop, bool, true);
|
||||
DEFINE_PROPERTY(PROP_SOUND_POSITIONAL, Positional, positional, bool, true);
|
||||
DEFINE_PROPERTY(PROP_SOUND_LOCAL_ONLY, LocalOnly, localOnly, bool, false);
|
||||
|
||||
static QString getComponentModeAsString(uint32_t mode);
|
||||
|
||||
public:
|
||||
|
|
|
@ -439,6 +439,16 @@ enum EntityPropertyList {
|
|||
PROP_MAJOR_TICK_MARKS_COLOR = PROP_DERIVED_17,
|
||||
PROP_MINOR_TICK_MARKS_COLOR = PROP_DERIVED_18,
|
||||
|
||||
// Sound
|
||||
PROP_SOUND_URL = PROP_DERIVED_0,
|
||||
PROP_SOUND_VOLUME = PROP_DERIVED_1,
|
||||
PROP_SOUND_TIME_OFFSET = PROP_DERIVED_2,
|
||||
PROP_SOUND_PITCH = PROP_DERIVED_3,
|
||||
PROP_SOUND_PLAYING = PROP_DERIVED_4,
|
||||
PROP_SOUND_POSITIONAL = PROP_DERIVED_5,
|
||||
PROP_SOUND_LOOP = PROP_DERIVED_6,
|
||||
PROP_SOUND_LOCAL_ONLY = PROP_DERIVED_7,
|
||||
|
||||
// WARNING!!! DO NOT ADD PROPS_xxx here unless you really really meant to.... Add them UP above
|
||||
};
|
||||
|
||||
|
|
|
@ -1879,6 +1879,7 @@ bool EntityScriptingInterface::setAllPoints(const QUuid& entityID, const QVector
|
|||
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
|
||||
if (!entity) {
|
||||
qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID;
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityTypes::EntityType entityType = entity->getType();
|
||||
|
@ -1915,6 +1916,29 @@ bool EntityScriptingInterface::appendPoint(const QUuid& entityID, const glm::vec
|
|||
return false;
|
||||
}
|
||||
|
||||
bool EntityScriptingInterface::restartSound(const QUuid& entityID) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
|
||||
if (!entity) {
|
||||
qCDebug(entities) << "EntityScriptingInterface::restartSound no entity with ID" << entityID;
|
||||
// There is no entity
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityTypes::EntityType entityType = entity->getType();
|
||||
|
||||
if (entityType == EntityTypes::Sound) {
|
||||
auto soundEntity = std::dynamic_pointer_cast<SoundEntityItem>(entity);
|
||||
bool isPlaying = soundEntity->getPlaying();
|
||||
if (isPlaying) {
|
||||
soundEntity->restartSound(true);
|
||||
}
|
||||
return isPlaying;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EntityScriptingInterface::actionWorker(const QUuid& entityID,
|
||||
std::function<bool(EntitySimulationPointer, EntityItemPointer)> actor) {
|
||||
|
|
|
@ -1263,6 +1263,27 @@ public slots:
|
|||
*/
|
||||
Q_INVOKABLE bool appendPoint(const QUuid& entityID, const glm::vec3& point);
|
||||
|
||||
/*@jsdoc
|
||||
* Restart a {@link Entities.EntityProperties-Sound|Sound} entity, locally only. It must also be <code>localOnly</code>.
|
||||
* @function Entities.restartSound
|
||||
* @param {Uuid} entityID - The ID of the {@link Entities.EntityProperties-Sound|Sound} entity.
|
||||
* @example <caption>Play a sound once and repeat it every 3 seconds.</caption>
|
||||
* var position = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.5, z: -8 }));
|
||||
* var sound = Entities.addEntity({
|
||||
* type: "Sound",
|
||||
* position: position,
|
||||
* soundURL: "https://themushroomkingdom.net/sounds/wav/lm/lm_gold_mouse.wav",
|
||||
* positional: false,
|
||||
* localOnly: true,
|
||||
* loop: false,
|
||||
* lifetime: 300 // Delete after 5 minutes.
|
||||
* });
|
||||
* Script.setInterval(() => {
|
||||
* Entities.restartSound(sound);
|
||||
* }, 3000);
|
||||
*/
|
||||
Q_INVOKABLE bool restartSound(const QUuid& entityID);
|
||||
|
||||
/*@jsdoc
|
||||
* Dumps debug information about all entities in Interface's local in-memory tree of entities it knows about to the program
|
||||
* log.
|
||||
|
|
|
@ -258,6 +258,9 @@ public:
|
|||
void setIsServerlessMode(bool value) { _serverlessDomain = value; }
|
||||
bool isServerlessMode() const { return _serverlessDomain; }
|
||||
|
||||
void setIsEntityServer(bool value) { _entityServer = value; }
|
||||
bool isEntityServer() const { return _entityServer; }
|
||||
|
||||
static void setGetEntityObjectOperator(std::function<QObject*(const QUuid&)> getEntityObjectOperator) { _getEntityObjectOperator = getEntityObjectOperator; }
|
||||
static QObject* getEntityObject(const QUuid& id);
|
||||
|
||||
|
@ -381,6 +384,7 @@ private:
|
|||
std::vector<int32_t> _staleProxies;
|
||||
|
||||
bool _serverlessDomain { false };
|
||||
bool _entityServer { false };
|
||||
|
||||
std::map<QString, QString> _namedPaths;
|
||||
|
||||
|
|
|
@ -257,8 +257,8 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori
|
|||
}
|
||||
} else {
|
||||
// if the entity type doesn't support a detailed intersection, then just return the non-AABox results
|
||||
// Never intersect with particle entities
|
||||
if (localDistance < distance && (entity->getType() != EntityTypes::ParticleEffect && entity->getType() != EntityTypes::ProceduralParticleEffect)) {
|
||||
// Never intersect with particle or sound entities
|
||||
if (localDistance < distance && (entity->getType() != EntityTypes::ParticleEffect && entity->getType() != EntityTypes::ProceduralParticleEffect && entity->getType() != EntityTypes::Sound)) {
|
||||
distance = localDistance;
|
||||
face = localFace;
|
||||
surfaceNormal = glm::vec3(rotation * glm::vec4(localSurfaceNormal, 0.0f));
|
||||
|
@ -409,8 +409,8 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3
|
|||
}
|
||||
} else {
|
||||
// if the entity type doesn't support a detailed intersection, then just return the non-AABox results
|
||||
// Never intersect with particle entities
|
||||
if (localDistance < parabolicDistance && (entity->getType() != EntityTypes::ParticleEffect && entity->getType() != EntityTypes::ProceduralParticleEffect)) {
|
||||
// Never intersect with particle or sound entities
|
||||
if (localDistance < parabolicDistance && (entity->getType() != EntityTypes::ParticleEffect && entity->getType() != EntityTypes::ProceduralParticleEffect && entity->getType() != EntityTypes::Sound)) {
|
||||
parabolicDistance = localDistance;
|
||||
face = localFace;
|
||||
surfaceNormal = glm::vec3(rotation * glm::vec4(localSurfaceNormal, 0.0f));
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "LightEntityItem.h"
|
||||
#include "ZoneEntityItem.h"
|
||||
#include "MaterialEntityItem.h"
|
||||
#include "SoundEntityItem.h"
|
||||
|
||||
QMap<EntityTypes::EntityType, QString> EntityTypes::_typeToNameMap;
|
||||
QMap<QString, EntityTypes::EntityType> EntityTypes::_nameToTypeMap;
|
||||
|
@ -62,6 +63,7 @@ REGISTER_ENTITY_TYPE(Gizmo)
|
|||
REGISTER_ENTITY_TYPE(Light)
|
||||
REGISTER_ENTITY_TYPE(Zone)
|
||||
REGISTER_ENTITY_TYPE(Material)
|
||||
REGISTER_ENTITY_TYPE(Sound)
|
||||
|
||||
bool EntityTypes::typeIsValid(EntityType type) {
|
||||
return type > EntityType::Unknown && type <= EntityType::NUM_TYPES;
|
||||
|
|
|
@ -90,6 +90,8 @@ public:
|
|||
* <td>{@link Entities.EntityProperties-Zone|EntityProperties-Zone}</td></tr>
|
||||
* <tr><td><code>"Material"</code></td><td>Modifies the existing materials on entities and avatars.</td>
|
||||
* <td>{@link Entities.EntityProperties-Material|EntityProperties-Material}</td></tr>
|
||||
* <tr><td><code>"Sound"</code></td><td>Plays a sound.</td>
|
||||
* <td>{@link Entities.EntityProperties-Material|EntityProperties-Sound}</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} Entities.EntityType
|
||||
|
@ -113,6 +115,7 @@ public:
|
|||
Light,
|
||||
Zone,
|
||||
Material,
|
||||
Sound,
|
||||
NUM_TYPES
|
||||
} EntityType;
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ void SimpleEntitySimulation::addEntityToInternalLists(EntityItemPointer entity)
|
|||
// we don't allow dynamic objects to move without an owner so nothing to do here
|
||||
} else if (entity->isMovingRelativeToParent()) {
|
||||
SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity);
|
||||
if (itr != _simpleKinematicEntities.end()) {
|
||||
if (itr == _simpleKinematicEntities.end()) {
|
||||
_simpleKinematicEntities.insert(entity);
|
||||
entity->setLastSimulated(usecTimestampNow());
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ void SimpleEntitySimulation::addEntityToInternalLists(EntityItemPointer entity)
|
|||
|
||||
if (entity->isMovingRelativeToParent()) {
|
||||
SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity);
|
||||
if (itr != _simpleKinematicEntities.end()) {
|
||||
if (itr == _simpleKinematicEntities.end()) {
|
||||
_simpleKinematicEntities.insert(entity);
|
||||
entity->setLastSimulated(usecTimestampNow());
|
||||
}
|
||||
|
|
446
libraries/entities/src/SoundEntityItem.cpp
Normal file
446
libraries/entities/src/SoundEntityItem.cpp
Normal file
|
@ -0,0 +1,446 @@
|
|||
//
|
||||
// Created by HifiExperiments on 12/30/2023
|
||||
// Copyright 2023 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "SoundEntityItem.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityItemProperties.h"
|
||||
#include "EntityTree.h"
|
||||
#include "EntityTreeElement.h"
|
||||
|
||||
EntityItemPointer SoundEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
std::shared_ptr<SoundEntityItem> entity(new SoundEntityItem(entityID), [](SoundEntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
// our non-pure virtual subclass for now...
|
||||
SoundEntityItem::SoundEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
|
||||
_type = EntityTypes::Sound;
|
||||
}
|
||||
|
||||
SoundEntityItem::~SoundEntityItem() {
|
||||
auto manager = DependencyManager::get<AudioInjectorManager>();
|
||||
if (manager && _injector) {
|
||||
manager->stop(_injector);
|
||||
}
|
||||
}
|
||||
|
||||
EntityItemProperties SoundEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(soundURL, getURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(volume, getVolume);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(timeOffset, getTimeOffset);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(pitch, getPitch);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(playing, getPlaying);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(loop, getLoop);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(positional, getPositional);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(localOnly, getLocalOnly);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
bool SoundEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
|
||||
bool somethingChanged = false;
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(soundURL, setURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(volume, setVolume);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(timeOffset, setTimeOffset);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(pitch, setPitch);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(playing, setPlaying);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(loop, setLoop);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(positional, setPositional);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localOnly, setLocalOnly);
|
||||
|
||||
return somethingChanged;
|
||||
}
|
||||
|
||||
int SoundEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||
bool& somethingChanged) {
|
||||
|
||||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_SOUND_URL, QString, setURL);
|
||||
READ_ENTITY_PROPERTY(PROP_SOUND_VOLUME, float, setVolume);
|
||||
READ_ENTITY_PROPERTY(PROP_SOUND_TIME_OFFSET, float, setTimeOffset);
|
||||
READ_ENTITY_PROPERTY(PROP_SOUND_PITCH, float, setPitch);
|
||||
READ_ENTITY_PROPERTY(PROP_SOUND_PLAYING, bool, setPlaying);
|
||||
READ_ENTITY_PROPERTY(PROP_SOUND_LOOP, bool, setLoop);
|
||||
READ_ENTITY_PROPERTY(PROP_SOUND_POSITIONAL, bool, setPositional);
|
||||
READ_ENTITY_PROPERTY(PROP_SOUND_LOCAL_ONLY, bool, setLocalOnly);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
EntityPropertyFlags SoundEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
|
||||
requestedProperties += PROP_SOUND_URL;
|
||||
requestedProperties += PROP_SOUND_VOLUME;
|
||||
requestedProperties += PROP_SOUND_TIME_OFFSET;
|
||||
requestedProperties += PROP_SOUND_PITCH;
|
||||
requestedProperties += PROP_SOUND_PLAYING;
|
||||
requestedProperties += PROP_SOUND_LOOP;
|
||||
requestedProperties += PROP_SOUND_POSITIONAL;
|
||||
requestedProperties += PROP_SOUND_LOCAL_ONLY;
|
||||
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
void SoundEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_URL, getURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_VOLUME, getVolume());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_TIME_OFFSET, getTimeOffset());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_PITCH, getPitch());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_PLAYING, getPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_LOOP, getLoop());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_POSITIONAL, getPositional());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOUND_LOCAL_ONLY, getLocalOnly());
|
||||
}
|
||||
|
||||
void SoundEntityItem::debugDump() const {
|
||||
quint64 now = usecTimestampNow();
|
||||
qCDebug(entities) << "SOUND EntityItem id:" << getEntityItemID() << "---------------------------------------------";
|
||||
qCDebug(entities) << " name:" << _name;
|
||||
qCDebug(entities) << " url:" << _url;
|
||||
qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition());
|
||||
qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions());
|
||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
qCDebug(entities) << "SOUND EntityItem Ptr:" << this;
|
||||
}
|
||||
|
||||
bool SoundEntityItem::shouldCreateSound(const EntityTreePointer& tree) const {
|
||||
bool clientShouldMakeSound = _localOnly || isMyAvatarEntity() || tree->isServerlessMode();
|
||||
bool serverShouldMakeSound = !_localOnly;
|
||||
return (clientShouldMakeSound && tree->getIsClient()) || (serverShouldMakeSound && tree->isEntityServer());
|
||||
}
|
||||
|
||||
void SoundEntityItem::update(const quint64& now) {
|
||||
const auto tree = getTree();
|
||||
if (tree) {
|
||||
std::lock_guard<std::recursive_mutex> lock(_soundLock);
|
||||
|
||||
_updateNeeded = false;
|
||||
|
||||
withReadLock([&] {
|
||||
if (shouldCreateSound(tree)) {
|
||||
_sound = DependencyManager::get<SoundCache>()->getSound(_url);
|
||||
}
|
||||
});
|
||||
|
||||
if (_sound) {
|
||||
if (_sound->isLoaded()) {
|
||||
updateSound(true);
|
||||
} else {
|
||||
connect(_sound.data(), &Resource::finished, this, [&] { updateSound(true); });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundEntityItem::locationChanged(bool tellPhysics, bool tellChildren) {
|
||||
EntityItem::locationChanged(tellPhysics, tellChildren);
|
||||
updateSound();
|
||||
}
|
||||
|
||||
void SoundEntityItem::dimensionsChanged() {
|
||||
EntityItem::dimensionsChanged();
|
||||
updateSound();
|
||||
}
|
||||
|
||||
void SoundEntityItem::setURL(const QString& value) {
|
||||
bool changed = false;
|
||||
withWriteLock([&] {
|
||||
if (value != _url) {
|
||||
_url = value;
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
const auto tree = getTree();
|
||||
if (!tree) {
|
||||
_updateNeeded = true;
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::recursive_mutex> lock(_soundLock);
|
||||
|
||||
withReadLock([&] {
|
||||
if (shouldCreateSound(tree)) {
|
||||
_sound = DependencyManager::get<SoundCache>()->getSound(_url);
|
||||
}
|
||||
});
|
||||
|
||||
if (_sound) {
|
||||
if (_sound->isLoaded()) {
|
||||
updateSound(true);
|
||||
} else {
|
||||
connect(_sound.data(), &Resource::finished, this, [&] { updateSound(true); });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString SoundEntityItem::getURL() const {
|
||||
return resultWithReadLock<QString>([&] {
|
||||
return _url;
|
||||
});
|
||||
}
|
||||
|
||||
void SoundEntityItem::setVolume(float value) {
|
||||
bool changed = false;
|
||||
withWriteLock([&] {
|
||||
if (value != _volume) {
|
||||
_volume = value;
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
updateSound();
|
||||
}
|
||||
}
|
||||
|
||||
float SoundEntityItem::getVolume() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _volume;
|
||||
});
|
||||
}
|
||||
|
||||
void SoundEntityItem::setTimeOffset(float value) {
|
||||
bool changed = false;
|
||||
withWriteLock([&] {
|
||||
if (value != _timeOffset) {
|
||||
_timeOffset = value;
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
updateSound(true);
|
||||
}
|
||||
}
|
||||
|
||||
float SoundEntityItem::getTimeOffset() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _timeOffset;
|
||||
});
|
||||
}
|
||||
|
||||
void SoundEntityItem::setPitch(float value) {
|
||||
bool changed = false;
|
||||
withWriteLock([&] {
|
||||
if (value != _pitch) {
|
||||
_pitch = value;
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
updateSound(true);
|
||||
}
|
||||
}
|
||||
|
||||
float SoundEntityItem::getPitch() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _pitch;
|
||||
});
|
||||
}
|
||||
|
||||
void SoundEntityItem::setPlaying(bool value) {
|
||||
bool changed = false;
|
||||
withWriteLock([&] {
|
||||
if (value != _playing) {
|
||||
_playing = value;
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
updateSound();
|
||||
}
|
||||
}
|
||||
|
||||
bool SoundEntityItem::getPlaying() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _playing;
|
||||
});
|
||||
}
|
||||
|
||||
void SoundEntityItem::setLoop(bool value) {
|
||||
bool changed = false;
|
||||
withWriteLock([&] {
|
||||
if (value != _loop) {
|
||||
_loop = value;
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
updateSound(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool SoundEntityItem::getLoop() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _loop;
|
||||
});
|
||||
}
|
||||
|
||||
void SoundEntityItem::setPositional(bool value) {
|
||||
bool changed = false;
|
||||
withWriteLock([&] {
|
||||
if (value != _positional) {
|
||||
_positional = value;
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
updateSound();
|
||||
}
|
||||
}
|
||||
|
||||
bool SoundEntityItem::getPositional() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _positional;
|
||||
});
|
||||
}
|
||||
|
||||
void SoundEntityItem::setLocalOnly(bool value) {
|
||||
bool changed = false;
|
||||
withWriteLock([&] {
|
||||
if (value != _localOnly) {
|
||||
_localOnly = value;
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
const auto tree = getTree();
|
||||
if (!tree) {
|
||||
_updateNeeded = true;
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::recursive_mutex> lock(_soundLock);
|
||||
|
||||
bool createdSound = false;
|
||||
withReadLock([&] {
|
||||
if (shouldCreateSound(tree)) {
|
||||
_sound = DependencyManager::get<SoundCache>()->getSound(_url);
|
||||
createdSound = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!createdSound) {
|
||||
_sound = nullptr;
|
||||
|
||||
if (_injector) {
|
||||
DependencyManager::get<AudioInjectorManager>()->stop(_injector);
|
||||
_injector = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (_sound) {
|
||||
if (_sound->isLoaded()) {
|
||||
updateSound(true);
|
||||
} else {
|
||||
connect(_sound.data(), &Resource::finished, this, [&] { updateSound(true); });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SoundEntityItem::getLocalOnly() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _localOnly;
|
||||
});
|
||||
}
|
||||
|
||||
bool SoundEntityItem::restartSound(bool lock) {
|
||||
if (lock) {
|
||||
_soundLock.lock();
|
||||
}
|
||||
|
||||
if (!_sound) {
|
||||
if (lock) {
|
||||
_soundLock.unlock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioInjectorOptions options;
|
||||
withReadLock([&] {
|
||||
const glm::quat orientation = getWorldOrientation();
|
||||
options.position = getWorldPosition() + orientation * (getScaledDimensions() * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()));
|
||||
options.positionSet = _positional;
|
||||
options.volume = _volume;
|
||||
options.loop = _loop;
|
||||
options.orientation = orientation;
|
||||
options.localOnly = _localOnly || _sound->isAmbisonic(); // force localOnly when ambisonic
|
||||
options.secondOffset = _timeOffset;
|
||||
options.pitch = _pitch;
|
||||
});
|
||||
|
||||
// stereo option isn't set from script, this comes from sound metadata or filename
|
||||
options.stereo = _sound->isStereo();
|
||||
options.ambisonic = _sound->isAmbisonic();
|
||||
|
||||
if (_injector) {
|
||||
DependencyManager::get<AudioInjectorManager>()->setOptions(_injector, options);
|
||||
} else {
|
||||
_injector = DependencyManager::get<AudioInjectorManager>()->playSound(_sound, options);
|
||||
}
|
||||
|
||||
if (lock) {
|
||||
_soundLock.unlock();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SoundEntityItem::updateSound(bool restart) {
|
||||
std::lock_guard<std::recursive_mutex> lock(_soundLock);
|
||||
|
||||
if (!_sound) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (restart) {
|
||||
if (_injector) {
|
||||
DependencyManager::get<AudioInjectorManager>()->stop(_injector);
|
||||
_injector = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (_playing) {
|
||||
restartSound();
|
||||
} else {
|
||||
if (_injector) {
|
||||
DependencyManager::get<AudioInjectorManager>()->stop(_injector);
|
||||
_injector = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
102
libraries/entities/src/SoundEntityItem.h
Normal file
102
libraries/entities/src/SoundEntityItem.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
//
|
||||
// Created by HifiExperiments on 12/30/2023
|
||||
// Copyright 2023 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_SoundEntityItem_h
|
||||
#define hifi_SoundEntityItem_h
|
||||
|
||||
#include "EntityItem.h"
|
||||
|
||||
#include <SoundCache.h>
|
||||
#include <AudioInjectorManager.h>
|
||||
|
||||
class SoundEntityItem : public EntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
SoundEntityItem(const EntityItemID& entityItemID);
|
||||
~SoundEntityItem();
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
|
||||
bool setSubClassProperties(const EntityItemProperties& properties) override;
|
||||
|
||||
EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
|
||||
|
||||
void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const override;
|
||||
|
||||
int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||
bool& somethingChanged) override;
|
||||
|
||||
bool shouldBePhysical() const override { return false; }
|
||||
|
||||
virtual void debugDump() const override;
|
||||
|
||||
virtual bool supportsDetailedIntersection() const override { return false; }
|
||||
|
||||
virtual void update(const quint64& now) override;
|
||||
bool needsToCallUpdate() const override { return _updateNeeded; }
|
||||
|
||||
void locationChanged(bool tellPhysics = true, bool tellChildren = true) override;
|
||||
void dimensionsChanged() override;
|
||||
|
||||
void setURL(const QString& value);
|
||||
QString getURL() const;
|
||||
|
||||
void setVolume(float value);
|
||||
float getVolume() const;
|
||||
|
||||
void setTimeOffset(float value);
|
||||
float getTimeOffset() const;
|
||||
|
||||
void setPitch(float value);
|
||||
float getPitch() const;
|
||||
|
||||
void setPlaying(bool value);
|
||||
bool getPlaying() const;
|
||||
|
||||
void setLoop(bool value);
|
||||
bool getLoop() const;
|
||||
|
||||
void setPositional(bool value);
|
||||
bool getPositional() const;
|
||||
|
||||
void setLocalOnly(bool value);
|
||||
bool getLocalOnly() const;
|
||||
|
||||
bool restartSound(bool lock = false);
|
||||
|
||||
protected:
|
||||
bool shouldCreateSound(const EntityTreePointer& tree) const;
|
||||
void updateSound(bool restart = false);
|
||||
|
||||
QString _url { "" };
|
||||
float _volume { 1.0f };
|
||||
float _timeOffset { 0.0f };
|
||||
float _pitch { 1.0f };
|
||||
bool _playing { true };
|
||||
bool _loop { true };
|
||||
bool _positional { true };
|
||||
bool _localOnly { false };
|
||||
|
||||
std::recursive_mutex _soundLock;
|
||||
SharedSoundPointer _sound;
|
||||
AudioInjectorPointer _injector;
|
||||
bool _updateNeeded { false };
|
||||
};
|
||||
|
||||
#endif // hifi_SoundEntityItem_h
|
|
@ -183,7 +183,6 @@ QString FSTReader::getNameFromType(ModelType modelType) {
|
|||
_typesToNames[HEAD_MODEL] = "head";
|
||||
_typesToNames[BODY_ONLY_MODEL] = "body";
|
||||
_typesToNames[HEAD_AND_BODY_MODEL] = "body+head";
|
||||
_typesToNames[ATTACHMENT_MODEL] = "attachment";
|
||||
}
|
||||
return _typesToNames[modelType];
|
||||
}
|
||||
|
@ -195,9 +194,6 @@ FSTReader::ModelType FSTReader::getTypeFromName(const QString& name) {
|
|||
_namesToTypes["head"] = HEAD_MODEL ;
|
||||
_namesToTypes["body"] = BODY_ONLY_MODEL;
|
||||
_namesToTypes["body+head"] = HEAD_AND_BODY_MODEL;
|
||||
|
||||
// NOTE: this is not yet implemented, but will be used to allow you to attach fully independent models to your avatar
|
||||
_namesToTypes["attachment"] = ATTACHMENT_MODEL;
|
||||
}
|
||||
return _namesToTypes[name];
|
||||
}
|
||||
|
|
|
@ -42,8 +42,7 @@ public:
|
|||
ENTITY_MODEL,
|
||||
HEAD_MODEL,
|
||||
BODY_ONLY_MODEL,
|
||||
HEAD_AND_BODY_MODEL,
|
||||
ATTACHMENT_MODEL
|
||||
HEAD_AND_BODY_MODEL
|
||||
};
|
||||
|
||||
/// Reads an FST mapping from the supplied data.
|
||||
|
|
|
@ -38,10 +38,10 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
return static_cast<PacketVersion>(EntityQueryPacketVersion::ConicalFrustums);
|
||||
case PacketType::AvatarIdentity:
|
||||
case PacketType::AvatarData:
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::ARKitBlendshapes);
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::RemoveAttachments);
|
||||
case PacketType::BulkAvatarData:
|
||||
case PacketType::KillAvatar:
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::ARKitBlendshapes);
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::RemoveAttachments);
|
||||
case PacketType::MessagesData:
|
||||
return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData);
|
||||
// ICE packets
|
||||
|
|
|
@ -298,6 +298,7 @@ enum class EntityVersion : PacketVersion {
|
|||
ProceduralParticles,
|
||||
ShapeUnlit,
|
||||
AmbientColor,
|
||||
SoundEntities,
|
||||
TonemappingAndAmbientOcclusion,
|
||||
|
||||
// Add new versions above here
|
||||
|
@ -364,7 +365,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
|
|||
FBXJointOrderChange,
|
||||
HandControllerSection,
|
||||
SendVerificationFailed,
|
||||
ARKitBlendshapes
|
||||
ARKitBlendshapes,
|
||||
RemoveAttachments,
|
||||
};
|
||||
|
||||
enum class DomainConnectRequestVersion : PacketVersion {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
set(TARGET_NAME physics)
|
||||
setup_hifi_library()
|
||||
link_hifi_libraries(shared workload entities shaders)
|
||||
include_hifi_library_headers(audio)
|
||||
include_hifi_library_headers(networking)
|
||||
include_hifi_library_headers(gpu)
|
||||
include_hifi_library_headers(avatars)
|
||||
|
|
|
@ -172,10 +172,6 @@ void RecordingScriptingInterface::setPlayerUseDisplayName(bool useDisplayName) {
|
|||
_useDisplayName = useDisplayName;
|
||||
}
|
||||
|
||||
void RecordingScriptingInterface::setPlayerUseAttachments(bool useAttachments) {
|
||||
_useAttachments = useAttachments;
|
||||
}
|
||||
|
||||
void RecordingScriptingInterface::setPlayerUseHeadModel(bool useHeadModel) {
|
||||
_useHeadModel = useHeadModel;
|
||||
}
|
||||
|
|
|
@ -162,14 +162,6 @@ public slots:
|
|||
*/
|
||||
void setPlayerUseDisplayName(bool useDisplayName);
|
||||
|
||||
/*@jsdoc
|
||||
* <p><em>Not used.</em></p>
|
||||
* @function Recording.setPlayerUseAttachments
|
||||
* @param {boolean} useAttachments - Use attachments.
|
||||
* @deprecated This method is deprecated and will be removed.
|
||||
*/
|
||||
void setPlayerUseAttachments(bool useAttachments);
|
||||
|
||||
/*@jsdoc
|
||||
* <p><em>Not used.</em></p>
|
||||
* @function Recording.setPlayerUseHeadModel
|
||||
|
@ -203,14 +195,6 @@ public slots:
|
|||
*/
|
||||
bool getPlayerUseDisplayName() { return _useDisplayName; }
|
||||
|
||||
/*@jsdoc
|
||||
* <p><em>Not used.</em></p>
|
||||
* @function Recording.getPlayerUseAttachments
|
||||
* @returns {boolean} Use attachments.
|
||||
* @deprecated This method is deprecated and will be removed.
|
||||
*/
|
||||
bool getPlayerUseAttachments() { return _useAttachments; }
|
||||
|
||||
/*@jsdoc
|
||||
* <p><em>Not used.</em></p>
|
||||
* @function Recording.getPlayerUseHeadModel
|
||||
|
@ -365,7 +349,6 @@ protected:
|
|||
Flag _playFromCurrentLocation { true };
|
||||
Flag _useDisplayName { false };
|
||||
Flag _useHeadModel { false };
|
||||
Flag _useAttachments { false };
|
||||
Flag _useSkeletonModel { false };
|
||||
recording::ClipPointer _lastClip;
|
||||
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
//
|
||||
// Created by Anthony J. Thibault on 12/17/15.
|
||||
// Copyright 2013 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
|
||||
//
|
||||
|
||||
#include "SoftAttachmentModel.h"
|
||||
|
||||
SoftAttachmentModel::SoftAttachmentModel(QObject* parent, const Rig& rigOverride) :
|
||||
CauterizedModel(parent),
|
||||
_rigOverride(rigOverride) {
|
||||
}
|
||||
|
||||
SoftAttachmentModel::~SoftAttachmentModel() {
|
||||
}
|
||||
|
||||
// virtual
|
||||
void SoftAttachmentModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||
_needsUpdateClusterMatrices = true;
|
||||
}
|
||||
|
||||
int SoftAttachmentModel::getJointIndexOverride(int i) const {
|
||||
QString name = _rig.nameOfJoint(i);
|
||||
if (name.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
return _rigOverride.indexOfJoint(name);
|
||||
}
|
||||
|
||||
// virtual
|
||||
// use the _rigOverride matrices instead of the Model::_rig
|
||||
void SoftAttachmentModel::updateClusterMatrices() {
|
||||
if (!_needsUpdateClusterMatrices) {
|
||||
return;
|
||||
}
|
||||
if (!isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_needsUpdateClusterMatrices = false;
|
||||
|
||||
const HFMModel& hfmModel = getHFMModel();
|
||||
|
||||
for (int i = 0; i < (int) _meshStates.size(); i++) {
|
||||
MeshState& state = _meshStates[i];
|
||||
const HFMMesh& mesh = hfmModel.meshes.at(i);
|
||||
int meshIndex = i;
|
||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||
const HFMCluster& cluster = mesh.clusters.at(j);
|
||||
|
||||
int clusterIndex = j;
|
||||
// TODO: cache these look-ups as an optimization
|
||||
int jointIndexOverride = getJointIndexOverride(cluster.jointIndex);
|
||||
glm::mat4 jointMatrix;
|
||||
if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) {
|
||||
jointMatrix = _rigOverride.getJointTransform(jointIndexOverride);
|
||||
} else {
|
||||
jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
||||
}
|
||||
if (_useDualQuaternionSkinning) {
|
||||
glm::mat4 m;
|
||||
glm_mat4u_mul(jointMatrix, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindMatrix, m);
|
||||
state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(m);
|
||||
} else {
|
||||
glm_mat4u_mul(jointMatrix, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindMatrix, state.clusterMatrices[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateBlendshapes();
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
//
|
||||
// Created by Anthony J. Thibault on 12/17/15.
|
||||
// Copyright 2015 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
|
||||
//
|
||||
|
||||
#ifndef hifi_SoftAttachmentModel_h
|
||||
#define hifi_SoftAttachmentModel_h
|
||||
|
||||
#include "CauterizedModel.h"
|
||||
|
||||
// A model that allows the creator to specify a secondary rig instance.
|
||||
// When the cluster matrices are created for rendering, the
|
||||
// cluster matrices will use the secondary rig for the joint poses
|
||||
// instead of the primary rig.
|
||||
//
|
||||
// This is used by Avatar instances to wear clothing that follows the same
|
||||
// animated pose as the SkeletonModel.
|
||||
|
||||
class SoftAttachmentModel : public CauterizedModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SoftAttachmentModel(QObject* parent, const Rig& rigOverride);
|
||||
~SoftAttachmentModel();
|
||||
|
||||
void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
||||
void updateClusterMatrices() override;
|
||||
|
||||
protected:
|
||||
int getJointIndexOverride(int i) const;
|
||||
|
||||
const Rig& _rigOverride;
|
||||
};
|
||||
|
||||
#endif // hifi_SoftAttachmentModel_h
|
|
@ -69,7 +69,6 @@ const QUuid SpatiallyNestable::getParentID() const {
|
|||
}
|
||||
|
||||
void SpatiallyNestable::setParentID(const QUuid& parentID) {
|
||||
bumpAncestorChainRenderableVersion();
|
||||
bool success = false;
|
||||
auto parent = getParentPointer(success);
|
||||
bool parentChanged = false;
|
||||
|
@ -89,7 +88,6 @@ void SpatiallyNestable::setParentID(const QUuid& parentID) {
|
|||
success = false;
|
||||
parent = getParentPointer(success);
|
||||
if (success && parent) {
|
||||
bumpAncestorChainRenderableVersion();
|
||||
parent->updateQueryAACube();
|
||||
parent->recalculateChildCauterization();
|
||||
}
|
||||
|
@ -1509,17 +1507,3 @@ QUuid SpatiallyNestable::getEditSenderID() {
|
|||
});
|
||||
return editSenderID;
|
||||
}
|
||||
|
||||
void SpatiallyNestable::bumpAncestorChainRenderableVersion(int depth) const {
|
||||
if (depth > MAX_PARENTING_CHAIN_SIZE) {
|
||||
// can't break the parent chain here, because it will call setParentID, which calls this
|
||||
return;
|
||||
}
|
||||
|
||||
_ancestorChainRenderableVersion++;
|
||||
bool success = false;
|
||||
auto parent = getParentPointer(success);
|
||||
if (success && parent) {
|
||||
parent->bumpAncestorChainRenderableVersion(depth + 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -224,8 +224,6 @@ public:
|
|||
bool hasGrabs();
|
||||
virtual QUuid getEditSenderID();
|
||||
|
||||
void bumpAncestorChainRenderableVersion(int depth = 0) const;
|
||||
|
||||
protected:
|
||||
QUuid _id;
|
||||
mutable SpatiallyNestableWeakPointer _parent;
|
||||
|
@ -248,8 +246,6 @@ protected:
|
|||
mutable ReadWriteLockable _grabsLock;
|
||||
QSet<GrabPointer> _grabs; // upon this thing
|
||||
|
||||
mutable std::atomic<uint32_t> _ancestorChainRenderableVersion { 0 };
|
||||
|
||||
private:
|
||||
SpatiallyNestable() = delete;
|
||||
const NestableType _nestableType; // EntityItem or an AvatarData
|
||||
|
|
258
scripts/system/assets/images/tools/sound.svg
Normal file
258
scripts/system/assets/images/tools/sound.svg
Normal file
|
@ -0,0 +1,258 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 50 150"
|
||||
style="enable-background:new 0 0 50 150;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="sound.svg"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs75"><pattern
|
||||
patternUnits="userSpaceOnUse"
|
||||
width="30.420844"
|
||||
height="6.5893951"
|
||||
patternTransform="translate(9.076365,85.62981)"
|
||||
id="pattern181821"><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.76147px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Bold';fill:#eaeaea;fill-opacity:1;stroke:none;stroke-width:0.219039"
|
||||
x="-0.31657657"
|
||||
y="6.3785896"
|
||||
id="text177288"
|
||||
transform="scale(0.98488846,1.0153434)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan177286"
|
||||
x="-0.31657657"
|
||||
y="6.3785896"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Arial;-inkscape-font-specification:'Arial Bold';fill:#eaeaea;stroke-width:0.219039">SOUND</tspan></text></pattern><pattern
|
||||
patternUnits="userSpaceOnUse"
|
||||
width="30.420844"
|
||||
height="6.5893951"
|
||||
patternTransform="translate(9.0763649,35.629775)"
|
||||
id="pattern185125"><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.76147px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.219039"
|
||||
x="-0.31657654"
|
||||
y="6.3785896"
|
||||
id="text128632"
|
||||
transform="scale(0.98488846,1.0153434)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan128630"
|
||||
x="-0.31657654"
|
||||
y="6.3785896"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Arial;-inkscape-font-specification:'Arial Bold';fill:#000000;stroke-width:0.219039">SOUND</tspan></text></pattern><pattern
|
||||
patternUnits="userSpaceOnUse"
|
||||
width="30.420844"
|
||||
height="6.5893951"
|
||||
patternTransform="translate(9.076365,135.62983)"
|
||||
id="pattern185150"><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.76147px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Bold';opacity:0.47;fill:#eaeaea;fill-opacity:1;stroke:none;stroke-width:0.219039"
|
||||
x="-0.31657657"
|
||||
y="6.3785896"
|
||||
id="text177292"
|
||||
transform="scale(0.98488846,1.0153434)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan177290"
|
||||
x="-0.31657657"
|
||||
y="6.3785896"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Arial;-inkscape-font-specification:'Arial Bold';fill:#eaeaea;stroke-width:0.219039">SOUND</tspan></text></pattern></defs><sodipodi:namedview
|
||||
id="namedview73"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="4"
|
||||
inkscape:cx="191.875"
|
||||
inkscape:cy="118.625"
|
||||
inkscape:window-width="5040"
|
||||
inkscape:window-height="979"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style2">
|
||||
.st0{opacity:0.9;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
.st2{fill:#1E1E1E;}
|
||||
.st3{fill:#EAEAEA;}
|
||||
.st4{opacity:0.47;}
|
||||
</style>
|
||||
<g
|
||||
id="g8">
|
||||
<g
|
||||
class="st0"
|
||||
id="g6">
|
||||
<path
|
||||
class="st1"
|
||||
d="M50,46.3c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4v-42c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V46.3z"
|
||||
id="path4" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
class="st0"
|
||||
id="g12">
|
||||
<path
|
||||
class="st2"
|
||||
d="M50,96.3c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4v-42c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V96.3z"
|
||||
id="path10" />
|
||||
</g>
|
||||
|
||||
<rect
|
||||
style="stroke:none;fill:none"
|
||||
width="30.420844"
|
||||
height="6.5893951"
|
||||
x="9.0763649"
|
||||
y="35.629775"
|
||||
id="rect185129" />
|
||||
|
||||
<rect
|
||||
style="stroke:none;fill:none"
|
||||
width="30.420844"
|
||||
height="6.5893951"
|
||||
x="9.076365"
|
||||
y="85.62981"
|
||||
id="rect181825" />
|
||||
<g
|
||||
class="st4"
|
||||
id="g52">
|
||||
<path
|
||||
class="st2"
|
||||
d="M50,146.3c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4v-42c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V146.3z"
|
||||
id="path50" />
|
||||
</g>
|
||||
|
||||
<rect
|
||||
style="stroke:none;fill:none"
|
||||
width="30.420844"
|
||||
height="6.5893951"
|
||||
x="9.076365"
|
||||
y="135.62983"
|
||||
id="rect185154" />
|
||||
<g
|
||||
id="g826"
|
||||
transform="matrix(0.0396779,0,0,0.0396779,9.9752519,4.2669074)"
|
||||
style="fill:#000000"><path
|
||||
d="m 0,0 c 13.827391,10.512174 20.597576,25.087167 23.011719,42.019531 0.092,2.555446 0.13969,5.082998 0.134221,7.637738 l 0.0071,2.281383 c 0.0067,2.525082 0.0062,5.050113 0.0058,7.575203 0.0033,1.827887 0.007,3.655773 0.01114,5.483658 0.01001,5.025394 0.01373,10.050777 0.01639,15.07618 0.0039,5.419517 0.01348,10.839025 0.02221,16.258537 0.01976,13.09077 0.02983,26.18153 0.03873,39.27231 0.0044,6.16812 0.0098,12.33624 0.01499,18.50435 0.01701,20.51107 0.03151,41.02213 0.03875,61.5332 0.0019,5.32194 0.0038,10.64388 0.0058,15.96582 l 7.27e-4,2.0035 c 0.0081,22.08256 0.03335,44.16506 0.06685,66.24759 0.0331,21.9971 0.05109,43.99417 0.05428,65.9913 0.0022,12.3458 0.01087,24.69152 0.03646,37.0373 0.02175,10.51721 0.02974,21.03431 0.02003,31.55154 -0.0045,5.36121 -0.0027,10.72221 0.01676,16.08338 0.01772,4.91925 0.01656,9.83813 0.0011,14.75738 -0.0024,1.76864 0.0019,3.53731 0.01383,5.30591 0.125724,19.85325 -2.709399,39.30431 -17.0403675,54.18372 -8.3454088,7.618 -17.7819935,11.15977 -28.4648435,14.25 l -1.973145,0.59863 c -17.150657,5.19924 -32.361378,4.00814 -48.326172,-4.36035 -15.138528,-8.289 -26.891988,-20.43111 -38.102049,-33.39453 -2.15675,-2.48745 -4.37538,-4.91572 -6.59863,-7.34375 -4.96347,-5.44789 -9.84694,-10.95022 -14.60547,-16.57812 -5.99986,-7.07897 -12.15416,-13.96475 -18.51807,-20.719 -3.54755,-3.76661 -6.99861,-7.5918 -10.37255,-11.51538 -2.14552,-2.40744 -4.4475,-4.64229 -6.75,-6.89844 -1.86484,-1.90221 -3.58897,-3.88668 -5.31641,-5.91406 -6.32304,-7.26238 -12.25876,-13.79009 -22.02691,-15.0505 l -7.22359,-0.6152 c -5.81299,0.20929 -14.93041,0.48418 -24.04986,0.73028 -2.01512,0.057 -4.03,0.12239 -6.04486,0.18835 -13.91246,0.43355 -26.19483,0.60604 -39.09228,-5.12793 l -2.60938,-1.12891 c -6.35051,-3.14241 -11.37831,-7.93784 -16.39062,-12.87109 l -2.35156,-2.3125 c -15.53838,-16.23253 -18.11876,-33.32369 -18.02076,-54.89502 -0.002,-1.8939 -0.006,-3.7878 -0.0111,-5.6817 -0.009,-5.10319 -4e-5,-10.20618 0.0133,-15.30936 0.0114,-5.36218 0.007,-10.72435 0.005,-16.08654 -8.8e-4,-8.99923 0.0101,-17.99839 0.0286,-26.99759 0.0212,-10.3804 0.0247,-20.76069 0.0184,-31.1411 -0.006,-10.01985 -4e-5,-20.03965 0.0112,-30.05949 0.005,-4.24929 0.006,-8.49855 0.003,-12.74784 -0.002,-5.00865 0.006,-10.01718 0.0221,-15.02579 0.004,-1.83006 0.005,-3.66013 0.002,-5.49019 -0.0285,-21.95225 3.71639,-37.88244 18.36863,-54.6435 14.61244,-14.24783 34.5115,-17.73471 54.02344,-17.75 2.80276,-0.0161 5.60547,-0.0379 8.4082,-0.0586 4.39744,-0.0303 8.79459,-0.0531 13.19214,-0.0513 3.5746,8e-4 7.14834,-0.0228 10.72271,-0.0619 2.00158,-0.0154 4.0033,-0.005 6.00491,0.006 9.31056,-0.12346 16.20132,-1.82773 23.25798,-8.08783 l 1.98828,-2.41797 2.23828,-2.652343 2.07422,-2.535156 c 1.11952,-1.296419 2.2442,-2.58841 3.375,-3.875 l 1.69531,-1.945312 c 3.77047,-4.258956 7.63759,-8.430729 11.49024,-12.615235 2.31687,-2.51807 4.62792,-5.041473 6.93945,-7.564453 0.91795,-1.001322 1.83591,-2.002624 2.75391,-3.003906 1.82093,-1.986413 3.64119,-3.973438 5.46093,-5.960938 10.1791,-11.115607 20.40503,-22.186149 30.69922,-33.195312 2.41728,-2.585792 4.82817,-5.177336 7.23438,-7.773438 2.915852,-3.144847 5.845981,-6.275773 8.786614,-9.3974604 C -90.139631,8.18094 -88.740775,6.6596201 -87.34375,5.1367187 -62.778713,-20.817295 -28.205909,-18.693328 0,0 Z m -48.244141,66.221924 -1.58789,1.692138 -1.763672,1.878907 -1.892578,2.039062 -1.939453,2.082031 c -4.247651,4.594835 -8.242647,9.327988 -12.146485,14.21875 -4.188864,5.009015 -8.7178,9.703144 -13.195312,14.453128 -2.882159,3.06065 -5.664738,6.19141 -8.410156,9.375 -3.385406,3.85336 -6.886651,7.60175 -10.376465,11.36035 -2.186548,2.35516 -4.370308,4.71285 -6.551998,7.07251 -8.21016,8.85958 -16.55506,17.57623 -25.05884,26.15454 -1.39336,1.41011 -2.78131,2.82559 -4.16406,4.24609 -2.04543,2.10046 -4.10708,4.18374 -6.17286,6.26416 l -1.8316,1.9003 c -24.02936,23.91421 -66.00557,10.69802 -94.65277,11.06064 v 168 l 58,1 c 30.35546,3.79443 30.35546,3.79443 43.37891,17.01563 l 1.98899,1.98748 c 1.37569,1.37802 2.74774,2.75968 4.11623,4.14484 2.06819,2.09176 4.14935,4.1699 6.23267,6.24658 6.87552,6.89041 13.43025,13.80534 19.2832,21.60547 5.573935,6.98354 11.3661,13.67388 17.437499,20.22266 2.661163,2.88428 5.24949,5.82071 7.820312,8.78515 2.821044,3.22586 5.703196,6.39642 8.578125,9.57422 1.798374,2.00938 3.547726,4.04712 5.289063,6.10547 3.727868,4.28705 7.742389,8.28942 11.75,12.3125 l 2.059082,2.073 1.933105,1.927 1.753418,1.75 c 1.192644,1.36192 1.192644,1.36192 2.379395,1.25 V 65.019531 c -1.169391,-0.11526 -1.169391,-0.11526 -2.25586,1.202393 z"
|
||||
fill="#000000"
|
||||
transform="translate(370.98828,94.980469)"
|
||||
id="path836"
|
||||
sodipodi:nodetypes="ccccccccccsssccsccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
||||
style="fill:#000000" /><path
|
||||
d="m 0,0 c 12.687715,8.3646425 16.54757,23.578013 21.25,37.25 0.420028,1.211683 0.420028,1.211683 0.848541,2.447845 C 24.093738,45.455849 26.057576,51.223992 28,57 c 0.358289,1.064594 0.358289,1.064594 0.723816,2.150696 9.196303,27.421957 18.34758,56.379674 22.213684,85.099304 0.165,1.21301 0.33,2.42602 0.5,3.67578 0.133418,0.98348 0.133418,0.98348 0.269531,1.98682 0.307725,2.19254 0.641643,4.37993 0.980469,6.56787 C 65.117247,237.74117 51.79423,319.60536 24,408 c -0.37689,1.17031 -0.753779,2.34062 -1.14209,3.54639 C 17.545759,427.78218 11.971055,440.11885 -3.1601563,449.3125 -10.974406,453.17271 -20.495807,453.32002 -29,452 c -6.447118,-2.21023 -11.581457,-5.80171 -16,-11 -0.659355,-0.72703 -0.659355,-0.72703 -1.332031,-1.46875 C -53.332437,431.62301 -53,422.82358 -53,412.69922 c 0.741111,-10.03973 4.593387,-18.57148 8.476563,-27.75293 C -4.1662297,289.1502 -7.3944601,181.67277 -47.370117,59.287109 -52.165555,46.157988 -56.413045,31.232358 -51.4375,17.4375 -46.91216,8.1345364 -38.697322,0.74480411 -29.140625,-3.171875 -19.460116,-5.7244469 -8.7875393,-4.8407102 0,0 Z"
|
||||
fill="#000000"
|
||||
transform="translate(634,136)"
|
||||
id="path838"
|
||||
style="fill:#000000" /><path
|
||||
d="m 0,0 c 17.968337,10.39053 22.143536,33.207156 27.238281,51.816406 9.06097,33.99317 13.985108,69.235084 14.882813,104.410154 0.02191,0.81179 0.04383,1.62358 0.06641,2.45996 1.024973,44.84255 -6.637484,88.87597 -20.066406,131.54004 -0.326455,1.04898 -0.65291,2.09795 -0.989258,3.17871 -1.007854,3.21683 -2.036103,6.4263 -3.073242,9.63379 -0.304138,0.96027 -0.608277,1.92054 -0.921631,2.90991 -3.75203,11.33325 -8.7198824,22.01013 -19.3283693,28.21509 -8.8558147,2.55168 -16.4996667,1.12221 -24.6874997,-2.9375 -8.148586,-4.91088 -14.567027,-10.35992 -18.375,-19.1875 -1.817982,-11.08969 -0.01228,-20.87108 3,-31.5625 0.556674,-2.04436 1.107614,-4.09021 1.658188,-6.13623 0.370535,-1.37582 0.742896,-2.75115 1.117096,-4.12597 1.752041,-6.46008 3.279791,-12.96668 4.787216,-19.4878 1.519228,-6.51781 3.16177,-12.83043 5.4375,-19.125 3.245102,-9.10722 4.514672,-18.63286 5.973633,-28.16113 0.401367,-2.21387 0.401367,-2.21387 1.401367,-5.21387 0.06725,-2.09304 -0.0012,-4.16495 -0.0625,-6.25781 0.05358,-2.35085 0.2595,-4.56839 0.542969,-6.89844 5.335996,-46.10945 -6.821894,-100.284491 -23.167969,-143.246091 -2.853907,-7.822763 -3.915598,-16.44719 -0.75,-24.347657 C -40.982968,8.9763575 -32.960334,3.2365619 -24.558594,-0.921875 -17.345835,-3.2139762 -7.0522415,-2.8528916 0,0 Z"
|
||||
fill="#000000"
|
||||
transform="translate(503.87891,195.77344)"
|
||||
id="path840"
|
||||
style="fill:#000000" /></g><g
|
||||
id="g915"
|
||||
transform="matrix(0.0396779,0,0,0.0396779,9.9752519,54.266907)"
|
||||
style="fill:#eaeaea"><path
|
||||
d="m 0,0 c 13.827391,10.512174 20.597576,25.087167 23.011719,42.019531 0.092,2.555446 0.13969,5.082998 0.134221,7.637738 l 0.0071,2.281383 c 0.0067,2.525082 0.0062,5.050113 0.0058,7.575203 0.0033,1.827887 0.007,3.655773 0.01114,5.483658 0.01001,5.025394 0.01373,10.050777 0.01639,15.07618 0.0039,5.419517 0.01348,10.839025 0.02221,16.258537 0.01976,13.09077 0.02983,26.18153 0.03873,39.27231 0.0044,6.16812 0.0098,12.33624 0.01499,18.50435 0.01701,20.51107 0.03151,41.02213 0.03875,61.5332 0.0019,5.32194 0.0038,10.64388 0.0058,15.96582 l 7.27e-4,2.0035 c 0.0081,22.08256 0.03335,44.16506 0.06685,66.24759 0.0331,21.9971 0.05109,43.99417 0.05428,65.9913 0.0022,12.3458 0.01087,24.69152 0.03646,37.0373 0.02175,10.51721 0.02974,21.03431 0.02003,31.55154 -0.0045,5.36121 -0.0027,10.72221 0.01676,16.08338 0.01772,4.91925 0.01656,9.83813 0.0011,14.75738 -0.0024,1.76864 0.0019,3.53731 0.01383,5.30591 0.125724,19.85325 -2.709399,39.30431 -17.0403675,54.18372 -8.3454088,7.618 -17.7819935,11.15977 -28.4648435,14.25 l -1.973145,0.59863 c -17.150657,5.19924 -32.361378,4.00814 -48.326172,-4.36035 -15.138528,-8.289 -26.891988,-20.43111 -38.102049,-33.39453 -2.15675,-2.48745 -4.37538,-4.91572 -6.59863,-7.34375 -4.96347,-5.44789 -9.84694,-10.95022 -14.60547,-16.57812 -5.99986,-7.07897 -12.15416,-13.96475 -18.51807,-20.719 -3.54755,-3.76661 -6.99861,-7.5918 -10.37255,-11.51538 -2.14552,-2.40744 -4.4475,-4.64229 -6.75,-6.89844 -1.86484,-1.90221 -3.58897,-3.88668 -5.31641,-5.91406 -6.32304,-7.26238 -12.25876,-13.79009 -22.02691,-15.0505 l -7.22359,-0.6152 c -5.81299,0.20929 -14.93041,0.48418 -24.04986,0.73028 -2.01512,0.057 -4.03,0.12239 -6.04486,0.18835 -13.91246,0.43355 -26.19483,0.60604 -39.09228,-5.12793 l -2.60938,-1.12891 c -6.35051,-3.14241 -11.37831,-7.93784 -16.39062,-12.87109 l -2.35156,-2.3125 c -15.53838,-16.23253 -18.11876,-33.32369 -18.02076,-54.89502 -0.002,-1.8939 -0.006,-3.7878 -0.0111,-5.6817 -0.009,-5.10319 -4e-5,-10.20618 0.0133,-15.30936 0.0114,-5.36218 0.007,-10.72435 0.005,-16.08654 -8.8e-4,-8.99923 0.0101,-17.99839 0.0286,-26.99759 0.0212,-10.3804 0.0247,-20.76069 0.0184,-31.1411 -0.006,-10.01985 -4e-5,-20.03965 0.0112,-30.05949 0.005,-4.24929 0.006,-8.49855 0.003,-12.74784 -0.002,-5.00865 0.006,-10.01718 0.0221,-15.02579 0.004,-1.83006 0.005,-3.66013 0.002,-5.49019 -0.0285,-21.95225 3.71639,-37.88244 18.36863,-54.6435 14.61244,-14.24783 34.5115,-17.73471 54.02344,-17.75 2.80276,-0.0161 5.60547,-0.0379 8.4082,-0.0586 4.39744,-0.0303 8.79459,-0.0531 13.19214,-0.0513 3.5746,8e-4 7.14834,-0.0228 10.72271,-0.0619 2.00158,-0.0154 4.0033,-0.005 6.00491,0.006 9.31056,-0.12346 16.20132,-1.82773 23.25798,-8.08783 l 1.98828,-2.41797 2.23828,-2.652343 2.07422,-2.535156 c 1.11952,-1.296419 2.2442,-2.58841 3.375,-3.875 l 1.69531,-1.945312 c 3.77047,-4.258956 7.63759,-8.430729 11.49024,-12.615235 2.31687,-2.51807 4.62792,-5.041473 6.93945,-7.564453 0.91795,-1.001322 1.83591,-2.002624 2.75391,-3.003906 1.82093,-1.986413 3.64119,-3.973438 5.46093,-5.960938 10.1791,-11.115607 20.40503,-22.186149 30.69922,-33.195312 2.41728,-2.585792 4.82817,-5.177336 7.23438,-7.773438 2.915852,-3.144847 5.845981,-6.275773 8.786614,-9.3974604 C -90.139631,8.18094 -88.740775,6.6596201 -87.34375,5.1367187 -62.778713,-20.817295 -28.205909,-18.693328 0,0 Z m -48.244141,66.221924 -1.58789,1.692138 -1.763672,1.878907 -1.892578,2.039062 -1.939453,2.082031 c -4.247651,4.594835 -8.242647,9.327988 -12.146485,14.21875 -4.188864,5.009015 -8.7178,9.703144 -13.195312,14.453128 -2.882159,3.06065 -5.664738,6.19141 -8.410156,9.375 -3.385406,3.85336 -6.886651,7.60175 -10.376465,11.36035 -2.186548,2.35516 -4.370308,4.71285 -6.551998,7.07251 -8.21016,8.85958 -16.55506,17.57623 -25.05884,26.15454 -1.39336,1.41011 -2.78131,2.82559 -4.16406,4.24609 -2.04543,2.10046 -4.10708,4.18374 -6.17286,6.26416 l -1.8316,1.9003 c -24.02936,23.91421 -66.00557,10.69802 -94.65277,11.06064 v 168 l 58,1 c 30.35546,3.79443 30.35546,3.79443 43.37891,17.01563 l 1.98899,1.98748 c 1.37569,1.37802 2.74774,2.75968 4.11623,4.14484 2.06819,2.09176 4.14935,4.1699 6.23267,6.24658 6.87552,6.89041 13.43025,13.80534 19.2832,21.60547 5.573935,6.98354 11.3661,13.67388 17.437499,20.22266 2.661163,2.88428 5.24949,5.82071 7.820312,8.78515 2.821044,3.22586 5.703196,6.39642 8.578125,9.57422 1.798374,2.00938 3.547726,4.04712 5.289063,6.10547 3.727868,4.28705 7.742389,8.28942 11.75,12.3125 l 2.059082,2.073 1.933105,1.927 1.753418,1.75 c 1.192644,1.36192 1.192644,1.36192 2.379395,1.25 V 65.019531 c -1.169391,-0.11526 -1.169391,-0.11526 -2.25586,1.202393 z"
|
||||
fill="#000000"
|
||||
transform="translate(370.98828,94.980469)"
|
||||
id="path909"
|
||||
sodipodi:nodetypes="ccccccccccsssccsccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
||||
style="fill:#eaeaea" /><path
|
||||
d="m 0,0 c 12.687715,8.3646425 16.54757,23.578013 21.25,37.25 0.420028,1.211683 0.420028,1.211683 0.848541,2.447845 C 24.093738,45.455849 26.057576,51.223992 28,57 c 0.358289,1.064594 0.358289,1.064594 0.723816,2.150696 9.196303,27.421957 18.34758,56.379674 22.213684,85.099304 0.165,1.21301 0.33,2.42602 0.5,3.67578 0.133418,0.98348 0.133418,0.98348 0.269531,1.98682 0.307725,2.19254 0.641643,4.37993 0.980469,6.56787 C 65.117247,237.74117 51.79423,319.60536 24,408 c -0.37689,1.17031 -0.753779,2.34062 -1.14209,3.54639 C 17.545759,427.78218 11.971055,440.11885 -3.1601563,449.3125 -10.974406,453.17271 -20.495807,453.32002 -29,452 c -6.447118,-2.21023 -11.581457,-5.80171 -16,-11 -0.659355,-0.72703 -0.659355,-0.72703 -1.332031,-1.46875 C -53.332437,431.62301 -53,422.82358 -53,412.69922 c 0.741111,-10.03973 4.593387,-18.57148 8.476563,-27.75293 C -4.1662297,289.1502 -7.3944601,181.67277 -47.370117,59.287109 -52.165555,46.157988 -56.413045,31.232358 -51.4375,17.4375 -46.91216,8.1345364 -38.697322,0.74480411 -29.140625,-3.171875 -19.460116,-5.7244469 -8.7875393,-4.8407102 0,0 Z"
|
||||
fill="#000000"
|
||||
transform="translate(634,136)"
|
||||
id="path911"
|
||||
style="fill:#eaeaea" /><path
|
||||
d="m 0,0 c 17.968337,10.39053 22.143536,33.207156 27.238281,51.816406 9.06097,33.99317 13.985108,69.235084 14.882813,104.410154 0.02191,0.81179 0.04383,1.62358 0.06641,2.45996 1.024973,44.84255 -6.637484,88.87597 -20.066406,131.54004 -0.326455,1.04898 -0.65291,2.09795 -0.989258,3.17871 -1.007854,3.21683 -2.036103,6.4263 -3.073242,9.63379 -0.304138,0.96027 -0.608277,1.92054 -0.921631,2.90991 -3.75203,11.33325 -8.7198824,22.01013 -19.3283693,28.21509 -8.8558147,2.55168 -16.4996667,1.12221 -24.6874997,-2.9375 -8.148586,-4.91088 -14.567027,-10.35992 -18.375,-19.1875 -1.817982,-11.08969 -0.01228,-20.87108 3,-31.5625 0.556674,-2.04436 1.107614,-4.09021 1.658188,-6.13623 0.370535,-1.37582 0.742896,-2.75115 1.117096,-4.12597 1.752041,-6.46008 3.279791,-12.96668 4.787216,-19.4878 1.519228,-6.51781 3.16177,-12.83043 5.4375,-19.125 3.245102,-9.10722 4.514672,-18.63286 5.973633,-28.16113 0.401367,-2.21387 0.401367,-2.21387 1.401367,-5.21387 0.06725,-2.09304 -0.0012,-4.16495 -0.0625,-6.25781 0.05358,-2.35085 0.2595,-4.56839 0.542969,-6.89844 5.335996,-46.10945 -6.821894,-100.284491 -23.167969,-143.246091 -2.853907,-7.822763 -3.915598,-16.44719 -0.75,-24.347657 C -40.982968,8.9763575 -32.960334,3.2365619 -24.558594,-0.921875 -17.345835,-3.2139762 -7.0522415,-2.8528916 0,0 Z"
|
||||
fill="#000000"
|
||||
transform="translate(503.87891,195.77344)"
|
||||
id="path913"
|
||||
style="fill:#eaeaea" /></g><g
|
||||
id="g923"
|
||||
transform="matrix(0.0396779,0,0,0.0396779,9.9752519,104.26691)"
|
||||
style="fill:#eaeaea;fill-opacity:0.72156864;opacity:0.47"><path
|
||||
d="m 0,0 c 13.827391,10.512174 20.597576,25.087167 23.011719,42.019531 0.092,2.555446 0.13969,5.082998 0.134221,7.637738 l 0.0071,2.281383 c 0.0067,2.525082 0.0062,5.050113 0.0058,7.575203 0.0033,1.827887 0.007,3.655773 0.01114,5.483658 0.01001,5.025394 0.01373,10.050777 0.01639,15.07618 0.0039,5.419517 0.01348,10.839025 0.02221,16.258537 0.01976,13.09077 0.02983,26.18153 0.03873,39.27231 0.0044,6.16812 0.0098,12.33624 0.01499,18.50435 0.01701,20.51107 0.03151,41.02213 0.03875,61.5332 0.0019,5.32194 0.0038,10.64388 0.0058,15.96582 l 7.27e-4,2.0035 c 0.0081,22.08256 0.03335,44.16506 0.06685,66.24759 0.0331,21.9971 0.05109,43.99417 0.05428,65.9913 0.0022,12.3458 0.01087,24.69152 0.03646,37.0373 0.02175,10.51721 0.02974,21.03431 0.02003,31.55154 -0.0045,5.36121 -0.0027,10.72221 0.01676,16.08338 0.01772,4.91925 0.01656,9.83813 0.0011,14.75738 -0.0024,1.76864 0.0019,3.53731 0.01383,5.30591 0.125724,19.85325 -2.709399,39.30431 -17.0403675,54.18372 -8.3454088,7.618 -17.7819935,11.15977 -28.4648435,14.25 l -1.973145,0.59863 c -17.150657,5.19924 -32.361378,4.00814 -48.326172,-4.36035 -15.138528,-8.289 -26.891988,-20.43111 -38.102049,-33.39453 -2.15675,-2.48745 -4.37538,-4.91572 -6.59863,-7.34375 -4.96347,-5.44789 -9.84694,-10.95022 -14.60547,-16.57812 -5.99986,-7.07897 -12.15416,-13.96475 -18.51807,-20.719 -3.54755,-3.76661 -6.99861,-7.5918 -10.37255,-11.51538 -2.14552,-2.40744 -4.4475,-4.64229 -6.75,-6.89844 -1.86484,-1.90221 -3.58897,-3.88668 -5.31641,-5.91406 -6.32304,-7.26238 -12.25876,-13.79009 -22.02691,-15.0505 l -7.22359,-0.6152 c -5.81299,0.20929 -14.93041,0.48418 -24.04986,0.73028 -2.01512,0.057 -4.03,0.12239 -6.04486,0.18835 -13.91246,0.43355 -26.19483,0.60604 -39.09228,-5.12793 l -2.60938,-1.12891 c -6.35051,-3.14241 -11.37831,-7.93784 -16.39062,-12.87109 l -2.35156,-2.3125 c -15.53838,-16.23253 -18.11876,-33.32369 -18.02076,-54.89502 -0.002,-1.8939 -0.006,-3.7878 -0.0111,-5.6817 -0.009,-5.10319 -4e-5,-10.20618 0.0133,-15.30936 0.0114,-5.36218 0.007,-10.72435 0.005,-16.08654 -8.8e-4,-8.99923 0.0101,-17.99839 0.0286,-26.99759 0.0212,-10.3804 0.0247,-20.76069 0.0184,-31.1411 -0.006,-10.01985 -4e-5,-20.03965 0.0112,-30.05949 0.005,-4.24929 0.006,-8.49855 0.003,-12.74784 -0.002,-5.00865 0.006,-10.01718 0.0221,-15.02579 0.004,-1.83006 0.005,-3.66013 0.002,-5.49019 -0.0285,-21.95225 3.71639,-37.88244 18.36863,-54.6435 14.61244,-14.24783 34.5115,-17.73471 54.02344,-17.75 2.80276,-0.0161 5.60547,-0.0379 8.4082,-0.0586 4.39744,-0.0303 8.79459,-0.0531 13.19214,-0.0513 3.5746,8e-4 7.14834,-0.0228 10.72271,-0.0619 2.00158,-0.0154 4.0033,-0.005 6.00491,0.006 9.31056,-0.12346 16.20132,-1.82773 23.25798,-8.08783 l 1.98828,-2.41797 2.23828,-2.652343 2.07422,-2.535156 c 1.11952,-1.296419 2.2442,-2.58841 3.375,-3.875 l 1.69531,-1.945312 c 3.77047,-4.258956 7.63759,-8.430729 11.49024,-12.615235 2.31687,-2.51807 4.62792,-5.041473 6.93945,-7.564453 0.91795,-1.001322 1.83591,-2.002624 2.75391,-3.003906 1.82093,-1.986413 3.64119,-3.973438 5.46093,-5.960938 10.1791,-11.115607 20.40503,-22.186149 30.69922,-33.195312 2.41728,-2.585792 4.82817,-5.177336 7.23438,-7.773438 2.915852,-3.144847 5.845981,-6.275773 8.786614,-9.3974604 C -90.139631,8.18094 -88.740775,6.6596201 -87.34375,5.1367187 -62.778713,-20.817295 -28.205909,-18.693328 0,0 Z m -48.244141,66.221924 -1.58789,1.692138 -1.763672,1.878907 -1.892578,2.039062 -1.939453,2.082031 c -4.247651,4.594835 -8.242647,9.327988 -12.146485,14.21875 -4.188864,5.009015 -8.7178,9.703144 -13.195312,14.453128 -2.882159,3.06065 -5.664738,6.19141 -8.410156,9.375 -3.385406,3.85336 -6.886651,7.60175 -10.376465,11.36035 -2.186548,2.35516 -4.370308,4.71285 -6.551998,7.07251 -8.21016,8.85958 -16.55506,17.57623 -25.05884,26.15454 -1.39336,1.41011 -2.78131,2.82559 -4.16406,4.24609 -2.04543,2.10046 -4.10708,4.18374 -6.17286,6.26416 l -1.8316,1.9003 c -24.02936,23.91421 -66.00557,10.69802 -94.65277,11.06064 v 168 l 58,1 c 30.35546,3.79443 30.35546,3.79443 43.37891,17.01563 l 1.98899,1.98748 c 1.37569,1.37802 2.74774,2.75968 4.11623,4.14484 2.06819,2.09176 4.14935,4.1699 6.23267,6.24658 6.87552,6.89041 13.43025,13.80534 19.2832,21.60547 5.573935,6.98354 11.3661,13.67388 17.437499,20.22266 2.661163,2.88428 5.24949,5.82071 7.820312,8.78515 2.821044,3.22586 5.703196,6.39642 8.578125,9.57422 1.798374,2.00938 3.547726,4.04712 5.289063,6.10547 3.727868,4.28705 7.742389,8.28942 11.75,12.3125 l 2.059082,2.073 1.933105,1.927 1.753418,1.75 c 1.192644,1.36192 1.192644,1.36192 2.379395,1.25 V 65.019531 c -1.169391,-0.11526 -1.169391,-0.11526 -2.25586,1.202393 z"
|
||||
fill="#000000"
|
||||
transform="translate(370.98828,94.980469)"
|
||||
id="path917"
|
||||
sodipodi:nodetypes="ccccccccccsssccsccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
||||
style="fill:#eaeaea;fill-opacity:0.72156864" /><path
|
||||
d="m 0,0 c 12.687715,8.3646425 16.54757,23.578013 21.25,37.25 0.420028,1.211683 0.420028,1.211683 0.848541,2.447845 C 24.093738,45.455849 26.057576,51.223992 28,57 c 0.358289,1.064594 0.358289,1.064594 0.723816,2.150696 9.196303,27.421957 18.34758,56.379674 22.213684,85.099304 0.165,1.21301 0.33,2.42602 0.5,3.67578 0.133418,0.98348 0.133418,0.98348 0.269531,1.98682 0.307725,2.19254 0.641643,4.37993 0.980469,6.56787 C 65.117247,237.74117 51.79423,319.60536 24,408 c -0.37689,1.17031 -0.753779,2.34062 -1.14209,3.54639 C 17.545759,427.78218 11.971055,440.11885 -3.1601563,449.3125 -10.974406,453.17271 -20.495807,453.32002 -29,452 c -6.447118,-2.21023 -11.581457,-5.80171 -16,-11 -0.659355,-0.72703 -0.659355,-0.72703 -1.332031,-1.46875 C -53.332437,431.62301 -53,422.82358 -53,412.69922 c 0.741111,-10.03973 4.593387,-18.57148 8.476563,-27.75293 C -4.1662297,289.1502 -7.3944601,181.67277 -47.370117,59.287109 -52.165555,46.157988 -56.413045,31.232358 -51.4375,17.4375 -46.91216,8.1345364 -38.697322,0.74480411 -29.140625,-3.171875 -19.460116,-5.7244469 -8.7875393,-4.8407102 0,0 Z"
|
||||
fill="#000000"
|
||||
transform="translate(634,136)"
|
||||
id="path919"
|
||||
style="fill:#eaeaea;fill-opacity:0.72156864" /><path
|
||||
d="m 0,0 c 17.968337,10.39053 22.143536,33.207156 27.238281,51.816406 9.06097,33.99317 13.985108,69.235084 14.882813,104.410154 0.02191,0.81179 0.04383,1.62358 0.06641,2.45996 1.024973,44.84255 -6.637484,88.87597 -20.066406,131.54004 -0.326455,1.04898 -0.65291,2.09795 -0.989258,3.17871 -1.007854,3.21683 -2.036103,6.4263 -3.073242,9.63379 -0.304138,0.96027 -0.608277,1.92054 -0.921631,2.90991 -3.75203,11.33325 -8.7198824,22.01013 -19.3283693,28.21509 -8.8558147,2.55168 -16.4996667,1.12221 -24.6874997,-2.9375 -8.148586,-4.91088 -14.567027,-10.35992 -18.375,-19.1875 -1.817982,-11.08969 -0.01228,-20.87108 3,-31.5625 0.556674,-2.04436 1.107614,-4.09021 1.658188,-6.13623 0.370535,-1.37582 0.742896,-2.75115 1.117096,-4.12597 1.752041,-6.46008 3.279791,-12.96668 4.787216,-19.4878 1.519228,-6.51781 3.16177,-12.83043 5.4375,-19.125 3.245102,-9.10722 4.514672,-18.63286 5.973633,-28.16113 0.401367,-2.21387 0.401367,-2.21387 1.401367,-5.21387 0.06725,-2.09304 -0.0012,-4.16495 -0.0625,-6.25781 0.05358,-2.35085 0.2595,-4.56839 0.542969,-6.89844 5.335996,-46.10945 -6.821894,-100.284491 -23.167969,-143.246091 -2.853907,-7.822763 -3.915598,-16.44719 -0.75,-24.347657 C -40.982968,8.9763575 -32.960334,3.2365619 -24.558594,-0.921875 -17.345835,-3.2139762 -7.0522415,-2.8528916 0,0 Z"
|
||||
fill="#000000"
|
||||
transform="translate(503.87891,195.77344)"
|
||||
id="path921"
|
||||
style="fill:#eaeaea;fill-opacity:0.72156864" /></g><g
|
||||
aria-label="SOUND"
|
||||
transform="scale(0.98488846,1.0153434)"
|
||||
id="text1834"
|
||||
style="font-weight:bold;font-size:8.76147px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Bold';stroke-width:0.219039"><path
|
||||
d="m 9.2156273,39.429309 1.2320817,-0.119786 q 0.11123,0.620319 0.449196,0.911227 0.342245,0.290908 0.919784,0.290908 0.611762,0 0.919783,-0.256683 0.312298,-0.260962 0.312298,-0.607485 0,-0.222459 -0.13262,-0.37647 -0.128341,-0.158288 -0.453474,-0.273796 -0.222459,-0.077 -1.013901,-0.273795 -1.018178,-0.252406 -1.428872,-0.620319 -0.5775385,-0.517646 -0.5775385,-1.262028 0,-0.479143 0.2695179,-0.894115 0.2737959,-0.41925 0.7828856,-0.637431 0.513367,-0.218182 1.236359,-0.218182 1.180745,0 1.775396,0.517646 0.598928,0.517645 0.628875,1.381814 l -1.266306,0.05561 q -0.08128,-0.48342 -0.350801,-0.693045 -0.26524,-0.213904 -0.799998,-0.213904 -0.55187,0 -0.864168,0.226738 -0.201069,0.145454 -0.201069,0.389303 0,0.222459 0.188235,0.380748 0.239571,0.201069 1.163632,0.41925 0.924062,0.218181 1.364702,0.453474 0.444918,0.231016 0.693046,0.637431 0.252406,0.402138 0.252406,0.996789 0,0.539036 -0.299465,1.009622 -0.299464,0.470587 -0.847056,0.701602 -0.547592,0.226738 -1.364702,0.226738 -1.189301,0 -1.8267318,-0.547592 -0.6374312,-0.55187 -0.7614949,-1.604273 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path4316" /><path
|
||||
d="m 15.12363,38.372628 q 0,-0.958286 0.28663,-1.608552 0.213903,-0.479142 0.581817,-0.85989 0.372191,-0.380747 0.812831,-0.564704 0.586095,-0.248128 1.351868,-0.248128 1.386092,0 2.216036,0.859891 0.834222,0.85989 0.834222,2.391436 0,1.518712 -0.825666,2.378602 -0.825666,0.855613 -2.20748,0.855613 -1.398926,0 -2.224592,-0.851335 -0.825666,-0.855612 -0.825666,-2.352933 z m 1.304809,-0.04278 q 0,1.065237 0.491977,1.617107 0.491977,0.547592 1.249194,0.547592 0.757217,0 1.240638,-0.543314 0.487699,-0.547592 0.487699,-1.638497 0,-1.078072 -0.474865,-1.608551 -0.470587,-0.53048 -1.253472,-0.53048 -0.782885,0 -1.262028,0.539036 -0.479143,0.534757 -0.479143,1.617107 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path4318" /><path
|
||||
d="m 22.18671,35.198306 h 1.266306 v 3.396781 q 0,0.808553 0.04706,1.048125 0.08128,0.385025 0.385025,0.620319 0.30802,0.231015 0.8385,0.231015 0.539036,0 0.812832,-0.218181 0.273796,-0.222459 0.329411,-0.543314 0.05561,-0.320855 0.05561,-1.065237 v -3.469508 h 1.266306 v 3.294107 q 0,1.129408 -0.102673,1.595717 -0.102673,0.466309 -0.380747,0.787163 -0.273796,0.320855 -0.735827,0.513368 -0.462031,0.188235 -1.206413,0.188235 -0.898393,0 -1.364702,-0.205347 Q 22.93537,41.161924 22.665853,40.832513 22.396335,40.498824 22.310773,40.135189 22.18671,39.596153 22.18671,38.54375 Z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path4320" /><path
|
||||
d="m 28.535352,41.469944 v -6.271638 h 1.232082 l 2.566837,4.188222 v -4.188222 h 1.176467 v 6.271638 h -1.270584 l -2.528335,-4.089827 v 4.089827 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path4322" /><path
|
||||
d="m 34.845493,35.198306 h 2.314432 q 0.782885,0 1.193579,0.119786 0.55187,0.162566 0.945451,0.577538 0.393582,0.414972 0.598929,1.018179 0.205347,0.598928 0.205347,1.480209 0,0.774329 -0.192513,1.334755 -0.235293,0.68449 -0.671655,1.108018 -0.329411,0.320855 -0.889837,0.500533 -0.41925,0.13262 -1.120852,0.13262 h -2.382881 z m 1.266307,1.060959 v 4.153998 h 0.945451 q 0.53048,0 0.765773,-0.05989 0.308021,-0.077 0.50909,-0.260962 0.205346,-0.183956 0.333688,-0.603206 0.128342,-0.423529 0.128342,-1.150799 0,-0.72727 -0.128342,-1.116574 -0.128342,-0.389304 -0.359357,-0.607485 -0.231015,-0.218181 -0.586094,-0.295186 -0.26524,-0.05989 -1.039569,-0.05989 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path4324" /></g><g
|
||||
aria-label="SOUND"
|
||||
transform="scale(0.98488846,1.0153434)"
|
||||
id="text4644"
|
||||
style="font-weight:bold;font-size:8.76147px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Bold';fill:#eaeaea;stroke-width:0.219039"><path
|
||||
d="M 9.2156273,88.673766 10.447709,88.55398 q 0.11123,0.620319 0.449196,0.911227 0.342245,0.290908 0.919784,0.290908 0.611762,0 0.919783,-0.256683 0.312298,-0.260962 0.312298,-0.607485 0,-0.222459 -0.13262,-0.376469 -0.128341,-0.158289 -0.453474,-0.273796 -0.222459,-0.077 -1.013901,-0.273796 -1.018178,-0.252406 -1.428872,-0.620319 -0.5775385,-0.517646 -0.5775385,-1.262028 0,-0.479143 0.2695179,-0.894115 0.2737959,-0.41925 0.7828856,-0.637431 0.513367,-0.218181 1.236359,-0.218181 1.180745,0 1.775396,0.517645 0.598928,0.517645 0.628875,1.381814 l -1.266306,0.05562 q -0.08128,-0.483421 -0.350801,-0.693046 -0.26524,-0.213903 -0.799998,-0.213903 -0.55187,0 -0.864168,0.226737 -0.201069,0.145454 -0.201069,0.389304 0,0.222459 0.188235,0.380747 0.239571,0.201069 1.163632,0.41925 0.924062,0.218181 1.364702,0.453475 0.444918,0.231015 0.693046,0.637431 0.252406,0.402137 0.252406,0.996788 0,0.539036 -0.299465,1.009623 -0.299464,0.470586 -0.847056,0.701602 -0.547592,0.226737 -1.364702,0.226737 -1.189301,0 -1.8267318,-0.547592 -0.6374312,-0.55187 -0.7614949,-1.604273 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path4646" /><path
|
||||
d="m 15.12363,87.617085 q 0,-0.958286 0.28663,-1.608551 0.213903,-0.479143 0.581817,-0.859891 0.372191,-0.380747 0.812831,-0.564704 0.586095,-0.248127 1.351868,-0.248127 1.386092,0 2.216036,0.85989 0.834222,0.85989 0.834222,2.391436 0,1.518712 -0.825666,2.378602 -0.825666,0.855613 -2.20748,0.855613 -1.398926,0 -2.224592,-0.851334 -0.825666,-0.855613 -0.825666,-2.352934 z m 1.304809,-0.04278 q 0,1.065237 0.491977,1.617107 0.491977,0.547592 1.249194,0.547592 0.757217,0 1.240638,-0.543314 0.487699,-0.547591 0.487699,-1.638497 0,-1.078072 -0.474865,-1.608551 -0.470587,-0.53048 -1.253472,-0.53048 -0.782885,0 -1.262028,0.539036 -0.479143,0.534758 -0.479143,1.617107 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path4648" /><path
|
||||
d="m 22.18671,84.442763 h 1.266306 v 3.396781 q 0,0.808554 0.04706,1.048125 0.08128,0.385026 0.385025,0.620319 0.30802,0.231015 0.8385,0.231015 0.539036,0 0.812832,-0.218181 0.273796,-0.222459 0.329411,-0.543314 0.05561,-0.320854 0.05561,-1.065237 v -3.469508 h 1.266306 v 3.294107 q 0,1.129409 -0.102673,1.595717 -0.102673,0.466309 -0.380747,0.787164 -0.273796,0.320854 -0.735827,0.513367 -0.462031,0.188235 -1.206413,0.188235 -0.898393,0 -1.364702,-0.205347 Q 22.93537,90.406381 22.665853,90.07697 22.396335,89.743281 22.310773,89.379646 22.18671,88.84061 22.18671,87.788207 Z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path4650" /><path
|
||||
d="m 28.535352,90.714401 v -6.271638 h 1.232082 l 2.566837,4.188222 v -4.188222 h 1.176467 v 6.271638 h -1.270584 l -2.528335,-4.089826 v 4.089826 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path4652" /><path
|
||||
d="m 34.845493,84.442763 h 2.314432 q 0.782885,0 1.193579,0.119786 0.55187,0.162566 0.945451,0.577538 0.393582,0.414972 0.598929,1.018179 0.205347,0.598928 0.205347,1.480209 0,0.774329 -0.192513,1.334755 -0.235293,0.68449 -0.671655,1.108018 -0.329411,0.320855 -0.889837,0.500533 -0.41925,0.13262 -1.120852,0.13262 h -2.382881 z m 1.266307,1.060959 v 4.153998 h 0.945451 q 0.53048,0 0.765773,-0.05989 0.308021,-0.077 0.50909,-0.260962 0.205346,-0.183956 0.333688,-0.603206 0.128342,-0.423528 0.128342,-1.150799 0,-0.72727 -0.128342,-1.116574 -0.128342,-0.389303 -0.359357,-0.607484 -0.231015,-0.218182 -0.586094,-0.295187 -0.26524,-0.05989 -1.039569,-0.05989 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path4654" /></g><g
|
||||
aria-label="SOUND"
|
||||
transform="scale(0.98488846,1.0153434)"
|
||||
id="text4974"
|
||||
style="font-weight:bold;font-size:8.76147px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Bold';opacity:0.47;fill:#eaeaea;stroke-width:0.219039"><path
|
||||
d="m 9.2156273,137.91821 1.2320817,-0.11978 q 0.11123,0.62031 0.449196,0.91122 0.342245,0.29091 0.919784,0.29091 0.611762,0 0.919783,-0.25668 0.312298,-0.26096 0.312298,-0.60749 0,-0.22246 -0.13262,-0.37647 -0.128341,-0.15828 -0.453474,-0.27379 -0.222459,-0.077 -1.013901,-0.2738 -1.018178,-0.2524 -1.428872,-0.62032 -0.5775385,-0.51764 -0.5775385,-1.26203 0,-0.47914 0.2695179,-0.89411 0.2737959,-0.41925 0.7828856,-0.63743 0.513367,-0.21818 1.236359,-0.21818 1.180745,0 1.775396,0.51764 0.598928,0.51765 0.628875,1.38182 l -1.266306,0.0556 q -0.08128,-0.48342 -0.350801,-0.69304 -0.26524,-0.21391 -0.799998,-0.21391 -0.55187,0 -0.864168,0.22674 -0.201069,0.14545 -0.201069,0.3893 0,0.22246 0.188235,0.38075 0.239571,0.20107 1.163632,0.41925 0.924062,0.21818 1.364702,0.45348 0.444918,0.23101 0.693046,0.63743 0.252406,0.40213 0.252406,0.99678 0,0.53904 -0.299465,1.00963 -0.299464,0.47058 -0.847056,0.7016 -0.547592,0.22674 -1.364702,0.22674 -1.189301,0 -1.8267318,-0.5476 -0.6374312,-0.55187 -0.7614949,-1.60427 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path5056" /><path
|
||||
d="m 15.12363,136.86153 q 0,-0.95829 0.28663,-1.60855 0.213903,-0.47914 0.581817,-0.85989 0.372191,-0.38075 0.812831,-0.56471 0.586095,-0.24812 1.351868,-0.24812 1.386092,0 2.216036,0.85989 0.834222,0.85989 0.834222,2.39143 0,1.51872 -0.825666,2.37861 -0.825666,0.85561 -2.20748,0.85561 -1.398926,0 -2.224592,-0.85134 -0.825666,-0.85561 -0.825666,-2.35293 z m 1.304809,-0.0428 q 0,1.06524 0.491977,1.61711 0.491977,0.54759 1.249194,0.54759 0.757217,0 1.240638,-0.54331 0.487699,-0.5476 0.487699,-1.6385 0,-1.07807 -0.474865,-1.60855 -0.470587,-0.53048 -1.253472,-0.53048 -0.782885,0 -1.262028,0.53903 -0.479143,0.53476 -0.479143,1.61711 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path5058" /><path
|
||||
d="m 22.18671,133.68721 h 1.266306 v 3.39678 q 0,0.80855 0.04706,1.04812 0.08128,0.38503 0.385025,0.62032 0.30802,0.23102 0.8385,0.23102 0.539036,0 0.812832,-0.21818 0.273796,-0.22246 0.329411,-0.54332 0.05561,-0.32085 0.05561,-1.06523 v -3.46951 h 1.266306 v 3.29411 q 0,1.1294 -0.102673,1.59571 -0.102673,0.46631 -0.380747,0.78717 -0.273796,0.32085 -0.735827,0.51336 -0.462031,0.18824 -1.206413,0.18824 -0.898393,0 -1.364702,-0.20535 -0.462031,-0.20962 -0.731548,-0.53903 -0.269518,-0.33369 -0.35508,-0.69733 -0.124063,-0.53903 -0.124063,-1.59144 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path5060" /><path
|
||||
d="m 28.535352,139.95885 v -6.27164 h 1.232082 l 2.566837,4.18822 v -4.18822 h 1.176467 v 6.27164 h -1.270584 l -2.528335,-4.08983 v 4.08983 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path5062" /><path
|
||||
d="m 34.845493,133.68721 h 2.314432 q 0.782885,0 1.193579,0.11978 0.55187,0.16257 0.945451,0.57754 0.393582,0.41497 0.598929,1.01818 0.205347,0.59893 0.205347,1.48021 0,0.77433 -0.192513,1.33476 -0.235293,0.68449 -0.671655,1.10801 -0.329411,0.32086 -0.889837,0.50054 -0.41925,0.13262 -1.120852,0.13262 h -2.382881 z m 1.266307,1.06096 v 4.154 h 0.945451 q 0.53048,0 0.765773,-0.0599 0.308021,-0.077 0.50909,-0.26096 0.205346,-0.18396 0.333688,-0.60321 0.128342,-0.42352 0.128342,-1.15079 0,-0.72727 -0.128342,-1.11658 -0.128342,-0.3893 -0.359357,-0.60748 -0.231015,-0.21818 -0.586094,-0.29519 -0.26524,-0.0599 -1.039569,-0.0599 z"
|
||||
style="font-family:Arial;-inkscape-font-specification:'Arial Bold'"
|
||||
id="path5064" /></g></svg>
|
After Width: | Height: | Size: 38 KiB |
|
@ -776,5 +776,29 @@
|
|||
},
|
||||
"particleRenderData": {
|
||||
"tooltip": "A JSON description of the shaders, textures, and uniforms to use during particle rendering."
|
||||
},
|
||||
"soundURL": {
|
||||
"tooltip": "The URL of the sound, as a wav, mp3, or raw file."
|
||||
},
|
||||
"playing": {
|
||||
"tooltip": "Whether or not the sound should play."
|
||||
},
|
||||
"volume": {
|
||||
"tooltip": "The volume of the sound."
|
||||
},
|
||||
"pitch": {
|
||||
"tooltip": "Alter the pitch of the sound, within +/- 2 octaves. The value is the relative sample rate at which to resample the sound."
|
||||
},
|
||||
"timeOffset": {
|
||||
"tooltip": "Starts playback from a specified time (seconds) within the sound file."
|
||||
},
|
||||
"loop": {
|
||||
"tooltip": "Whether or not the sound is played repeatedly."
|
||||
},
|
||||
"positional": {
|
||||
"tooltip": "Whether or not the sound volume drops off with distance."
|
||||
},
|
||||
"localOnly": {
|
||||
"tooltip": "Whether the sound should play locally for everyone separately, or globally via the audio mixer."
|
||||
}
|
||||
}
|
84
scripts/system/create/assets/images/icon-sound.svg
Normal file
84
scripts/system/create/assets/images/icon-sound.svg
Normal file
|
@ -0,0 +1,84 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
style="enable-background:new 0 0 512 512;"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
|
||||
sodipodi:docname="icon-sound.svg"
|
||||
width="512"
|
||||
height="512"
|
||||
id="svg43"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"><path
|
||||
d="m 355.34986,175.4077 c 11.3402,35.12172 13.21764,60.54899 13.96962,84.2159 0.0185,0.54619 0.0366,1.09241 0.0556,1.65515 0.85863,30.17151 -6.91623,62.84542 -12.64806,79.48246 -5.37828,17.78609 -5.88608,19.15003 -8.27799,25.02071 -4.24807,5.95906 -6.3021,8.15146 -12.9789,11.35411 -8.34639,1.45167 -15.67758,0.71082 -22.05025,-3.52324 -8.15172,-6.3978 -8.84375,-9.04763 -10.92875,-14.05903 -0.90418,-3.7934 -1.07115,-11.52366 1.18721,-19.68948 0.46632,-1.3755 2.43042,-8.67403 4.30468,-15.84048 1.96264,-7.69678 0.60592,0.34 7.74308,-36.57707 3.88716,-38.91707 -2.86528,-64.22135 -13.80806,-100.3773 -2.39066,-5.26342 -2.92645,-16.01596 -0.27471,-21.33166 3.63003,-5.71921 8.33266,-10.24533 15.37064,-13.04327 6.04199,-1.54219 17.99394,-3.87722 25.03914,3.2229 5.1707,4.72562 9.02898,6.96941 13.29675,19.4903 z"
|
||||
fill="#000000"
|
||||
id="path840"
|
||||
style="fill:#ffffff;stroke-width:0.750744"
|
||||
sodipodi:nodetypes="cccccccccccccccc" /><path
|
||||
d="m 421.02222,112.77065 c 9.70029,5.57712 11.50234,12.47065 14.45085,20.20168 2.94851,7.73103 4.83293,13.32692 10.45277,28.6113 5.87516,17.65937 8.02051,22.84194 12.25292,46.36576 0.12615,0.80878 0.2523,1.61755 0.38227,2.45083 0.10203,0.65574 0.10203,0.65574 0.20607,1.32471 0.23526,1.46188 0.49055,2.92032 0.74962,4.37913 8.99239,56.55562 -2.63794,116.26296 -15.73012,155.57643 -11.68789,36.31347 -14.14458,35.01445 -25.71301,41.14432 -5.9743,2.57381 -12.70311,2.25781 -19.20491,1.37769 -4.9291,-1.47367 -7.59602,-3.17895 -11.99548,-6.89491 -2.67801,-2.60429 -4.58932,-5.48475 -5.10361,-5.97929 -2.41586,-4.02283 -3.43831,-8.88986 -3.43831,-15.64027 0.5666,-6.694 1.00614,-13.25387 3.97498,-19.3756 29.57811,-63.74709 27.06244,-132.91138 0.58461,-210.63708 -3.66631,-8.75385 -5.25408,-22.08052 -1.45006,-31.27825 3.45981,-6.20275 8.84676,-11.00486 16.15324,-13.6163 7.40115,-1.70194 16.70974,-1.2377 23.42817,1.98985 z"
|
||||
fill="#000000"
|
||||
id="path838"
|
||||
style="fill:#ffffff;stroke-width:0.713973"
|
||||
sodipodi:nodetypes="cccccccccccccccccc" /><path
|
||||
d="m 336.29005,157.3505 c 11.50891,6.65525 14.18316,21.26954 17.4464,33.18895 5.80365,21.77299 8.95761,44.34581 9.53259,66.8758 0.0141,0.51996 0.028,1.03993 0.0425,1.57564 0.65652,28.72212 -4.25137,56.92599 -12.85273,84.25278 -0.20911,0.67188 -0.4182,1.34376 -0.63364,2.03599 -0.64553,2.06042 -1.30414,4.11612 -1.96844,6.17055 -0.1948,0.61507 -0.38961,1.23013 -0.59031,1.86383 -2.40322,7.25906 -5.58519,14.09771 -12.38003,18.07206 -5.67224,1.63437 -10.56821,0.71879 -15.81261,-1.8815 -5.21925,-3.14547 -9.33032,-6.63564 -11.76937,-12.28979 -1.16444,-7.10307 -0.008,-13.36815 1.92152,-20.21612 0.35656,-1.30943 0.70944,-2.61982 1.0621,-3.93032 0.23733,-0.88123 0.47582,-1.76214 0.71551,-2.64273 1.1222,-4.13775 2.10073,-8.3053 3.06626,-12.48214 0.97308,-4.17472 2.02514,-8.21802 3.48278,-12.24977 2.07851,-5.83326 2.89169,-11.93453 3.82617,-18.0375 0.25708,-1.418 0.25708,-1.68317 0.49984,-3.91406 0.17578,-1.3848 0.26453,-1.78381 0.35775,-3.43366 0.0343,-1.50575 0.16621,-2.92611 0.34777,-4.41853 3.41776,-29.53358 -4.36949,-64.23327 -14.83932,-91.75062 -1.82796,-5.01057 -2.50798,-10.5346 -0.48039,-15.59494 2.77561,-5.44447 7.91419,-9.12086 13.2956,-11.78439 4.61985,-1.46811 11.213,-1.23683 15.73004,0.59047 z"
|
||||
fill="#000000"
|
||||
id="path1737"
|
||||
style="fill:#000000;stroke-width:0.64051"
|
||||
sodipodi:nodetypes="sccccccccccccccccccccccss" /><path
|
||||
d="m 272.51296,111.27461 c 0.0625,1.73086 0.0951,3.44283 0.0913,5.17321 l 0.004,1.54522 c 0.004,1.71028 0.004,3.42054 0.004,5.13082 0.002,1.23807 0.004,2.47612 0.007,3.71419 0.006,3.40381 0.008,6.80758 0.0111,10.21138 0.002,3.67076 0.008,7.34148 0.0151,11.01223 0.0134,8.86663 0.0203,17.73324 0.0265,26.5999 0.002,4.17778 0.006,8.35557 0.009,12.53334 0.0115,13.89254 0.0215,27.78509 0.0265,41.67763 9.9e-4,3.60465 0.002,7.2093 0.004,10.81395 l 5.1e-4,1.35701 c 0.005,14.95695 0.0227,29.91384 0.0455,44.87077 0.0225,14.89906 0.0348,29.7981 0.0369,44.69717 9.9e-4,8.36206 0.007,16.72405 0.0249,25.08608 0.0147,7.12351 0.0202,14.24695 0.0136,21.37048 -0.003,3.63124 -0.002,7.26236 0.0113,10.89358 0.0119,3.3319 0.0111,6.66355 6.7e-4,9.99546 -9.9e-4,1.19792 9.8e-4,2.39589 0.008,3.59378 0.0855,13.447 -7.14775,27.68224 -14.42895,33.16415 -5.68126,5.15983 -12.10539,7.55874 -19.37792,9.65179 l -1.34327,0.40548 c -11.67562,3.52154 -23.44477,2.71479 -34.31308,-2.95335 -11.54324,-6.67497 -13.35743,-9.41898 -22.57986,-17.84579 -1.46825,-1.68479 -2.97861,-3.32951 -4.49215,-4.97406 -3.37894,-3.68996 -6.70345,-7.41681 -9.9429,-11.22868 -4.08451,-4.79472 -8.27417,-9.45859 -12.6065,-14.03338 -2.41506,-2.5512 -4.76442,-5.14206 -7.06128,-7.79958 -1.46061,-1.63062 -3.02771,-3.14433 -4.59519,-4.67247 -1.26952,-1.28839 -2.44327,-2.63252 -3.61923,-4.00569 -4.30454,-4.91895 -8.1686,-10.0474 -14.81841,-10.90111 l -4.91759,-0.41668 c -3.95729,0.14175 -10.16417,0.32794 -16.37236,0.49463 -1.37182,0.0386 -2.743497,0.0829 -4.115171,0.12758 -9.471106,0.29365 -17.125453,-0.11987 -25.905578,-4.00358 l -1.776394,-0.76464 c -4.323212,-2.1284 -7.745973,-5.37645 -11.158184,-8.71782 l -1.600891,-1.56632 C 47.251179,340.51668 45.49453,328.94052 45.561242,314.32985 c 0,-1.28279 -0.0067,-2.56555 -0.0074,-3.84833 -0.0067,-3.4565 0,-6.91284 0.0088,-10.36933 0.0074,-3.63191 0.0067,-7.26381 0.0067,-10.89572 -5.43e-4,-6.09535 0.0067,-12.19065 0.01973,-18.28599 0.01429,-7.03085 0.01702,-14.06162 0.01226,-21.09248 -0.0067,-6.78663 0,-13.57322 0.0074,-20.35985 0.0067,-2.87814 0.0067,-5.75625 0,-8.63437 0,-3.39245 0.0067,-6.78483 0.01497,-10.17724 v -3.71863 c -0.01905,-14.86868 2.530003,-25.6585 12.504809,-37.0111 9.947641,-9.65032 21.372975,-12.89593 34.656035,-12.90628 1.908048,-0.0111 3.816026,-0.0257 5.724014,-0.0396 2.9936,-0.0205 5.98708,-0.036 8.98075,-0.0348 2.43347,5.5e-4 4.8664,-0.0154 7.29973,-0.042 1.36256,-0.009 2.72531,-0.003 4.08792,0.004 6.33829,-0.0837 12.26677,-1.41474 17.07067,-5.65482 l 1.35363,-1.63779 1.52374,-1.79648 1.41207,-1.71712 c 0.76213,-0.87809 1.52777,-1.75317 2.29759,-2.62461 l 1.1541,-1.31759 c 2.56681,-2.88467 5.19943,-5.7103 7.82218,-8.54454 1.57726,-1.70554 3.15052,-3.4147 4.72416,-5.12355 0.62489,-0.67822 1.24982,-1.35642 1.87475,-2.0346 1.23964,-1.34546 2.4788,-2.69129 3.71764,-4.03746 6.92959,-7.52882 13.89106,-15.02711 20.89901,-22.48384 1.64561,-1.751395 3.28686,-3.506701 4.92492,-5.265088 1.98503,-2.130064 3.97976,-4.250696 5.98164,-6.365076 0.96307,-1.021271 1.91535,-2.051699 2.86641,-3.083185 12.48043,-10.508085 36.90033,-11.544359 53.5075,-1.918727 7.59155,5.206215 15.91278,9.067733 22.50599,27.960956 z"
|
||||
fill="#000000"
|
||||
id="path836"
|
||||
sodipodi:nodetypes="cccccccccsssccsccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
||||
style="fill:#ffffff;stroke-width:0.67904" /><path
|
||||
d="m 251.1722,92.79154 c 8.85658,6.73316 13.19296,16.0686 14.73924,26.91395 0.0589,1.63679 0.0895,3.25572 0.086,4.89206 l 0.004,1.46125 c 0.004,1.61733 0.004,3.23465 0.004,4.85199 0.002,1.17078 0.004,2.34156 0.007,3.51234 0.006,3.21883 0.008,6.43763 0.0105,9.65645 0.002,3.47127 0.008,6.94251 0.0142,10.41377 0.0127,8.38478 0.0191,16.76954 0.0248,25.15433 0.002,3.95074 0.006,7.90149 0.009,11.85222 0.0109,13.13756 0.0202,26.27512 0.0249,39.41267 10e-4,3.40876 0.002,6.81752 0.004,10.22628 l 4.7e-4,1.28326 c 0.005,14.14411 0.0213,28.28818 0.0427,42.43228 0.0212,14.08938 0.0328,28.17873 0.0347,42.26812 0.001,7.90762 0.007,15.81518 0.0234,23.72278 0.0139,6.73639 0.019,13.4727 0.0128,20.2091 -0.003,3.43391 -0.002,6.86769 0.0107,10.30157 0.0113,3.15083 0.0106,6.30142 6.4e-4,9.45226 -0.001,1.13283 10e-4,2.26569 0.008,3.39849 0.0805,12.71622 -1.73539,25.17483 -10.91454,34.70524 -5.34531,4.87942 -11.38955,7.14796 -18.23203,9.12727 l -1.26383,0.38344 c -10.98518,3.33016 -20.72781,2.56725 -30.95342,-2.79285 -9.69638,-5.3092 -17.2246,-13.08635 -24.40476,-21.38956 -1.38142,-1.59323 -2.80247,-3.14856 -4.2265,-4.70374 -3.17914,-3.48943 -6.30706,-7.01374 -9.35495,-10.61846 -3.84297,-4.53415 -7.78487,-8.94457 -11.86102,-13.27074 -2.27225,-2.41255 -4.48268,-4.86262 -6.64373,-7.37572 -1.37423,-1.54199 -2.84866,-2.97344 -4.32345,-4.41853 -1.19444,-1.21838 -2.29877,-2.48946 -3.40521,-3.78801 -4.04998,-4.65163 -7.85187,-8.8327 -14.10844,-9.64001 l -4.62679,-0.39403 c -3.72328,0.13404 -9.56314,0.31011 -15.40421,0.46775 -1.29069,0.0365 -2.58126,0.0783 -3.87182,0.12064 -8.91104,0.27769 -16.778047,0.38816 -25.038967,-3.2845 l -1.671348,-0.72308 c -4.067562,-2.01274 -7.287921,-5.08427 -10.498353,-8.24406 l -1.506224,-1.48119 C 53.971149,336.48946 52.318376,325.5424 52.381146,311.72574 c 0,-1.21307 -0.0064,-2.42613 -0.007,-3.63919 -0.0064,-3.26866 0,-6.53717 0.0083,-9.80581 0.007,-3.43454 0.0064,-6.86907 0.0064,-10.3036 -5.13e-4,-5.7641 0.0064,-11.52816 0.01857,-17.29224 0.01345,-6.64876 0.01601,-13.29744 0.01153,-19.94621 -0.0064,-6.41782 0,-12.8356 0.007,-19.25341 0.0064,-2.72172 0.0064,-5.44342 0,-8.16513 0,-3.20809 0.0064,-6.41611 0.01409,-9.62417 0,-1.17218 0,-2.34436 0,-3.51653 -0.01793,-14.06065 2.380394,-24.26411 11.765347,-34.99974 9.359395,-9.12588 22.104979,-11.35927 34.602557,-11.36906 1.79522,-0.0105 3.59037,-0.0243 5.38553,-0.0375 2.81658,-0.0194 5.63304,-0.034 8.44968,-0.0329 2.28957,5.2e-4 4.57863,-0.0146 6.86807,-0.0397 1.28198,-0.009 2.56416,-0.003 3.8462,0.004 5.96347,-0.0791 10.37711,-1.17068 14.89693,-5.18033 l 1.27358,-1.54879 1.43364,-1.69885 1.32856,-1.6238 c 0.71706,-0.83037 1.43743,-1.6579 2.16173,-2.48198 l 1.08585,-1.24599 c 2.41503,-2.7279 4.89197,-5.39997 7.35963,-8.08019 1.48398,-1.61285 2.96423,-3.22912 4.44479,-4.84511 0.58795,-0.64135 1.17592,-1.2827 1.7639,-1.92403 1.16633,-1.27233 2.33222,-2.54503 3.49779,-3.81804 6.51982,-7.11967 13.06963,-14.21046 19.66317,-21.26196 1.54829,-1.65622 3.09249,-3.31613 4.6337,-4.97896 1.86763,-2.01431 3.74441,-4.0197 5.62791,-6.01917 0.90612,-0.96577 1.80209,-1.9402 2.69691,-2.91563 15.73416,-16.623818 37.8784,-15.263399 55.94459,-3.29012 z m -30.90088,42.41584 -1.01707,1.08383 -1.12965,1.20347 -1.21222,1.30604 -1.24224,1.33355 c -2.72065,2.94304 -5.2795,5.97468 -7.77995,9.10727 -2.683,3.20833 -5.58384,6.21496 -8.45173,9.25738 -1.84605,1.96037 -3.62833,3.96566 -5.3868,6.00479 -2.16838,2.46811 -4.41097,4.86899 -6.64623,7.27641 -1.40051,1.50851 -2.79923,3.01864 -4.19662,4.53003 -5.2587,5.67465 -10.6037,11.25775 -16.05046,16.75226 -0.89246,0.90318 -1.78146,1.80982 -2.66712,2.71966 -1.31012,1.34536 -2.63063,2.67973 -3.95379,4.01225 l -1.17315,1.21717 c -15.39106,15.31731 -42.27727,6.85219 -60.626095,7.08446 v 107.60577 l 37.149605,0.6405 c 19.44299,2.43037 19.44299,2.43037 27.78465,10.89869 l 1.27397,1.27301 c 0.88114,0.88263 1.75995,1.76761 2.63648,2.65481 1.3247,1.3398 2.65771,2.67087 3.9921,4.001 4.40384,4.41339 8.60221,8.84247 12.35109,13.83853 3.57016,4.47303 7.28011,8.75827 11.16891,12.95283 1.7045,1.84742 3.36234,3.72823 5.00899,5.62699 1.8069,2.06619 3.65295,4.09696 5.49438,6.13238 1.15187,1.28703 2.27235,2.59222 3.38769,3.91062 2.38774,2.7459 4.95909,5.30946 7.52601,7.88628 l 1.31886,1.32779 1.23817,1.23426 1.12309,1.12089 c 0.7639,0.87233 0.7639,0.87233 1.52403,0.80064 V 134.43723 c -0.74901,-0.0738 -0.74901,-0.0738 -1.4449,0.77015 z"
|
||||
fill="#000000"
|
||||
id="path1813"
|
||||
sodipodi:nodetypes="ccccccccccsssccsccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
||||
style="stroke-width:0.64051;fill:#000000" /><path
|
||||
d="m 419.63397,119.06499 c 8.12662,5.35763 10.5989,15.10196 13.61085,23.85901 0.26904,0.77609 0.26904,0.77609 0.5435,1.56788 1.27795,3.68806 2.5358,7.3826 3.77995,11.0822 0.22948,0.68188 0.22948,0.68188 0.46361,1.37755 5.89033,17.56405 11.75182,36.11177 14.2281,54.50699 0.10568,0.77695 0.21136,1.55389 0.32025,2.35438 0.0855,0.62993 0.0855,0.62993 0.17264,1.27258 0.1971,1.40434 0.41097,2.80539 0.62801,4.20679 7.96138,52.04834 -0.57216,104.48321 -18.37465,161.10092 -0.24141,0.74959 -0.48281,1.49918 -0.73152,2.27149 -3.40249,10.39919 -6.97316,18.30096 -16.66486,24.18959 -5.0051,2.47251 -11.10366,2.56686 -16.55068,1.72138 -4.12946,-1.41568 -7.41805,-3.71606 -10.24817,-7.04562 -0.42233,-0.46567 -0.42233,-0.46567 -0.85318,-0.94075 -4.48384,-5.06531 -4.2709,-10.70145 -4.2709,-17.1862 0.47468,-6.43055 2.94211,-11.89523 5.42932,-17.77604 25.84921,-61.35841 23.7815,-130.19883 -1.82333,-208.58814 -3.07153,-8.40934 -5.7921,-17.96937 -2.6052,-26.80512 2.89853,-5.95864 8.16023,-10.69185 14.28138,-13.20051 6.20047,-1.63496 13.03637,-1.06891 18.66488,2.03162 z"
|
||||
fill="#000000"
|
||||
id="path1775"
|
||||
style="stroke-width:0.64051;fill:#000000" /><rect
|
||||
id="backgroundrect"
|
||||
width="511"
|
||||
height="510.51233"
|
||||
x="3.313553e-07"
|
||||
y="0.48767093"
|
||||
fill="none"
|
||||
stroke="none"
|
||||
style="stroke-width:3.81627" /><metadata
|
||||
id="metadata4211"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs4209" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="5040"
|
||||
inkscape:window-height="979"
|
||||
id="namedview4207"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="6.7175144"
|
||||
inkscape:cy="206.12163"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg43"
|
||||
inkscape:pagecheckerboard="0" /><style
|
||||
type="text/css"
|
||||
id="style4189">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:18;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:18;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:#000000;stroke-width:19;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
</style></svg>
|
After Width: | Height: | Size: 14 KiB |
|
@ -95,8 +95,9 @@
|
|||
var SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg");
|
||||
var ZONE_URL = Script.resolvePath("assets/images/icon-zone.svg");
|
||||
var MATERIAL_URL = Script.resolvePath("assets/images/icon-material.svg");
|
||||
var SOUND_URL = Script.resolvePath("assets/images/icon-sound.svg");
|
||||
|
||||
var entityIconOverlayManager = new EntityIconOverlayManager(["Light", "ParticleEffect", "ProceduralParticleEffect", "Zone", "Material"], function(entityID) {
|
||||
var entityIconOverlayManager = new EntityIconOverlayManager(["Light", "ParticleEffect", "ProceduralParticleEffect", "Zone", "Material", "Sound"], function(entityID) {
|
||||
var properties = Entities.getEntityProperties(entityID, ["type", "isSpotlight", "parentID", "name"]);
|
||||
if (properties.type === "Light") {
|
||||
return {
|
||||
|
@ -110,6 +111,8 @@
|
|||
} else {
|
||||
return { imageURL: "" };
|
||||
}
|
||||
} else if (properties.type === "Sound") {
|
||||
return { imageURL: SOUND_URL, rotation: Quat.fromPitchYawRollDegrees(0, 0, 0) };
|
||||
} else {
|
||||
return { imageURL: PARTICLE_SYSTEM_URL };
|
||||
}
|
||||
|
@ -530,6 +533,13 @@
|
|||
exponent: 1.0,
|
||||
cutoff: 75.0,
|
||||
},
|
||||
Sound: {
|
||||
volume: 1.0,
|
||||
playing: true,
|
||||
loop: true,
|
||||
positional: true,
|
||||
localOnly: false
|
||||
},
|
||||
};
|
||||
|
||||
var toolBar = (function () {
|
||||
|
@ -608,7 +618,7 @@
|
|||
if (!properties.grab) {
|
||||
properties.grab = {};
|
||||
if (Menu.isOptionChecked(MENU_CREATE_ENTITIES_GRABBABLE) &&
|
||||
!(properties.type === "Zone" || properties.type === "Light"
|
||||
!(properties.type === "Zone" || properties.type === "Light" || properties.type === "Sound"
|
||||
|| properties.type === "ParticleEffect" || properties.type == "ProceduralParticleEffect"
|
||||
|| properties.type === "Web")) {
|
||||
properties.grab.grabbable = true;
|
||||
|
@ -906,6 +916,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
function handleNewSoundDialogResult(result) {
|
||||
if (result) {
|
||||
var soundURL = result.textInput;
|
||||
if (soundURL) {
|
||||
createNewEntity({
|
||||
type: "Sound",
|
||||
soundURL: soundURL
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml.
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.popFromStack();
|
||||
|
@ -941,6 +963,13 @@
|
|||
case "newPolyVoxDialogCancel":
|
||||
closeExistingDialogWindow();
|
||||
break;
|
||||
case "newSoundDialogAdd":
|
||||
handleNewSoundDialogResult(message.params);
|
||||
closeExistingDialogWindow();
|
||||
break;
|
||||
case "newSoundDialogCancel":
|
||||
closeExistingDialogWindow();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1106,6 +1135,8 @@
|
|||
|
||||
addButton("newPolyVoxButton", createNewEntityDialogButtonCallback("PolyVox"));
|
||||
|
||||
addButton("newSoundButton", createNewEntityDialogButtonCallback("Sound"));
|
||||
|
||||
var deactivateCreateIfDesktopWindowsHidden = function() {
|
||||
if (!shouldUseEditTabletApp() && !entityListTool.isVisible() && !createToolsWindow.isVisible()) {
|
||||
that.setActive(false);
|
||||
|
@ -2092,7 +2123,7 @@
|
|||
var entityParentIDs = [];
|
||||
|
||||
var propType = Entities.getEntityProperties(pastedEntityIDs[0], ["type"]).type;
|
||||
var NO_ADJUST_ENTITY_TYPES = ["Zone", "Light", "ParticleEffect", "ProceduralParticleEffect"];
|
||||
var NO_ADJUST_ENTITY_TYPES = ["Zone", "Light", "ParticleEffect", "ProceduralParticleEffect", "Sound"];
|
||||
if (NO_ADJUST_ENTITY_TYPES.indexOf(propType) === -1) {
|
||||
var targetDirection;
|
||||
if (Camera.mode === "entity" || Camera.mode === "independent") {
|
||||
|
|
|
@ -211,7 +211,7 @@ var EntityListTool = function(shouldUseEditTabletApp, selectionManager) {
|
|||
PROFILE("getMultipleProperties", function () {
|
||||
var multipleProperties = Entities.getMultipleEntityProperties(ids, ['position', 'name', 'type', 'locked',
|
||||
'visible', 'renderInfo', 'modelURL', 'materialURL', 'imageURL', 'script', 'serverScripts',
|
||||
'skybox.url', 'ambientLight.url', 'created', 'lastEdited']);
|
||||
'skybox.url', 'ambientLight.url', 'soundURL', 'created', 'lastEdited']);
|
||||
for (var i = 0; i < multipleProperties.length; i++) {
|
||||
var properties = multipleProperties[i];
|
||||
|
||||
|
@ -223,6 +223,8 @@ var EntityListTool = function(shouldUseEditTabletApp, selectionManager) {
|
|||
url = properties.materialURL;
|
||||
} else if (properties.type === "Image") {
|
||||
url = properties.imageURL;
|
||||
} else if (properties.type === "Sound") {
|
||||
url = properties.soundURL;
|
||||
}
|
||||
//print("Global object before getParentState call: " + JSON.stringify(globalThis));
|
||||
var parentStatus = that.createApp.getParentState(ids[i]);
|
||||
|
|
|
@ -180,6 +180,7 @@ const FILTER_TYPES = [
|
|||
"PolyVox",
|
||||
"Text",
|
||||
"Grid",
|
||||
"Sound",
|
||||
];
|
||||
|
||||
const DOUBLE_CLICK_TIMEOUT = 300; // ms
|
||||
|
|
|
@ -1627,6 +1627,62 @@ const GROUPS = [
|
|||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "sound",
|
||||
label: "SOUND",
|
||||
properties: [
|
||||
{
|
||||
label: "Sound",
|
||||
type: "string",
|
||||
propertyID: "soundURL",
|
||||
placeholder: "URL",
|
||||
},
|
||||
{
|
||||
label: "Playing",
|
||||
type: "bool",
|
||||
propertyID: "playing",
|
||||
},
|
||||
{
|
||||
label: "Loop",
|
||||
type: "bool",
|
||||
propertyID: "loop",
|
||||
},
|
||||
{
|
||||
label: "Volume",
|
||||
type: "number-draggable",
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
decimals: 2,
|
||||
propertyID: "volume",
|
||||
},
|
||||
{
|
||||
label: "Positional",
|
||||
type: "bool",
|
||||
propertyID: "positional",
|
||||
},
|
||||
{
|
||||
label: "Pitch",
|
||||
type: "number-draggable",
|
||||
min: 0.0625,
|
||||
max: 16,
|
||||
step: 0.1,
|
||||
decimals: 2,
|
||||
propertyID: "pitch",
|
||||
},
|
||||
{
|
||||
label: "Time Offset",
|
||||
type: "number-draggable",
|
||||
step: 0.1,
|
||||
propertyID: "timeOffset",
|
||||
},
|
||||
{
|
||||
label: "Local Only",
|
||||
type: "bool",
|
||||
propertyID: "localOnly",
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "spatial",
|
||||
label: "SPATIAL",
|
||||
|
@ -2014,6 +2070,7 @@ const GROUPS_PER_TYPE = {
|
|||
PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ],
|
||||
PolyVox: [ 'base', 'polyvox', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ],
|
||||
Grid: [ 'base', 'grid', 'spatial', 'behavior', 'scripts', 'physics' ],
|
||||
Sound: [ 'base', 'sound', 'spatial', 'behavior', 'scripts', 'physics' ],
|
||||
Multiple: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ],
|
||||
};
|
||||
|
||||
|
|
BIN
scripts/system/create/entityProperties/html/tabs/sound.png
Normal file
BIN
scripts/system/create/entityProperties/html/tabs/sound.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 684 B |
|
@ -2255,7 +2255,7 @@ SelectionDisplay = (function() {
|
|||
Entities.editEntity(selectionBox, selectionBoxGeometry);
|
||||
|
||||
// UPDATE ICON TRANSLATE HANDLE
|
||||
if (SelectionManager.entityType === "ParticleEffect" || SelectionManager.entityType === "ProceduralParticleEffect" || SelectionManager.entityType === "Light") {
|
||||
if (SelectionManager.entityType === "ParticleEffect" || SelectionManager.entityType === "ProceduralParticleEffect" || SelectionManager.entityType === "Light" || SelectionManager.entityType === "Sound") {
|
||||
var iconSelectionBoxGeometry = {
|
||||
position: position,
|
||||
rotation: rotation
|
||||
|
|
|
@ -352,6 +352,17 @@ function brokenURLReport(entityIDs) {
|
|||
};
|
||||
brokenURLReportUrlList.push(brokenURLReportUrlEntry);
|
||||
}
|
||||
if (properties.type === "Sound" && properties.soundURL.toLowerCase().startsWith("http")) {
|
||||
brokenURLReportUrlEntry = {
|
||||
id: entityIDs[i],
|
||||
name: properties.name,
|
||||
type: properties.type,
|
||||
urlType: "soundURL",
|
||||
url: soundURL,
|
||||
validity: "NOT_TESTED"
|
||||
};
|
||||
brokenURLReportUrlList.push(brokenURLReportUrlEntry);
|
||||
}
|
||||
}
|
||||
if (brokenURLReportUrlList.length === 0) {
|
||||
audioFeedback.confirmation();
|
||||
|
|
|
@ -190,6 +190,18 @@ TabBar {
|
|||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/sound.svg"
|
||||
text: "SOUND"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newSoundButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
|
|
|
@ -196,6 +196,18 @@ TabBar {
|
|||
editTabView.currentIndex = tabIndex.properties
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/sound.svg"
|
||||
text: "SOUND"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newSoundButton" }
|
||||
});
|
||||
editTabView.currentIndex = tabIndex.properties
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
|
|
158
scripts/system/create/qml/NewSoundDialog.qml
Normal file
158
scripts/system/create/qml/NewSoundDialog.qml
Normal file
|
@ -0,0 +1,158 @@
|
|||
//
|
||||
// NewSoundDialog.qml
|
||||
// qml/hifi
|
||||
//
|
||||
// Created by HifiExperiments on 4/7/24
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||
|
||||
import stylesUit 1.0
|
||||
import controlsUit 1.0
|
||||
import hifi.dialogs 1.0
|
||||
|
||||
Rectangle {
|
||||
id: newSoundDialog
|
||||
// width: parent.width
|
||||
// height: parent.height
|
||||
HifiConstants { id: hifi }
|
||||
color: hifi.colors.baseGray;
|
||||
signal sendToScript(var message);
|
||||
property bool keyboardEnabled: false
|
||||
property bool punctuationMode: false
|
||||
|
||||
function errorMessageBox(message) {
|
||||
try {
|
||||
return desktop.messageBox({
|
||||
icon: hifi.icons.warning,
|
||||
defaultButton: OriginalDialogs.StandardButton.Ok,
|
||||
title: "Error",
|
||||
text: message
|
||||
});
|
||||
} catch(e) {
|
||||
Window.alert(message);
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: column1
|
||||
anchors.rightMargin: 10
|
||||
anchors.leftMargin: 10
|
||||
anchors.bottomMargin: 10
|
||||
anchors.topMargin: 10
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: keyboard.top
|
||||
|
||||
Text {
|
||||
id: text1
|
||||
text: qsTr("Sound URL")
|
||||
color: "#ffffff"
|
||||
font.pixelSize: 12
|
||||
}
|
||||
|
||||
TextInput {
|
||||
id: soundURL
|
||||
height: 20
|
||||
text: qsTr("")
|
||||
color: "white"
|
||||
anchors.top: text1.bottom
|
||||
anchors.topMargin: 5
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
font.pixelSize: 12
|
||||
|
||||
onAccepted: {
|
||||
newSoundDialog.keyboardEnabled = false;
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
newSoundDialog.keyboardEnabled = HMD.active
|
||||
parent.focus = true;
|
||||
parent.forceActiveFocus();
|
||||
soundURL.cursorPosition = soundURL.positionAt(mouseX, mouseY, TextInput.CursorBetweenCharaters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: textInputBox
|
||||
color: "white"
|
||||
anchors.fill: soundURL
|
||||
opacity: 0.1
|
||||
}
|
||||
|
||||
Row {
|
||||
id: row1
|
||||
height: 400
|
||||
spacing: 30
|
||||
anchors.top: soundURL.bottom
|
||||
anchors.topMargin: 5
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
|
||||
Column {
|
||||
id: column3
|
||||
height: 400
|
||||
spacing: 10
|
||||
|
||||
Row {
|
||||
id: row3
|
||||
width: 200
|
||||
height: 400
|
||||
spacing: 5
|
||||
|
||||
anchors.horizontalCenter: column3.horizontalCenter
|
||||
anchors.horizontalCenterOffset: 0
|
||||
|
||||
Button {
|
||||
id: button1
|
||||
text: qsTr("Create")
|
||||
z: -1
|
||||
onClicked: {
|
||||
newSoundDialog.sendToScript({
|
||||
method: "newSoundDialogAdd",
|
||||
params: {
|
||||
textInput: soundURL.text
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: button2
|
||||
z: -1
|
||||
text: qsTr("Cancel")
|
||||
onClicked: {
|
||||
newSoundDialog.sendToScript({method: "newSoundDialogCancel"})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keyboard {
|
||||
id: keyboard
|
||||
raised: parent.keyboardEnabled
|
||||
numeric: parent.punctuationMode
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
}
|
||||
}
|
31
scripts/system/create/qml/NewSoundWindow.qml
Normal file
31
scripts/system/create/qml/NewSoundWindow.qml
Normal file
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// NewSoundWindow.qml
|
||||
// qml/hifi
|
||||
//
|
||||
// Created by HifiExperiments on 4/7/24
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
StackView {
|
||||
id: stackView
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 10
|
||||
anchors.rightMargin: 10
|
||||
anchors.topMargin: 40
|
||||
|
||||
signal sendToScript(var message);
|
||||
|
||||
NewSoundDialog {
|
||||
id: dialog
|
||||
anchors.fill: parent
|
||||
Component.onCompleted:{
|
||||
dialog.sendToScript.connect(stackView.sendToScript);
|
||||
}
|
||||
}
|
||||
}
|
59
scripts/system/create/qml/icons/sound.svg
Normal file
59
scripts/system/create/qml/icons/sound.svg
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 512 512"
|
||||
style="enable-background:new 0 0 512 512;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="sound.svg"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs29" /><sodipodi:namedview
|
||||
id="namedview27"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.77539063"
|
||||
inkscape:cx="-56.100756"
|
||||
inkscape:cy="169.59194"
|
||||
inkscape:window-width="5040"
|
||||
inkscape:window-height="979"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style2">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:18;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:18;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:#000000;stroke-width:19;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
</style>
|
||||
|
||||
<g
|
||||
id="g826"
|
||||
transform="matrix(0.55495039,0,0,0.55495039,49.689478,51.969306)"><path
|
||||
d="m 0,0 c 13.827391,10.512174 20.597576,25.087167 23.011719,42.019531 0.092,2.555446 0.13969,5.082998 0.134221,7.637738 l 0.0071,2.281383 c 0.0067,2.525082 0.0062,5.050113 0.0058,7.575203 0.0033,1.827887 0.007,3.655773 0.01114,5.483658 0.01001,5.025394 0.01373,10.050777 0.01639,15.07618 0.0039,5.419517 0.01348,10.839025 0.02221,16.258537 0.01976,13.09077 0.02983,26.18153 0.03873,39.27231 0.0044,6.16812 0.0098,12.33624 0.01499,18.50435 0.01701,20.51107 0.03151,41.02213 0.03875,61.5332 0.0019,5.32194 0.0038,10.64388 0.0058,15.96582 l 7.27e-4,2.0035 c 0.0081,22.08256 0.03335,44.16506 0.06685,66.24759 0.0331,21.9971 0.05109,43.99417 0.05428,65.9913 0.0022,12.3458 0.01087,24.69152 0.03646,37.0373 0.02175,10.51721 0.02974,21.03431 0.02003,31.55154 -0.0045,5.36121 -0.0027,10.72221 0.01676,16.08338 0.01772,4.91925 0.01656,9.83813 0.0011,14.75738 -0.0024,1.76864 0.0019,3.53731 0.01383,5.30591 0.125724,19.85325 -2.709399,39.30431 -17.0403675,54.18372 -8.3454088,7.618 -17.7819935,11.15977 -28.4648435,14.25 l -1.973145,0.59863 c -17.150657,5.19924 -32.361378,4.00814 -48.326172,-4.36035 -15.138528,-8.289 -26.891988,-20.43111 -38.102049,-33.39453 -2.15675,-2.48745 -4.37538,-4.91572 -6.59863,-7.34375 -4.96347,-5.44789 -9.84694,-10.95022 -14.60547,-16.57812 -5.99986,-7.07897 -12.15416,-13.96475 -18.51807,-20.719 -3.54755,-3.76661 -6.99861,-7.5918 -10.37255,-11.51538 -2.14552,-2.40744 -4.4475,-4.64229 -6.75,-6.89844 -1.86484,-1.90221 -3.58897,-3.88668 -5.31641,-5.91406 -6.32304,-7.26238 -12.25876,-13.79009 -22.02691,-15.0505 l -7.22359,-0.6152 c -5.81299,0.20929 -14.93041,0.48418 -24.04986,0.73028 -2.01512,0.057 -4.03,0.12239 -6.04486,0.18835 -13.91246,0.43355 -26.19483,0.60604 -39.09228,-5.12793 l -2.60938,-1.12891 c -6.35051,-3.14241 -11.37831,-7.93784 -16.39062,-12.87109 l -2.35156,-2.3125 c -15.53838,-16.23253 -18.11876,-33.32369 -18.02076,-54.89502 -0.002,-1.8939 -0.006,-3.7878 -0.0111,-5.6817 -0.009,-5.10319 -4e-5,-10.20618 0.0133,-15.30936 0.0114,-5.36218 0.007,-10.72435 0.005,-16.08654 -8.8e-4,-8.99923 0.0101,-17.99839 0.0286,-26.99759 0.0212,-10.3804 0.0247,-20.76069 0.0184,-31.1411 -0.006,-10.01985 -4e-5,-20.03965 0.0112,-30.05949 0.005,-4.24929 0.006,-8.49855 0.003,-12.74784 -0.002,-5.00865 0.006,-10.01718 0.0221,-15.02579 0.004,-1.83006 0.005,-3.66013 0.002,-5.49019 -0.0285,-21.95225 3.71639,-37.88244 18.36863,-54.6435 14.61244,-14.24783 34.5115,-17.73471 54.02344,-17.75 2.80276,-0.0161 5.60547,-0.0379 8.4082,-0.0586 4.39744,-0.0303 8.79459,-0.0531 13.19214,-0.0513 3.5746,8e-4 7.14834,-0.0228 10.72271,-0.0619 2.00158,-0.0154 4.0033,-0.005 6.00491,0.006 9.31056,-0.12346 16.20132,-1.82773 23.25798,-8.08783 l 1.98828,-2.41797 2.23828,-2.652343 2.07422,-2.535156 c 1.11952,-1.296419 2.2442,-2.58841 3.375,-3.875 l 1.69531,-1.945312 c 3.77047,-4.258956 7.63759,-8.430729 11.49024,-12.615235 2.31687,-2.51807 4.62792,-5.041473 6.93945,-7.564453 0.91795,-1.001322 1.83591,-2.002624 2.75391,-3.003906 1.82093,-1.986413 3.64119,-3.973438 5.46093,-5.960938 10.1791,-11.115607 20.40503,-22.186149 30.69922,-33.195312 2.41728,-2.585792 4.82817,-5.177336 7.23438,-7.773438 2.915852,-3.144847 5.845981,-6.275773 8.786614,-9.3974604 C -90.139631,8.18094 -88.740775,6.6596201 -87.34375,5.1367187 -62.778713,-20.817295 -28.205909,-18.693328 0,0 Z m -48.244141,66.221924 -1.58789,1.692138 -1.763672,1.878907 -1.892578,2.039062 -1.939453,2.082031 c -4.247651,4.594835 -8.242647,9.327988 -12.146485,14.21875 -4.188864,5.009015 -8.7178,9.703144 -13.195312,14.453128 -2.882159,3.06065 -5.664738,6.19141 -8.410156,9.375 -3.385406,3.85336 -6.886651,7.60175 -10.376465,11.36035 -2.186548,2.35516 -4.370308,4.71285 -6.551998,7.07251 -8.21016,8.85958 -16.55506,17.57623 -25.05884,26.15454 -1.39336,1.41011 -2.78131,2.82559 -4.16406,4.24609 -2.04543,2.10046 -4.10708,4.18374 -6.17286,6.26416 l -1.8316,1.9003 c -24.02936,23.91421 -66.00557,10.69802 -94.65277,11.06064 v 168 l 58,1 c 30.35546,3.79443 30.35546,3.79443 43.37891,17.01563 l 1.98899,1.98748 c 1.37569,1.37802 2.74774,2.75968 4.11623,4.14484 2.06819,2.09176 4.14935,4.1699 6.23267,6.24658 6.87552,6.89041 13.43025,13.80534 19.2832,21.60547 5.573935,6.98354 11.3661,13.67388 17.437499,20.22266 2.661163,2.88428 5.24949,5.82071 7.820312,8.78515 2.821044,3.22586 5.703196,6.39642 8.578125,9.57422 1.798374,2.00938 3.547726,4.04712 5.289063,6.10547 3.727868,4.28705 7.742389,8.28942 11.75,12.3125 l 2.059082,2.073 1.933105,1.927 1.753418,1.75 c 1.192644,1.36192 1.192644,1.36192 2.379395,1.25 V 65.019531 c -1.169391,-0.11526 -1.169391,-0.11526 -2.25586,1.202393 z"
|
||||
fill="#000000"
|
||||
transform="translate(370.98828,94.980469)"
|
||||
id="path836"
|
||||
sodipodi:nodetypes="ccccccccccsssccsccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" /><path
|
||||
d="m 0,0 c 12.687715,8.3646425 16.54757,23.578013 21.25,37.25 0.420028,1.211683 0.420028,1.211683 0.848541,2.447845 C 24.093738,45.455849 26.057576,51.223992 28,57 c 0.358289,1.064594 0.358289,1.064594 0.723816,2.150696 9.196303,27.421957 18.34758,56.379674 22.213684,85.099304 0.165,1.21301 0.33,2.42602 0.5,3.67578 0.133418,0.98348 0.133418,0.98348 0.269531,1.98682 0.307725,2.19254 0.641643,4.37993 0.980469,6.56787 C 65.117247,237.74117 51.79423,319.60536 24,408 c -0.37689,1.17031 -0.753779,2.34062 -1.14209,3.54639 C 17.545759,427.78218 11.971055,440.11885 -3.1601563,449.3125 -10.974406,453.17271 -20.495807,453.32002 -29,452 c -6.447118,-2.21023 -11.581457,-5.80171 -16,-11 -0.659355,-0.72703 -0.659355,-0.72703 -1.332031,-1.46875 C -53.332437,431.62301 -53,422.82358 -53,412.69922 c 0.741111,-10.03973 4.593387,-18.57148 8.476563,-27.75293 C -4.1662297,289.1502 -7.3944601,181.67277 -47.370117,59.287109 -52.165555,46.157988 -56.413045,31.232358 -51.4375,17.4375 -46.91216,8.1345364 -38.697322,0.74480411 -29.140625,-3.171875 -19.460116,-5.7244469 -8.7875393,-4.8407102 0,0 Z"
|
||||
fill="#000000"
|
||||
transform="translate(634,136)"
|
||||
id="path838" /><path
|
||||
d="m 0,0 c 17.968337,10.39053 22.143536,33.207156 27.238281,51.816406 9.06097,33.99317 13.985108,69.235084 14.882813,104.410154 0.02191,0.81179 0.04383,1.62358 0.06641,2.45996 1.024973,44.84255 -6.637484,88.87597 -20.066406,131.54004 -0.326455,1.04898 -0.65291,2.09795 -0.989258,3.17871 -1.007854,3.21683 -2.036103,6.4263 -3.073242,9.63379 -0.304138,0.96027 -0.608277,1.92054 -0.921631,2.90991 -3.75203,11.33325 -8.7198824,22.01013 -19.3283693,28.21509 -8.8558147,2.55168 -16.4996667,1.12221 -24.6874997,-2.9375 -8.148586,-4.91088 -14.567027,-10.35992 -18.375,-19.1875 -1.817982,-11.08969 -0.01228,-20.87108 3,-31.5625 0.556674,-2.04436 1.107614,-4.09021 1.658188,-6.13623 0.370535,-1.37582 0.742896,-2.75115 1.117096,-4.12597 1.752041,-6.46008 3.279791,-12.96668 4.787216,-19.4878 1.519228,-6.51781 3.16177,-12.83043 5.4375,-19.125 3.245102,-9.10722 4.514672,-18.63286 5.973633,-28.16113 0.401367,-2.21387 0.401367,-2.21387 1.401367,-5.21387 0.06725,-2.09304 -0.0012,-4.16495 -0.0625,-6.25781 0.05358,-2.35085 0.2595,-4.56839 0.542969,-6.89844 5.335996,-46.10945 -6.821894,-100.284491 -23.167969,-143.246091 -2.853907,-7.822763 -3.915598,-16.44719 -0.75,-24.347657 C -40.982968,8.9763575 -32.960334,3.2365619 -24.558594,-0.921875 -17.345835,-3.2139762 -7.0522415,-2.8528916 0,0 Z"
|
||||
fill="#000000"
|
||||
transform="translate(503.87891,195.77344)"
|
||||
id="path840" /></g></svg>
|
After Width: | Height: | Size: 8.6 KiB |
|
@ -21,6 +21,7 @@ const ENTITY_TYPE_ICON = {
|
|||
PolyLine: "",
|
||||
Shape: "n",
|
||||
Sphere: "n",
|
||||
Sound: "G",
|
||||
Text: "l",
|
||||
Web: "q",
|
||||
Zone: "o",
|
||||
|
|
Loading…
Reference in a new issue