mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 07:37:20 +02:00
Merge pull request #6309 from thoys/20724
CR for Job #20724 - Camera entity mode
This commit is contained in:
commit
a1e10a9f04
9 changed files with 130 additions and 5 deletions
|
@ -1617,6 +1617,11 @@ PropertiesTool = function(opts) {
|
||||||
pushCommandForSelections();
|
pushCommandForSelections();
|
||||||
selectionManager._update();
|
selectionManager._update();
|
||||||
}
|
}
|
||||||
|
} else if (data.action == "previewCamera") {
|
||||||
|
if (selectionManager.hasSelection()) {
|
||||||
|
Camera.mode = "entity";
|
||||||
|
Camera.cameraEntity = selectionManager.selections[0];
|
||||||
|
}
|
||||||
} else if (data.action == "rescaleDimensions") {
|
} else if (data.action == "rescaleDimensions") {
|
||||||
var multiplier = data.percentage / 100;
|
var multiplier = data.percentage / 100;
|
||||||
if (selectionManager.hasSelection()) {
|
if (selectionManager.hasSelection()) {
|
||||||
|
|
57
examples/example/securityCamera.js
Normal file
57
examples/example/securityCamera.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
//
|
||||||
|
// securityCamera.js
|
||||||
|
// examples/example
|
||||||
|
//
|
||||||
|
// Created by Thijs Wenker on November 4, 2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
const CAMERA_OFFSET = {x: 0, y: 4, z: -14};
|
||||||
|
const LOOKAT_START_OFFSET = {x: -10, y: 0, z: 14};
|
||||||
|
const LOOKAT_END_OFFSET = {x: 10, y: 0, z: 14};
|
||||||
|
const TINY_VALUE = 0.001;
|
||||||
|
|
||||||
|
var lookatTargets = [Vec3.sum(MyAvatar.position, LOOKAT_START_OFFSET), Vec3.sum(MyAvatar.position, LOOKAT_END_OFFSET)];
|
||||||
|
var currentTarget = 0;
|
||||||
|
|
||||||
|
var forward = true;
|
||||||
|
|
||||||
|
var oldCameraMode = Camera.mode;
|
||||||
|
|
||||||
|
var cameraLookAt = function(cameraPos, lookAtPos) {
|
||||||
|
var lookAtRaw = Quat.lookAt(cameraPos, lookAtPos, Vec3.UP);
|
||||||
|
lookAtRaw.w = -lookAtRaw.w;
|
||||||
|
return lookAtRaw;
|
||||||
|
};
|
||||||
|
|
||||||
|
cameraEntity = Entities.addEntity({
|
||||||
|
type: "Box",
|
||||||
|
visible: false,
|
||||||
|
position: Vec3.sum(MyAvatar.position, CAMERA_OFFSET)
|
||||||
|
});
|
||||||
|
|
||||||
|
Camera.mode = "entity";
|
||||||
|
Camera.cameraEntity = cameraEntity;
|
||||||
|
|
||||||
|
Script.update.connect(function(deltaTime) {
|
||||||
|
var cameraProperties = Entities.getEntityProperties(cameraEntity, ["position", "rotation"]);
|
||||||
|
var targetOrientation = cameraLookAt(cameraProperties.position, lookatTargets[currentTarget]);
|
||||||
|
if (Math.abs(targetOrientation.x - cameraProperties.rotation.x) < TINY_VALUE &&
|
||||||
|
Math.abs(targetOrientation.y - cameraProperties.rotation.y) < TINY_VALUE &&
|
||||||
|
Math.abs(targetOrientation.z - cameraProperties.rotation.z) < TINY_VALUE &&
|
||||||
|
Math.abs(targetOrientation.w - cameraProperties.rotation.w) < TINY_VALUE) {
|
||||||
|
|
||||||
|
currentTarget = (currentTarget + 1) % lookatTargets.length;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Entities.editEntity(cameraEntity, {rotation: Quat.mix(cameraProperties.rotation, targetOrientation, deltaTime / 3)});
|
||||||
|
});
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(function() {
|
||||||
|
Entities.deleteEntity(cameraEntity);
|
||||||
|
Camera.mode = oldCameraMode;
|
||||||
|
Camera.cameraEntity = null;
|
||||||
|
});
|
|
@ -382,7 +382,7 @@
|
||||||
var elHyperlinkHref = document.getElementById("property-hyperlink-href");
|
var elHyperlinkHref = document.getElementById("property-hyperlink-href");
|
||||||
var elHyperlinkDescription = document.getElementById("property-hyperlink-description");
|
var elHyperlinkDescription = document.getElementById("property-hyperlink-description");
|
||||||
|
|
||||||
|
var elPreviewCameraButton = document.getElementById("preview-camera-button");
|
||||||
|
|
||||||
if (window.EventBridge !== undefined) {
|
if (window.EventBridge !== undefined) {
|
||||||
EventBridge.scriptEventReceived.connect(function(data) {
|
EventBridge.scriptEventReceived.connect(function(data) {
|
||||||
|
@ -931,6 +931,12 @@
|
||||||
action: "centerAtmosphereToZone",
|
action: "centerAtmosphereToZone",
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
elPreviewCameraButton.addEventListener("click", function() {
|
||||||
|
EventBridge.emitWebEvent(JSON.stringify({
|
||||||
|
type: "action",
|
||||||
|
action: "previewCamera"
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
window.onblur = function() {
|
window.onblur = function() {
|
||||||
// Fake a change event
|
// Fake a change event
|
||||||
|
@ -1032,7 +1038,7 @@
|
||||||
|
|
||||||
|
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<label>Spacial Properites</label>
|
<label>Spacial Properties</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="property">
|
<div class="property">
|
||||||
|
@ -1044,6 +1050,7 @@
|
||||||
<div>
|
<div>
|
||||||
<input type="button" id="move-selection-to-grid" value="Selection to Grid">
|
<input type="button" id="move-selection-to-grid" value="Selection to Grid">
|
||||||
<input type="button" id="move-all-to-grid" value="All to Grid">
|
<input type="button" id="move-all-to-grid" value="All to Grid">
|
||||||
|
<input type="button" id="preview-camera-button" value="Preview Camera">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -204,7 +204,7 @@ EntityPropertyDialogBox = (function () {
|
||||||
array.push({ label: "Collisions Will Move:", type: "checkbox", value: properties.collisionsWillMove });
|
array.push({ label: "Collisions Will Move:", type: "checkbox", value: properties.collisionsWillMove });
|
||||||
index++;
|
index++;
|
||||||
array.push({ label: "Collision Sound URL:", value: properties.collisionSoundURL });
|
array.push({ label: "Collision Sound URL:", value: properties.collisionSoundURL });
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
array.push({ label: "Lifetime:", value: properties.lifetime.toFixed(decimals) });
|
array.push({ label: "Lifetime:", value: properties.lifetime.toFixed(decimals) });
|
||||||
index++;
|
index++;
|
||||||
|
@ -260,6 +260,10 @@ EntityPropertyDialogBox = (function () {
|
||||||
array.push({ label: "Cutoff (in degrees):", value: properties.cutoff });
|
array.push({ label: "Cutoff (in degrees):", value: properties.cutoff });
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
array.push({ label: "", type: "inlineButton", buttonLabel: "Preview Camera", name: "previewCamera" });
|
||||||
|
index++;
|
||||||
|
|
||||||
array.push({ button: "Cancel" });
|
array.push({ button: "Cancel" });
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
|
@ -268,6 +272,11 @@ EntityPropertyDialogBox = (function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
Window.inlineButtonClicked.connect(function (name) {
|
Window.inlineButtonClicked.connect(function (name) {
|
||||||
|
if (name == "previewCamera") {
|
||||||
|
Camera.mode = "entity";
|
||||||
|
Camera.cameraEntity = propertiesForEditedEntity.id;
|
||||||
|
}
|
||||||
|
|
||||||
if (name == "resetDimensions") {
|
if (name == "resetDimensions") {
|
||||||
Window.reloadNonBlockingForm([
|
Window.reloadNonBlockingForm([
|
||||||
{ value: propertiesForEditedEntity.naturalDimensions.x.toFixed(decimals), oldIndex: dimensionX },
|
{ value: propertiesForEditedEntity.naturalDimensions.x.toFixed(decimals), oldIndex: dimensionX },
|
||||||
|
|
|
@ -1226,6 +1226,19 @@ void Application::paintGL() {
|
||||||
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
||||||
}
|
}
|
||||||
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
||||||
|
} else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) {
|
||||||
|
EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer();
|
||||||
|
if (cameraEntity != nullptr) {
|
||||||
|
if (isHMDMode()) {
|
||||||
|
glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
|
||||||
|
_myCamera.setRotation(cameraEntity->getRotation() * hmdRotation);
|
||||||
|
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
||||||
|
_myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset));
|
||||||
|
} else {
|
||||||
|
_myCamera.setRotation(cameraEntity->getRotation());
|
||||||
|
_myCamera.setPosition(cameraEntity->getPosition());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Update camera position
|
// Update camera position
|
||||||
if (!isHMDMode()) {
|
if (!isHMDMode()) {
|
||||||
|
@ -2676,8 +2689,8 @@ void Application::cycleCamera() {
|
||||||
menu->setIsOptionChecked(MenuOption::ThirdPerson, false);
|
menu->setIsOptionChecked(MenuOption::ThirdPerson, false);
|
||||||
menu->setIsOptionChecked(MenuOption::FullscreenMirror, true);
|
menu->setIsOptionChecked(MenuOption::FullscreenMirror, true);
|
||||||
|
|
||||||
} else if (menu->isOptionChecked(MenuOption::IndependentMode)) {
|
} else if (menu->isOptionChecked(MenuOption::IndependentMode) || menu->isOptionChecked(MenuOption::CameraEntityMode)) {
|
||||||
// do nothing if in independe mode
|
// do nothing if in independent or camera entity modes
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cameraMenuChanged(); // handle the menu change
|
cameraMenuChanged(); // handle the menu change
|
||||||
|
@ -2704,6 +2717,10 @@ void Application::cameraMenuChanged() {
|
||||||
if (_myCamera.getMode() != CAMERA_MODE_INDEPENDENT) {
|
if (_myCamera.getMode() != CAMERA_MODE_INDEPENDENT) {
|
||||||
_myCamera.setMode(CAMERA_MODE_INDEPENDENT);
|
_myCamera.setMode(CAMERA_MODE_INDEPENDENT);
|
||||||
}
|
}
|
||||||
|
} else if (Menu::getInstance()->isOptionChecked(MenuOption::CameraEntityMode)) {
|
||||||
|
if (_myCamera.getMode() != CAMERA_MODE_ENTITY) {
|
||||||
|
_myCamera.setMode(CAMERA_MODE_ENTITY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ CameraMode stringToMode(const QString& mode) {
|
||||||
return CAMERA_MODE_MIRROR;
|
return CAMERA_MODE_MIRROR;
|
||||||
} else if (mode == "independent") {
|
} else if (mode == "independent") {
|
||||||
return CAMERA_MODE_INDEPENDENT;
|
return CAMERA_MODE_INDEPENDENT;
|
||||||
|
} else if (mode == "entity") {
|
||||||
|
return CAMERA_MODE_ENTITY;
|
||||||
}
|
}
|
||||||
return CAMERA_MODE_NULL;
|
return CAMERA_MODE_NULL;
|
||||||
}
|
}
|
||||||
|
@ -41,6 +43,8 @@ QString modeToString(CameraMode mode) {
|
||||||
return "mirror";
|
return "mirror";
|
||||||
} else if (mode == CAMERA_MODE_INDEPENDENT) {
|
} else if (mode == CAMERA_MODE_INDEPENDENT) {
|
||||||
return "independent";
|
return "independent";
|
||||||
|
} else if (mode == CAMERA_MODE_ENTITY) {
|
||||||
|
return "entity";
|
||||||
}
|
}
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
@ -94,6 +98,17 @@ void Camera::setMode(CameraMode mode) {
|
||||||
emit modeUpdated(modeToString(mode));
|
emit modeUpdated(modeToString(mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QUuid Camera::getCameraEntity() const {
|
||||||
|
if (_cameraEntity != nullptr) {
|
||||||
|
return _cameraEntity->getID();
|
||||||
|
}
|
||||||
|
return QUuid();
|
||||||
|
};
|
||||||
|
|
||||||
|
void Camera::setCameraEntity(QUuid entityID) {
|
||||||
|
_cameraEntity = qApp->getEntities()->getTree()->findEntityByID(entityID);
|
||||||
|
}
|
||||||
|
|
||||||
void Camera::setProjection(const glm::mat4& projection) {
|
void Camera::setProjection(const glm::mat4& projection) {
|
||||||
_projection = projection;
|
_projection = projection;
|
||||||
}
|
}
|
||||||
|
@ -118,6 +133,9 @@ void Camera::setModeString(const QString& mode) {
|
||||||
case CAMERA_MODE_INDEPENDENT:
|
case CAMERA_MODE_INDEPENDENT:
|
||||||
Menu::getInstance()->setIsOptionChecked(MenuOption::IndependentMode, true);
|
Menu::getInstance()->setIsOptionChecked(MenuOption::IndependentMode, true);
|
||||||
break;
|
break;
|
||||||
|
case CAMERA_MODE_ENTITY:
|
||||||
|
Menu::getInstance()->setIsOptionChecked(MenuOption::CameraEntityMode, true);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ enum CameraMode
|
||||||
CAMERA_MODE_FIRST_PERSON,
|
CAMERA_MODE_FIRST_PERSON,
|
||||||
CAMERA_MODE_MIRROR,
|
CAMERA_MODE_MIRROR,
|
||||||
CAMERA_MODE_INDEPENDENT,
|
CAMERA_MODE_INDEPENDENT,
|
||||||
|
CAMERA_MODE_ENTITY,
|
||||||
NUM_CAMERA_MODES
|
NUM_CAMERA_MODES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@ class Camera : public QObject {
|
||||||
Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition)
|
Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition)
|
||||||
Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation)
|
Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation)
|
||||||
Q_PROPERTY(QString mode READ getModeString WRITE setModeString)
|
Q_PROPERTY(QString mode READ getModeString WRITE setModeString)
|
||||||
|
Q_PROPERTY(QUuid cameraEntity READ getCameraEntity WRITE setCameraEntity)
|
||||||
public:
|
public:
|
||||||
Camera();
|
Camera();
|
||||||
|
|
||||||
|
@ -49,6 +51,8 @@ public:
|
||||||
void loadViewFrustum(ViewFrustum& frustum) const;
|
void loadViewFrustum(ViewFrustum& frustum) const;
|
||||||
ViewFrustum toViewFrustum() const;
|
ViewFrustum toViewFrustum() const;
|
||||||
|
|
||||||
|
EntityItemPointer getCameraEntityPointer() const { return _cameraEntity; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
QString getModeString() const;
|
QString getModeString() const;
|
||||||
void setModeString(const QString& mode);
|
void setModeString(const QString& mode);
|
||||||
|
@ -68,6 +72,9 @@ public slots:
|
||||||
const glm::mat4& getProjection() const { return _projection; }
|
const glm::mat4& getProjection() const { return _projection; }
|
||||||
void setProjection(const glm::mat4& projection);
|
void setProjection(const glm::mat4& projection);
|
||||||
|
|
||||||
|
QUuid getCameraEntity() const;
|
||||||
|
void setCameraEntity(QUuid entityID);
|
||||||
|
|
||||||
PickRay computePickRay(float x, float y);
|
PickRay computePickRay(float x, float y);
|
||||||
|
|
||||||
// These only work on independent cameras
|
// These only work on independent cameras
|
||||||
|
@ -97,6 +104,7 @@ private:
|
||||||
glm::quat _rotation;
|
glm::quat _rotation;
|
||||||
bool _isKeepLookingAt{ false };
|
bool _isKeepLookingAt{ false };
|
||||||
glm::vec3 _lookingAt;
|
glm::vec3 _lookingAt;
|
||||||
|
EntityItemPointer _cameraEntity;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Camera_h
|
#endif // hifi_Camera_h
|
||||||
|
|
|
@ -268,6 +268,9 @@ Menu::Menu() {
|
||||||
cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(cameraModeMenu,
|
cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(cameraModeMenu,
|
||||||
MenuOption::IndependentMode, 0,
|
MenuOption::IndependentMode, 0,
|
||||||
false, qApp, SLOT(cameraMenuChanged())));
|
false, qApp, SLOT(cameraMenuChanged())));
|
||||||
|
cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(cameraModeMenu,
|
||||||
|
MenuOption::CameraEntityMode, 0,
|
||||||
|
false, qApp, SLOT(cameraMenuChanged())));
|
||||||
cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(cameraModeMenu,
|
cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(cameraModeMenu,
|
||||||
MenuOption::FullscreenMirror, 0, // QML Qt::Key_H,
|
MenuOption::FullscreenMirror, 0, // QML Qt::Key_H,
|
||||||
false, qApp, SLOT(cameraMenuChanged())));
|
false, qApp, SLOT(cameraMenuChanged())));
|
||||||
|
|
|
@ -155,6 +155,7 @@ namespace MenuOption {
|
||||||
const QString Bookmarks = "Bookmarks";
|
const QString Bookmarks = "Bookmarks";
|
||||||
const QString CachesSize = "RAM Caches Size";
|
const QString CachesSize = "RAM Caches Size";
|
||||||
const QString CalibrateCamera = "Calibrate Camera";
|
const QString CalibrateCamera = "Calibrate Camera";
|
||||||
|
const QString CameraEntityMode = "Entity Mode";
|
||||||
const QString CenterPlayerInView = "Center Player In View";
|
const QString CenterPlayerInView = "Center Player In View";
|
||||||
const QString Chat = "Chat...";
|
const QString Chat = "Chat...";
|
||||||
const QString Collisions = "Collisions";
|
const QString Collisions = "Collisions";
|
||||||
|
|
Loading…
Reference in a new issue