Merge branch 'master' of https://github.com/highfidelity/hifi into Case20377

This commit is contained in:
Roxanne Skelly 2018-12-27 14:13:40 -08:00
commit 4fc263ff24
60 changed files with 1647 additions and 722 deletions

View file

@ -189,15 +189,17 @@ Windows.ScrollingWindow {
var grabbable = MenuInterface.isOptionChecked("Create Entities As Grabbable (except Zones, Particles, and Lights)");
if (defaultURL.endsWith(".jpg") || defaultURL.endsWith(".png")) {
var name = assetProxyModel.data(treeView.selection.currentIndex);
var modelURL = "https://hifi-content.s3.amazonaws.com/DomainContent/production/default-image-model.fbx";
var textures = JSON.stringify({ "tex.picture": defaultURL});
var shapeType = "box";
var dynamic = false;
var collisionless = true;
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getForward(MyAvatar.orientation)));
var gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0);
Entities.addModelEntity(name, modelURL, textures, shapeType, dynamic, collisionless, grabbable, position, gravity);
Entities.addEntity({
type: "Image",
name: assetProxyModel.data(treeView.selection.currentIndex),
imageURL: defaultURL,
keepAspectRatio: false,
dynamic: false,
collisionless: true,
grabbable: grabbable,
position: Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getForward(MyAvatar.orientation))),
gravity: Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0)
});
} else {
var SHAPE_TYPE_NONE = 0;
var SHAPE_TYPE_SIMPLE_HULL = 1;

View file

@ -75,6 +75,10 @@ Rectangle {
if(materialUrlOrJson) {
wearable.text = 'Material: ' + materialUrlOrJson;
}
} else if (wearable.sourceUrl) {
wearable.text = extractTitleFromUrl(wearable.sourceUrl);
} else if (wearable.name) {
wearable.text = wearable.name;
}
wearablesCombobox.model.append(wearable);
}

View file

@ -176,6 +176,7 @@ Item {
Item {
property alias buttonGlyphText: buttonGlyph.text;
property alias buttonText: buttonText.text;
property alias glyphSize: buttonGlyph.size;
property string buttonColor: hifi.colors.black;
property string buttonColor_hover: hifi.colors.blueHighlight;
property alias enabled: buttonMouseArea.enabled;
@ -186,7 +187,8 @@ Item {
anchors.top: parent.top;
anchors.topMargin: 4;
anchors.horizontalCenter: parent.horizontalCenter;
anchors.bottom: parent.verticalCenter;
anchors.bottom: buttonText.visible ? parent.verticalCenter : parent.bottom;
anchors.bottomMargin: buttonText.visible ? 0 : 4;
width: parent.width;
size: 40;
horizontalAlignment: Text.AlignHCenter;
@ -196,6 +198,7 @@ Item {
RalewayRegular {
id: buttonText;
visible: text !== "";
anchors.top: parent.verticalCenter;
anchors.topMargin: 4;
anchors.bottom: parent.bottom;
@ -300,7 +303,7 @@ Item {
anchors.right: certificateButton.left;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
width: 78;
width: 72;
onLoaded: {
item.buttonGlyphText = hifi.glyphs.uninstall;
@ -310,6 +313,10 @@ Item {
Commerce.uninstallApp(root.itemHref);
}
}
onVisibleChanged: {
trashButton.updateProperties();
}
}
Loader {
@ -319,7 +326,7 @@ Item {
anchors.right: uninstallButton.visible ? uninstallButton.left : certificateButton.left;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
width: 84;
width: 78;
onLoaded: {
item.buttonGlyphText = hifi.glyphs.update;
@ -339,6 +346,45 @@ Item {
});
}
}
onVisibleChanged: {
trashButton.updateProperties();
}
}
Loader {
id: trashButton;
visible: root.itemEdition > 0;
sourceComponent: contextCardButton;
anchors.right: updateButton.visible ? updateButton.left : (uninstallButton.visible ? uninstallButton.left : certificateButton.left);
anchors.top: parent.top;
anchors.bottom: parent.bottom;
width: (updateButton.visible && uninstallButton.visible) ? 15 : 78;
onLoaded: {
item.buttonGlyphText = hifi.glyphs.trash;
updateProperties();
item.buttonClicked = function() {
sendToPurchases({method: 'showTrashLightbox',
isInstalled: root.isInstalled,
itemHref: root.itemHref,
itemName: root.itemName,
certID: root.certificateId,
itemType: root.itemType,
wornEntityID: root.wornEntityID
});
}
}
function updateProperties() {
if (updateButton.visible && uninstallButton.visible) {
item.buttonText = "";
item.glyphSize = 20;
} else {
item.buttonText = "Send to Trash";
item.glyphSize = 30;
}
}
}
}

View file

@ -651,6 +651,42 @@ Rectangle {
lightboxPopup.visible = false;
};
lightboxPopup.visible = true;
} else if (msg.method === "showTrashLightbox") {
lightboxPopup.titleText = "Send \"" + msg.itemName + "\" to Trash";
lightboxPopup.bodyText = "Sending this item to the Trash means you will no longer own this item " +
"and it will be inaccessible to you from Purchases.\n\nThis action cannot be undone.";
lightboxPopup.button1text = "CANCEL";
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.button2text = "CONFIRM";
lightboxPopup.button2method = function() {
if (msg.isInstalled) {
Commerce.uninstallApp(msg.itemHref);
}
if (MyAvatar.skeletonModelURL === msg.itemHref) {
MyAvatar.useFullAvatarURL('');
}
if (msg.itemType === "wearable" && msg.wornEntityID !== '') {
Entities.deleteEntity(msg.wornEntityID);
purchasesModel.setProperty(index, 'wornEntityID', '');
}
Commerce.transferAssetToUsername("trashbot", msg.certID, 1, "Sent " + msg.itemName + " to trash.");
lightboxPopup.titleText = '"' + msg.itemName + '" Sent to Trash';
lightboxPopup.button1text = "OK";
lightboxPopup.button1method = function() {
root.purchasesReceived = false;
lightboxPopup.visible = false;
getPurchases();
}
lightboxPopup.button2text = "";
lightboxPopup.bodyText = "";
};
lightboxPopup.visible = true;
} else if (msg.method === "showChangeAvatarLightbox") {
lightboxPopup.titleText = "Change Avatar";
lightboxPopup.bodyText = "This will change your current avatar to " + msg.itemName + " while retaining your wearables.";

View file

@ -189,15 +189,17 @@ Rectangle {
var grabbable = MenuInterface.isOptionChecked("Create Entities As Grabbable (except Zones, Particles, and Lights)");
if (defaultURL.endsWith(".jpg") || defaultURL.endsWith(".png")) {
var name = assetProxyModel.data(treeView.selection.currentIndex);
var modelURL = "https://hifi-content.s3.amazonaws.com/DomainContent/production/default-image-model.fbx";
var textures = JSON.stringify({ "tex.picture": defaultURL});
var shapeType = "box";
var dynamic = false;
var collisionless = true;
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getForward(MyAvatar.orientation)));
var gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0);
Entities.addModelEntity(name, modelURL, textures, shapeType, dynamic, collisionless, grabbable, position, gravity);
Entities.addEntity({
type: "Image",
name: assetProxyModel.data(treeView.selection.currentIndex),
imageURL: defaultURL,
keepAspectRatio: false,
dynamic: false,
collisionless: true,
grabbable: grabbable,
position: Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getForward(MyAvatar.orientation))),
gravity: Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0)
});
} else {
var SHAPE_TYPE_NONE = 0;
var SHAPE_TYPE_SIMPLE_HULL = 1;

View file

@ -15,6 +15,7 @@ Item {
property var openBrowser: null;
property string subMenu: ""
signal showDesktop();
signal screenChanged(var type, var url);
property bool shown: true
property int currentApp: -1;
property alias tabletApps: tabletApps
@ -113,6 +114,8 @@ Item {
if (loader.item.hasOwnProperty("gotoPreviousApp")) {
loader.item.gotoPreviousApp = true;
}
screenChanged("Web", url)
});
}
}
@ -266,6 +269,24 @@ Item {
if (callback) {
callback();
}
var type = "Unknown";
if (newSource === "") {
type = "Closed";
} else if (newSource === "hifi/tablet/TabletMenu.qml") {
type = "Menu";
} else if (newSource === "hifi/tablet/TabletHome.qml") {
type = "Home";
} else if (newSource === "hifi/tablet/TabletWebView.qml") {
// Handled in `callback()`
return;
} else if (newSource.toLowerCase().indexOf(".qml") > -1) {
type = "QML";
} else {
console.log("newSource is of unknown type!");
}
screenChanged(type, newSource);
});
}
}

View file

@ -20,6 +20,7 @@ Windows.ScrollingWindow {
id: tabletRoot
objectName: "tabletRoot"
property string username: "Unknown user"
signal screenChanged(var type, var url);
property var rootMenu;
property string subMenu: ""
@ -69,6 +70,8 @@ Windows.ScrollingWindow {
if (loader.item.hasOwnProperty("closeButtonVisible")) {
loader.item.closeButtonVisible = false;
}
screenChanged("Web", url);
});
}
@ -179,7 +182,25 @@ Windows.ScrollingWindow {
if (callback) {
callback();
}
var type = "Unknown";
if (newSource === "") {
type = "Closed";
} else if (newSource === "hifi/tablet/TabletMenu.qml") {
type = "Menu";
} else if (newSource === "hifi/tablet/TabletHome.qml") {
type = "Home";
} else if (newSource === "hifi/tablet/TabletWebView.qml") {
// Handled in `callback()`
return;
} else if (newSource.toLowerCase().indexOf(".qml") > -1) {
type = "QML";
} else {
console.log("newSource is of unknown type!");
}
screenChanged(type, newSource);
});
}
}

View file

