mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 21:12:53 +02:00
merge with master
This commit is contained in:
commit
5652fa0b1e
257 changed files with 6445 additions and 2496 deletions
|
@ -7,6 +7,11 @@ else()
|
||||||
cmake_minimum_required(VERSION 3.2)
|
cmake_minimum_required(VERSION 3.2)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# squelch the Policy CMP0074 warning without requiring an update to cmake 3.12.
|
||||||
|
if ((${CMAKE_MAJOR_VERSION} EQUAL 3 AND ${CMAKE_MINOR_VERSION} GREATER 11) OR ${CMAKE_MAJOR_VERSION} GREATER 3)
|
||||||
|
cmake_policy(SET CMP0074 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
project(hifi)
|
project(hifi)
|
||||||
|
|
||||||
include("cmake/init.cmake")
|
include("cmake/init.cmake")
|
||||||
|
|
1
android/gradle.properties
Normal file
1
android/gradle.properties
Normal file
|
@ -0,0 +1 @@
|
||||||
|
org.gradle.jvmargs=-Xms2g -Xmx4g
|
|
@ -368,11 +368,7 @@ void Agent::executeScript() {
|
||||||
|
|
||||||
// setup an Avatar for the script to use
|
// setup an Avatar for the script to use
|
||||||
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
|
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
|
||||||
|
|
||||||
scriptedAvatar->setID(getSessionUUID());
|
scriptedAvatar->setID(getSessionUUID());
|
||||||
|
|
||||||
connect(_scriptEngine.data(), SIGNAL(update(float)),
|
|
||||||
scriptedAvatar.data(), SLOT(update(float)), Qt::ConnectionType::QueuedConnection);
|
|
||||||
scriptedAvatar->setForceFaceTrackerConnected(true);
|
scriptedAvatar->setForceFaceTrackerConnected(true);
|
||||||
|
|
||||||
// call model URL setters with empty URLs so our avatar, if user, will have the default models
|
// call model URL setters with empty URLs so our avatar, if user, will have the default models
|
||||||
|
@ -504,8 +500,6 @@ void Agent::executeScript() {
|
||||||
|
|
||||||
DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree());
|
DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree());
|
||||||
|
|
||||||
_avatarAudioTimer.start();
|
|
||||||
|
|
||||||
// Agents should run at 45hz
|
// Agents should run at 45hz
|
||||||
static const int AVATAR_DATA_HZ = 45;
|
static const int AVATAR_DATA_HZ = 45;
|
||||||
static const int AVATAR_DATA_IN_MSECS = MSECS_PER_SECOND / AVATAR_DATA_HZ;
|
static const int AVATAR_DATA_IN_MSECS = MSECS_PER_SECOND / AVATAR_DATA_HZ;
|
||||||
|
@ -530,7 +524,8 @@ void Agent::executeScript() {
|
||||||
}
|
}
|
||||||
|
|
||||||
avatarDataTimer->stop();
|
avatarDataTimer->stop();
|
||||||
_avatarAudioTimer.stop();
|
|
||||||
|
setIsAvatar(false); // will stop timers for sending identity packets
|
||||||
}
|
}
|
||||||
|
|
||||||
setFinished(true);
|
setFinished(true);
|
||||||
|
@ -582,28 +577,33 @@ void Agent::setIsAvatar(bool isAvatar) {
|
||||||
}
|
}
|
||||||
_isAvatar = isAvatar;
|
_isAvatar = isAvatar;
|
||||||
|
|
||||||
if (_isAvatar && !_avatarIdentityTimer) {
|
auto scriptableAvatar = DependencyManager::get<ScriptableAvatar>();
|
||||||
// set up the avatar timers
|
if (_isAvatar) {
|
||||||
_avatarIdentityTimer = new QTimer(this);
|
if (!_avatarIdentityTimer) {
|
||||||
_avatarQueryTimer = new QTimer(this);
|
// set up the avatar timers
|
||||||
|
_avatarIdentityTimer = new QTimer(this);
|
||||||
|
_avatarQueryTimer = new QTimer(this);
|
||||||
|
|
||||||
// connect our slot
|
// connect our slot
|
||||||
connect(_avatarIdentityTimer, &QTimer::timeout, this, &Agent::sendAvatarIdentityPacket);
|
connect(_avatarIdentityTimer, &QTimer::timeout, this, &Agent::sendAvatarIdentityPacket);
|
||||||
connect(_avatarQueryTimer, &QTimer::timeout, this, &Agent::queryAvatars);
|
connect(_avatarQueryTimer, &QTimer::timeout, this, &Agent::queryAvatars);
|
||||||
|
|
||||||
static const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000;
|
static const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000;
|
||||||
static const int AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS = 1000;
|
static const int AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS = 1000;
|
||||||
|
|
||||||
// start the timers
|
// start the timers
|
||||||
_avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); // FIXME - we shouldn't really need to constantly send identity packets
|
_avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); // FIXME - we shouldn't really need to constantly send identity packets
|
||||||
_avatarQueryTimer->start(AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS);
|
_avatarQueryTimer->start(AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS);
|
||||||
|
|
||||||
// tell the avatarAudioTimer to start ticking
|
connect(_scriptEngine.data(), &ScriptEngine::update,
|
||||||
QMetaObject::invokeMethod(&_avatarAudioTimer, "start");
|
scriptableAvatar.data(), &ScriptableAvatar::update, Qt::QueuedConnection);
|
||||||
}
|
|
||||||
|
|
||||||
if (!_isAvatar) {
|
// tell the avatarAudioTimer to start ticking
|
||||||
|
QMetaObject::invokeMethod(&_avatarAudioTimer, "start");
|
||||||
|
}
|
||||||
|
|
||||||
|
_entityEditSender.setMyAvatar(scriptableAvatar.data());
|
||||||
|
} else {
|
||||||
if (_avatarIdentityTimer) {
|
if (_avatarIdentityTimer) {
|
||||||
_avatarIdentityTimer->stop();
|
_avatarIdentityTimer->stop();
|
||||||
delete _avatarIdentityTimer;
|
delete _avatarIdentityTimer;
|
||||||
|
@ -630,14 +630,14 @@ void Agent::setIsAvatar(bool isAvatar) {
|
||||||
packet->writePrimitive(KillAvatarReason::NoReason);
|
packet->writePrimitive(KillAvatarReason::NoReason);
|
||||||
nodeList->sendPacket(std::move(packet), *node);
|
nodeList->sendPacket(std::move(packet), *node);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
disconnect(_scriptEngine.data(), &ScriptEngine::update,
|
||||||
|
scriptableAvatar.data(), &ScriptableAvatar::update);
|
||||||
|
|
||||||
|
QMetaObject::invokeMethod(&_avatarAudioTimer, "stop");
|
||||||
}
|
}
|
||||||
|
|
||||||
QMetaObject::invokeMethod(&_avatarAudioTimer, "stop");
|
|
||||||
|
|
||||||
_entityEditSender.setMyAvatar(nullptr);
|
_entityEditSender.setMyAvatar(nullptr);
|
||||||
} else {
|
|
||||||
auto scriptableAvatar = DependencyManager::get<ScriptableAvatar>();
|
|
||||||
_entityEditSender.setMyAvatar(scriptableAvatar.data());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,7 +788,7 @@ void Agent::processAgentAvatarAudio() {
|
||||||
// seek past the sequence number, will be packed when destination node is known
|
// seek past the sequence number, will be packed when destination node is known
|
||||||
audioPacket->seek(sizeof(quint16));
|
audioPacket->seek(sizeof(quint16));
|
||||||
|
|
||||||
if (silentFrame) {
|
if (silentFrame && !_flushEncoder) {
|
||||||
|
|
||||||
if (!_isListeningToAudioStream) {
|
if (!_isListeningToAudioStream) {
|
||||||
// if we have a silent frame and we're not listening then just send nothing and break out of here
|
// if we have a silent frame and we're not listening then just send nothing and break out of here
|
||||||
|
@ -810,7 +810,7 @@ void Agent::processAgentAvatarAudio() {
|
||||||
|
|
||||||
// no matter what, the loudness should be set to 0
|
// no matter what, the loudness should be set to 0
|
||||||
computeLoudness(nullptr, scriptedAvatar);
|
computeLoudness(nullptr, scriptedAvatar);
|
||||||
} else if (nextSoundOutput) {
|
} else if (nextSoundOutput || _flushEncoder) {
|
||||||
|
|
||||||
// write the codec
|
// write the codec
|
||||||
audioPacket->writeString(_selectedCodecName);
|
audioPacket->writeString(_selectedCodecName);
|
||||||
|
@ -864,8 +864,6 @@ void Agent::processAgentAvatarAudio() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Agent::aboutToFinish() {
|
void Agent::aboutToFinish() {
|
||||||
setIsAvatar(false);// will stop timers for sending identity packets
|
|
||||||
|
|
||||||
// our entity tree is going to go away so tell that to the EntityScriptingInterface
|
// our entity tree is going to go away so tell that to the EntityScriptingInterface
|
||||||
DependencyManager::get<EntityScriptingInterface>()->setEntityTree(nullptr);
|
DependencyManager::get<EntityScriptingInterface>()->setEntityTree(nullptr);
|
||||||
|
|
||||||
|
|
|
@ -497,7 +497,7 @@ void AudioMixerClientData::processStreamPacket(ReceivedMessage& message, Concurr
|
||||||
|
|
||||||
if (newStream) {
|
if (newStream) {
|
||||||
// whenever a stream is added, push it to the concurrent vector of streams added this frame
|
// whenever a stream is added, push it to the concurrent vector of streams added this frame
|
||||||
addedStreams.emplace_back(getNodeID(), getNodeLocalID(), matchingStream->getStreamIdentifier(), matchingStream.get());
|
addedStreams.push_back(AddedStream(getNodeID(), getNodeLocalID(), matchingStream->getStreamIdentifier(), matchingStream.get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -380,6 +380,11 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) {
|
if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) {
|
||||||
++numAvatarsHeldBack;
|
++numAvatarsHeldBack;
|
||||||
shouldIgnore = true;
|
shouldIgnore = true;
|
||||||
|
} else if (lastSeqFromSender == 0) {
|
||||||
|
// We have have not yet recieved any data about this avatar. Ignore it for now
|
||||||
|
// This is important for Agent scripts that are not avatar
|
||||||
|
// so that they don't appear to be an avatar at the origin
|
||||||
|
shouldIgnore = true;
|
||||||
} else if (lastSeqFromSender - lastSeqToReceiver > 1) {
|
} else if (lastSeqFromSender - lastSeqToReceiver > 1) {
|
||||||
// this is a skip - we still send the packet but capture the presence of the skip so we see it happening
|
// this is a skip - we still send the packet but capture the presence of the skip so we see it happening
|
||||||
++numAvatarsWithSkippedFrames;
|
++numAvatarsWithSkippedFrames;
|
||||||
|
|
|
@ -164,7 +164,7 @@ public:
|
||||||
void setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement);
|
void setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement);
|
||||||
bool getHasAudioEnabledFaceMovement() const override { return _headData->getHasAudioEnabledFaceMovement(); }
|
bool getHasAudioEnabledFaceMovement() const override { return _headData->getHasAudioEnabledFaceMovement(); }
|
||||||
|
|
||||||
private slots:
|
public slots:
|
||||||
void update(float deltatime);
|
void update(float deltatime);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -59,6 +59,7 @@ $(document).ready(function(){
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/content/upload',
|
url: '/content/upload',
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
|
timeout: 3600000, // Set timeout to 1h
|
||||||
cache: false,
|
cache: false,
|
||||||
processData: false,
|
processData: false,
|
||||||
contentType: false,
|
contentType: false,
|
||||||
|
|
|
@ -2906,7 +2906,7 @@ void DomainServer::updateReplicationNodes(ReplicationServerDirection direction)
|
||||||
// collect them in a vector to separately remove them with handleKillNode (since eachNode has a read lock and
|
// collect them in a vector to separately remove them with handleKillNode (since eachNode has a read lock and
|
||||||
// we cannot recursively take the write lock required by handleKillNode)
|
// we cannot recursively take the write lock required by handleKillNode)
|
||||||
std::vector<SharedNodePointer> nodesToKill;
|
std::vector<SharedNodePointer> nodesToKill;
|
||||||
nodeList->eachNode([direction, replicationNodesInSettings, replicationDirection, &nodesToKill](const SharedNodePointer& otherNode) {
|
nodeList->eachNode([&direction, &replicationNodesInSettings, &replicationDirection, &nodesToKill](const SharedNodePointer& otherNode) {
|
||||||
if ((direction == Upstream && NodeType::isUpstream(otherNode->getType()))
|
if ((direction == Upstream && NodeType::isUpstream(otherNode->getType()))
|
||||||
|| (direction == Downstream && NodeType::isDownstream(otherNode->getType()))) {
|
|| (direction == Downstream && NodeType::isDownstream(otherNode->getType()))) {
|
||||||
bool nodeInSettings = find(replicationNodesInSettings.cbegin(), replicationNodesInSettings.cend(),
|
bool nodeInSettings = find(replicationNodesInSettings.cbegin(), replicationNodesInSettings.cend(),
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 82 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 164 KiB |
Binary file not shown.
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 175 KiB |
|
@ -39,6 +39,7 @@ Item {
|
||||||
property string sendingPubliclyEffectImage;
|
property string sendingPubliclyEffectImage;
|
||||||
property var http;
|
property var http;
|
||||||
property var listModelName;
|
property var listModelName;
|
||||||
|
property var keyboardContainer: nil;
|
||||||
|
|
||||||
// This object is always used in a popup or full-screen Wallet section.
|
// This object is always used in a popup or full-screen Wallet section.
|
||||||
// This MouseArea is used to prevent a user from being
|
// This MouseArea is used to prevent a user from being
|
||||||
|
@ -1125,8 +1126,7 @@ Item {
|
||||||
checked: Settings.getValue("sendAssetsNearbyPublicly", true);
|
checked: Settings.getValue("sendAssetsNearbyPublicly", true);
|
||||||
text: "Show Effect"
|
text: "Show Effect"
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: messageContainer.bottom;
|
anchors.verticalCenter: bottomBarContainer.verticalCenter;
|
||||||
anchors.topMargin: 16;
|
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.leftMargin: 20;
|
anchors.leftMargin: 20;
|
||||||
width: 130;
|
width: 130;
|
||||||
|
@ -1168,6 +1168,9 @@ Item {
|
||||||
lightboxPopup.visible = false;
|
lightboxPopup.visible = false;
|
||||||
}
|
}
|
||||||
lightboxPopup.visible = true;
|
lightboxPopup.visible = true;
|
||||||
|
if (keyboardContainer) {
|
||||||
|
keyboardContainer.keyboardRaised = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1178,8 +1181,8 @@ Item {
|
||||||
anchors.leftMargin: 20;
|
anchors.leftMargin: 20;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.rightMargin: 20;
|
anchors.rightMargin: 20;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.top: messageContainer.bottom;
|
||||||
anchors.bottomMargin: 20;
|
anchors.topMargin: 20;
|
||||||
height: 60;
|
height: 60;
|
||||||
|
|
||||||
// "CANCEL" button
|
// "CANCEL" button
|
||||||
|
@ -1187,11 +1190,11 @@ Item {
|
||||||
id: cancelButton_sendAssetStep;
|
id: cancelButton_sendAssetStep;
|
||||||
color: root.assetName === "" ? hifi.buttons.noneBorderlessWhite : hifi.buttons.noneBorderlessGray;
|
color: root.assetName === "" ? hifi.buttons.noneBorderlessWhite : hifi.buttons.noneBorderlessGray;
|
||||||
colorScheme: hifi.colorSchemes.dark;
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
anchors.left: parent.left;
|
anchors.right: sendButton.left;
|
||||||
anchors.leftMargin: 24;
|
anchors.rightMargin: 24;
|
||||||
anchors.verticalCenter: parent.verticalCenter;
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
height: 40;
|
height: 40;
|
||||||
width: 150;
|
width: 100;
|
||||||
text: "CANCEL";
|
text: "CANCEL";
|
||||||
onClicked: {
|
onClicked: {
|
||||||
resetSendAssetData();
|
resetSendAssetData();
|
||||||
|
@ -1205,10 +1208,10 @@ Item {
|
||||||
color: hifi.buttons.blue;
|
color: hifi.buttons.blue;
|
||||||
colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light;
|
colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.rightMargin: 24;
|
anchors.rightMargin: 0;
|
||||||
anchors.verticalCenter: parent.verticalCenter;
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
height: 40;
|
height: 40;
|
||||||
width: 150;
|
width: 100;
|
||||||
text: "SUBMIT";
|
text: "SUBMIT";
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.assetName === "" && parseInt(amountTextField.text) > parseInt(balanceText.text)) {
|
if (root.assetName === "" && parseInt(amountTextField.text) > parseInt(balanceText.text)) {
|
||||||
|
|
|
@ -158,6 +158,7 @@ Rectangle {
|
||||||
listModelName: "Gift Connections";
|
listModelName: "Gift Connections";
|
||||||
z: 998;
|
z: 998;
|
||||||
visible: root.activeView === "giftAsset";
|
visible: root.activeView === "giftAsset";
|
||||||
|
keyboardContainer: root;
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
parentAppTitleBarHeight: 70;
|
parentAppTitleBarHeight: 70;
|
||||||
parentAppNavBarHeight: 0;
|
parentAppNavBarHeight: 0;
|
||||||
|
@ -585,7 +586,7 @@ Rectangle {
|
||||||
visible: purchasesModel.count !== 0;
|
visible: purchasesModel.count !== 0;
|
||||||
clip: true;
|
clip: true;
|
||||||
model: purchasesModel;
|
model: purchasesModel;
|
||||||
snapMode: ListView.SnapToItem;
|
snapMode: ListView.NoSnap;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: separator.bottom;
|
anchors.top: separator.bottom;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
|
|
|
@ -354,6 +354,7 @@ Rectangle {
|
||||||
listModelName: "Send Money Connections";
|
listModelName: "Send Money Connections";
|
||||||
z: 997;
|
z: 997;
|
||||||
visible: root.activeView === "sendMoney";
|
visible: root.activeView === "sendMoney";
|
||||||
|
keyboardContainer: root;
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
parentAppTitleBarHeight: titleBarContainer.height;
|
parentAppTitleBarHeight: titleBarContainer.height;
|
||||||
parentAppNavBarHeight: tabButtonsContainer.height;
|
parentAppNavBarHeight: tabButtonsContainer.height;
|
||||||
|
|
|
@ -3534,6 +3534,7 @@ void Application::setIsInterstitialMode(bool interstitialMode) {
|
||||||
if (enableInterstitial) {
|
if (enableInterstitial) {
|
||||||
if (_interstitialMode != interstitialMode) {
|
if (_interstitialMode != interstitialMode) {
|
||||||
_interstitialMode = interstitialMode;
|
_interstitialMode = interstitialMode;
|
||||||
|
emit interstitialModeChanged(_interstitialMode);
|
||||||
|
|
||||||
DependencyManager::get<AudioClient>()->setAudioPaused(_interstitialMode);
|
DependencyManager::get<AudioClient>()->setAudioPaused(_interstitialMode);
|
||||||
DependencyManager::get<AvatarManager>()->setMyAvatarDataPacketsPaused(_interstitialMode);
|
DependencyManager::get<AvatarManager>()->setMyAvatarDataPacketsPaused(_interstitialMode);
|
||||||
|
@ -8476,6 +8477,16 @@ QUuid Application::getTabletFrameID() const {
|
||||||
return HMD->getCurrentTabletFrameID();
|
return HMD->getCurrentTabletFrameID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<QUuid> Application::getTabletIDs() const {
|
||||||
|
// Most important overlays first.
|
||||||
|
QVector<QUuid> result;
|
||||||
|
auto HMD = DependencyManager::get<HMDScriptingInterface>();
|
||||||
|
result << HMD->getCurrentTabletScreenID();
|
||||||
|
result << HMD->getCurrentHomeButtonID();
|
||||||
|
result << HMD->getCurrentTabletFrameID();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void Application::setAvatarOverrideUrl(const QUrl& url, bool save) {
|
void Application::setAvatarOverrideUrl(const QUrl& url, bool save) {
|
||||||
_avatarOverrideUrl = url;
|
_avatarOverrideUrl = url;
|
||||||
_saveAvatarOverrideUrl = save;
|
_saveAvatarOverrideUrl = save;
|
||||||
|
|
|
@ -298,6 +298,7 @@ public:
|
||||||
OverlayID getTabletScreenID() const;
|
OverlayID getTabletScreenID() const;
|
||||||
OverlayID getTabletHomeButtonID() const;
|
OverlayID getTabletHomeButtonID() const;
|
||||||
QUuid getTabletFrameID() const; // may be an entity or an overlay
|
QUuid getTabletFrameID() const; // may be an entity or an overlay
|
||||||
|
QVector<QUuid> getTabletIDs() const; // In order of most important IDs first.
|
||||||
|
|
||||||
void setAvatarOverrideUrl(const QUrl& url, bool save);
|
void setAvatarOverrideUrl(const QUrl& url, bool save);
|
||||||
void clearAvatarOverrideUrl() { _avatarOverrideUrl = QUrl(); _saveAvatarOverrideUrl = false; }
|
void clearAvatarOverrideUrl() { _avatarOverrideUrl = QUrl(); _saveAvatarOverrideUrl = false; }
|
||||||
|
@ -334,6 +335,8 @@ signals:
|
||||||
|
|
||||||
void uploadRequest(QString path);
|
void uploadRequest(QString path);
|
||||||
|
|
||||||
|
void interstitialModeChanged(bool isInInterstitialMode);
|
||||||
|
|
||||||
void loginDialogPoppedUp();
|
void loginDialogPoppedUp();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -78,8 +78,10 @@ void addAvatarEntities(const QVariantList& avatarEntities) {
|
||||||
}
|
}
|
||||||
|
|
||||||
entity->setLastBroadcast(usecTimestampNow());
|
entity->setLastBroadcast(usecTimestampNow());
|
||||||
// since we're creating this object we will immediately volunteer to own its simulation
|
if (entityProperties.getDynamic()) {
|
||||||
entity->setScriptSimulationPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
// since we're creating a dynamic object we volunteer immediately to own its simulation
|
||||||
|
entity->upgradeScriptSimulationPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||||
|
}
|
||||||
entityProperties.setLastEdited(entity->getLastEdited());
|
entityProperties.setLastEdited(entity->getLastEdited());
|
||||||
} else {
|
} else {
|
||||||
qCDebug(entities) << "AvatarEntitiesBookmark failed to add new Entity to local Octree";
|
qCDebug(entities) << "AvatarEntitiesBookmark failed to add new Entity to local Octree";
|
||||||
|
@ -108,6 +110,9 @@ AvatarBookmarks::AvatarBookmarks() {
|
||||||
|
|
||||||
if (!QFile::copy(defaultBookmarksFilename, _bookmarksFilename)) {
|
if (!QFile::copy(defaultBookmarksFilename, _bookmarksFilename)) {
|
||||||
qDebug() << "failed to copy" << defaultBookmarksFilename << "to" << _bookmarksFilename;
|
qDebug() << "failed to copy" << defaultBookmarksFilename << "to" << _bookmarksFilename;
|
||||||
|
} else {
|
||||||
|
QFile bookmarksFile(_bookmarksFilename);
|
||||||
|
bookmarksFile.setPermissions(bookmarksFile.permissions() | QFile::WriteUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readFromFile();
|
readFromFile();
|
||||||
|
|
|
@ -55,15 +55,7 @@ static const quint64 MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS = USECS_PER_SECOND /
|
||||||
// We add _myAvatar into the hash with all the other AvatarData, and we use the default NULL QUid as the key.
|
// We add _myAvatar into the hash with all the other AvatarData, and we use the default NULL QUid as the key.
|
||||||
const QUuid MY_AVATAR_KEY; // NULL key
|
const QUuid MY_AVATAR_KEY; // NULL key
|
||||||
|
|
||||||
namespace {
|
|
||||||
// For an unknown avatar-data packet, wait this long before requesting the identity.
|
|
||||||
constexpr std::chrono::milliseconds REQUEST_UNKNOWN_IDENTITY_DELAY { 5 * 1000 };
|
|
||||||
constexpr int REQUEST_UNKNOWN_IDENTITY_TRANSMITS = 3;
|
|
||||||
}
|
|
||||||
using std::chrono::steady_clock;
|
|
||||||
|
|
||||||
AvatarManager::AvatarManager(QObject* parent) :
|
AvatarManager::AvatarManager(QObject* parent) :
|
||||||
_avatarsToFade(),
|
|
||||||
_myAvatar(new MyAvatar(qApp->thread()), [](MyAvatar* ptr) { ptr->deleteLater(); })
|
_myAvatar(new MyAvatar(qApp->thread()), [](MyAvatar* ptr) { ptr->deleteLater(); })
|
||||||
{
|
{
|
||||||
// register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar
|
// register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar
|
||||||
|
@ -322,28 +314,6 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
|
|
||||||
simulateAvatarFades(deltaTime);
|
simulateAvatarFades(deltaTime);
|
||||||
|
|
||||||
// Check on avatars with pending identities:
|
|
||||||
steady_clock::time_point now = steady_clock::now();
|
|
||||||
QWriteLocker writeLock(&_hashLock);
|
|
||||||
for (auto pendingAvatar = _pendingAvatars.begin(); pendingAvatar != _pendingAvatars.end(); ++pendingAvatar) {
|
|
||||||
if (now - pendingAvatar->creationTime >= REQUEST_UNKNOWN_IDENTITY_DELAY) {
|
|
||||||
// Too long without an ID
|
|
||||||
sendIdentityRequest(pendingAvatar->avatar->getID());
|
|
||||||
if (++pendingAvatar->transmits >= REQUEST_UNKNOWN_IDENTITY_TRANSMITS) {
|
|
||||||
qCDebug(avatars) << "Requesting identity for unknown avatar (final request)" <<
|
|
||||||
pendingAvatar->avatar->getID().toString();
|
|
||||||
|
|
||||||
pendingAvatar = _pendingAvatars.erase(pendingAvatar);
|
|
||||||
if (pendingAvatar == _pendingAvatars.end()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pendingAvatar->creationTime = now;
|
|
||||||
qCDebug(avatars) << "Requesting identity for unknown avatar" << pendingAvatar->avatar->getID().toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_avatarSimulationTime = (float)(usecTimestampNow() - startTime) / (float)USECS_PER_MSEC;
|
_avatarSimulationTime = (float)(usecTimestampNow() - startTime) / (float)USECS_PER_MSEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ using SortedAvatar = std::pair<float, std::shared_ptr<Avatar>>;
|
||||||
* @borrows AvatarList.sessionUUIDChanged as sessionUUIDChanged
|
* @borrows AvatarList.sessionUUIDChanged as sessionUUIDChanged
|
||||||
* @borrows AvatarList.processAvatarDataPacket as processAvatarDataPacket
|
* @borrows AvatarList.processAvatarDataPacket as processAvatarDataPacket
|
||||||
* @borrows AvatarList.processAvatarIdentityPacket as processAvatarIdentityPacket
|
* @borrows AvatarList.processAvatarIdentityPacket as processAvatarIdentityPacket
|
||||||
|
* @borrows AvatarList.processBulkAvatarTraits as processBulkAvatarTraits
|
||||||
* @borrows AvatarList.processKillAvatar as processKillAvatar
|
* @borrows AvatarList.processKillAvatar as processKillAvatar
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -152,6 +153,13 @@ public:
|
||||||
const QVector<EntityItemID>& avatarsToInclude,
|
const QVector<EntityItemID>& avatarsToInclude,
|
||||||
const QVector<EntityItemID>& avatarsToDiscard);
|
const QVector<EntityItemID>& avatarsToDiscard);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* @function AvatarManager.findParabolaIntersectionVector
|
||||||
|
* @param {PickParabola} pick
|
||||||
|
* @param {Uuid[]} avatarsToInclude
|
||||||
|
* @param {Uuid[]} avatarsToDiscard
|
||||||
|
* @returns {ParabolaToAvatarIntersectionResult}
|
||||||
|
*/
|
||||||
Q_INVOKABLE ParabolaToAvatarIntersectionResult findParabolaIntersectionVector(const PickParabola& pick,
|
Q_INVOKABLE ParabolaToAvatarIntersectionResult findParabolaIntersectionVector(const PickParabola& pick,
|
||||||
const QVector<EntityItemID>& avatarsToInclude,
|
const QVector<EntityItemID>& avatarsToInclude,
|
||||||
const QVector<EntityItemID>& avatarsToDiscard);
|
const QVector<EntityItemID>& avatarsToDiscard);
|
||||||
|
@ -176,7 +184,7 @@ public:
|
||||||
* than iterating over each avatar and obtaining data about them in JavaScript, as that method
|
* than iterating over each avatar and obtaining data about them in JavaScript, as that method
|
||||||
* locks and unlocks each avatar's data structure potentially hundreds of times per update tick.
|
* locks and unlocks each avatar's data structure potentially hundreds of times per update tick.
|
||||||
* @function AvatarManager.getPalData
|
* @function AvatarManager.getPalData
|
||||||
* @param {string[]} specificAvatarIdentifiers - A list of specific Avatar Identifiers about
|
* @param {string[]} [specificAvatarIdentifiers] - A list of specific Avatar Identifiers about
|
||||||
* which you want to get PAL data
|
* which you want to get PAL data
|
||||||
* @returns {object}
|
* @returns {object}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -122,7 +122,6 @@ MyAvatar::MyAvatar(QThread* thread) :
|
||||||
_goToOrientation(),
|
_goToOrientation(),
|
||||||
_prevShouldDrawHead(true),
|
_prevShouldDrawHead(true),
|
||||||
_audioListenerMode(FROM_HEAD),
|
_audioListenerMode(FROM_HEAD),
|
||||||
_hmdAtRestDetector(glm::vec3(0), glm::quat()),
|
|
||||||
_dominantHandSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "dominantHand", DOMINANT_RIGHT_HAND),
|
_dominantHandSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "dominantHand", DOMINANT_RIGHT_HAND),
|
||||||
_headPitchSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "", 0.0f),
|
_headPitchSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "", 0.0f),
|
||||||
_scaleSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "scale", _targetScale),
|
_scaleSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "scale", _targetScale),
|
||||||
|
@ -702,6 +701,46 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
// before we perform rig animations and IK.
|
// before we perform rig animations and IK.
|
||||||
updateSensorToWorldMatrix();
|
updateSensorToWorldMatrix();
|
||||||
|
|
||||||
|
// if we detect the hand controller is at rest, i.e. lying on the table, or the hand is too far away from the hmd
|
||||||
|
// disable the associated hand controller input.
|
||||||
|
{
|
||||||
|
// NOTE: all poses are in sensor space.
|
||||||
|
auto leftHandIter = _controllerPoseMap.find(controller::Action::LEFT_HAND);
|
||||||
|
if (leftHandIter != _controllerPoseMap.end() && leftHandIter->second.isValid()) {
|
||||||
|
_leftHandAtRestDetector.update(leftHandIter->second.getTranslation(), leftHandIter->second.getRotation());
|
||||||
|
if (_leftHandAtRestDetector.isAtRest()) {
|
||||||
|
leftHandIter->second.valid = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_leftHandAtRestDetector.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rightHandIter = _controllerPoseMap.find(controller::Action::RIGHT_HAND);
|
||||||
|
if (rightHandIter != _controllerPoseMap.end() && rightHandIter->second.isValid()) {
|
||||||
|
_rightHandAtRestDetector.update(rightHandIter->second.getTranslation(), rightHandIter->second.getRotation());
|
||||||
|
if (_rightHandAtRestDetector.isAtRest()) {
|
||||||
|
rightHandIter->second.valid = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_rightHandAtRestDetector.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto headIter = _controllerPoseMap.find(controller::Action::HEAD);
|
||||||
|
|
||||||
|
// The 99th percentile man has a spine to fingertip to height ratio of 0.45. Lets increase that by about 10% to 0.5
|
||||||
|
// then measure the distance the center of the eyes to the finger tips. To come up with this ratio.
|
||||||
|
// From "The Measure of Man and Woman: Human Factors in Design, Revised Edition" by Alvin R. Tilley, Henry Dreyfuss Associates
|
||||||
|
const float MAX_HEAD_TO_HAND_DISTANCE_RATIO = 0.52f;
|
||||||
|
|
||||||
|
float maxHeadHandDistance = getUserHeight() * MAX_HEAD_TO_HAND_DISTANCE_RATIO;
|
||||||
|
if (glm::length(headIter->second.getTranslation() - leftHandIter->second.getTranslation()) > maxHeadHandDistance) {
|
||||||
|
leftHandIter->second.valid = false;
|
||||||
|
}
|
||||||
|
if (glm::length(headIter->second.getTranslation() - rightHandIter->second.getTranslation()) > maxHeadHandDistance) {
|
||||||
|
rightHandIter->second.valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("skeleton");
|
PerformanceTimer perfTimer("skeleton");
|
||||||
|
|
||||||
|
|
|
@ -629,8 +629,6 @@ public:
|
||||||
|
|
||||||
const MyHead* getMyHead() const;
|
const MyHead* getMyHead() const;
|
||||||
|
|
||||||
Q_INVOKABLE void toggleSmoothPoleVectors() { _skeletonModel->getRig().toggleSmoothPoleVectors(); };
|
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Get the current position of the avatar's "Head" joint.
|
* Get the current position of the avatar's "Head" joint.
|
||||||
* @function MyAvatar.getHeadPosition
|
* @function MyAvatar.getHeadPosition
|
||||||
|
@ -951,50 +949,72 @@ public:
|
||||||
void removeWearableAvatarEntities();
|
void removeWearableAvatarEntities();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
* Check whether your avatar is flying or not.
|
||||||
* @function MyAvatar.isFlying
|
* @function MyAvatar.isFlying
|
||||||
* @returns {boolean}
|
* @returns {boolean} <code>true</code> if your avatar is flying and not taking off or falling, otherwise
|
||||||
|
* <code>false</code>.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE bool isFlying();
|
Q_INVOKABLE bool isFlying();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
* Check whether your avatar is in the air or not.
|
||||||
* @function MyAvatar.isInAir
|
* @function MyAvatar.isInAir
|
||||||
* @returns {boolean}
|
* @returns {boolean} <code>true</code> if your avatar is taking off, flying, or falling, otherwise <code>false</code>
|
||||||
|
* because your avatar is on the ground.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE bool isInAir();
|
Q_INVOKABLE bool isInAir();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
* Set your preference for flying in your current desktop or HMD display mode. Note that your ability to fly also depends
|
||||||
|
* on whether the domain you're in allows you to fly.
|
||||||
* @function MyAvatar.setFlyingEnabled
|
* @function MyAvatar.setFlyingEnabled
|
||||||
* @param {boolean} enabled
|
* @param {boolean} enabled - Set <code>true</code> if you want to enable flying in your current desktop or HMD display
|
||||||
|
* mode, otherwise set <code>false</code>.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void setFlyingEnabled(bool enabled);
|
Q_INVOKABLE void setFlyingEnabled(bool enabled);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
* Get your preference for flying in your current desktop or HMD display mode. Note that your ability to fly also depends
|
||||||
|
* on whether the domain you're in allows you to fly.
|
||||||
* @function MyAvatar.getFlyingEnabled
|
* @function MyAvatar.getFlyingEnabled
|
||||||
* @returns {boolean}
|
* @returns {boolean} <code>true</code> if your preference is to enable flying in your current desktop or HMD display mode,
|
||||||
|
* otherwise <code>false</code>.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE bool getFlyingEnabled();
|
Q_INVOKABLE bool getFlyingEnabled();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
* Set your preference for flying in desktop display mode. Note that your ability to fly also depends on whether the domain
|
||||||
|
* you're in allows you to fly.
|
||||||
* @function MyAvatar.setFlyingDesktopPref
|
* @function MyAvatar.setFlyingDesktopPref
|
||||||
* @param {boolean} enabled
|
* @param {boolean} enabled - Set <code>true</code> if you want to enable flying in desktop display mode, otherwise set
|
||||||
|
* <code>false</code>.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void setFlyingDesktopPref(bool enabled);
|
Q_INVOKABLE void setFlyingDesktopPref(bool enabled);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
* Get your preference for flying in desktop display mode. Note that your ability to fly also depends on whether the domain
|
||||||
|
* you're in allows you to fly.
|
||||||
* @function MyAvatar.getFlyingDesktopPref
|
* @function MyAvatar.getFlyingDesktopPref
|
||||||
* @returns {boolean}
|
* @returns {boolean} <code>true</code> if your preference is to enable flying in desktop display mode, otherwise
|
||||||
|
* <code>false</code>.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE bool getFlyingDesktopPref();
|
Q_INVOKABLE bool getFlyingDesktopPref();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function MyAvatar.setFlyingDesktopPref
|
* Set your preference for flying in HMD display mode. Note that your ability to fly also depends on whether the domain
|
||||||
* @param {boolean} enabled
|
* you're in allows you to fly.
|
||||||
|
* @function MyAvatar.setFlyingHMDPref
|
||||||
|
* @param {boolean} enabled - Set <code>true</code> if you want to enable flying in HMD display mode, otherwise set
|
||||||
|
* <code>false</code>.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void setFlyingHMDPref(bool enabled);
|
Q_INVOKABLE void setFlyingHMDPref(bool enabled);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function MyAvatar.getFlyingDesktopPref
|
* Get your preference for flying in HMD display mode. Note that your ability to fly also depends on whether the domain
|
||||||
* @returns {boolean}
|
* you're in allows you to fly.
|
||||||
|
* @function MyAvatar.getFlyingHMDPref
|
||||||
|
* @returns {boolean} <code>true</code> if your preference is to enable flying in HMD display mode, otherwise
|
||||||
|
* <code>false</code>.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE bool getFlyingHMDPref();
|
Q_INVOKABLE bool getFlyingHMDPref();
|
||||||
|
|
||||||
|
@ -1766,8 +1786,8 @@ private:
|
||||||
glm::vec3 _customListenPosition;
|
glm::vec3 _customListenPosition;
|
||||||
glm::quat _customListenOrientation;
|
glm::quat _customListenOrientation;
|
||||||
|
|
||||||
AtRestDetector _hmdAtRestDetector;
|
AtRestDetector _leftHandAtRestDetector;
|
||||||
bool _lastIsMoving { false };
|
AtRestDetector _rightHandAtRestDetector;
|
||||||
|
|
||||||
// all poses are in sensor-frame
|
// all poses are in sensor-frame
|
||||||
std::map<controller::Action, controller::Pose> _controllerPoseMap;
|
std::map<controller::Action, controller::Pose> _controllerPoseMap;
|
||||||
|
|
|
@ -46,7 +46,7 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) {
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 hipsMat;
|
glm::mat4 hipsMat;
|
||||||
if (myAvatar->getCenterOfGravityModelEnabled() && !isFlying && !(myAvatar->getIsInWalkingState())) {
|
if (myAvatar->getCenterOfGravityModelEnabled() && !isFlying && !(myAvatar->getIsInWalkingState()) && myAvatar->getHMDLeanRecenterEnabled()) {
|
||||||
// then we use center of gravity model
|
// then we use center of gravity model
|
||||||
hipsMat = myAvatar->deriveBodyUsingCgModel();
|
hipsMat = myAvatar->deriveBodyUsingCgModel();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,12 +11,12 @@
|
||||||
|
|
||||||
#include "AvatarMotionState.h"
|
#include "AvatarMotionState.h"
|
||||||
|
|
||||||
static xColor getLoadingOrbColor(Avatar::LoadingStatus loadingStatus) {
|
static glm::u8vec3 getLoadingOrbColor(Avatar::LoadingStatus loadingStatus) {
|
||||||
|
|
||||||
const xColor NO_MODEL_COLOR(0xe3, 0xe3, 0xe3);
|
const glm::u8vec3 NO_MODEL_COLOR(0xe3, 0xe3, 0xe3);
|
||||||
const xColor LOAD_MODEL_COLOR(0xef, 0x93, 0xd1);
|
const glm::u8vec3 LOAD_MODEL_COLOR(0xef, 0x93, 0xd1);
|
||||||
const xColor LOAD_SUCCESS_COLOR(0x1f, 0xc6, 0xa6);
|
const glm::u8vec3 LOAD_SUCCESS_COLOR(0x1f, 0xc6, 0xa6);
|
||||||
const xColor LOAD_FAILURE_COLOR(0xc6, 0x21, 0x47);
|
const glm::u8vec3 LOAD_FAILURE_COLOR(0xc6, 0x21, 0x47);
|
||||||
switch (loadingStatus) {
|
switch (loadingStatus) {
|
||||||
case Avatar::LoadingStatus::NoModel:
|
case Avatar::LoadingStatus::NoModel:
|
||||||
return NO_MODEL_COLOR;
|
return NO_MODEL_COLOR;
|
||||||
|
|
|
@ -76,4 +76,4 @@ protected:
|
||||||
bool _includeNormals;
|
bool _includeNormals;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_CollisionPick_h
|
#endif // hifi_CollisionPick_h
|
||||||
|
|
|
@ -52,8 +52,7 @@ void ParabolaPointer::editRenderStatePath(const std::string& state, const QVaria
|
||||||
if (!pathMap.isEmpty()) {
|
if (!pathMap.isEmpty()) {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
if (pathMap["color"].isValid()) {
|
if (pathMap["color"].isValid()) {
|
||||||
bool valid;
|
color = toGlm(u8vec3FromVariant(pathMap["color"]));
|
||||||
color = toGlm(xColorFromVariant(pathMap["color"], valid));
|
|
||||||
}
|
}
|
||||||
if (pathMap["alpha"].isValid()) {
|
if (pathMap["alpha"].isValid()) {
|
||||||
alpha = pathMap["alpha"].toFloat();
|
alpha = pathMap["alpha"].toFloat();
|
||||||
|
@ -250,8 +249,7 @@ std::shared_ptr<StartEndRenderState> ParabolaPointer::buildRenderState(const QVa
|
||||||
enabled = true;
|
enabled = true;
|
||||||
QVariantMap pathMap = propMap["path"].toMap();
|
QVariantMap pathMap = propMap["path"].toMap();
|
||||||
if (pathMap["color"].isValid()) {
|
if (pathMap["color"].isValid()) {
|
||||||
bool valid;
|
color = toGlm(u8vec3FromVariant(pathMap["color"]));
|
||||||
color = toGlm(xColorFromVariant(pathMap["color"], valid));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pathMap["alpha"].isValid()) {
|
if (pathMap["alpha"].isValid()) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ class StartEndRenderState {
|
||||||
public:
|
public:
|
||||||
StartEndRenderState() {}
|
StartEndRenderState() {}
|
||||||
StartEndRenderState(const OverlayID& startID, const OverlayID& endID);
|
StartEndRenderState(const OverlayID& startID, const OverlayID& endID);
|
||||||
virtual ~StartEndRenderState() {}
|
virtual ~StartEndRenderState() = default;
|
||||||
|
|
||||||
const OverlayID& getStartID() const { return _startID; }
|
const OverlayID& getStartID() const { return _startID; }
|
||||||
const OverlayID& getEndID() const { return _endID; }
|
const OverlayID& getEndID() const { return _endID; }
|
||||||
|
|
|
@ -421,7 +421,7 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
|
||||||
auto colorVariant = properties["outlineUnoccludedColor"];
|
auto colorVariant = properties["outlineUnoccludedColor"];
|
||||||
if (colorVariant.isValid()) {
|
if (colorVariant.isValid()) {
|
||||||
bool isValid;
|
bool isValid;
|
||||||
auto color = xColorFromVariant(colorVariant, isValid);
|
auto color = u8vec3FromVariant(colorVariant, isValid);
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
_style._outlineUnoccluded.color = toGlm(color);
|
_style._outlineUnoccluded.color = toGlm(color);
|
||||||
}
|
}
|
||||||
|
@ -429,7 +429,7 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
|
||||||
colorVariant = properties["outlineOccludedColor"];
|
colorVariant = properties["outlineOccludedColor"];
|
||||||
if (colorVariant.isValid()) {
|
if (colorVariant.isValid()) {
|
||||||
bool isValid;
|
bool isValid;
|
||||||
auto color = xColorFromVariant(colorVariant, isValid);
|
auto color = u8vec3FromVariant(colorVariant, isValid);
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
_style._outlineOccluded.color = toGlm(color);
|
_style._outlineOccluded.color = toGlm(color);
|
||||||
}
|
}
|
||||||
|
@ -437,7 +437,7 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
|
||||||
colorVariant = properties["fillUnoccludedColor"];
|
colorVariant = properties["fillUnoccludedColor"];
|
||||||
if (colorVariant.isValid()) {
|
if (colorVariant.isValid()) {
|
||||||
bool isValid;
|
bool isValid;
|
||||||
auto color = xColorFromVariant(colorVariant, isValid);
|
auto color = u8vec3FromVariant(colorVariant, isValid);
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
_style._fillUnoccluded.color = toGlm(color);
|
_style._fillUnoccluded.color = toGlm(color);
|
||||||
}
|
}
|
||||||
|
@ -445,7 +445,7 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
|
||||||
colorVariant = properties["fillOccludedColor"];
|
colorVariant = properties["fillOccludedColor"];
|
||||||
if (colorVariant.isValid()) {
|
if (colorVariant.isValid()) {
|
||||||
bool isValid;
|
bool isValid;
|
||||||
auto color = xColorFromVariant(colorVariant, isValid);
|
auto color = u8vec3FromVariant(colorVariant, isValid);
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
_style._fillOccluded.color = toGlm(color);
|
_style._fillOccluded.color = toGlm(color);
|
||||||
}
|
}
|
||||||
|
@ -497,10 +497,11 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
|
||||||
QVariantMap SelectionHighlightStyle::toVariantMap() const {
|
QVariantMap SelectionHighlightStyle::toVariantMap() const {
|
||||||
QVariantMap properties;
|
QVariantMap properties;
|
||||||
|
|
||||||
properties["outlineUnoccludedColor"] = xColorToVariant(xColorFromGlm(_style._outlineUnoccluded.color));
|
const float MAX_COLOR = 255.0f;
|
||||||
properties["outlineOccludedColor"] = xColorToVariant(xColorFromGlm(_style._outlineOccluded.color));
|
properties["outlineUnoccludedColor"] = u8vec3ColortoVariant(_style._outlineUnoccluded.color * MAX_COLOR);
|
||||||
properties["fillUnoccludedColor"] = xColorToVariant(xColorFromGlm(_style._fillUnoccluded.color));
|
properties["outlineOccludedColor"] = u8vec3ColortoVariant(_style._outlineOccluded.color * MAX_COLOR);
|
||||||
properties["fillOccludedColor"] = xColorToVariant(xColorFromGlm(_style._fillOccluded.color));
|
properties["fillUnoccludedColor"] = u8vec3ColortoVariant(_style._fillUnoccluded.color * MAX_COLOR);
|
||||||
|
properties["fillOccludedColor"] = u8vec3ColortoVariant(_style._fillOccluded.color * MAX_COLOR);
|
||||||
|
|
||||||
properties["outlineUnoccludedAlpha"] = _style._outlineUnoccluded.alpha;
|
properties["outlineUnoccludedAlpha"] = _style._outlineUnoccluded.alpha;
|
||||||
properties["outlineOccludedAlpha"] = _style._outlineOccluded.alpha;
|
properties["outlineOccludedAlpha"] = _style._outlineOccluded.alpha;
|
||||||
|
|
|
@ -54,6 +54,9 @@ WindowScriptingInterface::WindowScriptingInterface() {
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(qApp->getWindow(), &MainWindow::windowGeometryChanged, this, &WindowScriptingInterface::onWindowGeometryChanged);
|
connect(qApp->getWindow(), &MainWindow::windowGeometryChanged, this, &WindowScriptingInterface::onWindowGeometryChanged);
|
||||||
|
connect(qApp, &Application::interstitialModeChanged, [this] (bool interstitialMode) {
|
||||||
|
emit interstitialModeChanged(interstitialMode);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowScriptingInterface::~WindowScriptingInterface() {
|
WindowScriptingInterface::~WindowScriptingInterface() {
|
||||||
|
|
|
@ -619,6 +619,14 @@ signals:
|
||||||
*/
|
*/
|
||||||
void redirectErrorStateChanged(bool isInErrorState);
|
void redirectErrorStateChanged(bool isInErrorState);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Triggered when interstitial mode changes.
|
||||||
|
* @function Window.interstitialModeChanged
|
||||||
|
* @param {bool} interstitialMode - The mode of the interstitial is changed to.
|
||||||
|
* @returns {Signal}
|
||||||
|
*/
|
||||||
|
void interstitialModeChanged(bool interstitialMode);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Triggered when a still snapshot has been taken by calling {@link Window.takeSnapshot|takeSnapshot} with
|
* Triggered when a still snapshot has been taken by calling {@link Window.takeSnapshot|takeSnapshot} with
|
||||||
* <code>includeAnimated = false</code> or {@link Window.takeSecondaryCameraSnapshot|takeSecondaryCameraSnapshot}.
|
* <code>includeAnimated = false</code> or {@link Window.takeSecondaryCameraSnapshot|takeSecondaryCameraSnapshot}.
|
||||||
|
|
|
@ -75,7 +75,6 @@ void Circle3DOverlay::render(RenderArgs* args) {
|
||||||
const float FULL_CIRCLE = 360.0f;
|
const float FULL_CIRCLE = 360.0f;
|
||||||
const float SLICES = 180.0f; // The amount of segment to create the circle
|
const float SLICES = 180.0f; // The amount of segment to create the circle
|
||||||
const float SLICE_ANGLE_RADIANS = glm::radians(FULL_CIRCLE / SLICES);
|
const float SLICE_ANGLE_RADIANS = glm::radians(FULL_CIRCLE / SLICES);
|
||||||
const float MAX_COLOR = 255.0f;
|
|
||||||
|
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
|
||||||
|
@ -246,20 +245,15 @@ void Circle3DOverlay::render(RenderArgs* args) {
|
||||||
angle += tickMarkAngle;
|
angle += tickMarkAngle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xColor majorColorX = getMajorTickMarksColor();
|
glm::vec4 majorColor(toGlm(getMajorTickMarksColor()), alpha);
|
||||||
glm::vec4 majorColor(majorColorX.red / MAX_COLOR, majorColorX.green / MAX_COLOR, majorColorX.blue / MAX_COLOR, alpha);
|
|
||||||
|
|
||||||
geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor);
|
geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor);
|
||||||
|
glm::vec4 minorColor(toGlm(getMinorTickMarksColor()), alpha);
|
||||||
xColor minorColorX = getMinorTickMarksColor();
|
|
||||||
glm::vec4 minorColor(minorColorX.red / MAX_COLOR, minorColorX.green / MAX_COLOR, minorColorX.blue / MAX_COLOR, alpha);
|
|
||||||
|
|
||||||
geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor);
|
geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
geometryCache->renderVertices(batch, gpu::LINES, _majorTicksVerticesID);
|
geometryCache->renderVertices(batch, gpu::LINES, _majorTicksVerticesID);
|
||||||
|
|
||||||
geometryCache->renderVertices(batch, gpu::LINES, _minorTicksVerticesID);
|
geometryCache->renderVertices(batch, gpu::LINES, _minorTicksVerticesID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,8 +274,8 @@ template<typename T> T fromVariant(const QVariant& v, bool& valid) {
|
||||||
return qvariant_cast<T>(v);
|
return qvariant_cast<T>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> xColor fromVariant(const QVariant& v, bool& valid) {
|
template<> glm::u8vec3 fromVariant(const QVariant& v, bool& valid) {
|
||||||
return xColorFromVariant(v, valid);
|
return u8vec3FromVariant(v, valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -344,11 +338,11 @@ void Circle3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
_dirty |= updateIfValid(properties, "outerStartAlpha", _outerStartAlpha);
|
_dirty |= updateIfValid(properties, "outerStartAlpha", _outerStartAlpha);
|
||||||
_dirty |= updateIfValid(properties, "outerEndAlpha", _outerEndAlpha);
|
_dirty |= updateIfValid(properties, "outerEndAlpha", _outerEndAlpha);
|
||||||
|
|
||||||
_dirty |= updateIfValid<xColor>(properties, "color", { _innerStartColor, _innerEndColor, _outerStartColor, _outerEndColor });
|
_dirty |= updateIfValid<glm::u8vec3>(properties, "color", { _innerStartColor, _innerEndColor, _outerStartColor, _outerEndColor });
|
||||||
_dirty |= updateIfValid<xColor>(properties, "startColor", { _innerStartColor, _outerStartColor } );
|
_dirty |= updateIfValid<glm::u8vec3>(properties, "startColor", { _innerStartColor, _outerStartColor } );
|
||||||
_dirty |= updateIfValid<xColor>(properties, "endColor", { _innerEndColor, _outerEndColor } );
|
_dirty |= updateIfValid<glm::u8vec3>(properties, "endColor", { _innerEndColor, _outerEndColor } );
|
||||||
_dirty |= updateIfValid<xColor>(properties, "innerColor", { _innerStartColor, _innerEndColor } );
|
_dirty |= updateIfValid<glm::u8vec3>(properties, "innerColor", { _innerStartColor, _innerEndColor } );
|
||||||
_dirty |= updateIfValid<xColor>(properties, "outerColor", { _outerStartColor, _outerEndColor } );
|
_dirty |= updateIfValid<glm::u8vec3>(properties, "outerColor", { _outerStartColor, _outerEndColor } );
|
||||||
_dirty |= updateIfValid(properties, "innerStartColor", _innerStartColor);
|
_dirty |= updateIfValid(properties, "innerStartColor", _innerStartColor);
|
||||||
_dirty |= updateIfValid(properties, "innerEndColor", _innerEndColor);
|
_dirty |= updateIfValid(properties, "innerEndColor", _innerEndColor);
|
||||||
_dirty |= updateIfValid(properties, "outerStartColor", _outerStartColor);
|
_dirty |= updateIfValid(properties, "outerStartColor", _outerStartColor);
|
||||||
|
@ -421,7 +415,7 @@ void Circle3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
* @property {number} endAt=360 - The counter-clockwise angle from the overlay's x-axis that drawing ends at, in degrees.
|
* @property {number} endAt=360 - The counter-clockwise angle from the overlay's x-axis that drawing ends at, in degrees.
|
||||||
* @property {number} outerRadius=1 - The outer radius of the overlay, in meters. Synonym: <code>radius</code>.
|
* @property {number} outerRadius=1 - The outer radius of the overlay, in meters. Synonym: <code>radius</code>.
|
||||||
* @property {number} innerRadius=0 - The inner radius of the overlay, in meters.
|
* @property {number} innerRadius=0 - The inner radius of the overlay, in meters.
|
||||||
* @property {Color} color=255,255,255 - The color of the overlay. Setting this value also sets the values of
|
* @property {Color} color=255,255,255 - The color of the overlay. Setting this value also sets the values of
|
||||||
* <code>innerStartColor</code>, <code>innerEndColor</code>, <code>outerStartColor</code>, and <code>outerEndColor</code>.
|
* <code>innerStartColor</code>, <code>innerEndColor</code>, <code>outerStartColor</code>, and <code>outerEndColor</code>.
|
||||||
* @property {Color} startColor - Sets the values of <code>innerStartColor</code> and <code>outerStartColor</code>.
|
* @property {Color} startColor - Sets the values of <code>innerStartColor</code> and <code>outerStartColor</code>.
|
||||||
* <em>Write-only.</em>
|
* <em>Write-only.</em>
|
||||||
|
@ -478,16 +472,16 @@ QVariant Circle3DOverlay::getProperty(const QString& property) {
|
||||||
return _innerRadius;
|
return _innerRadius;
|
||||||
}
|
}
|
||||||
if (property == "innerStartColor") {
|
if (property == "innerStartColor") {
|
||||||
return xColorToVariant(_innerStartColor);
|
return u8vec3ColortoVariant(_innerStartColor);
|
||||||
}
|
}
|
||||||
if (property == "innerEndColor") {
|
if (property == "innerEndColor") {
|
||||||
return xColorToVariant(_innerEndColor);
|
return u8vec3ColortoVariant(_innerEndColor);
|
||||||
}
|
}
|
||||||
if (property == "outerStartColor") {
|
if (property == "outerStartColor") {
|
||||||
return xColorToVariant(_outerStartColor);
|
return u8vec3ColortoVariant(_outerStartColor);
|
||||||
}
|
}
|
||||||
if (property == "outerEndColor") {
|
if (property == "outerEndColor") {
|
||||||
return xColorToVariant(_outerEndColor);
|
return u8vec3ColortoVariant(_outerEndColor);
|
||||||
}
|
}
|
||||||
if (property == "innerStartAlpha") {
|
if (property == "innerStartAlpha") {
|
||||||
return _innerStartAlpha;
|
return _innerStartAlpha;
|
||||||
|
@ -517,10 +511,10 @@ QVariant Circle3DOverlay::getProperty(const QString& property) {
|
||||||
return _minorTickMarksLength;
|
return _minorTickMarksLength;
|
||||||
}
|
}
|
||||||
if (property == "majorTickMarksColor") {
|
if (property == "majorTickMarksColor") {
|
||||||
return xColorToVariant(_majorTickMarksColor);
|
return u8vec3ColortoVariant(_majorTickMarksColor);
|
||||||
}
|
}
|
||||||
if (property == "minorTickMarksColor") {
|
if (property == "minorTickMarksColor") {
|
||||||
return xColorToVariant(_minorTickMarksColor);
|
return u8vec3ColortoVariant(_minorTickMarksColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Planar3DOverlay::getProperty(property);
|
return Planar3DOverlay::getProperty(property);
|
||||||
|
|
|
@ -39,8 +39,8 @@ public:
|
||||||
float getMinorTickMarksAngle() const { return _minorTickMarksAngle; }
|
float getMinorTickMarksAngle() const { return _minorTickMarksAngle; }
|
||||||
float getMajorTickMarksLength() const { return _majorTickMarksLength; }
|
float getMajorTickMarksLength() const { return _majorTickMarksLength; }
|
||||||
float getMinorTickMarksLength() const { return _minorTickMarksLength; }
|
float getMinorTickMarksLength() const { return _minorTickMarksLength; }
|
||||||
xColor getMajorTickMarksColor() const { return _majorTickMarksColor; }
|
glm::u8vec3 getMajorTickMarksColor() const { return _majorTickMarksColor; }
|
||||||
xColor getMinorTickMarksColor() const { return _minorTickMarksColor; }
|
glm::u8vec3 getMinorTickMarksColor() const { return _minorTickMarksColor; }
|
||||||
|
|
||||||
void setStartAt(float value) { _startAt = value; }
|
void setStartAt(float value) { _startAt = value; }
|
||||||
void setEndAt(float value) { _endAt = value; }
|
void setEndAt(float value) { _endAt = value; }
|
||||||
|
@ -51,8 +51,8 @@ public:
|
||||||
void setMinorTickMarksAngle(float value) { _minorTickMarksAngle = value; }
|
void setMinorTickMarksAngle(float value) { _minorTickMarksAngle = value; }
|
||||||
void setMajorTickMarksLength(float value) { _majorTickMarksLength = value; }
|
void setMajorTickMarksLength(float value) { _majorTickMarksLength = value; }
|
||||||
void setMinorTickMarksLength(float value) { _minorTickMarksLength = value; }
|
void setMinorTickMarksLength(float value) { _minorTickMarksLength = value; }
|
||||||
void setMajorTickMarksColor(const xColor& value) { _majorTickMarksColor = value; }
|
void setMajorTickMarksColor(const glm::u8vec3& value) { _majorTickMarksColor = value; }
|
||||||
void setMinorTickMarksColor(const xColor& value) { _minorTickMarksColor = value; }
|
void setMinorTickMarksColor(const glm::u8vec3& value) { _minorTickMarksColor = value; }
|
||||||
|
|
||||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
|
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
|
||||||
|
@ -67,10 +67,10 @@ protected:
|
||||||
float _outerRadius { 1 };
|
float _outerRadius { 1 };
|
||||||
float _innerRadius { 0 };
|
float _innerRadius { 0 };
|
||||||
|
|
||||||
xColor _innerStartColor { DEFAULT_OVERLAY_COLOR };
|
glm::u8vec3 _innerStartColor { DEFAULT_OVERLAY_COLOR };
|
||||||
xColor _innerEndColor { DEFAULT_OVERLAY_COLOR };
|
glm::u8vec3 _innerEndColor { DEFAULT_OVERLAY_COLOR };
|
||||||
xColor _outerStartColor { DEFAULT_OVERLAY_COLOR };
|
glm::u8vec3 _outerStartColor { DEFAULT_OVERLAY_COLOR };
|
||||||
xColor _outerEndColor { DEFAULT_OVERLAY_COLOR };
|
glm::u8vec3 _outerEndColor { DEFAULT_OVERLAY_COLOR };
|
||||||
float _innerStartAlpha { DEFAULT_ALPHA };
|
float _innerStartAlpha { DEFAULT_ALPHA };
|
||||||
float _innerEndAlpha { DEFAULT_ALPHA };
|
float _innerEndAlpha { DEFAULT_ALPHA };
|
||||||
float _outerStartAlpha { DEFAULT_ALPHA };
|
float _outerStartAlpha { DEFAULT_ALPHA };
|
||||||
|
@ -81,8 +81,8 @@ protected:
|
||||||
float _minorTickMarksAngle { 0 };
|
float _minorTickMarksAngle { 0 };
|
||||||
float _majorTickMarksLength { 0 };
|
float _majorTickMarksLength { 0 };
|
||||||
float _minorTickMarksLength { 0 };
|
float _minorTickMarksLength { 0 };
|
||||||
xColor _majorTickMarksColor { DEFAULT_OVERLAY_COLOR };
|
glm::u8vec3 _majorTickMarksColor { DEFAULT_OVERLAY_COLOR };
|
||||||
xColor _minorTickMarksColor { DEFAULT_OVERLAY_COLOR };
|
glm::u8vec3 _minorTickMarksColor { DEFAULT_OVERLAY_COLOR };
|
||||||
gpu::Primitive _solidPrimitive { gpu::TRIANGLE_FAN };
|
gpu::Primitive _solidPrimitive { gpu::TRIANGLE_FAN };
|
||||||
int _quadVerticesID { 0 };
|
int _quadVerticesID { 0 };
|
||||||
int _lineVerticesID { 0 };
|
int _lineVerticesID { 0 };
|
||||||
|
|
|
@ -83,7 +83,7 @@ ContextOverlayInterface::ContextOverlayInterface() {
|
||||||
_challengeOwnershipTimeoutTimer.setSingleShot(true);
|
_challengeOwnershipTimeoutTimer.setSingleShot(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const xColor CONTEXT_OVERLAY_COLOR = { 255, 255, 255 };
|
static const glm::u8vec3 CONTEXT_OVERLAY_COLOR = { 255, 255, 255 };
|
||||||
static const float CONTEXT_OVERLAY_INSIDE_DISTANCE = 1.0f; // in meters
|
static const float CONTEXT_OVERLAY_INSIDE_DISTANCE = 1.0f; // in meters
|
||||||
static const float CONTEXT_OVERLAY_SIZE = 0.09f; // in meters, same x and y dims
|
static const float CONTEXT_OVERLAY_SIZE = 0.09f; // in meters, same x and y dims
|
||||||
static const float CONTEXT_OVERLAY_OFFSET_DISTANCE = 0.1f;
|
static const float CONTEXT_OVERLAY_OFFSET_DISTANCE = 0.1f;
|
||||||
|
@ -142,14 +142,15 @@ bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID&
|
||||||
glm::vec3 cameraPosition = qApp->getCamera().getPosition();
|
glm::vec3 cameraPosition = qApp->getCamera().getPosition();
|
||||||
glm::vec3 entityDimensions = entityProperties.getDimensions();
|
glm::vec3 entityDimensions = entityProperties.getDimensions();
|
||||||
glm::vec3 entityPosition = entityProperties.getPosition();
|
glm::vec3 entityPosition = entityProperties.getPosition();
|
||||||
|
glm::vec3 registrationPoint = entityProperties.getRegistrationPoint();
|
||||||
glm::vec3 contextOverlayPosition = entityProperties.getPosition();
|
glm::vec3 contextOverlayPosition = entityProperties.getPosition();
|
||||||
glm::vec2 contextOverlayDimensions;
|
glm::vec2 contextOverlayDimensions;
|
||||||
|
|
||||||
// Update the position of the overlay if the registration point of the entity
|
// Update the position of the overlay if the registration point of the entity
|
||||||
// isn't default
|
// isn't default
|
||||||
if (entityProperties.getRegistrationPoint() != glm::vec3(0.5f)) {
|
if (registrationPoint != glm::vec3(0.5f)) {
|
||||||
glm::vec3 adjustPos = entityProperties.getRegistrationPoint() - glm::vec3(0.5f);
|
glm::vec3 adjustPos = registrationPoint - glm::vec3(0.5f);
|
||||||
entityPosition = entityPosition - (entityProperties.getRotation() * (adjustPos * entityProperties.getDimensions()));
|
entityPosition = entityPosition - (entityProperties.getRotation() * (adjustPos * entityDimensions));
|
||||||
}
|
}
|
||||||
|
|
||||||
enableEntityHighlight(entityItemID);
|
enableEntityHighlight(entityItemID);
|
||||||
|
|
|
@ -49,11 +49,8 @@ void Cube3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float alpha = getAlpha();
|
float alpha = getAlpha();
|
||||||
xColor color = getColor();
|
glm::u8vec3 color = getColor();
|
||||||
const float MAX_COLOR = 255.0f;
|
glm::vec4 cubeColor(toGlm(color), alpha);
|
||||||
glm::vec4 cubeColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
auto batch = args->_batch;
|
auto batch = args->_batch;
|
||||||
if (batch) {
|
if (batch) {
|
||||||
|
|
|
@ -57,11 +57,9 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
||||||
return; // do nothing if we're not visible
|
return; // do nothing if we're not visible
|
||||||
}
|
}
|
||||||
|
|
||||||
const float MAX_COLOR = 255.0f;
|
|
||||||
|
|
||||||
float alpha = getAlpha();
|
float alpha = getAlpha();
|
||||||
xColor color = getColor();
|
glm::u8vec3 color = getColor();
|
||||||
glm::vec4 gridColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
|
glm::vec4 gridColor(toGlm(color), alpha);
|
||||||
|
|
||||||
auto batch = args->_batch;
|
auto batch = args->_batch;
|
||||||
|
|
||||||
|
|
|
@ -107,17 +107,16 @@ void Image3DOverlay::render(RenderArgs* args) {
|
||||||
glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth,
|
glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth,
|
||||||
(fromImage.y() + fromImage.height() - 0.5f) / imageHeight);
|
(fromImage.y() + fromImage.height() - 0.5f) / imageHeight);
|
||||||
|
|
||||||
const float MAX_COLOR = 255.0f;
|
|
||||||
xColor color = getColor();
|
|
||||||
float alpha = getAlpha();
|
float alpha = getAlpha();
|
||||||
|
glm::u8vec3 color = getColor();
|
||||||
|
glm::vec4 imageColor(toGlm(color), alpha);
|
||||||
|
|
||||||
batch->setModelTransform(getRenderTransform());
|
batch->setModelTransform(getRenderTransform());
|
||||||
batch->setResourceTexture(0, _texture->getGPUTexture());
|
batch->setResourceTexture(0, _texture->getGPUTexture());
|
||||||
|
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(
|
DependencyManager::get<GeometryCache>()->renderQuad(
|
||||||
*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
||||||
glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha),
|
imageColor, _geometryId
|
||||||
_geometryId
|
|
||||||
);
|
);
|
||||||
|
|
||||||
batch->setResourceTexture(0, nullptr); // restore default white color after me
|
batch->setResourceTexture(0, nullptr); // restore default white color after me
|
||||||
|
|
|
@ -128,9 +128,8 @@ void Line3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float alpha = getAlpha();
|
float alpha = getAlpha();
|
||||||
xColor color = getColor();
|
glm::u8vec3 color = getColor();
|
||||||
const float MAX_COLOR = 255.0f;
|
glm::vec4 colorv4(toGlm(color), alpha);
|
||||||
glm::vec4 colorv4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
|
|
||||||
auto batch = args->_batch;
|
auto batch = args->_batch;
|
||||||
if (batch) {
|
if (batch) {
|
||||||
batch->setModelTransform(Transform());
|
batch->setModelTransform(Transform());
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
const xColor Overlay::DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
|
const glm::u8vec3 Overlay::DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
|
||||||
const float Overlay::DEFAULT_ALPHA = 0.7f;
|
const float Overlay::DEFAULT_ALPHA = 0.7f;
|
||||||
|
|
||||||
Overlay::Overlay() :
|
Overlay::Overlay() :
|
||||||
|
@ -57,7 +57,7 @@ Overlay::~Overlay() {
|
||||||
|
|
||||||
void Overlay::setProperties(const QVariantMap& properties) {
|
void Overlay::setProperties(const QVariantMap& properties) {
|
||||||
bool valid;
|
bool valid;
|
||||||
auto color = xColorFromVariant(properties["color"], valid);
|
auto color = u8vec3FromVariant(properties["color"], valid);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
_color = color;
|
_color = color;
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ QVariant Overlay::getProperty(const QString& property) {
|
||||||
return QVariant(getType());
|
return QVariant(getType());
|
||||||
}
|
}
|
||||||
if (property == "color") {
|
if (property == "color") {
|
||||||
return xColorToVariant(_color);
|
return u8vec3ColortoVariant(_color);
|
||||||
}
|
}
|
||||||
if (property == "alpha") {
|
if (property == "alpha") {
|
||||||
return _alpha;
|
return _alpha;
|
||||||
|
@ -143,21 +143,21 @@ QVariant Overlay::getProperty(const QString& property) {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
xColor Overlay::getColor() {
|
glm::u8vec3 Overlay::getColor() {
|
||||||
if (_colorPulse == 0.0f) {
|
if (_colorPulse == 0.0f) {
|
||||||
return _color;
|
return _color;
|
||||||
}
|
}
|
||||||
|
|
||||||
float pulseLevel = updatePulse();
|
float pulseLevel = updatePulse();
|
||||||
xColor result = _color;
|
glm::u8vec3 result = _color;
|
||||||
if (_colorPulse < 0.0f) {
|
if (_colorPulse < 0.0f) {
|
||||||
result.red *= (1.0f - pulseLevel);
|
result.x *= (1.0f - pulseLevel);
|
||||||
result.green *= (1.0f - pulseLevel);
|
result.y *= (1.0f - pulseLevel);
|
||||||
result.blue *= (1.0f - pulseLevel);
|
result.z *= (1.0f - pulseLevel);
|
||||||
} else {
|
} else {
|
||||||
result.red *= pulseLevel;
|
result.x *= pulseLevel;
|
||||||
result.green *= pulseLevel;
|
result.y *= pulseLevel;
|
||||||
result.blue *= pulseLevel;
|
result.z *= pulseLevel;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
#ifndef hifi_Overlay_h
|
#ifndef hifi_Overlay_h
|
||||||
#define hifi_Overlay_h
|
#define hifi_Overlay_h
|
||||||
|
|
||||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
|
||||||
#include <SharedUtil.h> // for xColor
|
|
||||||
#include <render/Scene.h>
|
#include <render/Scene.h>
|
||||||
|
|
||||||
class OverlayID : public QUuid {
|
class OverlayID : public QUuid {
|
||||||
|
@ -59,7 +57,7 @@ public:
|
||||||
virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; };
|
virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; };
|
||||||
virtual bool getIsVisibleInSecondaryCamera() const { return false; }
|
virtual bool getIsVisibleInSecondaryCamera() const { return false; }
|
||||||
|
|
||||||
xColor getColor();
|
glm::u8vec3 getColor();
|
||||||
float getAlpha();
|
float getAlpha();
|
||||||
|
|
||||||
float getPulseMax() const { return _pulseMax; }
|
float getPulseMax() const { return _pulseMax; }
|
||||||
|
@ -73,7 +71,7 @@ public:
|
||||||
// setters
|
// setters
|
||||||
virtual void setVisible(bool visible) { _visible = visible; }
|
virtual void setVisible(bool visible) { _visible = visible; }
|
||||||
void setDrawHUDLayer(bool drawHUDLayer);
|
void setDrawHUDLayer(bool drawHUDLayer);
|
||||||
void setColor(const xColor& color) { _color = color; }
|
void setColor(const glm::u8vec3& color) { _color = color; }
|
||||||
void setAlpha(float alpha) { _alpha = alpha; }
|
void setAlpha(float alpha) { _alpha = alpha; }
|
||||||
|
|
||||||
void setPulseMax(float value) { _pulseMax = value; }
|
void setPulseMax(float value) { _pulseMax = value; }
|
||||||
|
@ -115,12 +113,12 @@ protected:
|
||||||
float _alphaPulse; // ratio of the pulse to the alpha
|
float _alphaPulse; // ratio of the pulse to the alpha
|
||||||
float _colorPulse; // ratio of the pulse to the color
|
float _colorPulse; // ratio of the pulse to the color
|
||||||
|
|
||||||
xColor _color;
|
glm::u8vec3 _color;
|
||||||
bool _visible; // should the overlay be drawn at all
|
bool _visible; // should the overlay be drawn at all
|
||||||
|
|
||||||
unsigned int _stackOrder { 0 };
|
unsigned int _stackOrder { 0 };
|
||||||
|
|
||||||
static const xColor DEFAULT_OVERLAY_COLOR;
|
static const glm::u8vec3 DEFAULT_OVERLAY_COLOR;
|
||||||
static const float DEFAULT_ALPHA;
|
static const float DEFAULT_ALPHA;
|
||||||
|
|
||||||
std::unordered_map<std::string, graphics::MultiMaterial> _materials;
|
std::unordered_map<std::string, graphics::MultiMaterial> _materials;
|
||||||
|
|
|
@ -532,6 +532,8 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionVector(const PickRay
|
||||||
bool visibleOnly, bool collidableOnly) {
|
bool visibleOnly, bool collidableOnly) {
|
||||||
float bestDistance = std::numeric_limits<float>::max();
|
float bestDistance = std::numeric_limits<float>::max();
|
||||||
bool bestIsFront = false;
|
bool bestIsFront = false;
|
||||||
|
bool bestIsTablet = false;
|
||||||
|
auto tabletIDs = qApp->getTabletIDs();
|
||||||
|
|
||||||
QMutexLocker locker(&_mutex);
|
QMutexLocker locker(&_mutex);
|
||||||
RayToOverlayIntersectionResult result;
|
RayToOverlayIntersectionResult result;
|
||||||
|
@ -554,10 +556,11 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionVector(const PickRay
|
||||||
if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance,
|
if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance,
|
||||||
thisFace, thisSurfaceNormal, thisExtraInfo, precisionPicking)) {
|
thisFace, thisSurfaceNormal, thisExtraInfo, precisionPicking)) {
|
||||||
bool isDrawInFront = thisOverlay->getDrawInFront();
|
bool isDrawInFront = thisOverlay->getDrawInFront();
|
||||||
if ((bestIsFront && isDrawInFront && thisDistance < bestDistance)
|
bool isTablet = tabletIDs.contains(thisID);
|
||||||
|| (!bestIsFront && (isDrawInFront || thisDistance < bestDistance))) {
|
if ((isDrawInFront && !bestIsFront && !bestIsTablet)
|
||||||
|
|| ((isTablet || isDrawInFront || !bestIsFront) && thisDistance < bestDistance)) {
|
||||||
bestIsFront = isDrawInFront;
|
bestIsFront = isDrawInFront;
|
||||||
|
bestIsTablet = isTablet;
|
||||||
bestDistance = thisDistance;
|
bestDistance = thisDistance;
|
||||||
result.intersects = true;
|
result.intersects = true;
|
||||||
result.distance = thisDistance;
|
result.distance = thisDistance;
|
||||||
|
@ -629,9 +632,9 @@ QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine,
|
||||||
obj.setProperty("distance", value.distance);
|
obj.setProperty("distance", value.distance);
|
||||||
obj.setProperty("face", boxFaceToString(value.face));
|
obj.setProperty("face", boxFaceToString(value.face));
|
||||||
|
|
||||||
QScriptValue intersection = vec3toScriptValue(engine, value.intersection);
|
QScriptValue intersection = vec3ToScriptValue(engine, value.intersection);
|
||||||
obj.setProperty("intersection", intersection);
|
obj.setProperty("intersection", intersection);
|
||||||
QScriptValue surfaceNormal = vec3toScriptValue(engine, value.surfaceNormal);
|
QScriptValue surfaceNormal = vec3ToScriptValue(engine, value.surfaceNormal);
|
||||||
obj.setProperty("surfaceNormal", surfaceNormal);
|
obj.setProperty("surfaceNormal", surfaceNormal);
|
||||||
obj.setProperty("extraInfo", engine->toScriptValue(value.extraInfo));
|
obj.setProperty("extraInfo", engine->toScriptValue(value.extraInfo));
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -828,40 +831,12 @@ PointerEvent Overlays::calculateOverlayPointerEvent(OverlayID overlayID, PickRay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RayToOverlayIntersectionResult Overlays::findRayIntersectionForMouseEvent(PickRay ray) {
|
|
||||||
QVector<OverlayID> overlaysToInclude;
|
|
||||||
QVector<OverlayID> overlaysToDiscard;
|
|
||||||
RayToOverlayIntersectionResult rayPickResult;
|
|
||||||
|
|
||||||
// first priority is tablet screen
|
|
||||||
overlaysToInclude << qApp->getTabletScreenID();
|
|
||||||
rayPickResult = findRayIntersectionVector(ray, true, overlaysToInclude, overlaysToDiscard);
|
|
||||||
if (rayPickResult.intersects) {
|
|
||||||
return rayPickResult;
|
|
||||||
}
|
|
||||||
// then tablet home button
|
|
||||||
overlaysToInclude.clear();
|
|
||||||
overlaysToInclude << qApp->getTabletHomeButtonID();
|
|
||||||
rayPickResult = findRayIntersectionVector(ray, true, overlaysToInclude, overlaysToDiscard);
|
|
||||||
if (rayPickResult.intersects) {
|
|
||||||
return rayPickResult;
|
|
||||||
}
|
|
||||||
// then tablet frame
|
|
||||||
overlaysToInclude.clear();
|
|
||||||
overlaysToInclude << OverlayID(qApp->getTabletFrameID());
|
|
||||||
rayPickResult = findRayIntersectionVector(ray, true, overlaysToInclude, overlaysToDiscard);
|
|
||||||
if (rayPickResult.intersects) {
|
|
||||||
return rayPickResult;
|
|
||||||
}
|
|
||||||
// then whatever
|
|
||||||
return findRayIntersection(ray);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Overlays::mousePressEvent(QMouseEvent* event) {
|
bool Overlays::mousePressEvent(QMouseEvent* event) {
|
||||||
PerformanceTimer perfTimer("Overlays::mousePressEvent");
|
PerformanceTimer perfTimer("Overlays::mousePressEvent");
|
||||||
|
|
||||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
||||||
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(),
|
||||||
|
QVector<OverlayID>());
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
||||||
|
|
||||||
|
@ -901,7 +876,8 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
|
||||||
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
|
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
|
||||||
|
|
||||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
||||||
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(),
|
||||||
|
QVector<OverlayID>());
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
||||||
|
|
||||||
|
@ -964,7 +940,8 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
|
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
|
||||||
|
|
||||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
||||||
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(),
|
||||||
|
QVector<OverlayID>());
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release);
|
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release);
|
||||||
mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent);
|
mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent);
|
||||||
|
@ -993,7 +970,8 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
|
||||||
PerformanceTimer perfTimer("Overlays::mouseMoveEvent");
|
PerformanceTimer perfTimer("Overlays::mouseMoveEvent");
|
||||||
|
|
||||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
||||||
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(),
|
||||||
|
QVector<OverlayID>());
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move);
|
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move);
|
||||||
mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent);
|
mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent);
|
||||||
|
|
|
@ -44,8 +44,7 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPro
|
||||||
const OverlayID UNKNOWN_OVERLAY_ID = OverlayID();
|
const OverlayID UNKNOWN_OVERLAY_ID = OverlayID();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* The result of a {@link PickRay} search using {@link Overlays.findRayIntersection|findRayIntersection} or
|
* The result of a {@link PickRay} search using {@link Overlays.findRayIntersection|findRayIntersection}.
|
||||||
* {@link Overlays.findRayIntersectionVector|findRayIntersectionVector}.
|
|
||||||
* @typedef {object} Overlays.RayToOverlayIntersectionResult
|
* @typedef {object} Overlays.RayToOverlayIntersectionResult
|
||||||
* @property {boolean} intersects - <code>true</code> if the {@link PickRay} intersected with a 3D overlay, otherwise
|
* @property {boolean} intersects - <code>true</code> if the {@link PickRay} intersected with a 3D overlay, otherwise
|
||||||
* <code>false</code>.
|
* <code>false</code>.
|
||||||
|
@ -383,7 +382,11 @@ public slots:
|
||||||
OverlayPropertyResult getOverlaysProperties(const QVariant& overlaysProperties);
|
OverlayPropertyResult getOverlaysProperties(const QVariant& overlaysProperties);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Find the closest 3D overlay intersected by a {@link PickRay}.
|
* Find the closest 3D overlay intersected by a {@link PickRay}. Overlays with their <code>drawInFront</code> property set
|
||||||
|
* to <code>true</code> have priority over overlays that don't, except that tablet overlays have priority over any
|
||||||
|
* <code>drawInFront</code> overlays behind them. I.e., if a <code>drawInFront</code> overlay is behind one that isn't
|
||||||
|
* <code>drawInFront</code>, the <code>drawInFront</code> overlay is returned, but if a tablet overlay is in front of a
|
||||||
|
* <code>drawInFront</code> overlay, the tablet overlay is returned.
|
||||||
* @function Overlays.findRayIntersection
|
* @function Overlays.findRayIntersection
|
||||||
* @param {PickRay} pickRay - The PickRay to use for finding overlays.
|
* @param {PickRay} pickRay - The PickRay to use for finding overlays.
|
||||||
* @param {boolean} [precisionPicking=false] - <em>Unused</em>; exists to match Entity API.
|
* @param {boolean} [precisionPicking=false] - <em>Unused</em>; exists to match Entity API.
|
||||||
|
@ -750,8 +753,6 @@ private:
|
||||||
OverlayID _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID };
|
OverlayID _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID };
|
||||||
OverlayID _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID };
|
OverlayID _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID };
|
||||||
|
|
||||||
RayToOverlayIntersectionResult findRayIntersectionForMouseEvent(PickRay ray);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void mousePressPointerEvent(const OverlayID& overlayID, const PointerEvent& event);
|
void mousePressPointerEvent(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
void mouseMovePointerEvent(const OverlayID& overlayID, const PointerEvent& event);
|
void mouseMovePointerEvent(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
|
|
|
@ -64,7 +64,7 @@ void Planar3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
*/
|
*/
|
||||||
QVariant Planar3DOverlay::getProperty(const QString& property) {
|
QVariant Planar3DOverlay::getProperty(const QString& property) {
|
||||||
if (property == "dimensions" || property == "scale" || property == "size") {
|
if (property == "dimensions" || property == "scale" || property == "size") {
|
||||||
return vec2toVariant(getDimensions());
|
return vec2ToVariant(getDimensions());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Base3DOverlay::getProperty(property);
|
return Base3DOverlay::getProperty(property);
|
||||||
|
|
|
@ -51,9 +51,8 @@ void Rectangle3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float alpha = getAlpha();
|
float alpha = getAlpha();
|
||||||
xColor color = getColor();
|
glm::u8vec3 color = getColor();
|
||||||
const float MAX_COLOR = 255.0f;
|
glm::vec4 rectangleColor(toGlm(color), alpha);
|
||||||
glm::vec4 rectangleColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
|
|
||||||
|
|
||||||
auto batch = args->_batch;
|
auto batch = args->_batch;
|
||||||
if (batch) {
|
if (batch) {
|
||||||
|
|
|
@ -30,9 +30,8 @@ void Shape3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float alpha = getAlpha();
|
float alpha = getAlpha();
|
||||||
xColor color = getColor();
|
glm::u8vec3 color = getColor();
|
||||||
const float MAX_COLOR = 255.0f;
|
glm::vec4 shapeColor(toGlm(color), alpha);
|
||||||
glm::vec4 cubeColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
|
|
||||||
|
|
||||||
auto batch = args->_batch;
|
auto batch = args->_batch;
|
||||||
if (batch) {
|
if (batch) {
|
||||||
|
@ -44,9 +43,9 @@ void Shape3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
batch->setModelTransform(getRenderTransform());
|
batch->setModelTransform(getRenderTransform());
|
||||||
if (_isSolid) {
|
if (_isSolid) {
|
||||||
geometryCache->renderSolidShapeInstance(args, *batch, _shape, cubeColor, shapePipeline);
|
geometryCache->renderSolidShapeInstance(args, *batch, _shape, shapeColor, shapePipeline);
|
||||||
} else {
|
} else {
|
||||||
geometryCache->renderWireShapeInstance(args, *batch, _shape, cubeColor, shapePipeline);
|
geometryCache->renderWireShapeInstance(args, *batch, _shape, shapeColor, shapePipeline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,9 +77,8 @@ void Sphere3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float alpha = getAlpha();
|
float alpha = getAlpha();
|
||||||
xColor color = getColor();
|
glm::u8vec3 color = getColor();
|
||||||
const float MAX_COLOR = 255.0f;
|
glm::vec4 sphereColor(toGlm(color), alpha);
|
||||||
glm::vec4 sphereColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
|
|
||||||
|
|
||||||
auto batch = args->_batch;
|
auto batch = args->_batch;
|
||||||
|
|
||||||
|
|
|
@ -64,21 +64,21 @@ void Text3DOverlay::setText(const QString& text) {
|
||||||
_text = text;
|
_text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
xColor Text3DOverlay::getBackgroundColor() {
|
glm::u8vec3 Text3DOverlay::getBackgroundColor() {
|
||||||
if (_colorPulse == 0.0f) {
|
if (_colorPulse == 0.0f) {
|
||||||
return _backgroundColor;
|
return _backgroundColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
float pulseLevel = updatePulse();
|
float pulseLevel = updatePulse();
|
||||||
xColor result = _backgroundColor;
|
glm::u8vec3 result = _backgroundColor;
|
||||||
if (_colorPulse < 0.0f) {
|
if (_colorPulse < 0.0f) {
|
||||||
result.red *= (1.0f - pulseLevel);
|
result.x *= (1.0f - pulseLevel);
|
||||||
result.green *= (1.0f - pulseLevel);
|
result.y *= (1.0f - pulseLevel);
|
||||||
result.blue *= (1.0f - pulseLevel);
|
result.z *= (1.0f - pulseLevel);
|
||||||
} else {
|
} else {
|
||||||
result.red *= pulseLevel;
|
result.x *= pulseLevel;
|
||||||
result.green *= pulseLevel;
|
result.y *= pulseLevel;
|
||||||
result.blue *= pulseLevel;
|
result.z *= pulseLevel;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -94,10 +94,8 @@ void Text3DOverlay::render(RenderArgs* args) {
|
||||||
auto transform = getRenderTransform();
|
auto transform = getRenderTransform();
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
|
|
||||||
const float MAX_COLOR = 255.0f;
|
glm::u8vec3 backgroundColor = getBackgroundColor();
|
||||||
xColor backgroundColor = getBackgroundColor();
|
glm::vec4 quadColor(toGlm(backgroundColor), getBackgroundAlpha());
|
||||||
glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR,
|
|
||||||
backgroundColor.blue / MAX_COLOR, getBackgroundAlpha());
|
|
||||||
|
|
||||||
glm::vec2 dimensions = getDimensions();
|
glm::vec2 dimensions = getDimensions();
|
||||||
glm::vec2 halfDimensions = dimensions * 0.5f;
|
glm::vec2 halfDimensions = dimensions * 0.5f;
|
||||||
|
@ -122,8 +120,7 @@ void Text3DOverlay::render(RenderArgs* args) {
|
||||||
transform.setScale(scaleFactor);
|
transform.setScale(scaleFactor);
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
|
|
||||||
glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR,
|
glm::vec4 textColor = { toGlm(_color), getTextAlpha() };
|
||||||
_color.blue / MAX_COLOR, getTextAlpha() };
|
|
||||||
|
|
||||||
// FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline for a gpu performance increase.
|
// FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline for a gpu performance increase.
|
||||||
_textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f), true);
|
_textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f), true);
|
||||||
|
@ -164,7 +161,7 @@ void Text3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
bool valid;
|
bool valid;
|
||||||
auto backgroundColor = properties["backgroundColor"];
|
auto backgroundColor = properties["backgroundColor"];
|
||||||
if (backgroundColor.isValid()) {
|
if (backgroundColor.isValid()) {
|
||||||
auto color = xColorFromVariant(backgroundColor, valid);
|
auto color = u8vec3FromVariant(backgroundColor, valid);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
_backgroundColor = color;
|
_backgroundColor = color;
|
||||||
}
|
}
|
||||||
|
@ -260,7 +257,7 @@ QVariant Text3DOverlay::getProperty(const QString& property) {
|
||||||
return _textAlpha;
|
return _textAlpha;
|
||||||
}
|
}
|
||||||
if (property == "backgroundColor") {
|
if (property == "backgroundColor") {
|
||||||
return xColorToVariant(_backgroundColor);
|
return u8vec3ColortoVariant(_backgroundColor);
|
||||||
}
|
}
|
||||||
if (property == "backgroundAlpha") {
|
if (property == "backgroundAlpha") {
|
||||||
return Billboard3DOverlay::getProperty("alpha");
|
return Billboard3DOverlay::getProperty("alpha");
|
||||||
|
|
|
@ -39,7 +39,7 @@ public:
|
||||||
float getTopMargin() const { return _topMargin; }
|
float getTopMargin() const { return _topMargin; }
|
||||||
float getRightMargin() const { return _rightMargin; }
|
float getRightMargin() const { return _rightMargin; }
|
||||||
float getBottomMargin() const { return _bottomMargin; }
|
float getBottomMargin() const { return _bottomMargin; }
|
||||||
xColor getBackgroundColor();
|
glm::u8vec3 getBackgroundColor();
|
||||||
float getTextAlpha() { return _textAlpha; }
|
float getTextAlpha() { return _textAlpha; }
|
||||||
float getBackgroundAlpha() { return getAlpha(); }
|
float getBackgroundAlpha() { return getAlpha(); }
|
||||||
bool isTransparent() override { return Overlay::isTransparent() || _textAlpha < 1.0f; }
|
bool isTransparent() override { return Overlay::isTransparent() || _textAlpha < 1.0f; }
|
||||||
|
@ -65,7 +65,7 @@ private:
|
||||||
|
|
||||||
QString _text;
|
QString _text;
|
||||||
mutable QMutex _mutex; // used to make get/setText threadsafe, mutable so can be used in const functions
|
mutable QMutex _mutex; // used to make get/setText threadsafe, mutable so can be used in const functions
|
||||||
xColor _backgroundColor = xColor { 0, 0, 0 };
|
glm::u8vec3 _backgroundColor { 0, 0, 0 };
|
||||||
float _textAlpha { 1.0f };
|
float _textAlpha { 1.0f };
|
||||||
float _lineHeight { 1.0f };
|
float _lineHeight { 1.0f };
|
||||||
float _leftMargin { 0.1f };
|
float _leftMargin { 0.1f };
|
||||||
|
|
|
@ -40,7 +40,7 @@ QScriptValue AnimVariantMap::animVariantMapToScriptValue(QScriptEngine* engine,
|
||||||
target.setProperty(name, value.getString());
|
target.setProperty(name, value.getString());
|
||||||
break;
|
break;
|
||||||
case AnimVariant::Type::Vec3:
|
case AnimVariant::Type::Vec3:
|
||||||
target.setProperty(name, vec3toScriptValue(engine, value.getVec3()));
|
target.setProperty(name, vec3ToScriptValue(engine, value.getVec3()));
|
||||||
break;
|
break;
|
||||||
case AnimVariant::Type::Quat:
|
case AnimVariant::Type::Quat:
|
||||||
target.setProperty(name, quatToScriptValue(engine, value.getQuat()));
|
target.setProperty(name, quatToScriptValue(engine, value.getQuat()));
|
||||||
|
@ -169,7 +169,8 @@ std::map<QString, QString> AnimVariantMap::toDebugMap() const {
|
||||||
break;
|
break;
|
||||||
*/
|
*/
|
||||||
default:
|
default:
|
||||||
assert(("invalid AnimVariant::Type", false));
|
// invalid AnimVariant::Type
|
||||||
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
class Animation;
|
class Animation;
|
||||||
|
|
||||||
typedef QSharedPointer<Animation> AnimationPointer;
|
using AnimationPointer = QSharedPointer<Animation>;
|
||||||
|
|
||||||
class AnimationCache : public ResourceCache, public Dependency {
|
class AnimationCache : public ResourceCache, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
@ -1253,7 +1253,6 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
|
||||||
const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix) {
|
const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix) {
|
||||||
|
|
||||||
const bool ENABLE_POLE_VECTORS = true;
|
const bool ENABLE_POLE_VECTORS = true;
|
||||||
const float ELBOW_POLE_VECTOR_BLEND_FACTOR = 0.95f;
|
|
||||||
|
|
||||||
if (leftHandEnabled) {
|
if (leftHandEnabled) {
|
||||||
|
|
||||||
|
@ -1279,33 +1278,16 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
|
||||||
bool usePoleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, oppositeArmJointIndex, poleVector);
|
bool usePoleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, oppositeArmJointIndex, poleVector);
|
||||||
if (usePoleVector) {
|
if (usePoleVector) {
|
||||||
glm::vec3 sensorPoleVector = transformVectorFast(rigToSensorMatrix, poleVector);
|
glm::vec3 sensorPoleVector = transformVectorFast(rigToSensorMatrix, poleVector);
|
||||||
|
|
||||||
if (_smoothPoleVectors) {
|
|
||||||
// smooth toward desired pole vector from previous pole vector... to reduce jitter
|
|
||||||
if (!_prevLeftHandPoleVectorValid) {
|
|
||||||
_prevLeftHandPoleVectorValid = true;
|
|
||||||
_prevLeftHandPoleVector = sensorPoleVector;
|
|
||||||
}
|
|
||||||
glm::quat deltaRot = rotationBetween(_prevLeftHandPoleVector, sensorPoleVector);
|
|
||||||
glm::quat smoothDeltaRot = safeMix(deltaRot, Quaternions::IDENTITY, ELBOW_POLE_VECTOR_BLEND_FACTOR);
|
|
||||||
_prevLeftHandPoleVector = smoothDeltaRot * _prevLeftHandPoleVector;
|
|
||||||
} else {
|
|
||||||
_prevLeftHandPoleVector = sensorPoleVector;
|
|
||||||
}
|
|
||||||
_animVars.set("leftHandPoleVectorEnabled", true);
|
_animVars.set("leftHandPoleVectorEnabled", true);
|
||||||
_animVars.set("leftHandPoleReferenceVector", Vectors::UNIT_X);
|
_animVars.set("leftHandPoleReferenceVector", Vectors::UNIT_X);
|
||||||
_animVars.set("leftHandPoleVector", transformVectorFast(sensorToRigMatrix, _prevLeftHandPoleVector));
|
_animVars.set("leftHandPoleVector", transformVectorFast(sensorToRigMatrix, sensorPoleVector));
|
||||||
} else {
|
} else {
|
||||||
_prevLeftHandPoleVectorValid = false;
|
|
||||||
_animVars.set("leftHandPoleVectorEnabled", false);
|
_animVars.set("leftHandPoleVectorEnabled", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_prevLeftHandPoleVectorValid = false;
|
|
||||||
_animVars.set("leftHandPoleVectorEnabled", false);
|
_animVars.set("leftHandPoleVectorEnabled", false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_prevLeftHandPoleVectorValid = false;
|
|
||||||
_animVars.set("leftHandPoleVectorEnabled", false);
|
_animVars.set("leftHandPoleVectorEnabled", false);
|
||||||
|
|
||||||
_animVars.unset("leftHandPosition");
|
_animVars.unset("leftHandPosition");
|
||||||
|
@ -1344,33 +1326,16 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
|
||||||
bool usePoleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, oppositeArmJointIndex, poleVector);
|
bool usePoleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, oppositeArmJointIndex, poleVector);
|
||||||
if (usePoleVector) {
|
if (usePoleVector) {
|
||||||
glm::vec3 sensorPoleVector = transformVectorFast(rigToSensorMatrix, poleVector);
|
glm::vec3 sensorPoleVector = transformVectorFast(rigToSensorMatrix, poleVector);
|
||||||
|
|
||||||
if (_smoothPoleVectors) {
|
|
||||||
// smooth toward desired pole vector from previous pole vector... to reduce jitter
|
|
||||||
if (!_prevRightHandPoleVectorValid) {
|
|
||||||
_prevRightHandPoleVectorValid = true;
|
|
||||||
_prevRightHandPoleVector = sensorPoleVector;
|
|
||||||
}
|
|
||||||
glm::quat deltaRot = rotationBetween(_prevRightHandPoleVector, sensorPoleVector);
|
|
||||||
glm::quat smoothDeltaRot = safeMix(deltaRot, Quaternions::IDENTITY, ELBOW_POLE_VECTOR_BLEND_FACTOR);
|
|
||||||
_prevRightHandPoleVector = smoothDeltaRot * _prevRightHandPoleVector;
|
|
||||||
} else {
|
|
||||||
_prevRightHandPoleVector = sensorPoleVector;
|
|
||||||
}
|
|
||||||
|
|
||||||
_animVars.set("rightHandPoleVectorEnabled", true);
|
_animVars.set("rightHandPoleVectorEnabled", true);
|
||||||
_animVars.set("rightHandPoleReferenceVector", -Vectors::UNIT_X);
|
_animVars.set("rightHandPoleReferenceVector", -Vectors::UNIT_X);
|
||||||
_animVars.set("rightHandPoleVector", transformVectorFast(sensorToRigMatrix, _prevRightHandPoleVector));
|
_animVars.set("rightHandPoleVector", transformVectorFast(sensorToRigMatrix, sensorPoleVector));
|
||||||
} else {
|
} else {
|
||||||
_prevRightHandPoleVectorValid = false;
|
|
||||||
_animVars.set("rightHandPoleVectorEnabled", false);
|
_animVars.set("rightHandPoleVectorEnabled", false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_prevRightHandPoleVectorValid = false;
|
|
||||||
_animVars.set("rightHandPoleVectorEnabled", false);
|
_animVars.set("rightHandPoleVectorEnabled", false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_prevRightHandPoleVectorValid = false;
|
|
||||||
_animVars.set("rightHandPoleVectorEnabled", false);
|
_animVars.set("rightHandPoleVectorEnabled", false);
|
||||||
|
|
||||||
_animVars.unset("rightHandPosition");
|
_animVars.unset("rightHandPosition");
|
||||||
|
|
|
@ -227,7 +227,6 @@ public:
|
||||||
const AnimVariantMap& getAnimVars() const { return _lastAnimVars; }
|
const AnimVariantMap& getAnimVars() const { return _lastAnimVars; }
|
||||||
const AnimContext::DebugStateMachineMap& getStateMachineMap() const { return _lastContext.getStateMachineMap(); }
|
const AnimContext::DebugStateMachineMap& getStateMachineMap() const { return _lastContext.getStateMachineMap(); }
|
||||||
|
|
||||||
void toggleSmoothPoleVectors() { _smoothPoleVectors = !_smoothPoleVectors; };
|
|
||||||
signals:
|
signals:
|
||||||
void onLoadComplete();
|
void onLoadComplete();
|
||||||
|
|
||||||
|
@ -381,14 +380,6 @@ protected:
|
||||||
glm::vec3 _prevLeftFootPoleVector { Vectors::UNIT_Z }; // sensor space
|
glm::vec3 _prevLeftFootPoleVector { Vectors::UNIT_Z }; // sensor space
|
||||||
bool _prevLeftFootPoleVectorValid { false };
|
bool _prevLeftFootPoleVectorValid { false };
|
||||||
|
|
||||||
glm::vec3 _prevRightHandPoleVector{ -Vectors::UNIT_Z }; // sensor space
|
|
||||||
bool _prevRightHandPoleVectorValid{ false };
|
|
||||||
|
|
||||||
glm::vec3 _prevLeftHandPoleVector{ -Vectors::UNIT_Z }; // sensor space
|
|
||||||
bool _prevLeftHandPoleVectorValid{ false };
|
|
||||||
|
|
||||||
bool _smoothPoleVectors { false };
|
|
||||||
|
|
||||||
int _rigId;
|
int _rigId;
|
||||||
bool _headEnabled { false };
|
bool _headEnabled { false };
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ AudioInjectorOptions::AudioInjectorOptions() :
|
||||||
|
|
||||||
QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInjectorOptions& injectorOptions) {
|
QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInjectorOptions& injectorOptions) {
|
||||||
QScriptValue obj = engine->newObject();
|
QScriptValue obj = engine->newObject();
|
||||||
obj.setProperty("position", vec3toScriptValue(engine, injectorOptions.position));
|
obj.setProperty("position", vec3ToScriptValue(engine, injectorOptions.position));
|
||||||
obj.setProperty("volume", injectorOptions.volume);
|
obj.setProperty("volume", injectorOptions.volume);
|
||||||
obj.setProperty("loop", injectorOptions.loop);
|
obj.setProperty("loop", injectorOptions.loop);
|
||||||
obj.setProperty("orientation", quatToScriptValue(engine, injectorOptions.orientation));
|
obj.setProperty("orientation", quatToScriptValue(engine, injectorOptions.orientation));
|
||||||
|
|
|
@ -173,7 +173,6 @@ AvatarTransit::Status AvatarTransit::updatePosition(float deltaTime) {
|
||||||
Status status = Status::IDLE;
|
Status status = Status::IDLE;
|
||||||
if (_isTransiting) {
|
if (_isTransiting) {
|
||||||
float nextTime = _currentTime + deltaTime;
|
float nextTime = _currentTime + deltaTime;
|
||||||
glm::vec3 newPosition;
|
|
||||||
if (nextTime >= _totalTime) {
|
if (nextTime >= _totalTime) {
|
||||||
_currentPosition = _endPosition;
|
_currentPosition = _endPosition;
|
||||||
_isTransiting = false;
|
_isTransiting = false;
|
||||||
|
@ -704,6 +703,19 @@ static TextRenderer3D* textRenderer(TextRendererType type) {
|
||||||
return displayNameRenderer;
|
return displayNameRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Avatar::metaBlendshapeOperator(int blendshapeNumber, const QVector<BlendshapeOffset>& blendshapeOffsets, const QVector<int>& blendedMeshSizes,
|
||||||
|
const render::ItemIDs& subItemIDs) {
|
||||||
|
render::Transaction transaction;
|
||||||
|
transaction.updateItem<AvatarData>(_renderItemID, [blendshapeNumber, blendshapeOffsets, blendedMeshSizes,
|
||||||
|
subItemIDs](AvatarData& avatar) {
|
||||||
|
auto avatarPtr = dynamic_cast<Avatar*>(&avatar);
|
||||||
|
if (avatarPtr) {
|
||||||
|
avatarPtr->setBlendedVertices(blendshapeNumber, blendshapeOffsets, blendedMeshSizes, subItemIDs);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& scene, render::Transaction& transaction) {
|
void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||||
auto avatarPayload = new render::Payload<AvatarData>(self);
|
auto avatarPayload = new render::Payload<AvatarData>(self);
|
||||||
auto avatarPayloadPointer = std::shared_ptr<render::Payload<AvatarData>>(avatarPayload);
|
auto avatarPayloadPointer = std::shared_ptr<render::Payload<AvatarData>>(avatarPayload);
|
||||||
|
@ -713,7 +725,8 @@ void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& sc
|
||||||
// INitialize the _render bound as we are creating the avatar render item
|
// INitialize the _render bound as we are creating the avatar render item
|
||||||
_renderBound = getBounds();
|
_renderBound = getBounds();
|
||||||
transaction.resetItem(_renderItemID, avatarPayloadPointer);
|
transaction.resetItem(_renderItemID, avatarPayloadPointer);
|
||||||
_skeletonModel->addToScene(scene, transaction);
|
using namespace std::placeholders;
|
||||||
|
_skeletonModel->addToScene(scene, transaction, std::bind(&Avatar::metaBlendshapeOperator, this, _1, _2, _3, _4));
|
||||||
_skeletonModel->setTagMask(render::hifi::TAG_ALL_VIEWS);
|
_skeletonModel->setTagMask(render::hifi::TAG_ALL_VIEWS);
|
||||||
_skeletonModel->setGroupCulled(true);
|
_skeletonModel->setGroupCulled(true);
|
||||||
_skeletonModel->setCanCastShadow(true);
|
_skeletonModel->setCanCastShadow(true);
|
||||||
|
@ -792,7 +805,7 @@ void Avatar::updateRenderItem(render::Transaction& transaction) {
|
||||||
avatarPtr->_renderBound = renderBound;
|
avatarPtr->_renderBound = renderBound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -936,7 +949,8 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) {
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) {
|
if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) {
|
||||||
_skeletonModel->removeFromScene(scene, transaction);
|
_skeletonModel->removeFromScene(scene, transaction);
|
||||||
_skeletonModel->addToScene(scene, transaction);
|
using namespace std::placeholders;
|
||||||
|
_skeletonModel->addToScene(scene, transaction, std::bind(&Avatar::metaBlendshapeOperator, this, _1, _2, _3, _4));
|
||||||
|
|
||||||
_skeletonModel->setTagMask(render::hifi::TAG_ALL_VIEWS);
|
_skeletonModel->setTagMask(render::hifi::TAG_ALL_VIEWS);
|
||||||
_skeletonModel->setGroupCulled(true);
|
_skeletonModel->setGroupCulled(true);
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include "Rig.h"
|
#include "Rig.h"
|
||||||
#include <ThreadSafeValueCache.h>
|
#include <ThreadSafeValueCache.h>
|
||||||
|
|
||||||
|
#include "MetaModelPayload.h"
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar);
|
template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar);
|
||||||
template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar);
|
template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar);
|
||||||
|
@ -108,7 +110,7 @@ private:
|
||||||
float _scale { 1.0f };
|
float _scale { 1.0f };
|
||||||
};
|
};
|
||||||
|
|
||||||
class Avatar : public AvatarData, public scriptable::ModelProvider {
|
class Avatar : public AvatarData, public scriptable::ModelProvider, public MetaModelPayload {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
// This property has JSDoc in MyAvatar.h.
|
// This property has JSDoc in MyAvatar.h.
|
||||||
|
@ -620,6 +622,9 @@ protected:
|
||||||
static const float ATTACHMENT_LOADING_PRIORITY;
|
static const float ATTACHMENT_LOADING_PRIORITY;
|
||||||
|
|
||||||
LoadingStatus _loadingStatus { LoadingStatus::NoModel };
|
LoadingStatus _loadingStatus { LoadingStatus::NoModel };
|
||||||
|
|
||||||
|
void metaBlendshapeOperator(int blendshapeNumber, const QVector<BlendshapeOffset>& blendshapeOffsets, const QVector<int>& blendedMeshSizes,
|
||||||
|
const render::ItemIDs& subItemIDs);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Avatar_h
|
#endif // hifi_Avatar_h
|
||||||
|
|
|
@ -2832,10 +2832,10 @@ QScriptValue RayToAvatarIntersectionResultToScriptValue(QScriptEngine* engine, c
|
||||||
obj.setProperty("avatarID", avatarIDValue);
|
obj.setProperty("avatarID", avatarIDValue);
|
||||||
obj.setProperty("distance", value.distance);
|
obj.setProperty("distance", value.distance);
|
||||||
obj.setProperty("face", boxFaceToString(value.face));
|
obj.setProperty("face", boxFaceToString(value.face));
|
||||||
|
QScriptValue intersection = vec3ToScriptValue(engine, value.intersection);
|
||||||
|
|
||||||
QScriptValue intersection = vec3toScriptValue(engine, value.intersection);
|
|
||||||
obj.setProperty("intersection", intersection);
|
obj.setProperty("intersection", intersection);
|
||||||
QScriptValue surfaceNormal = vec3toScriptValue(engine, value.surfaceNormal);
|
QScriptValue surfaceNormal = vec3ToScriptValue(engine, value.surfaceNormal);
|
||||||
obj.setProperty("surfaceNormal", surfaceNormal);
|
obj.setProperty("surfaceNormal", surfaceNormal);
|
||||||
obj.setProperty("extraInfo", engine->toScriptValue(value.extraInfo));
|
obj.setProperty("extraInfo", engine->toScriptValue(value.extraInfo));
|
||||||
return obj;
|
return obj;
|
||||||
|
|
|
@ -258,7 +258,6 @@ AvatarSharedPointer AvatarHashMap::parseAvatarData(QSharedPointer<ReceivedMessag
|
||||||
|
|
||||||
if (isNewAvatar) {
|
if (isNewAvatar) {
|
||||||
QWriteLocker locker(&_hashLock);
|
QWriteLocker locker(&_hashLock);
|
||||||
_pendingAvatars.insert(sessionUUID, { std::chrono::steady_clock::now(), 0, avatar });
|
|
||||||
avatar->setIsNewAvatar(true);
|
avatar->setIsNewAvatar(true);
|
||||||
auto replicaIDs = _replicas.getReplicaIDs(sessionUUID);
|
auto replicaIDs = _replicas.getReplicaIDs(sessionUUID);
|
||||||
for (auto replicaID : replicaIDs) {
|
for (auto replicaID : replicaIDs) {
|
||||||
|
@ -300,7 +299,6 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer<ReceivedMessage>
|
||||||
|
|
||||||
{
|
{
|
||||||
QReadLocker locker(&_hashLock);
|
QReadLocker locker(&_hashLock);
|
||||||
_pendingAvatars.remove(identityUUID);
|
|
||||||
auto me = _avatarHash.find(EMPTY);
|
auto me = _avatarHash.find(EMPTY);
|
||||||
if ((me != _avatarHash.end()) && (identityUUID == me.value()->getSessionUUID())) {
|
if ((me != _avatarHash.end()) && (identityUUID == me.value()->getSessionUUID())) {
|
||||||
// We add MyAvatar to _avatarHash with an empty UUID. Code relies on this. In order to correctly handle an
|
// We add MyAvatar to _avatarHash with an empty UUID. Code relies on this. In order to correctly handle an
|
||||||
|
@ -419,7 +417,6 @@ void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason remo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_pendingAvatars.remove(sessionUUID);
|
|
||||||
auto removedAvatar = _avatarHash.take(sessionUUID);
|
auto removedAvatar = _avatarHash.take(sessionUUID);
|
||||||
|
|
||||||
if (removedAvatar) {
|
if (removedAvatar) {
|
||||||
|
|
|
@ -161,6 +161,11 @@ protected slots:
|
||||||
*/
|
*/
|
||||||
void processAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
void processAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* @function AvatarList.processBulkAvatarTraits
|
||||||
|
* @param {} message
|
||||||
|
* @param {} sendingNode
|
||||||
|
*/
|
||||||
void processBulkAvatarTraits(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
void processBulkAvatarTraits(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
@ -183,15 +188,8 @@ protected:
|
||||||
|
|
||||||
virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason);
|
virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason);
|
||||||
|
|
||||||
AvatarHash _avatarHash;
|
|
||||||
struct PendingAvatar {
|
|
||||||
std::chrono::steady_clock::time_point creationTime;
|
|
||||||
int transmits;
|
|
||||||
AvatarSharedPointer avatar;
|
|
||||||
};
|
|
||||||
using AvatarPendingHash = QHash<QUuid, PendingAvatar>;
|
|
||||||
AvatarPendingHash _pendingAvatars;
|
|
||||||
mutable QReadWriteLock _hashLock;
|
mutable QReadWriteLock _hashLock;
|
||||||
|
AvatarHash _avatarHash;
|
||||||
|
|
||||||
std::unordered_map<QUuid, AvatarTraits::TraitVersions> _processedTraitVersions;
|
std::unordered_map<QUuid, AvatarTraits::TraitVersions> _processedTraitVersions;
|
||||||
AvatarReplicas _replicas;
|
AvatarReplicas _replicas;
|
||||||
|
|
|
@ -98,7 +98,7 @@ enum Hand {
|
||||||
class InputDevice {
|
class InputDevice {
|
||||||
public:
|
public:
|
||||||
InputDevice(const QString& name) : _name(name) {}
|
InputDevice(const QString& name) : _name(name) {}
|
||||||
virtual ~InputDevice() {}
|
virtual ~InputDevice() = default;
|
||||||
|
|
||||||
using Pointer = std::shared_ptr<InputDevice>;
|
using Pointer = std::shared_ptr<InputDevice>;
|
||||||
|
|
||||||
|
|
|
@ -41,10 +41,10 @@ namespace controller {
|
||||||
*/
|
*/
|
||||||
QScriptValue Pose::toScriptValue(QScriptEngine* engine, const Pose& pose) {
|
QScriptValue Pose::toScriptValue(QScriptEngine* engine, const Pose& pose) {
|
||||||
QScriptValue obj = engine->newObject();
|
QScriptValue obj = engine->newObject();
|
||||||
obj.setProperty("translation", vec3toScriptValue(engine, pose.translation));
|
obj.setProperty("translation", vec3ToScriptValue(engine, pose.translation));
|
||||||
obj.setProperty("rotation", quatToScriptValue(engine, pose.rotation));
|
obj.setProperty("rotation", quatToScriptValue(engine, pose.rotation));
|
||||||
obj.setProperty("velocity", vec3toScriptValue(engine, pose.velocity));
|
obj.setProperty("velocity", vec3ToScriptValue(engine, pose.velocity));
|
||||||
obj.setProperty("angularVelocity", vec3toScriptValue(engine, pose.angularVelocity));
|
obj.setProperty("angularVelocity", vec3ToScriptValue(engine, pose.angularVelocity));
|
||||||
obj.setProperty("valid", pose.valid);
|
obj.setProperty("valid", pose.valid);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ namespace controller {
|
||||||
using Factory = hifi::SimpleFactory<Conditional, QString>;
|
using Factory = hifi::SimpleFactory<Conditional, QString>;
|
||||||
using Lambda = std::function<bool()>;
|
using Lambda = std::function<bool()>;
|
||||||
|
|
||||||
|
virtual ~Conditional() = default;
|
||||||
|
|
||||||
virtual bool satisfied() = 0;
|
virtual bool satisfied() = 0;
|
||||||
virtual bool parseParameters(const QJsonValue& parameters) { return true; }
|
virtual bool parseParameters(const QJsonValue& parameters) { return true; }
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ namespace controller {
|
||||||
using Lambda = std::function<float(float)>;
|
using Lambda = std::function<float(float)>;
|
||||||
using Factory = hifi::SimpleFactory<Filter, QString>;
|
using Factory = hifi::SimpleFactory<Filter, QString>;
|
||||||
|
|
||||||
|
virtual ~Filter() = default;
|
||||||
|
|
||||||
virtual float apply(float value) const = 0;
|
virtual float apply(float value) const = 0;
|
||||||
virtual Pose apply(Pose value) const = 0;
|
virtual Pose apply(Pose value) const = 0;
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,6 @@ public:
|
||||||
AndConditional(Conditional::Pointer& first, Conditional::Pointer& second)
|
AndConditional(Conditional::Pointer& first, Conditional::Pointer& second)
|
||||||
: _children({ first, second }) {}
|
: _children({ first, second }) {}
|
||||||
|
|
||||||
virtual ~AndConditional() {}
|
|
||||||
|
|
||||||
virtual bool satisfied() override;
|
virtual bool satisfied() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -18,7 +18,6 @@ namespace controller {
|
||||||
class EndpointConditional : public Conditional {
|
class EndpointConditional : public Conditional {
|
||||||
public:
|
public:
|
||||||
EndpointConditional(Endpoint::Pointer endpoint) : _endpoint(endpoint) {}
|
EndpointConditional(Endpoint::Pointer endpoint) : _endpoint(endpoint) {}
|
||||||
virtual ~EndpointConditional() {}
|
|
||||||
virtual bool satisfied() override { return _endpoint && _endpoint->peek() != 0.0f; }
|
virtual bool satisfied() override { return _endpoint && _endpoint->peek() != 0.0f; }
|
||||||
private:
|
private:
|
||||||
Endpoint::Pointer _endpoint;
|
Endpoint::Pointer _endpoint;
|
||||||
|
|
|
@ -19,7 +19,6 @@ namespace controller {
|
||||||
using Pointer = std::shared_ptr<NotConditional>;
|
using Pointer = std::shared_ptr<NotConditional>;
|
||||||
|
|
||||||
NotConditional(Conditional::Pointer operand) : _operand(operand) { }
|
NotConditional(Conditional::Pointer operand) : _operand(operand) { }
|
||||||
virtual ~NotConditional() {}
|
|
||||||
|
|
||||||
virtual bool satisfied() override;
|
virtual bool satisfied() override;
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ class ClampFilter : public Filter {
|
||||||
REGISTER_FILTER_CLASS(ClampFilter);
|
REGISTER_FILTER_CLASS(ClampFilter);
|
||||||
public:
|
public:
|
||||||
ClampFilter(float min = 0.0, float max = 1.0) : _min(min), _max(max) {};
|
ClampFilter(float min = 0.0, float max = 1.0) : _min(min), _max(max) {};
|
||||||
virtual ~ClampFilter() {}
|
|
||||||
virtual float apply(float value) const override {
|
virtual float apply(float value) const override {
|
||||||
return glm::clamp(value, _min, _max);
|
return glm::clamp(value, _min, _max);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,13 @@ namespace controller {
|
||||||
class ConstrainToIntegerFilter : public Filter {
|
class ConstrainToIntegerFilter : public Filter {
|
||||||
REGISTER_FILTER_CLASS(ConstrainToIntegerFilter);
|
REGISTER_FILTER_CLASS(ConstrainToIntegerFilter);
|
||||||
public:
|
public:
|
||||||
ConstrainToIntegerFilter() {};
|
ConstrainToIntegerFilter() = default;
|
||||||
virtual ~ConstrainToIntegerFilter() {}
|
|
||||||
|
|
||||||
virtual float apply(float value) const override {
|
virtual float apply(float value) const override {
|
||||||
return glm::sign(value);
|
return glm::sign(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Pose apply(Pose value) const override { return value; }
|
virtual Pose apply(Pose value) const override { return value; }
|
||||||
|
|
||||||
protected:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,13 @@ namespace controller {
|
||||||
class ConstrainToPositiveIntegerFilter : public Filter {
|
class ConstrainToPositiveIntegerFilter : public Filter {
|
||||||
REGISTER_FILTER_CLASS(ConstrainToPositiveIntegerFilter);
|
REGISTER_FILTER_CLASS(ConstrainToPositiveIntegerFilter);
|
||||||
public:
|
public:
|
||||||
ConstrainToPositiveIntegerFilter() {};
|
ConstrainToPositiveIntegerFilter() = default;
|
||||||
virtual ~ConstrainToPositiveIntegerFilter() {};
|
|
||||||
|
|
||||||
virtual float apply(float value) const override {
|
virtual float apply(float value) const override {
|
||||||
return (value <= 0.0f) ? 0.0f : 1.0f;
|
return (value <= 0.0f) ? 0.0f : 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Pose apply(Pose value) const override { return value; }
|
virtual Pose apply(Pose value) const override { return value; }
|
||||||
|
|
||||||
protected:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ class DeadZoneFilter : public Filter {
|
||||||
REGISTER_FILTER_CLASS(DeadZoneFilter);
|
REGISTER_FILTER_CLASS(DeadZoneFilter);
|
||||||
public:
|
public:
|
||||||
DeadZoneFilter(float min = 0.0) : _min(min) {};
|
DeadZoneFilter(float min = 0.0) : _min(min) {};
|
||||||
virtual ~DeadZoneFilter() {}
|
|
||||||
|
|
||||||
virtual float apply(float value) const override;
|
virtual float apply(float value) const override;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ namespace controller {
|
||||||
ExponentialSmoothingFilter() {}
|
ExponentialSmoothingFilter() {}
|
||||||
ExponentialSmoothingFilter(float rotationConstant, float translationConstant) :
|
ExponentialSmoothingFilter(float rotationConstant, float translationConstant) :
|
||||||
_translationConstant(translationConstant), _rotationConstant(rotationConstant) {}
|
_translationConstant(translationConstant), _rotationConstant(rotationConstant) {}
|
||||||
virtual ~ExponentialSmoothingFilter() {}
|
|
||||||
|
|
||||||
float apply(float value) const override { return value; }
|
float apply(float value) const override { return value; }
|
||||||
Pose apply(Pose value) const override;
|
Pose apply(Pose value) const override;
|
||||||
|
|
|
@ -18,7 +18,6 @@ class HysteresisFilter : public Filter {
|
||||||
REGISTER_FILTER_CLASS(HysteresisFilter);
|
REGISTER_FILTER_CLASS(HysteresisFilter);
|
||||||
public:
|
public:
|
||||||
HysteresisFilter(float min = 0.25, float max = 0.75);
|
HysteresisFilter(float min = 0.25, float max = 0.75);
|
||||||
virtual ~HysteresisFilter() {}
|
|
||||||
virtual float apply(float value) const override;
|
virtual float apply(float value) const override;
|
||||||
|
|
||||||
virtual Pose apply(Pose value) const override { return value; }
|
virtual Pose apply(Pose value) const override { return value; }
|
||||||
|
|
|
@ -19,11 +19,8 @@ class InvertFilter : public ScaleFilter {
|
||||||
public:
|
public:
|
||||||
using ScaleFilter::parseParameters;
|
using ScaleFilter::parseParameters;
|
||||||
InvertFilter() : ScaleFilter(-1.0f) {}
|
InvertFilter() : ScaleFilter(-1.0f) {}
|
||||||
virtual ~InvertFilter() {}
|
|
||||||
|
|
||||||
virtual bool parseParameters(const QJsonArray& parameters) { return true; }
|
virtual bool parseParameters(const QJsonArray& parameters) { return true; }
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,9 @@ namespace controller {
|
||||||
REGISTER_FILTER_CLASS(LowVelocityFilter);
|
REGISTER_FILTER_CLASS(LowVelocityFilter);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LowVelocityFilter() {}
|
LowVelocityFilter() = default;
|
||||||
LowVelocityFilter(float rotationConstant, float translationConstant) :
|
LowVelocityFilter(float rotationConstant, float translationConstant) :
|
||||||
_translationConstant(translationConstant), _rotationConstant(rotationConstant) {}
|
_translationConstant(translationConstant), _rotationConstant(rotationConstant) {}
|
||||||
virtual ~LowVelocityFilter() {}
|
|
||||||
|
|
||||||
float apply(float value) const override { return value; }
|
float apply(float value) const override { return value; }
|
||||||
Pose apply(Pose newPose) const override;
|
Pose apply(Pose newPose) const override;
|
||||||
|
|
|
@ -10,7 +10,6 @@ class NotFilter : public Filter {
|
||||||
REGISTER_FILTER_CLASS(NotFilter);
|
REGISTER_FILTER_CLASS(NotFilter);
|
||||||
public:
|
public:
|
||||||
NotFilter();
|
NotFilter();
|
||||||
virtual ~NotFilter() {}
|
|
||||||
|
|
||||||
virtual float apply(float value) const override;
|
virtual float apply(float value) const override;
|
||||||
virtual Pose apply(Pose value) const override { return value; }
|
virtual Pose apply(Pose value) const override { return value; }
|
||||||
|
|
|
@ -19,9 +19,8 @@ namespace controller {
|
||||||
class PostTransformFilter : public Filter {
|
class PostTransformFilter : public Filter {
|
||||||
REGISTER_FILTER_CLASS(PostTransformFilter);
|
REGISTER_FILTER_CLASS(PostTransformFilter);
|
||||||
public:
|
public:
|
||||||
PostTransformFilter() { }
|
PostTransformFilter() = default;
|
||||||
PostTransformFilter(glm::mat4 transform) : _transform(transform) {}
|
PostTransformFilter(glm::mat4 transform) : _transform(transform) {}
|
||||||
virtual ~PostTransformFilter() {}
|
|
||||||
virtual float apply(float value) const override { return value; }
|
virtual float apply(float value) const override { return value; }
|
||||||
virtual Pose apply(Pose value) const override { return value.postTransform(_transform); }
|
virtual Pose apply(Pose value) const override { return value.postTransform(_transform); }
|
||||||
virtual bool parseParameters(const QJsonValue& parameters) override { return parseMat4Parameter(parameters, _transform); }
|
virtual bool parseParameters(const QJsonValue& parameters) override { return parseMat4Parameter(parameters, _transform); }
|
||||||
|
|
|
@ -18,9 +18,8 @@ namespace controller {
|
||||||
class PulseFilter : public Filter {
|
class PulseFilter : public Filter {
|
||||||
REGISTER_FILTER_CLASS(PulseFilter);
|
REGISTER_FILTER_CLASS(PulseFilter);
|
||||||
public:
|
public:
|
||||||
PulseFilter() {}
|
PulseFilter() = default;
|
||||||
PulseFilter(float interval) : _interval(interval) {}
|
PulseFilter(float interval) : _interval(interval) {}
|
||||||
virtual ~PulseFilter() {}
|
|
||||||
|
|
||||||
virtual float apply(float value) const override;
|
virtual float apply(float value) const override;
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,8 @@ namespace controller {
|
||||||
class RotateFilter : public Filter {
|
class RotateFilter : public Filter {
|
||||||
REGISTER_FILTER_CLASS(RotateFilter);
|
REGISTER_FILTER_CLASS(RotateFilter);
|
||||||
public:
|
public:
|
||||||
RotateFilter() { }
|
RotateFilter() = default;
|
||||||
RotateFilter(glm::quat rotation) : _rotation(rotation) {}
|
RotateFilter(glm::quat rotation) : _rotation(rotation) {}
|
||||||
virtual ~RotateFilter() {}
|
|
||||||
|
|
||||||
virtual float apply(float value) const override { return value; }
|
virtual float apply(float value) const override { return value; }
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,8 @@ namespace controller {
|
||||||
class ScaleFilter : public Filter {
|
class ScaleFilter : public Filter {
|
||||||
REGISTER_FILTER_CLASS(ScaleFilter);
|
REGISTER_FILTER_CLASS(ScaleFilter);
|
||||||
public:
|
public:
|
||||||
ScaleFilter() {}
|
ScaleFilter() = default;
|
||||||
ScaleFilter(float scale) : _scale(scale) {}
|
ScaleFilter(float scale) : _scale(scale) {}
|
||||||
virtual ~ScaleFilter() {}
|
|
||||||
|
|
||||||
virtual float apply(float value) const override {
|
virtual float apply(float value) const override {
|
||||||
return value * _scale;
|
return value * _scale;
|
||||||
|
|
|
@ -19,9 +19,8 @@ namespace controller {
|
||||||
class TransformFilter : public Filter {
|
class TransformFilter : public Filter {
|
||||||
REGISTER_FILTER_CLASS(TransformFilter);
|
REGISTER_FILTER_CLASS(TransformFilter);
|
||||||
public:
|
public:
|
||||||
TransformFilter() { }
|
TransformFilter() = default;
|
||||||
TransformFilter(glm::mat4 transform) : _transform(transform) {}
|
TransformFilter(glm::mat4 transform) : _transform(transform) {}
|
||||||
virtual ~TransformFilter() {}
|
|
||||||
|
|
||||||
virtual float apply(float value) const override { return value; }
|
virtual float apply(float value) const override { return value; }
|
||||||
virtual Pose apply(Pose value) const override { return value.transform(_transform); }
|
virtual Pose apply(Pose value) const override { return value.transform(_transform); }
|
||||||
|
|
|
@ -19,9 +19,8 @@ namespace controller {
|
||||||
class TranslateFilter : public Filter {
|
class TranslateFilter : public Filter {
|
||||||
REGISTER_FILTER_CLASS(TranslateFilter);
|
REGISTER_FILTER_CLASS(TranslateFilter);
|
||||||
public:
|
public:
|
||||||
TranslateFilter() { }
|
TranslateFilter() = default;
|
||||||
TranslateFilter(glm::vec3 translate) : _translate(translate) {}
|
TranslateFilter(glm::vec3 translate) : _translate(translate) {}
|
||||||
virtual ~TranslateFilter() {}
|
|
||||||
|
|
||||||
virtual float apply(float value) const override { return value; }
|
virtual float apply(float value) const override { return value; }
|
||||||
virtual Pose apply(Pose value) const override { return value.transform(glm::translate(_translate)); }
|
virtual Pose apply(Pose value) const override { return value.transform(glm::translate(_translate)); }
|
||||||
|
|
|
@ -494,7 +494,7 @@ glm::mat4 CompositorHelper::getPoint2DTransform(const glm::vec2& point, float si
|
||||||
|
|
||||||
|
|
||||||
QVariant ReticleInterface::getPosition() const {
|
QVariant ReticleInterface::getPosition() const {
|
||||||
return vec2toVariant(_compositor->getReticlePosition());
|
return vec2ToVariant(_compositor->getReticlePosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReticleInterface::setPosition(QVariant position) {
|
void ReticleInterface::setPosition(QVariant position) {
|
||||||
|
|
|
@ -41,7 +41,7 @@ void LightEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
||||||
float largestDiameter = glm::compMax(dimensions);
|
float largestDiameter = glm::compMax(dimensions);
|
||||||
light->setMaximumRadius(largestDiameter / 2.0f);
|
light->setMaximumRadius(largestDiameter / 2.0f);
|
||||||
|
|
||||||
light->setColor(toGlm(entity->getXColor()));
|
light->setColor(toGlm(entity->getColor()));
|
||||||
|
|
||||||
float intensity = entity->getIntensity();//* entity->getFadingRatio();
|
float intensity = entity->getIntensity();//* entity->getFadingRatio();
|
||||||
light->setIntensity(intensity);
|
light->setIntensity(intensity);
|
||||||
|
|
|
@ -37,7 +37,7 @@ void LineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
|
||||||
if (_lineVerticesID == GeometryCache::UNKNOWN_ID) {
|
if (_lineVerticesID == GeometryCache::UNKNOWN_ID) {
|
||||||
_lineVerticesID = geometryCache->allocateID();
|
_lineVerticesID = geometryCache->allocateID();
|
||||||
}
|
}
|
||||||
glm::vec4 lineColor(toGlm(entity->getXColor()), entity->getLocalRenderAlpha());
|
glm::vec4 lineColor(toGlm(entity->getColor()), entity->getLocalRenderAlpha());
|
||||||
geometryCache->updateVertices(_lineVerticesID, _linePoints, lineColor);
|
geometryCache->updateVertices(_lineVerticesID, _linePoints, lineColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,18 @@ bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityP
|
||||||
if (entity->getMaterialMappingPos() != _materialMappingPos || entity->getMaterialMappingScale() != _materialMappingScale || entity->getMaterialMappingRot() != _materialMappingRot) {
|
if (entity->getMaterialMappingPos() != _materialMappingPos || entity->getMaterialMappingScale() != _materialMappingScale || entity->getMaterialMappingRot() != _materialMappingRot) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!_texturesLoaded) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
_drawMaterial = entity->getMaterial();
|
if (_drawMaterial != entity->getMaterial()) {
|
||||||
|
_texturesLoaded = false;
|
||||||
|
_drawMaterial = entity->getMaterial();
|
||||||
|
}
|
||||||
_parentID = entity->getParentID();
|
_parentID = entity->getParentID();
|
||||||
_materialMappingPos = entity->getMaterialMappingPos();
|
_materialMappingPos = entity->getMaterialMappingPos();
|
||||||
_materialMappingScale = entity->getMaterialMappingScale();
|
_materialMappingScale = entity->getMaterialMappingScale();
|
||||||
|
@ -38,6 +44,12 @@ void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer&
|
||||||
const float MATERIAL_ENTITY_SCALE = 0.5f;
|
const float MATERIAL_ENTITY_SCALE = 0.5f;
|
||||||
_renderTransform.postScale(MATERIAL_ENTITY_SCALE);
|
_renderTransform.postScale(MATERIAL_ENTITY_SCALE);
|
||||||
_renderTransform.postScale(ENTITY_ITEM_DEFAULT_DIMENSIONS);
|
_renderTransform.postScale(ENTITY_ITEM_DEFAULT_DIMENSIONS);
|
||||||
|
|
||||||
|
bool newTexturesLoaded = _drawMaterial ? !_drawMaterial->isMissingTexture() : false;
|
||||||
|
if (!_texturesLoaded && newTexturesLoaded) {
|
||||||
|
_drawMaterial->checkResetOpacityMap();
|
||||||
|
}
|
||||||
|
_texturesLoaded = newTexturesLoaded;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ private:
|
||||||
glm::vec2 _materialMappingPos;
|
glm::vec2 _materialMappingPos;
|
||||||
glm::vec2 _materialMappingScale;
|
glm::vec2 _materialMappingScale;
|
||||||
float _materialMappingRot;
|
float _materialMappingRot;
|
||||||
|
bool _texturesLoaded { false };
|
||||||
|
|
||||||
std::shared_ptr<NetworkMaterial> _drawMaterial;
|
std::shared_ptr<NetworkMaterial> _drawMaterial;
|
||||||
};
|
};
|
||||||
|
|
|
@ -975,14 +975,21 @@ QStringList RenderableModelEntityItem::getJointNames() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: deprecated; remove >= RC67
|
void RenderableModelEntityItem::setAnimationURL(const QString& url) {
|
||||||
bool RenderableModelEntityItem::getMeshes(MeshProxyList& result) {
|
QString oldURL = getAnimationURL();
|
||||||
auto model = getModel();
|
ModelEntityItem::setAnimationURL(url);
|
||||||
if (!model || !model->isLoaded()) {
|
if (oldURL != getAnimationURL()) {
|
||||||
return false;
|
_needsAnimationReset = true;
|
||||||
}
|
}
|
||||||
BLOCKING_INVOKE_METHOD(model.get(), "getMeshes", Q_RETURN_ARG(MeshProxyList, result));
|
}
|
||||||
return !result.isEmpty();
|
|
||||||
|
bool RenderableModelEntityItem::needsAnimationReset() const {
|
||||||
|
return _needsAnimationReset;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RenderableModelEntityItem::getAnimationURLAndReset() {
|
||||||
|
_needsAnimationReset = false;
|
||||||
|
return getAnimationURL();
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScriptableModel() {
|
scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScriptableModel() {
|
||||||
|
@ -1068,6 +1075,13 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RenderableModelEntityItem::readyToAnimate() const {
|
||||||
|
return resultWithReadLock<bool>([&] {
|
||||||
|
float firstFrame = _animationProperties.getFirstFrame();
|
||||||
|
return (firstFrame >= 0.0f) && (firstFrame <= _animationProperties.getLastFrame());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
using namespace render;
|
using namespace render;
|
||||||
using namespace render::entities;
|
using namespace render::entities;
|
||||||
|
|
||||||
|
@ -1155,7 +1169,7 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
||||||
|
|
||||||
const QVector<glm::quat>& rotations = frames[_lastKnownCurrentFrame].rotations;
|
const QVector<glm::quat>& rotations = frames[_lastKnownCurrentFrame].rotations;
|
||||||
const QVector<glm::vec3>& translations = frames[_lastKnownCurrentFrame].translations;
|
const QVector<glm::vec3>& translations = frames[_lastKnownCurrentFrame].translations;
|
||||||
|
|
||||||
jointsData.resize(_jointMapping.size());
|
jointsData.resize(_jointMapping.size());
|
||||||
for (int j = 0; j < _jointMapping.size(); j++) {
|
for (int j = 0; j < _jointMapping.size(); j++) {
|
||||||
int index = _jointMapping[j];
|
int index = _jointMapping[j];
|
||||||
|
@ -1169,13 +1183,12 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
||||||
}
|
}
|
||||||
} else if (index < animationJointNames.size()) {
|
} else if (index < animationJointNames.size()) {
|
||||||
QString jointName = fbxJoints[index].name; // Pushing this here so its not done on every entity, with the exceptions of those allowing for translation
|
QString jointName = fbxJoints[index].name; // Pushing this here so its not done on every entity, with the exceptions of those allowing for translation
|
||||||
|
|
||||||
if (originalFbxIndices.contains(jointName)) {
|
if (originalFbxIndices.contains(jointName)) {
|
||||||
// Making sure the joint names exist in the original model the animation is trying to apply onto. If they do, then remap and get it's translation.
|
// Making sure the joint names exist in the original model the animation is trying to apply onto. If they do, then remap and get it's translation.
|
||||||
int remappedIndex = originalFbxIndices[jointName] - 1; // JointIndeces seem to always start from 1 and the found index is always 1 higher than actual.
|
int remappedIndex = originalFbxIndices[jointName] - 1; // JointIndeces seem to always start from 1 and the found index is always 1 higher than actual.
|
||||||
translationMat = glm::translate(originalFbxJoints[remappedIndex].translation);
|
translationMat = glm::translate(originalFbxJoints[remappedIndex].translation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glm::mat4 rotationMat;
|
glm::mat4 rotationMat;
|
||||||
if (index < rotations.size()) {
|
if (index < rotations.size()) {
|
||||||
rotationMat = glm::mat4_cast(fbxJoints[index].preRotation * rotations[index] * fbxJoints[index].postRotation);
|
rotationMat = glm::mat4_cast(fbxJoints[index].preRotation * rotations[index] * fbxJoints[index].postRotation);
|
||||||
|
@ -1477,14 +1490,17 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
if (_animating) {
|
if (_animating) {
|
||||||
DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
|
DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
|
||||||
|
|
||||||
if (!jointsMapped()) {
|
if (_animation && entity->needsAnimationReset()) {
|
||||||
mapJoints(entity, model->getJointNames());
|
//(_animation->getURL().toString() != entity->getAnimationURL())) { // bad check
|
||||||
//else the joint have been mapped before but we have a new animation to load
|
// the joints have been mapped before but we have a new animation to load
|
||||||
} else if (_animation && (_animation->getURL().toString() != entity->getAnimationURL())) {
|
_animation.reset();
|
||||||
_jointMappingCompleted = false;
|
_jointMappingCompleted = false;
|
||||||
mapJoints(entity, model->getJointNames());
|
|
||||||
}
|
}
|
||||||
if (!(entity->getAnimationFirstFrame() < 0) && !(entity->getAnimationFirstFrame() > entity->getAnimationLastFrame())) {
|
|
||||||
|
if (!_jointMappingCompleted) {
|
||||||
|
mapJoints(entity, model);
|
||||||
|
}
|
||||||
|
if (entity->readyToAnimate()) {
|
||||||
animate(entity);
|
animate(entity);
|
||||||
}
|
}
|
||||||
emit requestRenderUpdate();
|
emit requestRenderUpdate();
|
||||||
|
@ -1518,19 +1534,20 @@ void ModelEntityRenderer::doRender(RenderArgs* args) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityRenderer::mapJoints(const TypedEntityPointer& entity, const QStringList& modelJointNames) {
|
void ModelEntityRenderer::mapJoints(const TypedEntityPointer& entity, const ModelPointer& model) {
|
||||||
// if we don't have animation, or we're already joint mapped then bail early
|
// if we don't have animation, or we're already joint mapped then bail early
|
||||||
if (!entity->hasAnimation() || jointsMapped()) {
|
if (!entity->hasAnimation()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_animation || _animation->getURL().toString() != entity->getAnimationURL()) {
|
if (!_animation) {
|
||||||
_animation = DependencyManager::get<AnimationCache>()->getAnimation(entity->getAnimationURL());
|
_animation = DependencyManager::get<AnimationCache>()->getAnimation(entity->getAnimationURLAndReset());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_animation && _animation->isLoaded()) {
|
if (_animation && _animation->isLoaded()) {
|
||||||
QStringList animationJointNames = _animation->getJointNames();
|
QStringList animationJointNames = _animation->getJointNames();
|
||||||
|
|
||||||
|
auto modelJointNames = model->getJointNames();
|
||||||
if (modelJointNames.size() > 0 && animationJointNames.size() > 0) {
|
if (modelJointNames.size() > 0 && animationJointNames.size() > 0) {
|
||||||
_jointMapping.resize(modelJointNames.size());
|
_jointMapping.resize(modelJointNames.size());
|
||||||
for (int i = 0; i < modelJointNames.size(); i++) {
|
for (int i = 0; i < modelJointNames.size(); i++) {
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
|
|
||||||
#include "RenderableEntityItem.h"
|
#include "RenderableEntityItem.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Model;
|
class Model;
|
||||||
class EntityTreeRenderer;
|
class EntityTreeRenderer;
|
||||||
|
|
||||||
|
@ -114,21 +112,25 @@ public:
|
||||||
virtual int getJointIndex(const QString& name) const override;
|
virtual int getJointIndex(const QString& name) const override;
|
||||||
virtual QStringList getJointNames() const override;
|
virtual QStringList getJointNames() const override;
|
||||||
|
|
||||||
bool getMeshes(MeshProxyList& result) override; // deprecated
|
void setAnimationURL(const QString& url) override;
|
||||||
|
bool needsAnimationReset() const;
|
||||||
|
QString getAnimationURLAndReset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool needsUpdateModelBounds() const;
|
bool needsUpdateModelBounds() const;
|
||||||
void autoResizeJointArrays();
|
void autoResizeJointArrays();
|
||||||
void copyAnimationJointDataToModel();
|
void copyAnimationJointDataToModel();
|
||||||
|
bool readyToAnimate() const;
|
||||||
void getCollisionGeometryResource();
|
void getCollisionGeometryResource();
|
||||||
|
|
||||||
GeometryResource::Pointer _compoundShapeResource;
|
GeometryResource::Pointer _compoundShapeResource;
|
||||||
bool _jointMapCompleted { false };
|
|
||||||
bool _originalTexturesRead { false };
|
|
||||||
std::vector<int> _jointMap;
|
std::vector<int> _jointMap;
|
||||||
QVariantMap _originalTextures;
|
QVariantMap _originalTextures;
|
||||||
|
bool _jointMapCompleted { false };
|
||||||
|
bool _originalTexturesRead { false };
|
||||||
bool _dimensionsInitialized { true };
|
bool _dimensionsInitialized { true };
|
||||||
bool _needsJointSimulation { false };
|
bool _needsJointSimulation { false };
|
||||||
|
bool _needsAnimationReset { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace render { namespace entities {
|
namespace render { namespace entities {
|
||||||
|
@ -169,8 +171,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void animate(const TypedEntityPointer& entity);
|
void animate(const TypedEntityPointer& entity);
|
||||||
void mapJoints(const TypedEntityPointer& entity, const QStringList& modelJointNames);
|
void mapJoints(const TypedEntityPointer& entity, const ModelPointer& model);
|
||||||
bool jointsMapped() const { return _jointMappingCompleted; }
|
|
||||||
|
|
||||||
// Transparency is handled in ModelMeshPartPayload
|
// Transparency is handled in ModelMeshPartPayload
|
||||||
virtual bool isTransparent() const override { return false; }
|
virtual bool isTransparent() const override { return false; }
|
||||||
|
|
|
@ -142,7 +142,7 @@ void PolyLineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo
|
||||||
}
|
}
|
||||||
if (strokeColorsChanged) {
|
if (strokeColorsChanged) {
|
||||||
_lastStrokeColors = entity->getStrokeColors();
|
_lastStrokeColors = entity->getStrokeColors();
|
||||||
_lastStrokeColors = _lastNormals.size() == _lastStrokeColors.size() ? _lastStrokeColors : QVector<glm::vec3>({ toGlm(entity->getXColor()) });
|
_lastStrokeColors = _lastNormals.size() == _lastStrokeColors.size() ? _lastStrokeColors : QVector<glm::vec3>({ toGlm(entity->getColor()) });
|
||||||
}
|
}
|
||||||
if (pointsChanged || strokeWidthsChanged || normalsChanged || strokeColorsChanged) {
|
if (pointsChanged || strokeWidthsChanged || normalsChanged || strokeColorsChanged) {
|
||||||
_empty = std::min(_lastPoints.size(), std::min(_lastNormals.size(), _lastStrokeWidths.size())) < 2;
|
_empty = std::min(_lastPoints.size(), std::min(_lastNormals.size(), _lastStrokeWidths.size())) < 2;
|
||||||
|
@ -161,10 +161,10 @@ void PolyLineEntityRenderer::updateGeometry(const std::vector<Vertex>& vertices)
|
||||||
_verticesBuffer->setSubData(0, vertices);
|
_verticesBuffer->setSubData(0, vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<PolyLineEntityRenderer::Vertex> PolyLineEntityRenderer::updateVertices(const QVector<glm::vec3>& points,
|
std::vector<PolyLineEntityRenderer::Vertex> PolyLineEntityRenderer::updateVertices(const QVector<glm::vec3>& points,
|
||||||
const QVector<glm::vec3>& normals,
|
const QVector<glm::vec3>& normals,
|
||||||
const QVector<float>& strokeWidths,
|
const QVector<float>& strokeWidths,
|
||||||
const QVector<glm::vec3>& strokeColors,
|
const QVector<glm::vec3>& strokeColors,
|
||||||
const bool isUVModeStretch,
|
const bool isUVModeStretch,
|
||||||
const float textureAspectRatio) {
|
const float textureAspectRatio) {
|
||||||
// Calculate the minimum vector size out of normals, points, and stroke widths
|
// Calculate the minimum vector size out of normals, points, and stroke widths
|
||||||
|
|
|
@ -52,10 +52,10 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
void updateGeometry(const std::vector<Vertex>& vertices);
|
void updateGeometry(const std::vector<Vertex>& vertices);
|
||||||
static std::vector<Vertex> updateVertices(const QVector<glm::vec3>& points,
|
static std::vector<Vertex> updateVertices(const QVector<glm::vec3>& points,
|
||||||
const QVector<glm::vec3>& normals,
|
const QVector<glm::vec3>& normals,
|
||||||
const QVector<float>& strokeWidths,
|
const QVector<float>& strokeWidths,
|
||||||
const QVector<glm::vec3>& strokeColors,
|
const QVector<glm::vec3>& strokeColors,
|
||||||
const bool isUVModeStretch,
|
const bool isUVModeStretch,
|
||||||
const float textureAspectRatio);
|
const float textureAspectRatio);
|
||||||
|
|
||||||
|
|
|
@ -47,11 +47,11 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_textColor != toGlm(entity->getTextColorX())) {
|
if (_textColor != toGlm(entity->getTextColor())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_backgroundColor != toGlm(entity->getBackgroundColorX())) {
|
if (_backgroundColor != toGlm(entity->getBackgroundColor())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,8 +77,8 @@ void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||||
_textColor = toGlm(entity->getTextColorX());
|
_textColor = toGlm(entity->getTextColor());
|
||||||
_backgroundColor = toGlm(entity->getBackgroundColorX());
|
_backgroundColor = toGlm(entity->getBackgroundColor());
|
||||||
_faceCamera = entity->getFaceCamera();
|
_faceCamera = entity->getFaceCamera();
|
||||||
_lineHeight = entity->getLineHeight();
|
_lineHeight = entity->getLineHeight();
|
||||||
_text = entity->getText();
|
_text = entity->getText();
|
||||||
|
|
|
@ -413,10 +413,10 @@ void ZoneEntityRenderer::updateHazeFromEntity(const TypedEntityPointer& entity)
|
||||||
haze->setAltitudeBased(_hazeProperties.getHazeAltitudeEffect());
|
haze->setAltitudeBased(_hazeProperties.getHazeAltitudeEffect());
|
||||||
|
|
||||||
haze->setHazeRangeFactor(graphics::Haze::convertHazeRangeToHazeRangeFactor(_hazeProperties.getHazeRange()));
|
haze->setHazeRangeFactor(graphics::Haze::convertHazeRangeToHazeRangeFactor(_hazeProperties.getHazeRange()));
|
||||||
xColor hazeColor = _hazeProperties.getHazeColor();
|
glm::u8vec3 hazeColor = _hazeProperties.getHazeColor();
|
||||||
haze->setHazeColor(glm::vec3(hazeColor.red / 255.0, hazeColor.green / 255.0, hazeColor.blue / 255.0));
|
haze->setHazeColor(toGlm(hazeColor));
|
||||||
xColor hazeGlareColor = _hazeProperties.getHazeGlareColor();
|
glm::u8vec3 hazeGlareColor = _hazeProperties.getHazeGlareColor();
|
||||||
haze->setHazeGlareColor(glm::vec3(hazeGlareColor.red / 255.0, hazeGlareColor.green / 255.0, hazeGlareColor.blue / 255.0));
|
haze->setHazeGlareColor(toGlm(hazeGlareColor));
|
||||||
haze->setHazeEnableGlare(_hazeProperties.getHazeEnableGlare());
|
haze->setHazeEnableGlare(_hazeProperties.getHazeEnableGlare());
|
||||||
haze->setHazeGlareBlend(graphics::Haze::convertGlareAngleToPower(_hazeProperties.getHazeGlareAngle()));
|
haze->setHazeGlareBlend(graphics::Haze::convertGlareAngleToPower(_hazeProperties.getHazeGlareAngle()));
|
||||||
|
|
||||||
|
@ -447,7 +447,7 @@ void ZoneEntityRenderer::updateKeyBackgroundFromEntity(const TypedEntityPointer&
|
||||||
setSkyboxMode((ComponentMode)entity->getSkyboxMode());
|
setSkyboxMode((ComponentMode)entity->getSkyboxMode());
|
||||||
|
|
||||||
editBackground();
|
editBackground();
|
||||||
setSkyboxColor(_skyboxProperties.getColorVec3());
|
setSkyboxColor(toGlm(_skyboxProperties.getColor()));
|
||||||
setProceduralUserData(entity->getUserData());
|
setProceduralUserData(entity->getUserData());
|
||||||
setSkyboxURL(_skyboxProperties.getURL());
|
setSkyboxURL(_skyboxProperties.getURL());
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,10 +104,10 @@ bool EntityEditFilters::filter(glm::vec3& position, EntityItemProperties& proper
|
||||||
AABox aaBox = zoneEntity->getAABox(success);
|
AABox aaBox = zoneEntity->getAABox(success);
|
||||||
if (success) {
|
if (success) {
|
||||||
QScriptValue boundingBox = filterData.engine->newObject();
|
QScriptValue boundingBox = filterData.engine->newObject();
|
||||||
QScriptValue bottomRightNear = vec3toScriptValue(filterData.engine, aaBox.getCorner());
|
QScriptValue bottomRightNear = vec3ToScriptValue(filterData.engine, aaBox.getCorner());
|
||||||
QScriptValue topFarLeft = vec3toScriptValue(filterData.engine, aaBox.calcTopFarLeft());
|
QScriptValue topFarLeft = vec3ToScriptValue(filterData.engine, aaBox.calcTopFarLeft());
|
||||||
QScriptValue center = vec3toScriptValue(filterData.engine, aaBox.calcCenter());
|
QScriptValue center = vec3ToScriptValue(filterData.engine, aaBox.calcCenter());
|
||||||
QScriptValue boundingBoxDimensions = vec3toScriptValue(filterData.engine, aaBox.getDimensions());
|
QScriptValue boundingBoxDimensions = vec3ToScriptValue(filterData.engine, aaBox.getDimensions());
|
||||||
boundingBox.setProperty("brn", bottomRightNear);
|
boundingBox.setProperty("brn", bottomRightNear);
|
||||||
boundingBox.setProperty("tfl", topFarLeft);
|
boundingBox.setProperty("tfl", topFarLeft);
|
||||||
boundingBox.setProperty("center", center);
|
boundingBox.setProperty("center", center);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue