mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 23:09:52 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into entityCollisions
This commit is contained in:
commit
efbe8ce757
38 changed files with 501 additions and 381 deletions
|
@ -117,6 +117,7 @@ function setupToolBars() {
|
||||||
leftMargin: TEXT_MARGIN,
|
leftMargin: TEXT_MARGIN,
|
||||||
topMargin: TEXT_MARGIN,
|
topMargin: TEXT_MARGIN,
|
||||||
alpha: ALPHA_OFF,
|
alpha: ALPHA_OFF,
|
||||||
|
backgroundAlpha: ALPHA_OFF,
|
||||||
visible: true
|
visible: true
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,7 @@ function setupTimer() {
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
visible: true
|
visible: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -129,6 +130,7 @@ function setupTimer() {
|
||||||
width: slider.w,
|
width: slider.w,
|
||||||
height: slider.h,
|
height: slider.h,
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
visible: true
|
visible: true
|
||||||
});
|
});
|
||||||
slider.foreground = Overlays.addOverlay("text", {
|
slider.foreground = Overlays.addOverlay("text", {
|
||||||
|
@ -138,6 +140,7 @@ function setupTimer() {
|
||||||
width: slider.pos * slider.w,
|
width: slider.pos * slider.w,
|
||||||
height: slider.h,
|
height: slider.h,
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
visible: true
|
visible: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -206,6 +206,7 @@ var progressDialog = (function () {
|
||||||
height: backgroundHeight,
|
height: backgroundHeight,
|
||||||
imageURL: backgroundUrl,
|
imageURL: backgroundUrl,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
backgroundAlpha: 0.9,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -216,6 +217,7 @@ var progressDialog = (function () {
|
||||||
textColor: textColor,
|
textColor: textColor,
|
||||||
backgroundColor: textBackground,
|
backgroundColor: textBackground,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
backgroundAlpha: 0.9,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -226,6 +228,7 @@ var progressDialog = (function () {
|
||||||
textColor: textColor,
|
textColor: textColor,
|
||||||
backgroundColor: textBackground,
|
backgroundColor: textBackground,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
backgroundAlpha: 0.9,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1169,24 +1172,22 @@ var toolBar = (function () {
|
||||||
menuItemHeight = Tool.IMAGE_HEIGHT / 2 - 2;
|
menuItemHeight = Tool.IMAGE_HEIGHT / 2 - 2;
|
||||||
|
|
||||||
loadURLMenuItem = Overlays.addOverlay("text", {
|
loadURLMenuItem = Overlays.addOverlay("text", {
|
||||||
x: newModelButton.x - menuItemWidth,
|
|
||||||
y: newModelButton.y + menuItemOffset,
|
|
||||||
height: menuItemHeight,
|
height: menuItemHeight,
|
||||||
backgroundColor: menuBackgroundColor,
|
backgroundColor: menuBackgroundColor,
|
||||||
topMargin: menuItemMargin,
|
topMargin: menuItemMargin,
|
||||||
text: "Model URL",
|
text: "Model URL",
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
backgroundAlpha: 0.9,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
loadFileMenuItem = Overlays.addOverlay("text", {
|
loadFileMenuItem = Overlays.addOverlay("text", {
|
||||||
x: newModelButton.x - menuItemWidth,
|
|
||||||
y: newModelButton.y + menuItemOffset + menuItemHeight,
|
|
||||||
height: menuItemHeight,
|
height: menuItemHeight,
|
||||||
backgroundColor: menuBackgroundColor,
|
backgroundColor: menuBackgroundColor,
|
||||||
topMargin: menuItemMargin,
|
topMargin: menuItemMargin,
|
||||||
text: "Model File",
|
text: "Model File",
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
backgroundAlpha: 0.9,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1493,6 +1494,7 @@ var ExportMenu = function (opts) {
|
||||||
width: scaleViewWidth,
|
width: scaleViewWidth,
|
||||||
height: height,
|
height: height,
|
||||||
alpha: 0.0,
|
alpha: 0.0,
|
||||||
|
backgroundAlpha: 0.0,
|
||||||
color: { red: 255, green: 255, blue: 255 },
|
color: { red: 255, green: 255, blue: 255 },
|
||||||
text: "1"
|
text: "1"
|
||||||
});
|
});
|
||||||
|
@ -2480,6 +2482,7 @@ function Tooltip() {
|
||||||
text: "",
|
text: "",
|
||||||
color: { red: 228, green: 228, blue: 228 },
|
color: { red: 228, green: 228, blue: 228 },
|
||||||
alpha: 0.8,
|
alpha: 0.8,
|
||||||
|
backgroundAlpha: 0.8,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
this.show = function (doShow) {
|
this.show = function (doShow) {
|
||||||
|
|
|
@ -319,7 +319,7 @@ function ScaleSelector() {
|
||||||
width: this.SECOND_PART, height: this.height,
|
width: this.SECOND_PART, height: this.height,
|
||||||
topMargin: 13,
|
topMargin: 13,
|
||||||
text: this.scale.toString(),
|
text: this.scale.toString(),
|
||||||
alpha: 0.9,
|
backgroundAlpha: 0.0,
|
||||||
visible: editToolsOn
|
visible: editToolsOn
|
||||||
});
|
});
|
||||||
this.powerOverlay = Overlays.addOverlay("text", {
|
this.powerOverlay = Overlays.addOverlay("text", {
|
||||||
|
@ -327,7 +327,7 @@ function ScaleSelector() {
|
||||||
width: this.SECOND_PART, height: this.height,
|
width: this.SECOND_PART, height: this.height,
|
||||||
leftMargin: 28,
|
leftMargin: 28,
|
||||||
text: this.power.toString(),
|
text: this.power.toString(),
|
||||||
alpha: 0.0,
|
backgroundAlpha: 0.0,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
this.setScale = function(scale) {
|
this.setScale = function(scale) {
|
||||||
|
|
|
@ -117,7 +117,7 @@ function ScaleSelector() {
|
||||||
width: this.SECOND_PART, height: this.height,
|
width: this.SECOND_PART, height: this.height,
|
||||||
topMargin: 13,
|
topMargin: 13,
|
||||||
text: this.scale.toString(),
|
text: this.scale.toString(),
|
||||||
alpha: 0.0,
|
backgroundAlpha: 0.0,
|
||||||
visible: editToolsOn,
|
visible: editToolsOn,
|
||||||
color: activeUIColor
|
color: activeUIColor
|
||||||
});
|
});
|
||||||
|
@ -126,7 +126,7 @@ function ScaleSelector() {
|
||||||
width: this.SECOND_PART, height: this.height,
|
width: this.SECOND_PART, height: this.height,
|
||||||
leftMargin: 28,
|
leftMargin: 28,
|
||||||
text: this.power.toString(),
|
text: this.power.toString(),
|
||||||
alpha: 0.0,
|
backgroundAlpha: 0.0,
|
||||||
visible: false,
|
visible: false,
|
||||||
color: activeUIColor
|
color: activeUIColor
|
||||||
});
|
});
|
||||||
|
|
|
@ -116,7 +116,7 @@ function ScaleSelector() {
|
||||||
width: this.SECOND_PART, height: this.height,
|
width: this.SECOND_PART, height: this.height,
|
||||||
topMargin: 13,
|
topMargin: 13,
|
||||||
text: this.scale.toString(),
|
text: this.scale.toString(),
|
||||||
alpha: 0.0,
|
backgroundAlpha: 0.0,
|
||||||
visible: editToolsOn,
|
visible: editToolsOn,
|
||||||
color: activeUIColor
|
color: activeUIColor
|
||||||
});
|
});
|
||||||
|
@ -125,7 +125,7 @@ function ScaleSelector() {
|
||||||
width: this.SECOND_PART, height: this.height,
|
width: this.SECOND_PART, height: this.height,
|
||||||
leftMargin: 28,
|
leftMargin: 28,
|
||||||
text: this.power.toString(),
|
text: this.power.toString(),
|
||||||
alpha: 0.0,
|
backgroundAlpha: 0.0,
|
||||||
visible: false,
|
visible: false,
|
||||||
color: activeUIColor
|
color: activeUIColor
|
||||||
});
|
});
|
||||||
|
|
|
@ -81,7 +81,7 @@ ExportMenu = function (opts) {
|
||||||
y: pos.y + margin,
|
y: pos.y + margin,
|
||||||
width: scaleViewWidth,
|
width: scaleViewWidth,
|
||||||
height: height,
|
height: height,
|
||||||
alpha: 0.0,
|
backgroundAlpha: 0.0,
|
||||||
color: { red: 255, green: 255, blue: 255 },
|
color: { red: 255, green: 255, blue: 255 },
|
||||||
text: "1"
|
text: "1"
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,6 +26,7 @@ function Tooltip() {
|
||||||
text: "",
|
text: "",
|
||||||
color: { red: 128, green: 128, blue: 128 },
|
color: { red: 128, green: 128, blue: 128 },
|
||||||
alpha: 0.2,
|
alpha: 0.2,
|
||||||
|
backgroundAlpha: 0.2,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
this.show = function (doShow) {
|
this.show = function (doShow) {
|
||||||
|
|
|
@ -390,6 +390,7 @@ var ZoomTool = function(opts) {
|
||||||
leftMargin: 4,
|
leftMargin: 4,
|
||||||
text: "+",
|
text: "+",
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
var decreaseButton = Overlays.addOverlay("text", {
|
var decreaseButton = Overlays.addOverlay("text", {
|
||||||
|
@ -403,6 +404,7 @@ var ZoomTool = function(opts) {
|
||||||
leftMargin: 4,
|
leftMargin: 4,
|
||||||
text: "-",
|
text: "-",
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
var zoomBar = Overlays.addOverlay("text", {
|
var zoomBar = Overlays.addOverlay("text", {
|
||||||
|
@ -416,6 +418,7 @@ var ZoomTool = function(opts) {
|
||||||
leftMargin: 4,
|
leftMargin: 4,
|
||||||
text: "",
|
text: "",
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
var zoomHandle = Overlays.addOverlay("text", {
|
var zoomHandle = Overlays.addOverlay("text", {
|
||||||
|
@ -428,6 +431,7 @@ var ZoomTool = function(opts) {
|
||||||
leftMargin: 4,
|
leftMargin: 4,
|
||||||
text: "",
|
text: "",
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -501,6 +505,7 @@ var ArrowTool = function(opts) {
|
||||||
leftMargin: 4,
|
leftMargin: 4,
|
||||||
text: "^",
|
text: "^",
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
var leftButton = Overlays.addOverlay("text", {
|
var leftButton = Overlays.addOverlay("text", {
|
||||||
|
@ -514,6 +519,7 @@ var ArrowTool = function(opts) {
|
||||||
leftMargin: 4,
|
leftMargin: 4,
|
||||||
text: "<",
|
text: "<",
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
var rightButton = Overlays.addOverlay("text", {
|
var rightButton = Overlays.addOverlay("text", {
|
||||||
|
@ -540,6 +546,7 @@ var ArrowTool = function(opts) {
|
||||||
leftMargin: 4,
|
leftMargin: 4,
|
||||||
text: "v",
|
text: "v",
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
var centerButton = Overlays.addOverlay("text", {
|
var centerButton = Overlays.addOverlay("text", {
|
||||||
|
@ -553,6 +560,7 @@ var ArrowTool = function(opts) {
|
||||||
leftMargin: 4,
|
leftMargin: 4,
|
||||||
text: "",
|
text: "",
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -368,6 +368,7 @@ SelectionDisplay = (function () {
|
||||||
color: { red: 0, green: 0, blue: 0},
|
color: { red: 0, green: 0, blue: 0},
|
||||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||||
alpha: 0.7,
|
alpha: 0.7,
|
||||||
|
backgroundAlpha: 0.7,
|
||||||
visible: false,
|
visible: false,
|
||||||
isFacingAvatar: true,
|
isFacingAvatar: true,
|
||||||
drawInFront: true,
|
drawInFront: true,
|
||||||
|
|
|
@ -40,6 +40,7 @@ progressDialog = (function () {
|
||||||
textColor: textColor,
|
textColor: textColor,
|
||||||
backgroundColor: textBackground,
|
backgroundColor: textBackground,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
backgroundAlpha: 0.9,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -50,6 +51,7 @@ progressDialog = (function () {
|
||||||
textColor: textColor,
|
textColor: textColor,
|
||||||
backgroundColor: textBackground,
|
backgroundColor: textBackground,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
backgroundAlpha: 0.9,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,7 @@ ToolBar = function(x, y, direction) {
|
||||||
width: this.width,
|
width: this.width,
|
||||||
height: this.height,
|
height: this.height,
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
this.spacing = [];
|
this.spacing = [];
|
||||||
|
@ -243,7 +244,10 @@ ToolBar = function(x, y, direction) {
|
||||||
this.tools[tool].setAlpha(alpha);
|
this.tools[tool].setAlpha(alpha);
|
||||||
}
|
}
|
||||||
if (this.back != null) {
|
if (this.back != null) {
|
||||||
Overlays.editOverlay(this.back, { alpha: alpha});
|
Overlays.editOverlay(this.back, {
|
||||||
|
alpha: alpha,
|
||||||
|
backgroundAlpha: alpha
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.tools[tool].setAlpha(alpha);
|
this.tools[tool].setAlpha(alpha);
|
||||||
|
@ -263,7 +267,7 @@ ToolBar = function(x, y, direction) {
|
||||||
((direction == ToolBar.VERTICAL) ? 1 : 2) * ToolBar.SPACING,
|
((direction == ToolBar.VERTICAL) ? 1 : 2) * ToolBar.SPACING,
|
||||||
visible: true,
|
visible: true,
|
||||||
backgroundColor: color,
|
backgroundColor: color,
|
||||||
alpha: alpha
|
backgroundAlpha: alpha
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ function drawLobby() {
|
||||||
};
|
};
|
||||||
|
|
||||||
var orbShellProps = {
|
var orbShellProps = {
|
||||||
url: HIFI_PUBLIC_BUCKET + "models/sets/Lobby/Lobby_v8/forStephen1/LobbyShell1.fbx",
|
url: HIFI_PUBLIC_BUCKET + "models/sets/Lobby/Lobby_v8/forStephen1/LobbyShell1.4_LightTag.fbx",
|
||||||
position: orbPosition,
|
position: orbPosition,
|
||||||
rotation: towardsMe,
|
rotation: towardsMe,
|
||||||
dimensions: orbDimensions,
|
dimensions: orbDimensions,
|
||||||
|
@ -113,6 +113,7 @@ function drawLobby() {
|
||||||
text: "",
|
text: "",
|
||||||
lineHeight: lineHeight,
|
lineHeight: lineHeight,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
backgroundAlpha: 0.9,
|
||||||
ignoreRayIntersection: true,
|
ignoreRayIntersection: true,
|
||||||
visible: false,
|
visible: false,
|
||||||
isFacingAvatar: true
|
isFacingAvatar: true
|
||||||
|
|
|
@ -140,24 +140,22 @@ var toolBar = (function () {
|
||||||
menuItemHeight = Tool.IMAGE_HEIGHT / 2 - 2;
|
menuItemHeight = Tool.IMAGE_HEIGHT / 2 - 2;
|
||||||
|
|
||||||
loadURLMenuItem = Overlays.addOverlay("text", {
|
loadURLMenuItem = Overlays.addOverlay("text", {
|
||||||
x: newModelButton.x - menuItemWidth,
|
|
||||||
y: newModelButton.y + menuItemOffset,
|
|
||||||
height: menuItemHeight,
|
height: menuItemHeight,
|
||||||
backgroundColor: menuBackgroundColor,
|
backgroundColor: menuBackgroundColor,
|
||||||
topMargin: menuItemMargin,
|
topMargin: menuItemMargin,
|
||||||
text: "Model URL",
|
text: "Model URL",
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
backgroundAlpha: 0.9,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
loadFileMenuItem = Overlays.addOverlay("text", {
|
loadFileMenuItem = Overlays.addOverlay("text", {
|
||||||
x: newModelButton.x - menuItemWidth,
|
|
||||||
y: newModelButton.y + menuItemOffset + menuItemHeight,
|
|
||||||
height: menuItemHeight,
|
height: menuItemHeight,
|
||||||
backgroundColor: menuBackgroundColor,
|
backgroundColor: menuBackgroundColor,
|
||||||
topMargin: menuItemMargin,
|
topMargin: menuItemMargin,
|
||||||
text: "Model File",
|
text: "Model File",
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
backgroundAlpha: 0.9,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,7 @@ function createNotification(text) {
|
||||||
color: textColor,
|
color: textColor,
|
||||||
backgroundColor: backColor,
|
backgroundColor: backColor,
|
||||||
alpha: backgroundAlpha,
|
alpha: backgroundAlpha,
|
||||||
|
backgroundAlpha: backgroundAlpha,
|
||||||
topMargin: topMargin,
|
topMargin: topMargin,
|
||||||
leftMargin: leftMargin,
|
leftMargin: leftMargin,
|
||||||
font: {size: fontSize},
|
font: {size: fontSize},
|
||||||
|
@ -160,7 +161,7 @@ function fadeIn(noticeIn, buttonIn) {
|
||||||
pauseTimer = Script.setInterval(function() {
|
pauseTimer = Script.setInterval(function() {
|
||||||
q++;
|
q++;
|
||||||
qFade = q / 10.0;
|
qFade = q / 10.0;
|
||||||
Overlays.editOverlay(noticeIn, {alpha: qFade});
|
Overlays.editOverlay(noticeIn, {alpha: qFade, backgroundAlpha: qFade});
|
||||||
Overlays.editOverlay(buttonIn, {alpha: qFade});
|
Overlays.editOverlay(buttonIn, {alpha: qFade});
|
||||||
if (q >= 9.0) {
|
if (q >= 9.0) {
|
||||||
Script.clearInterval(pauseTimer);
|
Script.clearInterval(pauseTimer);
|
||||||
|
@ -344,7 +345,7 @@ function fadeOut(noticeOut, buttonOut, arraysOut) {
|
||||||
pauseTimer = Script.setInterval(function() {
|
pauseTimer = Script.setInterval(function() {
|
||||||
r--;
|
r--;
|
||||||
rFade = r / 10.0;
|
rFade = r / 10.0;
|
||||||
Overlays.editOverlay(noticeOut, {alpha: rFade});
|
Overlays.editOverlay(noticeOut, {alpha: rFade, backgroundAlpha: rFade});
|
||||||
Overlays.editOverlay(buttonOut, {alpha: rFade});
|
Overlays.editOverlay(buttonOut, {alpha: rFade});
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
dismiss(noticeOut, buttonOut, arraysOut);
|
dismiss(noticeOut, buttonOut, arraysOut);
|
||||||
|
|
|
@ -69,7 +69,8 @@ var text = Overlays.addOverlay("text", {
|
||||||
topMargin: 4,
|
topMargin: 4,
|
||||||
leftMargin: 4,
|
leftMargin: 4,
|
||||||
text: "Here is some text.\nAnd a second line.",
|
text: "Here is some text.\nAnd a second line.",
|
||||||
alpha: 0.7
|
alpha: 0.7,
|
||||||
|
backgroundAlpha: 0.5
|
||||||
});
|
});
|
||||||
|
|
||||||
// This will create an image overlay, which starts out as invisible
|
// This will create an image overlay, which starts out as invisible
|
||||||
|
@ -170,6 +171,7 @@ var clipboardPreview = Overlays.addOverlay("clipboard", {
|
||||||
// Demonstrate retrieving overlay properties
|
// Demonstrate retrieving overlay properties
|
||||||
print("Text overlay text property value =\n" + Overlays.getProperty(text, "text"));
|
print("Text overlay text property value =\n" + Overlays.getProperty(text, "text"));
|
||||||
print("Text overlay alpha =\n" + Overlays.getProperty(text, "alpha"));
|
print("Text overlay alpha =\n" + Overlays.getProperty(text, "alpha"));
|
||||||
|
print("Text overlay background alpha =\n" + Overlays.getProperty(text, "backgroundAlpha"));
|
||||||
print("Text overlay visible =\n" + Overlays.getProperty(text, "visible"));
|
print("Text overlay visible =\n" + Overlays.getProperty(text, "visible"));
|
||||||
print("Text overlay font size =\n" + Overlays.getProperty(text, "font").size);
|
print("Text overlay font size =\n" + Overlays.getProperty(text, "font").size);
|
||||||
print("Text overlay anchor =\n" + Overlays.getProperty(text, "anchor"));
|
print("Text overlay anchor =\n" + Overlays.getProperty(text, "anchor"));
|
||||||
|
|
|
@ -57,6 +57,7 @@ var statusText = Overlays.addOverlay("text", {
|
||||||
height: 20,
|
height: 20,
|
||||||
backgroundColor: { red: 0, green: 0, blue: 0},
|
backgroundColor: { red: 0, green: 0, blue: 0},
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
backgroundAlpha: 1.0,
|
||||||
color: { red: 255, green: 255, blue: 255},
|
color: { red: 255, green: 255, blue: 255},
|
||||||
topMargin: 4,
|
topMargin: 4,
|
||||||
leftMargin: 4,
|
leftMargin: 4,
|
||||||
|
|
|
@ -44,6 +44,7 @@ var inputWindow = Overlays.addOverlay("text", {
|
||||||
color: textColor,
|
color: textColor,
|
||||||
backgroundColor: backColor,
|
backgroundColor: backColor,
|
||||||
alpha: backgroundAlpha,
|
alpha: backgroundAlpha,
|
||||||
|
backgroundAlpha: backgroundAlpha,
|
||||||
topMargin: topMargin,
|
topMargin: topMargin,
|
||||||
leftMargin: leftMargin,
|
leftMargin: leftMargin,
|
||||||
font: {size: fontSize},
|
font: {size: fontSize},
|
||||||
|
|
|
@ -150,7 +150,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat rotation = getRotation();
|
glm::quat rotation = getRotation();
|
||||||
if (needsSimulation() && _model->isActive()) {
|
if (needsToCallUpdate() && _model->isActive()) {
|
||||||
_model->setScaleToFit(true, dimensions);
|
_model->setScaleToFit(true, dimensions);
|
||||||
_model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
|
_model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
|
||||||
_model->setRotation(rotation);
|
_model->setRotation(rotation);
|
||||||
|
@ -253,8 +253,8 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderableModelEntityItem::needsSimulation() const {
|
bool RenderableModelEntityItem::needsToCallUpdate() const {
|
||||||
return _needsInitialSimulation || getSimulationState() == EntityItem::Moving;
|
return _needsInitialSimulation || ModelEntityItem::needsToCallUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItemProperties RenderableModelEntityItem::getProperties() const {
|
EntityItemProperties RenderableModelEntityItem::getProperties() const {
|
||||||
|
|
|
@ -57,9 +57,11 @@ public:
|
||||||
void** intersectedObject, bool precisionPicking) const;
|
void** intersectedObject, bool precisionPicking) const;
|
||||||
|
|
||||||
Model* getModel(EntityTreeRenderer* renderer);
|
Model* getModel(EntityTreeRenderer* renderer);
|
||||||
|
|
||||||
|
bool needsToCallUpdate() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void remapTextures();
|
void remapTextures();
|
||||||
bool needsSimulation() const;
|
|
||||||
|
|
||||||
Model* _model;
|
Model* _model;
|
||||||
bool _needsInitialSimulation;
|
bool _needsInitialSimulation;
|
||||||
|
|
|
@ -16,12 +16,14 @@
|
||||||
#include "ui/TextRenderer.h"
|
#include "ui/TextRenderer.h"
|
||||||
|
|
||||||
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
|
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
|
||||||
|
const float DEFAULT_BACKGROUND_ALPHA = 0.7f;
|
||||||
const float DEFAULT_MARGIN = 0.1f;
|
const float DEFAULT_MARGIN = 0.1f;
|
||||||
const int FIXED_FONT_POINT_SIZE = 40;
|
const int FIXED_FONT_POINT_SIZE = 40;
|
||||||
const float LINE_SCALE_RATIO = 1.2f;
|
const float LINE_SCALE_RATIO = 1.2f;
|
||||||
|
|
||||||
Text3DOverlay::Text3DOverlay() :
|
Text3DOverlay::Text3DOverlay() :
|
||||||
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
|
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
|
||||||
|
_backgroundAlpha(DEFAULT_BACKGROUND_ALPHA),
|
||||||
_lineHeight(0.1f),
|
_lineHeight(0.1f),
|
||||||
_leftMargin(DEFAULT_MARGIN),
|
_leftMargin(DEFAULT_MARGIN),
|
||||||
_topMargin(DEFAULT_MARGIN),
|
_topMargin(DEFAULT_MARGIN),
|
||||||
|
@ -35,6 +37,7 @@ Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) :
|
||||||
Planar3DOverlay(text3DOverlay),
|
Planar3DOverlay(text3DOverlay),
|
||||||
_text(text3DOverlay->_text),
|
_text(text3DOverlay->_text),
|
||||||
_backgroundColor(text3DOverlay->_backgroundColor),
|
_backgroundColor(text3DOverlay->_backgroundColor),
|
||||||
|
_backgroundAlpha(text3DOverlay->_backgroundAlpha),
|
||||||
_lineHeight(text3DOverlay->_lineHeight),
|
_lineHeight(text3DOverlay->_lineHeight),
|
||||||
_leftMargin(text3DOverlay->_leftMargin),
|
_leftMargin(text3DOverlay->_leftMargin),
|
||||||
_topMargin(text3DOverlay->_topMargin),
|
_topMargin(text3DOverlay->_topMargin),
|
||||||
|
@ -88,8 +91,8 @@ void Text3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
const float MAX_COLOR = 255.0f;
|
const float MAX_COLOR = 255.0f;
|
||||||
xColor backgroundColor = getBackgroundColor();
|
xColor backgroundColor = getBackgroundColor();
|
||||||
float alpha = getAlpha();
|
glColor4f(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR,
|
||||||
glColor4f(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, alpha);
|
getBackgroundAlpha());
|
||||||
|
|
||||||
glm::vec2 dimensions = getDimensions();
|
glm::vec2 dimensions = getDimensions();
|
||||||
glm::vec2 halfDimensions = dimensions * 0.5f;
|
glm::vec2 halfDimensions = dimensions * 0.5f;
|
||||||
|
@ -124,6 +127,7 @@ void Text3DOverlay::render(RenderArgs* args) {
|
||||||
enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y);
|
enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y);
|
||||||
|
|
||||||
glColor3f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR);
|
glColor3f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR);
|
||||||
|
float alpha = getAlpha();
|
||||||
QStringList lines = _text.split("\n");
|
QStringList lines = _text.split("\n");
|
||||||
int lineOffset = maxHeight;
|
int lineOffset = maxHeight;
|
||||||
foreach(QString thisLine, lines) {
|
foreach(QString thisLine, lines) {
|
||||||
|
@ -166,6 +170,10 @@ void Text3DOverlay::setProperties(const QScriptValue& properties) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (properties.property("backgroundAlpha").isValid()) {
|
||||||
|
_backgroundAlpha = properties.property("backgroundAlpha").toVariant().toFloat();
|
||||||
|
}
|
||||||
|
|
||||||
if (properties.property("lineHeight").isValid()) {
|
if (properties.property("lineHeight").isValid()) {
|
||||||
setLineHeight(properties.property("lineHeight").toVariant().toFloat());
|
setLineHeight(properties.property("lineHeight").toVariant().toFloat());
|
||||||
}
|
}
|
||||||
|
@ -200,6 +208,9 @@ QScriptValue Text3DOverlay::getProperty(const QString& property) {
|
||||||
if (property == "backgroundColor") {
|
if (property == "backgroundColor") {
|
||||||
return xColorToScriptValue(_scriptEngine, _backgroundColor);
|
return xColorToScriptValue(_scriptEngine, _backgroundColor);
|
||||||
}
|
}
|
||||||
|
if (property == "backgroundAlpha") {
|
||||||
|
return _backgroundAlpha;
|
||||||
|
}
|
||||||
if (property == "lineHeight") {
|
if (property == "lineHeight") {
|
||||||
return _lineHeight;
|
return _lineHeight;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ public:
|
||||||
float getBottomMargin() const { return _bottomMargin; }
|
float getBottomMargin() const { return _bottomMargin; }
|
||||||
bool getIsFacingAvatar() const { return _isFacingAvatar; }
|
bool getIsFacingAvatar() const { return _isFacingAvatar; }
|
||||||
xColor getBackgroundColor();
|
xColor getBackgroundColor();
|
||||||
|
float getBackgroundAlpha() const { return _backgroundAlpha; }
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
void setText(const QString& text) { _text = text; }
|
void setText(const QString& text) { _text = text; }
|
||||||
|
@ -59,6 +60,7 @@ private:
|
||||||
|
|
||||||
QString _text;
|
QString _text;
|
||||||
xColor _backgroundColor;
|
xColor _backgroundColor;
|
||||||
|
float _backgroundAlpha;
|
||||||
float _lineHeight;
|
float _lineHeight;
|
||||||
float _leftMargin;
|
float _leftMargin;
|
||||||
float _topMargin;
|
float _topMargin;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
TextOverlay::TextOverlay() :
|
TextOverlay::TextOverlay() :
|
||||||
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
|
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
|
||||||
|
_backgroundAlpha(DEFAULT_BACKGROUND_ALPHA),
|
||||||
_leftMargin(DEFAULT_MARGIN),
|
_leftMargin(DEFAULT_MARGIN),
|
||||||
_topMargin(DEFAULT_MARGIN),
|
_topMargin(DEFAULT_MARGIN),
|
||||||
_fontSize(DEFAULT_FONTSIZE)
|
_fontSize(DEFAULT_FONTSIZE)
|
||||||
|
@ -29,6 +30,7 @@ TextOverlay::TextOverlay(const TextOverlay* textOverlay) :
|
||||||
Overlay2D(textOverlay),
|
Overlay2D(textOverlay),
|
||||||
_text(textOverlay->_text),
|
_text(textOverlay->_text),
|
||||||
_backgroundColor(textOverlay->_backgroundColor),
|
_backgroundColor(textOverlay->_backgroundColor),
|
||||||
|
_backgroundAlpha(textOverlay->_backgroundAlpha),
|
||||||
_leftMargin(textOverlay->_leftMargin),
|
_leftMargin(textOverlay->_leftMargin),
|
||||||
_topMargin(textOverlay->_topMargin),
|
_topMargin(textOverlay->_topMargin),
|
||||||
_fontSize(textOverlay->_fontSize)
|
_fontSize(textOverlay->_fontSize)
|
||||||
|
@ -63,11 +65,10 @@ void TextOverlay::render(RenderArgs* args) {
|
||||||
return; // do nothing if we're not visible
|
return; // do nothing if we're not visible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const float MAX_COLOR = 255.0f;
|
const float MAX_COLOR = 255.0f;
|
||||||
xColor backgroundColor = getBackgroundColor();
|
xColor backgroundColor = getBackgroundColor();
|
||||||
float alpha = getAlpha();
|
glColor4f(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR,
|
||||||
glColor4f(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, alpha);
|
getBackgroundAlpha());
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glVertex2f(_bounds.left(), _bounds.top());
|
glVertex2f(_bounds.left(), _bounds.top());
|
||||||
|
@ -85,6 +86,7 @@ void TextOverlay::render(RenderArgs* args) {
|
||||||
int y = _bounds.top() + _topMargin + topAdjust;
|
int y = _bounds.top() + _topMargin + topAdjust;
|
||||||
|
|
||||||
glColor3f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR);
|
glColor3f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR);
|
||||||
|
float alpha = getAlpha();
|
||||||
QStringList lines = _text.split("\n");
|
QStringList lines = _text.split("\n");
|
||||||
int lineOffset = 0;
|
int lineOffset = 0;
|
||||||
foreach(QString thisLine, lines) {
|
foreach(QString thisLine, lines) {
|
||||||
|
@ -125,6 +127,10 @@ void TextOverlay::setProperties(const QScriptValue& properties) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (properties.property("backgroundAlpha").isValid()) {
|
||||||
|
_backgroundAlpha = properties.property("backgroundAlpha").toVariant().toFloat();
|
||||||
|
}
|
||||||
|
|
||||||
if (properties.property("leftMargin").isValid()) {
|
if (properties.property("leftMargin").isValid()) {
|
||||||
setLeftMargin(properties.property("leftMargin").toVariant().toInt());
|
setLeftMargin(properties.property("leftMargin").toVariant().toInt());
|
||||||
}
|
}
|
||||||
|
@ -150,6 +156,9 @@ QScriptValue TextOverlay::getProperty(const QString& property) {
|
||||||
if (property == "backgroundColor") {
|
if (property == "backgroundColor") {
|
||||||
return xColorToScriptValue(_scriptEngine, _backgroundColor);
|
return xColorToScriptValue(_scriptEngine, _backgroundColor);
|
||||||
}
|
}
|
||||||
|
if (property == "backgroundAlpha") {
|
||||||
|
return _backgroundAlpha;
|
||||||
|
}
|
||||||
if (property == "leftMargin") {
|
if (property == "leftMargin") {
|
||||||
return _leftMargin;
|
return _leftMargin;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "Overlay2D.h"
|
#include "Overlay2D.h"
|
||||||
|
|
||||||
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
|
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
|
||||||
|
const float DEFAULT_BACKGROUND_ALPHA = 0.7f;
|
||||||
const int DEFAULT_MARGIN = 10;
|
const int DEFAULT_MARGIN = 10;
|
||||||
const int DEFAULT_FONTSIZE = 11;
|
const int DEFAULT_FONTSIZE = 11;
|
||||||
const int DEFAULT_FONT_WEIGHT = 50;
|
const int DEFAULT_FONT_WEIGHT = 50;
|
||||||
|
@ -46,6 +47,7 @@ public:
|
||||||
int getLeftMargin() const { return _leftMargin; }
|
int getLeftMargin() const { return _leftMargin; }
|
||||||
int getTopMargin() const { return _topMargin; }
|
int getTopMargin() const { return _topMargin; }
|
||||||
xColor getBackgroundColor();
|
xColor getBackgroundColor();
|
||||||
|
float getBackgroundAlpha() const { return _backgroundAlpha; }
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
void setText(const QString& text) { _text = text; }
|
void setText(const QString& text) { _text = text; }
|
||||||
|
@ -62,6 +64,7 @@ public:
|
||||||
private:
|
private:
|
||||||
QString _text;
|
QString _text;
|
||||||
xColor _backgroundColor;
|
xColor _backgroundColor;
|
||||||
|
float _backgroundAlpha;
|
||||||
int _leftMargin;
|
int _leftMargin;
|
||||||
int _topMargin;
|
int _topMargin;
|
||||||
int _fontSize;
|
int _fontSize;
|
||||||
|
|
|
@ -209,7 +209,9 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) {
|
||||||
propertiesA.setPosition(newPositionA * (float)TREE_SCALE);
|
propertiesA.setPosition(newPositionA * (float)TREE_SCALE);
|
||||||
propertiesA.setLastEdited(now);
|
propertiesA.setLastEdited(now);
|
||||||
|
|
||||||
_entityTree->updateEntity(idA, propertiesA);
|
// NOTE: EntityTree::updateEntity() will cause the entity to get sorted correctly in the EntitySimulation,
|
||||||
|
// thereby waking up static non-moving entities.
|
||||||
|
_entityTree->updateEntity(entityA, propertiesA);
|
||||||
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idA, propertiesA);
|
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idA, propertiesA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +228,9 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) {
|
||||||
propertiesB.setPosition(newPositionB * (float)TREE_SCALE);
|
propertiesB.setPosition(newPositionB * (float)TREE_SCALE);
|
||||||
propertiesB.setLastEdited(now);
|
propertiesB.setLastEdited(now);
|
||||||
|
|
||||||
_entityTree->updateEntity(idB, propertiesB);
|
// NOTE: EntityTree::updateEntity() will cause the entity to get sorted correctly in the EntitySimulation,
|
||||||
|
// thereby waking up static non-moving entities.
|
||||||
|
_entityTree->updateEntity(entityB, propertiesB);
|
||||||
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idB, propertiesB);
|
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idB, propertiesB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,6 +336,6 @@ void EntityCollisionSystem::applyHardCollision(EntityItem* entity, const Collisi
|
||||||
properties.setVelocity(velocity * (float)TREE_SCALE);
|
properties.setVelocity(velocity * (float)TREE_SCALE);
|
||||||
properties.setLastEdited(usecTimestampNow());
|
properties.setLastEdited(usecTimestampNow());
|
||||||
|
|
||||||
_entityTree->updateEntity(entityItemID, properties);
|
_entityTree->updateEntity(entity, properties);
|
||||||
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, entityItemID, properties);
|
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, entityItemID, properties);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ const float EntityItem::DEFAULT_LOCAL_RENDER_ALPHA = 1.0f;
|
||||||
const float EntityItem::DEFAULT_MASS = 1.0f;
|
const float EntityItem::DEFAULT_MASS = 1.0f;
|
||||||
const float EntityItem::DEFAULT_LIFETIME = EntityItem::IMMORTAL;
|
const float EntityItem::DEFAULT_LIFETIME = EntityItem::IMMORTAL;
|
||||||
const QString EntityItem::DEFAULT_USER_DATA = QString("");
|
const QString EntityItem::DEFAULT_USER_DATA = QString("");
|
||||||
const float EntityItem::DEFAULT_DAMPING = 0.5f;
|
const float EntityItem::DEFAULT_DAMPING = 2.0f;
|
||||||
const glm::vec3 EntityItem::NO_VELOCITY = glm::vec3(0, 0, 0);
|
const glm::vec3 EntityItem::NO_VELOCITY = glm::vec3(0, 0, 0);
|
||||||
const float EntityItem::EPSILON_VELOCITY_LENGTH = (1.0f / 1000.0f) / (float)TREE_SCALE; // really small: 1mm/second
|
const float EntityItem::EPSILON_VELOCITY_LENGTH = (1.0f / 1000.0f) / (float)TREE_SCALE; // really small: 1mm/second
|
||||||
const glm::vec3 EntityItem::DEFAULT_VELOCITY = EntityItem::NO_VELOCITY;
|
const glm::vec3 EntityItem::DEFAULT_VELOCITY = EntityItem::NO_VELOCITY;
|
||||||
|
@ -42,7 +42,7 @@ const glm::vec3 EntityItem::DEFAULT_DIMENSIONS = glm::vec3(0.1f, 0.1f, 0.1f);
|
||||||
const glm::vec3 EntityItem::DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f, 0.5f, 0.5f); // center
|
const glm::vec3 EntityItem::DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f, 0.5f, 0.5f); // center
|
||||||
const glm::vec3 EntityItem::NO_ANGULAR_VELOCITY = glm::vec3(0.0f, 0.0f, 0.0f);
|
const glm::vec3 EntityItem::NO_ANGULAR_VELOCITY = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
const glm::vec3 EntityItem::DEFAULT_ANGULAR_VELOCITY = NO_ANGULAR_VELOCITY;
|
const glm::vec3 EntityItem::DEFAULT_ANGULAR_VELOCITY = NO_ANGULAR_VELOCITY;
|
||||||
const float EntityItem::DEFAULT_ANGULAR_DAMPING = 0.5f;
|
const float EntityItem::DEFAULT_ANGULAR_DAMPING = 2.0f;
|
||||||
const bool EntityItem::DEFAULT_VISIBLE = true;
|
const bool EntityItem::DEFAULT_VISIBLE = true;
|
||||||
const bool EntityItem::DEFAULT_IGNORE_FOR_COLLISIONS = false;
|
const bool EntityItem::DEFAULT_IGNORE_FOR_COLLISIONS = false;
|
||||||
const bool EntityItem::DEFAULT_COLLISIONS_WILL_MOVE = false;
|
const bool EntityItem::DEFAULT_COLLISIONS_WILL_MOVE = false;
|
||||||
|
@ -58,6 +58,7 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) {
|
||||||
_lastEditedFromRemote = 0;
|
_lastEditedFromRemote = 0;
|
||||||
_lastEditedFromRemoteInRemoteTime = 0;
|
_lastEditedFromRemoteInRemoteTime = 0;
|
||||||
|
|
||||||
|
_lastSimulated = 0;
|
||||||
_lastUpdated = 0;
|
_lastUpdated = 0;
|
||||||
_created = 0; // TODO: when do we actually want to make this "now"
|
_created = 0; // TODO: when do we actually want to make this "now"
|
||||||
_changedOnServer = 0;
|
_changedOnServer = 0;
|
||||||
|
@ -88,12 +89,12 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) {
|
||||||
_lastEdited = 0;
|
_lastEdited = 0;
|
||||||
_lastEditedFromRemote = 0;
|
_lastEditedFromRemote = 0;
|
||||||
_lastEditedFromRemoteInRemoteTime = 0;
|
_lastEditedFromRemoteInRemoteTime = 0;
|
||||||
|
_lastSimulated = 0;
|
||||||
_lastUpdated = 0;
|
_lastUpdated = 0;
|
||||||
_created = 0;
|
_created = 0;
|
||||||
_updateFlags = 0;
|
_dirtyFlags = 0;
|
||||||
_changedOnServer = 0;
|
_changedOnServer = 0;
|
||||||
initFromEntityItemID(entityItemID);
|
initFromEntityItemID(entityItemID);
|
||||||
_simulationState = EntityItem::Static;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) {
|
EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) {
|
||||||
|
@ -101,13 +102,13 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert
|
||||||
_lastEdited = 0;
|
_lastEdited = 0;
|
||||||
_lastEditedFromRemote = 0;
|
_lastEditedFromRemote = 0;
|
||||||
_lastEditedFromRemoteInRemoteTime = 0;
|
_lastEditedFromRemoteInRemoteTime = 0;
|
||||||
|
_lastSimulated = 0;
|
||||||
_lastUpdated = 0;
|
_lastUpdated = 0;
|
||||||
_created = properties.getCreated();
|
_created = properties.getCreated();
|
||||||
_updateFlags = 0;
|
_dirtyFlags = 0;
|
||||||
_changedOnServer = 0;
|
_changedOnServer = 0;
|
||||||
initFromEntityItemID(entityItemID);
|
initFromEntityItemID(entityItemID);
|
||||||
setProperties(properties, true); // force copy
|
setProperties(properties, true); // force copy
|
||||||
_simulationState = EntityItem::Static;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||||
|
@ -154,7 +155,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
||||||
ByteCountCoded<quint32> typeCoder = getType();
|
ByteCountCoded<quint32> typeCoder = getType();
|
||||||
QByteArray encodedType = typeCoder;
|
QByteArray encodedType = typeCoder;
|
||||||
|
|
||||||
quint64 updateDelta = getLastUpdated() <= getLastEdited() ? 0 : getLastUpdated() - getLastEdited();
|
quint64 updateDelta = getLastSimulated() <= getLastEdited() ? 0 : getLastSimulated() - getLastEdited();
|
||||||
ByteCountCoded<quint64> updateDeltaCoder = updateDelta;
|
ByteCountCoded<quint64> updateDeltaCoder = updateDelta;
|
||||||
QByteArray encodedUpdateDelta = updateDeltaCoder;
|
QByteArray encodedUpdateDelta = updateDeltaCoder;
|
||||||
EntityPropertyFlags propertyFlags(PROP_LAST_ITEM);
|
EntityPropertyFlags propertyFlags(PROP_LAST_ITEM);
|
||||||
|
@ -450,9 +451,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
ByteCountCoded<quint64> updateDeltaCoder = encodedUpdateDelta;
|
ByteCountCoded<quint64> updateDeltaCoder = encodedUpdateDelta;
|
||||||
quint64 updateDelta = updateDeltaCoder;
|
quint64 updateDelta = updateDeltaCoder;
|
||||||
if (overwriteLocalData) {
|
if (overwriteLocalData) {
|
||||||
_lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that for _lastEdited
|
_lastSimulated = _lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that for _lastEdited
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
qDebug() << "_lastUpdated=" << _lastUpdated;
|
qDebug() << "_lastUpdated =" << _lastUpdated;
|
||||||
qDebug() << "_lastEdited=" << _lastEdited;
|
qDebug() << "_lastEdited=" << _lastEdited;
|
||||||
qDebug() << "lastEditedFromBufferAdjusted=" << lastEditedFromBufferAdjusted;
|
qDebug() << "lastEditedFromBufferAdjusted=" << lastEditedFromBufferAdjusted;
|
||||||
}
|
}
|
||||||
|
@ -565,20 +566,20 @@ bool EntityItem::isRestingOnSurface() const {
|
||||||
&& _gravity.y < 0.0f;
|
&& _gravity.y < 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::update(const quint64& updateTime) {
|
void EntityItem::simulate(const quint64& now) {
|
||||||
bool wantDebug = false;
|
bool wantDebug = false;
|
||||||
|
|
||||||
if (_lastUpdated == 0) {
|
if (_lastSimulated == 0) {
|
||||||
_lastUpdated = updateTime;
|
_lastSimulated = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
float timeElapsed = (float)(updateTime - _lastUpdated) / (float)(USECS_PER_SECOND);
|
float timeElapsed = (float)(now - _lastSimulated) / (float)(USECS_PER_SECOND);
|
||||||
|
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
qDebug() << "********** EntityItem::update()";
|
qDebug() << "********** EntityItem::update()";
|
||||||
qDebug() << " entity ID=" << getEntityItemID();
|
qDebug() << " entity ID=" << getEntityItemID();
|
||||||
qDebug() << " updateTime=" << updateTime;
|
qDebug() << " now=" << now;
|
||||||
qDebug() << " _lastUpdated=" << _lastUpdated;
|
qDebug() << " _lastSimulated=" << _lastSimulated;
|
||||||
qDebug() << " timeElapsed=" << timeElapsed;
|
qDebug() << " timeElapsed=" << timeElapsed;
|
||||||
qDebug() << " hasVelocity=" << hasVelocity();
|
qDebug() << " hasVelocity=" << hasVelocity();
|
||||||
qDebug() << " hasGravity=" << hasGravity();
|
qDebug() << " hasGravity=" << hasGravity();
|
||||||
|
@ -611,10 +612,10 @@ void EntityItem::update(const quint64& updateTime) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastUpdated = updateTime;
|
_lastSimulated = now;
|
||||||
|
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
qDebug() << " ********** EntityItem::update() .... SETTING _lastUpdated=" << _lastUpdated;
|
qDebug() << " ********** EntityItem::update() .... SETTING _lastSimulated=" << _lastSimulated;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasAngularVelocity()) {
|
if (hasAngularVelocity()) {
|
||||||
|
@ -631,13 +632,13 @@ void EntityItem::update(const quint64& updateTime) {
|
||||||
setRotation(rotation);
|
setRotation(rotation);
|
||||||
|
|
||||||
// handle damping for angular velocity
|
// handle damping for angular velocity
|
||||||
if (getAngularDamping() > 0.0f) {
|
float dampingTimescale = getAngularDamping();
|
||||||
glm::vec3 dampingResistance = getAngularVelocity() * getAngularDamping();
|
if (dampingTimescale > 0.0f) {
|
||||||
glm::vec3 newAngularVelocity = getAngularVelocity() - (dampingResistance * timeElapsed);
|
float dampingFactor = glm::clamp(timeElapsed / dampingTimescale, 0.0f, 1.0f);
|
||||||
|
glm::vec3 newAngularVelocity = (1.0f - dampingFactor) * getAngularVelocity();
|
||||||
setAngularVelocity(newAngularVelocity);
|
setAngularVelocity(newAngularVelocity);
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
qDebug() << " getDamping():" << getDamping();
|
qDebug() << " dampingTimescale :" << dampingTimescale;
|
||||||
qDebug() << " dampingResistance:" << dampingResistance;
|
|
||||||
qDebug() << " newAngularVelocity:" << newAngularVelocity;
|
qDebug() << " newAngularVelocity:" << newAngularVelocity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -688,13 +689,15 @@ void EntityItem::update(const quint64& updateTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle damping for velocity
|
// handle damping for velocity
|
||||||
glm::vec3 dampingResistance = velocity * getDamping();
|
float dampingTimescale = getDamping();
|
||||||
if (wantDebug) {
|
if (dampingTimescale > 0.0f) {
|
||||||
qDebug() << " getDamping():" << getDamping();
|
float dampingFactor = glm::clamp(timeElapsed / dampingTimescale, 0.0f, 1.0f);
|
||||||
qDebug() << " dampingResistance:" << dampingResistance;
|
velocity *= (1.0f - dampingFactor);
|
||||||
qDebug() << " dampingResistance * timeElapsed:" << dampingResistance * timeElapsed;
|
if (wantDebug) {
|
||||||
|
qDebug() << " dampingTimescale:" << dampingTimescale;
|
||||||
|
qDebug() << " newVelocity:" << velocity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
velocity -= dampingResistance * timeElapsed;
|
|
||||||
|
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
qDebug() << " velocity AFTER dampingResistance:" << velocity;
|
qDebug() << " velocity AFTER dampingResistance:" << velocity;
|
||||||
|
@ -707,6 +710,7 @@ void EntityItem::update(const quint64& updateTime) {
|
||||||
velocity = NO_VELOCITY;
|
velocity = NO_VELOCITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: the simulation should NOT set any DirtyFlags on this entity
|
||||||
setPosition(position); // this will automatically recalculate our collision shape
|
setPosition(position); // this will automatically recalculate our collision shape
|
||||||
setVelocity(velocity);
|
setVelocity(velocity);
|
||||||
|
|
||||||
|
@ -719,20 +723,18 @@ void EntityItem::update(const quint64& updateTime) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItem::SimulationState EntityItem::computeSimulationState() const {
|
bool EntityItem::isMoving() const {
|
||||||
if (hasVelocity() || (hasGravity() && !isRestingOnSurface()) || hasAngularVelocity()) {
|
return hasVelocity() || (hasGravity() && !isRestingOnSurface()) || hasAngularVelocity();
|
||||||
return EntityItem::Moving;
|
|
||||||
}
|
|
||||||
if (isMortal()) {
|
|
||||||
return EntityItem::Mortal;
|
|
||||||
}
|
|
||||||
return EntityItem::Static;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityItem::lifetimeHasExpired() const {
|
bool EntityItem::lifetimeHasExpired() const {
|
||||||
return isMortal() && (getAge() > getLifetime());
|
return isMortal() && (getAge() > getLifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quint64 EntityItem::getExpiry() const {
|
||||||
|
return _created + (quint64)(_lifetime * (float)USECS_PER_SECOND);
|
||||||
|
}
|
||||||
|
|
||||||
EntityItemProperties EntityItem::getProperties() const {
|
EntityItemProperties EntityItem::getProperties() const {
|
||||||
EntityItemProperties properties;
|
EntityItemProperties properties;
|
||||||
properties._id = getID();
|
properties._id = getID();
|
||||||
|
@ -778,23 +780,23 @@ bool EntityItem::setProperties(const EntityItemProperties& properties, bool forc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, setPositionInMeters); // this will call recalculate collision shape if needed
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, updatePositionInMeters); // this will call recalculate collision shape if needed
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, setDimensionsInMeters); // NOTE: radius is obsolete
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, updateDimensionsInMeters); // NOTE: radius is obsolete
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, setRotation);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, updateRotation);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(mass, setMass);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(mass, updateMass);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, setVelocityInMeters);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, updateVelocityInMeters);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, setGravityInMeters);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, updateGravityInMeters);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(damping, setDamping);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(damping, setDamping);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, setLifetime);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, updateLifetime);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, updateScript);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularVelocity, setAngularVelocity);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularVelocity, updateAngularVelocity);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularDamping, setAngularDamping);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularDamping, setAngularDamping);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignoreForCollisions, setIgnoreForCollisions);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignoreForCollisions, updateIgnoreForCollisions);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, setCollisionsWillMove);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, updateCollisionsWillMove);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
|
||||||
|
|
||||||
|
@ -948,7 +950,7 @@ void EntityItem::updatePosition(const glm::vec3& value) {
|
||||||
if (_position != value) {
|
if (_position != value) {
|
||||||
_position = value;
|
_position = value;
|
||||||
recalculateCollisionShape();
|
recalculateCollisionShape();
|
||||||
_updateFlags |= EntityItem::UPDATE_POSITION;
|
_dirtyFlags |= EntityItem::DIRTY_POSITION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -957,7 +959,7 @@ void EntityItem::updatePositionInMeters(const glm::vec3& value) {
|
||||||
if (_position != position) {
|
if (_position != position) {
|
||||||
_position = position;
|
_position = position;
|
||||||
recalculateCollisionShape();
|
recalculateCollisionShape();
|
||||||
_updateFlags |= EntityItem::UPDATE_POSITION;
|
_dirtyFlags |= EntityItem::DIRTY_POSITION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,7 +967,7 @@ void EntityItem::updateDimensions(const glm::vec3& value) {
|
||||||
if (_dimensions != value) {
|
if (_dimensions != value) {
|
||||||
_dimensions = value;
|
_dimensions = value;
|
||||||
recalculateCollisionShape();
|
recalculateCollisionShape();
|
||||||
_updateFlags |= EntityItem::UPDATE_SHAPE;
|
_dirtyFlags |= EntityItem::DIRTY_SHAPE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -974,7 +976,7 @@ void EntityItem::updateDimensionsInMeters(const glm::vec3& value) {
|
||||||
if (_dimensions != dimensions) {
|
if (_dimensions != dimensions) {
|
||||||
_dimensions = dimensions;
|
_dimensions = dimensions;
|
||||||
recalculateCollisionShape();
|
recalculateCollisionShape();
|
||||||
_updateFlags |= EntityItem::UPDATE_SHAPE;
|
_dirtyFlags |= EntityItem::DIRTY_SHAPE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,21 +984,21 @@ void EntityItem::updateRotation(const glm::quat& rotation) {
|
||||||
if (_rotation != rotation) {
|
if (_rotation != rotation) {
|
||||||
_rotation = rotation;
|
_rotation = rotation;
|
||||||
recalculateCollisionShape();
|
recalculateCollisionShape();
|
||||||
_updateFlags |= EntityItem::UPDATE_POSITION;
|
_dirtyFlags |= EntityItem::DIRTY_POSITION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::updateMass(float value) {
|
void EntityItem::updateMass(float value) {
|
||||||
if (_mass != value) {
|
if (_mass != value) {
|
||||||
_mass = value;
|
_mass = value;
|
||||||
_updateFlags |= EntityItem::UPDATE_MASS;
|
_dirtyFlags |= EntityItem::DIRTY_MASS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::updateVelocity(const glm::vec3& value) {
|
void EntityItem::updateVelocity(const glm::vec3& value) {
|
||||||
if (_velocity != value) {
|
if (_velocity != value) {
|
||||||
_velocity = value;
|
_velocity = value;
|
||||||
_updateFlags |= EntityItem::UPDATE_VELOCITY;
|
_dirtyFlags |= EntityItem::DIRTY_VELOCITY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1004,14 +1006,14 @@ void EntityItem::updateVelocityInMeters(const glm::vec3& value) {
|
||||||
glm::vec3 velocity = value / (float) TREE_SCALE;
|
glm::vec3 velocity = value / (float) TREE_SCALE;
|
||||||
if (_velocity != velocity) {
|
if (_velocity != velocity) {
|
||||||
_velocity = velocity;
|
_velocity = velocity;
|
||||||
_updateFlags |= EntityItem::UPDATE_VELOCITY;
|
_dirtyFlags |= EntityItem::DIRTY_VELOCITY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::updateGravity(const glm::vec3& value) {
|
void EntityItem::updateGravity(const glm::vec3& value) {
|
||||||
if (_gravity != value) {
|
if (_gravity != value) {
|
||||||
_gravity = value;
|
_gravity = value;
|
||||||
_updateFlags |= EntityItem::UPDATE_VELOCITY;
|
_dirtyFlags |= EntityItem::DIRTY_VELOCITY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1019,36 +1021,42 @@ void EntityItem::updateGravityInMeters(const glm::vec3& value) {
|
||||||
glm::vec3 gravity = value / (float) TREE_SCALE;
|
glm::vec3 gravity = value / (float) TREE_SCALE;
|
||||||
if (_gravity != gravity) {
|
if (_gravity != gravity) {
|
||||||
_gravity = gravity;
|
_gravity = gravity;
|
||||||
_updateFlags |= EntityItem::UPDATE_VELOCITY;
|
_dirtyFlags |= EntityItem::DIRTY_VELOCITY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::updateAngularVelocity(const glm::vec3& value) {
|
void EntityItem::updateAngularVelocity(const glm::vec3& value) {
|
||||||
if (_angularVelocity != value) {
|
if (_angularVelocity != value) {
|
||||||
_angularVelocity = value;
|
_angularVelocity = value;
|
||||||
_updateFlags |= EntityItem::UPDATE_VELOCITY;
|
_dirtyFlags |= EntityItem::DIRTY_VELOCITY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::updateIgnoreForCollisions(bool value) {
|
void EntityItem::updateIgnoreForCollisions(bool value) {
|
||||||
if (_ignoreForCollisions != value) {
|
if (_ignoreForCollisions != value) {
|
||||||
_ignoreForCollisions = value;
|
_ignoreForCollisions = value;
|
||||||
_updateFlags |= EntityItem::UPDATE_COLLISION_GROUP;
|
_dirtyFlags |= EntityItem::DIRTY_COLLISION_GROUP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::updateCollisionsWillMove(bool value) {
|
void EntityItem::updateCollisionsWillMove(bool value) {
|
||||||
if (_collisionsWillMove != value) {
|
if (_collisionsWillMove != value) {
|
||||||
_collisionsWillMove = value;
|
_collisionsWillMove = value;
|
||||||
_updateFlags |= EntityItem::UPDATE_MOTION_TYPE;
|
_dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::updateLifetime(float value) {
|
void EntityItem::updateLifetime(float value) {
|
||||||
if (_lifetime != value) {
|
if (_lifetime != value) {
|
||||||
_lifetime = value;
|
_lifetime = value;
|
||||||
_updateFlags |= EntityItem::UPDATE_LIFETIME;
|
_dirtyFlags |= EntityItem::DIRTY_LIFETIME;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityItem::updateScript(const QString& value) {
|
||||||
|
if (_script != value) {
|
||||||
|
_script = value;
|
||||||
|
_dirtyFlags |= EntityItem::DIRTY_SCRIPT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,15 +41,17 @@ class EntityTreeElementExtraEncodeData;
|
||||||
class EntityItem {
|
class EntityItem {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum EntityUpdateFlags {
|
enum EntityDirtyFlags {
|
||||||
UPDATE_POSITION = 0x0001,
|
DIRTY_POSITION = 0x0001,
|
||||||
UPDATE_VELOCITY = 0x0002,
|
DIRTY_VELOCITY = 0x0002,
|
||||||
UPDATE_MASS = 0x0004,
|
DIRTY_MASS = 0x0004,
|
||||||
UPDATE_COLLISION_GROUP = 0x0008,
|
DIRTY_COLLISION_GROUP = 0x0008,
|
||||||
UPDATE_MOTION_TYPE = 0x0010,
|
DIRTY_MOTION_TYPE = 0x0010,
|
||||||
UPDATE_SHAPE = 0x0020,
|
DIRTY_SHAPE = 0x0020,
|
||||||
UPDATE_LIFETIME = 0x0040
|
DIRTY_LIFETIME = 0x0040,
|
||||||
//UPDATE_APPEARANCE = 0x8000,
|
// add new simulation-relevant flags above
|
||||||
|
// all other flags below
|
||||||
|
DIRTY_SCRIPT = 0x8000
|
||||||
};
|
};
|
||||||
|
|
||||||
DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly
|
DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly
|
||||||
|
@ -77,12 +79,12 @@ public:
|
||||||
/// has changed. This will be called with properties change or when new data is loaded from a stream
|
/// has changed. This will be called with properties change or when new data is loaded from a stream
|
||||||
virtual void somethingChangedNotification() { }
|
virtual void somethingChangedNotification() { }
|
||||||
|
|
||||||
quint64 getLastUpdated() const { return _lastUpdated; } /// Last simulated time of this entity universal usecs
|
quint64 getLastSimulated() const { return _lastSimulated; } /// Last simulated time of this entity universal usecs
|
||||||
|
|
||||||
/// Last edited time of this entity universal usecs
|
/// Last edited time of this entity universal usecs
|
||||||
quint64 getLastEdited() const { return _lastEdited; }
|
quint64 getLastEdited() const { return _lastEdited; }
|
||||||
void setLastEdited(quint64 lastEdited)
|
void setLastEdited(quint64 lastEdited)
|
||||||
{ _lastEdited = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); }
|
{ _lastEdited = _lastSimulated = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); }
|
||||||
float getEditedAgo() const /// Elapsed seconds since this entity was last edited
|
float getEditedAgo() const /// Elapsed seconds since this entity was last edited
|
||||||
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
|
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
|
||||||
|
|
||||||
|
@ -121,17 +123,14 @@ public:
|
||||||
unsigned char* bufferOut, int sizeIn, int& sizeOut);
|
unsigned char* bufferOut, int sizeIn, int& sizeOut);
|
||||||
|
|
||||||
static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, size_t length, int clockSkew);
|
static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, size_t length, int clockSkew);
|
||||||
virtual void update(const quint64& now);
|
|
||||||
|
// perform update
|
||||||
|
virtual void update(const quint64& now) { _lastUpdated = now; }
|
||||||
|
|
||||||
typedef enum SimulationState_t {
|
// perform linear extrapolation for SimpleEntitySimulation
|
||||||
Static,
|
void simulate(const quint64& now);
|
||||||
Mortal,
|
|
||||||
Moving
|
|
||||||
} SimulationState;
|
|
||||||
|
|
||||||
// computes the SimulationState that the entity SHOULD be in.
|
bool needsToCallUpdate() const { return false; }
|
||||||
// Use getSimulationState() to find the state under which it is currently categorized.
|
|
||||||
virtual SimulationState computeSimulationState() const;
|
|
||||||
|
|
||||||
virtual void debugDump() const;
|
virtual void debugDump() const;
|
||||||
|
|
||||||
|
@ -221,11 +220,14 @@ public:
|
||||||
/// age of this entity in seconds
|
/// age of this entity in seconds
|
||||||
float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; }
|
float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; }
|
||||||
bool lifetimeHasExpired() const;
|
bool lifetimeHasExpired() const;
|
||||||
|
quint64 getExpiry() const;
|
||||||
|
|
||||||
// position, size, and bounds related helpers
|
// position, size, and bounds related helpers
|
||||||
float getSize() const; /// get maximum dimension in domain scale units (0.0 - 1.0)
|
float getSize() const; /// get maximum dimension in domain scale units (0.0 - 1.0)
|
||||||
AACube getMaximumAACube() const;
|
AACube getMaximumAACube() const;
|
||||||
AACube getMinimumAACube() const;
|
AACube getMinimumAACube() const;
|
||||||
|
AACube getOldMaximumAACube() const { return _oldMaximumAACube; }
|
||||||
|
void setOldMaximumAACube(const AACube& cube) { _oldMaximumAACube = cube; }
|
||||||
AABox getAABox() const; /// axis aligned bounding box in domain scale units (0.0 - 1.0)
|
AABox getAABox() const; /// axis aligned bounding box in domain scale units (0.0 - 1.0)
|
||||||
|
|
||||||
static const QString DEFAULT_SCRIPT;
|
static const QString DEFAULT_SCRIPT;
|
||||||
|
@ -278,7 +280,7 @@ public:
|
||||||
virtual const Shape& getCollisionShapeInMeters() const { return _collisionShape; }
|
virtual const Shape& getCollisionShapeInMeters() const { return _collisionShape; }
|
||||||
virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); }
|
virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); }
|
||||||
|
|
||||||
// updateFoo() methods to be used when changes need to be accumulated in the _updateFlags
|
// updateFoo() methods to be used when changes need to be accumulated in the _dirtyFlags
|
||||||
void updatePosition(const glm::vec3& value);
|
void updatePosition(const glm::vec3& value);
|
||||||
void updatePositionInMeters(const glm::vec3& value);
|
void updatePositionInMeters(const glm::vec3& value);
|
||||||
void updateDimensions(const glm::vec3& value);
|
void updateDimensions(const glm::vec3& value);
|
||||||
|
@ -293,13 +295,13 @@ public:
|
||||||
void updateIgnoreForCollisions(bool value);
|
void updateIgnoreForCollisions(bool value);
|
||||||
void updateCollisionsWillMove(bool value);
|
void updateCollisionsWillMove(bool value);
|
||||||
void updateLifetime(float value);
|
void updateLifetime(float value);
|
||||||
|
void updateScript(const QString& value);
|
||||||
|
|
||||||
uint32_t getUpdateFlags() const { return _updateFlags; }
|
uint32_t getDirtyFlags() const { return _dirtyFlags; }
|
||||||
void clearUpdateFlags() { _updateFlags = 0; }
|
void clearDirtyFlags(uint32_t mask = 0xffff) { _dirtyFlags &= ~mask; }
|
||||||
|
|
||||||
SimulationState getSimulationState() const { return _simulationState; }
|
|
||||||
|
|
||||||
void setSimulationState(SimulationState state) { _simulationState = state; }
|
bool isMoving() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init
|
virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init
|
||||||
|
@ -309,7 +311,8 @@ protected:
|
||||||
QUuid _id;
|
QUuid _id;
|
||||||
uint32_t _creatorTokenID;
|
uint32_t _creatorTokenID;
|
||||||
bool _newlyCreated;
|
bool _newlyCreated;
|
||||||
quint64 _lastUpdated;
|
quint64 _lastSimulated; // last time this entity called simulate()
|
||||||
|
quint64 _lastUpdated; // last time this entity called update()
|
||||||
quint64 _lastEdited; // this is the last official local or remote edit time
|
quint64 _lastEdited; // this is the last official local or remote edit time
|
||||||
quint64 _lastEditedFromRemote; // this is the last time we received and edit from the server
|
quint64 _lastEditedFromRemote; // this is the last time we received and edit from the server
|
||||||
quint64 _lastEditedFromRemoteInRemoteTime; // time in server time space the last time we received and edit from the server
|
quint64 _lastEditedFromRemoteInRemoteTime; // time in server time space the last time we received and edit from the server
|
||||||
|
@ -324,12 +327,12 @@ protected:
|
||||||
float _mass;
|
float _mass;
|
||||||
glm::vec3 _velocity;
|
glm::vec3 _velocity;
|
||||||
glm::vec3 _gravity;
|
glm::vec3 _gravity;
|
||||||
float _damping;
|
float _damping; // timescale
|
||||||
float _lifetime;
|
float _lifetime;
|
||||||
QString _script;
|
QString _script;
|
||||||
glm::vec3 _registrationPoint;
|
glm::vec3 _registrationPoint;
|
||||||
glm::vec3 _angularVelocity;
|
glm::vec3 _angularVelocity;
|
||||||
float _angularDamping;
|
float _angularDamping; // timescale
|
||||||
bool _visible;
|
bool _visible;
|
||||||
bool _ignoreForCollisions;
|
bool _ignoreForCollisions;
|
||||||
bool _collisionsWillMove;
|
bool _collisionsWillMove;
|
||||||
|
@ -343,11 +346,10 @@ protected:
|
||||||
void setRadius(float value);
|
void setRadius(float value);
|
||||||
|
|
||||||
AACubeShape _collisionShape;
|
AACubeShape _collisionShape;
|
||||||
SimulationState _simulationState; // only set by EntityTree
|
AACube _oldMaximumAACube; // remember this so we know where the entity used to live in the tree
|
||||||
|
|
||||||
// UpdateFlags are set whenever a property changes that requires the change to be communicated to other
|
// DirtyFlags are set whenever a property changes that the EntitySimulation needs to know about.
|
||||||
// data structures. It is the responsibility of the EntityTree to relay changes entity and clear flags.
|
uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation
|
||||||
uint32_t _updateFlags;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,178 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <AACube.h>
|
||||||
|
|
||||||
#include "EntitySimulation.h"
|
#include "EntitySimulation.h"
|
||||||
|
#include "MovingEntitiesOperator.h"
|
||||||
|
|
||||||
void EntitySimulation::setEntityTree(EntityTree* tree) {
|
void EntitySimulation::setEntityTree(EntityTree* tree) {
|
||||||
if (_entityTree && _entityTree != tree) {
|
if (_entityTree && _entityTree != tree) {
|
||||||
clearEntities();
|
_mortalEntities.clear();
|
||||||
|
_nextExpiry = quint64(-1);
|
||||||
|
_updateableEntities.clear();
|
||||||
|
_entitiesToBeSorted.clear();
|
||||||
}
|
}
|
||||||
_entityTree = tree;
|
_entityTree = tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntitySimulation::updateEntities(QSet<EntityItem*>& entitiesToDelete) {
|
||||||
|
quint64 now = usecTimestampNow();
|
||||||
|
|
||||||
|
// these methods may accumulate entries in _entitiesToBeDeleted
|
||||||
|
expireMortalEntities(now);
|
||||||
|
callUpdateOnEntitiesThatNeedIt(now);
|
||||||
|
updateEntitiesInternal(now);
|
||||||
|
sortEntitiesThatMoved();
|
||||||
|
|
||||||
|
// at this point we harvest _entitiesToBeDeleted
|
||||||
|
entitiesToDelete.unite(_entitiesToDelete);
|
||||||
|
_entitiesToDelete.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntitySimulation::expireMortalEntities(const quint64& now) {
|
||||||
|
if (now > _nextExpiry) {
|
||||||
|
// only search for expired entities if we expect to find one
|
||||||
|
_nextExpiry = quint64(-1);
|
||||||
|
QSet<EntityItem*>::iterator itemItr = _mortalEntities.begin();
|
||||||
|
while (itemItr != _mortalEntities.end()) {
|
||||||
|
EntityItem* entity = *itemItr;
|
||||||
|
quint64 expiry = entity->getExpiry();
|
||||||
|
if (expiry < now) {
|
||||||
|
_entitiesToDelete.insert(entity);
|
||||||
|
itemItr = _mortalEntities.erase(itemItr);
|
||||||
|
_updateableEntities.remove(entity);
|
||||||
|
_entitiesToBeSorted.remove(entity);
|
||||||
|
removeEntityInternal(entity);
|
||||||
|
} else {
|
||||||
|
if (expiry < _nextExpiry) {
|
||||||
|
// remeber the smallest _nextExpiry so we know when to start the next search
|
||||||
|
_nextExpiry = expiry;
|
||||||
|
}
|
||||||
|
++itemItr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntitySimulation::callUpdateOnEntitiesThatNeedIt(const quint64& now) {
|
||||||
|
PerformanceTimer perfTimer("updatingEntities");
|
||||||
|
QSet<EntityItem*>::iterator itemItr = _updateableEntities.begin();
|
||||||
|
while (itemItr != _updateableEntities.end()) {
|
||||||
|
EntityItem* entity = *itemItr;
|
||||||
|
// TODO: catch transition from needing update to not as a "change"
|
||||||
|
// so we don't have to scan for it here.
|
||||||
|
if (!entity->needsToCallUpdate()) {
|
||||||
|
itemItr = _updateableEntities.erase(itemItr);
|
||||||
|
} else {
|
||||||
|
entity->update(now);
|
||||||
|
++itemItr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntitySimulation::sortEntitiesThatMoved() {
|
||||||
|
// NOTE: this is only for entities that have been moved by THIS EntitySimulation.
|
||||||
|
// External changes to entity position/shape are expected to be sorted outside of the EntitySimulation.
|
||||||
|
PerformanceTimer perfTimer("sortingEntities");
|
||||||
|
MovingEntitiesOperator moveOperator(_entityTree);
|
||||||
|
AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f);
|
||||||
|
QSet<EntityItem*>::iterator itemItr = _entitiesToBeSorted.begin();
|
||||||
|
while (itemItr != _entitiesToBeSorted.end()) {
|
||||||
|
EntityItem* entity = *itemItr;
|
||||||
|
// check to see if this movement has sent the entity outside of the domain.
|
||||||
|
AACube newCube = entity->getMaximumAACube();
|
||||||
|
if (!domainBounds.touches(newCube)) {
|
||||||
|
qDebug() << "Entity " << entity->getEntityItemID() << " moved out of domain bounds.";
|
||||||
|
_entitiesToDelete.insert(entity);
|
||||||
|
_mortalEntities.remove(entity);
|
||||||
|
_updateableEntities.remove(entity);
|
||||||
|
removeEntityInternal(entity);
|
||||||
|
} else {
|
||||||
|
moveOperator.addEntityToMoveList(entity, newCube);
|
||||||
|
}
|
||||||
|
++itemItr;
|
||||||
|
}
|
||||||
|
_entitiesToBeSorted.clear();
|
||||||
|
|
||||||
|
if (moveOperator.hasMovingEntities()) {
|
||||||
|
PerformanceTimer perfTimer("recurseTreeWithOperator");
|
||||||
|
_entityTree->recurseTreeWithOperator(&moveOperator);
|
||||||
|
moveOperator.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntitySimulation::addEntity(EntityItem* entity) {
|
||||||
|
assert(entity);
|
||||||
|
if (entity->isMortal()) {
|
||||||
|
_mortalEntities.insert(entity);
|
||||||
|
quint64 expiry = entity->getExpiry();
|
||||||
|
if (expiry < _nextExpiry) {
|
||||||
|
_nextExpiry = expiry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (entity->needsToCallUpdate()) {
|
||||||
|
_updateableEntities.insert(entity);
|
||||||
|
}
|
||||||
|
addEntityInternal(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntitySimulation::removeEntity(EntityItem* entity) {
|
||||||
|
assert(entity);
|
||||||
|
_updateableEntities.remove(entity);
|
||||||
|
_mortalEntities.remove(entity);
|
||||||
|
_entitiesToBeSorted.remove(entity);
|
||||||
|
_entitiesToDelete.remove(entity);
|
||||||
|
removeEntityInternal(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntitySimulation::entityChanged(EntityItem* entity) {
|
||||||
|
assert(entity);
|
||||||
|
|
||||||
|
// Although it is not the responsibility of the EntitySimulation to sort the tree for EXTERNAL changes
|
||||||
|
// it IS responsibile for triggering deletes for entities that leave the bounds of the domain, hence
|
||||||
|
// we must check for that case here, however we rely on the change event to have set DIRTY_POSITION flag.
|
||||||
|
bool wasRemoved = false;
|
||||||
|
uint32_t dirtyFlags = entity->getDirtyFlags();
|
||||||
|
if (dirtyFlags & EntityItem::DIRTY_POSITION) {
|
||||||
|
AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f);
|
||||||
|
AACube newCube = entity->getMaximumAACube();
|
||||||
|
if (!domainBounds.touches(newCube)) {
|
||||||
|
qDebug() << "Entity " << entity->getEntityItemID() << " moved out of domain bounds.";
|
||||||
|
_entitiesToDelete.insert(entity);
|
||||||
|
_mortalEntities.remove(entity);
|
||||||
|
_updateableEntities.remove(entity);
|
||||||
|
removeEntityInternal(entity);
|
||||||
|
wasRemoved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!wasRemoved) {
|
||||||
|
if (dirtyFlags & EntityItem::DIRTY_LIFETIME) {
|
||||||
|
if (entity->isMortal()) {
|
||||||
|
_mortalEntities.insert(entity);
|
||||||
|
quint64 expiry = entity->getExpiry();
|
||||||
|
if (expiry < _nextExpiry) {
|
||||||
|
_nextExpiry = expiry;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_mortalEntities.remove(entity);
|
||||||
|
}
|
||||||
|
entity->clearDirtyFlags(EntityItem::DIRTY_LIFETIME);
|
||||||
|
}
|
||||||
|
if (entity->needsToCallUpdate()) {
|
||||||
|
_updateableEntities.insert(entity);
|
||||||
|
} else {
|
||||||
|
_updateableEntities.remove(entity);
|
||||||
|
}
|
||||||
|
entityChangedInternal(entity);
|
||||||
|
}
|
||||||
|
entity->clearDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntitySimulation::clearEntities() {
|
||||||
|
_mortalEntities.clear();
|
||||||
|
_nextExpiry = quint64(-1);
|
||||||
|
_updateableEntities.clear();
|
||||||
|
_entitiesToBeSorted.clear();
|
||||||
|
clearEntitiesInternal();
|
||||||
|
}
|
||||||
|
|
|
@ -14,36 +14,61 @@
|
||||||
|
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
|
||||||
|
#include <PerfStat.h>
|
||||||
|
|
||||||
#include "EntityTree.h"
|
#include "EntityTree.h"
|
||||||
|
|
||||||
class EntitySimulation {
|
class EntitySimulation {
|
||||||
public:
|
public:
|
||||||
EntitySimulation() : _entityTree(NULL) { }
|
EntitySimulation() : _entityTree(NULL) { }
|
||||||
virtual ~EntitySimulation() {}
|
virtual ~EntitySimulation() { setEntityTree(NULL); }
|
||||||
|
|
||||||
/// \param tree pointer to EntityTree which is stored internally
|
/// \param tree pointer to EntityTree which is stored internally
|
||||||
virtual void setEntityTree(EntityTree* tree);
|
void setEntityTree(EntityTree* tree);
|
||||||
|
|
||||||
/// \param[out] entitiesToDelete list of entities removed from simulation and should be deleted.
|
/// \param[out] entitiesToDelete list of entities removed from simulation and should be deleted.
|
||||||
virtual void update(QSet<EntityItem*>& entitiesToDelete) = 0;
|
void updateEntities(QSet<EntityItem*>& entitiesToDelete);
|
||||||
|
|
||||||
/// \param entity pointer to EntityItem to add to the simulation
|
/// \param entity pointer to EntityItem to add to the simulation
|
||||||
/// \sideeffect the EntityItem::_simulationState member may be updated to indicate membership to internal list
|
/// \sideeffect the EntityItem::_simulationState member may be updated to indicate membership to internal list
|
||||||
virtual void addEntity(EntityItem* entity) = 0;
|
void addEntity(EntityItem* entity);
|
||||||
|
|
||||||
/// \param entity pointer to EntityItem to removed from the simulation
|
/// \param entity pointer to EntityItem to removed from the simulation
|
||||||
/// \sideeffect the EntityItem::_simulationState member may be updated to indicate non-membership to internal list
|
/// \sideeffect the EntityItem::_simulationState member may be updated to indicate non-membership to internal list
|
||||||
virtual void removeEntity(EntityItem* entity) = 0;
|
void removeEntity(EntityItem* entity);
|
||||||
|
|
||||||
/// \param entity pointer to EntityItem to that may have changed in a way that would affect its simulation
|
/// \param entity pointer to EntityItem to that may have changed in a way that would affect its simulation
|
||||||
virtual void entityChanged(EntityItem* entity) = 0;
|
/// call this whenever an entity was changed from some EXTERNAL event (NOT by the EntitySimulation itself)
|
||||||
|
void entityChanged(EntityItem* entity);
|
||||||
|
|
||||||
virtual void clearEntities() = 0;
|
void clearEntities();
|
||||||
|
|
||||||
EntityTree* getEntityTree() { return _entityTree; }
|
EntityTree* getEntityTree() { return _entityTree; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
// These pure virtual methods are protected because they are not to be called will-nilly. The base class
|
||||||
|
// calls them in the right places.
|
||||||
|
virtual void updateEntitiesInternal(const quint64& now) = 0;
|
||||||
|
virtual void addEntityInternal(EntityItem* entity) = 0;
|
||||||
|
virtual void removeEntityInternal(EntityItem* entity) = 0;
|
||||||
|
virtual void entityChangedInternal(EntityItem* entity) = 0;
|
||||||
|
virtual void clearEntitiesInternal() = 0;
|
||||||
|
|
||||||
|
void expireMortalEntities(const quint64& now);
|
||||||
|
void callUpdateOnEntitiesThatNeedIt(const quint64& now);
|
||||||
|
void sortEntitiesThatMoved();
|
||||||
|
|
||||||
|
// back pointer to EntityTree structure
|
||||||
EntityTree* _entityTree;
|
EntityTree* _entityTree;
|
||||||
|
|
||||||
|
// We maintain multiple lists, each for its distinct purpose.
|
||||||
|
// An entity may be in more than one list.
|
||||||
|
QSet<EntityItem*> _mortalEntities; // entities that have an expiry
|
||||||
|
quint64 _nextExpiry;
|
||||||
|
QSet<EntityItem*> _updateableEntities; // entities that need update() called
|
||||||
|
QSet<EntityItem*> _entitiesToBeSorted; // entities that were moved by THIS simulation and might need to be resorted in the tree
|
||||||
|
QSet<EntityItem*> _entitiesToDelete;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_EntitySimulation_h
|
#endif // hifi_EntitySimulation_h
|
||||||
|
|
|
@ -83,6 +83,7 @@ EntityItem* EntityTree::getOrCreateEntityItem(const EntityItemID& entityID, cons
|
||||||
/// Adds a new entity item to the tree
|
/// Adds a new entity item to the tree
|
||||||
void EntityTree::postAddEntity(EntityItem* entity) {
|
void EntityTree::postAddEntity(EntityItem* entity) {
|
||||||
assert(entity);
|
assert(entity);
|
||||||
|
entity->setOldMaximumAACube(entity->getMaximumAACube());
|
||||||
// check to see if we need to simulate this entity..
|
// check to see if we need to simulate this entity..
|
||||||
if (_simulation) {
|
if (_simulation) {
|
||||||
_simulation->addEntity(entity);
|
_simulation->addEntity(entity);
|
||||||
|
@ -103,51 +104,64 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp
|
||||||
qDebug() << "UNEXPECTED!!!! don't call updateEntity() on entity items that don't exist. entityID=" << entityID;
|
qDebug() << "UNEXPECTED!!!! don't call updateEntity() on entity items that don't exist. entityID=" << entityID;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return updateEntityWithElement(existingEntity, properties, containingElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EntityTree::updateEntity(EntityItem* entity, const EntityItemProperties& properties) {
|
||||||
|
EntityTreeElement* containingElement = getContainingElement(entity->getEntityItemID());
|
||||||
|
if (!containingElement) {
|
||||||
|
qDebug() << "UNEXPECTED!!!! EntityTree::updateEntity() entity-->element lookup failed!!! entityID="
|
||||||
|
<< entity->getEntityItemID();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return updateEntityWithElement(entity, properties, containingElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemProperties& properties,
|
||||||
|
EntityTreeElement* containingElement) {
|
||||||
// enforce support for locked entities. If an entity is currently locked, then the only
|
// enforce support for locked entities. If an entity is currently locked, then the only
|
||||||
// property we allow you to change is the locked property.
|
// property we allow you to change is the locked property.
|
||||||
if (existingEntity->getLocked()) {
|
if (entity->getLocked()) {
|
||||||
if (properties.lockedChanged()) {
|
if (properties.lockedChanged()) {
|
||||||
bool wantsLocked = properties.getLocked();
|
bool wantsLocked = properties.getLocked();
|
||||||
if (!wantsLocked) {
|
if (!wantsLocked) {
|
||||||
EntityItemProperties tempProperties;
|
EntityItemProperties tempProperties;
|
||||||
tempProperties.setLocked(wantsLocked);
|
tempProperties.setLocked(wantsLocked);
|
||||||
UpdateEntityOperator theOperator(this, containingElement, existingEntity, tempProperties);
|
UpdateEntityOperator theOperator(this, containingElement, entity, tempProperties);
|
||||||
recurseTreeWithOperator(&theOperator);
|
recurseTreeWithOperator(&theOperator);
|
||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
if (_simulation && existingEntity->getUpdateFlags() != 0) {
|
|
||||||
_simulation->entityChanged(existingEntity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// check to see if we need to simulate this entity...
|
QString entityScriptBefore = entity->getScript();
|
||||||
QString entityScriptBefore = existingEntity->getScript();
|
|
||||||
|
|
||||||
UpdateEntityOperator theOperator(this, containingElement, existingEntity, properties);
|
UpdateEntityOperator theOperator(this, containingElement, entity, properties);
|
||||||
recurseTreeWithOperator(&theOperator);
|
recurseTreeWithOperator(&theOperator);
|
||||||
|
entity->setOldMaximumAACube(entity->getMaximumAACube());
|
||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
|
|
||||||
if (_simulation && existingEntity->getUpdateFlags() != 0) {
|
if (_simulation && entity->getDirtyFlags() != 0) {
|
||||||
_simulation->entityChanged(existingEntity);
|
_simulation->entityChanged(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString entityScriptAfter = existingEntity->getScript();
|
QString entityScriptAfter = entity->getScript();
|
||||||
if (entityScriptBefore != entityScriptAfter) {
|
if (entityScriptBefore != entityScriptAfter) {
|
||||||
emitEntityScriptChanging(entityID); // the entity script has changed
|
emit entityScriptChanging(entity->getEntityItemID()); // the entity script has changed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
containingElement = getContainingElement(entityID);
|
// TODO: this final containingElement check should eventually be removed (or wrapped in an #ifdef DEBUG).
|
||||||
|
containingElement = getContainingElement(entity->getEntityItemID());
|
||||||
if (!containingElement) {
|
if (!containingElement) {
|
||||||
qDebug() << "UNEXPECTED!!!! after updateEntity() we no longer have a containing element??? entityID=" << entityID;
|
qDebug() << "UNEXPECTED!!!! after updateEntity() we no longer have a containing element??? entityID="
|
||||||
|
<< entity->getEntityItemID();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||||
EntityItem* result = NULL;
|
EntityItem* result = NULL;
|
||||||
|
|
||||||
|
@ -576,7 +590,7 @@ void EntityTree::update() {
|
||||||
if (_simulation) {
|
if (_simulation) {
|
||||||
lockForWrite();
|
lockForWrite();
|
||||||
QSet<EntityItem*> entitiesToDelete;
|
QSet<EntityItem*> entitiesToDelete;
|
||||||
_simulation->update(entitiesToDelete);
|
_simulation->updateEntities(entitiesToDelete);
|
||||||
if (entitiesToDelete.size() > 0) {
|
if (entitiesToDelete.size() > 0) {
|
||||||
// translate into list of ID's
|
// translate into list of ID's
|
||||||
QSet<EntityItemID> idsToDelete;
|
QSet<EntityItemID> idsToDelete;
|
||||||
|
|
|
@ -82,7 +82,13 @@ public:
|
||||||
void postAddEntity(EntityItem* entityItem);
|
void postAddEntity(EntityItem* entityItem);
|
||||||
|
|
||||||
EntityItem* addEntity(const EntityItemID& entityID, const EntityItemProperties& properties);
|
EntityItem* addEntity(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
|
|
||||||
|
// use this method if you only know the entityID
|
||||||
bool updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties);
|
bool updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
|
|
||||||
|
// use this method if you have a pointer to the entity (avoid an extra entity lookup)
|
||||||
|
bool updateEntity(EntityItem* entity, const EntityItemProperties& properties);
|
||||||
|
|
||||||
void deleteEntity(const EntityItemID& entityID);
|
void deleteEntity(const EntityItemID& entityID);
|
||||||
void deleteEntities(QSet<EntityItemID> entityIDs);
|
void deleteEntities(QSet<EntityItemID> entityIDs);
|
||||||
void removeEntityFromSimulation(EntityItem* entity);
|
void removeEntityFromSimulation(EntityItem* entity);
|
||||||
|
@ -156,6 +162,8 @@ signals:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
bool updateEntityWithElement(EntityItem* entity, const EntityItemProperties& properties,
|
||||||
|
EntityTreeElement* containingElement);
|
||||||
static bool findNearPointOperation(OctreeElement* element, void* extraData);
|
static bool findNearPointOperation(OctreeElement* element, void* extraData);
|
||||||
static bool findInSphereOperation(OctreeElement* element, void* extraData);
|
static bool findInSphereOperation(OctreeElement* element, void* extraData);
|
||||||
static bool findInCubeOperation(OctreeElement* element, void* extraData);
|
static bool findInCubeOperation(OctreeElement* element, void* extraData);
|
||||||
|
|
|
@ -761,7 +761,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
|
||||||
EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID);
|
EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID);
|
||||||
|
|
||||||
bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
|
bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
|
||||||
if (entityItem->getUpdateFlags()) {
|
if (entityItem->getDirtyFlags()) {
|
||||||
_myTree->entityChanged(entityItem);
|
_myTree->entityChanged(entityItem);
|
||||||
}
|
}
|
||||||
bool bestFitAfter = bestFitEntityBounds(entityItem);
|
bool bestFitAfter = bestFitEntityBounds(entityItem);
|
||||||
|
|
|
@ -373,17 +373,11 @@ bool ModelEntityItem::isAnimatingSomething() const {
|
||||||
!getAnimationURL().isEmpty();
|
!getAnimationURL().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItem::SimulationState ModelEntityItem::computeSimulationState() const {
|
bool ModelEntityItem::needsToCallUpdate() const {
|
||||||
// if we're animating then we need to have update() periodically called on this entity
|
return isAnimatingSomething() ? true : EntityItem::needsToCallUpdate();
|
||||||
// which means we need to categorized as Moving
|
|
||||||
return isAnimatingSomething() ? EntityItem::Moving : EntityItem::computeSimulationState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityItem::update(const quint64& updateTime) {
|
void ModelEntityItem::update(const quint64& now) {
|
||||||
EntityItem::update(updateTime); // let our base class handle it's updates...
|
|
||||||
|
|
||||||
quint64 now = updateTime;
|
|
||||||
|
|
||||||
// only advance the frame index if we're playing
|
// only advance the frame index if we're playing
|
||||||
if (getAnimationIsPlaying()) {
|
if (getAnimationIsPlaying()) {
|
||||||
float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND;
|
float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND;
|
||||||
|
@ -392,6 +386,7 @@ void ModelEntityItem::update(const quint64& updateTime) {
|
||||||
} else {
|
} else {
|
||||||
_lastAnimated = now;
|
_lastAnimated = now;
|
||||||
}
|
}
|
||||||
|
EntityItem::update(now); // let our base class handle it's updates...
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityItem::debugDump() const {
|
void ModelEntityItem::debugDump() const {
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
|
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
|
||||||
|
|
||||||
virtual void update(const quint64& now);
|
virtual void update(const quint64& now);
|
||||||
virtual SimulationState computeSimulationState() const;
|
virtual bool needsToCallUpdate() const;
|
||||||
virtual void debugDump() const;
|
virtual void debugDump() const;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,10 @@ MovingEntitiesOperator::~MovingEntitiesOperator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MovingEntitiesOperator::addEntityToMoveList(EntityItem* entity, const AACube& oldCube, const AACube& newCube) {
|
void MovingEntitiesOperator::addEntityToMoveList(EntityItem* entity, const AACube& newCube) {
|
||||||
EntityTreeElement* oldContainingElement = _tree->getContainingElement(entity->getEntityItemID());
|
EntityTreeElement* oldContainingElement = _tree->getContainingElement(entity->getEntityItemID());
|
||||||
AABox newCubeClamped = newCube.clamp(0.0f, 1.0f);
|
AABox newCubeClamped = newCube.clamp(0.0f, 1.0f);
|
||||||
|
AACube oldCube = entity->getOldMaximumAACube();
|
||||||
AABox oldCubeClamped = oldCube.clamp(0.0f, 1.0f);
|
AABox oldCubeClamped = oldCube.clamp(0.0f, 1.0f);
|
||||||
|
|
||||||
if (_wantDebug) {
|
if (_wantDebug) {
|
||||||
|
@ -290,3 +291,9 @@ OctreeElement* MovingEntitiesOperator::possiblyCreateChildAt(OctreeElement* elem
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MovingEntitiesOperator::finish() {
|
||||||
|
foreach(const EntityToMoveDetails& details, _entitiesToMove) {
|
||||||
|
details.entity->setOldMaximumAACube(details.newCube);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -38,11 +38,12 @@ public:
|
||||||
MovingEntitiesOperator(EntityTree* tree);
|
MovingEntitiesOperator(EntityTree* tree);
|
||||||
~MovingEntitiesOperator();
|
~MovingEntitiesOperator();
|
||||||
|
|
||||||
void addEntityToMoveList(EntityItem* entity, const AACube& oldCube, const AACube& newCube);
|
void addEntityToMoveList(EntityItem* entity, const AACube& newCube);
|
||||||
virtual bool preRecursion(OctreeElement* element);
|
virtual bool preRecursion(OctreeElement* element);
|
||||||
virtual bool postRecursion(OctreeElement* element);
|
virtual bool postRecursion(OctreeElement* element);
|
||||||
virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex);
|
virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex);
|
||||||
bool hasMovingEntities() const { return _entitiesToMove.size() > 0; }
|
bool hasMovingEntities() const { return _entitiesToMove.size() > 0; }
|
||||||
|
void finish();
|
||||||
private:
|
private:
|
||||||
EntityTree* _tree;
|
EntityTree* _tree;
|
||||||
QSet<EntityToMoveDetails> _entitiesToMove;
|
QSet<EntityToMoveDetails> _entitiesToMove;
|
||||||
|
|
|
@ -9,216 +9,64 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <AACube.h>
|
//#include <PerfStat.h>
|
||||||
#include <PerfStat.h>
|
|
||||||
|
|
||||||
#include "EntityItem.h"
|
#include "EntityItem.h"
|
||||||
#include "MovingEntitiesOperator.h"
|
|
||||||
#include "SimpleEntitySimulation.h"
|
#include "SimpleEntitySimulation.h"
|
||||||
|
|
||||||
void SimpleEntitySimulation::update(QSet<EntityItem*>& entitiesToDelete) {
|
|
||||||
quint64 now = usecTimestampNow();
|
|
||||||
updateChangedEntities(now, entitiesToDelete);
|
|
||||||
updateMovingEntities(now, entitiesToDelete);
|
|
||||||
updateMortalEntities(now, entitiesToDelete);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleEntitySimulation::addEntity(EntityItem* entity) {
|
void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) {
|
||||||
assert(entity && entity->getSimulationState() == EntityItem::Static);
|
QSet<EntityItem*>::iterator itemItr = _movingEntities.begin();
|
||||||
EntityItem::SimulationState state = entity->computeSimulationState();
|
while (itemItr != _movingEntities.end()) {
|
||||||
switch(state) {
|
EntityItem* entity = *itemItr;
|
||||||
case EntityItem::Moving:
|
if (!entity->isMoving()) {
|
||||||
_movingEntities.push_back(entity);
|
itemItr = _movingEntities.erase(itemItr);
|
||||||
entity->setSimulationState(state);
|
_movableButStoppedEntities.insert(entity);
|
||||||
break;
|
} else {
|
||||||
case EntityItem::Mortal:
|
entity->simulate(now);
|
||||||
_mortalEntities.push_back(entity);
|
_entitiesToBeSorted.insert(entity);
|
||||||
entity->setSimulationState(state);
|
++itemItr;
|
||||||
break;
|
}
|
||||||
case EntityItem::Static:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleEntitySimulation::removeEntity(EntityItem* entity) {
|
void SimpleEntitySimulation::addEntityInternal(EntityItem* entity) {
|
||||||
assert(entity);
|
if (entity->getCollisionsWillMove()) {
|
||||||
// make sure to remove it from any of our simulation lists
|
if (entity->isMoving()) {
|
||||||
EntityItem::SimulationState state = entity->getSimulationState();
|
_movingEntities.insert(entity);
|
||||||
switch (state) {
|
} else {
|
||||||
case EntityItem::Moving:
|
_movableButStoppedEntities.insert(entity);
|
||||||
_movingEntities.removeAll(entity);
|
}
|
||||||
break;
|
|
||||||
case EntityItem::Mortal:
|
|
||||||
_mortalEntities.removeAll(entity);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
entity->setSimulationState(EntityItem::Static);
|
|
||||||
_changedEntities.remove(entity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleEntitySimulation::entityChanged(EntityItem* entity) {
|
void SimpleEntitySimulation::removeEntityInternal(EntityItem* entity) {
|
||||||
assert(entity);
|
_movingEntities.remove(entity);
|
||||||
// we batch all changes and deal with them in updateChangedEntities()
|
_movableButStoppedEntities.remove(entity);
|
||||||
_changedEntities.insert(entity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleEntitySimulation::clearEntities() {
|
const int SIMPLE_SIMULATION_DIRTY_FLAGS = EntityItem::DIRTY_VELOCITY | EntityItem::DIRTY_MOTION_TYPE;
|
||||||
foreach (EntityItem* entity, _changedEntities) {
|
|
||||||
entity->clearUpdateFlags();
|
void SimpleEntitySimulation::entityChangedInternal(EntityItem* entity) {
|
||||||
entity->setSimulationState(EntityItem::Static);
|
int dirtyFlags = entity->getDirtyFlags();
|
||||||
|
if (dirtyFlags & SIMPLE_SIMULATION_DIRTY_FLAGS) {
|
||||||
|
if (entity->getCollisionsWillMove()) {
|
||||||
|
if (entity->isMoving()) {
|
||||||
|
_movingEntities.insert(entity);
|
||||||
|
_movableButStoppedEntities.remove(entity);
|
||||||
|
} else {
|
||||||
|
_movingEntities.remove(entity);
|
||||||
|
_movableButStoppedEntities.insert(entity);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_movingEntities.remove(entity);
|
||||||
|
_movableButStoppedEntities.remove(entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_changedEntities.clear();
|
}
|
||||||
|
|
||||||
|
void SimpleEntitySimulation::clearEntitiesInternal() {
|
||||||
_movingEntities.clear();
|
_movingEntities.clear();
|
||||||
_mortalEntities.clear();
|
_movableButStoppedEntities.clear();
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleEntitySimulation::updateChangedEntities(quint64 now, QSet<EntityItem*>& entitiesToDelete) {
|
|
||||||
foreach (EntityItem* entity, _changedEntities) {
|
|
||||||
// check to see if the lifetime has expired, for immortal entities this is always false
|
|
||||||
if (entity->lifetimeHasExpired()) {
|
|
||||||
qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID();
|
|
||||||
entitiesToDelete.insert(entity);
|
|
||||||
clearEntityState(entity);
|
|
||||||
} else {
|
|
||||||
updateEntityState(entity);
|
|
||||||
}
|
|
||||||
entity->clearUpdateFlags();
|
|
||||||
}
|
|
||||||
_changedEntities.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleEntitySimulation::updateMovingEntities(quint64 now, QSet<EntityItem*>& entitiesToDelete) {
|
|
||||||
if (_entityTree && _movingEntities.size() > 0) {
|
|
||||||
PerformanceTimer perfTimer("_movingEntities");
|
|
||||||
MovingEntitiesOperator moveOperator(_entityTree);
|
|
||||||
QList<EntityItem*>::iterator item_itr = _movingEntities.begin();
|
|
||||||
while (item_itr != _movingEntities.end()) {
|
|
||||||
EntityItem* entity = *item_itr;
|
|
||||||
|
|
||||||
// always check to see if the lifetime has expired, for immortal entities this is always false
|
|
||||||
if (entity->lifetimeHasExpired()) {
|
|
||||||
qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID();
|
|
||||||
entitiesToDelete.insert(entity);
|
|
||||||
// remove entity from the list
|
|
||||||
item_itr = _movingEntities.erase(item_itr);
|
|
||||||
entity->setSimulationState(EntityItem::Static);
|
|
||||||
} else {
|
|
||||||
AACube oldCube = entity->getMaximumAACube();
|
|
||||||
entity->update(now);
|
|
||||||
AACube newCube = entity->getMaximumAACube();
|
|
||||||
|
|
||||||
// check to see if this movement has sent the entity outside of the domain.
|
|
||||||
AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f);
|
|
||||||
if (!domainBounds.touches(newCube)) {
|
|
||||||
qDebug() << "Entity " << entity->getEntityItemID() << " moved out of domain bounds.";
|
|
||||||
entitiesToDelete.insert(entity);
|
|
||||||
// remove entity from the list
|
|
||||||
item_itr = _movingEntities.erase(item_itr);
|
|
||||||
entity->setSimulationState(EntityItem::Static);
|
|
||||||
} else {
|
|
||||||
moveOperator.addEntityToMoveList(entity, oldCube, newCube);
|
|
||||||
EntityItem::SimulationState newState = entity->computeSimulationState();
|
|
||||||
if (newState != EntityItem::Moving) {
|
|
||||||
if (newState == EntityItem::Mortal) {
|
|
||||||
_mortalEntities.push_back(entity);
|
|
||||||
}
|
|
||||||
// remove entity from the list
|
|
||||||
item_itr = _movingEntities.erase(item_itr);
|
|
||||||
entity->setSimulationState(newState);
|
|
||||||
} else {
|
|
||||||
++item_itr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (moveOperator.hasMovingEntities()) {
|
|
||||||
PerformanceTimer perfTimer("recurseTreeWithOperator");
|
|
||||||
_entityTree->recurseTreeWithOperator(&moveOperator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleEntitySimulation::updateMortalEntities(quint64 now, QSet<EntityItem*>& entitiesToDelete) {
|
|
||||||
QList<EntityItem*>::iterator item_itr = _mortalEntities.begin();
|
|
||||||
while (item_itr != _mortalEntities.end()) {
|
|
||||||
EntityItem* entity = *item_itr;
|
|
||||||
// always check to see if the lifetime has expired, for immortal entities this is always false
|
|
||||||
if (entity->lifetimeHasExpired()) {
|
|
||||||
qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID();
|
|
||||||
entitiesToDelete.insert(entity);
|
|
||||||
// remove entity from the list
|
|
||||||
item_itr = _mortalEntities.erase(item_itr);
|
|
||||||
entity->setSimulationState(EntityItem::Static);
|
|
||||||
} else {
|
|
||||||
// check to see if this entity is no longer moving
|
|
||||||
EntityItem::SimulationState newState = entity->computeSimulationState();
|
|
||||||
if (newState != EntityItem::Mortal) {
|
|
||||||
if (newState == EntityItem::Moving) {
|
|
||||||
entity->update(now);
|
|
||||||
_movingEntities.push_back(entity);
|
|
||||||
}
|
|
||||||
// remove entity from the list
|
|
||||||
item_itr = _mortalEntities.erase(item_itr);
|
|
||||||
entity->setSimulationState(newState);
|
|
||||||
} else {
|
|
||||||
++item_itr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleEntitySimulation::updateEntityState(EntityItem* entity) {
|
|
||||||
EntityItem::SimulationState oldState = entity->getSimulationState();
|
|
||||||
EntityItem::SimulationState newState = entity->computeSimulationState();
|
|
||||||
if (newState != oldState) {
|
|
||||||
switch (oldState) {
|
|
||||||
case EntityItem::Moving:
|
|
||||||
_movingEntities.removeAll(entity);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EntityItem::Mortal:
|
|
||||||
_mortalEntities.removeAll(entity);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (newState) {
|
|
||||||
case EntityItem::Moving:
|
|
||||||
_movingEntities.push_back(entity);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EntityItem::Mortal:
|
|
||||||
_mortalEntities.push_back(entity);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
entity->setSimulationState(newState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleEntitySimulation::clearEntityState(EntityItem* entity) {
|
|
||||||
EntityItem::SimulationState oldState = entity->getSimulationState();
|
|
||||||
switch (oldState) {
|
|
||||||
case EntityItem::Moving:
|
|
||||||
_movingEntities.removeAll(entity);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EntityItem::Mortal:
|
|
||||||
_mortalEntities.removeAll(entity);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
entity->setSimulationState(EntityItem::Static);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,29 +19,17 @@
|
||||||
class SimpleEntitySimulation : public EntitySimulation {
|
class SimpleEntitySimulation : public EntitySimulation {
|
||||||
public:
|
public:
|
||||||
SimpleEntitySimulation() : EntitySimulation() { }
|
SimpleEntitySimulation() : EntitySimulation() { }
|
||||||
virtual ~SimpleEntitySimulation() { setEntityTree(NULL); }
|
virtual ~SimpleEntitySimulation() { clearEntitiesInternal(); }
|
||||||
|
|
||||||
virtual void update(QSet<EntityItem*>& entitiesToDelete);
|
|
||||||
|
|
||||||
virtual void addEntity(EntityItem* entity);
|
|
||||||
virtual void removeEntity(EntityItem* entity);
|
|
||||||
virtual void entityChanged(EntityItem* entity);
|
|
||||||
|
|
||||||
virtual void clearEntities();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void updateEntityState(EntityItem* entity);
|
virtual void updateEntitiesInternal(const quint64& now);
|
||||||
void clearEntityState(EntityItem* entity);
|
virtual void addEntityInternal(EntityItem* entity);
|
||||||
|
virtual void removeEntityInternal(EntityItem* entity);
|
||||||
|
virtual void entityChangedInternal(EntityItem* entity);
|
||||||
|
virtual void clearEntitiesInternal();
|
||||||
|
|
||||||
QList<EntityItem*>& getMovingEntities() { return _movingEntities; }
|
QSet<EntityItem*> _movingEntities;
|
||||||
|
QSet<EntityItem*> _movableButStoppedEntities;
|
||||||
void updateChangedEntities(quint64 now, QSet<EntityItem*>& entitiesToDelete);
|
|
||||||
void updateMovingEntities(quint64 now, QSet<EntityItem*>& entitiesToDelete);
|
|
||||||
void updateMortalEntities(quint64 now, QSet<EntityItem*>& entitiesToDelete);
|
|
||||||
|
|
||||||
QSet<EntityItem*> _changedEntities; // entities that have changed in the last frame
|
|
||||||
QList<EntityItem*> _movingEntities; // entities that need to be updated
|
|
||||||
QList<EntityItem*> _mortalEntities; // non-moving entities that need to be checked for expiry
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_SimpleEntitySimulation_h
|
#endif // hifi_SimpleEntitySimulation_h
|
||||||
|
|
Loading…
Reference in a new issue