@ -2315,6 +2315,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
DependencyManager::get<PickManager>()->setPrecisionPicking(rayPickID, value);
});
EntityTreeRenderer::setGetAvatarUpOperator([] {
return DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * Vectors::UP;
});
// Preload Tablet sounds
DependencyManager::get<TabletScriptingInterface>()->preloadSounds();
DependencyManager::get<Keyboard>()->createKeyboard();
@ -2460,6 +2464,10 @@ void Application::updateHeartbeat() const {
void Application::onAboutToQuit() {
emit beforeAboutToQuit();
if (getLoginDialogPoppedUp() && _firstRun.get()) {
_firstRun.set(false);
}
foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) {
if (inputPlugin->isActive()) {
inputPlugin->deactivate();
@ -5252,7 +5260,8 @@ void Application::resumeAfterLoginDialogActionTaken() {
// this will force the model the look at the correct directory (weird order of operations issue)
scriptEngines->reloadLocalFiles();
if (!_defaultScriptsLocation.exists()) {
// if the --scripts command-line argument was used.
if (!_defaultScriptsLocation.exists() && (arguments().indexOf(QString("--").append(SCRIPTS_SWITCH))) != -1) {
scriptEngines->loadDefaultScripts();
scriptEngines->defaultScriptsLocationOverridden(true);
} else {
@ -5260,39 +5269,25 @@ void Application::resumeAfterLoginDialogActionTaken() {
}
}
if (_firstRun.get()) {
// not first run anymore since action was taken.
_firstRun.set(false);
}
auto accountManager = DependencyManager::get<AccountManager>();
auto addressManager = DependencyManager::get<AddressManager>();
// restart domain handler.
nodeList->getDomainHandler().resetting();
if (!accountManager->isLoggedIn()) {
QVariant testProperty = property(hifi::properties::TEST);
if (testProperty.isValid()) {
const auto testScript = property(hifi::properties::TEST).toUrl();
// Set last parameter to exit interface when the test script finishes, if so requested
DependencyManager::get<ScriptEngines>()->loadScript(testScript, false, false, false, false, quitWhenFinished);
// This is done so we don't get a "connection time-out" message when we haven't passed in a URL.
if (arguments().contains("--url")) {
auto reply = SandboxUtils::getStatus();
connect(reply, &QNetworkReply::finished, this, [this, reply] { handleSandboxStatus(reply); });
} else {
addressManager->goToEntry();
}
} else {
QVariant testProperty = property(hifi::properties::TEST);
if (testProperty.isValid()) {
const auto testScript = property(hifi::properties::TEST).toUrl();
// Set last parameter to exit interface when the test script finishes, if so requested
DependencyManager::get<ScriptEngines>()->loadScript(testScript, false, false, false, false, quitWhenFinished);
// This is done so we don't get a "connection time-out" message when we haven't passed in a URL.
if (arguments().contains("--url")) {
auto reply = SandboxUtils::getStatus();
connect(reply, &QNetworkReply::finished, this, [this, reply] { handleSandboxStatus(reply); });
}
} else {
auto reply = SandboxUtils::getStatus();
connect(reply, &QNetworkReply::finished, this, [this, reply] { handleSandboxStatus(reply); });
}
auto reply = SandboxUtils::getStatus();
connect(reply, &QNetworkReply::finished, this, [this, reply] { handleSandboxStatus(reply); });
}
auto menu = Menu::getInstance();
@ -7698,16 +7693,13 @@ void Application::addAssetToWorldSetMapping(QString filePath, QString mapping, Q
void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) {
EntityItemProperties properties;
properties.setType(EntityTypes::Model);
properties.setName(mapping.right(mapping.length() - 1));
if (filePath.toLower().endsWith(PNG_EXTENSION) || filePath.toLower().endsWith(JPG_EXTENSION)) {
QJsonObject textures {
{"tex.picture", QString("atp:" + mapping) }
};
properties.setModelURL("https://hifi-content.s3.amazonaws.com/DomainContent/production/default-image-model.fbx");
properties.setTextures(QJsonDocument(textures).toJson(QJsonDocument::Compact));
properties.setShapeType(SHAPE_TYPE_BOX);
properties.setType(EntityTypes::Image);
properties.setImageURL(QString("atp:" + mapping));
properties.setKeepAspectRatio(false);
} else {
properties.setType(EntityTypes::Model);
properties.setModelURL("atp:" + mapping);
properties.setShapeType(SHAPE_TYPE_SIMPLE_COMPOUND);
}

View file

@ -2418,10 +2418,10 @@ void MyAvatar::attachmentDataToEntityProperties(const AttachmentData& data, Enti
void MyAvatar::initHeadBones() {
int neckJointIndex = -1;
if (_skeletonModel->isLoaded()) {
neckJointIndex = _skeletonModel->getHFMModel().neckJointIndex;
neckJointIndex = getJointIndex("Neck");
}
if (neckJointIndex == -1) {
neckJointIndex = (_skeletonModel->getHFMModel().headJointIndex - 1);
neckJointIndex = (getJointIndex("Head") - 1);
if (neckJointIndex < 0) {
// return if the head is not even there. can't cauterize!!
return;

View file

@ -301,8 +301,8 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
eyeParams.eyeSaccade = head->getSaccade();
eyeParams.modelRotation = getRotation();
eyeParams.modelTranslation = getTranslation();
eyeParams.leftEyeJointIndex = hfmModel.leftEyeJointIndex;
eyeParams.rightEyeJointIndex = hfmModel.rightEyeJointIndex;
eyeParams.leftEyeJointIndex = _rig.indexOfJoint("LeftEye");
eyeParams.rightEyeJointIndex = _rig.indexOfJoint("RightEye");
_rig.updateFromEyeParameters(eyeParams);

View file

@ -95,7 +95,12 @@ void LoginDialog::toggleAction() {
} else {
// change the menu item to login
loginAction->setText("Log In / Sign Up");
connection = connect(loginAction, &QAction::triggered, [] { LoginDialog::showWithSelection(); });
connection = connect(loginAction, &QAction::triggered, [] {
// if not in login state, show.
if (!qApp->getLoginDialogPoppedUp()) {
LoginDialog::showWithSelection();
}
});
}
}

View file

@ -82,18 +82,21 @@ void Image3DOverlay::render(RenderArgs* args) {
float imageHeight = _texture->getHeight();
QRect fromImage;
if (_fromImage.isNull()) {
if (_fromImage.width() <= 0) {
fromImage.setX(0);
fromImage.setY(0);
fromImage.setWidth(imageWidth);
fromImage.setHeight(imageHeight);
} else {
float scaleX = imageWidth / _texture->getOriginalWidth();
float scaleY = imageHeight / _texture->getOriginalHeight();
fromImage.setX(scaleX * _fromImage.x());
fromImage.setY(scaleY * _fromImage.y());
fromImage.setWidth(scaleX * _fromImage.width());
}
if (_fromImage.height() <= 0) {
fromImage.setY(0);
fromImage.setHeight(imageHeight);
} else {
float scaleY = imageHeight / _texture->getOriginalHeight();
fromImage.setY(scaleY * _fromImage.y());
fromImage.setHeight(scaleY * _fromImage.height());
}
@ -247,9 +250,6 @@ QVariant Image3DOverlay::getProperty(const QString& property) {
if (property == "subImage") {
return _fromImage;
}
if (property == "offsetPosition") {
return vec3toVariant(getOffsetPosition());
}
if (property == "emissive") {
return _emissive;
}

View file

@ -343,18 +343,18 @@ void Rig::initJointStates(const HFMModel& hfmModel, const glm::mat4& modelOffset
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
_rootJointIndex = hfmModel.rootJointIndex;
_leftEyeJointIndex = hfmModel.leftEyeJointIndex;
_rightEyeJointIndex = hfmModel.rightEyeJointIndex;
_leftHandJointIndex = hfmModel.leftHandJointIndex;
_rootJointIndex = indexOfJoint("Hips");
_leftEyeJointIndex = indexOfJoint("LeftEye");
_rightEyeJointIndex = indexOfJoint("RightEye");
_leftHandJointIndex = indexOfJoint("LeftHand");
_leftElbowJointIndex = _leftHandJointIndex >= 0 ? hfmModel.joints.at(_leftHandJointIndex).parentIndex : -1;
_leftShoulderJointIndex = _leftElbowJointIndex >= 0 ? hfmModel.joints.at(_leftElbowJointIndex).parentIndex : -1;
_rightHandJointIndex = hfmModel.rightHandJointIndex;
_rightHandJointIndex = indexOfJoint("RightHand");
_rightElbowJointIndex = _rightHandJointIndex >= 0 ? hfmModel.joints.at(_rightHandJointIndex).parentIndex : -1;
_rightShoulderJointIndex = _rightElbowJointIndex >= 0 ? hfmModel.joints.at(_rightElbowJointIndex).parentIndex : -1;
_leftEyeJointChildren = _animSkeleton->getChildrenOfJoint(hfmModel.leftEyeJointIndex);
_rightEyeJointChildren = _animSkeleton->getChildrenOfJoint(hfmModel.rightEyeJointIndex);
_leftEyeJointChildren = _animSkeleton->getChildrenOfJoint(indexOfJoint("LeftEye"));
_rightEyeJointChildren = _animSkeleton->getChildrenOfJoint(indexOfJoint("RightEye"));
}
void Rig::reset(const HFMModel& hfmModel) {
@ -390,18 +390,18 @@ void Rig::reset(const HFMModel& hfmModel) {
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
_rootJointIndex = hfmModel.rootJointIndex;
_leftEyeJointIndex = hfmModel.leftEyeJointIndex;
_rightEyeJointIndex = hfmModel.rightEyeJointIndex;
_leftHandJointIndex = hfmModel.leftHandJointIndex;
_rootJointIndex = indexOfJoint("Hips");;
_leftEyeJointIndex = indexOfJoint("LeftEye");
_rightEyeJointIndex = indexOfJoint("RightEye");
_leftHandJointIndex = indexOfJoint("LeftHand");
_leftElbowJointIndex = _leftHandJointIndex >= 0 ? hfmModel.joints.at(_leftHandJointIndex).parentIndex : -1;
_leftShoulderJointIndex = _leftElbowJointIndex >= 0 ? hfmModel.joints.at(_leftElbowJointIndex).parentIndex : -1;
_rightHandJointIndex = hfmModel.rightHandJointIndex;
_rightHandJointIndex = indexOfJoint("RightHand");
_rightElbowJointIndex = _rightHandJointIndex >= 0 ? hfmModel.joints.at(_rightHandJointIndex).parentIndex : -1;
_rightShoulderJointIndex = _rightElbowJointIndex >= 0 ? hfmModel.joints.at(_rightElbowJointIndex).parentIndex : -1;
_leftEyeJointChildren = _animSkeleton->getChildrenOfJoint(hfmModel.leftEyeJointIndex);
_rightEyeJointChildren = _animSkeleton->getChildrenOfJoint(hfmModel.rightEyeJointIndex);
_leftEyeJointChildren = _animSkeleton->getChildrenOfJoint(indexOfJoint("LeftEye"));
_rightEyeJointChildren = _animSkeleton->getChildrenOfJoint(indexOfJoint("RightEye"));
if (!_animGraphURL.isEmpty()) {
_animNode.reset();

View file

@ -1314,7 +1314,7 @@ glm::quat Avatar::getAbsoluteJointRotationInObjectFrame(int index) const {
case CAMERA_MATRIX_INDEX: {
glm::quat rotation;
if (_skeletonModel && _skeletonModel->isActive()) {
int headJointIndex = _skeletonModel->getHFMModel().headJointIndex;
int headJointIndex = getJointIndex("Head");
if (headJointIndex >= 0) {
_skeletonModel->getAbsoluteJointRotationInRigFrame(headJointIndex, rotation);
}
@ -1363,7 +1363,7 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const {
case CAMERA_MATRIX_INDEX: {
glm::vec3 translation;
if (_skeletonModel && _skeletonModel->isActive()) {
int headJointIndex = _skeletonModel->getHFMModel().headJointIndex;
int headJointIndex = getJointIndex("Head");
if (headJointIndex >= 0) {
_skeletonModel->getAbsoluteJointTranslationInRigFrame(headJointIndex, translation);
}

View file

@ -66,7 +66,7 @@ void SkeletonModel::initJointStates() {
}
// Determine the default eye position for avatar scale = 1.0
int headJointIndex = hfmModel.headJointIndex;
int headJointIndex = _rig.indexOfJoint("Head");
if (0 > headJointIndex || headJointIndex >= _rig.getJointStateCount()) {
qCWarning(avatars_renderer) << "Bad head joint! Got:" << headJointIndex << "jointCount:" << _rig.getJointStateCount();
}
@ -74,7 +74,7 @@ void SkeletonModel::initJointStates() {
getEyeModelPositions(leftEyePosition, rightEyePosition);
glm::vec3 midEyePosition = (leftEyePosition + rightEyePosition) / 2.0f;
int rootJointIndex = hfmModel.rootJointIndex;
int rootJointIndex = _rig.indexOfJoint("Hips");
glm::vec3 rootModelPosition;
getJointPosition(rootJointIndex, rootModelPosition);
@ -96,7 +96,6 @@ void SkeletonModel::initJointStates() {
// Called within Model::simulate call, below.
void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
assert(!_owningAvatar->isMyAvatar());
const HFMModel& hfmModel = getHFMModel();
Head* head = _owningAvatar->getHead();
@ -124,7 +123,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
// If the head is not positioned, updateEyeJoints won't get the math right
glm::quat headOrientation;
_rig.getJointRotation(hfmModel.headJointIndex, headOrientation);
_rig.getJointRotation(_rig.indexOfJoint("Head"), headOrientation);
glm::vec3 eulers = safeEulerAngles(headOrientation);
head->setBasePitch(glm::degrees(-eulers.x));
head->setBaseYaw(glm::degrees(eulers.y));
@ -135,8 +134,8 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
eyeParams.eyeSaccade = glm::vec3(0.0f);
eyeParams.modelRotation = getRotation();
eyeParams.modelTranslation = getTranslation();
eyeParams.leftEyeJointIndex = hfmModel.leftEyeJointIndex;
eyeParams.rightEyeJointIndex = hfmModel.rightEyeJointIndex;
eyeParams.leftEyeJointIndex = _rig.indexOfJoint("LeftEye");
eyeParams.rightEyeJointIndex = _rig.indexOfJoint("RightEye");
_rig.updateFromEyeParameters(eyeParams);
}
@ -259,45 +258,44 @@ bool SkeletonModel::getRightShoulderPosition(glm::vec3& position) const {
}
bool SkeletonModel::getHeadPosition(glm::vec3& headPosition) const {
return isActive() && getJointPositionInWorldFrame(getHFMModel().headJointIndex, headPosition);
return isActive() && getJointPositionInWorldFrame(_rig.indexOfJoint("Head"), headPosition);
}
bool SkeletonModel::getNeckPosition(glm::vec3& neckPosition) const {
return isActive() && getJointPositionInWorldFrame(getHFMModel().neckJointIndex, neckPosition);
return isActive() && getJointPositionInWorldFrame(_rig.indexOfJoint("Neck"), neckPosition);
}
bool SkeletonModel::getLocalNeckPosition(glm::vec3& neckPosition) const {
return isActive() && getJointPosition(getHFMModel().neckJointIndex, neckPosition);
return isActive() && getJointPosition(_rig.indexOfJoint("Neck"), neckPosition);
}
bool SkeletonModel::getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
if (!isActive()) {
return false;
}
const HFMModel& hfmModel = getHFMModel();
if (getJointPosition(hfmModel.leftEyeJointIndex, firstEyePosition) &&
getJointPosition(hfmModel.rightEyeJointIndex, secondEyePosition)) {
if (getJointPosition(_rig.indexOfJoint("LeftEye"), firstEyePosition) &&
getJointPosition(_rig.indexOfJoint("RightEye"), secondEyePosition)) {
return true;
}
// no eye joints; try to estimate based on head/neck joints
glm::vec3 neckPosition, headPosition;
if (getJointPosition(hfmModel.neckJointIndex, neckPosition) &&
getJointPosition(hfmModel.headJointIndex, headPosition)) {
if (getJointPosition(_rig.indexOfJoint("Neck"), neckPosition) &&
getJointPosition(_rig.indexOfJoint("Head"), headPosition)) {
const float EYE_PROPORTION = 0.6f;
glm::vec3 baseEyePosition = glm::mix(neckPosition, headPosition, EYE_PROPORTION);
glm::quat headRotation;
getJointRotation(hfmModel.headJointIndex, headRotation);
getJointRotation(_rig.indexOfJoint("Head"), headRotation);
const float EYES_FORWARD = 0.25f;
const float EYE_SEPARATION = 0.1f;
float headHeight = glm::distance(neckPosition, headPosition);
firstEyePosition = baseEyePosition + headRotation * glm::vec3(EYE_SEPARATION, 0.0f, EYES_FORWARD) * headHeight;
secondEyePosition = baseEyePosition + headRotation * glm::vec3(-EYE_SEPARATION, 0.0f, EYES_FORWARD) * headHeight;
return true;
} else if (getJointPosition(hfmModel.headJointIndex, headPosition)) {
} else if (getJointPosition(_rig.indexOfJoint("Head"), headPosition)) {
glm::vec3 baseEyePosition = headPosition;
glm::quat headRotation;
getJointRotation(hfmModel.headJointIndex, headRotation);
getJointRotation(_rig.indexOfJoint("Head"), headRotation);
const float EYES_FORWARD_HEAD_ONLY = 0.30f;
const float EYE_SEPARATION = 0.1f;
firstEyePosition = baseEyePosition + headRotation * glm::vec3(EYE_SEPARATION, 0.0f, EYES_FORWARD_HEAD_ONLY);
@ -331,7 +329,7 @@ void SkeletonModel::computeBoundingShape() {
}
const HFMModel& hfmModel = getHFMModel();
if (hfmModel.joints.isEmpty() || hfmModel.rootJointIndex == -1) {
if (hfmModel.joints.isEmpty() || _rig.indexOfJoint("Hips") == -1) {
// rootJointIndex == -1 if the avatar model has no skeleton
return;
}
@ -369,7 +367,7 @@ void SkeletonModel::renderBoundingCollisionShapes(RenderArgs* args, gpu::Batch&
}
bool SkeletonModel::hasSkeleton() {
return isActive() ? getHFMModel().rootJointIndex != -1 : false;
return isActive() ? _rig.indexOfJoint("Hips") != -1 : false;
}
void SkeletonModel::onInvalidate() {

View file

@ -41,10 +41,10 @@ public:
void updateAttitude(const glm::quat& orientation);
/// Returns the index of the left hand joint, or -1 if not found.
int getLeftHandJointIndex() const { return isActive() ? getHFMModel().leftHandJointIndex : -1; }
int getLeftHandJointIndex() const { return isActive() ? _rig.indexOfJoint("LeftHand") : -1; }
/// Returns the index of the right hand joint, or -1 if not found.
int getRightHandJointIndex() const { return isActive() ? getHFMModel().rightHandJointIndex : -1; }
int getRightHandJointIndex() const { return isActive() ? _rig.indexOfJoint("RightHand") : -1; }
bool getLeftGrabPosition(glm::vec3& position) const;
bool getRightGrabPosition(glm::vec3& position) const;

View file

@ -41,6 +41,7 @@
#include <PointerManager.h>
std::function<bool()> EntityTreeRenderer::_entitiesShouldFadeFunction = []() { return true; };
std::function<glm::vec3()> EntityTreeRenderer::_getAvatarUpOperator = []() { return Vectors::UP; };
QString resolveScriptURL(const QString& scriptUrl) {
auto normalizedScriptUrl = DependencyManager::get<ResourceManager>()->normalizeURL(scriptUrl);
@ -61,8 +62,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
_lastPointerEventValid(false),
_viewState(viewState),
_scriptingServices(scriptingServices),
_displayModelBounds(false),
_layeredZones(this)
_displayModelBounds(false)
{
setMouseRayPickResultOperator([](unsigned int rayPickID) {
RayToEntityIntersectionResult entityResult;
@ -516,41 +516,36 @@ bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVector<EntityIt
auto hasScript = !entity->getScript().isEmpty();
// only consider entities that are zones or have scripts, all other entities can
// be ignored because they can have events fired on them.
// be ignored because they can't have events fired on them.
// FIXME - this could be optimized further by determining if the script is loaded
// and if it has either an enterEntity or leaveEntity method
//
// also, don't flag a scripted entity as containing the avatar until the script is loaded,
// so that the script is awake in time to receive the "entityEntity" call (even if the entity is a zone).
if ((!hasScript && isZone) ||
(hasScript && entity->isScriptPreloadFinished())) {
// now check to see if the point contains our entity, this can be expensive if
// the entity has a collision hull
if (entity->contains(_avatarPosition)) {
bool contains = false;
bool scriptHasLoaded = hasScript && entity->isScriptPreloadFinished();
if (isZone || scriptHasLoaded) {
contains = entity->contains(_avatarPosition);
}
if (contains) {
// if this entity is a zone and visible, add it to our layered zones
if (isZone && entity->getVisible() && renderableForEntity(entity)) {
_layeredZones.insert(std::dynamic_pointer_cast<ZoneEntityItem>(entity));
}
if ((!hasScript && isZone) || scriptHasLoaded) {
if (entitiesContainingAvatar) {
*entitiesContainingAvatar << entity->getEntityItemID();
}
// if this entity is a zone and visible, determine if it is the bestZone
if (isZone && entity->getVisible() && renderableForEntity(entity)) {
auto zone = std::dynamic_pointer_cast<ZoneEntityItem>(entity);
_layeredZones.insert(zone);
}
}
}
}
}
// check if our layered zones have changed
if (_layeredZones.empty()) {
if (oldLayeredZones.empty()) {
return;
}
} else if (!oldLayeredZones.empty()) {
if (_layeredZones.contains(oldLayeredZones)) {
return;
}
if ((_layeredZones.empty() && oldLayeredZones.empty()) || (!oldLayeredZones.empty() && _layeredZones.contains(oldLayeredZones))) {
return;
}
_layeredZones.apply();
applyLayeredZones();
@ -653,8 +648,8 @@ bool EntityTreeRenderer::applyLayeredZones() {
} else {
qCWarning(entitiesrenderer) << "EntityTreeRenderer::applyLayeredZones(), Unexpected null scene, possibly during application shutdown";
}
return true;
return true;
}
void EntityTreeRenderer::processEraseMessage(ReceivedMessage& message, const SharedNodePointer& sourceNode) {
@ -1151,18 +1146,12 @@ std::pair<EntityTreeRenderer::LayeredZones::iterator, bool> EntityTreeRenderer::
return { it, success };
}
void EntityTreeRenderer::LayeredZones::apply() {
assert(_entityTreeRenderer);
}
void EntityTreeRenderer::LayeredZones::update(std::shared_ptr<ZoneEntityItem> zone) {
assert(_entityTreeRenderer);
bool isVisible = zone->isVisible();
if (empty() && isVisible) {
// there are no zones: set this one
insert(zone);
apply();
return;
} else {
LayeredZone zoneLayer(zone);

View file

@ -117,6 +117,9 @@ public:
// Access the workload Space
workload::SpacePointer getWorkloadSpace() const { return _space; }
static void setGetAvatarUpOperator(std::function<glm::vec3()> getAvatarUpOperator) { _getAvatarUpOperator = getAvatarUpOperator; }
static glm::vec3 getAvatarUp() { return _getAvatarUpOperator(); }
signals:
void enterEntity(const EntityItemID& entityItemID);
void leaveEntity(const EntityItemID& entityItemID);
@ -205,42 +208,28 @@ private:
class LayeredZones : public std::set<LayeredZone> {
public:
LayeredZones(EntityTreeRenderer* parent) : _entityTreeRenderer(parent) {}
LayeredZones() {};
LayeredZones(LayeredZones&& other);
// avoid accidental misconstruction
LayeredZones() = delete;
LayeredZones(const LayeredZones&) = delete;
LayeredZones& operator=(const LayeredZones&) = delete;
LayeredZones& operator=(LayeredZones&&) = delete;
void clear();
std::pair<iterator, bool> insert(const LayeredZone& layer);
void apply();
void update(std::shared_ptr<ZoneEntityItem> zone);
bool contains(const LayeredZones& other);
std::shared_ptr<ZoneEntityItem> getZone() { return empty() ? nullptr : begin()->zone; }
private:
void applyPartial(iterator layer);
std::map<QUuid, iterator> _map;
iterator _skyboxLayer{ end() };
EntityTreeRenderer* _entityTreeRenderer;
iterator _skyboxLayer { end() };
};
LayeredZones _layeredZones;
QString _zoneUserData;
NetworkTexturePointer _ambientTexture;
NetworkTexturePointer _skyboxTexture;
QString _ambientTextureURL;
QString _skyboxTextureURL;
float _avgRenderableUpdateCost { 0.0f };
bool _pendingAmbientTexture { false };
bool _pendingSkyboxTexture { false };
uint64_t _lastZoneCheck { 0 };
const uint64_t ZONE_CHECK_INTERVAL = USECS_PER_MSEC * 100; // ~10hz
@ -262,6 +251,8 @@ private:
mutable std::mutex _spaceLock;
workload::SpacePointer _space{ new workload::Space() };
workload::Transaction::Updates _spaceUpdates;
static std::function<glm::vec3()> _getAvatarUpOperator;
};

View file

@ -25,6 +25,7 @@
#include "RenderableWebEntityItem.h"
#include "RenderableZoneEntityItem.h"
#include "RenderableMaterialEntityItem.h"
#include "RenderableImageEntityItem.h"
using namespace render;
@ -217,22 +218,39 @@ EntityRenderer::Pointer EntityRenderer::addToScene(EntityTreeRenderer& renderer,
using Type = EntityTypes::EntityType_t;
auto type = entity->getType();
switch (type) {
case Type::Light:
result = make_renderer<LightEntityRenderer>(entity);
break;
case Type::Line:
result = make_renderer<LineEntityRenderer>(entity);
case Type::Shape:
case Type::Box:
case Type::Sphere:
result = make_renderer<ShapeEntityRenderer>(entity);
break;
case Type::Model:
result = make_renderer<ModelEntityRenderer>(entity);
break;
case Type::Text:
result = make_renderer<TextEntityRenderer>(entity);
break;
case Type::Image:
result = make_renderer<ImageEntityRenderer>(entity);
break;
case Type::Web:
if (!nsightActive()) {
result = make_renderer<WebEntityRenderer>(entity);
}
break;
case Type::ParticleEffect:
result = make_renderer<ParticleEffectEntityRenderer>(entity);
break;
case Type::Line:
result = make_renderer<LineEntityRenderer>(entity);
break;
case Type::PolyLine:
result = make_renderer<PolyLineEntityRenderer>(entity);
break;
@ -241,20 +259,8 @@ EntityRenderer::Pointer EntityRenderer::addToScene(EntityTreeRenderer& renderer,
result = make_renderer<PolyVoxEntityRenderer>(entity);
break;
case Type::Shape:
case Type::Box:
case Type::Sphere:
result = make_renderer<ShapeEntityRenderer>(entity);
break;
case Type::Text:
result = make_renderer<TextEntityRenderer>(entity);
break;
case Type::Web:
if (!nsightActive()) {
result = make_renderer<WebEntityRenderer>(entity);
}
case Type::Light:
result = make_renderer<LightEntityRenderer>(entity);
break;
case Type::Zone:

View file

@ -0,0 +1,218 @@
//
// Created by Sam Gondelman on 11/29/18
// Copyright 2018 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 "RenderableImageEntityItem.h"
#include <DependencyManager.h>
#include <GeometryCache.h>
using namespace render;
using namespace render::entities;
ImageEntityRenderer::ImageEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
_geometryId = DependencyManager::get<GeometryCache>()->allocateID();
}
ImageEntityRenderer::~ImageEntityRenderer() {
auto geometryCache = DependencyManager::get<GeometryCache>();
if (geometryCache) {
geometryCache->releaseID(_geometryId);
}
}
bool ImageEntityRenderer::isTransparent() const {
return Parent::isTransparent() || (_textureIsLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha()) || _alpha < 1.0f;
}
bool ImageEntityRenderer::needsRenderUpdate() const {
bool textureLoadedChanged = resultWithReadLock<bool>([&] {
return (!_textureIsLoaded && _texture && _texture->isLoaded());
});
if (textureLoadedChanged) {
return true;
}
return Parent::needsRenderUpdate();
}
bool ImageEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
bool needsUpdate = resultWithReadLock<bool>([&] {
if (_imageURL != entity->getImageURL()) {
return true;
}
if (_emissive != entity->getEmissive()) {
return true;
}
if (_keepAspectRatio != entity->getKeepAspectRatio()) {
return true;
}
if (_billboardMode != entity->getBillboardMode()) {
return true;
}
if (_subImage != entity->getSubImage()) {
return true;
}
if (_color != entity->getColor()) {
return true;
}
if (_alpha != entity->getAlpha()) {
return true;
}
return false;
});
return needsUpdate;
}
void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
withWriteLock([&] {
auto imageURL = entity->getImageURL();
if (_imageURL != imageURL) {
_imageURL = imageURL;
if (imageURL.isEmpty()) {
_texture.reset();
} else {
_texture = DependencyManager::get<TextureCache>()->getTexture(_imageURL);
}
_textureIsLoaded = false;
}
_emissive = entity->getEmissive();
_keepAspectRatio = entity->getKeepAspectRatio();
_billboardMode = entity->getBillboardMode();
_subImage = entity->getSubImage();
_color = entity->getColor();
_alpha = entity->getAlpha();
if (!_textureIsLoaded && _texture && _texture->isLoaded()) {
_textureIsLoaded = true;
}
});
void* key = (void*)this;
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() {
withWriteLock([&] {
_dimensions = entity->getScaledDimensions();
updateModelTransformAndBound();
_renderTransform = getModelTransform();
});
});
}
ShapeKey ImageEntityRenderer::getShapeKey() {
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias();
if (isTransparent()) {
builder.withTranslucent();
}
withReadLock([&] {
if (_emissive) {
builder.withUnlit();
}
});
return builder.build();
}
void ImageEntityRenderer::doRender(RenderArgs* args) {
NetworkTexturePointer texture;
QRect subImage;
glm::u8vec3 color;
glm::vec3 dimensions;
Transform transform;
withReadLock([&] {
texture = _texture;
subImage = _subImage;
color = _color;
dimensions = _dimensions;
transform = _renderTransform;
});
if (!_visible || !texture || !texture->isLoaded()) {
return;
}
Q_ASSERT(args->_batch);
gpu::Batch* batch = args->_batch;
if (_billboardMode == BillboardMode::YAW) {
//rotate about vertical to face the camera
glm::vec3 dPosition = args->getViewFrustum().getPosition() - transform.getTranslation();
// If x and z are 0, atan(x, z) is undefined, so default to 0 degrees
float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z);
glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f));
transform.setRotation(orientation);
} else if (_billboardMode == BillboardMode::FULL) {
glm::vec3 billboardPos = transform.getTranslation();
glm::vec3 cameraPos = args->getViewFrustum().getPosition();
// use the referencial from the avatar, y isn't always up
glm::vec3 avatarUP = EntityTreeRenderer::getAvatarUp();
// check to see if glm::lookAt will work / using glm::lookAt variable name
glm::highp_vec3 s(glm::cross(billboardPos - cameraPos, avatarUP));
// make sure s is not NaN for any component
if (glm::length2(s) > 0.0f) {
glm::quat rotation(conjugate(toQuat(glm::lookAt(cameraPos, billboardPos, avatarUP))));
transform.setRotation(rotation);
}
}
transform.postScale(dimensions);
batch->setModelTransform(transform);
batch->setResourceTexture(0, texture->getGPUTexture());
float imageWidth = texture->getWidth();
float imageHeight = texture->getHeight();
QRect fromImage;
if (subImage.width() <= 0) {
fromImage.setX(0);
fromImage.setWidth(imageWidth);
} else {
float scaleX = imageWidth / texture->getOriginalWidth();
fromImage.setX(scaleX * subImage.x());
fromImage.setWidth(scaleX * subImage.width());
}
if (subImage.height() <= 0) {
fromImage.setY(0);
fromImage.setHeight(imageHeight);
} else {
float scaleY = imageHeight / texture->getOriginalHeight();
fromImage.setY(scaleY * subImage.y());
fromImage.setHeight(scaleY * subImage.height());
}
float maxSize = glm::max(fromImage.width(), fromImage.height());
float x = _keepAspectRatio ? fromImage.width() / (2.0f * maxSize) : 0.5f;
float y = _keepAspectRatio ? -fromImage.height() / (2.0f * maxSize) : -0.5f;
glm::vec2 topLeft(-x, -y);
glm::vec2 bottomRight(x, y);
glm::vec2 texCoordTopLeft((fromImage.x() + 0.5f) / imageWidth, (fromImage.y() + 0.5f) / imageHeight);
glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth,
(fromImage.y() + fromImage.height() - 0.5f) / imageHeight);
glm::vec4 imageColor(toGlm(color), _alpha);
DependencyManager::get<GeometryCache>()->renderQuad(
*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
imageColor, _geometryId
);
batch->setResourceTexture(0, nullptr);
}

View file

@ -0,0 +1,56 @@
//
// Created by Sam Gondelman on 11/29/18
// Copyright 2018 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_RenderableImageEntityItem_h
#define hifi_RenderableImageEntityItem_h
#include "RenderableEntityItem.h"
#include <ImageEntityItem.h>
namespace render {
namespace entities {
class ImageEntityRenderer : public TypedEntityRenderer<ImageEntityItem> {
using Parent = TypedEntityRenderer<ImageEntityItem>;
using Pointer = std::shared_ptr<ImageEntityRenderer>;
public:
ImageEntityRenderer(const EntityItemPointer& entity);
~ImageEntityRenderer();
protected:
ShapeKey getShapeKey() override;
bool isTransparent() const override;
private:
virtual bool needsRenderUpdate() const override;
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
virtual void doRender(RenderArgs* args) override;
QString _imageURL;
NetworkTexturePointer _texture;
bool _textureIsLoaded { false };
bool _emissive;
bool _keepAspectRatio;
BillboardMode _billboardMode;
QRect _subImage;
glm::u8vec3 _color;
float _alpha;
glm::vec3 _dimensions;
int _geometryId { 0 };
};
}
}
#endif // hifi_RenderableImageEntityItem_h

View file

@ -83,34 +83,6 @@ void RenderableModelEntityItem::setUnscaledDimensions(const glm::vec3& value) {
}
}
QVariantMap parseTexturesToMap(QString textures, const QVariantMap& defaultTextures) {
// If textures are unset, revert to original textures
if (textures.isEmpty()) {
return defaultTextures;
}
// Legacy: a ,\n-delimited list of filename:"texturepath"
if (*textures.cbegin() != '{') {
textures = "{\"" + textures.replace(":\"", "\":\"").replace(",\n", ",\"") + "}";
}
QJsonParseError error;
QJsonDocument texturesJson = QJsonDocument::fromJson(textures.toUtf8(), &error);
// If textures are invalid, revert to original textures
if (error.error != QJsonParseError::NoError) {
qCWarning(entitiesrenderer) << "Could not evaluate textures property value:" << textures;
return defaultTextures;
}
QVariantMap texturesMap = texturesJson.toVariant().toMap();
// If textures are unset, revert to original textures
if (texturesMap.isEmpty()) {
return defaultTextures;
}
return texturesJson.toVariant().toMap();
}
void RenderableModelEntityItem::doInitialModelSimulation() {
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
ModelPointer model = getModel();

View file

@ -15,7 +15,6 @@
#include <GeometryCache.h>
#include <PerfStat.h>
#include <Transform.h>
#include <TextEntityItem.h>
#include <TextRenderer3D.h>
#include "GLMHelpers.h"
@ -59,7 +58,7 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint
return true;
}
if (_faceCamera != entity->getFaceCamera()) {
if (_billboardMode != entity->getBillboardMode()) {
return true;
}
return false;
@ -79,7 +78,7 @@ void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen
void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
_textColor = toGlm(entity->getTextColor());
_backgroundColor = toGlm(entity->getBackgroundColor());
_faceCamera = entity->getFaceCamera();
_billboardMode = entity->getBillboardMode();
_lineHeight = entity->getLineHeight();
_text = entity->getText();
}
@ -110,13 +109,26 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
gpu::Batch& batch = *args->_batch;
auto transformToTopLeft = modelTransform;
if (_faceCamera) {
if (_billboardMode == BillboardMode::YAW) {
//rotate about vertical to face the camera
glm::vec3 dPosition = args->getViewFrustum().getPosition() - modelTransform.getTranslation();
// If x and z are 0, atan(x, z) is undefined, so default to 0 degrees
float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z);
glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f));
transformToTopLeft.setRotation(orientation);
} else if (_billboardMode == BillboardMode::FULL) {
glm::vec3 billboardPos = transformToTopLeft.getTranslation();
glm::vec3 cameraPos = args->getViewFrustum().getPosition();
// use the referencial from the avatar, y isn't always up
glm::vec3 avatarUP = EntityTreeRenderer::getAvatarUp();
// check to see if glm::lookAt will work / using glm::lookAt variable name
glm::highp_vec3 s(glm::cross(billboardPos - cameraPos, avatarUP));
// make sure s is not NaN for any component
if (glm::length2(s) > 0.0f) {
glm::quat rotation(conjugate(toQuat(glm::lookAt(cameraPos, billboardPos, avatarUP))));
transformToTopLeft.setRotation(rotation);
}
}
transformToTopLeft.postTranslate(dimensions * glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left
transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed

View file

@ -32,7 +32,7 @@ private:
virtual void doRender(RenderArgs* args) override;
int _geometryID{ 0 };
std::shared_ptr<TextRenderer3D> _textRenderer;
bool _faceCamera;
BillboardMode _billboardMode;
glm::vec3 _dimensions;
glm::vec3 _textColor;
glm::vec3 _backgroundColor;

View file

@ -219,15 +219,6 @@ QString EntityItemProperties::getBloomModeAsString() const {
return getComponentModeAsString(_bloomMode);
}
QString EntityItemProperties::getComponentModeString(uint32_t mode) {
// return "inherit" if mode is not valid
if (mode < COMPONENT_MODE_ITEM_COUNT) {
return COMPONENT_MODES[mode].second;
} else {
return COMPONENT_MODES[COMPONENT_MODE_INHERIT].second;
}
}
std::array<ComponentPair, COMPONENT_MODE_ITEM_COUNT>::const_iterator EntityItemProperties::findComponent(const QString& mode) {
return std::find_if(COMPONENT_MODES.begin(), COMPONENT_MODES.end(), [&](const ComponentPair& pair) {
return (pair.second == mode);
@ -329,6 +320,33 @@ void EntityItemProperties::setEntityHostTypeFromString(const QString& entityHost
}
}
QHash<QString, BillboardMode> stringToBillboardModeLookup;
void addBillboardMode(BillboardMode mode) {
stringToBillboardModeLookup[BillboardModeHelpers::getNameForBillboardMode(mode)] = mode;
}
void buildStringToBillboardModeLookup() {
addBillboardMode(BillboardMode::NONE);
addBillboardMode(BillboardMode::YAW);
addBillboardMode(BillboardMode::FULL);
}
QString EntityItemProperties::getBillboardModeAsString() const {
return BillboardModeHelpers::getNameForBillboardMode(_billboardMode);
}
void EntityItemProperties::setBillboardModeFromString(const QString& materialMappingMode) {
if (stringToBillboardModeLookup.empty()) {
buildStringToBillboardModeLookup();
}
auto billboardModeItr = stringToBillboardModeLookup.find(materialMappingMode.toLower());
if (billboardModeItr != stringToBillboardModeLookup.end()) {
_billboardMode = billboardModeItr.value();
_billboardModeChanged = true;
}
}
EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
EntityPropertyFlags changedProperties;
@ -416,6 +434,11 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_SPIN_FINISH, spinFinish);
CHECK_PROPERTY_CHANGE(PROP_PARTICLE_ROTATE_WITH_ENTITY, rotateWithEntity);
CHECK_PROPERTY_CHANGE(PROP_IMAGE_URL, imageURL);
CHECK_PROPERTY_CHANGE(PROP_EMISSIVE, emissive);
CHECK_PROPERTY_CHANGE(PROP_KEEP_ASPECT_RATIO, keepAspectRatio);
CHECK_PROPERTY_CHANGE(PROP_SUB_IMAGE, subImage);
// Certifiable Properties
CHECK_PROPERTY_CHANGE(PROP_ITEM_NAME, itemName);
CHECK_PROPERTY_CHANGE(PROP_ITEM_DESCRIPTION, itemDescription);
@ -445,7 +468,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_LINE_POINTS, linePoints);
CHECK_PROPERTY_CHANGE(PROP_HREF, href);
CHECK_PROPERTY_CHANGE(PROP_DESCRIPTION, description);
CHECK_PROPERTY_CHANGE(PROP_FACE_CAMERA, faceCamera);
CHECK_PROPERTY_CHANGE(PROP_BILLBOARD_MODE, billboardMode);
CHECK_PROPERTY_CHANGE(PROP_ACTION_DATA, actionData);
CHECK_PROPERTY_CHANGE(PROP_NORMALS, normals);
CHECK_PROPERTY_CHANGE(PROP_STROKE_COLORS, strokeColors);
@ -681,18 +704,19 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
*
* @see The different entity types have additional properties as follows:
* @see {@link Entities.EntityProperties-Box|EntityProperties-Box}
* @see {@link Entities.EntityProperties-Light|EntityProperties-Light}
* @see {@link Entities.EntityProperties-Line|EntityProperties-Line}
* @see {@link Entities.EntityProperties-Material|EntityProperties-Material}
* @see {@link Entities.EntityProperties-Sphere|EntityProperties-Sphere}
* @see {@link Entities.EntityProperties-Shape|EntityProperties-Shape}
* @see {@link Entities.EntityProperties-Model|EntityProperties-Model}
* @see {@link Entities.EntityProperties-Text|EntityProperties-Text}
* @see {@link Entities.EntityProperties-Image|EntityProperties-Image}
* @see {@link Entities.EntityProperties-Web|EntityProperties-Web}
* @see {@link Entities.EntityProperties-ParticleEffect|EntityProperties-ParticleEffect}
* @see {@link Entities.EntityProperties-Line|EntityProperties-Line}
* @see {@link Entities.EntityProperties-PolyLine|EntityProperties-PolyLine}
* @see {@link Entities.EntityProperties-PolyVox|EntityProperties-PolyVox}
* @see {@link Entities.EntityProperties-Shape|EntityProperties-Shape}
* @see {@link Entities.EntityProperties-Sphere|EntityProperties-Sphere}
* @see {@link Entities.EntityProperties-Text|EntityProperties-Text}
* @see {@link Entities.EntityProperties-Web|EntityProperties-Web}
* @see {@link Entities.EntityProperties-Light|EntityProperties-Light}
* @see {@link Entities.EntityProperties-Zone|EntityProperties-Zone}
* @see {@link Entities.EntityProperties-Material|EntityProperties-Material}
*/
/**jsdoc
@ -812,7 +836,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* materialData: JSON.stringify({
* materialVersion: 1,
* materials: {
* // Can only set albedo on a Shape entity.
* // Value overrides entity's "color" property.
* albedo: [1.0, 1.0, 0] // Yellow
* }
@ -829,8 +852,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* <code>{@link Entities.EntityProperties|naturalDimensions}</code>.
* @property {Color} color=255,255,255 - <em>Currently not used.</em>
* @property {string} modelURL="" - The URL of the FBX of OBJ model. Baked FBX models' URLs end in ".baked.fbx".<br />
* Note: If the name ends with <code>"default-image-model.fbx"</code> then the entity is considered to be an "Image"
* entity, in which case the <code>textures</code> property should be set per the example.
* @property {string} textures="" - A JSON string of texture name, URL pairs used when rendering the model in place of the
* model's original textures. Use a texture name from the <code>originalTextures</code> property to override that texture.
* Only the texture names and URLs to be overridden need be specified; original textures are used where there are no
@ -876,24 +897,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* dimensions: { x: 0.0945, y: 0.0921, z: 0.0423 },
* lifetime: 300 // Delete after 5 minutes.
* });
* @example <caption>Create an "Image" entity like you can in the Create app.</caption>
* var IMAGE_MODEL = "https://hifi-content.s3.amazonaws.com/DomainContent/production/default-image-model.fbx";
* var DEFAULT_IMAGE = "https://hifi-content.s3.amazonaws.com/DomainContent/production/no-image.jpg";
* var entity = Entities.addEntity({
* type: "Model",
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.5, z: -3 })),
* rotation: MyAvatar.orientation,
* dimensions: {
* x: 0.5385,
* y: 0.2819,
* z: 0.0092
* },
* shapeType: "box",
* collisionless: true,
* modelURL: IMAGE_MODEL,
* textures: JSON.stringify({ "tex.picture": DEFAULT_IMAGE }),
* lifetime: 300 // Delete after 5 minutes
* });
*/
/**jsdoc
@ -1134,8 +1137,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* @property {number} lineHeight=0.1 - The height of each line of text (thus determining the font size).
* @property {Color} textColor=255,255,255 - The color of the text.
* @property {Color} backgroundColor=0,0,0 - The color of the background rectangle.
* @property {boolean} faceCamera=false - If <code>true</code>, the entity is oriented to face each user's camera (i.e., it
* differs for each user present).
* @property {BillboardMode} billboardMode="none" - If <code>"none"</code>, the entity is not billboarded. If <code>"yaw"</code>, the entity will be
* oriented to follow your camera around the y-axis. If <code>"full"</code> the entity will be oriented to face your camera. The following deprecated
* behavior is also supported: you can also set <code>"faceCamera"</code> to <code>true</code> to set <code>billboardMode</code> to "yaw", and you can set
* <code>"isFacingAvatar"</code> to <code>true</code> to set <code>billboardMode</code> to "full". Setting either to <code>false</code> sets the mode to "none"
* @example <caption>Create a text entity.</caption>
* var text = Entities.addEntity({
* type: "Text",
@ -1143,7 +1148,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* dimensions: { x: 0.6, y: 0.3, z: 0.01 },
* lineHeight: 0.12,
* text: "Hello\nthere!",
* faceCamera: true,
* billboardMode: "yaw",
* lifetime: 300 // Delete after 5 minutes.
* });
*/
@ -1254,6 +1259,32 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* });
*/
/**jsdoc
* The <code>"Image"</code> {@link Entities.EntityType|EntityType} displays an image on a 2D rectangle in the domain.
* It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}.
* @typedef {object} Entities.EntityProperties-Image
* @property {string} imageURL="" - The URL of the image to use.
* @property {boolean} emissive=false - Whether or not the image should be emissive (unlit).
* @property {boolean} keepAspectRatio=true - Whether or not the image should maintain its aspect ratio.
* @property {BillboardMode} billboardMode="none" - If <code>"none"</code>, the entity is not billboarded. If <code>"yaw"</code>, the entity will be
* oriented to follow your camera around the y-axis. If <code>"full"</code> the entity will be oriented to face your camera. The following deprecated
* behavior is also supported: you can also set <code>"faceCamera"</code> to <code>true</code> to set <code>billboardMode</code> to "yaw", and you can set
* <code>"isFacingAvatar"</code> to <code>true</code> to set <code>billboardMode</code> to "full". Setting either to <code>false</code> sets the mode to "none"
* @property {Rect} subImage={ x: 0, y: 0, width: -1, height: -1 } - The portion of the image to display. If width or height are -1, defaults to
* the full image in that dimension.
* @property {Color} color=255,255,255 - The color of image.
* @property {number} alpha=1 - The alpha of the image.
* @example <caption>Create a image entity.</caption>
* var image = Entities.addEntity({
* type: "Image",
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -5 })),
* dimensions: { x: 0.6, y: 0.3, z: 0.01 },
* imageURL: "https://images.pexels.com/photos/1020315/pexels-photo-1020315.jpeg",
* billboardMode: "yaw",
* lifetime: 300 // Delete after 5 minutes.
* });
*/
QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool skipDefaults, bool allowUnknownCreateTime,
bool strictSemantics, EntityPsuedoPropertyFlags psueudoPropertyFlags) const {
@ -1329,11 +1360,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROXY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_DYNAMIC, dynamic, collisionsWillMove, getDynamic()); // legacy support
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_HREF, href);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DESCRIPTION, description);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FACE_CAMERA, faceCamera); // Text only.
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ACTION_DATA, actionData);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCKED, locked);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USER_DATA, userData);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera);
// Certifiable Properties
@ -1354,33 +1383,44 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
// Particles only
if (_type == EntityTypes::ParticleEffect) {
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMITTING_PARTICLES, isEmitting);
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, getShapeTypeAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAX_PARTICLES, maxParticles);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LIFESPAN, lifespan);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMITTING_PARTICLES, isEmitting);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_RATE, emitRate);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_SPEED, emitSpeed);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SPEED_SPREAD, speedSpread);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_ORIENTATION, emitOrientation);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_DIMENSIONS, emitDimensions);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_RADIUS_START, emitRadiusStart);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_POLAR_START, polarStart);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_POLAR_FINISH, polarFinish);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_AZIMUTH_START, azimuthStart);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_AZIMUTH_FINISH, azimuthFinish);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_ACCELERATION, emitAcceleration);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ACCELERATION_SPREAD, accelerationSpread);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARTICLE_RADIUS, particleRadius);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RADIUS_SPREAD, radiusSpread);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RADIUS_START, radiusStart);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RADIUS_FINISH, radiusFinish);
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR_SPREAD, colorSpread, u8vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR_START, colorStart, vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR_FINISH, colorFinish, vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_SPREAD, alphaSpread);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_START, alphaStart);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_FINISH, alphaFinish);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMITTER_SHOULD_TRAIL, emitterShouldTrail);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARTICLE_SPIN, particleSpin);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SPIN_SPREAD, spinSpread);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SPIN_START, spinStart);
@ -1390,22 +1430,21 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
// Models only
if (_type == EntityTypes::Model) {
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MODEL_URL, modelURL);
if (!psuedoPropertyFlagsButDesiredEmpty) {
_animation.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
}
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures);
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, getShapeTypeAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS_SET, jointRotationsSet);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS, jointRotations);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_TRANSLATIONS_SET, jointTranslationsSet);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_TRANSLATIONS, jointTranslations);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RELAY_PARENT_JOINTS, relayParentJoints);
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
if (!psuedoPropertyFlagsButDesiredEmpty) {
_animation.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
}
}
if (_type == EntityTypes::Model || _type == EntityTypes::Zone || _type == EntityTypes::ParticleEffect) {
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, getShapeTypeAsString());
}
// FIXME: Shouldn't provide a shapeType property for Box and Sphere entities.
if (_type == EntityTypes::Box) {
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, QString("Box"));
@ -1417,26 +1456,17 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
if (_type == EntityTypes::Box || _type == EntityTypes::Sphere || _type == EntityTypes::Shape) {
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SHAPE, shape);
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
}
// FIXME - it seems like ParticleEffect should also support this
if (_type == EntityTypes::Model || _type == EntityTypes::Zone) {
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
}
// Models & Particles
if (_type == EntityTypes::Model || _type == EntityTypes::ParticleEffect) {
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
}
// Lights only
if (_type == EntityTypes::Light) {
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IS_SPOTLIGHT, isSpotlight);
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_INTENSITY, intensity);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FALLOFF_RADIUS, falloffRadius);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EXPONENT, exponent);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CUTOFF, cutoff);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FALLOFF_RADIUS, falloffRadius);
}
// Text only
@ -1445,6 +1475,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_HEIGHT, lineHeight);
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_TYPED(PROP_TEXT_COLOR, textColor, getTextColor(), u8vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_TYPED(PROP_BACKGROUND_COLOR, backgroundColor, getBackgroundColor(), u8vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString());
}
// Zones only
@ -1452,24 +1483,22 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
if (!psuedoPropertyFlagsButDesiredEmpty) {
_keyLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
_ambientLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
_skybox.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
_haze.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
_bloom.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
}
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, getShapeTypeAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FLYING_ALLOWED, flyingAllowed);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GHOSTING_ALLOWED, ghostingAllowed);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FILTER_URL, filterURL);
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_HAZE_MODE, hazeMode, getHazeModeAsString());
if (!psuedoPropertyFlagsButDesiredEmpty) {
_haze.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
}
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BLOOM_MODE, bloomMode, getBloomModeAsString());
if (!psuedoPropertyFlagsButDesiredEmpty) {
_bloom.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
}
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_KEY_LIGHT_MODE, keyLightMode, getKeyLightModeAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_AMBIENT_LIGHT_MODE, ambientLightMode, getAmbientLightModeAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SKYBOX_MODE, skyboxMode, getSkyboxModeAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_HAZE_MODE, hazeMode, getHazeModeAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BLOOM_MODE, bloomMode, getBloomModeAsString());
}
// Web only
@ -1497,15 +1526,22 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
}
// Lines & PolyLines
if (_type == EntityTypes::Line || _type == EntityTypes::PolyLine) {
if (_type == EntityTypes::Line) {
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_WIDTH, lineWidth);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_POINTS, linePoints);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_NORMALS, normals); // Polyline only.
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_STROKE_COLORS, strokeColors, qVectorVec3Color); // Polyline only.
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_STROKE_WIDTHS, strokeWidths); // Polyline only.
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures); // Polyline only.
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IS_UV_MODE_STRETCH, isUVModeStretch); // Polyline only.
}
if (_type == EntityTypes::PolyLine) {
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_WIDTH, lineWidth);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_POINTS, linePoints);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_NORMALS, normals);
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_STROKE_COLORS, strokeColors, qVectorVec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_STROKE_WIDTHS, strokeWidths);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IS_UV_MODE_STRETCH, isUVModeStretch);
}
// Materials
@ -1521,6 +1557,26 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_REPEAT, materialRepeat);
}
// Image only
if (_type == EntityTypes::Image) {
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IMAGE_URL, imageURL);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMISSIVE, emissive);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_KEEP_ASPECT_RATIO, keepAspectRatio);
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SUB_IMAGE, subImage);
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
// Handle conversions to old 'textures' property from "imageURL"
if (((!psuedoPropertyFlagsButDesiredEmpty && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(PROP_IMAGE_URL)) &&
(!skipDefaults || defaultEntityProperties._imageURL != _imageURL)) {
QScriptValue textures = engine->newObject();
textures.setProperty("tex.picture", _imageURL);
properties.setProperty("textures", textures);
}
}
/**jsdoc
* The axis-aligned bounding box of an entity.
* @typedef {object} Entities.BoundingBox
@ -1611,6 +1667,13 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
properties.setProperty("localEntity", convertScriptValue(engine, getEntityHostType() == entity::HostType::LOCAL));
}
if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::FaceCamera)) {
properties.setProperty("faceCamera", convertScriptValue(engine, getBillboardMode() == BillboardMode::YAW));
}
if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::IsFacingAvatar)) {
properties.setProperty("isFacingAvatar", convertScriptValue(engine, getBillboardMode() == BillboardMode::FULL));
}
// FIXME - I don't think these properties are supported any more
//COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha);
@ -1651,7 +1714,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaSpread, float, setAlphaSpread);
COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaStart, float, setAlphaStart);
COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaFinish, float, setAlphaFinish);
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitterShouldTrail , bool, setEmitterShouldTrail);
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitterShouldTrail, bool, setEmitterShouldTrail);
COPY_PROPERTY_FROM_QSCRIPTVALUE(modelURL, QString, setModelURL);
COPY_PROPERTY_FROM_QSCRIPTVALUE(compoundShapeURL, QString, setCompoundShapeURL);
COPY_PROPERTY_FROM_QSCRIPTVALUE(localRenderAlpha, float, setLocalRenderAlpha);
@ -1740,20 +1803,24 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(linePoints, qVectorVec3, setLinePoints);
COPY_PROPERTY_FROM_QSCRIPTVALUE(href, QString, setHref);
COPY_PROPERTY_FROM_QSCRIPTVALUE(description, QString, setDescription);
COPY_PROPERTY_FROM_QSCRIPTVALUE(faceCamera, bool, setFaceCamera);
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(billboardMode, BillboardMode);
COPY_PROPERTY_FROM_QSCRIPTVALUE(actionData, QByteArray, setActionData);
COPY_PROPERTY_FROM_QSCRIPTVALUE(normals, qVectorVec3, setNormals);
COPY_PROPERTY_FROM_QSCRIPTVALUE(strokeColors, qVectorVec3, setStrokeColors);
COPY_PROPERTY_FROM_QSCRIPTVALUE(strokeWidths,qVectorFloat, setStrokeWidths);
COPY_PROPERTY_FROM_QSCRIPTVALUE(strokeWidths, qVectorFloat, setStrokeWidths);
COPY_PROPERTY_FROM_QSCRIPTVALUE(isUVModeStretch, bool, setIsUVModeStretch);
COPY_PROPERTY_FROM_QSCRIPTVALUE(imageURL, QString, setImageURL);
COPY_PROPERTY_FROM_QSCRIPTVALUE(emissive, bool, setEmissive);
COPY_PROPERTY_FROM_QSCRIPTVALUE(keepAspectRatio, bool, setKeepAspectRatio);
COPY_PROPERTY_FROM_QSCRIPTVALUE(subImage, QRect, setSubImage);
if (!honorReadOnly) {
// this is used by the json reader to set things that we don't want javascript to able to affect.
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(created, QDateTime, setCreated, [this]() {
auto result = QDateTime::fromMSecsSinceEpoch(_created / 1000, Qt::UTC); // usec per msec
return result;
});
auto result = QDateTime::fromMSecsSinceEpoch(_created / 1000, Qt::UTC); // usec per msec
return result;
});
// TODO: expose this to QScriptValue for JSON saves?
//COPY_PROPERTY_FROM_QSCRIPTVALUE(simulationOwner, ???, setSimulatorPriority);
}
@ -1810,6 +1877,47 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneAvatarEntity, bool, setCloneAvatarEntity);
COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneOriginID, QUuid, setCloneOriginID);
// Handle conversions from old 'textures' property to "imageURL"
{
QScriptValue V = object.property("textures");
if (_type == EntityTypes::Image && V.isValid() && !object.property("imageURL").isValid()) {
bool isValid = false;
QString textures = QString_convertFromScriptValue(V, isValid);
if (isValid) {
QVariantMap texturesMap = parseTexturesToMap(textures, QVariantMap());
auto texPicture = texturesMap.find("tex.picture");
if (texPicture != texturesMap.end()) {
auto imageURL = texPicture.value().toString();
if (_defaultSettings || imageURL != _imageURL) {
setImageURL(imageURL);
}
}
}
}
}
// Handle old "faceCamera" and "isFacingAvatar" props
{
QScriptValue P = object.property("faceCamera");
if (P.isValid() && !object.property("billboardMode").isValid()) {
bool newValue = P.toVariant().toBool();
bool oldValue = getBillboardMode() == BillboardMode::YAW;
if (_defaultSettings || newValue != oldValue) {
setBillboardMode(newValue ? BillboardMode::YAW : BillboardMode::NONE);
}
}
}
{
QScriptValue P = object.property("isFacingAvatar");
if (P.isValid() && !object.property("billboardMode").isValid() && !object.property("faceCamera").isValid()) {
bool newValue = P.toVariant().toBool();
bool oldValue = getBillboardMode() == BillboardMode::FULL;
if (_defaultSettings || newValue != oldValue) {
setBillboardMode(newValue ? BillboardMode::FULL : BillboardMode::NONE);
}
}
}
_lastEdited = usecTimestampNow();
}
@ -1886,6 +1994,11 @@ void EntityItemProperties::merge(const EntityItemProperties& other) {
COPY_PROPERTY_IF_CHANGED(spinFinish);
COPY_PROPERTY_IF_CHANGED(rotateWithEntity);
COPY_PROPERTY_IF_CHANGED(imageURL);
COPY_PROPERTY_IF_CHANGED(emissive);
COPY_PROPERTY_IF_CHANGED(keepAspectRatio);
COPY_PROPERTY_IF_CHANGED(subImage);
// Certifiable Properties
COPY_PROPERTY_IF_CHANGED(itemName);
COPY_PROPERTY_IF_CHANGED(itemDescription);
@ -1916,7 +2029,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) {
COPY_PROPERTY_IF_CHANGED(linePoints);
COPY_PROPERTY_IF_CHANGED(href);
COPY_PROPERTY_IF_CHANGED(description);
COPY_PROPERTY_IF_CHANGED(faceCamera);
COPY_PROPERTY_IF_CHANGED(billboardMode);
COPY_PROPERTY_IF_CHANGED(actionData);
COPY_PROPERTY_IF_CHANGED(normals);
COPY_PROPERTY_IF_CHANGED(strokeColors);
@ -2018,7 +2131,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
static std::once_flag initMap;
std::call_once(initMap, [](){
std::call_once(initMap, []() {
ADD_PROPERTY_TO_MAP(PROP_VISIBLE, Visible, visible, bool);
ADD_PROPERTY_TO_MAP(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool);
ADD_PROPERTY_TO_MAP(PROP_POSITION, Position, position, vec3);
@ -2135,7 +2248,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_PROPERTY_TO_MAP(PROP_LINE_POINTS, LinePoints, linePoints, QVector<vec3>);
ADD_PROPERTY_TO_MAP(PROP_HREF, Href, href, QString);
ADD_PROPERTY_TO_MAP(PROP_DESCRIPTION, Description, description, QString);
ADD_PROPERTY_TO_MAP(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool);
ADD_PROPERTY_TO_MAP(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode);
ADD_PROPERTY_TO_MAP(PROP_ACTION_DATA, ActionData, actionData, QByteArray);
ADD_PROPERTY_TO_MAP(PROP_NORMALS, Normals, normals, QVector<vec3>);
ADD_PROPERTY_TO_MAP(PROP_STROKE_COLORS, StrokeColors, strokeColors, QVector<vec3>);
@ -2241,6 +2354,11 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_EQUIPPABLE_INDICATOR_OFFSET, Grab, grab,
EquippableIndicatorOffset, equippableIndicatorOffset);
ADD_PROPERTY_TO_MAP(PROP_IMAGE_URL, ImageURL, imageURL, QString);
ADD_PROPERTY_TO_MAP(PROP_EMISSIVE, Emissive, emissive, bool);
ADD_PROPERTY_TO_MAP(PROP_KEEP_ASPECT_RATIO, KeepAspectRatio, keepAspectRatio, bool);
ADD_PROPERTY_TO_MAP(PROP_SUB_IMAGE, SubImage, subImage, QRect);
// FIXME - these are not yet handled
//ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64);
@ -2350,8 +2468,8 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
bool successPropertyFlagsFits = packetData->appendRawData(encodedPropertyFlags);
int propertyCount = 0;
bool headerFits = successIDFits && successTypeFits && successLastEditedFits
&& successLastUpdatedFits && successPropertyFlagsFits;
bool headerFits = successIDFits && successTypeFits && successLastEditedFits &&
successLastUpdatedFits && successPropertyFlagsFits;
int startOfEntityItemData = packetData->getUncompressedByteOffset();
@ -2404,39 +2522,40 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, properties.getLineHeight());
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, properties.getTextColor());
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, properties.getBackgroundColor());
APPEND_ENTITY_PROPERTY(PROP_FACE_CAMERA, properties.getFaceCamera());
APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode());
}
if (properties.getType() == EntityTypes::Model) {
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, properties.getModelURL());
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, properties.getCompoundShapeURL());
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures());
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)(properties.getShapeType()));
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
_staticAnimation.setProperties(properties);
_staticAnimation.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, properties.getJointRotationsSet());
APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, properties.getJointRotations());
APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, properties.getJointTranslationsSet());
APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, properties.getJointTranslations());
APPEND_ENTITY_PROPERTY(PROP_RELAY_PARENT_JOINTS, properties.getRelayParentJoints());
_staticAnimation.setProperties(properties);
_staticAnimation.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
}
if (properties.getType() == EntityTypes::Light) {
APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, properties.getIsSpotlight());
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
APPEND_ENTITY_PROPERTY(PROP_INTENSITY, properties.getIntensity());
APPEND_ENTITY_PROPERTY(PROP_FALLOFF_RADIUS, properties.getFalloffRadius());
APPEND_ENTITY_PROPERTY(PROP_EXPONENT, properties.getExponent());
APPEND_ENTITY_PROPERTY(PROP_CUTOFF, properties.getCutoff());
APPEND_ENTITY_PROPERTY(PROP_FALLOFF_RADIUS, properties.getFalloffRadius());
}
if (properties.getType() == EntityTypes::ParticleEffect) {
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures());
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)(properties.getShapeType()));
APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, properties.getMaxParticles());
APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, properties.getLifespan());
APPEND_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, properties.getIsEmitting());
APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, properties.getEmitRate());
APPEND_ENTITY_PROPERTY(PROP_EMIT_SPEED, properties.getEmitSpeed());
@ -2444,24 +2563,33 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
APPEND_ENTITY_PROPERTY(PROP_EMIT_ORIENTATION, properties.getEmitOrientation());
APPEND_ENTITY_PROPERTY(PROP_EMIT_DIMENSIONS, properties.getEmitDimensions());
APPEND_ENTITY_PROPERTY(PROP_EMIT_RADIUS_START, properties.getEmitRadiusStart());
APPEND_ENTITY_PROPERTY(PROP_POLAR_START, properties.getPolarStart());
APPEND_ENTITY_PROPERTY(PROP_POLAR_FINISH, properties.getPolarFinish());
APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_START, properties.getAzimuthStart());
APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, properties.getAzimuthFinish());
APPEND_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, properties.getEmitAcceleration());
APPEND_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, properties.getAccelerationSpread());
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, properties.getParticleRadius());
APPEND_ENTITY_PROPERTY(PROP_RADIUS_SPREAD, properties.getRadiusSpread());
APPEND_ENTITY_PROPERTY(PROP_RADIUS_START, properties.getRadiusStart());
APPEND_ENTITY_PROPERTY(PROP_RADIUS_FINISH, properties.getRadiusFinish());
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
APPEND_ENTITY_PROPERTY(PROP_COLOR_SPREAD, properties.getColorSpread());
APPEND_ENTITY_PROPERTY(PROP_COLOR_START, properties.getColorStart());
APPEND_ENTITY_PROPERTY(PROP_COLOR_FINISH, properties.getColorFinish());
APPEND_ENTITY_PROPERTY(PROP_ALPHA, properties.getAlpha());
APPEND_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, properties.getAlphaSpread());
APPEND_ENTITY_PROPERTY(PROP_ALPHA_START, properties.getAlphaStart());
APPEND_ENTITY_PROPERTY(PROP_ALPHA_FINISH, properties.getAlphaFinish());
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures());
APPEND_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, properties.getEmitterShouldTrail());
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_SPIN, properties.getParticleSpin());
APPEND_ENTITY_PROPERTY(PROP_SPIN_SPREAD, properties.getSpinSpread());
APPEND_ENTITY_PROPERTY(PROP_SPIN_START, properties.getSpinStart());
@ -2476,27 +2604,27 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
_staticAmbientLight.setProperties(properties);
_staticAmbientLight.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)properties.getShapeType());
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, properties.getCompoundShapeURL());
_staticSkybox.setProperties(properties);
_staticSkybox.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
_staticHaze.setProperties(properties);
_staticHaze.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
_staticBloom.setProperties(properties);
_staticBloom.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)properties.getShapeType());
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, properties.getCompoundShapeURL());
APPEND_ENTITY_PROPERTY(PROP_FLYING_ALLOWED, properties.getFlyingAllowed());
APPEND_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, properties.getGhostingAllowed());
APPEND_ENTITY_PROPERTY(PROP_FILTER_URL, properties.getFilterURL());
APPEND_ENTITY_PROPERTY(PROP_HAZE_MODE, (uint32_t)properties.getHazeMode());
_staticHaze.setProperties(properties);
_staticHaze.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
APPEND_ENTITY_PROPERTY(PROP_BLOOM_MODE, (uint32_t)properties.getBloomMode());
_staticBloom.setProperties(properties);
_staticBloom.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
APPEND_ENTITY_PROPERTY(PROP_KEY_LIGHT_MODE, (uint32_t)properties.getKeyLightMode());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_MODE, (uint32_t)properties.getAmbientLightMode());
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_MODE, (uint32_t)properties.getSkyboxMode());
APPEND_ENTITY_PROPERTY(PROP_HAZE_MODE, (uint32_t)properties.getHazeMode());
APPEND_ENTITY_PROPERTY(PROP_BLOOM_MODE, (uint32_t)properties.getBloomMode());
}
if (properties.getType() == EntityTypes::PolyVox) {
@ -2537,6 +2665,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
properties.getType() == EntityTypes::Sphere) {
APPEND_ENTITY_PROPERTY(PROP_SHAPE, properties.getShape());
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
APPEND_ENTITY_PROPERTY(PROP_ALPHA, properties.getAlpha());
}
// Materials
@ -2552,10 +2681,21 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_REPEAT, properties.getMaterialRepeat());
}
// Image
if (properties.getType() == EntityTypes::Image) {
APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, properties.getImageURL());
APPEND_ENTITY_PROPERTY(PROP_EMISSIVE, properties.getEmissive());
APPEND_ENTITY_PROPERTY(PROP_KEEP_ASPECT_RATIO, properties.getKeepAspectRatio());
APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode());
APPEND_ENTITY_PROPERTY(PROP_SUB_IMAGE, properties.getSubImage());
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
APPEND_ENTITY_PROPERTY(PROP_ALPHA, properties.getAlpha());
}
APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName());
APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, properties.getCollisionSoundURL());
APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, properties.getActionData());
APPEND_ENTITY_PROPERTY(PROP_ALPHA, properties.getAlpha());
// Certifiable Properties
APPEND_ENTITY_PROPERTY(PROP_ITEM_NAME, properties.getItemName());
@ -2586,8 +2726,8 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
encodedPropertyFlags = propertyFlags;
int newPropertyFlagsLength = encodedPropertyFlags.length();
packetData->updatePriorBytes(propertyFlagsOffset,
(const unsigned char*)encodedPropertyFlags.constData(), encodedPropertyFlags.length());
packetData->updatePriorBytes(propertyFlagsOffset, (const unsigned char*)encodedPropertyFlags.constData(),
encodedPropertyFlags.length());
// if the size of the PropertyFlags shrunk, we need to shift everything down to front of packet.
if (newPropertyFlagsLength < oldPropertyFlagsLength) {
@ -2798,38 +2938,39 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_COLOR, u8vec3Color, setTextColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_COLOR, u8vec3Color, setBackgroundColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FACE_CAMERA, bool, setFaceCamera);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode);
}
if (properties.getType() == EntityTypes::Model) {
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MODEL_URL, QString, setModelURL);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor);
properties.getAnimation().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_ROTATIONS_SET, QVector<bool>, setJointRotationsSet);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_ROTATIONS, QVector<quat>, setJointRotations);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_TRANSLATIONS_SET, QVector<bool>, setJointTranslationsSet);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_TRANSLATIONS, QVector<vec3>, setJointTranslations);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RELAY_PARENT_JOINTS, bool, setRelayParentJoints);
properties.getAnimation().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
}
if (properties.getType() == EntityTypes::Light) {
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_INTENSITY, float, setIntensity);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FALLOFF_RADIUS, float, setFalloffRadius);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EXPONENT, float, setExponent);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CUTOFF, float, setCutoff);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FALLOFF_RADIUS, float, setFalloffRadius);
}
if (properties.getType() == EntityTypes::ParticleEffect) {
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, quint32, setMaxParticles);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFESPAN, float, setLifespan);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMITTING_PARTICLES, bool, setIsEmitting);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_SPEED, float, setEmitSpeed);
@ -2837,24 +2978,33 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_ORIENTATION, quat, setEmitOrientation);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_DIMENSIONS, vec3, setEmitDimensions);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RADIUS_START, float, setEmitRadiusStart);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_POLAR_START, float, setPolarStart);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_POLAR_FINISH, float, setPolarFinish);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_AZIMUTH_START, float, setAzimuthStart);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_AZIMUTH_FINISH, float, setAzimuthFinish);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_ACCELERATION, vec3, setEmitAcceleration);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ACCELERATION_SPREAD, vec3, setAccelerationSpread);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RADIUS_SPREAD, float, setRadiusSpread);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RADIUS_START, float, setRadiusStart);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RADIUS_FINISH, float, setRadiusFinish);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR_SPREAD, u8vec3Color, setColorSpread);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR_START, vec3Color, setColorStart);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR_FINISH, vec3Color, setColorFinish);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_SPREAD, float, setAlphaSpread);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_START, float, setAlphaStart);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_FINISH, float, setAlphaFinish);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMITTER_SHOULD_TRAIL, bool, setEmitterShouldTrail);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_SPIN, float, setParticleSpin);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SPIN_SPREAD, float, setSpinSpread);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SPIN_START, float, setSpinStart);
@ -2865,24 +3015,22 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
if (properties.getType() == EntityTypes::Zone) {
properties.getKeyLight().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
properties.getAmbientLight().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
properties.getSkybox().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
properties.getHaze().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
properties.getBloom().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
properties.getSkybox().decodeFromEditPacket(propertyFlags, dataAt , processedBytes);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FLYING_ALLOWED, bool, setFlyingAllowed);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_GHOSTING_ALLOWED, bool, setGhostingAllowed);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FILTER_URL, QString, setFilterURL);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_HAZE_MODE, uint32_t, setHazeMode);
properties.getHaze().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BLOOM_MODE, uint32_t, setBloomMode);
properties.getBloom().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEY_LIGHT_MODE, uint32_t, setKeyLightMode);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_AMBIENT_LIGHT_MODE, uint32_t, setAmbientLightMode);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SKYBOX_MODE, uint32_t, setSkyboxMode);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_HAZE_MODE, uint32_t, setHazeMode);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BLOOM_MODE, uint32_t, setBloomMode);
}
if (properties.getType() == EntityTypes::PolyVox) {
@ -2925,6 +3073,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
properties.getType() == EntityTypes::Sphere) {
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE, QString, setShape);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha);
}
// Materials
@ -2940,10 +3089,21 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_REPEAT, bool, setMaterialRepeat);
}
// Image
if (properties.getType() == EntityTypes::Image) {
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IMAGE_URL, QString, setImageURL);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMISSIVE, bool, setEmissive);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEEP_ASPECT_RATIO, bool, setKeepAspectRatio);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SUB_IMAGE, QRect, setSubImage);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha);
}
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ACTION_DATA, QByteArray, setActionData);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha);
// Certifiable Properties
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ITEM_NAME, QString, setItemName);
@ -2986,7 +3146,7 @@ QVector<vec3> EntityItemProperties::unpackNormals(const QByteArray& normals) {
j++;
}
} else {
qCDebug(entities) << "WARNING - Expected received size for normals does not match. Expected: " << (int)normals[0]
qCDebug(entities) << "WARNING - Expected received size for normals does not match. Expected: " << (int)normals[0]
<< " Received: " << (normals.size() / 6);
}
return unpackedNormals;
@ -2999,7 +3159,7 @@ void EntityItemProperties::setPackedStrokeColors(const QByteArray& value) {
QVector<vec3> EntityItemProperties::unpackStrokeColors(const QByteArray& strokeColors) {
// the size of the vector is packed first
QVector<vec3> unpackedStrokeColors = QVector<vec3>((int)strokeColors[0]);
if ((int)strokeColors[0] == strokeColors.size() / 3) {
int j = 0;
for (int i = 1; i < strokeColors.size();) {
@ -3010,7 +3170,7 @@ QVector<vec3> EntityItemProperties::unpackStrokeColors(const QByteArray& strokeC
unpackedStrokeColors[j++] = vec3(r, g, b);
}
} else {
qCDebug(entities) << "WARNING - Expected received size for stroke colors does not match. Expected: "
qCDebug(entities) << "WARNING - Expected received size for stroke colors does not match. Expected: "
<< (int)strokeColors[0] << " Received: " << (strokeColors.size() / 3);
}
@ -3027,7 +3187,7 @@ bool EntityItemProperties::encodeEraseEntityMessage(const EntityItemID& entityIt
int outputLength = 0;
if (buffer.size() < (int) (sizeof(numberOfIds) + NUM_BYTES_RFC4122_UUID)) {
if (buffer.size() < (int)(sizeof(numberOfIds) + NUM_BYTES_RFC4122_UUID)) {
qCDebug(entities) << "ERROR - encodeEraseEntityMessage() called with buffer that is too small!";
return false;
}
@ -3218,7 +3378,7 @@ void EntityItemProperties::markAllChanged() {
_hrefChanged = true;
_descriptionChanged = true;
_faceCameraChanged = true;
_billboardModeChanged = true;
_actionDataChanged = true;
_normalsChanged = true;
@ -3268,6 +3428,11 @@ void EntityItemProperties::markAllChanged() {
_cloneOriginIDChanged = true;
_isVisibleInSecondaryCameraChanged = true;
_imageURLChanged = true;
_emissiveChanged = true;
_keepAspectRatioChanged = true;
_subImageChanged = true;
}
// The minimum bounding box for the entity.
@ -3276,7 +3441,7 @@ AABox EntityItemProperties::getAABox() const {
// _position represents the position of the registration point.
vec3 registrationRemainder = vec3(1.0f) - _registrationPoint;
vec3 unrotatedMinRelativeToEntity = - (_dimensions * _registrationPoint);
vec3 unrotatedMinRelativeToEntity = -(_dimensions * _registrationPoint);
vec3 unrotatedMaxRelativeToEntity = _dimensions * registrationRemainder;
Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity };
Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(_rotation);
@ -3288,7 +3453,7 @@ AABox EntityItemProperties::getAABox() const {
}
bool EntityItemProperties::hasTransformOrVelocityChanges() const {
return _positionChanged ||_localPositionChanged
return _positionChanged || _localPositionChanged
|| _rotationChanged || _localRotationChanged
|| _velocityChanged || _localVelocityChanged
|| _angularVelocityChanged || _localAngularVelocityChanged
@ -3374,7 +3539,7 @@ uint8_t EntityItemProperties::computeSimulationBidPriority() const {
if (_parentIDChanged || _parentJointIndexChanged) {
// we need higher simulation ownership priority to chang parenting info
priority = SCRIPT_GRAB_SIMULATION_PRIORITY;
} else if ( _positionChanged || _localPositionChanged
} else if (_positionChanged || _localPositionChanged
|| _rotationChanged || _localRotationChanged
|| _velocityChanged || _localVelocityChanged
|| _angularVelocityChanged || _localAngularVelocityChanged) {
@ -3807,6 +3972,23 @@ QList<QString> EntityItemProperties::listChangedProperties() {
out += "cloneOriginID";
}
if (imageURLChanged()) {
out += "imageURL";
}
if (emissiveChanged()) {
out += "emissive";
}
if (keepAspectRatioChanged()) {
out += "keepAspectRatio";
}
if (subImageChanged()) {
out += "subImage";
}
if (billboardModeChanged()) {
out += "billboardMode";
}
getAnimation().listChangedProperties(out);
getKeyLight().listChangedProperties(out);
getAmbientLight().listChangedProperties(out);
@ -4004,4 +4186,4 @@ void EntityItemProperties::convertToCloneProperties(const EntityItemID& entityID
setCloneLimit(ENTITY_ITEM_DEFAULT_CLONE_LIMIT);
setCloneDynamic(ENTITY_ITEM_DEFAULT_CLONE_DYNAMIC);
setCloneAvatarEntity(ENTITY_ITEM_DEFAULT_CLONE_AVATAR_ENTITY);
}
}

View file

@ -48,6 +48,7 @@
#include "ZoneEntityItem.h"
#include "MaterialMappingMode.h"
#include "BillboardMode.h"
const quint64 UNKNOWN_CREATED_TIME = 0;
@ -68,18 +69,19 @@ using u8vec3Color = glm::u8vec3;
class EntityItemProperties {
// TODO: consider removing these friend relationship and use public methods
friend class EntityItem;
friend class ModelEntityItem;
friend class BoxEntityItem;
friend class SphereEntityItem;
friend class LightEntityItem;
friend class TextEntityItem;
friend class ParticleEffectEntityItem;
friend class ZoneEntityItem;
friend class WebEntityItem;
friend class LineEntityItem;
friend class PolyVoxEntityItem;
friend class PolyLineEntityItem;
friend class ShapeEntityItem;
friend class ModelEntityItem;
friend class TextEntityItem;
friend class ImageEntityItem;
friend class WebEntityItem;
friend class ParticleEffectEntityItem;
friend class LineEntityItem;
friend class PolyLineEntityItem;
friend class PolyVoxEntityItem;
friend class LightEntityItem;
friend class ZoneEntityItem;
friend class MaterialEntityItem;
public:
EntityItemProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags());
@ -213,7 +215,7 @@ public:
DEFINE_PROPERTY_REF(LINE_POINTS, LinePoints, linePoints, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
DEFINE_PROPERTY_REF(PROP_HREF, Href, href, QString, "");
DEFINE_PROPERTY_REF(PROP_DESCRIPTION, Description, description, QString, "");
DEFINE_PROPERTY(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool, TextEntityItem::DEFAULT_FACE_CAMERA);
DEFINE_PROPERTY_REF_ENUM(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode, BillboardMode::NONE);
DEFINE_PROPERTY_REF(PROP_ACTION_DATA, ActionData, actionData, QByteArray, QByteArray());
DEFINE_PROPERTY(PROP_NORMALS, Normals, normals, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
DEFINE_PROPERTY(PROP_STROKE_COLORS, StrokeColors, strokeColors, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
@ -251,6 +253,11 @@ public:
DEFINE_PROPERTY(PROP_SPIN_FINISH, SpinFinish, spinFinish, float, particle::DEFAULT_SPIN_FINISH);
DEFINE_PROPERTY(PROP_PARTICLE_ROTATE_WITH_ENTITY, RotateWithEntity, rotateWithEntity, bool, particle::DEFAULT_ROTATE_WITH_ENTITY);
DEFINE_PROPERTY_REF(PROP_IMAGE_URL, ImageURL, imageURL, QString, "");
DEFINE_PROPERTY_REF(PROP_EMISSIVE, Emissive, emissive, bool, false);
DEFINE_PROPERTY_REF(PROP_KEEP_ASPECT_RATIO, KeepAspectRatio, keepAspectRatio, bool, true);
DEFINE_PROPERTY_REF(PROP_SUB_IMAGE, SubImage, subImage, QRect, QRect());
// Certifiable Properties - related to Proof of Purchase certificates
DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME);
DEFINE_PROPERTY_REF(PROP_ITEM_DESCRIPTION, ItemDescription, itemDescription, QString, ENTITY_ITEM_DEFAULT_ITEM_DESCRIPTION);
@ -299,7 +306,6 @@ public:
DEFINE_PROPERTY_GROUP(Grab, grab, GrabPropertyGroup);
static QString getComponentModeString(uint32_t mode);
static QString getComponentModeAsString(uint32_t mode);
std::array<ComponentPair, COMPONENT_MODE_ITEM_COUNT>::const_iterator findComponent(const QString& mode);

View file

@ -122,6 +122,8 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<glm::quat
inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<bool>& v) {return qVectorBoolToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<float>& v) { return qVectorFloatToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QRect& v) { return qRectToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QByteArray& v) {
QByteArray b64 = v.toBase64();
return QScriptValue(QString(b64));
@ -323,6 +325,13 @@ inline glm::quat quat_convertFromScriptValue(const QScriptValue& v, bool& isVali
return glm::quat();
}
inline QRect QRect_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
isValid = true;
QRect rect;
qRectFromScriptValue(v, rect);
return rect;
}
#define COPY_PROPERTY_IF_CHANGED(P) \
{ \
if (other._##P##Changed) { \

View file

@ -67,7 +67,7 @@ QDebug& operator<<(QDebug& dbg, const EntityPropertyFlags& f) {
result = f.getHasProperty(PROP_LINE_POINTS) ? result + "linePoints " : result;
result = f.getHasProperty(PROP_HREF) ? result + "href " : result;
result = f.getHasProperty(PROP_DESCRIPTION) ? result + "description " : result;
result = f.getHasProperty(PROP_FACE_CAMERA) ? result + "faceCamera " : result;
result = f.getHasProperty(PROP_BILLBOARD_MODE) ? result + "billboardMode " : result;
result = f.getHasProperty(PROP_SCRIPT_TIMESTAMP) ? result + "scriptTimestamp " : result;
result = f.getHasProperty(PROP_ACTION_DATA) ? result + "actionData " : result;
result = f.getHasProperty(PROP_X_TEXTURE_URL) ? result + "xTextureUrl " : result;

View file

@ -99,7 +99,7 @@ enum EntityPropertyList {
PROP_HREF,
PROP_DESCRIPTION, // 61
PROP_FACE_CAMERA,
PROP_BILLBOARD_MODE,
PROP_SCRIPT_TIMESTAMP,
PROP_ACTION_DATA,
@ -277,6 +277,9 @@ enum EntityPropertyList {
PROP_MATERIAL_REPEAT,
PROP_EMISSIVE,
PROP_SUB_IMAGE,
////////////////////////////////////////////////////////////////////////////////////////////////////
// ATTENTION: add new properties to end of list just ABOVE this line
PROP_AFTER_LAST_ITEM,
@ -310,6 +313,11 @@ enum EntityPropertyList {
// other properties which will never overlap with each other.
PROP_EMITTING_PARTICLES = PROP_ANIMATION_PLAYING,
// Aliases/Piggyback properties for Image. These properties intentionally reuse the enum values for
// other properties which will never overlap with each other.
PROP_IMAGE_URL = PROP_MODEL_URL,
PROP_KEEP_ASPECT_RATIO = PROP_ANIMATION_PLAYING,
// WARNING!!! DO NOT ADD PROPS_xxx here unless you really really meant to.... Add them UP above
};

View file

@ -34,6 +34,8 @@ namespace EntityPsuedoPropertyFlag {
OwningAvatarID,
AvatarEntity,
LocalEntity,
FaceCamera,
IsFacingAvatar,
NumFlags
};

View file

@ -698,6 +698,10 @@ QScriptValue EntityScriptingInterface::getMultipleEntityPropertiesInternal(QScri
psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::AvatarEntity);
} else if (extendedPropertyString == "localEntity") {
psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::LocalEntity);
} else if (extendedPropertyString == "faceCamera") {
psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::FaceCamera);
} else if (extendedPropertyString == "isFacingAvatar") {
psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::IsFacingAvatar);
}
};

View file

@ -20,38 +20,40 @@
#include "EntityItemProperties.h"
#include "EntitiesLogging.h"
#include "LightEntityItem.h"
#include "ShapeEntityItem.h"
#include "ModelEntityItem.h"
#include "ParticleEffectEntityItem.h"
#include "TextEntityItem.h"
#include "ImageEntityItem.h"
#include "WebEntityItem.h"
#include "ZoneEntityItem.h"
#include "LineEntityItem.h"
#include "PolyVoxEntityItem.h"
#include "PolyLineEntityItem.h"
#include "ShapeEntityItem.h"
#include "PolyVoxEntityItem.h"
#include "LightEntityItem.h"
#include "ZoneEntityItem.h"
#include "MaterialEntityItem.h"
QMap<EntityTypes::EntityType, QString> EntityTypes::_typeToNameMap;
QMap<QString, EntityTypes::EntityType> EntityTypes::_nameToTypeMap;
EntityTypeFactory EntityTypes::_factories[EntityTypes::LAST + 1];
EntityTypeFactory EntityTypes::_factories[EntityTypes::NUM_TYPES];
bool EntityTypes::_factoriesInitialized = false;
const QString ENTITY_TYPE_NAME_UNKNOWN = "Unknown";
// Register Entity the default implementations of entity types here...
REGISTER_ENTITY_TYPE(Model)
REGISTER_ENTITY_TYPE(Web)
REGISTER_ENTITY_TYPE(Light)
REGISTER_ENTITY_TYPE(Text)
REGISTER_ENTITY_TYPE(ParticleEffect)
REGISTER_ENTITY_TYPE(Zone)
REGISTER_ENTITY_TYPE(Line)
REGISTER_ENTITY_TYPE(PolyVox)
REGISTER_ENTITY_TYPE(PolyLine)
REGISTER_ENTITY_TYPE(Shape)
REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, ShapeEntityItem::boxFactory)
REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, ShapeEntityItem::sphereFactory)
REGISTER_ENTITY_TYPE(Shape)
REGISTER_ENTITY_TYPE(Model)
REGISTER_ENTITY_TYPE(Text)
REGISTER_ENTITY_TYPE(Image)
REGISTER_ENTITY_TYPE(Web)
REGISTER_ENTITY_TYPE(ParticleEffect)
REGISTER_ENTITY_TYPE(Line)
REGISTER_ENTITY_TYPE(PolyLine)
REGISTER_ENTITY_TYPE(PolyVox)
REGISTER_ENTITY_TYPE(Light)
REGISTER_ENTITY_TYPE(Zone)
REGISTER_ENTITY_TYPE(Material)
const QString& EntityTypes::getEntityTypeName(EntityType entityType) {
@ -80,7 +82,7 @@ bool EntityTypes::registerEntityType(EntityType entityType, const char* name, En
memset(&_factories,0,sizeof(_factories));
_factoriesInitialized = true;
}
if (entityType >= 0 && entityType <= LAST) {
if (entityType >= 0 && entityType < NUM_TYPES) {
_factories[entityType] = factoryMethod;
return true;
}
@ -91,7 +93,7 @@ EntityItemPointer EntityTypes::constructEntityItem(EntityType entityType, const
const EntityItemProperties& properties) {
EntityItemPointer newEntityItem = NULL;
EntityTypeFactory factory = NULL;
if (entityType >= 0 && entityType <= LAST) {
if (entityType >= 0 && entityType < NUM_TYPES) {
factory = _factories[entityType];
}
if (factory) {

View file

@ -49,25 +49,6 @@ public:
* <code>"Cube"</code>. If an entity of type <code>Shape</code> or <code>Sphere</code> has its <code>shape</code> set
* to <code>"Cube"</code> then its <code>type</code> will be reported as <code>"Box"</code>.
* <td>{@link Entities.EntityProperties-Box|EntityProperties-Box}</td></tr>
* <tr><td><code>"Light"</code></td><td>A local lighting effect.</td>
* <td>{@link Entities.EntityProperties-Light|EntityProperties-Light}</td></tr>
* <tr><td><code>"Line"</code></td><td>A sequence of one or more simple straight lines.</td>
* <td>{@link Entities.EntityProperties-Line|EntityProperties-Line}</td></tr>
* <tr><td><code>"Material"</code></td><td>Modifies the existing materials on Model entities, Shape entities (albedo
* only), {@link Overlays.OverlayType|model overlays}, and avatars.</td>
* <td>{@link Entities.EntityProperties-Material|EntityProperties-Material}</td></tr>
* <tr><td><code>"Model"</code></td><td>A mesh model from an FBX or OBJ file.</td>
* <td>{@link Entities.EntityProperties-Model|EntityProperties-Model}</td></tr>
* <tr><td><code>"ParticleEffect"</code></td><td>A particle system that can be used to simulate things such as fire,
* smoke, snow, magic spells, etc.</td>
* <td>{@link Entities.EntityProperties-ParticleEffect|EntityProperties-ParticleEffect}</td></tr>
* <tr><td><code>"PolyLine"</code></td><td>A sequence of one or more textured straight lines.</td>
* <td>{@link Entities.EntityProperties-PolyLine|EntityProperties-PolyLine}</td></tr>
* <tr><td><code>"PolyVox"</code></td><td>A set of textured voxels.</td>
* <td>{@link Entities.EntityProperties-PolyVox|EntityProperties-PolyVox}</td></tr>
* <tr><td><code>"Shape"</code></td><td>A basic entity such as a cube.
* See also, the <code>"Box"</code> and <code>"Sphere"</code> entity types.</td>
* <td>{@link Entities.EntityProperties-Shape|EntityProperties-Shape}</td></tr>
* <tr><td><code>"Sphere"</code></td><td>A sphere. This is a synonym of <code>"Shape"</code> for the case
* where the entity's <code>shape</code> property value is <code>"Sphere"</code>.<br />
* If an entity is created with its <code>type</code>
@ -75,32 +56,54 @@ public:
* <code>"Sphere"</code>. If an entity of type <code>Box</code> or <code>Shape</code> has its <code>shape</code> set
* to <code>"Sphere"</code> then its <code>type</code> will be reported as <code>"Sphere"</code>.
* <td>{@link Entities.EntityProperties-Sphere|EntityProperties-Sphere}</td></tr>
* <tr><td><code>"Shape"</code></td><td>A basic entity such as a cube.
* See also, the <code>"Box"</code> and <code>"Sphere"</code> entity types.</td>
* <td>{@link Entities.EntityProperties-Shape|EntityProperties-Shape}</td></tr>
* <tr><td><code>"Model"</code></td><td>A mesh model from an FBX or OBJ file.</td>
* <td>{@link Entities.EntityProperties-Model|EntityProperties-Model}</td></tr>
* <tr><td><code>"Text"</code></td><td>A pane of text oriented in space.</td>
* <td>{@link Entities.EntityProperties-Text|EntityProperties-Text}</td></tr>
* <tr><td><code>"Image"</code></td><td>An image oriented in space.</td>
* <td>{@link Entities.EntityProperties-Image|EntityProperties-Image}</td></tr>
* <tr><td><code>"Web"</code></td><td>A browsable Web page.</td>
* <td>{@link Entities.EntityProperties-Web|EntityProperties-Web}</td></tr>
* <tr><td><code>"ParticleEffect"</code></td><td>A particle system that can be used to simulate things such as fire,
* smoke, snow, magic spells, etc.</td>
* <td>{@link Entities.EntityProperties-ParticleEffect|EntityProperties-ParticleEffect}</td></tr>
* <tr><td><code>"Line"</code></td><td>A sequence of one or more simple straight lines.</td>
* <td>{@link Entities.EntityProperties-Line|EntityProperties-Line}</td></tr>
* <tr><td><code>"PolyLine"</code></td><td>A sequence of one or more textured straight lines.</td>
* <td>{@link Entities.EntityProperties-PolyLine|EntityProperties-PolyLine}</td></tr>
* <tr><td><code>"PolyVox"</code></td><td>A set of textured voxels.</td>
* <td>{@link Entities.EntityProperties-PolyVox|EntityProperties-PolyVox}</td></tr>
* <tr><td><code>"Light"</code></td><td>A local lighting effect.</td>
* <td>{@link Entities.EntityProperties-Light|EntityProperties-Light}</td></tr>
* <tr><td><code>"Zone"</code></td><td>A volume of lighting effects and avatar permissions.</td>
* <td>{@link Entities.EntityProperties-Zone|EntityProperties-Zone}</td></tr>
* <tr><td><code>"Material"</code></td><td>Modifies the existing materials on Model entities, Shape entities,
* {@link Overlays.OverlayType|model overlays}, and avatars.</td>
* <td>{@link Entities.EntityProperties-Material|EntityProperties-Material}</td></tr>
* </tbody>
* </table>
* @typedef {string} Entities.EntityType
*/
typedef enum EntityType_t {
Unknown,
Model,
Box,
Sphere,
Light,
Text,
ParticleEffect,
Zone,
Web,
Line,
PolyVox,
PolyLine,
Shape,
Model,
Text,
Image,
Web,
ParticleEffect,
Line,
PolyLine,
PolyVox,
Light,
Zone,
Material,
LAST = Material
NUM_TYPES
} EntityType;
static const QString& getEntityTypeName(EntityType entityType);
@ -112,7 +115,7 @@ public:
private:
static QMap<EntityType, QString> _typeToNameMap;
static QMap<QString, EntityTypes::EntityType> _nameToTypeMap;
static EntityTypeFactory _factories[LAST + 1];
static EntityTypeFactory _factories[NUM_TYPES];
static bool _factoriesInitialized;
};

