Merge branch 'master' of https://github.com/SeijiEmery/hifi into unit-tests
|
@ -852,9 +852,11 @@ void AudioMixer::run() {
|
|||
|
||||
// since we're a while loop we need to help Qt's event processing
|
||||
QCoreApplication::processEvents();
|
||||
QCoreApplication::sendPostedEvents(this, 0);
|
||||
|
||||
if (_isFinished) {
|
||||
// at this point the audio-mixer is done
|
||||
// check if we have a deferred delete event to process (which we should once finished)
|
||||
QCoreApplication::sendPostedEvents(this, QEvent::DeferredDelete);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ var RainSquall = function (properties) {
|
|||
function setUp() {
|
||||
if (debug) {
|
||||
squallCircle = Overlays.addOverlay("circle3d", {
|
||||
size: { x: 2 * squallRadius, y: 2 * squallRadius },
|
||||
size: { x: squallRadius, y: squallRadius },
|
||||
color: SQUALL_CIRCLE_COLOR,
|
||||
alpha: SQUALL_CIRCLE_ALPHA,
|
||||
solid: true,
|
||||
|
|
|
@ -1321,6 +1321,15 @@ PropertiesTool = function(opts) {
|
|||
pushCommandForSelections();
|
||||
selectionManager._update();
|
||||
}
|
||||
} else if (data.action == "reloadScript") {
|
||||
if (selectionManager.hasSelection()) {
|
||||
var timestamp = Date.now();
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
Entities.editEntity(selectionManager.selections[i], {
|
||||
scriptTimestamp: timestamp,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (data.action == "centerAtmosphereToZone") {
|
||||
if (selectionManager.hasSelection()) {
|
||||
selectionManager.saveProperties();
|
||||
|
|
|
@ -250,6 +250,8 @@
|
|||
var elCollisionSoundURL = document.getElementById("property-collision-sound-url");
|
||||
var elLifetime = document.getElementById("property-lifetime");
|
||||
var elScriptURL = document.getElementById("property-script-url");
|
||||
var elScriptTimestamp = document.getElementById("property-script-timestamp");
|
||||
var elReloadScriptButton = document.getElementById("reload-script-button");
|
||||
var elUserData = document.getElementById("property-user-data");
|
||||
|
||||
var elColorSection = document.getElementById("color-section");
|
||||
|
@ -470,6 +472,7 @@
|
|||
elCollisionSoundURL.value = properties.collisionSoundURL;
|
||||
elLifetime.value = properties.lifetime;
|
||||
elScriptURL.value = properties.script;
|
||||
elScriptTimestamp.value = properties.scriptTimestamp;
|
||||
elUserData.value = properties.userData;
|
||||
|
||||
elHyperlinkHref.value = properties.href;
|
||||
|
@ -688,6 +691,7 @@
|
|||
|
||||
elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime'));
|
||||
elScriptURL.addEventListener('change', createEmitTextPropertyUpdateFunction('script'));
|
||||
elScriptTimestamp.addEventListener('change', createEmitNumberPropertyUpdateFunction('scriptTimestamp'));
|
||||
elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData'));
|
||||
|
||||
var colorChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||
|
@ -889,6 +893,12 @@
|
|||
percentage: parseInt(elRescaleDimensionsPct.value),
|
||||
}));
|
||||
});
|
||||
elReloadScriptButton.addEventListener("click", function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "action",
|
||||
action: "reloadScript"
|
||||
}));
|
||||
});
|
||||
elCenterAtmosphereToZone.addEventListener("click", function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "action",
|
||||
|
@ -932,6 +942,7 @@
|
|||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body class="properties" onload='loaded();'>
|
||||
<div id="properties-list">
|
||||
<div id="type" class="property">
|
||||
|
@ -939,9 +950,12 @@
|
|||
<label>Type: </label><span id="property-type"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="property">
|
||||
<div id="id" class="property">
|
||||
<span class="label" style="float: left; margin-right: 6px">
|
||||
<label>ID: <label>
|
||||
</span>
|
||||
<div class="value">
|
||||
<label id="property-id" class="selectable"></label>
|
||||
<span id="property-id" class="selectable"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="property">
|
||||
|
@ -951,17 +965,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<div class="label">Hyperlink</div>
|
||||
<div class="input-area">Href<br></div>
|
||||
<div class="value">
|
||||
<input id="property-hyperlink-href" class="url"></input>
|
||||
</div>
|
||||
<div class="input-area">Description<br></div> <div class="value">
|
||||
<input id="property-hyperlink-description" class="url"></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<span class="label">Locked</span>
|
||||
<span class="value">
|
||||
|
@ -976,6 +979,36 @@
|
|||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<div class="label">User Data</div>
|
||||
<div class="value">
|
||||
<textarea id="property-user-data"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section-header">
|
||||
<label>Hyperlink</label>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<div class="label">Href</div>
|
||||
<div class="value">
|
||||
<input id="property-hyperlink-href" class="url"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="property">
|
||||
<div class="label">Description</div>
|
||||
<div class="value">
|
||||
<input id="property-hyperlink-description" class="url"></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section-header">
|
||||
<label>Spacial Properites</label>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<div class="label">Position</div>
|
||||
<div class="value">
|
||||
|
@ -1043,6 +1076,11 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section-header">
|
||||
<label>Physical Properites</label>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<div class="label">Linear Velocity</div>
|
||||
<div class="value">
|
||||
|
@ -1109,6 +1147,21 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="color-section" class="property">
|
||||
<div class="label">Color</div>
|
||||
<div class="value">
|
||||
<div id="property-color" class='color-picker'></div>
|
||||
<div class="input-area">R <input class="coord" type='number' id="property-color-red"></input></div>
|
||||
<div class="input-area">G <input class="coord" type='number' id="property-color-green"></input></div>
|
||||
<div class="input-area">B <input class="coord" type='number' id="property-color-blue"></input></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section-header">
|
||||
<label>Behavior</label>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<span class="label">Ignore For Collisions</span>
|
||||
<span class="value">
|
||||
|
@ -1138,80 +1191,18 @@
|
|||
</div>
|
||||
|
||||
<div class="property">
|
||||
<div class="label">Script URL</div>
|
||||
<div class="label">Script URL
|
||||
<input type="hidden" id="property-script-timestamp" class="value"></input>
|
||||
<input type="button" id="reload-script-button" value="Reload"></input>
|
||||
</div>
|
||||
<div class="value">
|
||||
<input id="property-script-url" class="url"></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<div class="label">User Data</div>
|
||||
<div class="value">
|
||||
<textarea id="property-user-data"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="color-section" class="property">
|
||||
<div class="label">Color</div>
|
||||
<div class="value">
|
||||
<div id="property-color" class='color-picker'></div>
|
||||
<div class="input-area">R <input class="coord" type='number' id="property-color-red"></input></div>
|
||||
<div class="input-area">G <input class="coord" type='number' id="property-color-green"></input></div>
|
||||
<div class="input-area">B <input class="coord" type='number' id="property-color-blue"></input></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="web-section property">
|
||||
<div class="label">Source URL</div>
|
||||
<div class="value">
|
||||
<input type="text" id="property-web-source-url" class="url"></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="particle-section property">
|
||||
<div class="label">Max Particles</div>
|
||||
<div class="value">
|
||||
<input type='number' id="property-particle-maxparticles" min="0" max="2048" step="1"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="particle-section property">
|
||||
<div class="label">Particle Life Span</div>
|
||||
<div class="value">
|
||||
<input type='number' id="property-particle-lifespan" min="0" step="0.1"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="particle-section property">
|
||||
<div class="label">Particle Emission Rate</div>
|
||||
<div class="value">
|
||||
<input type='number' id="property-particle-emit-rate" min="0" step="0.5"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="particle-section property">
|
||||
<div class="label">Particle Emission Direction</div>
|
||||
<div class="value">
|
||||
<div class="input-area">X <input class="coord" type='number' id="property-particle-emit-direction-x"></input></div>
|
||||
<div class="input-area">Y <input class="coord" type='number' id="property-particle-emit-direction-y"></input></div>
|
||||
<div class="input-area">Z <input class="coord" type='number' id="property-particle-emit-direction-z"></input></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="particle-section property">
|
||||
<div class="label">Particle Emission Strength</div>
|
||||
<div class="value">
|
||||
<input type='number' id="property-particle-emit-strength" min="0" step="0.1"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="particle-section property">
|
||||
<div class="label">Particle Local Gravity</div>
|
||||
<div class="value">
|
||||
<input class="coord" type='number' id="property-particle-localgravity" step="0.05"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="particle-section property">
|
||||
<div class="label">Particle Radius</div>
|
||||
<div class="value">
|
||||
<input class="coord" type='number' id="property-particle-radius" min="0" step="0.005"></input>
|
||||
</div>
|
||||
<div class="section-header model-section zone-section">
|
||||
<label>Model</label>
|
||||
</div>
|
||||
|
||||
<div class="model-section property">
|
||||
|
@ -1220,6 +1211,7 @@
|
|||
<input type="text" id="property-model-url" class="url"></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="model-section zone-section property">
|
||||
<div class="label">Shape Type</div>
|
||||
<div class="value">
|
||||
|
@ -1280,8 +1272,75 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section-header web-section">
|
||||
<label>Web</label>
|
||||
</div>
|
||||
|
||||
<div class="web-section property">
|
||||
<div class="label">Source URL</div>
|
||||
<div class="value">
|
||||
<input type="text" id="property-web-source-url" class="url"></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section-header particle-section">
|
||||
<label>Particle</label>
|
||||
</div>
|
||||
|
||||
<div class="particle-section property">
|
||||
<div class="label">Max Particles</div>
|
||||
<div class="value">
|
||||
<input type='number' id="property-particle-maxparticles" min="0" max="2048" step="1"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="particle-section property">
|
||||
<div class="label">Particle Life Span</div>
|
||||
<div class="value">
|
||||
<input type='number' id="property-particle-lifespan" min="0" step="0.1"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="particle-section property">
|
||||
<div class="label">Particle Emission Rate</div>
|
||||
<div class="value">
|
||||
<input type='number' id="property-particle-emit-rate" min="0" step="0.5"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="particle-section property">
|
||||
<div class="label">Particle Emission Direction</div>
|
||||
<div class="value">
|
||||
<div class="input-area">X <input class="coord" type='number' id="property-particle-emit-direction-x"></input></div>
|
||||
<div class="input-area">Y <input class="coord" type='number' id="property-particle-emit-direction-y"></input></div>
|
||||
<div class="input-area">Z <input class="coord" type='number' id="property-particle-emit-direction-z"></input></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="particle-section property">
|
||||
<div class="label">Particle Emission Strength</div>
|
||||
<div class="value">
|
||||
<input type='number' id="property-particle-emit-strength" min="0" step="0.1"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="particle-section property">
|
||||
<div class="label">Particle Local Gravity</div>
|
||||
<div class="value">
|
||||
<input class="coord" type='number' id="property-particle-localgravity" step="0.05"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="particle-section property">
|
||||
<div class="label">Particle Radius</div>
|
||||
<div class="value">
|
||||
<input class="coord" type='number' id="property-particle-radius" min="0" step="0.005"></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section-header text-section">
|
||||
<label>Text</label>
|
||||
</div>
|
||||
|
||||
<div class="text-section property">
|
||||
<div class="label">Text</div>
|
||||
<div class="label">Text Content</div>
|
||||
<div class="value">
|
||||
<input type="text" id="property-text-text"></input>
|
||||
</div>
|
||||
|
@ -1311,6 +1370,11 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section-header light-section">
|
||||
<label>Light</label>
|
||||
</div>
|
||||
|
||||
<div class="light-section property">
|
||||
<span class="label">Spot Light</span>
|
||||
<span class="value">
|
||||
|
@ -1345,6 +1409,11 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section-header zone-section">
|
||||
<label>Zone</label>
|
||||
</div>
|
||||
|
||||
<div class="zone-section property">
|
||||
<span class="label">Stage Sun Model Enabled</span>
|
||||
<span class="value">
|
||||
|
@ -1431,6 +1500,12 @@
|
|||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="sub-section-header zone-section skybox-section">
|
||||
<label>Skybox</label>
|
||||
</div>
|
||||
|
||||
<div class="zone-section skybox-section property">
|
||||
<div class="label">Skybox Color</div>
|
||||
<div class="value">
|
||||
|
@ -1446,6 +1521,12 @@
|
|||
<input type="text" id="property-zone-skybox-url" class="url"></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="sub-section-header zone-section atmosphere-section">
|
||||
<label>Atmosphere</label>
|
||||
</div>
|
||||
|
||||
<div class="zone-section atmosphere-section property">
|
||||
<div class="label">Atmosphere Center</div>
|
||||
<div class="value">
|
||||
|
@ -1495,8 +1576,6 @@
|
|||
<input type='checkbox' id="property-zone-atmosphere-has-stars">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -44,16 +44,26 @@ body {
|
|||
border: 1.5pt solid black;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
.section-header, .sub-section-header {
|
||||
background: #AAA;
|
||||
border-bottom: 0.75pt solid #CCC;
|
||||
background-color: #333333;
|
||||
color: #999;
|
||||
padding: 3pt;
|
||||
padding-top: 6pt;
|
||||
}
|
||||
|
||||
.section-header label {
|
||||
.section-header label, .sub-section-header label {
|
||||
font-weight: bold;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
.sub-section-header {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.sub-section-header label {
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
.multi-property-section {
|
||||
|
@ -183,11 +193,11 @@ div.input-area {
|
|||
input {
|
||||
}
|
||||
|
||||
#type {
|
||||
#type, #id {
|
||||
font-size: 9.0pt;
|
||||
}
|
||||
|
||||
#type label {
|
||||
#type label, #id label {
|
||||
color: rgb(150, 150, 150);
|
||||
}
|
||||
|
||||
|
@ -250,6 +260,11 @@ table#properties-list {
|
|||
height: 1.2em;
|
||||
}
|
||||
|
||||
#properties-list .label input[type=button] {
|
||||
float: right;
|
||||
padding: 0 5px 1px;
|
||||
}
|
||||
|
||||
#properties-list .value > div{
|
||||
padding: 3pt 0;
|
||||
}
|
||||
|
|
89
examples/html/walkSettings.html
Normal file
|
@ -0,0 +1,89 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="walkStyle.css">
|
||||
<script>
|
||||
|
||||
function emitUpdate() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "update",
|
||||
armsFree: elArmsFree.checked,
|
||||
makesFootStepSounds: elFootstepSounds.checked,
|
||||
blenderPreRotations: elBlenderPreRotations.checked
|
||||
}));
|
||||
}
|
||||
|
||||
function loaded() {
|
||||
// assign form elements to vars
|
||||
var powerOn = true;
|
||||
elPower = document.getElementById("power");
|
||||
elArmsFree = document.getElementById("arms-free");
|
||||
elFootstepSounds = document.getElementById("footstep-sounds");
|
||||
elBlenderPreRotations = document.getElementById("bender-pre-rotations");
|
||||
|
||||
if (window.EventBridge !== undefined) {
|
||||
EventBridge.scriptEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
|
||||
if (data.type == "update") {
|
||||
if (data.armsFree !== undefined) {
|
||||
elArmsFree.checked = data.armsFree;
|
||||
}
|
||||
if (data.makesFootStepSounds !== undefined) {
|
||||
elFootstepSounds.checked = data.makesFootStepSounds;
|
||||
}
|
||||
if (data.blenderPreRotations !== undefined) {
|
||||
elBlenderPreRotations.checked = data.blenderPreRotations;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
elArmsFree.addEventListener("change", emitUpdate);
|
||||
elFootstepSounds.addEventListener("change", emitUpdate);
|
||||
elBlenderPreRotations.addEventListener("change", emitUpdate);
|
||||
elPower.addEventListener("click", function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "powerToggle"
|
||||
}));
|
||||
powerOn = !powerOn;
|
||||
if (powerOn) {
|
||||
elPower.value = "Turn Animation Off";
|
||||
} else {
|
||||
elPower.value = "Turn Animation On";
|
||||
}
|
||||
});
|
||||
// request initial values
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'init' }));
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='loaded();'>
|
||||
<div>
|
||||
|
||||
<div id="walk-settings-header">
|
||||
<input type="button" id="power" value="Turn Animation Off" style="margin-left:30px; margin-top:10px"></button>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<label>Arms free</label>
|
||||
<span>
|
||||
<input type='checkbox' id="arms-free">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<label>Footstep sounds</label>
|
||||
<span>
|
||||
<input type='checkbox' id="footstep-sounds">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<label>Blender pre-rotations</label>
|
||||
<span>
|
||||
<input type='checkbox' id="bender-pre-rotations">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
48
examples/html/walkStyle.css
Normal file
|
@ -0,0 +1,48 @@
|
|||
* {
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
background-color: rgb(76, 76, 76);
|
||||
color: rgb(204, 204, 204);
|
||||
font-family: Arial;
|
||||
font-size: 9pt;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#walk-settings-header {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.settings-section {
|
||||
display: block;
|
||||
margin: 10 10;
|
||||
height: 22.5pt;
|
||||
}
|
||||
|
||||
.settings-section label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.settings-section span {
|
||||
float: right;
|
||||
}
|
||||
|
||||
input[type=button] {
|
||||
cursor: pointer;
|
||||
background-color: #608e96;
|
||||
border-color: #608e96;
|
||||
border-radius: 3.75pt;
|
||||
padding: 3.75pt 7.5pt;
|
||||
border: 0;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
|
@ -392,7 +392,8 @@ SelectionDisplay = (function () {
|
|||
|
||||
var grabberSpotLightCircle = Overlays.addOverlay("circle3d", {
|
||||
color: lightOverlayColor,
|
||||
isSolid: false
|
||||
isSolid: false,
|
||||
visible: false
|
||||
});
|
||||
var grabberSpotLightLineT = Overlays.addOverlay("line3d", spotLightLineProperties);
|
||||
var grabberSpotLightLineB = Overlays.addOverlay("line3d", spotLightLineProperties);
|
||||
|
@ -409,17 +410,20 @@ SelectionDisplay = (function () {
|
|||
var grabberPointLightCircleX = Overlays.addOverlay("circle3d", {
|
||||
rotation: Quat.fromPitchYawRollDegrees(0, 90, 0),
|
||||
color: lightOverlayColor,
|
||||
isSolid: false
|
||||
isSolid: false,
|
||||
visible: false
|
||||
});
|
||||
var grabberPointLightCircleY = Overlays.addOverlay("circle3d", {
|
||||
rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
|
||||
color: lightOverlayColor,
|
||||
isSolid: false
|
||||
isSolid: false,
|
||||
visible: false
|
||||
});
|
||||
var grabberPointLightCircleZ = Overlays.addOverlay("circle3d", {
|
||||
rotation: Quat.fromPitchYawRollDegrees(0, 0, 0),
|
||||
color: lightOverlayColor,
|
||||
isSolid: false
|
||||
isSolid: false,
|
||||
visible: false
|
||||
});
|
||||
var grabberPointLightT = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
||||
var grabberPointLightB = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
||||
|
@ -546,7 +550,7 @@ SelectionDisplay = (function () {
|
|||
|
||||
var rotateOverlayTarget = Overlays.addOverlay("circle3d", {
|
||||
position: { x:0, y: 0, z: 0},
|
||||
size: rotateOverlayTargetSize * 2,
|
||||
size: rotateOverlayTargetSize,
|
||||
color: { red: 0, green: 0, blue: 0 },
|
||||
alpha: 0.0,
|
||||
solid: true,
|
||||
|
@ -1186,7 +1190,7 @@ SelectionDisplay = (function () {
|
|||
});
|
||||
Overlays.editOverlay(grabberSpotLightCircle, {
|
||||
position: NEAR,
|
||||
dimensions: { x: distance * 2, y: distance * 2, z: 1 },
|
||||
dimensions: { x: distance, y: distance, z: 1 },
|
||||
lineWidth: 1.5,
|
||||
rotation: rotation,
|
||||
visible: true,
|
||||
|
@ -1258,19 +1262,19 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(grabberPointLightCircleX, {
|
||||
position: position,
|
||||
rotation: Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(0, 90, 0)),
|
||||
dimensions: { x: properties.dimensions.z, y: properties.dimensions.z, z: 1 },
|
||||
dimensions: { x: properties.dimensions.z / 2.0, y: properties.dimensions.z / 2.0, z: 1 },
|
||||
visible: true,
|
||||
});
|
||||
Overlays.editOverlay(grabberPointLightCircleY, {
|
||||
position: position,
|
||||
rotation: Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(90, 0, 0)),
|
||||
dimensions: { x: properties.dimensions.z, y: properties.dimensions.z, z: 1 },
|
||||
dimensions: { x: properties.dimensions.z / 2.0, y: properties.dimensions.z / 2.0, z: 1 },
|
||||
visible: true,
|
||||
});
|
||||
Overlays.editOverlay(grabberPointLightCircleZ, {
|
||||
position: position,
|
||||
rotation: rotation,
|
||||
dimensions: { x: properties.dimensions.z, y: properties.dimensions.z, z: 1 },
|
||||
dimensions: { x: properties.dimensions.z / 2.0, y: properties.dimensions.z / 2.0, z: 1 },
|
||||
visible: true,
|
||||
});
|
||||
|
||||
|
@ -1966,7 +1970,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayInner,
|
||||
{
|
||||
visible: true,
|
||||
size: innerRadius * 2,
|
||||
size: innerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
|
@ -1976,7 +1980,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayOuter,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius * 2,
|
||||
size: outerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
|
@ -1986,7 +1990,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayCurrent,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius * 2,
|
||||
size: outerRadius,
|
||||
startAt: 0,
|
||||
endAt: 0,
|
||||
innerRadius: 0.9,
|
||||
|
@ -2064,13 +2068,13 @@ SelectionDisplay = (function () {
|
|||
if (snapToInner) {
|
||||
Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 });
|
||||
Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius * 2,
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius,
|
||||
majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0,
|
||||
majorTickMarksLength: -0.25, minorTickMarksLength: 0, });
|
||||
} else {
|
||||
Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 });
|
||||
Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius * 2,
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius,
|
||||
majorTickMarksAngle: 45.0, minorTickMarksAngle: 5,
|
||||
majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, });
|
||||
}
|
||||
|
@ -2095,7 +2099,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayInner,
|
||||
{
|
||||
visible: true,
|
||||
size: innerRadius * 2,
|
||||
size: innerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
|
@ -2105,7 +2109,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayOuter,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius * 2,
|
||||
size: outerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
|
@ -2115,7 +2119,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayCurrent,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius * 2,
|
||||
size: outerRadius,
|
||||
startAt: 0,
|
||||
endAt: 0,
|
||||
innerRadius: 0.9,
|
||||
|
@ -2186,13 +2190,13 @@ SelectionDisplay = (function () {
|
|||
if (snapToInner) {
|
||||
Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 });
|
||||
Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius * 2,
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius,
|
||||
majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0,
|
||||
majorTickMarksLength: -0.25, minorTickMarksLength: 0, });
|
||||
} else {
|
||||
Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 });
|
||||
Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius * 2,
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius,
|
||||
majorTickMarksAngle: 45.0, minorTickMarksAngle: 5,
|
||||
majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, });
|
||||
}
|
||||
|
@ -2216,7 +2220,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayInner,
|
||||
{
|
||||
visible: true,
|
||||
size: innerRadius * 2,
|
||||
size: innerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
|
@ -2226,7 +2230,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayOuter,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius * 2,
|
||||
size: outerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
|
@ -2236,7 +2240,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayCurrent,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius * 2,
|
||||
size: outerRadius,
|
||||
startAt: 0,
|
||||
endAt: 0,
|
||||
innerRadius: 0.9,
|
||||
|
@ -2306,13 +2310,13 @@ SelectionDisplay = (function () {
|
|||
if (snapToInner) {
|
||||
Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 });
|
||||
Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius * 2,
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius,
|
||||
majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0,
|
||||
majorTickMarksLength: -0.25, minorTickMarksLength: 0, });
|
||||
} else {
|
||||
Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 });
|
||||
Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius * 2,
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius,
|
||||
majorTickMarksAngle: 45.0, minorTickMarksAngle: 5,
|
||||
majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, });
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
|
|||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = 0;
|
||||
this.height = 0;
|
||||
this.height = ToolBar.TITLE_BAR_HEIGHT;
|
||||
this.back = this.back = Overlays.addOverlay("text", {
|
||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||
x: this.x,
|
||||
|
@ -371,13 +371,13 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
|
|||
// These are currently only doing that which is necessary for toolbar hover and toolbar drag.
|
||||
// They have not yet been extended to tool hover/click/release, etc.
|
||||
this.mousePressEvent = function (event) {
|
||||
if (!that.contains(event)) {
|
||||
if (Overlays.getOverlayAtPoint({ x: event.x, y: event.y }) == that.back) {
|
||||
that.mightBeDragging = true;
|
||||
that.dragOffsetX = that.x - event.x;
|
||||
that.dragOffsetY = that.y - event.y;
|
||||
} else {
|
||||
that.mightBeDragging = false;
|
||||
return;
|
||||
}
|
||||
that.mightBeDragging = true;
|
||||
that.dragOffsetX = that.x - event.x;
|
||||
that.dragOffsetY = that.y - event.y;
|
||||
};
|
||||
this.mouseMove = function (event) {
|
||||
if (!that.mightBeDragging || !event.isLeftButton) {
|
||||
|
@ -437,3 +437,4 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
|
|||
ToolBar.SPACING = 4;
|
||||
ToolBar.VERTICAL = 0;
|
||||
ToolBar.HORIZONTAL = 1;
|
||||
ToolBar.TITLE_BAR_HEIGHT = 10;
|
||||
|
|
54
examples/libraries/walkConstants.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// walkConstants.js
|
||||
// version 1.0
|
||||
//
|
||||
// Created by David Wooldridge, June 2015
|
||||
// Copyright © 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Provides constants necessary for the operation of the walk.js script and the walkApi.js script
|
||||
//
|
||||
// Editing tools for animation data files available here: https://github.com/DaveDubUK/walkTools
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// locomotion states
|
||||
STATIC = 1;
|
||||
SURFACE_MOTION = 2;
|
||||
AIR_MOTION = 4;
|
||||
|
||||
// directions
|
||||
UP = 1;
|
||||
DOWN = 2;
|
||||
LEFT = 4;
|
||||
RIGHT = 8;
|
||||
FORWARDS = 16;
|
||||
BACKWARDS = 32;
|
||||
NONE = 64;
|
||||
|
||||
// waveshapes
|
||||
SAWTOOTH = 1;
|
||||
TRIANGLE = 2;
|
||||
SQUARE = 4;
|
||||
|
||||
// used by walk.js and walkApi.js
|
||||
MAX_WALK_SPEED = 2.9; // peak, by observation
|
||||
MAX_FT_WHEEL_INCREMENT = 25; // avoid fast walk when landing
|
||||
TOP_SPEED = 300;
|
||||
ON_SURFACE_THRESHOLD = 0.1; // height above surface to be considered as on the surface
|
||||
TRANSITION_COMPLETE = 1000;
|
||||
PITCH_MAX = 60; // maximum speed induced pitch
|
||||
ROLL_MAX = 80; // maximum speed induced leaning / banking
|
||||
DELTA_YAW_MAX = 1.7; // maximum change in yaw in rad/s
|
||||
|
||||
// used by walkApi.js only
|
||||
MOVE_THRESHOLD = 0.075; // movement dead zone
|
||||
ACCELERATION_THRESHOLD = 0.2; // detect stop to walking
|
||||
DECELERATION_THRESHOLD = -6; // detect walking to stop
|
||||
FAST_DECELERATION_THRESHOLD = -150; // detect flying to stop
|
||||
BOUNCE_ACCELERATION_THRESHOLD = 25; // used to ignore gravity influence fluctuations after landing
|
||||
GRAVITY_THRESHOLD = 3.0; // height above surface where gravity is in effect
|
||||
OVERCOME_GRAVITY_SPEED = 0.5; // reaction sensitivity to jumping under gravity
|
||||
LANDING_THRESHOLD = 0.35; // metres from a surface below which need to prepare for impact
|
||||
MAX_TRANSITION_RECURSION = 10; // how many nested transitions are permitted
|
|
@ -1,134 +1,78 @@
|
|||
//
|
||||
// walkFilters.js
|
||||
// version 1.1
|
||||
//
|
||||
// version 1.002
|
||||
// Created by David Wooldridge, June 2015
|
||||
// Copyright © 2014 - 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Created by David Wooldridge, Autumn 2014
|
||||
//
|
||||
// Provides a variety of filters for use by the walk.js script v1.12
|
||||
// Provides a variety of filters for use by the walk.js script v1.2+
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// simple averaging (LP) filter for damping / smoothing
|
||||
AveragingFilter = function(length) {
|
||||
|
||||
//this.name = name;
|
||||
// initialise the array of past values
|
||||
this.pastValues = [];
|
||||
|
||||
for(var i = 0; i < length; i++) {
|
||||
for (var i = 0; i < length; i++) {
|
||||
this.pastValues.push(0);
|
||||
}
|
||||
|
||||
// single arg is the nextInputValue
|
||||
this.process = function() {
|
||||
|
||||
if (this.pastValues.length === 0 && arguments[0]) {
|
||||
|
||||
return arguments[0];
|
||||
|
||||
} else if (arguments[0] !== null) {
|
||||
|
||||
// apply quick and simple LP filtering
|
||||
this.pastValues.push(arguments[0]);
|
||||
this.pastValues.shift();
|
||||
var nextOutputValue = 0;
|
||||
for (var ea in this.pastValues) nextOutputValue += this.pastValues[ea];
|
||||
for (var value in this.pastValues) nextOutputValue += this.pastValues[value];
|
||||
return nextOutputValue / this.pastValues.length;
|
||||
|
||||
} else {
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// 1st order Butterworth filter - calculate coeffs here: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html
|
||||
// provides LP filtering with a more stable frequency / phase response (-3 dB @ 3 Hz)
|
||||
ButterworthFilter1 = function() {
|
||||
|
||||
this.gain = 7.313751515;
|
||||
this.coeff = 0.7265425280;
|
||||
// 2nd order 2Hz Butterworth LP filter
|
||||
ButterworthFilter = function() {
|
||||
// coefficients calculated at: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html
|
||||
this.gain = 104.9784742;
|
||||
this.coeffOne = -0.7436551950;
|
||||
this.coeffTwo = 1.7055521455;
|
||||
|
||||
// initialise the arrays
|
||||
this.xv = [];
|
||||
this.yv = [];
|
||||
|
||||
for(var i = 0; i < 2; i++) {
|
||||
|
||||
for (var i = 0; i < 3; i++) {
|
||||
this.xv.push(0);
|
||||
this.yv.push(0);
|
||||
}
|
||||
|
||||
// process values
|
||||
this.process = function(nextInputValue) {
|
||||
|
||||
this.xv[0] = this.xv[1];
|
||||
this.xv[1] = nextInputValue / this.gain;
|
||||
|
||||
this.yv[0] = this.yv[1];
|
||||
this.yv[1] = this.xv[0] + this.xv[1] + this.coeff * this.yv[0];
|
||||
|
||||
return this.yv[1];
|
||||
};
|
||||
|
||||
}; // end Butterworth filter constructor
|
||||
|
||||
// 2nd order Butterworth LP filter - calculate coeffs here: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html
|
||||
// provides LP filtering with a more stable frequency / phase response
|
||||
ButterworthFilter2 = function(cutOff) {
|
||||
|
||||
switch(cutOff) {
|
||||
|
||||
case 5:
|
||||
default:
|
||||
|
||||
this.gain = 20.20612010;
|
||||
this.coeffOne = -0.4775922501;
|
||||
this.coeffTwo = 1.2796324250;
|
||||
break;
|
||||
}
|
||||
|
||||
// initialise the arrays
|
||||
this.xv = [];
|
||||
this.yv = [];
|
||||
for(var i = 0; i < 3; i++) {
|
||||
|
||||
this.xv.push(0);
|
||||
this.yv.push(0);
|
||||
}
|
||||
|
||||
// process values
|
||||
this.process = function(nextInputValue) {
|
||||
|
||||
this.xv[0] = this.xv[1];
|
||||
this.xv[1] = this.xv[2];
|
||||
this.xv[2] = nextInputValue / this.gain;
|
||||
|
||||
this.yv[0] = this.yv[1];
|
||||
this.yv[1] = this.yv[2];
|
||||
this.yv[2] = (this.xv[0] + this.xv[2]) +
|
||||
2 * this.xv[1] +
|
||||
(this.coeffOne * this.yv[0]) +
|
||||
(this.coeffTwo * this.yv[1]);
|
||||
|
||||
return this.yv[2];
|
||||
};
|
||||
}; // end Butterworth filter constructor
|
||||
|
||||
|
||||
// Add harmonics to a given sine wave to form square, sawtooth or triangle waves
|
||||
// Geometric wave synthesis fundamentals taken from: http://hyperphysics.phy-astr.gsu.edu/hbase/audio/geowv.html
|
||||
WaveSynth = function(waveShape, numHarmonics, smoothing) {
|
||||
|
||||
this.numHarmonics = numHarmonics;
|
||||
this.waveShape = waveShape;
|
||||
this.smoothingFilter = new AveragingFilter(smoothing);
|
||||
|
||||
// NB: frequency in radians
|
||||
this.calculate = function(frequency) {
|
||||
|
||||
// make some shapes
|
||||
var harmonics = 0;
|
||||
var multiplier = 0;
|
||||
|
@ -136,20 +80,15 @@ WaveSynth = function(waveShape, numHarmonics, smoothing) {
|
|||
if (this.waveShape === TRIANGLE) {
|
||||
iterations++;
|
||||
}
|
||||
|
||||
for(var n = 1; n < iterations; n++) {
|
||||
|
||||
switch(this.waveShape) {
|
||||
|
||||
for (var n = 1; n < iterations; n++) {
|
||||
switch (this.waveShape) {
|
||||
case SAWTOOTH: {
|
||||
|
||||
multiplier = 1 / n;
|
||||
harmonics += multiplier * Math.sin(n * frequency);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRIANGLE: {
|
||||
|
||||
if (n % 2 === 1) {
|
||||
var mulitplier = 1 / (n * n);
|
||||
// multiply (4n-1)th harmonics by -1
|
||||
|
@ -162,7 +101,6 @@ WaveSynth = function(waveShape, numHarmonics, smoothing) {
|
|||
}
|
||||
|
||||
case SQUARE: {
|
||||
|
||||
if (n % 2 === 1) {
|
||||
multiplier = 1 / n;
|
||||
harmonics += multiplier * Math.sin(n * frequency);
|
||||
|
@ -171,34 +109,35 @@ WaveSynth = function(waveShape, numHarmonics, smoothing) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// smooth the result and return
|
||||
return this.smoothingFilter.process(harmonics);
|
||||
};
|
||||
};
|
||||
|
||||
// Create a motion wave by summing pre-calcualted sinusoidal harmonics
|
||||
// Create a motion wave by summing pre-calculated harmonics (Fourier synthesis)
|
||||
HarmonicsFilter = function(magnitudes, phaseAngles) {
|
||||
|
||||
this.magnitudes = magnitudes;
|
||||
this.phaseAngles = phaseAngles;
|
||||
|
||||
this.calculate = function(twoPiFT) {
|
||||
|
||||
var harmonics = 0;
|
||||
var numHarmonics = magnitudes.length;
|
||||
|
||||
for(var n = 0; n < numHarmonics; n++) {
|
||||
for (var n = 0; n < numHarmonics; n++) {
|
||||
harmonics += this.magnitudes[n] * Math.cos(n * twoPiFT - this.phaseAngles[n]);
|
||||
}
|
||||
return harmonics;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// the main filter object
|
||||
// the main filter object literal
|
||||
filter = (function() {
|
||||
|
||||
const HALF_CYCLE = 180;
|
||||
|
||||
// Bezier private variables
|
||||
var _C1 = {x:0, y:0};
|
||||
var _C4 = {x:1, y:1};
|
||||
|
||||
// Bezier private functions
|
||||
function _B1(t) { return t * t * t };
|
||||
function _B2(t) { return 3 * t * t * (1 - t) };
|
||||
|
@ -209,63 +148,52 @@ filter = (function() {
|
|||
|
||||
// helper methods
|
||||
degToRad: function(degrees) {
|
||||
|
||||
var convertedValue = degrees * Math.PI / 180;
|
||||
var convertedValue = degrees * Math.PI / HALF_CYCLE;
|
||||
return convertedValue;
|
||||
},
|
||||
|
||||
radToDeg: function(radians) {
|
||||
|
||||
var convertedValue = radians * 180 / Math.PI;
|
||||
var convertedValue = radians * HALF_CYCLE / Math.PI;
|
||||
return convertedValue;
|
||||
},
|
||||
|
||||
// these filters need instantiating, as they hold arrays of previous values
|
||||
createAveragingFilter: function(length) {
|
||||
|
||||
// simple averaging (LP) filter for damping / smoothing
|
||||
createAveragingFilter: function(length) {
|
||||
var newAveragingFilter = new AveragingFilter(length);
|
||||
return newAveragingFilter;
|
||||
},
|
||||
|
||||
createButterworthFilter1: function() {
|
||||
|
||||
var newButterworthFilter = new ButterworthFilter1();
|
||||
return newButterworthFilter;
|
||||
},
|
||||
|
||||
createButterworthFilter2: function(cutoff) {
|
||||
|
||||
var newButterworthFilter = new ButterworthFilter2(cutoff);
|
||||
// provides LP filtering with improved frequency / phase response
|
||||
createButterworthFilter: function() {
|
||||
var newButterworthFilter = new ButterworthFilter();
|
||||
return newButterworthFilter;
|
||||
},
|
||||
|
||||
// generates sawtooth, triangle or square waves using harmonics
|
||||
createWaveSynth: function(waveShape, numHarmonics, smoothing) {
|
||||
|
||||
var newWaveSynth = new WaveSynth(waveShape, numHarmonics, smoothing);
|
||||
return newWaveSynth;
|
||||
},
|
||||
|
||||
// generates arbitrary waveforms using pre-calculated harmonics
|
||||
createHarmonicsFilter: function(magnitudes, phaseAngles) {
|
||||
|
||||
var newHarmonicsFilter = new HarmonicsFilter(magnitudes, phaseAngles);
|
||||
return newHarmonicsFilter;
|
||||
},
|
||||
|
||||
|
||||
// the following filters do not need separate instances, as they hold no previous values
|
||||
bezier: function(percent, C1, C2, C3, C4) {
|
||||
|
||||
// Bezier functions for more natural transitions
|
||||
// Bezier response curve shaping for more natural transitions
|
||||
bezier: function(input, C2, C3) {
|
||||
// based on script by Dan Pupius (www.pupius.net) http://13thparallel.com/archive/bezier-curves/
|
||||
var pos = {x: 0, y: 0};
|
||||
pos.x = C1.x * _B1(percent) + C2.x * _B2(percent) + C3.x * _B3(percent) + C4.x * _B4(percent);
|
||||
pos.y = C1.y * _B1(percent) + C2.y * _B2(percent) + C3.y * _B3(percent) + C4.y * _B4(percent);
|
||||
return pos;
|
||||
input = 1 - input;
|
||||
return _C1.y * _B1(input) + C2.y * _B2(input) + C3.y * _B3(input) + _C4.y * _B4(input);
|
||||
},
|
||||
|
||||
// simple clipping filter (clips bottom of wave only)
|
||||
// simple clipping filter (special case for hips y-axis skeleton offset for walk animation)
|
||||
clipTrough: function(inputValue, peak, strength) {
|
||||
|
||||
var outputValue = inputValue * strength;
|
||||
if (outputValue < -peak) {
|
||||
outputValue = -peak;
|
||||
|
@ -273,5 +201,4 @@ filter = (function() {
|
|||
return outputValue;
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
|
@ -1,340 +0,0 @@
|
|||
//
|
||||
// walkInterface.js
|
||||
//
|
||||
// version 2.0
|
||||
//
|
||||
// Created by David Wooldridge, Autumn 2014
|
||||
//
|
||||
// Presents the UI for the walk.js script v1.12
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
walkInterface = (function() {
|
||||
|
||||
// references to walk.js objects
|
||||
var _motion = null;
|
||||
var _walkAssets = null;
|
||||
|
||||
// controller UI element positions and dimensions
|
||||
var _backgroundWidth = 350;
|
||||
var _backgroundHeight = 700;
|
||||
var _backgroundX = Window.innerWidth - _backgroundWidth - 58;
|
||||
var _backgroundY = Window.innerHeight / 2 - _backgroundHeight / 2;
|
||||
var _bigButtonsY = 348;
|
||||
|
||||
// Load up the overlays
|
||||
var _buttonOverlays = [];
|
||||
|
||||
// ui minimised tab
|
||||
var _controlsMinimisedTab = Overlays.addOverlay("image", {
|
||||
x: Window.innerWidth - 58,
|
||||
y: Window.innerHeight - 145,
|
||||
width: 50, height: 50,
|
||||
imageURL: pathToAssets + 'overlay-images/minimised-tab.png',
|
||||
visible: true, alpha: 0.9
|
||||
});
|
||||
|
||||
// ui background
|
||||
var _controlsBackground = Overlays.addOverlay("image", {
|
||||
bounds: {
|
||||
x: _backgroundX,
|
||||
y: _backgroundY,
|
||||
width: _backgroundWidth,
|
||||
height: _backgroundHeight
|
||||
},
|
||||
imageURL: pathToAssets + "overlay-images/background.png",
|
||||
alpha: 1, visible: false
|
||||
});
|
||||
|
||||
// button overlays
|
||||
var _controlsMinimiseButton = Overlays.addOverlay("image", {
|
||||
bounds: {
|
||||
x: _backgroundX + _backgroundWidth - 62,
|
||||
y: _backgroundY + 40,
|
||||
width: 25, height: 25
|
||||
},
|
||||
imageURL: pathToAssets + "overlay-images/minimise-button.png",
|
||||
alpha: 1, visible: false
|
||||
});
|
||||
_buttonOverlays.push(_controlsMinimiseButton);
|
||||
|
||||
var _onButton = Overlays.addOverlay("image", {
|
||||
bounds: {
|
||||
x: _backgroundX + _backgroundWidth / 2 - 115,
|
||||
y: _backgroundY + _bigButtonsY,
|
||||
width: 230, height: 36
|
||||
},
|
||||
imageURL: pathToAssets + "overlay-images/power-button-selected.png",
|
||||
alpha: 1, visible: false
|
||||
});
|
||||
_buttonOverlays.push(_onButton);
|
||||
|
||||
var _offButton = Overlays.addOverlay("image", {
|
||||
bounds: {
|
||||
x: _backgroundX + _backgroundWidth / 2 - 115,
|
||||
y: _backgroundY + _bigButtonsY,
|
||||
width: 230, height: 36
|
||||
},
|
||||
imageURL: pathToAssets + "overlay-images/power-button.png",
|
||||
alpha: 1, visible: false
|
||||
});
|
||||
_buttonOverlays.push(_offButton);
|
||||
|
||||
var _femaleButton = Overlays.addOverlay("image", {
|
||||
bounds: {
|
||||
x: _backgroundX + _backgroundWidth / 2 - 115,
|
||||
y: _backgroundY + _bigButtonsY + 60,
|
||||
width: 230, height: 36
|
||||
},
|
||||
imageURL: pathToAssets + "overlay-images/female-button.png",
|
||||
alpha: 1, visible: false
|
||||
});
|
||||
_buttonOverlays.push(_femaleButton);
|
||||
|
||||
var _femaleButtonSelected = Overlays.addOverlay("image", {
|
||||
bounds: {
|
||||
x: _backgroundX + _backgroundWidth / 2 - 115,
|
||||
y: _backgroundY + _bigButtonsY + 60,
|
||||
width: 230, height: 36
|
||||
},
|
||||
imageURL: pathToAssets + "overlay-images/female-button-selected.png",
|
||||
alpha: 1, visible: false
|
||||
});
|
||||
_buttonOverlays.push(_femaleButtonSelected);
|
||||
|
||||
var _maleButton = Overlays.addOverlay("image", {
|
||||
bounds: {
|
||||
x: _backgroundX + _backgroundWidth / 2 - 115,
|
||||
y: _backgroundY + _bigButtonsY + 120,
|
||||
width: 230, height: 36
|
||||
},
|
||||
imageURL: pathToAssets + "overlay-images/male-button.png",
|
||||
alpha: 1, visible: false
|
||||
});
|
||||
_buttonOverlays.push(_maleButton);
|
||||
|
||||
var _maleButtonSelected = Overlays.addOverlay("image", {
|
||||
bounds: {
|
||||
x: _backgroundX + _backgroundWidth / 2 - 115,
|
||||
y: _backgroundY + _bigButtonsY + 120,
|
||||
width: 230, height: 36
|
||||
},
|
||||
imageURL: pathToAssets + "overlay-images/male-button-selected.png",
|
||||
alpha: 1, visible: false
|
||||
});
|
||||
_buttonOverlays.push(_maleButtonSelected);
|
||||
|
||||
var _armsFreeButton = Overlays.addOverlay("image", {
|
||||
bounds: {
|
||||
x: _backgroundX + _backgroundWidth / 2 - 115,
|
||||
y: _backgroundY + _bigButtonsY + 180,
|
||||
width: 230, height: 36
|
||||
},
|
||||
imageURL: pathToAssets + "overlay-images/arms-free-button.png",
|
||||
alpha: 1, visible: false
|
||||
});
|
||||
_buttonOverlays.push(_armsFreeButton);
|
||||
|
||||
var _armsFreeButtonSelected = Overlays.addOverlay("image", {
|
||||
bounds: {
|
||||
x: _backgroundX + _backgroundWidth / 2 - 115,
|
||||
y: _backgroundY + _bigButtonsY + 180,
|
||||
width: 230, height: 36
|
||||
},
|
||||
imageURL: pathToAssets + "overlay-images/arms-free-button-selected.png",
|
||||
alpha: 1, visible: false
|
||||
});
|
||||
_buttonOverlays.push(_armsFreeButtonSelected);
|
||||
|
||||
var _footstepsButton = Overlays.addOverlay("image", {
|
||||
bounds: {
|
||||
x: _backgroundX + _backgroundWidth / 2 - 115,
|
||||
y: _backgroundY + _bigButtonsY + 240,
|
||||
width: 230, height: 36
|
||||
},
|
||||
imageURL: pathToAssets + "overlay-images/footstep-sounds-button.png",
|
||||
alpha: 1, visible: false
|
||||
});
|
||||
_buttonOverlays.push(_footstepsButton);
|
||||
|
||||
var _footstepsButtonSelected = Overlays.addOverlay("image", {
|
||||
bounds: {
|
||||
x: _backgroundX + _backgroundWidth / 2 - 115,
|
||||
y: _backgroundY + _bigButtonsY + 240,
|
||||
width: 230, height: 36
|
||||
},
|
||||
imageURL: pathToAssets + "overlay-images/footstep-sounds-button-selected.png",
|
||||
alpha: 1, visible: false
|
||||
});
|
||||
_buttonOverlays.push(_footstepsButtonSelected);
|
||||
|
||||
|
||||
function minimiseDialog(minimise) {
|
||||
|
||||
Overlays.editOverlay(_controlsBackground, {visible: !minimise});
|
||||
Overlays.editOverlay(_controlsMinimisedTab, {visible: minimise});
|
||||
Overlays.editOverlay(_controlsMinimiseButton, {visible: !minimise});
|
||||
|
||||
if(_state.powerOn) {
|
||||
|
||||
Overlays.editOverlay(_onButton, {visible: !minimise});
|
||||
Overlays.editOverlay(_offButton, {visible: false});
|
||||
|
||||
} else {
|
||||
|
||||
Overlays.editOverlay(_onButton, {visible: false});
|
||||
Overlays.editOverlay(_offButton, {visible: !minimise});
|
||||
|
||||
}
|
||||
if (_motion.avatarGender === FEMALE) {
|
||||
|
||||
Overlays.editOverlay(_femaleButtonSelected, {visible: !minimise});
|
||||
Overlays.editOverlay(_femaleButton, {visible: false});
|
||||
Overlays.editOverlay(_maleButtonSelected, {visible: false});
|
||||
Overlays.editOverlay(_maleButton, {visible: !minimise});
|
||||
|
||||
} else {
|
||||
|
||||
Overlays.editOverlay(_femaleButtonSelected, {visible: false});
|
||||
Overlays.editOverlay(_femaleButton, {visible: !minimise});
|
||||
Overlays.editOverlay(_maleButtonSelected, {visible: !minimise});
|
||||
Overlays.editOverlay(_maleButton, {visible: false});
|
||||
}
|
||||
if (_motion.armsFree) {
|
||||
|
||||
Overlays.editOverlay(_armsFreeButtonSelected, {visible: !minimise});
|
||||
Overlays.editOverlay(_armsFreeButton, {visible: false});
|
||||
|
||||
} else {
|
||||
|
||||
Overlays.editOverlay(_armsFreeButtonSelected, {visible: false});
|
||||
Overlays.editOverlay(_armsFreeButton, {visible: !minimise});
|
||||
}
|
||||
if (_motion.makesFootStepSounds) {
|
||||
|
||||
Overlays.editOverlay(_footstepsButtonSelected, {visible: !minimise});
|
||||
Overlays.editOverlay(_footstepsButton, {visible: false});
|
||||
|
||||
} else {
|
||||
|
||||
Overlays.editOverlay(_footstepsButtonSelected, {visible: false});
|
||||
Overlays.editOverlay(_footstepsButton, {visible: !minimise});
|
||||
}
|
||||
};
|
||||
|
||||
// mouse event handler
|
||||
function mousePressEvent(event) {
|
||||
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
||||
|
||||
switch (clickedOverlay) {
|
||||
|
||||
case _controlsMinimiseButton:
|
||||
|
||||
minimiseDialog(true);
|
||||
_state.setInternalState(_state.STANDING);
|
||||
return;
|
||||
|
||||
case _controlsMinimisedTab:
|
||||
|
||||
minimiseDialog(false);
|
||||
_state.setInternalState(_state.STANDING);
|
||||
return;
|
||||
|
||||
case _onButton:
|
||||
|
||||
_state.powerOn = false;
|
||||
Overlays.editOverlay(_offButton, {visible: true});
|
||||
Overlays.editOverlay(_onButton, {visible: false});
|
||||
_state.setInternalState(state.STANDING);
|
||||
return;
|
||||
|
||||
case _offButton:
|
||||
|
||||
_state.powerOn = true;
|
||||
Overlays.editOverlay(_offButton, {visible: false});
|
||||
Overlays.editOverlay(_onButton, {visible: true});
|
||||
_state.setInternalState(state.STANDING);
|
||||
return;
|
||||
|
||||
|
||||
case _footstepsButton:
|
||||
|
||||
_motion.makesFootStepSounds = true;
|
||||
Overlays.editOverlay(_footstepsButtonSelected, {visible: true});
|
||||
Overlays.editOverlay(_footstepsButton, {visible: false});
|
||||
return;
|
||||
|
||||
case _footstepsButtonSelected:
|
||||
|
||||
_motion.makesFootStepSounds = false;
|
||||
Overlays.editOverlay(_footstepsButton, {visible: true});
|
||||
Overlays.editOverlay(_footstepsButtonSelected, {visible: false});
|
||||
return;
|
||||
|
||||
case _femaleButton:
|
||||
case _maleButtonSelected:
|
||||
|
||||
_motion.setGender(FEMALE);
|
||||
Overlays.editOverlay(_femaleButtonSelected, {visible: true});
|
||||
Overlays.editOverlay(_femaleButton, {visible: false});
|
||||
Overlays.editOverlay(_maleButton, {visible: true});
|
||||
Overlays.editOverlay(_maleButtonSelected, {visible: false});
|
||||
return;
|
||||
|
||||
case _maleButton:
|
||||
case _femaleButtonSelected:
|
||||
|
||||
_motion.setGender(MALE);
|
||||
Overlays.editOverlay(_femaleButton, {visible: true});
|
||||
Overlays.editOverlay(_femaleButtonSelected, {visible: false});
|
||||
Overlays.editOverlay(_maleButtonSelected, {visible: true});
|
||||
Overlays.editOverlay(_maleButton, {visible: false});
|
||||
return;
|
||||
|
||||
case _armsFreeButton:
|
||||
|
||||
_motion.armsFree = true;
|
||||
Overlays.editOverlay(_armsFreeButtonSelected, {visible: true});
|
||||
Overlays.editOverlay(_armsFreeButton, {visible: false});
|
||||
return;
|
||||
|
||||
case _armsFreeButtonSelected:
|
||||
|
||||
_motion.armsFree = false;
|
||||
_motion.poseFingers();
|
||||
Overlays.editOverlay(_armsFreeButtonSelected, {visible: false});
|
||||
Overlays.editOverlay(_armsFreeButton, {visible: true});
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
|
||||
// delete overlays on script ending
|
||||
Script.scriptEnding.connect(function() {
|
||||
|
||||
// delete overlays
|
||||
Overlays.deleteOverlay(_controlsBackground);
|
||||
Overlays.deleteOverlay(_controlsMinimisedTab);
|
||||
for (var i in _buttonOverlays) {
|
||||
Overlays.deleteOverlay(_buttonOverlays[i]);
|
||||
}
|
||||
});
|
||||
|
||||
// public method
|
||||
return {
|
||||
|
||||
// gather references to objects from the walk.js script
|
||||
initialise: function(state, motion, walkAssets) {
|
||||
|
||||
_state = state;
|
||||
_motion = motion;
|
||||
_walkAssets = walkAssets;
|
||||
}
|
||||
|
||||
}; // end public methods (return)
|
||||
|
||||
})();
|
97
examples/libraries/walkSettings.js
Normal file
|
@ -0,0 +1,97 @@
|
|||
//
|
||||
// walkSettings.js
|
||||
// version 0.1
|
||||
//
|
||||
// Created by David Wooldridge, June 2015
|
||||
// Copyright © 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Presents settings for walk.js
|
||||
//
|
||||
// Editing tools for animation data files available here: https://github.com/DaveDubUK/walkTools
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
WalkSettings = function() {
|
||||
var _visible = false;
|
||||
var _innerWidth = Window.innerWidth;
|
||||
const MARGIN_RIGHT = 58;
|
||||
const MARGIN_TOP = 145;
|
||||
const ICON_SIZE = 50;
|
||||
const ICON_ALPHA = 0.9;
|
||||
|
||||
var minimisedTab = Overlays.addOverlay("image", {
|
||||
x: _innerWidth - MARGIN_RIGHT, y: Window.innerHeight - MARGIN_TOP,
|
||||
width: ICON_SIZE, height: ICON_SIZE,
|
||||
imageURL: pathToAssets + 'overlay-images/ddpa-minimised-ddpa-tab.png',
|
||||
visible: true, alpha: ICON_ALPHA
|
||||
});
|
||||
|
||||
function mousePressEvent(event) {
|
||||
if (Overlays.getOverlayAtPoint(event) === minimisedTab) {
|
||||
_visible = !_visible;
|
||||
_webWindow.setVisible(_visible);
|
||||
}
|
||||
}
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
|
||||
Script.update.connect(function(deltaTime) {
|
||||
if (window.innerWidth !== _innerWidth) {
|
||||
_innerWidth = window.innerWidth;
|
||||
Overlays.EditOverlay(minimisedTab, {x: _innerWidth - MARGIN_RIGHT});
|
||||
}
|
||||
});
|
||||
|
||||
function cleanup() {
|
||||
Overlays.deleteOverlay(minimisedTab);
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
|
||||
var _shift = false;
|
||||
function keyPressEvent(event) {
|
||||
if (event.text === "SHIFT") {
|
||||
_shift = true;
|
||||
}
|
||||
if (_shift && (event.text === 'o' || event.text === 'O')) {
|
||||
_visible = !_visible;
|
||||
_webWindow.setVisible(_visible);
|
||||
}
|
||||
}
|
||||
function keyReleaseEvent(event) {
|
||||
if (event.text === "SHIFT") {
|
||||
_shift = false;
|
||||
}
|
||||
}
|
||||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||
|
||||
// web window
|
||||
const PANEL_WIDTH = 200;
|
||||
const PANEL_HEIGHT = 180;
|
||||
var _url = Script.resolvePath('html/walkSettings.html');
|
||||
var _webWindow = new WebWindow('Walk Settings', _url, PANEL_WIDTH, PANEL_HEIGHT, false);
|
||||
_webWindow.setVisible(false);
|
||||
_webWindow.eventBridge.webEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
|
||||
if (data.type == "init") {
|
||||
// send the current settings to the window
|
||||
_webWindow.eventBridge.emitScriptEvent(JSON.stringify({
|
||||
type: "update",
|
||||
armsFree: avatar.armsFree,
|
||||
makesFootStepSounds: avatar.makesFootStepSounds,
|
||||
blenderPreRotations: avatar.blenderPreRotations
|
||||
}));
|
||||
} else if (data.type == "powerToggle") {
|
||||
motion.isLive = !motion.isLive;
|
||||
} else if (data.type == "update") {
|
||||
// receive settings from the window
|
||||
avatar.armsFree = data.armsFree;
|
||||
avatar.makesFootStepSounds = data.makesFootStepSounds;
|
||||
avatar.blenderPreRotations = data.blenderPreRotations;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
walkSettings = WalkSettings();
|
|
@ -38,7 +38,7 @@ var mouseLook = (function () {
|
|||
keyboardID = 0;
|
||||
|
||||
function onKeyPressEvent(event) {
|
||||
if (event.text == 'm' && event.isMeta) {
|
||||
if (event.text == 'M') {
|
||||
active = !active;
|
||||
updateMapping();
|
||||
}
|
||||
|
|
1064
examples/walk.js
3
interface/resources/images/header_sep.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="624 233 250 8" width="250pt" height="8pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2015-06-22 17:35Z</dc:date><!-- Produced by OmniGraffle Professional 5.4.4 --></metadata><defs></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 1</title><g><title>No info</title><line x1="627" y1="236.4375" x2="871" y2="236.4375" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/></g></g></svg>
|
After Width: | Height: | Size: 715 B |
50
interface/resources/images/left-arrow-disabled.svg
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="133.1 714.2 21.3 33.4"
|
||||
enable-background="new 133.1 714.2 21.3 33.4"
|
||||
xml:space="preserve"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="left-arrow.svg"><metadata
|
||||
id="metadata13"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs11" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="775"
|
||||
id="namedview9"
|
||||
showgrid="false"
|
||||
inkscape:zoom="14.131736"
|
||||
inkscape:cx="12.772881"
|
||||
inkscape:cy="16.700001"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g5" /><g
|
||||
id="g3"
|
||||
transform="matrix(-1,0,0,1,287.5,0)"><g
|
||||
id="g5"><path
|
||||
d="m 133.1,714.2 21.3,16.7 -21.3,16.7 0,-33.4 z"
|
||||
id="path7"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#cccccc;fill-opacity:1" /></g></g></svg>
|
After Width: | Height: | Size: 1.8 KiB |
BIN
interface/resources/images/link.png
Normal file
After Width: | Height: | Size: 43 KiB |
3
interface/resources/images/no-picture-provided.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="618 289 264 186" width="22pc" height="186pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2015-06-22 17:35Z</dc:date><!-- Produced by OmniGraffle Professional 5.4.4 --></metadata><defs><font-face font-family="Helvetica" font-size="19" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="522.94922" cap-height="717.28516" ascent="770.01953" descent="-229.98047" font-weight="500"><font-face-src><font-face-name name="Helvetica"/></font-face-src></font-face></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 1</title><g><title>No info</title><path d="M 620 291 L 879.5 291 L 879.5 473 L 620 473 Z" stroke="#999" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1" stroke-dasharray="4,4"/><text transform="translate(625 370.5)" fill="#ccc"><tspan font-family="Helvetica" font-size="19" font-weight="500" fill="#ccc" x="40.265863" y="19" textLength="174.24707">No Picture Provided </tspan></text></g></g></svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns:xl="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="133.1 714.2 21.3 33.4"
|
||||
enable-background="new 133.1 714.2 21.3 33.4" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FF5353" d="M133.1,714.2l21.3,16.7l-21.3,16.7V714.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 501 B |
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns:xl="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="225.8 714.2 326.5 512"
|
||||
enable-background="new 225.8 714.2 326.5 512" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FF5353" d="M552.4,1226.2l-326.5-256l326.5-256V1226.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 503 B |
50
interface/resources/images/reload-script.svg
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 100 100"
|
||||
enable-background="new 0 0 100 100"
|
||||
xml:space="preserve"
|
||||
id="svg2"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="reload-script-43339.svg"><metadata
|
||||
id="metadata14"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs12" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1184"
|
||||
inkscape:window-height="655"
|
||||
id="namedview10"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.36"
|
||||
inkscape:cx="-12.5"
|
||||
inkscape:cy="56.355932"
|
||||
inkscape:window-x="424"
|
||||
inkscape:window-y="79"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2" /><g
|
||||
id="g4"
|
||||
style="fill:#c4c4c4;fill-opacity:1"
|
||||
transform="matrix(1.0520186,0,0,1.0809642,-4.9561957,-7.0141066)"><g
|
||||
id="g6"
|
||||
style="fill:#c4c4c4;fill-opacity:1"><path
|
||||
d="m 8.139,47.902 14.505,0 c 1.51,0 2.838,-0.987 3.28,-2.429 1.222,-4.042 3.425,-7.649 6.357,-10.583 4.643,-4.627 10.918,-7.442 17.982,-7.45 7.056,0.008 13.331,2.823 17.979,7.45 0.144,0.147 0.271,0.31 0.411,0.457 L 59.46,46.155 c -0.257,0.299 -0.313,0.724 -0.157,1.078 0.173,0.365 0.53,0.59 0.923,0.584 l 38.526,0.111 c 0.294,0.005 0.581,-0.129 0.771,-0.352 0.197,-0.231 0.278,-0.527 0.23,-0.818 L 93.483,8.741 C 93.421,8.353 93.137,8.038 92.753,7.933 92.375,7.828 91.968,7.952 91.714,8.248 L 82.256,19.366 C 73.983,11.441 62.706,6.512 50.337,6.491 50.279,6.488 50.206,6.488 50.122,6.491 37.396,6.527 25.801,11.73 17.469,20.08 11.119,26.417 6.604,34.634 4.776,43.81 c -0.198,1.013 0.062,2.046 0.715,2.843 0.655,0.793 1.617,1.249 2.648,1.249 z m 90.845,10.939 c -0.652,-0.798 -1.618,-1.259 -2.646,-1.259 l -14.506,0 c -1.507,0 -2.836,0.991 -3.279,2.435 -1.223,4.039 -3.427,7.649 -6.357,10.587 -4.64,4.622 -10.915,7.439 -17.982,7.45 -7.056,-0.011 -13.331,-2.828 -17.979,-7.45 -0.144,-0.146 -0.269,-0.32 -0.41,-0.464 l 9.196,-10.811 c 0.256,-0.294 0.311,-0.717 0.154,-1.076 -0.173,-0.356 -0.527,-0.587 -0.923,-0.585 L 5.727,57.561 c -0.294,0 -0.581,0.126 -0.773,0.352 -0.195,0.229 -0.277,0.524 -0.229,0.824 l 6.271,38.012 c 0.062,0.388 0.345,0.701 0.729,0.812 0.378,0.104 0.784,-0.025 1.039,-0.322 L 22.22,86.125 c 8.278,7.922 19.553,12.859 31.921,12.87 0.06,0.005 0.131,0.005 0.215,0 12.729,-0.032 24.323,-5.237 32.655,-13.583 6.348,-6.338 10.865,-14.561 12.69,-23.728 0.199,-1.012 -0.062,-2.045 -0.717,-2.843 z"
|
||||
id="path8"
|
||||
style="fill:#c4c4c4;fill-opacity:1"
|
||||
inkscape:connector-curvature="0" /></g></g></svg>
|
After Width: | Height: | Size: 3.2 KiB |
11
interface/resources/images/right-arrow-disabled.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns:xl="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="133.1 714.2 21.3 33.4"
|
||||
enable-background="new 133.1 714.2 21.3 33.4" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#CCCCCC" d="M133.1,714.2l21.3,16.7l-21.3,16.7V714.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 507 B |
3
interface/resources/images/tooltip_container.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="594 183 323 423" width="323pt" height="423pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2015-06-22 17:35Z</dc:date><!-- Produced by OmniGraffle Professional 5.4.4 --></metadata><defs></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 1</title><g><title>Info</title><path d="M 603 183 L 908 183 C 912.97056 183 917 187.02944 917 192 L 917 597 C 917 601.97056 912.97056 606 908 606 L 603 606 C 598.02944 606 594 601.97056 594 597 L 594 192 C 594 187.02944 598.02944 183 603 183 Z" fill="#333" fill-opacity=".67"/></g></g></svg>
|
After Width: | Height: | Size: 830 B |
|
@ -79,7 +79,7 @@ DialogContainer {
|
|||
Image {
|
||||
id: backArrow
|
||||
|
||||
source: addressBarDialog.backEnabled ? "../images/left-arrow.svg" : "../images/redarrow_reversed.svg"
|
||||
source: addressBarDialog.backEnabled ? "../images/left-arrow.svg" : "../images/left-arrow-disabled.svg"
|
||||
|
||||
anchors {
|
||||
fill: parent
|
||||
|
@ -101,7 +101,7 @@ DialogContainer {
|
|||
Image {
|
||||
id: forwardArrow
|
||||
|
||||
source: addressBarDialog.forwardEnabled ? "../images/right-arrow.svg" : "../images/redarrow.svg"
|
||||
source: addressBarDialog.forwardEnabled ? "../images/right-arrow.svg" : "../images/right-arrow-disabled.svg"
|
||||
|
||||
anchors {
|
||||
fill: parent
|
||||
|
|
|
@ -12,11 +12,6 @@ Item {
|
|||
implicitWidth: row.width
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
readonly property int sTATS_GENERAL_MIN_WIDTH: 165
|
||||
readonly property int sTATS_PING_MIN_WIDTH: 190
|
||||
readonly property int sTATS_GEO_MIN_WIDTH: 240
|
||||
readonly property int sTATS_OCTREE_MIN_WIDTH: 410
|
||||
readonly property int fontSize: 12
|
||||
readonly property string fontColor: "white"
|
||||
readonly property string bgColor: "#99333333"
|
||||
|
@ -37,7 +32,6 @@ Item {
|
|||
Column {
|
||||
id: generalCol
|
||||
spacing: 4; x: 4; y: 4;
|
||||
width: sTATS_GENERAL_MIN_WIDTH
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
|
@ -78,7 +72,6 @@ Item {
|
|||
Column {
|
||||
id: pingCol
|
||||
spacing: 4; x: 4; y: 4;
|
||||
width: sTATS_PING_MIN_WIDTH
|
||||
Text {
|
||||
color: root.fontColor
|
||||
font.pixelSize: root.fontSize
|
||||
|
@ -114,7 +107,6 @@ Item {
|
|||
Column {
|
||||
id: geoCol
|
||||
spacing: 4; x: 4; y: 4;
|
||||
width: sTATS_GEO_MIN_WIDTH
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
|
@ -157,7 +149,6 @@ Item {
|
|||
Column {
|
||||
id: octreeCol
|
||||
spacing: 4; x: 4; y: 4;
|
||||
width: sTATS_OCTREE_MIN_WIDTH
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
|
|
|
@ -1,31 +1,86 @@
|
|||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.3 as Original
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Layouts 1.1
|
||||
import "controls"
|
||||
import "styles"
|
||||
|
||||
Hifi.Tooltip {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
// FIXME adjust position based on the edges of the screen
|
||||
x: (lastMousePosition.x > surfaceSize.width/2) ? lastMousePosition.x - 140 : lastMousePosition.x + 20
|
||||
//y: lastMousePosition.y + 5
|
||||
y: (lastMousePosition.y > surfaceSize.height/2) ? lastMousePosition.y - 70 : lastMousePosition.y + 5
|
||||
implicitWidth: border.implicitWidth
|
||||
implicitHeight: border.implicitHeight
|
||||
x: lastMousePosition.x + offsetX
|
||||
y: lastMousePosition.y + offsetY
|
||||
property int offsetX: 0
|
||||
property int offsetY: 0
|
||||
width: border.width
|
||||
height: border.height
|
||||
|
||||
Border {
|
||||
Component.onCompleted: {
|
||||
offsetX = (lastMousePosition.x > surfaceSize.width/2) ? -root.width : 0
|
||||
offsetY = (lastMousePosition.y > surfaceSize.height/2) ? -root.height : 0
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: border
|
||||
anchors.fill: parent
|
||||
implicitWidth: text.implicitWidth
|
||||
implicitHeight: Math.max(text.implicitHeight, 64)
|
||||
color: "#7f000000"
|
||||
width: 322
|
||||
height: col.height + hifi.layout.spacing * 2
|
||||
|
||||
Text {
|
||||
id: text
|
||||
anchors.fill: parent
|
||||
anchors.margins: 16
|
||||
font.pixelSize: hifi.fonts.pixelSize / 2
|
||||
text: root.text
|
||||
wrapMode: Original.Text.WordWrap
|
||||
Column {
|
||||
id: col
|
||||
x: hifi.layout.spacing
|
||||
y: hifi.layout.spacing
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: hifi.layout.spacing
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: hifi.layout.spacing
|
||||
spacing: 5
|
||||
|
||||
Text {
|
||||
id: textPlace
|
||||
color: "white"
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
font.pixelSize: hifi.fonts.pixelSize * 2
|
||||
text: root.title
|
||||
wrapMode: Text.WrapAnywhere
|
||||
|
||||
/* Uncomment for debugging to see the extent of the
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#7fff00ff"
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: seperator
|
||||
color: "white"
|
||||
width: col.width
|
||||
height: hifi.layout.spacing / 3
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
}
|
||||
|
||||
Image {
|
||||
id: tooltipPic
|
||||
source: root.imageURL
|
||||
height: 180
|
||||
width: 320
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
verticalAlignment: Image.AlignVCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
id: textDescription
|
||||
color: "white"
|
||||
width: border.implicitWidth
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: root.description
|
||||
font.pixelSize: hifi.fonts.pixelSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -604,6 +604,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
_settingsTimer.setSingleShot(false);
|
||||
_settingsTimer.setInterval(SAVE_SETTINGS_INTERVAL);
|
||||
_settingsThread.start();
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::IndependentMode)) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true);
|
||||
cameraMenuChanged();
|
||||
}
|
||||
|
||||
_trayIcon->show();
|
||||
|
||||
|
@ -891,8 +896,11 @@ void Application::paintGL() {
|
|||
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
Menu::getInstance()->setIsOptionChecked("First Person", _myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN);
|
||||
Application::getInstance()->cameraMenuChanged();
|
||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, _myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN);
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !(_myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));
|
||||
Application::getInstance()->cameraMenuChanged();
|
||||
}
|
||||
|
||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||
// Always use the default eye position, not the actual head eye position.
|
||||
|
@ -984,7 +992,7 @@ void Application::paintGL() {
|
|||
glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo));
|
||||
glBlitFramebuffer(0, 0, _renderResolution.x, _renderResolution.y,
|
||||
0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height(),
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
||||
_compositor.displayOverlayTexture(&renderArgs);
|
||||
|
@ -1384,11 +1392,17 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
if (isShifted) {
|
||||
Menu::getInstance()->triggerOption(MenuOption::Mirror);
|
||||
} else {
|
||||
Menu::getInstance()->triggerOption(MenuOption::FullscreenMirror);
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, !Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror));
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true);
|
||||
}
|
||||
cameraMenuChanged();
|
||||
}
|
||||
break;
|
||||
case Qt::Key_P:
|
||||
Menu::getInstance()->triggerOption(MenuOption::FirstPerson);
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, !Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson));
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson));
|
||||
cameraMenuChanged();
|
||||
break;
|
||||
case Qt::Key_Slash:
|
||||
Menu::getInstance()->triggerOption(MenuOption::Stats);
|
||||
|
@ -2351,13 +2365,17 @@ void Application::cameraMenuChanged() {
|
|||
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
||||
_myAvatar->setBoomLength(MyAvatar::ZOOM_MIN);
|
||||
}
|
||||
} else {
|
||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::ThirdPerson)) {
|
||||
if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) {
|
||||
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
|
||||
if (_myAvatar->getBoomLength() == MyAvatar::ZOOM_MIN) {
|
||||
_myAvatar->setBoomLength(MyAvatar::ZOOM_DEFAULT);
|
||||
}
|
||||
}
|
||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::IndependentMode)) {
|
||||
if (_myCamera.getMode() != CAMERA_MODE_INDEPENDENT) {
|
||||
_myCamera.setMode(CAMERA_MODE_INDEPENDENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2451,20 +2469,22 @@ void Application::update(float deltaTime) {
|
|||
|
||||
// Transfer the user inputs to the driveKeys
|
||||
_myAvatar->clearDriveKeys();
|
||||
if (!_controllerScriptingInterface.areActionsCaptured()) {
|
||||
_myAvatar->setDriveKeys(FWD, _userInputMapper.getActionState(UserInputMapper::LONGITUDINAL_FORWARD));
|
||||
_myAvatar->setDriveKeys(BACK, _userInputMapper.getActionState(UserInputMapper::LONGITUDINAL_BACKWARD));
|
||||
_myAvatar->setDriveKeys(UP, _userInputMapper.getActionState(UserInputMapper::VERTICAL_UP));
|
||||
_myAvatar->setDriveKeys(DOWN, _userInputMapper.getActionState(UserInputMapper::VERTICAL_DOWN));
|
||||
_myAvatar->setDriveKeys(LEFT, _userInputMapper.getActionState(UserInputMapper::LATERAL_LEFT));
|
||||
_myAvatar->setDriveKeys(RIGHT, _userInputMapper.getActionState(UserInputMapper::LATERAL_RIGHT));
|
||||
_myAvatar->setDriveKeys(ROT_UP, _userInputMapper.getActionState(UserInputMapper::PITCH_UP));
|
||||
_myAvatar->setDriveKeys(ROT_DOWN, _userInputMapper.getActionState(UserInputMapper::PITCH_DOWN));
|
||||
_myAvatar->setDriveKeys(ROT_LEFT, _userInputMapper.getActionState(UserInputMapper::YAW_LEFT));
|
||||
_myAvatar->setDriveKeys(ROT_RIGHT, _userInputMapper.getActionState(UserInputMapper::YAW_RIGHT));
|
||||
if (_myCamera.getMode() != CAMERA_MODE_INDEPENDENT) {
|
||||
if (!_controllerScriptingInterface.areActionsCaptured()) {
|
||||
_myAvatar->setDriveKeys(FWD, _userInputMapper.getActionState(UserInputMapper::LONGITUDINAL_FORWARD));
|
||||
_myAvatar->setDriveKeys(BACK, _userInputMapper.getActionState(UserInputMapper::LONGITUDINAL_BACKWARD));
|
||||
_myAvatar->setDriveKeys(UP, _userInputMapper.getActionState(UserInputMapper::VERTICAL_UP));
|
||||
_myAvatar->setDriveKeys(DOWN, _userInputMapper.getActionState(UserInputMapper::VERTICAL_DOWN));
|
||||
_myAvatar->setDriveKeys(LEFT, _userInputMapper.getActionState(UserInputMapper::LATERAL_LEFT));
|
||||
_myAvatar->setDriveKeys(RIGHT, _userInputMapper.getActionState(UserInputMapper::LATERAL_RIGHT));
|
||||
_myAvatar->setDriveKeys(ROT_UP, _userInputMapper.getActionState(UserInputMapper::PITCH_UP));
|
||||
_myAvatar->setDriveKeys(ROT_DOWN, _userInputMapper.getActionState(UserInputMapper::PITCH_DOWN));
|
||||
_myAvatar->setDriveKeys(ROT_LEFT, _userInputMapper.getActionState(UserInputMapper::YAW_LEFT));
|
||||
_myAvatar->setDriveKeys(ROT_RIGHT, _userInputMapper.getActionState(UserInputMapper::YAW_RIGHT));
|
||||
}
|
||||
_myAvatar->setDriveKeys(BOOM_IN, _userInputMapper.getActionState(UserInputMapper::BOOM_IN));
|
||||
_myAvatar->setDriveKeys(BOOM_OUT, _userInputMapper.getActionState(UserInputMapper::BOOM_OUT));
|
||||
}
|
||||
_myAvatar->setDriveKeys(BOOM_IN, _userInputMapper.getActionState(UserInputMapper::BOOM_IN));
|
||||
_myAvatar->setDriveKeys(BOOM_OUT, _userInputMapper.getActionState(UserInputMapper::BOOM_OUT));
|
||||
|
||||
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
||||
|
||||
|
@ -2481,24 +2501,45 @@ void Application::update(float deltaTime) {
|
|||
|
||||
_entitySimulation.lock();
|
||||
_physicsEngine.deleteObjects(_entitySimulation.getObjectsToDelete());
|
||||
_entitySimulation.unlock();
|
||||
|
||||
_entities.getTree()->lockForWrite();
|
||||
_entitySimulation.lock();
|
||||
_physicsEngine.addObjects(_entitySimulation.getObjectsToAdd());
|
||||
_entitySimulation.unlock();
|
||||
_entities.getTree()->unlock();
|
||||
|
||||
_entities.getTree()->lockForWrite();
|
||||
_entitySimulation.lock();
|
||||
_physicsEngine.changeObjects(_entitySimulation.getObjectsToChange());
|
||||
_entitySimulation.unlock();
|
||||
_entities.getTree()->unlock();
|
||||
|
||||
_entitySimulation.lock();
|
||||
_entitySimulation.applyActionChanges();
|
||||
_entitySimulation.unlock();
|
||||
|
||||
|
||||
AvatarManager* avatarManager = DependencyManager::get<AvatarManager>().data();
|
||||
_physicsEngine.deleteObjects(avatarManager->getObjectsToDelete());
|
||||
_physicsEngine.addObjects(avatarManager->getObjectsToAdd());
|
||||
_physicsEngine.changeObjects(avatarManager->getObjectsToChange());
|
||||
|
||||
_entities.getTree()->lockForWrite();
|
||||
_physicsEngine.stepSimulation();
|
||||
_entities.getTree()->unlock();
|
||||
|
||||
if (_physicsEngine.hasOutgoingChanges()) {
|
||||
_entities.getTree()->lockForWrite();
|
||||
_entitySimulation.lock();
|
||||
_entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges(), _physicsEngine.getSessionID());
|
||||
_entitySimulation.unlock();
|
||||
_entities.getTree()->unlock();
|
||||
|
||||
_entities.getTree()->lockForWrite();
|
||||
avatarManager->handleOutgoingChanges(_physicsEngine.getOutgoingChanges());
|
||||
_entities.getTree()->unlock();
|
||||
|
||||
auto collisionEvents = _physicsEngine.getCollisionEvents();
|
||||
avatarManager->handleCollisionEvents(collisionEvents);
|
||||
|
||||
|
@ -3306,6 +3347,11 @@ namespace render {
|
|||
|
||||
|
||||
void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly, bool billboard) {
|
||||
|
||||
// FIXME: This preRender call is temporary until we create a separate render::scene for the mirror rendering.
|
||||
// Then we can move this logic into the Avatar::simulate call.
|
||||
_myAvatar->preRender(renderArgs);
|
||||
|
||||
activeRenderingThread = QThread::currentThread();
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
PerformanceTimer perfTimer("display");
|
||||
|
@ -4007,6 +4053,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
connect(scriptEngine, SIGNAL(finished(const QString&)), this, SLOT(scriptFinished(const QString&)));
|
||||
|
||||
connect(scriptEngine, SIGNAL(loadScript(const QString&, bool)), this, SLOT(loadScript(const QString&, bool)));
|
||||
connect(scriptEngine, SIGNAL(reloadScript(const QString&, bool)), this, SLOT(reloadScript(const QString&, bool)));
|
||||
|
||||
scriptEngine->registerGlobalObject("Overlays", &_overlays);
|
||||
qScriptRegisterMetaType(scriptEngine, OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue);
|
||||
|
@ -4222,7 +4269,7 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
|||
}
|
||||
|
||||
ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded,
|
||||
bool loadScriptFromEditor, bool activateMainWindow) {
|
||||
bool loadScriptFromEditor, bool activateMainWindow, bool reload) {
|
||||
|
||||
if (isAboutToQuit()) {
|
||||
return NULL;
|
||||
|
@ -4251,7 +4298,7 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
|
|||
connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &Application::handleScriptLoadError);
|
||||
|
||||
// get the script engine object to load the script at the designated script URL
|
||||
scriptEngine->loadURL(scriptUrl);
|
||||
scriptEngine->loadURL(scriptUrl, reload);
|
||||
}
|
||||
|
||||
// restore the main window's active state
|
||||
|
@ -4262,6 +4309,10 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
|
|||
return scriptEngine;
|
||||
}
|
||||
|
||||
void Application::reloadScript(const QString& scriptName, bool isUserLoaded) {
|
||||
loadScript(scriptName, isUserLoaded, false, false, true);
|
||||
}
|
||||
|
||||
void Application::handleScriptEngineLoaded(const QString& scriptFilename) {
|
||||
ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender());
|
||||
|
||||
|
@ -4289,14 +4340,25 @@ void Application::scriptFinished(const QString& scriptName) {
|
|||
}
|
||||
|
||||
void Application::stopAllScripts(bool restart) {
|
||||
// stops all current running scripts
|
||||
if (restart) {
|
||||
// Delete all running scripts from cache so that they are re-downloaded when they are restarted
|
||||
auto scriptCache = DependencyManager::get<ScriptCache>();
|
||||
for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
|
||||
it != _scriptEnginesHash.constEnd(); it++) {
|
||||
if (!it.value()->isFinished()) {
|
||||
scriptCache->deleteScript(it.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop and possibly restart all currently running scripts
|
||||
for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
|
||||
it != _scriptEnginesHash.constEnd(); it++) {
|
||||
if (it.value()->isFinished()) {
|
||||
continue;
|
||||
}
|
||||
if (restart && it.value()->isUserLoaded()) {
|
||||
connect(it.value(), SIGNAL(finished(const QString&)), SLOT(loadScript(const QString&)));
|
||||
connect(it.value(), SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&)));
|
||||
}
|
||||
it.value()->stop();
|
||||
qCDebug(interfaceapp) << "stopping script..." << it.key();
|
||||
|
@ -4304,13 +4366,20 @@ void Application::stopAllScripts(bool restart) {
|
|||
// HACK: ATM scripts cannot set/get their animation priorities, so we clear priorities
|
||||
// whenever a script stops in case it happened to have been setting joint rotations.
|
||||
// TODO: expose animation priorities and provide a layered animation control system.
|
||||
_myAvatar->clearJointAnimationPriorities();
|
||||
_myAvatar->clearScriptableSettings();
|
||||
}
|
||||
|
||||
void Application::stopScript(const QString &scriptName) {
|
||||
void Application::stopScript(const QString &scriptName, bool restart) {
|
||||
const QString& scriptURLString = QUrl(scriptName).toString();
|
||||
if (_scriptEnginesHash.contains(scriptURLString)) {
|
||||
_scriptEnginesHash.value(scriptURLString)->stop();
|
||||
ScriptEngine* scriptEngine = _scriptEnginesHash[scriptURLString];
|
||||
if (restart) {
|
||||
auto scriptCache = DependencyManager::get<ScriptCache>();
|
||||
scriptCache->deleteScript(scriptName);
|
||||
connect(scriptEngine, SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&)));
|
||||
}
|
||||
scriptEngine->stop();
|
||||
qCDebug(interfaceapp) << "stopping script..." << scriptName;
|
||||
// HACK: ATM scripts cannot set/get their animation priorities, so we clear priorities
|
||||
// whenever a script stops in case it happened to have been setting joint rotations.
|
||||
|
@ -4326,6 +4395,10 @@ void Application::reloadAllScripts() {
|
|||
stopAllScripts(true);
|
||||
}
|
||||
|
||||
void Application::reloadOneScript(const QString& scriptName) {
|
||||
stopScript(scriptName, true);
|
||||
}
|
||||
|
||||
void Application::loadDefaultScripts() {
|
||||
if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) {
|
||||
loadScript(DEFAULT_SCRIPTS_JS_URL);
|
||||
|
|
|
@ -409,15 +409,19 @@ public slots:
|
|||
bool acceptSnapshot(const QString& urlString);
|
||||
bool askToSetAvatarUrl(const QString& url);
|
||||
bool askToLoadScript(const QString& scriptFilenameOrURL);
|
||||
|
||||
ScriptEngine* loadScript(const QString& scriptFilename = QString(), bool isUserLoaded = true,
|
||||
bool loadScriptFromEditor = false, bool activateMainWindow = false);
|
||||
bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false);
|
||||
void reloadScript(const QString& scriptName, bool isUserLoaded = true);
|
||||
void scriptFinished(const QString& scriptName);
|
||||
void stopAllScripts(bool restart = false);
|
||||
void stopScript(const QString& scriptName);
|
||||
void stopScript(const QString& scriptName, bool restart = false);
|
||||
void reloadAllScripts();
|
||||
void reloadOneScript(const QString& scriptName);
|
||||
void loadDefaultScripts();
|
||||
void toggleRunningScriptsWidget();
|
||||
void saveScripts();
|
||||
|
||||
void showFriendsWindow();
|
||||
void friendsWindowClosed();
|
||||
|
||||
|
@ -444,6 +448,8 @@ public slots:
|
|||
void notifyPacketVersionMismatch();
|
||||
|
||||
void domainConnectionDenied(const QString& reason);
|
||||
|
||||
void cameraMenuChanged();
|
||||
|
||||
private slots:
|
||||
void clearDomainOctreeDetails();
|
||||
|
@ -460,7 +466,7 @@ private slots:
|
|||
void setFullscreen(bool fullscreen);
|
||||
void setEnable3DTVMode(bool enable3DTVMode);
|
||||
void setEnableVRMode(bool enableVRMode);
|
||||
void cameraMenuChanged();
|
||||
|
||||
void rotationModeChanged();
|
||||
|
||||
glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint);
|
||||
|
|
|
@ -87,24 +87,26 @@ PickRay Camera::computePickRay(float x, float y) {
|
|||
|
||||
void Camera::setModeString(const QString& mode) {
|
||||
CameraMode targetMode = stringToMode(mode);
|
||||
|
||||
|
||||
switch (targetMode) {
|
||||
case CAMERA_MODE_FIRST_PERSON:
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, true);
|
||||
break;
|
||||
case CAMERA_MODE_THIRD_PERSON:
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, false);
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, false);
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true);
|
||||
break;
|
||||
case CAMERA_MODE_MIRROR:
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, true);
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, false);
|
||||
break;
|
||||
case CAMERA_MODE_INDEPENDENT:
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, false);
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, false);
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::IndependentMode, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
qApp->cameraMenuChanged();
|
||||
|
||||
if (_mode != targetMode) {
|
||||
setMode(targetMode);
|
||||
}
|
||||
|
|
|
@ -268,9 +268,22 @@ Menu::Menu() {
|
|||
qApp,
|
||||
SLOT(setFullscreen(bool)));
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson,
|
||||
0, // QML Qt::Key_P,
|
||||
true, qApp, SLOT(cameraMenuChanged()));
|
||||
MenuWrapper* cameraModeMenu = viewMenu->addMenu("Camera Mode");
|
||||
QActionGroup* cameraModeGroup = new QActionGroup(cameraModeMenu);
|
||||
cameraModeGroup->setExclusive(true);
|
||||
cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(cameraModeMenu,
|
||||
MenuOption::FirstPerson, 0, // QML Qt:: Key_P
|
||||
false, qApp, SLOT(cameraMenuChanged())));
|
||||
cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(cameraModeMenu,
|
||||
MenuOption::ThirdPerson, 0,
|
||||
true, qApp, SLOT(cameraMenuChanged())));
|
||||
cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(cameraModeMenu,
|
||||
MenuOption::IndependentMode, 0,
|
||||
false, qApp, SLOT(cameraMenuChanged())));
|
||||
cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(cameraModeMenu,
|
||||
MenuOption::FullscreenMirror, 0, // QML Qt::Key_H,
|
||||
false, qApp, SLOT(cameraMenuChanged())));
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror,
|
||||
0, //QML Qt::SHIFT | Qt::Key_H,
|
||||
true);
|
||||
|
|
|
@ -158,6 +158,7 @@ namespace MenuOption {
|
|||
const QString CascadedShadows = "Cascaded";
|
||||
const QString CachesSize = "RAM Caches Size";
|
||||
const QString CalibrateCamera = "Calibrate Camera";
|
||||
const QString CenterPlayerInView = "Center Player In View";
|
||||
const QString Chat = "Chat...";
|
||||
const QString Collisions = "Collisions";
|
||||
const QString Console = "Console...";
|
||||
|
@ -199,11 +200,10 @@ namespace MenuOption {
|
|||
const QString FrameTimer = "Show Timer";
|
||||
const QString Fullscreen = "Fullscreen";
|
||||
const QString FullscreenMirror = "Fullscreen Mirror";
|
||||
const QString CenterPlayerInView = "Center Player In View";
|
||||
const QString GlowWhenSpeaking = "Glow When Speaking";
|
||||
const QString NamesAboveHeads = "Names Above Heads";
|
||||
const QString HMDTools = "HMD Tools";
|
||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||
const QString IndependentMode = "Independent Mode";
|
||||
const QString KeyboardMotorControl = "Enable Keyboard Motor Control";
|
||||
const QString LeapMotionOnHMD = "Leap Motion on HMD";
|
||||
const QString LoadScript = "Open and Run Script File...";
|
||||
|
@ -217,6 +217,7 @@ namespace MenuOption {
|
|||
const QString MuteAudio = "Mute Microphone";
|
||||
const QString MuteEnvironment = "Mute Environment";
|
||||
const QString MuteFaceTracking = "Mute Face Tracking";
|
||||
const QString NamesAboveHeads = "Names Above Heads";
|
||||
const QString NoFaceTracking = "None";
|
||||
const QString OctreeStats = "Entity Statistics";
|
||||
const QString OnlyDisplayTopTen = "Only Display Top Ten";
|
||||
|
@ -277,6 +278,7 @@ namespace MenuOption {
|
|||
const QString StopAllScripts = "Stop All Scripts";
|
||||
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
||||
const QString TestPing = "Test Ping";
|
||||
const QString ThirdPerson = "Third Person";
|
||||
const QString ToolWindow = "Tool Window";
|
||||
const QString TransmitterDrive = "Transmitter Drive";
|
||||
const QString TurnWithHead = "Turn using Head";
|
||||
|
|
|
@ -445,10 +445,10 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo
|
|||
_skeletonModel.renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
|
||||
if (renderHead && shouldRenderHead(renderArgs, cameraPosition)) {
|
||||
if (renderHead && shouldRenderHead(renderArgs)) {
|
||||
getHead()->getFaceModel().renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
if (renderBounding && shouldRenderHead(renderArgs, cameraPosition)) {
|
||||
if (renderBounding && shouldRenderHead(renderArgs)) {
|
||||
_skeletonModel.renderBoundingCollisionShapes(0.7f);
|
||||
}
|
||||
|
||||
|
@ -533,6 +533,7 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
|||
}
|
||||
|
||||
void Avatar::fixupModelsInScene() {
|
||||
|
||||
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
||||
// fix them up in the scene
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
|
@ -581,7 +582,7 @@ void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool
|
|||
getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting);
|
||||
}
|
||||
|
||||
bool Avatar::shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const {
|
||||
bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ protected:
|
|||
Transform calculateDisplayNameTransform(const ViewFrustum& frustum, float fontSize) const;
|
||||
void renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum) const;
|
||||
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel = 0.0f);
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const;
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
|
||||
virtual void fixupModelsInScene();
|
||||
|
||||
void simulateAttachments(float deltaTime);
|
||||
|
|
|
@ -13,14 +13,14 @@
|
|||
|
||||
#include <QScriptEngine>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdouble-promotion"
|
||||
#endif
|
||||
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
@ -74,19 +74,19 @@ void AvatarManager::init() {
|
|||
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
render::PendingChanges pendingChanges;
|
||||
_myAvatar->addToScene(_myAvatar, scene, pendingChanges);
|
||||
_myAvatar->addToScene(_myAvatar, scene, pendingChanges);
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
}
|
||||
|
||||
void AvatarManager::updateMyAvatar(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()");
|
||||
|
||||
|
||||
_myAvatar->update(deltaTime);
|
||||
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
quint64 dt = now - _lastSendAvatarDataTime;
|
||||
|
||||
|
||||
if (dt > MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS) {
|
||||
// send head/hand data to the avatar mixer and voxel server
|
||||
PerformanceTimer perfTimer("send");
|
||||
|
@ -103,12 +103,12 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
PerformanceWarning warn(showWarnings, "Application::updateAvatars()");
|
||||
|
||||
PerformanceTimer perfTimer("otherAvatars");
|
||||
|
||||
|
||||
// simulate avatars
|
||||
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||
while (avatarIterator != _avatarHash.end()) {
|
||||
auto avatar = std::dynamic_pointer_cast<Avatar>(avatarIterator.value());
|
||||
|
||||
|
||||
if (avatar == _myAvatar || !avatar->isInitialized()) {
|
||||
// DO NOT update _myAvatar! Its update has already been done earlier in the main loop.
|
||||
// DO NOT update or fade out uninitialized Avatars
|
||||
|
@ -122,17 +122,17 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
++avatarIterator;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// simulate avatar fades
|
||||
simulateAvatarFades(deltaTime);
|
||||
}
|
||||
|
||||
void AvatarManager::simulateAvatarFades(float deltaTime) {
|
||||
QVector<AvatarSharedPointer>::iterator fadingIterator = _avatarFades.begin();
|
||||
|
||||
|
||||
const float SHRINK_RATE = 0.9f;
|
||||
const float MIN_FADE_SCALE = 0.001f;
|
||||
|
||||
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
render::PendingChanges pendingChanges;
|
||||
while (fadingIterator != _avatarFades.end()) {
|
||||
|
@ -153,12 +153,12 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() {
|
|||
return AvatarSharedPointer(std::make_shared<Avatar>());
|
||||
}
|
||||
|
||||
// virtual
|
||||
// virtual
|
||||
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
auto avatar = std::dynamic_pointer_cast<Avatar>(AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer));
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
render::PendingChanges pendingChanges;
|
||||
avatar->addToScene(avatar, scene, pendingChanges);
|
||||
avatar->addToScene(avatar, scene, pendingChanges);
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
return avatar;
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ void AvatarManager::removeAvatarMotionState(AvatarSharedPointer avatar) {
|
|||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
// virtual
|
||||
void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
|
||||
AvatarHash::iterator avatarIterator = _avatarHash.find(sessionUUID);
|
||||
if (avatarIterator != _avatarHash.end()) {
|
||||
|
|
|
@ -128,20 +128,13 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
|||
const float AVERAGE_SACCADE_INTERVAL = 6.0f;
|
||||
const float MICROSACCADE_MAGNITUDE = 0.002f;
|
||||
const float SACCADE_MAGNITUDE = 0.04f;
|
||||
const float MAXIMUM_SACCADE_SPEED = 0.8f;
|
||||
|
||||
if (randFloat() < deltaTime / AVERAGE_MICROSACCADE_INTERVAL) {
|
||||
_saccadeTarget = MICROSACCADE_MAGNITUDE * randVector();
|
||||
} else if (randFloat() < deltaTime / AVERAGE_SACCADE_INTERVAL) {
|
||||
_saccadeTarget = SACCADE_MAGNITUDE * randVector();
|
||||
}
|
||||
|
||||
glm::vec3 saccadeDelta = (_saccadeTarget - _saccade) * 0.5f;
|
||||
float speed = glm::length(saccadeDelta) / deltaTime;
|
||||
if (speed > MAXIMUM_SACCADE_SPEED) {
|
||||
saccadeDelta = saccadeDelta * MAXIMUM_SACCADE_SPEED / speed;
|
||||
}
|
||||
_saccade += saccadeDelta;
|
||||
_saccade += (_saccadeTarget - _saccade) * 0.5f;
|
||||
|
||||
// Detect transition from talking to not; force blink after that and a delay
|
||||
bool forceBlink = false;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <GeometryUtil.h>
|
||||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <PathUtils.h>
|
||||
#include <PerfStat.h>
|
||||
#include <ShapeCollider.h>
|
||||
#include <SharedUtil.h>
|
||||
|
@ -96,8 +97,12 @@ MyAvatar::MyAvatar() :
|
|||
_feetTouchFloor(true),
|
||||
_isLookingAtLeftEye(true),
|
||||
_realWorldFieldOfView("realWorldFieldOfView",
|
||||
DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES)
|
||||
DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES),
|
||||
_firstPersonSkeletonModel(this),
|
||||
_prevShouldDrawHead(true)
|
||||
{
|
||||
_firstPersonSkeletonModel.setIsFirstPerson(true);
|
||||
|
||||
ShapeCollider::initDispatchTable();
|
||||
for (int i = 0; i < MAX_DRIVE_KEYS; i++) {
|
||||
_driveKeys[i] = 0.0f;
|
||||
|
@ -131,6 +136,7 @@ QByteArray MyAvatar::toByteArray() {
|
|||
|
||||
void MyAvatar::reset() {
|
||||
_skeletonModel.reset();
|
||||
_firstPersonSkeletonModel.reset();
|
||||
getHead()->reset();
|
||||
|
||||
_targetVelocity = glm::vec3(0.0f);
|
||||
|
@ -189,6 +195,7 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
{
|
||||
PerformanceTimer perfTimer("skeleton");
|
||||
_skeletonModel.simulate(deltaTime);
|
||||
_firstPersonSkeletonModel.simulate(deltaTime);
|
||||
}
|
||||
|
||||
if (!_skeletonModel.hasSkeleton()) {
|
||||
|
@ -986,16 +993,35 @@ QString MyAvatar::getModelDescription() const {
|
|||
}
|
||||
|
||||
void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) {
|
||||
|
||||
Avatar::setFaceModelURL(faceModelURL);
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
getHead()->getFaceModel().setVisibleInScene(_prevShouldDrawHead, scene);
|
||||
_billboardValid = false;
|
||||
}
|
||||
|
||||
void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||
|
||||
Avatar::setSkeletonModelURL(skeletonModelURL);
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
_billboardValid = false;
|
||||
|
||||
if (_useFullAvatar) {
|
||||
_skeletonModel.setVisibleInScene(_prevShouldDrawHead, scene);
|
||||
|
||||
const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst");
|
||||
_firstPersonSkeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar());
|
||||
_firstPersonSkeletonModel.setVisibleInScene(!_prevShouldDrawHead, scene);
|
||||
} else {
|
||||
_skeletonModel.setVisibleInScene(true, scene);
|
||||
|
||||
_firstPersonSkeletonModel.setVisibleInScene(false, scene);
|
||||
_firstPersonSkeletonModel.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) {
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "useFullAvatarURL", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(const QUrl&, fullAvatarURL),
|
||||
|
@ -1177,17 +1203,13 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, const g
|
|||
void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) {
|
||||
|
||||
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
return; // wait until both models are loaded
|
||||
return; // wait until all models are loaded
|
||||
}
|
||||
|
||||
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
||||
// fix them up in the scene
|
||||
fixupModelsInScene();
|
||||
|
||||
const glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition();
|
||||
|
||||
// Render head so long as the camera isn't inside it
|
||||
if (shouldRenderHead(renderArgs, cameraPos)) {
|
||||
if (shouldRenderHead(renderArgs)) {
|
||||
getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting);
|
||||
}
|
||||
if (postLighting) {
|
||||
|
@ -1195,12 +1217,51 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bo
|
|||
}
|
||||
}
|
||||
|
||||
void MyAvatar::setVisibleInSceneIfReady(Model* model, render::ScenePointer scene, bool visible) {
|
||||
if (model->isActive() && model->isRenderable()) {
|
||||
model->setVisibleInScene(visible, scene);
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::preRender(RenderArgs* renderArgs) {
|
||||
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
const bool shouldDrawHead = shouldRenderHead(renderArgs);
|
||||
|
||||
_skeletonModel.initWhenReady(scene);
|
||||
if (_useFullAvatar) {
|
||||
_firstPersonSkeletonModel.initWhenReady(scene);
|
||||
}
|
||||
|
||||
if (shouldDrawHead != _prevShouldDrawHead) {
|
||||
if (_useFullAvatar) {
|
||||
if (shouldDrawHead) {
|
||||
_skeletonModel.setVisibleInScene(true, scene);
|
||||
_firstPersonSkeletonModel.setVisibleInScene(false, scene);
|
||||
} else {
|
||||
_skeletonModel.setVisibleInScene(false, scene);
|
||||
_firstPersonSkeletonModel.setVisibleInScene(true, scene);
|
||||
}
|
||||
} else {
|
||||
getHead()->getFaceModel().setVisibleInScene(shouldDrawHead, scene);
|
||||
}
|
||||
|
||||
}
|
||||
_prevShouldDrawHead = shouldDrawHead;
|
||||
}
|
||||
|
||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
|
||||
|
||||
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const {
|
||||
bool MyAvatar::cameraInsideHead() const {
|
||||
const Head* head = getHead();
|
||||
return (renderArgs->_renderMode != RenderArgs::NORMAL_RENDER_MODE) || (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) ||
|
||||
(glm::length(cameraPosition - head->getEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale);
|
||||
const glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();
|
||||
return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * _scale);
|
||||
}
|
||||
|
||||
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
||||
return ((renderArgs->_renderMode != RenderArgs::DEFAULT_RENDER_MODE) ||
|
||||
(Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) ||
|
||||
!cameraInsideHead());
|
||||
}
|
||||
|
||||
void MyAvatar::updateOrientation(float deltaTime) {
|
||||
|
|
|
@ -35,11 +35,12 @@ public:
|
|||
void reset();
|
||||
void update(float deltaTime);
|
||||
void simulate(float deltaTime);
|
||||
void preRender(RenderArgs* renderArgs);
|
||||
void updateFromTrackers(float deltaTime);
|
||||
|
||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting = false) override;
|
||||
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel = 0.0f) override;
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const override;
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const override;
|
||||
void renderDebugBodyPoints();
|
||||
|
||||
// setters
|
||||
|
@ -206,10 +207,14 @@ signals:
|
|||
|
||||
private:
|
||||
|
||||
bool cameraInsideHead() const;
|
||||
|
||||
// These are made private for MyAvatar so that you will use the "use" methods instead
|
||||
virtual void setFaceModelURL(const QUrl& faceModelURL);
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||
|
||||
void setVisibleInSceneIfReady(Model* model, render::ScenePointer scene, bool visiblity);
|
||||
|
||||
glm::vec3 _gravity;
|
||||
|
||||
float _driveKeys[MAX_DRIVE_KEYS];
|
||||
|
@ -265,6 +270,10 @@ private:
|
|||
QString _headModelName;
|
||||
QString _bodyModelName;
|
||||
QString _fullAvatarModelName;
|
||||
|
||||
// used for rendering when in first person view or when in an HMD.
|
||||
SkeletonModel _firstPersonSkeletonModel;
|
||||
bool _prevShouldDrawHead;
|
||||
};
|
||||
|
||||
#endif // hifi_MyAvatar_h
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "Menu.h"
|
||||
#include "SkeletonModel.h"
|
||||
#include "Util.h"
|
||||
#include "InterfaceLogging.h"
|
||||
|
||||
enum StandingFootState {
|
||||
LEFT_FOOT,
|
||||
|
@ -38,7 +39,8 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) :
|
|||
_standingFoot(NO_FOOT),
|
||||
_standingOffset(0.0f),
|
||||
_clampedFootPosition(0.0f),
|
||||
_headClipDistance(DEFAULT_NEAR_CLIP)
|
||||
_headClipDistance(DEFAULT_NEAR_CLIP),
|
||||
_isFirstPerson(false)
|
||||
{
|
||||
assert(_owningAvatar);
|
||||
_enableShapes = true;
|
||||
|
@ -98,7 +100,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
|||
setRotation(_owningAvatar->getOrientation() * refOrientation);
|
||||
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale());
|
||||
setBlendshapeCoefficients(_owningAvatar->getHead()->getBlendshapeCoefficients());
|
||||
|
||||
|
||||
Model::simulate(deltaTime, fullUpdate);
|
||||
|
||||
if (!isActive() || !_owningAvatar->isMyAvatar()) {
|
||||
|
@ -140,6 +142,11 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
|||
applyPalmData(geometry.rightHandJointIndex, hand->getPalms()[rightPalmIndex]);
|
||||
}
|
||||
|
||||
if (_isFirstPerson) {
|
||||
cauterizeHead();
|
||||
updateClusterMatrices();
|
||||
}
|
||||
|
||||
_boundingShape.setTranslation(_translation + _rotation * _boundingShapeLocalOffset);
|
||||
_boundingShape.setRotation(_rotation);
|
||||
}
|
||||
|
@ -806,3 +813,57 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) {
|
|||
bool SkeletonModel::hasSkeleton() {
|
||||
return isActive() ? _geometry->getFBXGeometry().rootJointIndex != -1 : false;
|
||||
}
|
||||
|
||||
void SkeletonModel::initHeadBones() {
|
||||
_headBones.clear();
|
||||
const FBXGeometry& fbxGeometry = _geometry->getFBXGeometry();
|
||||
const int neckJointIndex = fbxGeometry.neckJointIndex;
|
||||
std::queue<int> q;
|
||||
q.push(neckJointIndex);
|
||||
_headBones.push_back(neckJointIndex);
|
||||
|
||||
// fbxJoints only hold links to parents not children, so we have to do a bit of extra work here.
|
||||
while (q.size() > 0) {
|
||||
int jointIndex = q.front();
|
||||
for (int i = 0; i < fbxGeometry.joints.size(); i++) {
|
||||
const FBXJoint& fbxJoint = fbxGeometry.joints[i];
|
||||
if (jointIndex == fbxJoint.parentIndex) {
|
||||
_headBones.push_back(i);
|
||||
q.push(i);
|
||||
}
|
||||
}
|
||||
q.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonModel::invalidateHeadBones() {
|
||||
_headBones.clear();
|
||||
}
|
||||
|
||||
void SkeletonModel::cauterizeHead() {
|
||||
if (isActive()) {
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const int neckJointIndex = geometry.neckJointIndex;
|
||||
if (neckJointIndex > 0 && neckJointIndex < _jointStates.size()) {
|
||||
|
||||
// lazy init of headBones
|
||||
if (_headBones.size() == 0) {
|
||||
initHeadBones();
|
||||
}
|
||||
|
||||
// preserve the translation for the neck
|
||||
glm::vec4 trans = _jointStates[neckJointIndex].getTransform()[3];
|
||||
glm::vec4 zero(0, 0, 0, 0);
|
||||
for (const int &i : _headBones) {
|
||||
JointState& joint = _jointStates[i];
|
||||
glm::mat4 newXform(zero, zero, zero, trans);
|
||||
joint.setTransform(newXform);
|
||||
joint.setVisibleTransform(newXform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonModel::onInvalidate() {
|
||||
invalidateHeadBones();
|
||||
}
|
||||
|
|
|
@ -112,6 +112,11 @@ public:
|
|||
|
||||
float getHeadClipDistance() const { return _headClipDistance; }
|
||||
|
||||
void setIsFirstPerson(bool value) { _isFirstPerson = value; }
|
||||
bool getIsFirstPerson() const { return _isFirstPerson; }
|
||||
|
||||
virtual void onInvalidate() override;
|
||||
|
||||
signals:
|
||||
|
||||
void skeletonLoaded();
|
||||
|
@ -132,7 +137,11 @@ protected:
|
|||
void maybeUpdateLeanRotation(const JointState& parentState, JointState& state);
|
||||
void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
|
||||
void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
|
||||
|
||||
|
||||
void cauterizeHead();
|
||||
void initHeadBones();
|
||||
void invalidateHeadBones();
|
||||
|
||||
private:
|
||||
|
||||
void renderJointConstraints(int jointIndex);
|
||||
|
@ -164,6 +173,9 @@ private:
|
|||
glm::vec3 _clampedFootPosition;
|
||||
|
||||
float _headClipDistance; // Near clip distance to use if no separate head model
|
||||
|
||||
bool _isFirstPerson;
|
||||
std::vector<int> _headBones;
|
||||
};
|
||||
|
||||
#endif // hifi_SkeletonModel_h
|
||||
|
|
|
@ -225,14 +225,14 @@ void KeyboardMouseDevice::assignDefaultInputMapping(UserInputMapper& mapper) {
|
|||
mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(Qt::Key_C), BUTTON_MOVE_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(Qt::Key_E), BUTTON_MOVE_SPEED);
|
||||
|
||||
mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(Qt::Key_W), makeInput(Qt::Key_Shift), BUTTON_BOOM_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(Qt::Key_S), makeInput(Qt::Key_Shift), BUTTON_BOOM_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(Qt::Key_E), makeInput(Qt::Key_Shift), BUTTON_BOOM_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(Qt::Key_C), makeInput(Qt::Key_Shift), BUTTON_BOOM_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(Qt::Key_A), makeInput(Qt::RightButton), BUTTON_YAW_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(Qt::Key_D), makeInput(Qt::RightButton), BUTTON_YAW_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(Qt::Key_A), makeInput(Qt::Key_Shift), BUTTON_YAW_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(Qt::Key_D), makeInput(Qt::Key_Shift), BUTTON_YAW_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::PITCH_DOWN, makeInput(Qt::Key_C), makeInput(Qt::Key_Shift), BUTTON_PITCH_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::PITCH_UP, makeInput(Qt::Key_E), makeInput(Qt::Key_Shift), BUTTON_PITCH_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::PITCH_DOWN, makeInput(Qt::Key_S), makeInput(Qt::Key_Shift), BUTTON_PITCH_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::PITCH_UP, makeInput(Qt::Key_W), makeInput(Qt::Key_Shift), BUTTON_PITCH_SPEED);
|
||||
|
||||
// Arrow keys mapping
|
||||
mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(Qt::Key_Down), BUTTON_MOVE_SPEED);
|
||||
|
@ -270,8 +270,8 @@ void KeyboardMouseDevice::assignDefaultInputMapping(UserInputMapper& mapper) {
|
|||
mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(TOUCH_AXIS_X_POS), TOUCH_YAW_SPEED);
|
||||
|
||||
// Wheel move
|
||||
mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(MOUSE_AXIS_WHEEL_Y_NEG), BUTTON_BOOM_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(MOUSE_AXIS_WHEEL_Y_POS), BUTTON_BOOM_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(MOUSE_AXIS_WHEEL_Y_POS), BUTTON_BOOM_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(MOUSE_AXIS_WHEEL_Y_NEG), BUTTON_BOOM_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(MOUSE_AXIS_WHEEL_X_NEG), BUTTON_YAW_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(MOUSE_AXIS_WHEEL_X_POS), BUTTON_YAW_SPEED);
|
||||
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
|
||||
#include <avatar/AvatarManager.h>
|
||||
#include <gpu/GLBackend.h>
|
||||
#include <CursorManager.h>
|
||||
#include <Tooltip.h>
|
||||
|
||||
#include "CursorManager.h"
|
||||
#include "Tooltip.h"
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
|
@ -117,7 +118,7 @@ ApplicationCompositor::ApplicationCompositor() {
|
|||
memset(_magSizeMult, 0, sizeof(_magSizeMult));
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
|
||||
_reticleQuad = geometryCache->allocateID();
|
||||
_magnifierQuad = geometryCache->allocateID();
|
||||
_magnifierBorder = geometryCache->allocateID();
|
||||
|
@ -128,11 +129,25 @@ ApplicationCompositor::ApplicationCompositor() {
|
|||
_hoverItemId = entityItemID;
|
||||
_hoverItemEnterUsecs = usecTimestampNow();
|
||||
auto properties = entityScriptingInterface->getEntityProperties(_hoverItemId);
|
||||
_hoverItemHref = properties.getHref();
|
||||
|
||||
// check the format of this href string before we parse it
|
||||
QString hrefString = properties.getHref();
|
||||
|
||||
auto cursor = Cursor::Manager::instance().getCursor();
|
||||
if (!_hoverItemHref.isEmpty()) {
|
||||
if (!hrefString.isEmpty()) {
|
||||
if (!hrefString.startsWith("hifi:")) {
|
||||
hrefString.prepend("hifi://");
|
||||
}
|
||||
|
||||
// parse out a QUrl from the hrefString
|
||||
QUrl href = QUrl(hrefString);
|
||||
|
||||
_hoverItemTitle = href.host();
|
||||
_hoverItemDescription = properties.getDescription();
|
||||
cursor->setIcon(Cursor::Icon::LINK);
|
||||
} else {
|
||||
_hoverItemTitle.clear();
|
||||
_hoverItemDescription.clear();
|
||||
cursor->setIcon(Cursor::Icon::DEFAULT);
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +156,10 @@ ApplicationCompositor::ApplicationCompositor() {
|
|||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, [=](const EntityItemID& entityItemID, const MouseEvent& event) {
|
||||
if (_hoverItemId == entityItemID) {
|
||||
_hoverItemId = _noItemId;
|
||||
_hoverItemHref.clear();
|
||||
|
||||
_hoverItemTitle.clear();
|
||||
_hoverItemDescription.clear();
|
||||
|
||||
auto cursor = Cursor::Manager::instance().getCursor();
|
||||
cursor->setIcon(Cursor::Icon::DEFAULT);
|
||||
if (!_tooltipId.isEmpty()) {
|
||||
|
@ -182,7 +200,8 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) {
|
|||
|
||||
updateTooltips();
|
||||
|
||||
vec2 canvasSize = qApp->getCanvasSize();
|
||||
auto deviceSize = qApp->getDeviceSize();
|
||||
glViewport(0, 0, deviceSize.width(), deviceSize.height());
|
||||
|
||||
//Handle fading and deactivation/activation of UI
|
||||
gpu::Batch batch;
|
||||
|
@ -204,6 +223,7 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) {
|
|||
|
||||
//draw the mouse pointer
|
||||
// Get the mouse coordinates and convert to NDC [-1, 1]
|
||||
vec2 canvasSize = qApp->getCanvasSize();
|
||||
vec2 mousePosition = toNormalizedDeviceScale(vec2(qApp->getMouse()), canvasSize);
|
||||
// Invert the Y axis
|
||||
mousePosition.y *= -1.0f;
|
||||
|
@ -312,7 +332,7 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
|
|||
batch.setModelTransform(reticleXfm);
|
||||
geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad);
|
||||
}
|
||||
|
||||
|
||||
renderArgs->_context->render(batch);
|
||||
}
|
||||
|
||||
|
@ -322,7 +342,7 @@ void ApplicationCompositor::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& or
|
|||
const glm::vec2 projection = screenToSpherical(cursorPos);
|
||||
// The overlay space orientation of the mouse coordinates
|
||||
const glm::quat orientation(glm::vec3(-projection.y, projection.x, 0.0f));
|
||||
// FIXME We now have the direction of the ray FROM THE DEFAULT HEAD POSE.
|
||||
// FIXME We now have the direction of the ray FROM THE DEFAULT HEAD POSE.
|
||||
// Now we need to account for the actual camera position relative to the overlay
|
||||
glm::vec3 overlaySpaceDirection = glm::normalize(orientation * IDENTITY_FRONT);
|
||||
|
||||
|
@ -375,7 +395,7 @@ QPoint ApplicationCompositor::getPalmClickLocation(const PalmData *palm) const {
|
|||
//Finds the collision point of a world space ray
|
||||
bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
|
||||
|
||||
glm::quat inverseOrientation = glm::inverse(myAvatar->getOrientation());
|
||||
|
||||
glm::vec3 relativePosition = inverseOrientation * (position - myAvatar->getDefaultEyePosition());
|
||||
|
@ -407,7 +427,7 @@ void ApplicationCompositor::renderPointers(gpu::Batch& batch) {
|
|||
renderControllerPointers(batch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
|
@ -515,7 +535,7 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) {
|
|||
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
||||
glm::vec4(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,10 +545,10 @@ void ApplicationCompositor::renderMagnifier(gpu::Batch& batch, const glm::vec2&
|
|||
return;
|
||||
}
|
||||
auto canvasSize = qApp->getCanvasSize();
|
||||
|
||||
|
||||
const int widgetWidth = canvasSize.x;
|
||||
const int widgetHeight = canvasSize.y;
|
||||
|
||||
|
||||
const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f;
|
||||
const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f;
|
||||
// Magnification Texture Coordinates
|
||||
|
@ -536,7 +556,7 @@ void ApplicationCompositor::renderMagnifier(gpu::Batch& batch, const glm::vec2&
|
|||
const float magnifyURight = (magPos.x + halfWidth) / (float)widgetWidth;
|
||||
const float magnifyVTop = 1.0f - (magPos.y - halfHeight) / (float)widgetHeight;
|
||||
const float magnifyVBottom = 1.0f - (magPos.y + halfHeight) / (float)widgetHeight;
|
||||
|
||||
|
||||
const float newHalfWidth = halfWidth * MAGNIFY_MULT;
|
||||
const float newHalfHeight = halfHeight * MAGNIFY_MULT;
|
||||
//Get yaw / pitch value for the corners
|
||||
|
@ -544,7 +564,7 @@ void ApplicationCompositor::renderMagnifier(gpu::Batch& batch, const glm::vec2&
|
|||
magPos.y - newHalfHeight));
|
||||
const glm::vec2 bottomRightYawPitch = overlayToSpherical(glm::vec2(magPos.x + newHalfWidth,
|
||||
magPos.y + newHalfHeight));
|
||||
|
||||
|
||||
const glm::vec3 bottomLeft = getPoint(topLeftYawPitch.x, bottomRightYawPitch.y);
|
||||
const glm::vec3 bottomRight = getPoint(bottomRightYawPitch.x, bottomRightYawPitch.y);
|
||||
const glm::vec3 topLeft = getPoint(topLeftYawPitch.x, topLeftYawPitch.y);
|
||||
|
@ -567,7 +587,7 @@ void ApplicationCompositor::renderMagnifier(gpu::Batch& batch, const glm::vec2&
|
|||
_previousMagnifierTopLeft = topLeft;
|
||||
_previousMagnifierTopRight = topRight;
|
||||
}
|
||||
|
||||
|
||||
glPushMatrix(); {
|
||||
if (showBorder) {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
@ -579,12 +599,12 @@ void ApplicationCompositor::renderMagnifier(gpu::Batch& batch, const glm::vec2&
|
|||
glm::vec4 magnifierColor = { 1.0f, 1.0f, 1.0f, _alpha };
|
||||
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(bottomLeft, bottomRight, topRight, topLeft,
|
||||
glm::vec2(magnifyULeft, magnifyVBottom),
|
||||
glm::vec2(magnifyURight, magnifyVBottom),
|
||||
glm::vec2(magnifyURight, magnifyVTop),
|
||||
glm::vec2(magnifyULeft, magnifyVBottom),
|
||||
glm::vec2(magnifyURight, magnifyVBottom),
|
||||
glm::vec2(magnifyURight, magnifyVTop),
|
||||
glm::vec2(magnifyULeft, magnifyVTop),
|
||||
magnifierColor, _magnifierQuad);
|
||||
|
||||
|
||||
} glPopMatrix();
|
||||
}
|
||||
|
||||
|
@ -609,8 +629,8 @@ void ApplicationCompositor::buildHemiVertices(
|
|||
}
|
||||
|
||||
//UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm
|
||||
|
||||
vec3 pos;
|
||||
|
||||
vec3 pos;
|
||||
vec2 uv;
|
||||
// Compute vertices positions and texture UV coordinate
|
||||
// Create and write to buffer
|
||||
|
@ -629,13 +649,13 @@ void ApplicationCompositor::buildHemiVertices(
|
|||
_hemiVertices->append(sizeof(vec4), (gpu::Byte*)&color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Compute number of indices needed
|
||||
static const int VERTEX_PER_TRANGLE = 3;
|
||||
static const int TRIANGLE_PER_RECTANGLE = 2;
|
||||
int numberOfRectangles = (slices - 1) * (stacks - 1);
|
||||
_hemiIndexCount = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE;
|
||||
|
||||
|
||||
// Compute indices order
|
||||
std::vector<GLushort> indices;
|
||||
for (int i = 0; i < stacks - 1; i++) {
|
||||
|
@ -692,7 +712,7 @@ glm::vec2 ApplicationCompositor::directionToSpherical(const glm::vec3& direction
|
|||
}
|
||||
// Compute pitch
|
||||
result.y = angleBetween(IDENTITY_UP, direction) - PI_OVER_TWO;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -708,7 +728,7 @@ glm::vec2 ApplicationCompositor::screenToSpherical(const glm::vec2& screenPos) {
|
|||
result.y = (screenPos.y / screenSize.y - 0.5f);
|
||||
result.x *= MOUSE_YAW_RANGE;
|
||||
result.y *= MOUSE_PITCH_RANGE;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -718,7 +738,7 @@ glm::vec2 ApplicationCompositor::sphericalToScreen(const glm::vec2& sphericalPos
|
|||
result /= MOUSE_RANGE;
|
||||
result += 0.5f;
|
||||
result *= qApp->getCanvasSize();
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::vec2 ApplicationCompositor::sphericalToOverlay(const glm::vec2& sphericalPos) const {
|
||||
|
@ -735,7 +755,7 @@ glm::vec2 ApplicationCompositor::overlayToSpherical(const glm::vec2& overlayPos
|
|||
glm::vec2 result = overlayPos;
|
||||
result /= qApp->getCanvasSize();
|
||||
result -= 0.5f;
|
||||
result *= _textureFov;
|
||||
result *= _textureFov;
|
||||
result.x *= _textureAspectRatio;
|
||||
result.x *= -1.0f;
|
||||
return result;
|
||||
|
@ -752,10 +772,10 @@ glm::vec2 ApplicationCompositor::overlayToScreen(const glm::vec2& overlayPos) co
|
|||
void ApplicationCompositor::updateTooltips() {
|
||||
if (_hoverItemId != _noItemId) {
|
||||
quint64 hoverDuration = usecTimestampNow() - _hoverItemEnterUsecs;
|
||||
if (_hoverItemEnterUsecs != UINT64_MAX && !_hoverItemHref.isEmpty() && hoverDuration > TOOLTIP_DELAY) {
|
||||
if (_hoverItemEnterUsecs != UINT64_MAX && !_hoverItemTitle.isEmpty() && hoverDuration > TOOLTIP_DELAY) {
|
||||
// TODO Enable and position the tooltip
|
||||
_hoverItemEnterUsecs = UINT64_MAX;
|
||||
_tooltipId = Tooltip::showTip("URL: " + _hoverItemHref);
|
||||
_tooltipId = Tooltip::showTip(_hoverItemTitle, _hoverItemDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
|
||||
QPoint getPalmClickLocation(const PalmData *palm) const;
|
||||
bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const;
|
||||
|
||||
|
||||
bool hasMagnifier() const { return _magnifier; }
|
||||
void toggleMagnifier() { _magnifier = !_magnifier; }
|
||||
|
||||
|
@ -68,7 +68,7 @@ public:
|
|||
static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos);
|
||||
static glm::vec2 screenToSpherical(const glm::vec2 & screenPos);
|
||||
static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos);
|
||||
|
||||
|
||||
private:
|
||||
void displayOverlayTextureStereo(RenderArgs* renderArgs, float aspectRatio, float fov);
|
||||
void bindCursorTexture(gpu::Batch& batch, uint8_t cursorId = 0);
|
||||
|
@ -83,9 +83,10 @@ private:
|
|||
|
||||
// Support for hovering and tooltips
|
||||
static EntityItemID _noItemId;
|
||||
EntityItemID _hoverItemId{ _noItemId };
|
||||
QString _hoverItemHref;
|
||||
quint64 _hoverItemEnterUsecs{ 0 };
|
||||
EntityItemID _hoverItemId { _noItemId };
|
||||
QString _hoverItemTitle;
|
||||
QString _hoverItemDescription;
|
||||
quint64 _hoverItemEnterUsecs { 0 };
|
||||
|
||||
float _hmdUIAngularSize = DEFAULT_HMD_UI_ANGULAR_SIZE;
|
||||
float _textureFov{ glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE) };
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdouble-promotion"
|
||||
#endif
|
||||
|
@ -20,7 +20,7 @@
|
|||
#include <QTextBlock>
|
||||
#include <QtGui>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
|
|
@ -32,7 +32,8 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
|
|||
QWidget(parent, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint |
|
||||
Qt::WindowCloseButtonHint),
|
||||
ui(new Ui::RunningScriptsWidget),
|
||||
_signalMapper(this),
|
||||
_reloadSignalMapper(this),
|
||||
_stopSignalMapper(this),
|
||||
_scriptsModelFilter(this),
|
||||
_scriptsModel(this) {
|
||||
ui->setupUi(this);
|
||||
|
@ -64,7 +65,8 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
|
|||
Application::getInstance(), &Application::loadDialog);
|
||||
connect(ui->loadScriptFromURLButton, &QPushButton::clicked,
|
||||
Application::getInstance(), &Application::loadScriptURLDialog);
|
||||
connect(&_signalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&)));
|
||||
connect(&_reloadSignalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(reloadOneScript(const QString&)));
|
||||
connect(&_stopSignalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&)));
|
||||
|
||||
UIUtil::scaleWidgetFontSizes(this);
|
||||
}
|
||||
|
@ -115,6 +117,17 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) {
|
|||
name->setText(name->text() + "(" + QString::number(hash.find(list.at(i)).value()) + ")");
|
||||
}
|
||||
++hash[list.at(i)];
|
||||
|
||||
QPushButton* reloadButton = new QPushButton(row);
|
||||
reloadButton->setFlat(true);
|
||||
reloadButton->setIcon(
|
||||
QIcon(QPixmap(PathUtils::resourcesPath() + "images/reload-script.svg").scaledToHeight(CLOSE_ICON_HEIGHT)));
|
||||
reloadButton->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
|
||||
reloadButton->setStyleSheet("border: 0;");
|
||||
reloadButton->setCursor(Qt::PointingHandCursor);
|
||||
connect(reloadButton, SIGNAL(clicked()), &_reloadSignalMapper, SLOT(map()));
|
||||
_reloadSignalMapper.setMapping(reloadButton, url.toString());
|
||||
|
||||
QPushButton* closeButton = new QPushButton(row);
|
||||
closeButton->setFlat(true);
|
||||
closeButton->setIcon(
|
||||
|
@ -122,9 +135,8 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) {
|
|||
closeButton->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
|
||||
closeButton->setStyleSheet("border: 0;");
|
||||
closeButton->setCursor(Qt::PointingHandCursor);
|
||||
|
||||
connect(closeButton, SIGNAL(clicked()), &_signalMapper, SLOT(map()));
|
||||
_signalMapper.setMapping(closeButton, url.toString());
|
||||
connect(closeButton, SIGNAL(clicked()), &_stopSignalMapper, SLOT(map()));
|
||||
_stopSignalMapper.setMapping(closeButton, url.toString());
|
||||
|
||||
row->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
|
||||
|
||||
|
@ -132,6 +144,7 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) {
|
|||
row->layout()->setSpacing(0);
|
||||
|
||||
row->layout()->addWidget(name);
|
||||
row->layout()->addWidget(reloadButton);
|
||||
row->layout()->addWidget(closeButton);
|
||||
|
||||
row->setToolTip(url.toString());
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
const ScriptsModel* getScriptsModel() { return &_scriptsModel; }
|
||||
|
||||
signals:
|
||||
void stopScriptName(const QString& name);
|
||||
void stopScriptName(const QString& name, bool restart = false);
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject* sender, QEvent* event);
|
||||
|
@ -59,7 +59,8 @@ private slots:
|
|||
|
||||
private:
|
||||
Ui::RunningScriptsWidget* ui;
|
||||
QSignalMapper _signalMapper;
|
||||
QSignalMapper _reloadSignalMapper;
|
||||
QSignalMapper _stopSignalMapper;
|
||||
ScriptsModelFilter _scriptsModelFilter;
|
||||
ScriptsModel _scriptsModel;
|
||||
ScriptsTableWidget* _recentlyLoadedScriptsTable;
|
||||
|
|
|
@ -29,7 +29,7 @@ class Stats : public QQuickItem {
|
|||
HIFI_QML_DECL
|
||||
Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged)
|
||||
Q_PROPERTY(bool timingExpanded READ isTimingExpanded NOTIFY timingExpandedChanged)
|
||||
Q_PROPERTY(QString monospaceFont READ monospaceFont)
|
||||
Q_PROPERTY(QString monospaceFont READ monospaceFont CONSTANT)
|
||||
|
||||
STATS_PROPERTY(int, serverCount, 0)
|
||||
STATS_PROPERTY(int, framerate, 0)
|
||||
|
|
|
@ -16,15 +16,12 @@
|
|||
#include "Application.h"
|
||||
#include "Base3DOverlay.h"
|
||||
|
||||
const glm::vec3 DEFAULT_POSITION = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
const float DEFAULT_LINE_WIDTH = 1.0f;
|
||||
const bool DEFAULT_IS_SOLID = false;
|
||||
const bool DEFAULT_IS_DASHED_LINE = false;
|
||||
|
||||
Base3DOverlay::Base3DOverlay() :
|
||||
_position(DEFAULT_POSITION),
|
||||
_lineWidth(DEFAULT_LINE_WIDTH),
|
||||
_rotation(),
|
||||
_isSolid(DEFAULT_IS_SOLID),
|
||||
_isDashedLine(DEFAULT_IS_DASHED_LINE),
|
||||
_ignoreRayIntersection(false),
|
||||
|
@ -35,9 +32,8 @@ Base3DOverlay::Base3DOverlay() :
|
|||
|
||||
Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) :
|
||||
Overlay(base3DOverlay),
|
||||
_position(base3DOverlay->_position),
|
||||
_transform(base3DOverlay->_transform),
|
||||
_lineWidth(base3DOverlay->_lineWidth),
|
||||
_rotation(base3DOverlay->_rotation),
|
||||
_isSolid(base3DOverlay->_isSolid),
|
||||
_isDashedLine(base3DOverlay->_isDashedLine),
|
||||
_ignoreRayIntersection(base3DOverlay->_ignoreRayIntersection),
|
||||
|
@ -46,14 +42,6 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) :
|
|||
{
|
||||
}
|
||||
|
||||
Base3DOverlay::~Base3DOverlay() {
|
||||
}
|
||||
|
||||
// TODO: Implement accurate getBounds() implementations
|
||||
AABox Base3DOverlay::getBounds() const {
|
||||
return AABox(_position, glm::vec3(1.0f));
|
||||
}
|
||||
|
||||
void Base3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
Overlay::setProperties(properties);
|
||||
|
||||
|
@ -151,13 +139,13 @@ void Base3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
|
||||
QScriptValue Base3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "position" || property == "start" || property == "p1" || property == "point") {
|
||||
return vec3toScriptValue(_scriptEngine, _position);
|
||||
return vec3toScriptValue(_scriptEngine, getPosition());
|
||||
}
|
||||
if (property == "lineWidth") {
|
||||
return _lineWidth;
|
||||
}
|
||||
if (property == "rotation") {
|
||||
return quatToScriptValue(_scriptEngine, _rotation);
|
||||
return quatToScriptValue(_scriptEngine, getRotation());
|
||||
}
|
||||
if (property == "isSolid" || property == "isFilled" || property == "solid" || property == "filed") {
|
||||
return _isSolid;
|
||||
|
|
|
@ -11,10 +11,7 @@
|
|||
#ifndef hifi_Base3DOverlay_h
|
||||
#define hifi_Base3DOverlay_h
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include <BoxBase.h>
|
||||
#include <Transform.h>
|
||||
|
||||
#include "Overlay.h"
|
||||
|
||||
|
@ -24,32 +21,38 @@ class Base3DOverlay : public Overlay {
|
|||
public:
|
||||
Base3DOverlay();
|
||||
Base3DOverlay(const Base3DOverlay* base3DOverlay);
|
||||
~Base3DOverlay();
|
||||
|
||||
// getters
|
||||
virtual bool is3D() const { return true; }
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
const glm::vec3& getCenter() const { return _position; } // TODO: consider implementing registration points in this class
|
||||
const glm::vec3& getPosition() const { return _transform.getTranslation(); }
|
||||
const glm::quat& getRotation() const { return _transform.getRotation(); }
|
||||
const glm::vec3& getScale() const { return _transform.getScale(); }
|
||||
|
||||
// TODO: consider implementing registration points in this class
|
||||
const glm::vec3& getCenter() const { return getPosition(); }
|
||||
|
||||
float getLineWidth() const { return _lineWidth; }
|
||||
bool getIsSolid() const { return _isSolid; }
|
||||
bool getIsDashedLine() const { return _isDashedLine; }
|
||||
bool getIsSolidLine() const { return !_isDashedLine; }
|
||||
const glm::quat& getRotation() const { return _rotation; }
|
||||
bool getIgnoreRayIntersection() const { return _ignoreRayIntersection; }
|
||||
bool getDrawInFront() const { return _drawInFront; }
|
||||
bool getDrawOnHUD() const { return _drawOnHUD; }
|
||||
|
||||
// setters
|
||||
void setPosition(const glm::vec3& position) { _position = position; }
|
||||
void setPosition(const glm::vec3& value) { _transform.setTranslation(value); }
|
||||
void setRotation(const glm::quat& value) { _transform.setRotation(value); }
|
||||
void setScale(float value) { _transform.setScale(value); }
|
||||
void setScale(const glm::vec3& value) { _transform.setScale(value); }
|
||||
|
||||
void setLineWidth(float lineWidth) { _lineWidth = lineWidth; }
|
||||
void setIsSolid(bool isSolid) { _isSolid = isSolid; }
|
||||
void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; }
|
||||
void setRotation(const glm::quat& value) { _rotation = value; }
|
||||
void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; }
|
||||
void setDrawInFront(bool value) { _drawInFront = value; }
|
||||
void setDrawOnHUD(bool value) { _drawOnHUD = value; }
|
||||
|
||||
virtual AABox getBounds() const;
|
||||
virtual AABox getBounds() const = 0;
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
@ -62,9 +65,9 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
glm::vec3 _position;
|
||||
Transform _transform;
|
||||
|
||||
float _lineWidth;
|
||||
glm::quat _rotation;
|
||||
bool _isSolid;
|
||||
bool _isDashedLine;
|
||||
bool _ignoreRayIntersection;
|
||||
|
|
|
@ -9,26 +9,20 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Application.h"
|
||||
#include "GeometryUtil.h"
|
||||
#include "PlaneShape.h"
|
||||
|
||||
#include "BillboardOverlay.h"
|
||||
|
||||
BillboardOverlay::BillboardOverlay() :
|
||||
_fromImage(),
|
||||
_scale(1.0f),
|
||||
_isFacingAvatar(true)
|
||||
{
|
||||
#include "Application.h"
|
||||
#include "GeometryUtil.h"
|
||||
|
||||
BillboardOverlay::BillboardOverlay() {
|
||||
_isLoaded = false;
|
||||
}
|
||||
|
||||
BillboardOverlay::BillboardOverlay(const BillboardOverlay* billboardOverlay) :
|
||||
Base3DOverlay(billboardOverlay),
|
||||
Planar3DOverlay(billboardOverlay),
|
||||
_url(billboardOverlay->_url),
|
||||
_texture(billboardOverlay->_texture),
|
||||
_fromImage(billboardOverlay->_fromImage),
|
||||
_scale(billboardOverlay->_scale),
|
||||
_isFacingAvatar(billboardOverlay->_isFacingAvatar)
|
||||
{
|
||||
}
|
||||
|
@ -46,8 +40,8 @@ void BillboardOverlay::render(RenderArgs* args) {
|
|||
glm::quat rotation;
|
||||
if (_isFacingAvatar) {
|
||||
// rotate about vertical to face the camera
|
||||
rotation = Application::getInstance()->getCamera()->getRotation();
|
||||
rotation *= glm::angleAxis(glm::pi<float>(), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
rotation = args->_viewFrustum->getOrientation();
|
||||
rotation *= glm::angleAxis(glm::pi<float>(), IDENTITY_UP);
|
||||
rotation *= getRotation();
|
||||
} else {
|
||||
rotation = getRotation();
|
||||
|
@ -89,11 +83,9 @@ void BillboardOverlay::render(RenderArgs* args) {
|
|||
auto batch = args->_batch;
|
||||
|
||||
if (batch) {
|
||||
Transform transform;
|
||||
transform.setTranslation(_position);
|
||||
transform.setRotation(rotation);
|
||||
transform.setScale(_scale);
|
||||
|
||||
Transform transform = _transform;
|
||||
transform.postScale(glm::vec3(getDimensions(), 1.0f));
|
||||
|
||||
batch->setModelTransform(transform);
|
||||
batch->setUniformTexture(0, _texture->getGPUTexture());
|
||||
|
||||
|
@ -111,10 +103,10 @@ void BillboardOverlay::render(RenderArgs* args) {
|
|||
glBindTexture(GL_TEXTURE_2D, _texture->getID());
|
||||
|
||||
glPushMatrix(); {
|
||||
glTranslatef(_position.x, _position.y, _position.z);
|
||||
glTranslatef(getPosition().x, getPosition().y, getPosition().z);
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||
glScalef(_scale, _scale, _scale);
|
||||
glScalef(_dimensions.x, _dimensions.y, 1.0f);
|
||||
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
||||
glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha));
|
||||
|
@ -130,7 +122,7 @@ void BillboardOverlay::render(RenderArgs* args) {
|
|||
}
|
||||
|
||||
void BillboardOverlay::setProperties(const QScriptValue &properties) {
|
||||
Base3DOverlay::setProperties(properties);
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
|
||||
QScriptValue urlValue = properties.property("url");
|
||||
if (urlValue.isValid()) {
|
||||
|
@ -171,11 +163,6 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue scaleValue = properties.property("scale");
|
||||
if (scaleValue.isValid()) {
|
||||
_scale = scaleValue.toVariant().toFloat();
|
||||
}
|
||||
|
||||
QScriptValue isFacingAvatarValue = properties.property("isFacingAvatar");
|
||||
if (isFacingAvatarValue.isValid()) {
|
||||
_isFacingAvatar = isFacingAvatarValue.toVariant().toBool();
|
||||
|
@ -189,14 +176,11 @@ QScriptValue BillboardOverlay::getProperty(const QString& property) {
|
|||
if (property == "subImage") {
|
||||
return qRectToScriptValue(_scriptEngine, _fromImage);
|
||||
}
|
||||
if (property == "scale") {
|
||||
return _scale;
|
||||
}
|
||||
if (property == "isFacingAvatar") {
|
||||
return _isFacingAvatar;
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
return Planar3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
void BillboardOverlay::setURL(const QString& url) {
|
||||
|
@ -212,13 +196,11 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v
|
|||
float& distance, BoxFace& face) {
|
||||
|
||||
if (_texture) {
|
||||
glm::quat rotation;
|
||||
glm::quat rotation = getRotation();
|
||||
if (_isFacingAvatar) {
|
||||
// rotate about vertical to face the camera
|
||||
rotation = Application::getInstance()->getCamera()->getRotation();
|
||||
rotation *= glm::angleAxis(glm::pi<float>(), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
} else {
|
||||
rotation = _rotation;
|
||||
}
|
||||
|
||||
// Produce the dimensions of the billboard based on the image's aspect ratio and the overlay's scale.
|
||||
|
@ -226,9 +208,9 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v
|
|||
float width = isNull ? _texture->getWidth() : _fromImage.width();
|
||||
float height = isNull ? _texture->getHeight() : _fromImage.height();
|
||||
float maxSize = glm::max(width, height);
|
||||
glm::vec2 dimensions = _scale * glm::vec2(width / maxSize, height / maxSize);
|
||||
glm::vec2 dimensions = _dimensions * glm::vec2(width / maxSize, height / maxSize);
|
||||
|
||||
return findRayRectangleIntersection(origin, direction, rotation, _position, dimensions, distance);
|
||||
return findRayRectangleIntersection(origin, direction, rotation, getPosition(), dimensions, distance);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -12,14 +12,11 @@
|
|||
#ifndef hifi_BillboardOverlay_h
|
||||
#define hifi_BillboardOverlay_h
|
||||
|
||||
#include <QScopedPointer>
|
||||
#include <QUrl>
|
||||
|
||||
#include <TextureCache.h>
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
class BillboardOverlay : public Base3DOverlay {
|
||||
class BillboardOverlay : public Planar3DOverlay {
|
||||
Q_OBJECT
|
||||
public:
|
||||
BillboardOverlay();
|
||||
|
@ -29,7 +26,6 @@ public:
|
|||
|
||||
// setters
|
||||
void setURL(const QString& url);
|
||||
void setScale(float scale) { _scale = scale; }
|
||||
void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
@ -48,8 +44,7 @@ private:
|
|||
|
||||
QRect _fromImage; // where from in the image to sample
|
||||
|
||||
float _scale;
|
||||
bool _isFacingAvatar;
|
||||
bool _isFacingAvatar = true;
|
||||
};
|
||||
|
||||
#endif // hifi_BillboardOverlay_h
|
||||
|
|
|
@ -8,16 +8,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
#include "Circle3DOverlay.h"
|
||||
|
||||
#include <DeferredLightingEffect.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <GlowEffect.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <StreamUtils.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "Circle3DOverlay.h"
|
||||
|
||||
Circle3DOverlay::Circle3DOverlay() :
|
||||
_startAt(0.0f),
|
||||
|
@ -66,9 +62,6 @@ Circle3DOverlay::Circle3DOverlay(const Circle3DOverlay* circle3DOverlay) :
|
|||
{
|
||||
}
|
||||
|
||||
Circle3DOverlay::~Circle3DOverlay() {
|
||||
}
|
||||
|
||||
void Circle3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
|
@ -103,15 +96,13 @@ void Circle3DOverlay::render(RenderArgs* args) {
|
|||
_lastColor = colorX;
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(getCenter());
|
||||
transform.setRotation(getRotation());
|
||||
transform.setScale(glm::vec3(getDimensions(), 0.01f));
|
||||
|
||||
|
||||
Q_ASSERT(args->_batch);
|
||||
auto& batch = *args->_batch;
|
||||
batch._glLineWidth(_lineWidth);
|
||||
|
||||
auto transform = _transform;
|
||||
transform.postScale(glm::vec3(getDimensions(), 1.0f));
|
||||
batch.setModelTransform(transform);
|
||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, false, false);
|
||||
|
||||
|
@ -402,12 +393,12 @@ bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin,
|
|||
|
||||
if (intersects) {
|
||||
glm::vec3 hitPosition = origin + (distance * direction);
|
||||
glm::vec3 localHitPosition = glm::inverse(_rotation) * (hitPosition - _position);
|
||||
localHitPosition.y = localHitPosition.y * _dimensions.x / _dimensions.y; // Scale to make circular
|
||||
glm::vec3 localHitPosition = glm::inverse(getRotation()) * (hitPosition - getPosition());
|
||||
localHitPosition.y = localHitPosition.y * getDimensions().x / getDimensions().y; // Scale to make circular
|
||||
|
||||
float distanceToHit = glm::length(localHitPosition);
|
||||
float innerRadius = _dimensions.x / 2.0f * _innerRadius;
|
||||
float outerRadius = _dimensions.x / 2.0f * _outerRadius;
|
||||
float innerRadius = getDimensions().x / 2.0f * _innerRadius;
|
||||
float outerRadius = getDimensions().x / 2.0f * _outerRadius;
|
||||
|
||||
intersects = innerRadius <= distanceToHit && distanceToHit <= outerRadius;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#ifndef hifi_Circle3DOverlay_h
|
||||
#define hifi_Circle3DOverlay_h
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
class Circle3DOverlay : public Planar3DOverlay {
|
||||
|
@ -19,7 +22,7 @@ class Circle3DOverlay : public Planar3DOverlay {
|
|||
public:
|
||||
Circle3DOverlay();
|
||||
Circle3DOverlay(const Circle3DOverlay* circle3DOverlay);
|
||||
~Circle3DOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
|
|
@ -19,17 +19,11 @@
|
|||
#include "Application.h"
|
||||
#include "Cube3DOverlay.h"
|
||||
|
||||
Cube3DOverlay::Cube3DOverlay() : _borderSize(0) {
|
||||
}
|
||||
|
||||
Cube3DOverlay::Cube3DOverlay(const Cube3DOverlay* cube3DOverlay) :
|
||||
Volume3DOverlay(cube3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
Cube3DOverlay::~Cube3DOverlay() {
|
||||
}
|
||||
|
||||
void Cube3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
|
|
|
@ -17,9 +17,9 @@ class Cube3DOverlay : public Volume3DOverlay {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Cube3DOverlay();
|
||||
Cube3DOverlay() {}
|
||||
Cube3DOverlay(const Cube3DOverlay* cube3DOverlay);
|
||||
~Cube3DOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
virtual Cube3DOverlay* createClone() const;
|
||||
|
|
|
@ -9,28 +9,29 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "Grid3DOverlay.h"
|
||||
|
||||
#include <PathUtils.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Grid3DOverlay.h"
|
||||
|
||||
ProgramObject Grid3DOverlay::_gridProgram;
|
||||
|
||||
Grid3DOverlay::Grid3DOverlay() : Base3DOverlay(),
|
||||
Grid3DOverlay::Grid3DOverlay() :
|
||||
_minorGridWidth(1.0),
|
||||
_majorGridEvery(5) {
|
||||
}
|
||||
|
||||
Grid3DOverlay::Grid3DOverlay(const Grid3DOverlay* grid3DOverlay) :
|
||||
Base3DOverlay(grid3DOverlay),
|
||||
Planar3DOverlay(grid3DOverlay),
|
||||
_minorGridWidth(grid3DOverlay->_minorGridWidth),
|
||||
_majorGridEvery(grid3DOverlay->_majorGridEvery)
|
||||
{
|
||||
}
|
||||
|
||||
Grid3DOverlay::~Grid3DOverlay() {
|
||||
}
|
||||
|
||||
void Grid3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
|
@ -41,7 +42,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
const float MAX_COLOR = 255.0f;
|
||||
|
||||
// center the grid around the camera position on the plane
|
||||
glm::vec3 rotated = glm::inverse(_rotation) * Application::getInstance()->getCamera()->getPosition();
|
||||
glm::vec3 rotated = glm::inverse(getRotation()) * Application::getInstance()->getCamera()->getPosition();
|
||||
|
||||
float spacing = _minorGridWidth;
|
||||
|
||||
|
@ -53,7 +54,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
if (batch) {
|
||||
Transform transform;
|
||||
transform.setRotation(_rotation);
|
||||
transform.setRotation(getRotation());
|
||||
|
||||
|
||||
// Minor grid
|
||||
|
@ -61,7 +62,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
batch->_glLineWidth(1.0f);
|
||||
auto position = glm::vec3(_minorGridWidth * (floorf(rotated.x / spacing) - MINOR_GRID_DIVISIONS / 2),
|
||||
spacing * (floorf(rotated.y / spacing) - MINOR_GRID_DIVISIONS / 2),
|
||||
_position.z);
|
||||
getPosition().z);
|
||||
float scale = MINOR_GRID_DIVISIONS * spacing;
|
||||
|
||||
transform.setTranslation(position);
|
||||
|
@ -78,7 +79,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
spacing *= _majorGridEvery;
|
||||
auto position = glm::vec3(spacing * (floorf(rotated.x / spacing) - MAJOR_GRID_DIVISIONS / 2),
|
||||
spacing * (floorf(rotated.y / spacing) - MAJOR_GRID_DIVISIONS / 2),
|
||||
_position.z);
|
||||
getPosition().z);
|
||||
float scale = MAJOR_GRID_DIVISIONS * spacing;
|
||||
|
||||
transform.setTranslation(position);
|
||||
|
@ -161,7 +162,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
}
|
||||
|
||||
void Grid3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
Base3DOverlay::setProperties(properties);
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
|
||||
if (properties.property("minorGridWidth").isValid()) {
|
||||
_minorGridWidth = properties.property("minorGridWidth").toVariant().toFloat();
|
||||
|
@ -180,7 +181,7 @@ QScriptValue Grid3DOverlay::getProperty(const QString& property) {
|
|||
return _majorGridEvery;
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
return Planar3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
Grid3DOverlay* Grid3DOverlay::createClone() const {
|
||||
|
|
|
@ -15,20 +15,16 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <ProgramObject.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
class Grid3DOverlay : public Base3DOverlay {
|
||||
class Grid3DOverlay : public Planar3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Grid3DOverlay();
|
||||
Grid3DOverlay(const Grid3DOverlay* grid3DOverlay);
|
||||
~Grid3DOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
|
|
@ -8,17 +8,11 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QSvgRenderer>
|
||||
#include "ImageOverlay.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "ImageOverlay.h"
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
ImageOverlay::ImageOverlay() :
|
||||
_imageURL(),
|
||||
|
@ -38,9 +32,6 @@ ImageOverlay::ImageOverlay(const ImageOverlay* imageOverlay) :
|
|||
{
|
||||
}
|
||||
|
||||
ImageOverlay::~ImageOverlay() {
|
||||
}
|
||||
|
||||
// TODO: handle setting image multiple times, how do we manage releasing the bound texture?
|
||||
void ImageOverlay::setImageURL(const QUrl& url) {
|
||||
_imageURL = url;
|
||||
|
|
|
@ -15,17 +15,11 @@
|
|||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QNetworkReply>
|
||||
#include <QRect>
|
||||
#include <QScriptValue>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
#include <NetworkAccessManager.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <TextureCache.h>
|
||||
|
||||
#include "Overlay.h"
|
||||
#include "Overlay2D.h"
|
||||
|
||||
class ImageOverlay : public Overlay2D {
|
||||
|
@ -34,7 +28,7 @@ class ImageOverlay : public Overlay2D {
|
|||
public:
|
||||
ImageOverlay();
|
||||
ImageOverlay(const ImageOverlay* imageOverlay);
|
||||
~ImageOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
// getters
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <GlowEffect.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "Line3DOverlay.h"
|
||||
|
||||
|
@ -33,13 +34,12 @@ Line3DOverlay::~Line3DOverlay() {
|
|||
}
|
||||
|
||||
AABox Line3DOverlay::getBounds() const {
|
||||
auto start = _position + _start;
|
||||
auto end = _position + _end;
|
||||
|
||||
auto min = glm::min(start, end);
|
||||
auto max = glm::max(start, end);
|
||||
|
||||
return AABox(min, max - min);
|
||||
auto extents = Extents{};
|
||||
extents.addPoint(_start);
|
||||
extents.addPoint(_end);
|
||||
extents.transform(_transform);
|
||||
|
||||
return AABox(extents);
|
||||
}
|
||||
|
||||
void Line3DOverlay::render(RenderArgs* args) {
|
||||
|
@ -55,14 +55,11 @@ void Line3DOverlay::render(RenderArgs* args) {
|
|||
auto batch = args->_batch;
|
||||
|
||||
if (batch) {
|
||||
Transform transform;
|
||||
transform.setTranslation(_position);
|
||||
transform.setRotation(_rotation);
|
||||
batch->setModelTransform(transform);
|
||||
batch->setModelTransform(_transform);
|
||||
|
||||
if (getIsDashedLine()) {
|
||||
// TODO: add support for color to renderDashedLine()
|
||||
DependencyManager::get<GeometryCache>()->renderDashedLine(*batch, _position, _end, colorv4, _geometryCacheID);
|
||||
DependencyManager::get<GeometryCache>()->renderDashedLine(*batch, _start, _end, colorv4, _geometryCacheID);
|
||||
} else {
|
||||
DependencyManager::get<GeometryCache>()->renderLine(*batch, _start, _end, colorv4, _geometryCacheID);
|
||||
}
|
||||
|
@ -87,7 +84,7 @@ void Line3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
if (getIsDashedLine()) {
|
||||
// TODO: add support for color to renderDashedLine()
|
||||
DependencyManager::get<GeometryCache>()->renderDashedLine(_position, _end, colorv4, _geometryCacheID);
|
||||
DependencyManager::get<GeometryCache>()->renderDashedLine(_start, _end, colorv4, _geometryCacheID);
|
||||
} else {
|
||||
DependencyManager::get<GeometryCache>()->renderLine(_start, _end, colorv4, _geometryCacheID);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public:
|
|||
Line3DOverlay(const Line3DOverlay* line3DOverlay);
|
||||
~Line3DOverlay();
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual AABox getBounds() const override;
|
||||
virtual AABox getBounds() const;
|
||||
|
||||
// getters
|
||||
const glm::vec3& getStart() const { return _start; }
|
||||
|
|
|
@ -24,10 +24,6 @@ LocalModelsOverlay::LocalModelsOverlay(const LocalModelsOverlay* localModelsOver
|
|||
Volume3DOverlay(localModelsOverlay),
|
||||
_entityTreeRenderer(localModelsOverlay->_entityTreeRenderer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LocalModelsOverlay::~LocalModelsOverlay() {
|
||||
}
|
||||
|
||||
void LocalModelsOverlay::update(float deltatime) {
|
||||
|
@ -46,7 +42,7 @@ void LocalModelsOverlay::render(RenderArgs* args) {
|
|||
glPushMatrix(); {
|
||||
Application* app = Application::getInstance();
|
||||
glm::vec3 oldTranslation = app->getViewMatrixTranslation();
|
||||
app->setViewMatrixTranslation(oldTranslation + _position);
|
||||
app->setViewMatrixTranslation(oldTranslation + getPosition());
|
||||
_entityTreeRenderer->render(args);
|
||||
Application::getInstance()->setViewMatrixTranslation(oldTranslation);
|
||||
} glPopMatrix();
|
||||
|
|
|
@ -21,7 +21,6 @@ class LocalModelsOverlay : public Volume3DOverlay {
|
|||
public:
|
||||
LocalModelsOverlay(EntityTreeRenderer* entityTreeRenderer);
|
||||
LocalModelsOverlay(const LocalModelsOverlay* localModelsOverlay);
|
||||
~LocalModelsOverlay();
|
||||
|
||||
virtual void update(float deltatime);
|
||||
virtual void render(RenderArgs* args);
|
||||
|
|
|
@ -9,15 +9,15 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ModelOverlay.h"
|
||||
|
||||
#include <Application.h>
|
||||
#include <GlowEffect.h>
|
||||
|
||||
#include "ModelOverlay.h"
|
||||
|
||||
ModelOverlay::ModelOverlay()
|
||||
: _model(),
|
||||
_modelTextures(QVariantMap()),
|
||||
_scale(1.0f),
|
||||
_updateModel(false)
|
||||
{
|
||||
_model.init();
|
||||
|
@ -25,12 +25,10 @@ ModelOverlay::ModelOverlay()
|
|||
}
|
||||
|
||||
ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) :
|
||||
Base3DOverlay(modelOverlay),
|
||||
Volume3DOverlay(modelOverlay),
|
||||
_model(),
|
||||
_modelTextures(QVariantMap()),
|
||||
_url(modelOverlay->_url),
|
||||
_rotation(modelOverlay->_rotation),
|
||||
_scale(modelOverlay->_scale),
|
||||
_updateModel(false)
|
||||
{
|
||||
_model.init();
|
||||
|
@ -45,8 +43,9 @@ void ModelOverlay::update(float deltatime) {
|
|||
_updateModel = false;
|
||||
|
||||
_model.setSnapModelToCenter(true);
|
||||
_model.setRotation(_rotation);
|
||||
_model.setTranslation(_position);
|
||||
_model.setScale(getScale());
|
||||
_model.setRotation(getRotation());
|
||||
_model.setTranslation(getPosition());
|
||||
_model.setURL(_url);
|
||||
_model.simulate(deltatime, true);
|
||||
} else {
|
||||
|
@ -56,13 +55,13 @@ void ModelOverlay::update(float deltatime) {
|
|||
}
|
||||
|
||||
bool ModelOverlay::addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||
Base3DOverlay::addToScene(overlay, scene, pendingChanges);
|
||||
Volume3DOverlay::addToScene(overlay, scene, pendingChanges);
|
||||
_model.addToScene(scene, pendingChanges);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModelOverlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||
Base3DOverlay::removeFromScene(overlay, scene, pendingChanges);
|
||||
Volume3DOverlay::removeFromScene(overlay, scene, pendingChanges);
|
||||
_model.removeFromScene(scene, pendingChanges);
|
||||
}
|
||||
|
||||
|
@ -100,54 +99,26 @@ void ModelOverlay::render(RenderArgs* args) {
|
|||
}
|
||||
|
||||
void ModelOverlay::setProperties(const QScriptValue &properties) {
|
||||
Base3DOverlay::setProperties(properties);
|
||||
auto position = getPosition();
|
||||
auto rotation = getRotation();
|
||||
auto scale = getDimensions();
|
||||
|
||||
Volume3DOverlay::setProperties(properties);
|
||||
|
||||
if (position != getPosition() || rotation != getRotation() || scale != getDimensions()) {
|
||||
_model.setScaleToFit(true, getScale());
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
QScriptValue urlValue = properties.property("url");
|
||||
if (urlValue.isValid()) {
|
||||
_url = urlValue.toVariant().toString();
|
||||
if (urlValue.isValid() && urlValue.isString()) {
|
||||
_url = urlValue.toString();
|
||||
_updateModel = true;
|
||||
_isLoaded = false;
|
||||
}
|
||||
|
||||
QScriptValue scaleValue = properties.property("scale");
|
||||
if (scaleValue.isValid()) {
|
||||
_scale = scaleValue.toVariant().toFloat();
|
||||
_model.setScaleToFit(true, _scale);
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
QScriptValue rotationValue = properties.property("rotation");
|
||||
if (rotationValue.isValid()) {
|
||||
QScriptValue x = rotationValue.property("x");
|
||||
QScriptValue y = rotationValue.property("y");
|
||||
QScriptValue z = rotationValue.property("z");
|
||||
QScriptValue w = rotationValue.property("w");
|
||||
if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) {
|
||||
_rotation.x = x.toVariant().toFloat();
|
||||
_rotation.y = y.toVariant().toFloat();
|
||||
_rotation.z = z.toVariant().toFloat();
|
||||
_rotation.w = w.toVariant().toFloat();
|
||||
}
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
QScriptValue dimensionsValue = properties.property("dimensions");
|
||||
if (dimensionsValue.isValid()) {
|
||||
QScriptValue x = dimensionsValue.property("x");
|
||||
QScriptValue y = dimensionsValue.property("y");
|
||||
QScriptValue z = dimensionsValue.property("z");
|
||||
if (x.isValid() && y.isValid() && z.isValid()) {
|
||||
glm::vec3 dimensions;
|
||||
dimensions.x = x.toVariant().toFloat();
|
||||
dimensions.y = y.toVariant().toFloat();
|
||||
dimensions.z = z.toVariant().toFloat();
|
||||
_model.setScaleToFit(true, dimensions);
|
||||
}
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
QScriptValue texturesValue = properties.property("textures");
|
||||
if (texturesValue.isValid()) {
|
||||
if (texturesValue.isValid() && texturesValue.toVariant().canConvert(QVariant::Map)) {
|
||||
QVariantMap textureMap = texturesValue.toVariant().toMap();
|
||||
foreach(const QString& key, textureMap.keys()) {
|
||||
|
||||
|
@ -161,22 +132,12 @@ void ModelOverlay::setProperties(const QScriptValue &properties) {
|
|||
_modelTextures[key] = newTextureURL; // Keep local track of textures for getProperty()
|
||||
}
|
||||
}
|
||||
|
||||
if (properties.property("position").isValid()) {
|
||||
_updateModel = true;
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue ModelOverlay::getProperty(const QString& property) {
|
||||
if (property == "url") {
|
||||
return _url.toString();
|
||||
}
|
||||
if (property == "scale") {
|
||||
return _scale;
|
||||
}
|
||||
if (property == "rotation") {
|
||||
return quatToScriptValue(_scriptEngine, _rotation);
|
||||
}
|
||||
if (property == "dimensions") {
|
||||
return vec3toScriptValue(_scriptEngine, _model.getScaleToFitDimensions());
|
||||
}
|
||||
|
@ -192,7 +153,7 @@ QScriptValue ModelOverlay::getProperty(const QString& property) {
|
|||
}
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
return Volume3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
|
||||
#include <Model.h>
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
#include "Volume3DOverlay.h"
|
||||
|
||||
class ModelOverlay : public Base3DOverlay {
|
||||
class ModelOverlay : public Volume3DOverlay {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ModelOverlay();
|
||||
|
@ -41,9 +41,6 @@ private:
|
|||
QVariantMap _modelTextures;
|
||||
|
||||
QUrl _url;
|
||||
glm::quat _rotation;
|
||||
float _scale;
|
||||
|
||||
bool _updateModel;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "Overlay.h"
|
||||
|
||||
#include <NumericalConstants.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
static const xColor DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
|
||||
static const float DEFAULT_ALPHA = 0.7f;
|
||||
|
||||
Overlay::Overlay() :
|
||||
_renderItemID(render::Item::INVALID_ITEM_ID),
|
||||
|
|
|
@ -14,18 +14,11 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QRect>
|
||||
#include <QScriptValue>
|
||||
#include <QString>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <SharedUtil.h> // for xColor
|
||||
#include <RenderArgs.h>
|
||||
#include <AABox.h>
|
||||
#include <render/Scene.h>
|
||||
|
||||
const xColor DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
|
||||
const float DEFAULT_ALPHA = 0.7f;
|
||||
class QScriptEngine;
|
||||
class QScriptValue;
|
||||
|
||||
class Overlay : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -37,7 +30,6 @@ public:
|
|||
};
|
||||
|
||||
typedef std::shared_ptr<Overlay> Pointer;
|
||||
|
||||
typedef render::Payload<Overlay> Payload;
|
||||
typedef std::shared_ptr<render::Item::PayloadInterface> PayloadPointer;
|
||||
|
||||
|
@ -47,6 +39,8 @@ public:
|
|||
void init(QScriptEngine* scriptEngine);
|
||||
virtual void update(float deltatime) {}
|
||||
virtual void render(RenderArgs* args) = 0;
|
||||
|
||||
virtual AABox getBounds() const = 0;
|
||||
|
||||
virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
||||
virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
||||
|
|
|
@ -8,16 +8,9 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Overlay2D.h"
|
||||
|
||||
|
||||
Overlay2D::Overlay2D() {
|
||||
}
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
Overlay2D::Overlay2D(const Overlay2D* overlay2D) :
|
||||
Overlay(overlay2D),
|
||||
|
@ -25,7 +18,9 @@ Overlay2D::Overlay2D(const Overlay2D* overlay2D) :
|
|||
{
|
||||
}
|
||||
|
||||
Overlay2D::~Overlay2D() {
|
||||
AABox Overlay2D::getBounds() const {
|
||||
return AABox(glm::vec3(_bounds.x(), _bounds.y(), 0.0f),
|
||||
glm::vec3(_bounds.width(), _bounds.height(), 0.01f));
|
||||
}
|
||||
|
||||
void Overlay2D::setProperties(const QScriptValue& properties) {
|
||||
|
@ -40,7 +35,7 @@ void Overlay2D::setProperties(const QScriptValue& properties) {
|
|||
boundsRect.setHeight(bounds.property("height").toVariant().toInt());
|
||||
setBounds(boundsRect);
|
||||
} else {
|
||||
QRect oldBounds = getBounds();
|
||||
QRect oldBounds = _bounds;
|
||||
QRect newBounds = oldBounds;
|
||||
|
||||
if (properties.property("x").isValid()) {
|
||||
|
|
|
@ -15,10 +15,6 @@
|
|||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QRect>
|
||||
#include <QScriptValue>
|
||||
#include <QString>
|
||||
|
||||
#include <SharedUtil.h> // for xColor
|
||||
|
||||
#include "Overlay.h"
|
||||
|
||||
|
@ -26,9 +22,10 @@ class Overlay2D : public Overlay {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Overlay2D();
|
||||
Overlay2D() {}
|
||||
Overlay2D(const Overlay2D* overlay2D);
|
||||
~Overlay2D();
|
||||
|
||||
virtual AABox getBounds() const;
|
||||
|
||||
virtual bool is3D() const { return false; }
|
||||
|
||||
|
@ -37,8 +34,8 @@ public:
|
|||
int getY() const { return _bounds.y(); }
|
||||
int getWidth() const { return _bounds.width(); }
|
||||
int getHeight() const { return _bounds.height(); }
|
||||
const QRect& getBounds() const { return _bounds; }
|
||||
|
||||
const QRect& getBoundingRect() const { return _bounds; }
|
||||
|
||||
// setters
|
||||
void setX(int x) { _bounds.setX(x); }
|
||||
void setY(int y) { _bounds.setY(y); }
|
||||
|
|
|
@ -8,14 +8,13 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Overlays.h"
|
||||
|
||||
#include <QScriptValueIterator>
|
||||
|
||||
#include <limits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <Application.h>
|
||||
#include <avatar/AvatarManager.h>
|
||||
#include <LODManager.h>
|
||||
#include <render/Scene.h>
|
||||
|
||||
#include "BillboardOverlay.h"
|
||||
|
@ -25,7 +24,6 @@
|
|||
#include "Line3DOverlay.h"
|
||||
#include "LocalModelsOverlay.h"
|
||||
#include "ModelOverlay.h"
|
||||
#include "Overlays.h"
|
||||
#include "Rectangle3DOverlay.h"
|
||||
#include "Sphere3DOverlay.h"
|
||||
#include "Grid3DOverlay.h"
|
||||
|
@ -37,7 +35,6 @@ Overlays::Overlays() : _nextOverlayID(1) {
|
|||
}
|
||||
|
||||
Overlays::~Overlays() {
|
||||
|
||||
{
|
||||
QWriteLocker lock(&_lock);
|
||||
QWriteLocker deleteLock(&_deleteLock);
|
||||
|
@ -99,9 +96,6 @@ void Overlays::cleanupOverlaysToDelete() {
|
|||
|
||||
void Overlays::renderHUD(RenderArgs* renderArgs) {
|
||||
QReadLocker lock(&_lock);
|
||||
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
|
||||
foreach(Overlay::Pointer thisOverlay, _overlaysHUD) {
|
||||
if (thisOverlay->is3D()) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
@ -284,7 +278,7 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
|||
} else {
|
||||
Overlay2D* thisOverlay = static_cast<Overlay2D*>(i.value().get());
|
||||
if (thisOverlay->getVisible() && thisOverlay->isLoaded() &&
|
||||
thisOverlay->getBounds().contains(pointCopy.x, pointCopy.y, false)) {
|
||||
thisOverlay->getBoundingRect().contains(pointCopy.x, pointCopy.y, false)) {
|
||||
return thisID;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
#ifndef hifi_Overlays_h
|
||||
#define hifi_Overlays_h
|
||||
|
||||
#include <QString>
|
||||
#include <QReadWriteLock>
|
||||
#include <QScriptValue>
|
||||
#include <QSignalMapper>
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
#include "Overlay.h"
|
||||
|
||||
class PickRay;
|
||||
|
||||
class OverlayPropertyResult {
|
||||
public:
|
||||
OverlayPropertyResult();
|
||||
|
@ -48,9 +48,11 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R
|
|||
|
||||
class Overlays : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Overlays();
|
||||
~Overlays();
|
||||
|
||||
void init();
|
||||
void update(float deltatime);
|
||||
void renderHUD(RenderArgs* renderArgs);
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) {
|
||||
if (overlay->is3D() && !static_cast<Base3DOverlay*>(overlay.get())->getDrawOnHUD()) {
|
||||
if (static_cast<Base3DOverlay*>(overlay.get())->getDrawInFront()) {
|
||||
if (overlay->is3D() && !std::dynamic_pointer_cast<Base3DOverlay>(overlay)->getDrawOnHUD()) {
|
||||
if (std::dynamic_pointer_cast<Base3DOverlay>(overlay)->getDrawInFront()) {
|
||||
return ItemKey::Builder().withTypeShape().withLayered().build();
|
||||
} else {
|
||||
return ItemKey::Builder::opaqueShape();
|
||||
|
@ -46,12 +46,7 @@ namespace render {
|
|||
}
|
||||
}
|
||||
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) {
|
||||
if (overlay->is3D()) {
|
||||
return static_cast<Base3DOverlay*>(overlay.get())->getBounds();
|
||||
} else {
|
||||
QRect bounds = static_cast<Overlay2D*>(overlay.get())->getBounds();
|
||||
return AABox(glm::vec3(bounds.x(), bounds.y(), 0.0f), glm::vec3(bounds.width(), bounds.height(), 0.1f));
|
||||
}
|
||||
return overlay->getBounds();
|
||||
}
|
||||
template <> int payloadGetLayer(const Overlay::Pointer& overlay) {
|
||||
// MAgic number while we are defining the layering mechanism:
|
||||
|
@ -59,7 +54,7 @@ namespace render {
|
|||
const int LAYER_3D_FRONT = 1;
|
||||
const int LAYER_3D = 0;
|
||||
if (overlay->is3D()) {
|
||||
return (static_cast<Base3DOverlay*>(overlay.get())->getDrawInFront() ? LAYER_3D_FRONT : LAYER_3D);
|
||||
return (std::dynamic_pointer_cast<Base3DOverlay>(overlay)->getDrawInFront() ? LAYER_3D_FRONT : LAYER_3D);
|
||||
} else {
|
||||
return LAYER_2D;
|
||||
}
|
||||
|
|
|
@ -8,32 +8,24 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <PlaneShape.h>
|
||||
#include <RayIntersectionInfo.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <StreamUtils.h>
|
||||
|
||||
#include "GeometryUtil.h"
|
||||
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
const float DEFAULT_SIZE = 1.0f;
|
||||
|
||||
Planar3DOverlay::Planar3DOverlay() :
|
||||
_dimensions(glm::vec2(DEFAULT_SIZE, DEFAULT_SIZE))
|
||||
{
|
||||
}
|
||||
#include <Extents.h>
|
||||
#include <GeometryUtil.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
Planar3DOverlay::Planar3DOverlay(const Planar3DOverlay* planar3DOverlay) :
|
||||
Base3DOverlay(planar3DOverlay),
|
||||
_dimensions(planar3DOverlay->_dimensions)
|
||||
Base3DOverlay(planar3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
Planar3DOverlay::~Planar3DOverlay() {
|
||||
AABox Planar3DOverlay::getBounds() const {
|
||||
auto halfDimensions = glm::vec3{_dimensions / 2.0f, 0.01f};
|
||||
|
||||
auto extents = Extents{-halfDimensions, halfDimensions};
|
||||
extents.transform(_transform);
|
||||
|
||||
return AABox(extents);
|
||||
}
|
||||
|
||||
void Planar3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
|
@ -86,7 +78,7 @@ void Planar3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
|
||||
QScriptValue Planar3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "dimensions" || property == "scale" || property == "size") {
|
||||
return vec2toScriptValue(_scriptEngine, _dimensions);
|
||||
return vec2toScriptValue(_scriptEngine, getDimensions());
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
|
@ -94,5 +86,5 @@ QScriptValue Planar3DOverlay::getProperty(const QString& property) {
|
|||
|
||||
bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face) {
|
||||
return findRayRectangleIntersection(origin, direction, _rotation, _position, _dimensions, distance);
|
||||
return findRayRectangleIntersection(origin, direction, getRotation(), getPosition(), getDimensions(), distance);
|
||||
}
|
||||
|
|
|
@ -14,34 +14,28 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <QScriptValue>
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
|
||||
class Planar3DOverlay : public Base3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Planar3DOverlay();
|
||||
Planar3DOverlay() {}
|
||||
Planar3DOverlay(const Planar3DOverlay* planar3DOverlay);
|
||||
~Planar3DOverlay();
|
||||
|
||||
// getters
|
||||
const glm::vec2& getDimensions() const { return _dimensions; }
|
||||
|
||||
// setters
|
||||
void setSize(float size) { _dimensions = glm::vec2(size, size); }
|
||||
|
||||
AABox getBounds() const;
|
||||
|
||||
glm::vec2 getDimensions() const { return _dimensions; }
|
||||
void setDimensions(float value) { _dimensions = glm::vec2(value); }
|
||||
void setDimensions(const glm::vec2& value) { _dimensions = value; }
|
||||
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
|
||||
|
||||
|
||||
protected:
|
||||
glm::vec2 _dimensions;
|
||||
glm::vec2 _dimensions{1.0f, 1.0f};
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -11,12 +11,12 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "Rectangle3DOverlay.h"
|
||||
|
||||
#include <GeometryCache.h>
|
||||
#include <GlowEffect.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Rectangle3DOverlay.h"
|
||||
|
||||
Rectangle3DOverlay::Rectangle3DOverlay() :
|
||||
_geometryCacheID(DependencyManager::get<GeometryCache>()->allocateID())
|
||||
{
|
||||
|
|
|
@ -17,17 +17,12 @@
|
|||
#include "Sphere3DOverlay.h"
|
||||
#include "Application.h"
|
||||
|
||||
Sphere3DOverlay::Sphere3DOverlay() {
|
||||
}
|
||||
|
||||
Sphere3DOverlay::Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay) :
|
||||
Volume3DOverlay(Sphere3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
Sphere3DOverlay::~Sphere3DOverlay() {
|
||||
}
|
||||
|
||||
void Sphere3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
|
@ -42,11 +37,8 @@ void Sphere3DOverlay::render(RenderArgs* args) {
|
|||
auto batch = args->_batch;
|
||||
|
||||
if (batch) {
|
||||
Transform transform;
|
||||
transform.setTranslation(_position);
|
||||
transform.setRotation(_rotation);
|
||||
transform.setScale(_dimensions);
|
||||
|
||||
Transform transform = _transform;
|
||||
transform.postScale(getDimensions());
|
||||
batch->setModelTransform(transform);
|
||||
DependencyManager::get<GeometryCache>()->renderSphere(*batch, 1.0f, SLICES, SLICES, sphereColor, _isSolid);
|
||||
} else {
|
||||
|
|
|
@ -17,9 +17,9 @@ class Sphere3DOverlay : public Volume3DOverlay {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Sphere3DOverlay();
|
||||
Sphere3DOverlay() {}
|
||||
Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay);
|
||||
~Sphere3DOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
virtual Sphere3DOverlay* createClone() const;
|
||||
|
|
|
@ -11,13 +11,18 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "Text3DOverlay.h"
|
||||
|
||||
#include <RenderDeferredTask.h>
|
||||
#include <TextRenderer3D.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
|
||||
const float DEFAULT_BACKGROUND_ALPHA = 0.7f;
|
||||
const float DEFAULT_MARGIN = 0.1f;
|
||||
const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation
|
||||
const int FIXED_FONT_POINT_SIZE = 40;
|
||||
const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 80.0f; // this is a ratio determined through experimentation
|
||||
const float LINE_SCALE_RATIO = 1.2f;
|
||||
|
||||
Text3DOverlay::Text3DOverlay() :
|
||||
|
@ -30,6 +35,7 @@ Text3DOverlay::Text3DOverlay() :
|
|||
_bottomMargin(DEFAULT_MARGIN),
|
||||
_isFacingAvatar(false)
|
||||
{
|
||||
_textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||
}
|
||||
|
||||
Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) :
|
||||
|
@ -44,6 +50,7 @@ Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) :
|
|||
_bottomMargin(text3DOverlay->_bottomMargin),
|
||||
_isFacingAvatar(text3DOverlay->_isFacingAvatar)
|
||||
{
|
||||
_textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||
}
|
||||
|
||||
Text3DOverlay::~Text3DOverlay() {
|
||||
|
@ -52,7 +59,7 @@ Text3DOverlay::~Text3DOverlay() {
|
|||
|
||||
xColor Text3DOverlay::getBackgroundColor() {
|
||||
if (_colorPulse == 0.0f) {
|
||||
return _backgroundColor;
|
||||
return _backgroundColor;
|
||||
}
|
||||
|
||||
float pulseLevel = updatePulse();
|
||||
|
@ -75,72 +82,63 @@ void Text3DOverlay::render(RenderArgs* args) {
|
|||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
glPushMatrix(); {
|
||||
glTranslatef(_position.x, _position.y, _position.z);
|
||||
glm::quat rotation;
|
||||
|
||||
if (_isFacingAvatar) {
|
||||
// rotate about vertical to face the camera
|
||||
rotation = Application::getInstance()->getCamera()->getRotation();
|
||||
} else {
|
||||
rotation = getRotation();
|
||||
}
|
||||
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||
|
||||
const float MAX_COLOR = 255.0f;
|
||||
xColor backgroundColor = getBackgroundColor();
|
||||
glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR,
|
||||
getBackgroundAlpha());
|
||||
|
||||
glm::vec2 dimensions = getDimensions();
|
||||
glm::vec2 halfDimensions = dimensions * 0.5f;
|
||||
|
||||
const float SLIGHTLY_BEHIND = -0.005f;
|
||||
|
||||
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, quadColor);
|
||||
|
||||
// Same font properties as textSize()
|
||||
float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO;
|
||||
|
||||
float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
|
||||
|
||||
glTranslatef(-(halfDimensions.x - _leftMargin), halfDimensions.y - _topMargin, 0.0f);
|
||||
|
||||
glm::vec2 clipMinimum(0.0f, 0.0f);
|
||||
glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor,
|
||||
(dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor);
|
||||
|
||||
glScalef(scaleFactor, -scaleFactor, scaleFactor);
|
||||
enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipDimensions.x);
|
||||
enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x);
|
||||
enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y);
|
||||
enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y);
|
||||
|
||||
glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() };
|
||||
_textRenderer->draw(0, 0, _text, textColor);
|
||||
|
||||
glDisable(GL_CLIP_PLANE0);
|
||||
glDisable(GL_CLIP_PLANE1);
|
||||
glDisable(GL_CLIP_PLANE2);
|
||||
glDisable(GL_CLIP_PLANE3);
|
||||
|
||||
} glPopMatrix();
|
||||
Q_ASSERT(args->_batch);
|
||||
auto& batch = *args->_batch;
|
||||
|
||||
}
|
||||
|
||||
void Text3DOverlay::enableClipPlane(GLenum plane, float x, float y, float z, float w) {
|
||||
GLdouble coefficients[] = { x, y, z, w };
|
||||
glClipPlane(plane, coefficients);
|
||||
glEnable(plane);
|
||||
glm::quat rotation;
|
||||
|
||||
if (_isFacingAvatar) {
|
||||
// rotate about vertical to face the camera
|
||||
rotation = args->_viewFrustum->getOrientation();
|
||||
} else {
|
||||
rotation = getRotation();
|
||||
}
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(getPosition());
|
||||
transform.setRotation(rotation);
|
||||
transform.setScale(getScale());
|
||||
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
const float MAX_COLOR = 255.0f;
|
||||
xColor backgroundColor = getBackgroundColor();
|
||||
glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR,
|
||||
getBackgroundAlpha());
|
||||
|
||||
glm::vec2 dimensions = getDimensions();
|
||||
glm::vec2 halfDimensions = dimensions * 0.5f;
|
||||
|
||||
const float SLIGHTLY_BEHIND = -0.005f;
|
||||
|
||||
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, quadColor);
|
||||
|
||||
// Same font properties as textSize()
|
||||
float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO;
|
||||
|
||||
float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
|
||||
|
||||
glm::vec2 clipMinimum(0.0f, 0.0f);
|
||||
glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor,
|
||||
(dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor);
|
||||
|
||||
transform.setTranslation(getPosition());
|
||||
transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin) , halfDimensions.y - _topMargin, 0.01f));
|
||||
transform.setScale(scaleFactor);
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() };
|
||||
_textRenderer->draw(batch, 0, 0, _text, textColor);
|
||||
|
||||
batch.setPipeline(DrawOverlay3D::getOpaquePipeline());
|
||||
}
|
||||
|
||||
void Text3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
|
||||
|
||||
QScriptValue text = properties.property("text");
|
||||
if (text.isValid()) {
|
||||
setText(text.toVariant().toString());
|
||||
|
|
|
@ -16,12 +16,9 @@
|
|||
|
||||
#include <QString>
|
||||
|
||||
#include <RenderArgs.h>
|
||||
#include <TextRenderer.h>
|
||||
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
const int FIXED_FONT_POINT_SIZE = 40;
|
||||
class TextRenderer3D;
|
||||
|
||||
class Text3DOverlay : public Planar3DOverlay {
|
||||
Q_OBJECT
|
||||
|
@ -60,9 +57,7 @@ public:
|
|||
virtual Text3DOverlay* createClone() const;
|
||||
|
||||
private:
|
||||
void enableClipPlane(GLenum plane, float x, float y, float z, float w);
|
||||
|
||||
TextRenderer* _textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||
TextRenderer3D* _textRenderer = nullptr;
|
||||
|
||||
QString _text;
|
||||
xColor _backgroundColor;
|
||||
|
|
|
@ -11,11 +11,14 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "TextOverlay.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <TextRenderer.h>
|
||||
|
||||
#include "TextOverlay.h"
|
||||
|
||||
TextOverlay::TextOverlay() :
|
||||
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
|
||||
|
|
|
@ -14,22 +14,20 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QRect>
|
||||
#include <QScriptValue>
|
||||
#include <QString>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <TextRenderer.h>
|
||||
|
||||
#include "Overlay.h"
|
||||
#include "Overlay2D.h"
|
||||
|
||||
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
|
||||
const float DEFAULT_BACKGROUND_ALPHA = 0.7f;
|
||||
const int DEFAULT_MARGIN = 10;
|
||||
const int DEFAULT_FONTSIZE = 11;
|
||||
const int DEFAULT_FONTSIZE = 12;
|
||||
const int DEFAULT_FONT_WEIGHT = 50;
|
||||
|
||||
class TextRenderer;
|
||||
|
||||
class TextOverlay : public Overlay2D {
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -8,32 +8,22 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <AABox.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <StreamUtils.h>
|
||||
|
||||
#include "Volume3DOverlay.h"
|
||||
|
||||
const float DEFAULT_SIZE = 1.0f;
|
||||
|
||||
Volume3DOverlay::Volume3DOverlay() :
|
||||
_dimensions(glm::vec3(DEFAULT_SIZE, DEFAULT_SIZE, DEFAULT_SIZE))
|
||||
{
|
||||
}
|
||||
#include <Extents.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
Volume3DOverlay::Volume3DOverlay(const Volume3DOverlay* volume3DOverlay) :
|
||||
Base3DOverlay(volume3DOverlay),
|
||||
_dimensions(volume3DOverlay->_dimensions)
|
||||
Base3DOverlay(volume3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
Volume3DOverlay::~Volume3DOverlay() {
|
||||
AABox Volume3DOverlay::getBounds() const {
|
||||
auto extents = Extents{_localBoundingBox};
|
||||
extents.rotate(getRotation());
|
||||
extents.shiftBy(getPosition());
|
||||
|
||||
return AABox(extents);
|
||||
}
|
||||
|
||||
void Volume3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
|
@ -58,26 +48,30 @@ void Volume3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
QScriptValue z = dimensions.property("z");
|
||||
|
||||
|
||||
if (x.isValid() && y.isValid() && z.isValid()) {
|
||||
newDimensions.x = x.toVariant().toFloat();
|
||||
newDimensions.y = y.toVariant().toFloat();
|
||||
newDimensions.z = z.toVariant().toFloat();
|
||||
if (x.isValid() && x.isNumber() &&
|
||||
y.isValid() && y.isNumber() &&
|
||||
z.isValid() && z.isNumber()) {
|
||||
newDimensions.x = x.toNumber();
|
||||
newDimensions.y = y.toNumber();
|
||||
newDimensions.z = z.toNumber();
|
||||
validDimensions = true;
|
||||
} else {
|
||||
QScriptValue width = dimensions.property("width");
|
||||
QScriptValue height = dimensions.property("height");
|
||||
QScriptValue depth = dimensions.property("depth");
|
||||
if (width.isValid() && height.isValid() && depth.isValid()) {
|
||||
newDimensions.x = width.toVariant().toFloat();
|
||||
newDimensions.y = height.toVariant().toFloat();
|
||||
newDimensions.z = depth.toVariant().toFloat();
|
||||
if (width.isValid() && width.isNumber() &&
|
||||
height.isValid() && height.isNumber() &&
|
||||
depth.isValid() && depth.isNumber()) {
|
||||
newDimensions.x = width.toNumber();
|
||||
newDimensions.y = height.toNumber();
|
||||
newDimensions.z = depth.toNumber();
|
||||
validDimensions = true;
|
||||
}
|
||||
}
|
||||
|
||||
// size, scale, dimensions is special, it might just be a single scalar, check that here
|
||||
if (!validDimensions && dimensions.isNumber()) {
|
||||
float size = dimensions.toVariant().toFloat();
|
||||
float size = dimensions.toNumber();
|
||||
newDimensions.x = size;
|
||||
newDimensions.y = size;
|
||||
newDimensions.z = size;
|
||||
|
@ -92,7 +86,7 @@ void Volume3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
|
||||
QScriptValue Volume3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "dimensions" || property == "scale" || property == "size") {
|
||||
return vec3toScriptValue(_scriptEngine, _dimensions);
|
||||
return vec3toScriptValue(_scriptEngine, getDimensions());
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
|
@ -100,24 +94,14 @@ QScriptValue Volume3DOverlay::getProperty(const QString& property) {
|
|||
|
||||
bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face) {
|
||||
|
||||
// extents is the entity relative, scaled, centered extents of the entity
|
||||
glm::vec3 position = getPosition();
|
||||
glm::mat4 rotation = glm::mat4_cast(getRotation());
|
||||
glm::mat4 translation = glm::translate(position);
|
||||
glm::mat4 entityToWorldMatrix = translation * rotation;
|
||||
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);
|
||||
|
||||
glm::vec3 dimensions = _dimensions;
|
||||
glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the overlay frame of reference
|
||||
AABox overlayFrameBox(corner, dimensions);
|
||||
glm::mat4 worldToEntityMatrix;
|
||||
_transform.getInverseMatrix(worldToEntityMatrix);
|
||||
|
||||
glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f));
|
||||
glm::vec3 overlayFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f));
|
||||
|
||||
// we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame
|
||||
// and testing intersection there.
|
||||
if (overlayFrameBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return _localBoundingBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face);
|
||||
}
|
||||
|
|
|
@ -14,36 +14,29 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <QScriptValue>
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
|
||||
class Volume3DOverlay : public Base3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Volume3DOverlay();
|
||||
Volume3DOverlay() {}
|
||||
Volume3DOverlay(const Volume3DOverlay* volume3DOverlay);
|
||||
~Volume3DOverlay();
|
||||
|
||||
// getters
|
||||
const glm::vec3& getCenter() const { return _position; } // TODO: consider adding registration point!!
|
||||
glm::vec3 getCorner() const { return _position - (_dimensions * 0.5f); } // TODO: consider adding registration point!!
|
||||
const glm::vec3& getDimensions() const { return _dimensions; }
|
||||
|
||||
// setters
|
||||
void setSize(float size) { _dimensions = glm::vec3(size, size, size); }
|
||||
void setDimensions(const glm::vec3& value) { _dimensions = value; }
|
||||
|
||||
virtual AABox getBounds() const;
|
||||
|
||||
const glm::vec3& getDimensions() const { return _localBoundingBox.getDimensions(); }
|
||||
void setDimensions(float value) { _localBoundingBox.setBox(glm::vec3(-value / 2.0f), value); }
|
||||
void setDimensions(const glm::vec3& value) { _localBoundingBox.setBox(-value / 2.0f, value); }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
|
||||
|
||||
|
||||
protected:
|
||||
glm::vec3 _dimensions;
|
||||
// Centered local bounding box
|
||||
AABox _localBoundingBox;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -93,7 +93,6 @@ void AudioInjector::injectAudio() {
|
|||
}
|
||||
|
||||
void AudioInjector::restart() {
|
||||
qCDebug(audio) << "Restarting an AudioInjector by stopping and starting over.";
|
||||
connect(this, &AudioInjector::finished, this, &AudioInjector::restartPortionAfterFinished);
|
||||
if (!_isStarted || _isFinished) {
|
||||
emit finished();
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "RenderableLineEntityItem.h"
|
||||
#include "RenderablePolyVoxEntityItem.h"
|
||||
#include "EntitiesRendererLogging.h"
|
||||
#include "AddressManager.h"
|
||||
|
||||
EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
|
||||
AbstractScriptingServicesInterface* scriptingServices) :
|
||||
|
@ -121,9 +122,9 @@ void EntityTreeRenderer::init() {
|
|||
// first chance, we'll check for enter/leave entity events.
|
||||
_lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE);
|
||||
|
||||
connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity);
|
||||
connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity);
|
||||
connect(entityTree, &EntityTree::entityScriptChanging, this, &EntityTreeRenderer::entitySciptChanging);
|
||||
connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity, Qt::QueuedConnection);
|
||||
connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity, Qt::QueuedConnection);
|
||||
connect(entityTree, &EntityTree::entityScriptChanging, this, &EntityTreeRenderer::entitySciptChanging, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::shutdown() {
|
||||
|
@ -147,13 +148,14 @@ void EntityTreeRenderer::errorInLoadingScript(const QUrl& url) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID, bool isPreload) {
|
||||
QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID, bool isPreload, bool reload) {
|
||||
EntityItemPointer entity = static_cast<EntityTree*>(_tree)->findEntityByEntityItemID(entityItemID);
|
||||
return loadEntityScript(entity, isPreload);
|
||||
return loadEntityScript(entity, isPreload, reload);
|
||||
}
|
||||
|
||||
|
||||
QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& urlOut) {
|
||||
QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& urlOut,
|
||||
bool& reload) {
|
||||
isPending = false;
|
||||
QUrl url(scriptMaybeURLorText);
|
||||
|
||||
|
@ -191,7 +193,7 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe
|
|||
auto scriptCache = DependencyManager::get<ScriptCache>();
|
||||
|
||||
if (!scriptCache->isInBadScriptList(url)) {
|
||||
scriptContents = scriptCache->getScript(url, this, isPending);
|
||||
scriptContents = scriptCache->getScript(url, this, isPending, reload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -200,7 +202,7 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe
|
|||
}
|
||||
|
||||
|
||||
QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool isPreload) {
|
||||
QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool isPreload, bool reload) {
|
||||
if (_shuttingDown) {
|
||||
return QScriptValue(); // since we're shutting down, we don't load any more scripts
|
||||
}
|
||||
|
@ -220,8 +222,8 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool
|
|||
if (_entityScripts.contains(entityID)) {
|
||||
EntityScriptDetails details = _entityScripts[entityID];
|
||||
|
||||
// check to make sure our script text hasn't changed on us since we last loaded it
|
||||
if (details.scriptText == entityScript) {
|
||||
// check to make sure our script text hasn't changed on us since we last loaded it and we're not redownloading it
|
||||
if (details.scriptText == entityScript && !reload) {
|
||||
return details.scriptObject; // previously loaded
|
||||
}
|
||||
|
||||
|
@ -236,7 +238,7 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool
|
|||
bool isURL = false; // loadScriptContents() will tell us if this is a URL or just text.
|
||||
bool isPending = false;
|
||||
QUrl url;
|
||||
QString scriptContents = loadScriptContents(entityScript, isURL, isPending, url);
|
||||
QString scriptContents = loadScriptContents(entityScript, isURL, isPending, url, reload);
|
||||
|
||||
if (isPending && isPreload && isURL) {
|
||||
_waitingOnPreload.insert(url, entityID);
|
||||
|
@ -836,6 +838,14 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int device
|
|||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
||||
if (rayPickResult.intersects) {
|
||||
//qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID;
|
||||
|
||||
QString urlString = rayPickResult.properties.getHref();
|
||||
QUrl url = QUrl(urlString, QUrl::StrictMode);
|
||||
if (url.isValid() && !url.isEmpty()){
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(urlString);
|
||||
|
||||
}
|
||||
|
||||
emit mousePressOnEntity(rayPickResult, event, deviceID);
|
||||
|
||||
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
|
||||
|
@ -1021,17 +1031,17 @@ void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) {
|
|||
}
|
||||
|
||||
|
||||
void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID) {
|
||||
void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID, const bool reload) {
|
||||
if (_tree && !_shuttingDown) {
|
||||
checkAndCallUnload(entityID);
|
||||
checkAndCallPreload(entityID);
|
||||
checkAndCallPreload(entityID, reload);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID) {
|
||||
void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, const bool reload) {
|
||||
if (_tree && !_shuttingDown) {
|
||||
// load the entity script if needed...
|
||||
QScriptValue entityScript = loadEntityScript(entityID, true); // is preload!
|
||||
QScriptValue entityScript = loadEntityScript(entityID, true, reload); // is preload!
|
||||
if (entityScript.property("preload").isValid()) {
|
||||
QScriptValueList entityArgs = createEntityArgs(entityID);
|
||||
entityScript.property("preload").call(entityScript, entityArgs);
|
||||
|
|
|
@ -110,7 +110,7 @@ signals:
|
|||
public slots:
|
||||
void addingEntity(const EntityItemID& entityID);
|
||||
void deletingEntity(const EntityItemID& entityID);
|
||||
void entitySciptChanging(const EntityItemID& entityID);
|
||||
void entitySciptChanging(const EntityItemID& entityID, const bool reload);
|
||||
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
||||
|
||||
// optional slots that can be wired to menu items
|
||||
|
@ -127,7 +127,7 @@ private:
|
|||
|
||||
void applyZonePropertiesToScene(std::shared_ptr<ZoneEntityItem> zone);
|
||||
void renderElementProxy(EntityTreeElement* entityTreeElement, RenderArgs* args);
|
||||
void checkAndCallPreload(const EntityItemID& entityID);
|
||||
void checkAndCallPreload(const EntityItemID& entityID, const bool reload = false);
|
||||
void checkAndCallUnload(const EntityItemID& entityID);
|
||||
|
||||
QList<Model*> _releasedModels;
|
||||
|
@ -148,10 +148,10 @@ private:
|
|||
ScriptEngine* _entitiesScriptEngine;
|
||||
ScriptEngine* _sandboxScriptEngine;
|
||||
|
||||
QScriptValue loadEntityScript(EntityItemPointer entity, bool isPreload = false);
|
||||
QScriptValue loadEntityScript(const EntityItemID& entityItemID, bool isPreload = false);
|
||||
QScriptValue loadEntityScript(EntityItemPointer entity, bool isPreload = false, bool reload = false);
|
||||
QScriptValue loadEntityScript(const EntityItemID& entityItemID, bool isPreload = false, bool reload = false);
|
||||
QScriptValue getPreviouslyLoadedEntityScript(const EntityItemID& entityItemID);
|
||||
QString loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& url);
|
||||
QString loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& url, bool& reload);
|
||||
QScriptValueList createMouseEventArgs(const EntityItemID& entityID, QMouseEvent* event, unsigned int deviceID);
|
||||
QScriptValueList createMouseEventArgs(const EntityItemID& entityID, const MouseEvent& mouseEvent);
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include <QByteArray>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdouble-promotion"
|
||||
#endif
|
||||
|
@ -19,7 +19,7 @@
|
|||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
@ -458,7 +458,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o
|
|||
const glm::vec3& direction,
|
||||
bool& keepSearching,
|
||||
OctreeElement*& element,
|
||||
float& distance, BoxFace& face,
|
||||
float& distance, BoxFace& face,
|
||||
void** intersectedObject,
|
||||
bool precisionPicking) const
|
||||
{
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
#include <DeferredLightingEffect.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <PerfStat.h>
|
||||
#include <Transform.h>
|
||||
|
||||
|
||||
|
||||
#include "RenderableTextEntityItem.h"
|
||||
#include "GLMHelpers.h"
|
||||
|
@ -37,14 +40,22 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
|
|||
transformToTopLeft.postTranslate(glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left
|
||||
transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed
|
||||
|
||||
// Render background
|
||||
glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND);
|
||||
glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND);
|
||||
|
||||
|
||||
// Batch render calls
|
||||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
batch.setModelTransform(transformToTopLeft);
|
||||
|
||||
// Render background
|
||||
glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND);
|
||||
glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND);
|
||||
//rotate about vertical to face the camera
|
||||
if (getFaceCamera()) {
|
||||
transformToTopLeft.postRotate(args->_viewFrustum->getOrientation());
|
||||
batch.setModelTransform(transformToTopLeft);
|
||||
}
|
||||
|
||||
DependencyManager::get<DeferredLightingEffect>()->renderQuad(batch, minCorner, maxCorner, backgroundColor);
|
||||
|
||||
float scale = _lineHeight / _textRenderer->getFontSize();
|
||||
|
@ -55,6 +66,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
|
|||
glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin,
|
||||
dimensions.y - 2.0f * topMargin);
|
||||
_textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, _text, textColor, bounds / scale);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
|
|||
_friction(ENTITY_ITEM_DEFAULT_FRICTION),
|
||||
_lifetime(ENTITY_ITEM_DEFAULT_LIFETIME),
|
||||
_script(ENTITY_ITEM_DEFAULT_SCRIPT),
|
||||
_scriptTimestamp(ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP),
|
||||
_collisionSoundURL(ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL),
|
||||
_registrationPoint(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT),
|
||||
_angularVelocity(ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY),
|
||||
|
@ -107,6 +108,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
|
|||
requestedProperties += PROP_FRICTION;
|
||||
requestedProperties += PROP_LIFETIME;
|
||||
requestedProperties += PROP_SCRIPT;
|
||||
requestedProperties += PROP_SCRIPT_TIMESTAMP;
|
||||
requestedProperties += PROP_COLLISION_SOUND_URL;
|
||||
requestedProperties += PROP_REGISTRATION_POINT;
|
||||
requestedProperties += PROP_ANGULAR_VELOCITY;
|
||||
|
@ -238,6 +240,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
APPEND_ENTITY_PROPERTY(PROP_FRICTION, getFriction());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LIFETIME, getLifetime());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, getScript());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, getScriptTimestamp());
|
||||
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, getRegistrationPoint());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, getAngularVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, getAngularDamping());
|
||||
|
@ -555,6 +558,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
READ_ENTITY_PROPERTY(PROP_FRICTION, float, updateFriction);
|
||||
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime);
|
||||
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
|
||||
READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp);
|
||||
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
|
||||
//READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocityInDegrees);
|
||||
|
@ -901,6 +905,7 @@ EntityItemProperties EntityItem::getProperties() const {
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(created, getCreated);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifetime, getLifetime);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(script, getScript);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(scriptTimestamp, getScriptTimestamp);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionSoundURL, getCollisionSoundURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(registrationPoint, getRegistrationPoint);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularVelocity, getAngularVelocity);
|
||||
|
@ -967,6 +972,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
|
||||
// non-simulation properties below
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(scriptTimestamp, setScriptTimestamp);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionSoundURL, setCollisionSoundURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha);
|
||||
|
|
|
@ -276,6 +276,10 @@ public:
|
|||
|
||||
const QString& getScript() const { return _script; }
|
||||
void setScript(const QString& value) { _script = value; }
|
||||
|
||||
quint64 getScriptTimestamp() const { return _scriptTimestamp; }
|
||||
void setScriptTimestamp(const quint64 value) { _scriptTimestamp = value; }
|
||||
|
||||
const QString& getCollisionSoundURL() const { return _collisionSoundURL; }
|
||||
void setCollisionSoundURL(const QString& value) { _collisionSoundURL = value; }
|
||||
|
||||
|
@ -313,7 +317,7 @@ public:
|
|||
|
||||
const QString& getUserData() const { return _userData; }
|
||||
void setUserData(const QString& value) { _userData = value; }
|
||||
|
||||
|
||||
QUuid getSimulatorID() const { return _simulatorID; }
|
||||
void setSimulatorID(const QUuid& value);
|
||||
void updateSimulatorID(const QUuid& value);
|
||||
|
@ -412,6 +416,7 @@ protected:
|
|||
float _friction;
|
||||
float _lifetime;
|
||||
QString _script;
|
||||
quint64 _scriptTimestamp;
|
||||
QString _collisionSoundURL;
|
||||
glm::vec3 _registrationPoint;
|
||||
glm::vec3 _angularVelocity;
|
||||
|
|
|
@ -51,6 +51,7 @@ CONSTRUCT_PROPERTY(friction, ENTITY_ITEM_DEFAULT_FRICTION),
|
|||
CONSTRUCT_PROPERTY(lifetime, ENTITY_ITEM_DEFAULT_LIFETIME),
|
||||
CONSTRUCT_PROPERTY(created, UNKNOWN_CREATED_TIME),
|
||||
CONSTRUCT_PROPERTY(script, ENTITY_ITEM_DEFAULT_SCRIPT),
|
||||
CONSTRUCT_PROPERTY(scriptTimestamp, ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP),
|
||||
CONSTRUCT_PROPERTY(collisionSoundURL, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL),
|
||||
CONSTRUCT_PROPERTY(color, ),
|
||||
CONSTRUCT_PROPERTY(modelURL, ""),
|
||||
|
@ -98,6 +99,7 @@ CONSTRUCT_PROPERTY(backgroundMode, BACKGROUND_MODE_INHERIT),
|
|||
CONSTRUCT_PROPERTY(sourceUrl, ""),
|
||||
CONSTRUCT_PROPERTY(lineWidth, LineEntityItem::DEFAULT_LINE_WIDTH),
|
||||
CONSTRUCT_PROPERTY(linePoints, QVector<glm::vec3>()),
|
||||
CONSTRUCT_PROPERTY(faceCamera, TextEntityItem::DEFAULT_FACE_CAMERA),
|
||||
|
||||
|
||||
_id(UNKNOWN_ENTITY_ID),
|
||||
|
@ -299,6 +301,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_FRICTION, friction);
|
||||
CHECK_PROPERTY_CHANGE(PROP_LIFETIME, lifetime);
|
||||
CHECK_PROPERTY_CHANGE(PROP_SCRIPT, script);
|
||||
CHECK_PROPERTY_CHANGE(PROP_SCRIPT_TIMESTAMP, scriptTimestamp);
|
||||
CHECK_PROPERTY_CHANGE(PROP_COLLISION_SOUND_URL, collisionSoundURL);
|
||||
CHECK_PROPERTY_CHANGE(PROP_COLOR, color);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL);
|
||||
|
@ -349,6 +352,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_LINE_POINTS, linePoints);
|
||||
CHECK_PROPERTY_CHANGE(PROP_HREF, href);
|
||||
CHECK_PROPERTY_CHANGE(PROP_DESCRIPTION, description);
|
||||
CHECK_PROPERTY_CHANGE(PROP_FACE_CAMERA, faceCamera);
|
||||
|
||||
changedProperties += _stage.getChangedProperties();
|
||||
changedProperties += _atmosphere.getChangedProperties();
|
||||
|
@ -391,6 +395,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(created, created.toString(Qt::ISODate));
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(script);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(scriptTimestamp);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(registrationPoint);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(angularVelocity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(angularDamping);
|
||||
|
@ -444,6 +449,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(linePoints);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(href);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(description);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(faceCamera);
|
||||
|
||||
// Sitting properties support
|
||||
if (!skipDefaults) {
|
||||
|
@ -503,6 +509,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(friction, float, setFriction);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(lifetime, float, setLifetime);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(script, QString, setScript);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(scriptTimestamp, quint64, setScriptTimestamp);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(registrationPoint, glmVec3, setRegistrationPoint);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularVelocity, glmVec3, setAngularVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularDamping, float, setAngularDamping);
|
||||
|
@ -555,7 +562,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(linePoints, qVectorVec3, setLinePoints);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(href, QString, setHref);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(description, QString, setDescription);
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(faceCamera, bool, setFaceCamera);
|
||||
|
||||
if (!honorReadOnly) {
|
||||
// this is used by the json reader to set things that we don't want javascript to able to affect.
|
||||
|
@ -710,6 +717,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
APPEND_ENTITY_PROPERTY(PROP_FRICTION, properties.getFriction());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LIFETIME, properties.getLifetime());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, properties.getScript());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, properties.getScriptTimestamp());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, properties.getRegistrationPoint());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, properties.getAngularVelocity());
|
||||
|
@ -723,6 +731,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
APPEND_ENTITY_PROPERTY(PROP_HREF, properties.getHref());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DESCRIPTION, properties.getDescription());
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Web) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, properties.getSourceUrl());
|
||||
}
|
||||
|
@ -732,6 +741,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, properties.getLineHeight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, properties.getTextColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, properties.getBackgroundColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_FACE_CAMERA, properties.getFaceCamera());
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Model) {
|
||||
|
@ -961,7 +971,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RESTITUTION, float, setRestitution);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FRICTION, float, setFriction);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFETIME, float, setLifetime);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT,QString, setScript);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT, QString, setScript);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, xColor, setColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_VELOCITY, glm::vec3, setAngularVelocity);
|
||||
|
@ -975,6 +986,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_HREF, QString, setHref);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DESCRIPTION, QString, setDescription);
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Web) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl);
|
||||
}
|
||||
|
@ -984,6 +996,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_COLOR, xColor, setTextColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_COLOR, xColor, setBackgroundColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FACE_CAMERA, bool, setFaceCamera);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Model) {
|
||||
|
@ -1099,6 +1112,7 @@ void EntityItemProperties::markAllChanged() {
|
|||
_userDataChanged = true;
|
||||
_simulatorIDChanged = true;
|
||||
_scriptChanged = true;
|
||||
_scriptTimestampChanged = true;
|
||||
_collisionSoundURLChanged = true;
|
||||
_registrationPointChanged = true;
|
||||
_angularVelocityChanged = true;
|
||||
|
@ -1161,7 +1175,9 @@ void EntityItemProperties::markAllChanged() {
|
|||
|
||||
_hrefChanged = true;
|
||||
_descriptionChanged = true;
|
||||
|
||||
|
||||
_faceCameraChanged = true;
|
||||
|
||||
}
|
||||
|
||||
/// The maximum bounding cube for the entity, independent of it's rotation.
|
||||
|
|
|
@ -98,6 +98,7 @@ public:
|
|||
DEFINE_PROPERTY(PROP_LIFETIME, Lifetime, lifetime, float);
|
||||
DEFINE_PROPERTY(PROP_CREATED, Created, created, quint64);
|
||||
DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString);
|
||||
DEFINE_PROPERTY(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64);
|
||||
DEFINE_PROPERTY_REF(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor);
|
||||
DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString);
|
||||
|
@ -150,7 +151,8 @@ public:
|
|||
DEFINE_PROPERTY_REF(LINE_POINTS, LinePoints, linePoints, QVector<glm::vec3>);
|
||||
DEFINE_PROPERTY_REF(PROP_HREF, Href, href, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_DESCRIPTION, Description, description, QString);
|
||||
|
||||
DEFINE_PROPERTY(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool);
|
||||
|
||||
static QString getBackgroundModeString(BackgroundMode mode);
|
||||
|
||||
|
||||
|
@ -261,6 +263,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
|||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Friction, friction, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifetime, lifetime, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Script, script, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ScriptTimestamp, scriptTimestamp, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, CollisionSoundURL, collisionSoundURL, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Color, color, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ModelURL, modelURL, "");
|
||||
|
|
|
@ -32,6 +32,7 @@ const float ENTITY_ITEM_DEFAULT_GLOW_LEVEL = 0.0f;
|
|||
const bool ENTITY_ITEM_DEFAULT_VISIBLE = true;
|
||||
|
||||
const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString("");
|
||||
const quint64 ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP = 0;
|
||||
const QString ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL = QString("");
|
||||
const glm::vec3 ENTITY_ITEM_DEFAULT_REGISTRATION_POINT = ENTITY_ITEM_HALF_VEC3; // center
|
||||
|
||||
|
@ -66,6 +67,7 @@ const float ENTITY_ITEM_DEFAULT_FRICTION = 0.5f;
|
|||
|
||||
const bool ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS = false;
|
||||
const bool ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE = false;
|
||||
const bool ENTITY_ITEM_DEFAULT_BILLBOARDED = false;
|
||||
|
||||
const float ENTITY_ITEM_DEFAULT_CUTOFF = PI / 2;
|
||||
|
||||
|
|
|
@ -92,6 +92,7 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::vec3& v) { r
|
|||
inline QScriptValue convertScriptValue(QScriptEngine* e, float v) { return QScriptValue(v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, int v) { return QScriptValue(v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, quint32 v) { return QScriptValue(v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, quint64 v) { return QScriptValue((qsreal)v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, const QString& v) { return QScriptValue(v); }
|
||||
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, const xColor& v) { return xColorToScriptValue(e, v); }
|
||||
|
@ -134,6 +135,7 @@ typedef glm::vec3 glmVec3;
|
|||
typedef glm::quat glmQuat;
|
||||
typedef QVector<glm::vec3> qVectorVec3;
|
||||
inline float float_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); }
|
||||
inline quint64 quint64_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toULongLong(&isValid); }
|
||||
inline uint16_t uint16_t_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
|
||||
inline int int_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
|
||||
inline bool bool_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toBool(); }
|
||||
|
|
|
@ -122,8 +122,11 @@ enum EntityPropertyList {
|
|||
PROP_HREF,
|
||||
PROP_DESCRIPTION,
|
||||
|
||||
PROP_FACE_CAMERA,
|
||||
PROP_SCRIPT_TIMESTAMP,
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ATTENTION: add new properties ABOVE this line
|
||||
// ATTENTION: add new properties to end of list just ABOVE this line
|
||||
PROP_AFTER_LAST_ITEM,
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -185,6 +185,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
|||
// else client accepts what the server says
|
||||
|
||||
QString entityScriptBefore = entity->getScript();
|
||||
quint64 entityScriptTimestampBefore = entity->getScriptTimestamp();
|
||||
QString collisionSoundURLBefore = entity->getCollisionSoundURL();
|
||||
uint32_t preFlags = entity->getDirtyFlags();
|
||||
UpdateEntityOperator theOperator(this, containingElement, entity, properties);
|
||||
|
@ -206,8 +207,10 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
|||
}
|
||||
|
||||
QString entityScriptAfter = entity->getScript();
|
||||
if (entityScriptBefore != entityScriptAfter) {
|
||||
emitEntityScriptChanging(entity->getEntityItemID()); // the entity script has changed
|
||||
quint64 entityScriptTimestampAfter = entity->getScriptTimestamp();
|
||||
bool reload = entityScriptTimestampBefore != entityScriptTimestampAfter;
|
||||
if (entityScriptBefore != entityScriptAfter || reload) {
|
||||
emitEntityScriptChanging(entity->getEntityItemID(), reload); // the entity script has changed
|
||||
}
|
||||
maybeNotifyNewCollisionSoundURL(collisionSoundURLBefore, entity->getCollisionSoundURL());
|
||||
}
|
||||
|
@ -266,9 +269,10 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti
|
|||
return result;
|
||||
}
|
||||
|
||||
void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID) {
|
||||
emit entityScriptChanging(entityItemID);
|
||||
void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID, const bool reload) {
|
||||
emit entityScriptChanging(entityItemID, reload);
|
||||
}
|
||||
|
||||
void EntityTree::maybeNotifyNewCollisionSoundURL(const QString& previousCollisionSoundURL, const QString& nextCollisionSoundURL) {
|
||||
if (!nextCollisionSoundURL.isEmpty() && (nextCollisionSoundURL != previousCollisionSoundURL)) {
|
||||
emit newCollisionSoundURL(QUrl(nextCollisionSoundURL));
|
||||
|
|
|
@ -155,7 +155,7 @@ public:
|
|||
|
||||
void entityChanged(EntityItemPointer entity);
|
||||
|
||||
void emitEntityScriptChanging(const EntityItemID& entityItemID);
|
||||
void emitEntityScriptChanging(const EntityItemID& entityItemID, const bool reload);
|
||||
|
||||
void setSimulation(EntitySimulation* simulation);
|
||||
EntitySimulation* getSimulation() const { return _simulation; }
|
||||
|
@ -171,7 +171,7 @@ public:
|
|||
signals:
|
||||
void deletingEntity(const EntityItemID& entityID);
|
||||
void addingEntity(const EntityItemID& entityID);
|
||||
void entityScriptChanging(const EntityItemID& entityItemID);
|
||||
void entityScriptChanging(const EntityItemID& entityItemID, const bool reload);
|
||||
void newCollisionSoundURL(const QUrl& url);
|
||||
void clearingEntities();
|
||||
|
||||
|
|
|
@ -733,6 +733,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
|
|||
// 3) remember the old cube for the entity so we can mark it as dirty
|
||||
if (entityItem) {
|
||||
QString entityScriptBefore = entityItem->getScript();
|
||||
quint64 entityScriptTimestampBefore = entityItem->getScriptTimestamp();
|
||||
bool bestFitBefore = bestFitEntityBounds(entityItem);
|
||||
EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID);
|
||||
|
||||
|
@ -755,8 +756,10 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
|
|||
}
|
||||
|
||||
QString entityScriptAfter = entityItem->getScript();
|
||||
if (entityScriptBefore != entityScriptAfter) {
|
||||
_myTree->emitEntityScriptChanging(entityItemID); // the entity script has changed
|
||||
quint64 entityScriptTimestampAfter = entityItem->getScriptTimestamp();
|
||||
bool reload = entityScriptTimestampBefore != entityScriptTimestampAfter;
|
||||
if (entityScriptBefore != entityScriptAfter || reload) {
|
||||
_myTree->emitEntityScriptChanging(entityItemID, reload); // the entity script has changed
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
|
@ -27,6 +27,7 @@ const QString TextEntityItem::DEFAULT_TEXT("");
|
|||
const float TextEntityItem::DEFAULT_LINE_HEIGHT = 0.1f;
|
||||
const xColor TextEntityItem::DEFAULT_TEXT_COLOR = { 255, 255, 255 };
|
||||
const xColor TextEntityItem::DEFAULT_BACKGROUND_COLOR = { 0, 0, 0};
|
||||
const bool TextEntityItem::DEFAULT_FACE_CAMERA = false;
|
||||
|
||||
EntityItemPointer TextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return EntityItemPointer(new TextEntityItem(entityID, properties));
|
||||
|
@ -54,6 +55,7 @@ EntityItemProperties TextEntityItem::getProperties() const {
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textColor, getTextColorX);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(backgroundColor, getBackgroundColorX);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(faceCamera, getFaceCamera);
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -65,6 +67,7 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineHeight, setLineHeight);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textColor, setTextColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(backgroundColor, setBackgroundColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(faceCamera, setFaceCamera);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
|
@ -91,7 +94,8 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
READ_ENTITY_PROPERTY(PROP_LINE_HEIGHT, float, setLineHeight);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXT_COLOR, rgbColor, setTextColor);
|
||||
READ_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, rgbColor, setBackgroundColor);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_FACE_CAMERA, bool, setFaceCamera);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
@ -103,6 +107,7 @@ EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& p
|
|||
requestedProperties += PROP_LINE_HEIGHT;
|
||||
requestedProperties += PROP_TEXT_COLOR;
|
||||
requestedProperties += PROP_BACKGROUND_COLOR;
|
||||
requestedProperties += PROP_FACE_CAMERA;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
|
@ -120,6 +125,8 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
|
|||
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, getLineHeight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, getTextColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, getBackgroundColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_FACE_CAMERA, getFaceCamera());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|