View file

@ -0,0 +1,269 @@
//
// Created by Sam Gondelman on 11/29/18
// Copyright 2018 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 "ImageEntityItem.h"
#include "EntityItemProperties.h"
EntityItemPointer ImageEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
Pointer entity(new ImageEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
entity->setProperties(properties);
return entity;
}
// our non-pure virtual subclass for now...
ImageEntityItem::ImageEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
_type = EntityTypes::Image;
}
void ImageEntityItem::setUnscaledDimensions(const glm::vec3& value) {
const float IMAGE_ENTITY_ITEM_FIXED_DEPTH = 0.01f;
// NOTE: Image Entities always have a "depth" of 1cm.
EntityItem::setUnscaledDimensions(glm::vec3(value.x, value.y, IMAGE_ENTITY_ITEM_FIXED_DEPTH));
}
EntityItemProperties ImageEntityItem::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(imageURL, getImageURL);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emissive, getEmissive);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(keepAspectRatio, getKeepAspectRatio);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(subImage, getSubImage);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);
return properties;
}
bool ImageEntityItem::setProperties(const EntityItemProperties& properties) {
bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
SET_ENTITY_PROPERTY_FROM_PROPERTIES(imageURL, setImageURL);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emissive, setEmissive);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(keepAspectRatio, setKeepAspectRatio);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(subImage, setSubImage);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
if (somethingChanged) {
bool wantDebug = false;
if (wantDebug) {
uint64_t now = usecTimestampNow();
int elapsed = now - getLastEdited();
qCDebug(entities) << "ImageEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
"now=" << now << " getLastEdited()=" << getLastEdited();
}
setLastEdited(properties.getLastEdited());
}
return somethingChanged;
}
int ImageEntityItem::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_IMAGE_URL, QString, setImageURL);
READ_ENTITY_PROPERTY(PROP_EMISSIVE, bool, setEmissive);
READ_ENTITY_PROPERTY(PROP_KEEP_ASPECT_RATIO, bool, setKeepAspectRatio);
READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode);
READ_ENTITY_PROPERTY(PROP_SUB_IMAGE, QRect, setSubImage);
READ_ENTITY_PROPERTY(PROP_COLOR, u8vec3Color, setColor);
READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha);
return bytesRead;
}
EntityPropertyFlags ImageEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_IMAGE_URL;
requestedProperties += PROP_EMISSIVE;
requestedProperties += PROP_KEEP_ASPECT_RATIO;
requestedProperties += PROP_BILLBOARD_MODE;
requestedProperties += PROP_SUB_IMAGE;
requestedProperties += PROP_COLOR;
requestedProperties += PROP_ALPHA;
return requestedProperties;
}
void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, getImageURL());
APPEND_ENTITY_PROPERTY(PROP_EMISSIVE, getEmissive());
APPEND_ENTITY_PROPERTY(PROP_KEEP_ASPECT_RATIO, getKeepAspectRatio());
APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode());
APPEND_ENTITY_PROPERTY(PROP_SUB_IMAGE, getSubImage());
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha());
}
bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
OctreeElementPointer& element,
float& distance, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const {
glm::vec3 dimensions = getScaledDimensions();
glm::vec2 xyDimensions(dimensions.x, dimensions.y);
glm::quat rotation = getWorldOrientation();
glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()));
if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) {
glm::vec3 forward = rotation * Vectors::FRONT;
if (glm::dot(forward, direction) > 0.0f) {
face = MAX_Z_FACE;
surfaceNormal = -forward;
} else {
face = MIN_Z_FACE;
surfaceNormal = forward;
}
return true;
}
return false;
}
bool ImageEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
OctreeElementPointer& element, float& parabolicDistance,
BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const {
glm::vec3 dimensions = getScaledDimensions();
glm::vec2 xyDimensions(dimensions.x, dimensions.y);
glm::quat rotation = getWorldOrientation();
glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()));
glm::quat inverseRot = glm::inverse(rotation);
glm::vec3 localOrigin = inverseRot * (origin - position);
glm::vec3 localVelocity = inverseRot * velocity;
glm::vec3 localAcceleration = inverseRot * acceleration;
if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) {
float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance;
glm::vec3 forward = rotation * Vectors::FRONT;
if (localIntersectionVelocityZ > 0.0f) {
face = MIN_Z_FACE;
surfaceNormal = forward;
} else {
face = MAX_Z_FACE;
surfaceNormal = -forward;
}
return true;
}
return false;
}
QString ImageEntityItem::getImageURL() const {
QString result;
withReadLock([&] {
result = _imageURL;
});
return result;
}
void ImageEntityItem::setImageURL(const QString& url) {
withWriteLock([&] {
_imageURL = url;
});
}
bool ImageEntityItem::getEmissive() const {
bool result;
withReadLock([&] {
result = _emissive;
});
return result;
}
void ImageEntityItem::setEmissive(bool emissive) {
withWriteLock([&] {
_emissive = emissive;
});
}
bool ImageEntityItem::getKeepAspectRatio() const {
bool result;
withReadLock([&] {
result = _keepAspectRatio;
});
return result;
}
void ImageEntityItem::setKeepAspectRatio(bool keepAspectRatio) {
withWriteLock([&] {
_keepAspectRatio = keepAspectRatio;
});
}
BillboardMode ImageEntityItem::getBillboardMode() const {
BillboardMode result;
withReadLock([&] {
result = _billboardMode;
});
return result;
}
void ImageEntityItem::setBillboardMode(BillboardMode value) {
withWriteLock([&] {
_billboardMode = value;
});
}
QRect ImageEntityItem::getSubImage() const {
QRect result;
withReadLock([&] {
result = _subImage;
});
return result;
}
void ImageEntityItem::setSubImage(const QRect& subImage) {
withWriteLock([&] {
_subImage = subImage;
});
}
void ImageEntityItem::setColor(const glm::u8vec3& color) {
withWriteLock([&] {
_color = color;
});
}
glm::u8vec3 ImageEntityItem::getColor() const {
return resultWithReadLock<glm::u8vec3>([&] {
return _color;
});
}
void ImageEntityItem::setAlpha(float alpha) {
withWriteLock([&] {
_alpha = alpha;
});
}
float ImageEntityItem::getAlpha() const {
return resultWithReadLock<float>([&] {
return _alpha;
});
}

View file

@ -0,0 +1,86 @@
//
// Created by Sam Gondelman on 11/29/18
// Copyright 2018 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_ImageEntityItem_h
#define hifi_ImageEntityItem_h
#include "EntityItem.h"
class ImageEntityItem : public EntityItem {
using Pointer = std::shared_ptr<ImageEntityItem>;
public:
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
ImageEntityItem(const EntityItemID& entityItemID);
ALLOW_INSTANTIATION // This class can be instantiated
virtual void setUnscaledDimensions(const glm::vec3& value) override;
// methods for getting/setting all properties of an entity
EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
bool setProperties(const EntityItemProperties& properties) override;
EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData,
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;
virtual bool supportsDetailedIntersection() const override { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override;
virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity,
const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance,
BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override;
void setImageURL(const QString& imageUrl);
QString getImageURL() const;
void setEmissive(bool emissive);
bool getEmissive() const;
void setKeepAspectRatio(bool keepAspectRatio);
bool getKeepAspectRatio() const;
void setBillboardMode(BillboardMode value);
BillboardMode getBillboardMode() const;
void setSubImage(const QRect& subImage);
QRect getSubImage() const;
void setColor(const glm::u8vec3& color);
glm::u8vec3 getColor() const;
void setAlpha(float alpha);
float getAlpha() const;
protected:
QString _imageURL;
bool _emissive { false };
bool _keepAspectRatio { true };
BillboardMode _billboardMode;
QRect _subImage;
glm::u8vec3 _color;
float _alpha;
};
#endif // hifi_ImageEntityItem_h

View file

@ -120,6 +120,11 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
READ_ENTITY_PROPERTY(PROP_MODEL_URL, QString, setModelURL);
READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType);
READ_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, QVector<bool>, setJointRotationsSet);
READ_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, QVector<glm::quat>, setJointRotations);
READ_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, QVector<bool>, setJointTranslationsSet);
READ_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, QVector<glm::vec3>, setJointTranslations);
READ_ENTITY_PROPERTY(PROP_RELAY_PARENT_JOINTS, bool, setRelayParentJoints);
// grab a local copy of _animationProperties to avoid multiple locks
@ -140,13 +145,6 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
bytesRead += bytesFromAnimation;
dataAt += bytesFromAnimation;
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType);
READ_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, QVector<bool>, setJointRotationsSet);
READ_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, QVector<glm::quat>, setJointRotations);
READ_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, QVector<bool>, setJointTranslationsSet);
READ_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, QVector<glm::vec3>, setJointTranslations);
return bytesRead;
}
@ -158,12 +156,12 @@ EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams&
requestedProperties += PROP_COMPOUND_SHAPE_URL;
requestedProperties += PROP_TEXTURES;
requestedProperties += PROP_SHAPE_TYPE;
requestedProperties += _animationProperties.getEntityProperties(params);
requestedProperties += PROP_JOINT_ROTATIONS_SET;
requestedProperties += PROP_JOINT_ROTATIONS;
requestedProperties += PROP_JOINT_TRANSLATIONS_SET;
requestedProperties += PROP_JOINT_TRANSLATIONS;
requestedProperties += PROP_RELAY_PARENT_JOINTS;
requestedProperties += _animationProperties.getEntityProperties(params);
return requestedProperties;
}
@ -182,19 +180,17 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, getModelURL());
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL());
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, getJointRotationsSet());
APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, getJointRotations());
APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, getJointTranslationsSet());
APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, getJointTranslations());
APPEND_ENTITY_PROPERTY(PROP_RELAY_PARENT_JOINTS, getRelayParentJoints());
withReadLock([&] {
_animationProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
});
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, getJointRotationsSet());
APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, getJointRotations());
APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, getJointTranslationsSet());
APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, getJointTranslations());
}

View file

@ -409,11 +409,10 @@ void ParticleEffectEntityItem::computeAndUpdateDimensions() {
EntityItemProperties ParticleEffectEntityItem::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(color, getColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); // FIXME - this doesn't appear to get used
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(maxParticles, getMaxParticles);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifespan, getLifespan);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(isEmitting, getIsEmitting);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitRate, getEmitRate);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitSpeed, getEmitSpeed);
@ -421,24 +420,33 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(const EntityPropert
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitOrientation, getEmitOrientation);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitDimensions, getEmitDimensions);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitRadiusStart, getEmitRadiusStart);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(polarStart, getPolarStart);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(polarFinish, getPolarFinish);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(azimuthStart, getAzimuthStart);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(azimuthFinish, getAzimuthFinish);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitAcceleration, getEmitAcceleration);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(accelerationSpread, getAccelerationSpread);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleRadius, getParticleRadius);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(radiusSpread, getRadiusSpread);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(radiusStart, getRadiusStart);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(radiusFinish, getRadiusFinish);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(colorSpread, getColorSpread);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(colorStart, getColorStart);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(colorFinish, getColorFinish);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaSpread, getAlphaSpread);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaStart, getAlphaStart);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaFinish, getAlphaFinish);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitterShouldTrail, getEmitterShouldTrail);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleSpin, getParticleSpin);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(spinSpread, getSpinSpread);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(spinStart, getSpinStart);
@ -451,11 +459,10 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(const EntityPropert
bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& properties) {
bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, setShapeType);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(maxParticles, setMaxParticles);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifespan, setLifespan);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(isEmitting, setIsEmitting);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitRate, setEmitRate);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitSpeed, setEmitSpeed);
@ -463,24 +470,33 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitOrientation, setEmitOrientation);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitDimensions, setEmitDimensions);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitRadiusStart, setEmitRadiusStart);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(polarStart, setPolarStart);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(polarFinish, setPolarFinish);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(azimuthStart, setAzimuthStart);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(azimuthFinish, setAzimuthFinish);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitAcceleration, setEmitAcceleration);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(accelerationSpread, setAccelerationSpread);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(radiusSpread, setRadiusSpread);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(radiusStart, setRadiusStart);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(radiusFinish, setRadiusFinish);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(colorSpread, setColorSpread);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(colorStart, setColorStart);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(colorFinish, setColorFinish);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaSpread, setAlphaSpread);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaStart, setAlphaStart);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaFinish, setAlphaFinish);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitterShouldTrail, setEmitterShouldTrail);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleSpin, setParticleSpin);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(spinSpread, setSpinSpread);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(spinStart, setSpinStart);
@ -514,40 +530,42 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
int bytesRead = 0;
const unsigned char* dataAt = data;
READ_ENTITY_PROPERTY(PROP_COLOR, u8vec3Color, setColor);
READ_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, bool, setIsEmitting);
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType);
READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles);
READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan);
READ_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, bool, setIsEmitting);
READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate);
READ_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration);
READ_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, glm::vec3, setAccelerationSpread);
READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius);
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
READ_ENTITY_PROPERTY(PROP_RADIUS_SPREAD, float, setRadiusSpread);
READ_ENTITY_PROPERTY(PROP_RADIUS_START, float, setRadiusStart);
READ_ENTITY_PROPERTY(PROP_RADIUS_FINISH, float, setRadiusFinish);
READ_ENTITY_PROPERTY(PROP_COLOR_SPREAD, u8vec3Color, setColorSpread);
READ_ENTITY_PROPERTY(PROP_COLOR_START, vec3Color, setColorStart);
READ_ENTITY_PROPERTY(PROP_COLOR_FINISH, vec3Color, setColorFinish);
READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha);
READ_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, float, setAlphaSpread);
READ_ENTITY_PROPERTY(PROP_ALPHA_START, float, setAlphaStart);
READ_ENTITY_PROPERTY(PROP_ALPHA_FINISH, float, setAlphaFinish);
READ_ENTITY_PROPERTY(PROP_EMIT_SPEED, float, setEmitSpeed);
READ_ENTITY_PROPERTY(PROP_SPEED_SPREAD, float, setSpeedSpread);
READ_ENTITY_PROPERTY(PROP_EMIT_ORIENTATION, quat, setEmitOrientation);
READ_ENTITY_PROPERTY(PROP_EMIT_DIMENSIONS, glm::vec3, setEmitDimensions);
READ_ENTITY_PROPERTY(PROP_EMIT_RADIUS_START, float, setEmitRadiusStart);
READ_ENTITY_PROPERTY(PROP_POLAR_START, float, setPolarStart);
READ_ENTITY_PROPERTY(PROP_POLAR_FINISH, float, setPolarFinish);
READ_ENTITY_PROPERTY(PROP_AZIMUTH_START, float, setAzimuthStart);
READ_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, float, setAzimuthFinish);
READ_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration);
READ_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, glm::vec3, setAccelerationSpread);
READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius);
READ_ENTITY_PROPERTY(PROP_RADIUS_SPREAD, float, setRadiusSpread);
READ_ENTITY_PROPERTY(PROP_RADIUS_START, float, setRadiusStart);
READ_ENTITY_PROPERTY(PROP_RADIUS_FINISH, float, setRadiusFinish);
READ_ENTITY_PROPERTY(PROP_COLOR, u8vec3Color, setColor);
READ_ENTITY_PROPERTY(PROP_COLOR_SPREAD, u8vec3Color, setColorSpread);
READ_ENTITY_PROPERTY(PROP_COLOR_START, vec3Color, setColorStart);
READ_ENTITY_PROPERTY(PROP_COLOR_FINISH, vec3Color, setColorFinish);
READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha);
READ_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, float, setAlphaSpread);
READ_ENTITY_PROPERTY(PROP_ALPHA_START, float, setAlphaStart);
READ_ENTITY_PROPERTY(PROP_ALPHA_FINISH, float, setAlphaFinish);
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
READ_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, bool, setEmitterShouldTrail);
READ_ENTITY_PROPERTY(PROP_PARTICLE_SPIN, float, setParticleSpin);
@ -562,36 +580,44 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_COLOR;
requestedProperties += PROP_SHAPE_TYPE;
requestedProperties += PROP_MAX_PARTICLES;
requestedProperties += PROP_LIFESPAN;
requestedProperties += PROP_EMITTING_PARTICLES;
requestedProperties += PROP_EMIT_RATE;
requestedProperties += PROP_EMIT_ACCELERATION;
requestedProperties += PROP_ACCELERATION_SPREAD;
requestedProperties += PROP_PARTICLE_RADIUS;
requestedProperties += PROP_TEXTURES;
requestedProperties += PROP_RADIUS_SPREAD;
requestedProperties += PROP_RADIUS_START;
requestedProperties += PROP_RADIUS_FINISH;
requestedProperties += PROP_COLOR_SPREAD;
requestedProperties += PROP_COLOR_START;
requestedProperties += PROP_COLOR_FINISH;
requestedProperties += PROP_ALPHA;
requestedProperties += PROP_ALPHA_SPREAD;
requestedProperties += PROP_ALPHA_START;
requestedProperties += PROP_ALPHA_FINISH;
requestedProperties += PROP_EMIT_SPEED;
requestedProperties += PROP_SPEED_SPREAD;
requestedProperties += PROP_EMIT_ORIENTATION;
requestedProperties += PROP_EMIT_DIMENSIONS;
requestedProperties += PROP_EMIT_RADIUS_START;
requestedProperties += PROP_POLAR_START;
requestedProperties += PROP_POLAR_FINISH;
requestedProperties += PROP_AZIMUTH_START;
requestedProperties += PROP_AZIMUTH_FINISH;
requestedProperties += PROP_EMIT_ACCELERATION;
requestedProperties += PROP_ACCELERATION_SPREAD;
requestedProperties += PROP_PARTICLE_RADIUS;
requestedProperties += PROP_RADIUS_SPREAD;
requestedProperties += PROP_RADIUS_START;
requestedProperties += PROP_RADIUS_FINISH;
requestedProperties += PROP_COLOR;
requestedProperties += PROP_COLOR_SPREAD;
requestedProperties += PROP_COLOR_START;
requestedProperties += PROP_COLOR_FINISH;
requestedProperties += PROP_ALPHA;
requestedProperties += PROP_ALPHA_SPREAD;
requestedProperties += PROP_ALPHA_START;
requestedProperties += PROP_ALPHA_FINISH;
requestedProperties += PROP_TEXTURES;
requestedProperties += PROP_EMITTER_SHOULD_TRAIL;
requestedProperties += PROP_PARTICLE_SPIN;
requestedProperties += PROP_SPIN_SPREAD;
requestedProperties += PROP_SPIN_START;
@ -610,36 +636,44 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
APPEND_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, getIsEmitting());
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, getMaxParticles());
APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, getLifespan());
APPEND_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, getIsEmitting());
APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, getEmitRate());
APPEND_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, getEmitAcceleration());
APPEND_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, getAccelerationSpread());
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, getParticleRadius());
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
APPEND_ENTITY_PROPERTY(PROP_RADIUS_SPREAD, getRadiusSpread());
APPEND_ENTITY_PROPERTY(PROP_RADIUS_START, getRadiusStart());
APPEND_ENTITY_PROPERTY(PROP_RADIUS_FINISH, getRadiusFinish());
APPEND_ENTITY_PROPERTY(PROP_COLOR_SPREAD, getColorSpread());
APPEND_ENTITY_PROPERTY(PROP_COLOR_START, getColorStart());
APPEND_ENTITY_PROPERTY(PROP_COLOR_FINISH, getColorFinish());
APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha());
APPEND_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, getAlphaSpread());
APPEND_ENTITY_PROPERTY(PROP_ALPHA_START, getAlphaStart());
APPEND_ENTITY_PROPERTY(PROP_ALPHA_FINISH, getAlphaFinish());
APPEND_ENTITY_PROPERTY(PROP_EMIT_SPEED, getEmitSpeed());
APPEND_ENTITY_PROPERTY(PROP_SPEED_SPREAD, getSpeedSpread());
APPEND_ENTITY_PROPERTY(PROP_EMIT_ORIENTATION, getEmitOrientation());
APPEND_ENTITY_PROPERTY(PROP_EMIT_DIMENSIONS, getEmitDimensions());
APPEND_ENTITY_PROPERTY(PROP_EMIT_RADIUS_START, getEmitRadiusStart());
APPEND_ENTITY_PROPERTY(PROP_POLAR_START, getPolarStart());
APPEND_ENTITY_PROPERTY(PROP_POLAR_FINISH, getPolarFinish());
APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_START, getAzimuthStart());
APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, getAzimuthFinish());
APPEND_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, getEmitAcceleration());
APPEND_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, getAccelerationSpread());
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, getParticleRadius());
APPEND_ENTITY_PROPERTY(PROP_RADIUS_SPREAD, getRadiusSpread());
APPEND_ENTITY_PROPERTY(PROP_RADIUS_START, getRadiusStart());
APPEND_ENTITY_PROPERTY(PROP_RADIUS_FINISH, getRadiusFinish());
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
APPEND_ENTITY_PROPERTY(PROP_COLOR_SPREAD, getColorSpread());
APPEND_ENTITY_PROPERTY(PROP_COLOR_START, getColorStart());
APPEND_ENTITY_PROPERTY(PROP_COLOR_FINISH, getColorFinish());
APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha());
APPEND_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, getAlphaSpread());
APPEND_ENTITY_PROPERTY(PROP_ALPHA_START, getAlphaStart());
APPEND_ENTITY_PROPERTY(PROP_ALPHA_FINISH, getAlphaFinish());
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
APPEND_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, getEmitterShouldTrail());
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_SPIN, getParticleSpin());
APPEND_ENTITY_PROPERTY(PROP_SPIN_SPREAD, getSpinSpread());
APPEND_ENTITY_PROPERTY(PROP_SPIN_START, getSpinStart());
@ -647,8 +681,6 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_ROTATE_WITH_ENTITY, getRotateWithEntity());
}
void ParticleEffectEntityItem::debugDump() const {
quint64 now = usecTimestampNow();
qCDebug(entities) << "PA EFFECT EntityItem id:" << getEntityItemID() << "---------------------------------------------";
@ -749,4 +781,4 @@ particle::Properties ParticleEffectEntityItem::getParticleProperties() const {
}
return result;
}
}

View file

@ -43,6 +43,7 @@ EntityItemProperties PolyLineEntityItem::getProperties(const EntityPropertyFlags
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineWidth, getLineWidth);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(linePoints, getLinePoints);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(normals, getNormals);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(strokeColors, getStrokeColors);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(strokeWidths, getStrokeWidths);
@ -59,6 +60,7 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineWidth, setLineWidth);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(linePoints, setLinePoints);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(normals, setNormals);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(strokeColors, setStrokeColors);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(strokeWidths, setStrokeWidths);
@ -203,6 +205,7 @@ int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da
READ_ENTITY_PROPERTY(PROP_COLOR, glm::u8vec3, setColor);
READ_ENTITY_PROPERTY(PROP_LINE_WIDTH, float, setLineWidth);
READ_ENTITY_PROPERTY(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
READ_ENTITY_PROPERTY(PROP_NORMALS, QVector<glm::vec3>, setNormals);
READ_ENTITY_PROPERTY(PROP_STROKE_COLORS, QVector<glm::vec3>, setStrokeColors);
READ_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, QVector<float>, setStrokeWidths);
@ -217,6 +220,7 @@ EntityPropertyFlags PolyLineEntityItem::getEntityProperties(EncodeBitstreamParam
requestedProperties += PROP_COLOR;
requestedProperties += PROP_LINE_WIDTH;
requestedProperties += PROP_LINE_POINTS;
requestedProperties += PROP_NORMALS;
requestedProperties += PROP_STROKE_COLORS;
requestedProperties += PROP_STROKE_WIDTHS;
@ -239,6 +243,7 @@ void PolyLineEntityItem::appendSubclassData(OctreePacketData* packetData, Encode
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
APPEND_ENTITY_PROPERTY(PROP_LINE_WIDTH, getLineWidth());
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, getLinePoints());
APPEND_ENTITY_PROPERTY(PROP_NORMALS, getNormals());
APPEND_ENTITY_PROPERTY(PROP_STROKE_COLORS, getStrokeColors());
APPEND_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, getStrokeWidths());

View file

@ -158,9 +158,9 @@ void ShapeEntityItem::setShape(const entity::Shape& shape) {
bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) {
bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
if (somethingChanged) {
bool wantDebug = false;

View file

@ -27,7 +27,6 @@ const QString TextEntityItem::DEFAULT_TEXT("");
const float TextEntityItem::DEFAULT_LINE_HEIGHT = 0.1f;
const glm::u8vec3 TextEntityItem::DEFAULT_TEXT_COLOR = { 255, 255, 255 };
const glm::u8vec3 TextEntityItem::DEFAULT_BACKGROUND_COLOR = { 0, 0, 0};
const bool TextEntityItem::DEFAULT_FACE_CAMERA = false;
EntityItemPointer TextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItemPointer entity(new TextEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
@ -39,9 +38,8 @@ TextEntityItem::TextEntityItem(const EntityItemID& entityItemID) : EntityItem(en
_type = EntityTypes::Text;
}
const float TEXT_ENTITY_ITEM_FIXED_DEPTH = 0.01f;
void TextEntityItem::setUnscaledDimensions(const glm::vec3& value) {
const float TEXT_ENTITY_ITEM_FIXED_DEPTH = 0.01f;
// NOTE: Text Entities always have a "depth" of 1cm.
EntityItem::setUnscaledDimensions(glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH));
}
@ -53,7 +51,7 @@ EntityItemProperties TextEntityItem::getProperties(const EntityPropertyFlags& de
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textColor, getTextColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(backgroundColor, getBackgroundColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(faceCamera, getFaceCamera);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode);
return properties;
}
@ -65,7 +63,7 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) {
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineHeight, setLineHeight);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textColor, setTextColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(backgroundColor, setBackgroundColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(faceCamera, setFaceCamera);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode);
if (somethingChanged) {
bool wantDebug = false;
@ -93,7 +91,7 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
READ_ENTITY_PROPERTY(PROP_LINE_HEIGHT, float, setLineHeight);
READ_ENTITY_PROPERTY(PROP_TEXT_COLOR, glm::u8vec3, setTextColor);
READ_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, glm::u8vec3, setBackgroundColor);
READ_ENTITY_PROPERTY(PROP_FACE_CAMERA, bool, setFaceCamera);
READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode);
return bytesRead;
}
@ -104,7 +102,7 @@ EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& p
requestedProperties += PROP_LINE_HEIGHT;
requestedProperties += PROP_TEXT_COLOR;
requestedProperties += PROP_BACKGROUND_COLOR;
requestedProperties += PROP_FACE_CAMERA;
requestedProperties += PROP_BILLBOARD_MODE;
return requestedProperties;
}
@ -122,7 +120,7 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, getLineHeight());
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, getTextColor());
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, getBackgroundColor());
APPEND_ENTITY_PROPERTY(PROP_FACE_CAMERA, getFaceCamera());
APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode());
}
@ -230,17 +228,17 @@ glm::u8vec3 TextEntityItem::getBackgroundColor() const {
});
}
bool TextEntityItem::getFaceCamera() const {
bool result;
BillboardMode TextEntityItem::getBillboardMode() const {
BillboardMode result;
withReadLock([&] {
result = _faceCamera;
result = _billboardMode;
});
return result;
}
void TextEntityItem::setFaceCamera(bool value) {
void TextEntityItem::setBillboardMode(BillboardMode value) {
withWriteLock([&] {
_faceCamera = value;
_billboardMode = value;
});
}

View file

@ -71,16 +71,15 @@ public:
glm::u8vec3 getBackgroundColor() const;
void setBackgroundColor(const glm::u8vec3& value);
static const bool DEFAULT_FACE_CAMERA;
bool getFaceCamera() const;
void setFaceCamera(bool value);
BillboardMode getBillboardMode() const;
void setBillboardMode(BillboardMode value);
private:
QString _text;
float _lineHeight;
glm::u8vec3 _textColor;
glm::u8vec3 _backgroundColor;
bool _faceCamera;
BillboardMode _billboardMode;
};
#endif // hifi_TextEntityItem_h

View file

@ -64,10 +64,10 @@ EntityItemProperties ZoneEntityItem::getProperties(const EntityPropertyFlags& de
COPY_ENTITY_PROPERTY_TO_PROPERTIES(ghostingAllowed, getGhostingAllowed);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(filterURL, getFilterURL);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(hazeMode, getHazeMode);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightMode, getKeyLightMode);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(ambientLightMode, getAmbientLightMode);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(skyboxMode, getSkyboxMode);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(hazeMode, getHazeMode);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(bloomMode, getBloomMode);
return properties;
@ -110,10 +110,10 @@ bool ZoneEntityItem::setSubClassProperties(const EntityItemProperties& propertie
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ghostingAllowed, setGhostingAllowed);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(filterURL, setFilterURL);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(hazeMode, setHazeMode);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(keyLightMode, setKeyLightMode);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ambientLightMode, setAmbientLightMode);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(skyboxMode, setSkyboxMode);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(hazeMode, setHazeMode);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(bloomMode, setBloomMode);
somethingChanged = somethingChanged || _keyLightPropertiesChanged || _ambientLightPropertiesChanged ||
@ -185,10 +185,10 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
READ_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, bool, setGhostingAllowed);
READ_ENTITY_PROPERTY(PROP_FILTER_URL, QString, setFilterURL);
READ_ENTITY_PROPERTY(PROP_HAZE_MODE, uint32_t, setHazeMode);
READ_ENTITY_PROPERTY(PROP_KEY_LIGHT_MODE, uint32_t, setKeyLightMode);
READ_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_MODE, uint32_t, setAmbientLightMode);
READ_ENTITY_PROPERTY(PROP_SKYBOX_MODE, uint32_t, setSkyboxMode);
READ_ENTITY_PROPERTY(PROP_HAZE_MODE, uint32_t, setHazeMode);
READ_ENTITY_PROPERTY(PROP_BLOOM_MODE, uint32_t, setBloomMode);
return bytesRead;
@ -197,11 +197,9 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
withReadLock([&] {
requestedProperties += _keyLightProperties.getEntityProperties(params);
requestedProperties += _ambientLightProperties.getEntityProperties(params);
requestedProperties += _skyboxProperties.getEntityProperties(params);
});
requestedProperties += _keyLightProperties.getEntityProperties(params);
requestedProperties += _ambientLightProperties.getEntityProperties(params);
requestedProperties += _skyboxProperties.getEntityProperties(params);
requestedProperties += _hazeProperties.getEntityProperties(params);
requestedProperties += _bloomProperties.getEntityProperties(params);
@ -212,10 +210,10 @@ EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& p
requestedProperties += PROP_GHOSTING_ALLOWED;
requestedProperties += PROP_FILTER_URL;
requestedProperties += PROP_HAZE_MODE;
requestedProperties += PROP_KEY_LIGHT_MODE;
requestedProperties += PROP_AMBIENT_LIGHT_MODE;
requestedProperties += PROP_SKYBOX_MODE;
requestedProperties += PROP_HAZE_MODE;
requestedProperties += PROP_BLOOM_MODE;
return requestedProperties;
@ -231,12 +229,14 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
bool successPropertyFits = true;
_keyLightProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
_ambientLightProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
_skyboxProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
withReadLock([&] {
_keyLightProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
_ambientLightProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
_skyboxProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
});
_hazeProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
_bloomProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
@ -249,10 +249,10 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
APPEND_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, getGhostingAllowed());
APPEND_ENTITY_PROPERTY(PROP_FILTER_URL, getFilterURL());
APPEND_ENTITY_PROPERTY(PROP_HAZE_MODE, (uint32_t)getHazeMode());
APPEND_ENTITY_PROPERTY(PROP_KEY_LIGHT_MODE, (uint32_t)getKeyLightMode());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_MODE, (uint32_t)getAmbientLightMode());
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_MODE, (uint32_t)getSkyboxMode());
APPEND_ENTITY_PROPERTY(PROP_HAZE_MODE, (uint32_t)getHazeMode());
APPEND_ENTITY_PROPERTY(PROP_BLOOM_MODE, (uint32_t)getBloomMode());
}
@ -262,11 +262,11 @@ void ZoneEntityItem::debugDump() const {
qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition());
qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions());
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
qCDebug(entities) << " _hazeMode:" << EntityItemProperties::getComponentModeString(_hazeMode);
qCDebug(entities) << " _keyLightMode:" << EntityItemProperties::getComponentModeString(_keyLightMode);
qCDebug(entities) << " _ambientLightMode:" << EntityItemProperties::getComponentModeString(_ambientLightMode);
qCDebug(entities) << " _skyboxMode:" << EntityItemProperties::getComponentModeString(_skyboxMode);
qCDebug(entities) << " _bloomMode:" << EntityItemProperties::getComponentModeString(_bloomMode);
qCDebug(entities) << " _hazeMode:" << EntityItemProperties::getComponentModeAsString(_hazeMode);
qCDebug(entities) << " _keyLightMode:" << EntityItemProperties::getComponentModeAsString(_keyLightMode);
qCDebug(entities) << " _ambientLightMode:" << EntityItemProperties::getComponentModeAsString(_ambientLightMode);
qCDebug(entities) << " _skyboxMode:" << EntityItemProperties::getComponentModeAsString(_skyboxMode);
qCDebug(entities) << " _bloomMode:" << EntityItemProperties::getComponentModeAsString(_bloomMode);
_keyLightProperties.debugDump();
_ambientLightProperties.debugDump();

View file

@ -126,26 +126,6 @@ QString getID(const QVariantList& properties, int index = 0) {
return processID(properties.at(index).toString());
}
/// The names of the joints in the Maya HumanIK rig
static const std::array<const char*, 16> HUMANIK_JOINTS = {{
"RightHand",
"RightForeArm",
"RightArm",
"Head",
"LeftArm",
"LeftForeArm",
"LeftHand",
"Neck",
"Spine",
"Hips",
"RightUpLeg",
"LeftUpLeg",
"RightLeg",
"LeftLeg",
"RightFoot",
"LeftFoot"
}};
class FBXModel {
public:
QString name;
@ -478,32 +458,6 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
std::map<QString, HFMLight> lights;
QVariantHash joints = mapping.value("joint").toHash();
QString jointEyeLeftName = "EyeLeft";
QString jointEyeRightName = "EyeRight";
QString jointNeckName = "Neck";
QString jointRootName = "Hips";
QString jointLeanName = "Spine";
QString jointHeadName = "Head";
QString jointLeftHandName = "LeftHand";
QString jointRightHandName = "RightHand";
QString jointEyeLeftID;
QString jointEyeRightID;
QString jointNeckID;
QString jointRootID;
QString jointLeanID;
QString jointHeadID;
QString jointLeftHandID;
QString jointRightHandID;
QString jointLeftToeID;
QString jointRightToeID;
QVector<QString> humanIKJointNames;
for (int i = 0; i < (int) HUMANIK_JOINTS.size(); i++) {
QByteArray jointName = HUMANIK_JOINTS[i];
humanIKJointNames.append(processID(getString(joints.value(jointName, jointName))));
}
QVector<QString> humanIKJointIDs(humanIKJointNames.size());
QVariantHash blendshapeMappings = mapping.value("bs").toHash();
@ -602,42 +556,6 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
hifiGlobalNodeID = id;
}
if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye" || (hfmModel.hfmToHifiJointNameMapping.contains(jointEyeLeftName) && (name == hfmModel.hfmToHifiJointNameMapping[jointEyeLeftName]))) {
jointEyeLeftID = getID(object.properties);
} else if (name == jointEyeRightName || name == "EyeR" || name == "joint_Reye" || (hfmModel.hfmToHifiJointNameMapping.contains(jointEyeRightName) && (name == hfmModel.hfmToHifiJointNameMapping[jointEyeRightName]))) {
jointEyeRightID = getID(object.properties);
} else if (name == jointNeckName || name == "NeckRot" || name == "joint_neck" || (hfmModel.hfmToHifiJointNameMapping.contains(jointNeckName) && (name == hfmModel.hfmToHifiJointNameMapping[jointNeckName]))) {
jointNeckID = getID(object.properties);
} else if (name == jointRootName || (hfmModel.hfmToHifiJointNameMapping.contains(jointRootName) && (name == hfmModel.hfmToHifiJointNameMapping[jointRootName]))) {
jointRootID = getID(object.properties);
} else if (name == jointLeanName || (hfmModel.hfmToHifiJointNameMapping.contains(jointLeanName) && (name == hfmModel.hfmToHifiJointNameMapping[jointLeanName]))) {
jointLeanID = getID(object.properties);
} else if ((name == jointHeadName) || (hfmModel.hfmToHifiJointNameMapping.contains(jointHeadName) && (name == hfmModel.hfmToHifiJointNameMapping[jointHeadName]))) {
jointHeadID = getID(object.properties);
} else if (name == jointLeftHandName || name == "LeftHand" || name == "joint_L_hand" || (hfmModel.hfmToHifiJointNameMapping.contains(jointLeftHandName) && (name == hfmModel.hfmToHifiJointNameMapping[jointLeftHandName]))) {
jointLeftHandID = getID(object.properties);
} else if (name == jointRightHandName || name == "RightHand" || name == "joint_R_hand" || (hfmModel.hfmToHifiJointNameMapping.contains(jointRightHandName) && (name == hfmModel.hfmToHifiJointNameMapping[jointRightHandName]))) {
jointRightHandID = getID(object.properties);
} else if (name == "LeftToe" || name == "joint_L_toe" || name == "LeftToe_End" || (hfmModel.hfmToHifiJointNameMapping.contains("LeftToe") && (name == hfmModel.hfmToHifiJointNameMapping["LeftToe"]))) {
jointLeftToeID = getID(object.properties);
} else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End" || (hfmModel.hfmToHifiJointNameMapping.contains("RightToe") && (name == hfmModel.hfmToHifiJointNameMapping["RightToe"]))) {
jointRightToeID = getID(object.properties);
}
int humanIKJointIndex = humanIKJointNames.indexOf(name);
if (humanIKJointIndex != -1) {
humanIKJointIDs[humanIKJointIndex] = getID(object.properties);
}
glm::vec3 translation;
// NOTE: the euler angles as supplied by the FBX file are in degrees
glm::vec3 rotationOffset;
@ -1449,28 +1367,6 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
std::vector<ShapeVertices> shapeVertices;
shapeVertices.resize(std::max(1, hfmModel.joints.size()) );
// find our special joints
hfmModel.leftEyeJointIndex = modelIDs.indexOf(jointEyeLeftID);
hfmModel.rightEyeJointIndex = modelIDs.indexOf(jointEyeRightID);
hfmModel.neckJointIndex = modelIDs.indexOf(jointNeckID);
hfmModel.rootJointIndex = modelIDs.indexOf(jointRootID);
hfmModel.leanJointIndex = modelIDs.indexOf(jointLeanID);
hfmModel.headJointIndex = modelIDs.indexOf(jointHeadID);
hfmModel.leftHandJointIndex = modelIDs.indexOf(jointLeftHandID);
hfmModel.rightHandJointIndex = modelIDs.indexOf(jointRightHandID);
hfmModel.leftToeJointIndex = modelIDs.indexOf(jointLeftToeID);
hfmModel.rightToeJointIndex = modelIDs.indexOf(jointRightToeID);
foreach (const QString& id, humanIKJointIDs) {
hfmModel.humanIKJointIndices.append(modelIDs.indexOf(id));
}
// extract the translation component of the neck transform
if (hfmModel.neckJointIndex != -1) {
const glm::mat4& transform = hfmModel.joints.at(hfmModel.neckJointIndex).transform;
hfmModel.neckPivot = glm::vec3(transform[3][0], transform[3][1], transform[3][2]);
}
hfmModel.bindExtents.reset();
hfmModel.meshExtents.reset();

View file

@ -533,14 +533,13 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
QJsonDocument d = QJsonDocument::fromJson(data);
QJsonObject jsFile = d.object();
bool isvalid = setAsset(jsFile);
if (isvalid) {
bool success = setAsset(jsFile);
if (success) {
QJsonArray accessors;
if (getObjectArrayVal(jsFile, "accessors", accessors, _file.defined)) {
foreach(const QJsonValue & accVal, accessors) {
if (accVal.isObject()) {
addAccessor(accVal.toObject());
success = success && addAccessor(accVal.toObject());
}
}
}
@ -549,7 +548,7 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
if (getObjectArrayVal(jsFile, "animations", animations, _file.defined)) {
foreach(const QJsonValue & animVal, accessors) {
if (animVal.isObject()) {
addAnimation(animVal.toObject());
success = success && addAnimation(animVal.toObject());
}
}
}
@ -558,7 +557,7 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
if (getObjectArrayVal(jsFile, "bufferViews", bufferViews, _file.defined)) {
foreach(const QJsonValue & bufviewVal, bufferViews) {
if (bufviewVal.isObject()) {
addBufferView(bufviewVal.toObject());
success = success && addBufferView(bufviewVal.toObject());
}
}
}
@ -567,7 +566,7 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
if (getObjectArrayVal(jsFile, "buffers", buffers, _file.defined)) {
foreach(const QJsonValue & bufVal, buffers) {
if (bufVal.isObject()) {
addBuffer(bufVal.toObject());
success = success && addBuffer(bufVal.toObject());
}
}
}
@ -576,7 +575,7 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
if (getObjectArrayVal(jsFile, "cameras", cameras, _file.defined)) {
foreach(const QJsonValue & camVal, cameras) {
if (camVal.isObject()) {
addCamera(camVal.toObject());
success = success && addCamera(camVal.toObject());
}
}
}
@ -585,7 +584,7 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
if (getObjectArrayVal(jsFile, "images", images, _file.defined)) {
foreach(const QJsonValue & imgVal, images) {
if (imgVal.isObject()) {
addImage(imgVal.toObject());
success = success && addImage(imgVal.toObject());
}
}
}
@ -594,7 +593,7 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
if (getObjectArrayVal(jsFile, "materials", materials, _file.defined)) {
foreach(const QJsonValue & matVal, materials) {
if (matVal.isObject()) {
addMaterial(matVal.toObject());
success = success && addMaterial(matVal.toObject());
}
}
}
@ -603,7 +602,7 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
if (getObjectArrayVal(jsFile, "meshes", meshes, _file.defined)) {
foreach(const QJsonValue & meshVal, meshes) {
if (meshVal.isObject()) {
addMesh(meshVal.toObject());
success = success && addMesh(meshVal.toObject());
}
}
}
@ -612,7 +611,7 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
if (getObjectArrayVal(jsFile, "nodes", nodes, _file.defined)) {
foreach(const QJsonValue & nodeVal, nodes) {
if (nodeVal.isObject()) {
addNode(nodeVal.toObject());
success = success && addNode(nodeVal.toObject());
}
}
}
@ -621,7 +620,7 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
if (getObjectArrayVal(jsFile, "samplers", samplers, _file.defined)) {
foreach(const QJsonValue & samVal, samplers) {
if (samVal.isObject()) {
addSampler(samVal.toObject());
success = success && addSampler(samVal.toObject());
}
}
}
@ -630,7 +629,7 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
if (getObjectArrayVal(jsFile, "scenes", scenes, _file.defined)) {
foreach(const QJsonValue & sceneVal, scenes) {
if (sceneVal.isObject()) {
addScene(sceneVal.toObject());
success = success && addScene(sceneVal.toObject());
}
}
}
@ -639,7 +638,7 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
if (getObjectArrayVal(jsFile, "skins", skins, _file.defined)) {
foreach(const QJsonValue & skinVal, skins) {
if (skinVal.isObject()) {
addSkin(skinVal.toObject());
success = success && addSkin(skinVal.toObject());
}
}
}
@ -648,15 +647,12 @@ bool GLTFSerializer::parseGLTF(const QByteArray& data) {
if (getObjectArrayVal(jsFile, "textures", textures, _file.defined)) {
foreach(const QJsonValue & texVal, textures) {
if (texVal.isObject()) {
addTexture(texVal.toObject());
success = success && addTexture(texVal.toObject());
}
}
}
} else {
qCDebug(modelformat) << "Error parsing GLTF file.";
return false;
}
return true;
}
return success;
}
glm::mat4 GLTFSerializer::getModelTransform(const GLTFNode& node) {
@ -927,16 +923,20 @@ HFMModel::Pointer GLTFSerializer::read(const QByteArray& data, const QVariantHas
_url = QUrl(QFileInfo(localFileName).absoluteFilePath());
}
parseGLTF(data);
//_file.dump();
auto hfmModelPtr = std::make_shared<HFMModel>();
HFMModel& hfmModel = *hfmModelPtr;
if (parseGLTF(data)) {
//_file.dump();
auto hfmModelPtr = std::make_shared<HFMModel>();
HFMModel& hfmModel = *hfmModelPtr;
buildGeometry(hfmModel, _url);
//hfmDebugDump(data);
return hfmModelPtr;
buildGeometry(hfmModel, _url);
//hfmDebugDump(data);
return hfmModelPtr;
} else {
qCDebug(modelformat) << "Error parsing GLTF file.";
}
return nullptr;
}
bool GLTFSerializer::readBinary(const QString& url, QByteArray& outdata) {
@ -1188,19 +1188,6 @@ void GLTFSerializer::hfmDebugDump(const HFMModel& hfmModel) {
qCDebug(modelformat) << " hasSkeletonJoints =" << hfmModel.hasSkeletonJoints;
qCDebug(modelformat) << " offset =" << hfmModel.offset;
qCDebug(modelformat) << " leftEyeJointIndex =" << hfmModel.leftEyeJointIndex;
qCDebug(modelformat) << " rightEyeJointIndex =" << hfmModel.rightEyeJointIndex;
qCDebug(modelformat) << " neckJointIndex =" << hfmModel.neckJointIndex;
qCDebug(modelformat) << " rootJointIndex =" << hfmModel.rootJointIndex;
qCDebug(modelformat) << " leanJointIndex =" << hfmModel.leanJointIndex;
qCDebug(modelformat) << " headJointIndex =" << hfmModel.headJointIndex;
qCDebug(modelformat) << " leftHandJointIndex" << hfmModel.leftHandJointIndex;
qCDebug(modelformat) << " rightHandJointIndex" << hfmModel.rightHandJointIndex;
qCDebug(modelformat) << " leftToeJointIndex" << hfmModel.leftToeJointIndex;
qCDebug(modelformat) << " rightToeJointIndex" << hfmModel.rightToeJointIndex;
qCDebug(modelformat) << " leftEyeSize = " << hfmModel.leftEyeSize;
qCDebug(modelformat) << " rightEyeSize = " << hfmModel.rightEyeSize;
qCDebug(modelformat) << " palmDirection = " << hfmModel.palmDirection;
qCDebug(modelformat) << " neckPivot = " << hfmModel.neckPivot;

View file

@ -270,22 +270,6 @@ public:
glm::mat4 offset; // This includes offset, rotation, and scale as specified by the FST file
int leftEyeJointIndex = -1;
int rightEyeJointIndex = -1;
int neckJointIndex = -1;
int rootJointIndex = -1;
int leanJointIndex = -1;
int headJointIndex = -1;
int leftHandJointIndex = -1;
int rightHandJointIndex = -1;
int leftToeJointIndex = -1;
int rightToeJointIndex = -1;
float leftEyeSize = 0.0f; // Maximum mesh extents dimension
float rightEyeSize = 0.0f;
QVector<int> humanIKJointIndices;
glm::vec3 palmDirection;
glm::vec3 neckPivot;

View file

@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::EntityEdit:
case PacketType::EntityData:
case PacketType::EntityPhysics:
return static_cast<PacketVersion>(EntityVersion::EntityHostTypes);
return static_cast<PacketVersion>(EntityVersion::ImageEntities);
case PacketType::EntityQuery:
return static_cast<PacketVersion>(EntityQueryPacketVersion::ConicalFrustums);
case PacketType::AvatarIdentity:

View file

@ -246,7 +246,9 @@ enum class EntityVersion : PacketVersion {
ScriptGlmVectors,
FixedLightSerialization,
MaterialRepeat,
EntityHostTypes
EntityHostTypes,
CleanupProperties,
ImageEntities
};
enum class EntityScriptCallMethodVersion : PacketVersion {

View file

@ -546,6 +546,17 @@ bool OctreePacketData::appendValue(const AACube& aaCube) {
return success;
}
bool OctreePacketData::appendValue(const QRect& value) {
const unsigned char* data = (const unsigned char*)&value;
int length = sizeof(QRect);
bool success = append(data, length);
if (success) {
_bytesOfValues += length;
_totalBytesOfValues += length;
}
return success;
}
bool OctreePacketData::appendPosition(const glm::vec3& value) {
const unsigned char* data = (const unsigned char*)&value;
int length = sizeof(value);
@ -804,3 +815,8 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, AACube
result = AACube(cube.corner, cube.scale);
return sizeof(aaCubeData);
}
int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QRect& result) {
memcpy(&result, dataBytes, sizeof(result));
return sizeof(result);
}

View file

@ -34,6 +34,7 @@
#include <udt/PacketHeaders.h>
#include "MaterialMappingMode.h"
#include "BillboardMode.h"
#include "OctreeConstants.h"
#include "OctreeElement.h"
@ -197,6 +198,9 @@ public:
/// appends an AACube value to the end of the stream, may fail if new data stream is too long to fit in packet
bool appendValue(const AACube& aaCube);
/// appends an QRect value to the end of the stream, may fail if new data stream is too long to fit in packet
bool appendValue(const QRect& rect);
/// appends a position to the end of the stream, may fail if new data stream is too long to fit in packet
bool appendPosition(const glm::vec3& value);
@ -258,6 +262,7 @@ public:
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::quat& result) { int bytes = unpackOrientationQuatFromBytes(dataBytes, result); return bytes; }
static int unpackDataFromBytes(const unsigned char* dataBytes, ShapeType& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
static int unpackDataFromBytes(const unsigned char* dataBytes, MaterialMappingMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
static int unpackDataFromBytes(const unsigned char* dataBytes, BillboardMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec2& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::u8vec3& result);
@ -269,6 +274,7 @@ public:
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<bool>& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, AACube& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, QRect& result);
private:
/// appends raw bytes, might fail if byte would cause packet to be too large

View file

@ -137,7 +137,7 @@ void CauterizedModel::updateClusterMatrices() {
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
if (!_cauterizeBoneSet.empty()) {
AnimPose cauterizePose = _rig.getJointPose(hfmModel.neckJointIndex);
AnimPose cauterizePose = _rig.getJointPose(_rig.indexOfJoint("Neck"));
cauterizePose.scale() = glm::vec3(0.0001f, 0.0001f, 0.0001f);
static const glm::mat4 zeroScale(
@ -145,7 +145,7 @@ void CauterizedModel::updateClusterMatrices() {
glm::vec4(0.0f, 0.0001f, 0.0f, 0.0f),
glm::vec4(0.0f, 0.0f, 0.0001f, 0.0f),
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
auto cauterizeMatrix = _rig.getJointTransform(hfmModel.neckJointIndex) * zeroScale;
auto cauterizeMatrix = _rig.getJointTransform(_rig.indexOfJoint("Neck")) * zeroScale;
for (int i = 0; i < _cauterizeMeshStates.size(); i++) {
Model::MeshState& state = _cauterizeMeshStates[i];

View file

@ -0,0 +1,25 @@
//
// Created by Sam Gondelman on 11/30/18
// Copyright 2018 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 "BillboardMode.h"
const char* billboardModeNames[] = {
"none",
"yaw",
"full"
};
static const size_t MATERIAL_MODE_NAMES = (sizeof(billboardModeNames) / sizeof((billboardModeNames)[0]));
QString BillboardModeHelpers::getNameForBillboardMode(BillboardMode mode) {
if (((int)mode <= 0) || ((int)mode >= (int)MATERIAL_MODE_NAMES)) {
mode = (BillboardMode)0;
}
return billboardModeNames[(int)mode];
}

View file

@ -0,0 +1,41 @@
//
// Created by Sam Gondelman on 11/30/18.
// Copyright 2018 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_BillboardMode_h
#define hifi_BillboardMode_h
#include "QString"
/**jsdoc
* <p>How an entity is billboarded.</p>
* <table>
* <thead>
* <tr><th>Value</th><th>Description</th></tr>
* </thead>
* <tbody>
* <tr><td><code>none</code></td><td>The entity will not be billboarded.</td></tr>
* <tr><td><code>yaw</code></td><td>The entity will yaw, but not pitch, to face the camera. Its actual rotation will be ignored.</td></tr>
* <tr><td><code>full</code></td><td>The entity will be billboarded to face the camera. Its actual rotation will be ignored.</td></tr>
* </tbody>
* </table>
* @typedef {string} BillboardMode
*/
enum class BillboardMode {
NONE = 0,
YAW,
FULL
};
class BillboardModeHelpers {
public:
static QString getNameForBillboardMode(BillboardMode mode);
};
#endif // hifi_BillboardMode_h

View file

@ -24,6 +24,7 @@
#include <QtNetwork/QAbstractSocket>
#include <QtScript/QScriptValue>
#include <QtScript/QScriptValueIterator>
#include <QJsonDocument>
int vec2MetaTypeId = qRegisterMetaType<glm::vec2>();
int u8vec3MetaTypeId = qRegisterMetaType<u8vec3>();
@ -1245,3 +1246,31 @@ void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector<MeshFace>
result << meshFace;
}
}
QVariantMap parseTexturesToMap(QString textures, const QVariantMap& defaultTextures) {
// If textures are unset, revert to original textures
if (textures.isEmpty()) {
return defaultTextures;
}
// Legacy: a ,\n-delimited list of filename:"texturepath"
if (*textures.cbegin() != '{') {
textures = "{\"" + textures.replace(":\"", "\":\"").replace(",\n", ",\"") + "}";
}
QJsonParseError error;
QJsonDocument texturesJson = QJsonDocument::fromJson(textures.toUtf8(), &error);
// If textures are invalid, revert to original textures
if (error.error != QJsonParseError::NoError) {
qWarning() << "Could not evaluate textures property value:" << textures;
return defaultTextures;
}
QVariantMap texturesMap = texturesJson.toVariant().toMap();
// If textures are unset, revert to original textures
if (texturesMap.isEmpty()) {
return defaultTextures;
}
return texturesJson.toVariant().toMap();
}

View file

@ -705,5 +705,7 @@ void meshFaceFromScriptValue(const QScriptValue &object, MeshFace& meshFaceResul
QScriptValue qVectorMeshFaceToScriptValue(QScriptEngine* engine, const QVector<MeshFace>& vector);
void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector<MeshFace>& result);
QVariantMap parseTexturesToMap(QString textures, const QVariantMap& defaultTextures);
#endif // hifi_RegisteredMetaTypes_h

View file

@ -377,6 +377,7 @@ void TabletProxy::setToolbarMode(bool toolbarMode) {
QObject::connect(quickItem, SIGNAL(windowClosed()), this, SLOT(desktopWindowClosed()));
QObject::connect(tabletRootWindow, SIGNAL(webEventReceived(QVariant)), this, SLOT(emitWebEvent(QVariant)), Qt::DirectConnection);
QObject::connect(quickItem, SIGNAL(screenChanged(QVariant, QVariant)), this, SIGNAL(screenChanged(QVariant, QVariant)), Qt::DirectConnection);
// forward qml surface events to interface js
connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml);
@ -488,6 +489,7 @@ void TabletProxy::setQmlTabletRoot(OffscreenQmlSurface* qmlOffscreenSurface) {
_qmlTabletRoot = qmlOffscreenSurface ? qmlOffscreenSurface->getRootItem() : nullptr;
if (_qmlTabletRoot && _qmlOffscreenSurface) {
QObject::connect(_qmlOffscreenSurface, SIGNAL(webEventReceived(QVariant)), this, SLOT(emitWebEvent(QVariant)));
QObject::connect(_qmlTabletRoot, SIGNAL(screenChanged(QVariant, QVariant)), this, SIGNAL(screenChanged(QVariant, QVariant)));
// forward qml surface events to interface js
connect(_qmlOffscreenSurface, &OffscreenQmlSurface::fromQml, [this](QVariant message) {
@ -570,7 +572,6 @@ void TabletProxy::gotoMenuScreen(const QString& submenu) {
QMetaObject::invokeMethod(root, "setMenuProperties", Q_ARG(QVariant, QVariant::fromValue(menu)), Q_ARG(const QVariant&, QVariant(submenu)));
QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, QVariant(VRMENU_SOURCE_URL)));
_state = State::Menu;
emit screenChanged(QVariant("Menu"), QVariant(VRMENU_SOURCE_URL));
_currentPathLoaded = VRMENU_SOURCE_URL;
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
if (_toolbarMode && _desktopWindow) {
@ -640,9 +641,6 @@ void TabletProxy::loadQMLSource(const QVariant& path, bool resizable) {
if (root) {
QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, path));
_state = State::QML;
if (path != _currentPathLoaded) {
emit screenChanged(QVariant("QML"), path);
}
_currentPathLoaded = path;
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
if (_toolbarMode && _desktopWindow) {
@ -749,7 +747,6 @@ void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) {
}
}
_state = State::Home;
emit screenChanged(QVariant("Home"), QVariant(TABLET_HOME_SOURCE_URL));
_currentPathLoaded = TABLET_HOME_SOURCE_URL;
}
}
@ -810,7 +807,6 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS
QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(false)));
}
_state = State::Web;
emit screenChanged(QVariant("Web"), QVariant(url));
_currentPathLoaded = QVariant(url);
} else {
// tablet is not initialized yet, save information and load when

View file

@ -433,7 +433,6 @@ function fromQml(message) {
}
break;
case 'needsLogIn_loginClicked':
ui.close();
openLoginWindow();
break;
case 'disableHmdPreview':

View file

@ -42,7 +42,6 @@ var TITLE_OFFSET = 60;
var CREATE_TOOLS_WIDTH = 490;
var MAX_DEFAULT_ENTITY_LIST_HEIGHT = 942;
var IMAGE_MODEL = "https://hifi-content.s3.amazonaws.com/DomainContent/production/default-image-model.fbx";
var DEFAULT_IMAGE = "https://hifi-content.s3.amazonaws.com/DomainContent/production/no-image.jpg";
var createToolsWindow = new CreateWindow(
@ -398,8 +397,8 @@ const DEFAULT_ENTITY_PROPERTIES = {
},
shapeType: "box",
collisionless: true,
modelURL: IMAGE_MODEL,
textures: JSON.stringify({ "tex.picture": "" })
keepAspectRatio: false,
imageURL: DEFAULT_IMAGE
},
Web: {
dimensions: {
@ -495,9 +494,6 @@ var toolBar = (function () {
var type = requestedProperties.type;
if (type === "Box" || type === "Sphere") {
applyProperties(properties, DEFAULT_ENTITY_PROPERTIES.Shape);
} else if (type === "Image") {
requestedProperties.type = "Model";
applyProperties(properties, DEFAULT_ENTITY_PROPERTIES.Image);
} else {
applyProperties(properties, DEFAULT_ENTITY_PROPERTIES[type]);
}
@ -515,7 +511,7 @@ var toolBar = (function () {
}
direction = Vec3.multiplyQbyV(direction, Vec3.UNIT_Z);
var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Web", "Material"];
var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Image", "Web", "Material"];
if (PRE_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) {
// Adjust position of entity per bounding box prior to creating it.

View file

@ -11,7 +11,6 @@ const DESCENDING_SORT = -1;
const ASCENDING_STRING = '&#x25B4;';
const DESCENDING_STRING = '&#x25BE;';
const BYTES_PER_MEGABYTE = 1024 * 1024;
const IMAGE_MODEL_NAME = 'default-image-model.fbx';
const COLLAPSE_EXTRA_INFO = "E";
const EXPAND_EXTRA_INFO = "D";
const FILTER_IN_VIEW_ATTRIBUTE = "pressed";
@ -628,9 +627,6 @@ function loaded() {
entityData.forEach(function(entity) {
let type = entity.type;
let filename = getFilename(entity.url);
if (filename === IMAGE_MODEL_NAME) {
type = "Image";
}
let entityData = {
id: entity.id,

View file

@ -476,7 +476,7 @@ const GROUPS = [
label: "Image",
type: "string",
placeholder: "URL",
propertyID: "image",
propertyID: "imageURL",
},
]
},
@ -1821,14 +1821,6 @@ function updateCheckedSubProperty(propertyName, propertyValue, subPropertyElemen
updateProperty(propertyName, propertyValue, isParticleProperty);
}
function createImageURLUpdateFunction(property) {
return function () {
let newTextures = JSON.stringify({ "tex.picture": this.value });
updateProperty(property.name, newTextures, property.isParticleProperty);
};
}
/**
* PROPERTY ELEMENT CREATION FUNCTIONS
*/
@ -3132,17 +3124,6 @@ function loaded() {
// the event bridge and json parsing handle our avatar id string differently.
lastEntityID = '"' + selectedEntityProperties.id + '"';
// HTML workaround since image is not yet a separate entity type
let IMAGE_MODEL_NAME = 'default-image-model.fbx';
if (selectedEntityProperties.type === "Model") {
let urlParts = selectedEntityProperties.modelURL.split('/');
let propsFilename = urlParts[urlParts.length - 1];
if (propsFilename === IMAGE_MODEL_NAME) {
selectedEntityProperties.type = "Image";
}
}
showGroupsForType(selectedEntityProperties.type);
if (selectedEntityProperties.locked) {
@ -3290,10 +3271,7 @@ function loaded() {
updateVisibleSpaceModeProperties();
if (selectedEntityProperties.type === "Image") {
let imageLink = JSON.parse(selectedEntityProperties.textures)["tex.picture"];
getPropertyInputElement("image").value = imageLink;
} else if (selectedEntityProperties.type === "Material") {
if (selectedEntityProperties.type === "Material") {
let elParentMaterialNameString = getPropertyInputElement("materialNameToReplace");
let elParentMaterialNameNumber = getPropertyInputElement("submeshToReplace");
let elParentMaterialNameCheckbox = getPropertyInputElement("selectSubmesh");
@ -3456,8 +3434,6 @@ function loaded() {
}
});
getPropertyInputElement("image").addEventListener('change', createImageURLUpdateFunction(properties['textures']));
// Collapsible sections
let elCollapsible = document.getElementsByClassName("collapse-icon");

View file

@ -164,7 +164,7 @@ EntityListTool = function(shouldUseEditTabletApp) {
var cameraPosition = Camera.position;
PROFILE("getMultipleProperties", function () {
var multipleProperties = Entities.getMultipleEntityProperties(ids, ['name', 'type', 'locked',
'visible', 'renderInfo', 'modelURL', 'materialURL', 'script', 'certificateID']);
'visible', 'renderInfo', 'modelURL', 'materialURL', 'imageURL', 'script', 'certificateID']);
for (var i = 0; i < multipleProperties.length; i++) {
var properties = multipleProperties[i];
@ -174,6 +174,8 @@ EntityListTool = function(shouldUseEditTabletApp) {
url = properties.modelURL;
} else if (properties.type === "Material") {
url = properties.materialURL;
} else if (properties.type === "Image") {
url = properties.imageURL;
}
entities.push({
id: ids[i],