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

This commit is contained in:
samcake 2015-10-07 14:27:01 -07:00
commit f0b7622ef0
77 changed files with 1078 additions and 800 deletions

View file

@ -61,17 +61,17 @@ void ScriptableAvatar::update(float deltatime) {
_jointData.resize(modelJoints.size());
}
float frameIndex = _animationDetails.frameIndex + deltatime * _animationDetails.fps;
if (_animationDetails.loop || frameIndex < _animationDetails.lastFrame) {
while (frameIndex >= _animationDetails.lastFrame) {
frameIndex -= (_animationDetails.lastFrame - _animationDetails.firstFrame);
float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps;
if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) {
while (currentFrame >= _animationDetails.lastFrame) {
currentFrame -= (_animationDetails.lastFrame - _animationDetails.firstFrame);
}
_animationDetails.frameIndex = frameIndex;
_animationDetails.currentFrame = currentFrame;
const int frameCount = _animation->getFrames().size();
const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(frameIndex) % frameCount);
const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(frameIndex) % frameCount);
const float frameFraction = glm::fract(frameIndex);
const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
const float frameFraction = glm::fract(currentFrame);
for (int i = 0; i < modelJoints.size(); i++) {
int mapping = animationJoints.indexOf(modelJoints[i]);

View file

@ -19,7 +19,7 @@ Agent.isAvatar = true;
var jointMapping;
var frameIndex = 0.0;
var currentFrame = 0.0;
var FRAME_RATE = 30.0; // frames per second
@ -35,9 +35,9 @@ Script.update.connect(function(deltaTime) {
jointMapping[i] = animationJointNames.indexOf(avatarJointNames[i]);
}
}
frameIndex += deltaTime * FRAME_RATE;
currentFrame += deltaTime * FRAME_RATE;
var frames = animation.frames;
var rotations = frames[Math.floor(frameIndex) % frames.length].rotations;
var rotations = frames[Math.floor(currentFrame) % frames.length].rotations;
for (var j = 0; j < jointMapping.length; j++) {
var rotationIndex = jointMapping[j];
if (rotationIndex != -1) {

View file

@ -32,8 +32,7 @@
this.leaveEntity = function(entityID) {
Entities.editEntity(entityID, {
animationURL: animationURL,
animationSettings: '{ "frameIndex": 1, "running": false }'
animation: { url: animationURL, currentFrame: 1, running: false }
});
playSound();
@ -41,8 +40,7 @@
this.hoverEnterEntity = function(entityID) {
Entities.editEntity(entityID, {
animationURL: animationURL,
animationSettings: '{ "fps": 24, "firstFrame": 1, "lastFrame": 25, "frameIndex": 1, "running": true, "hold": true }'
animation: { url: animationURL, fps: 24, firstFrame: 1, lastFrame: 25, currentFrame: 1, running: true, hold: true }
});
};
})

View file

@ -18,7 +18,7 @@ function displayAnimationDetails(deltaTime) {
print("count =" + count + " deltaTime=" + deltaTime);
count++;
var animationDetails = MyAvatar.getAnimationDetailsByRole("idle");
print("animationDetails.frameIndex=" + animationDetails.frameIndex);
print("animationDetails.currentFrame=" + animationDetails.currentFrame);
}
function scriptEnding() {

View file

@ -18,7 +18,7 @@ var stopAfter = moveUntil + 100;
var pitch = 0.0;
var yaw = 0.0;
var roll = 0.0;
var rotation = Quat.fromPitchYawRollDegrees(pitch, yaw, roll)
var rotation = Quat.fromPitchYawRollDegrees(pitch, yaw, roll);
var originalProperties = {
type: "Model",
@ -37,8 +37,14 @@ var originalProperties = {
modelURL: "http://public.highfidelity.io/cozza13/club/dragon/dragon.fbx",
rotation: rotation,
animationURL: "http://public.highfidelity.io/cozza13/club/dragon/flying.fbx",
animationIsPlaying: true,
animation: {
url: "http://public.highfidelity.io/cozza13/club/dragon/flying.fbx",
running: true,
fps: 30,
firstFrame: 10,
lastFrame: 20,
loop: true
}
};
var modelID = Entities.addEntity(originalProperties);
@ -99,13 +105,15 @@ function moveModel(deltaTime) {
if (somethingChanged) {
var newProperties = {
animationIsPlaying: isPlaying,
animationFPS: animationFPS,
animation: {
running: isPlaying,
fps: animationFPS
}
};
if (resetFrame) {
print("resetting the frame!");
newProperties.animationFrameIndex = 0;
newProperties.animation.currentFrame = 0;
resetFrame = false;
}

View file

@ -85,8 +85,17 @@ function addButterfly() {
damping: 0.00001,
dimensions: dimensions,
color: color,
animationURL: "http://public.highfidelity.io/models/content/butterfly/butterfly.fbx",
animationSettings: "{\"firstFrame\":0,\"fps\":" + newFrameRate + ",\"frameIndex\":0,\"hold\":false,\"lastFrame\":10000,\"loop\":true,\"running\":true,\"startAutomatically\":false}",
animation: {
url: "http://public.highfidelity.io/models/content/butterfly/butterfly.fbx",
firstFrame: 0,
fps: newFrameRate,
currentFrame: 0,
hold: false,
lastFrame: 10000,
loop: true,
running: true,
startAutomatically:false
},
modelURL: "http://public.highfidelity.io/models/content/butterfly/butterfly.fbx"
};
butterflies.push(Entities.addEntity(properties));

View file

@ -43,7 +43,7 @@
speedSpread: 0.0,
accelerationSpread: { x: 0.0, y: 0.0, z: 0.0 },
radiusSpread: 0.0,
animationIsPlaying: true
isEmitting: true
});
break;
case 1:
@ -195,7 +195,7 @@
polarFinish: 0.0,
azimuthStart: -PI,
azimuthFinish: PI,
animationIsPlaying: false
isEmitting: false
});
Entities.editEntity(box, {
visible: true
@ -210,15 +210,7 @@
function setUp() {
var boxPoint,
spawnPoint,
animation = {
fps: 30,
frameIndex: 0,
running: true,
firstFrame: 0,
lastFrame: 30,
loop: true
};
spawnPoint;
boxPoint = Vec3.sum(MyAvatar.position, Vec3.multiply(4.0, Quat.getFront(Camera.getOrientation())));
boxPoint = Vec3.sum(boxPoint, { x: 0.0, y: -0.5, z: 0.0 });
@ -265,8 +257,7 @@
lifespan: 5.0,
visible: false,
locked: false,
animationSettings: animation,
animationIsPlaying: false,
isEmitting: false,
lifetime: 3600 // 1 hour; just in case
});

View file

@ -117,15 +117,6 @@ Rocket = function(point, colorPalette) {
}
});
this.animationSettings = JSON.stringify({
fps: 40,
frameIndex: 0,
running: true,
firstFrame: 0,
lastFrame: 20,
loop: false
});
this.direction = {
x: randFloat(-0.4, 0.4),
y: 1.0,
@ -170,7 +161,7 @@ Rocket.prototype.explode = function(position) {
print(JSON.stringify(color));
this.bursts.push(Entities.addEntity({
type: "ParticleEffect",
animationSettings: this.animationSettings,
isEmitting: true,
position: position,
textures: 'https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png',
emitRate: this.emitRate,

View file

@ -10,6 +10,15 @@
var DEGREES_TO_RADIANS = PI / 180.0;
var RADIANS_TO_DEGREES = 180.0 / PI;
debugPrint = function(message) {
EventBridge.emitWebEvent(
JSON.stringify({
type:"print",
message: message
})
);
};
function enableChildren(el, selector) {
els = el.querySelectorAll(selector);
for (var i = 0; i < els.length; i++) {
@ -37,7 +46,7 @@
};
}
function createEmitGroupCheckedPropertyUpdateFunction(group, propertyName) {
return function() {
return function () {
var properties = {};
properties[group] = {};
properties[group][propertyName] = this.checked;
@ -282,7 +291,11 @@
var elModelAnimationPlaying = document.getElementById("property-model-animation-playing");
var elModelAnimationFPS = document.getElementById("property-model-animation-fps");
var elModelAnimationFrame = document.getElementById("property-model-animation-frame");
var elModelAnimationSettings = document.getElementById("property-model-animation-settings");
var elModelAnimationFirstFrame = document.getElementById("property-model-animation-first-frame");
var elModelAnimationLastFrame = document.getElementById("property-model-animation-last-frame");
var elModelAnimationLoop = document.getElementById("property-model-animation-loop");
var elModelAnimationHold = document.getElementById("property-model-animation-hold");
var elModelAnimationStartAutomatically = document.getElementById("property-model-animation-start-automatically");
var elModelTextures = document.getElementById("property-model-textures");
var elModelOriginalTextures = document.getElementById("property-model-original-textures");
@ -506,11 +519,15 @@
elModelURL.value = properties.modelURL;
elShapeType.value = properties.shapeType;
elCompoundShapeURL.value = properties.compoundShapeURL;
elModelAnimationURL.value = properties.animationURL;
elModelAnimationPlaying.checked = properties.animationIsPlaying;
elModelAnimationFPS.value = properties.animationFPS;
elModelAnimationFrame.value = properties.animationFrameIndex;
elModelAnimationSettings.value = properties.animationSettings;
elModelAnimationURL.value = properties.animation.url;
elModelAnimationPlaying.checked = properties.animation.running;
elModelAnimationFPS.value = properties.animation.fps;
elModelAnimationFrame.value = properties.animation.currentFrame;
elModelAnimationFirstFrame.value = properties.animation.firstFrame;
elModelAnimationLastFrame.value = properties.animation.lastFrame;
elModelAnimationLoop.checked = properties.animation.loop;
elModelAnimationHold.checked = properties.animation.hold;
elModelAnimationStartAutomatically.checked = properties.animation.startAutomatically;
elModelTextures.value = properties.textures;
elModelOriginalTextures.value = properties.originalTextures;
} else if (properties.type == "Web") {
@ -756,11 +773,17 @@
elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL'));
elShapeType.addEventListener('change', createEmitTextPropertyUpdateFunction('shapeType'));
elCompoundShapeURL.addEventListener('change', createEmitTextPropertyUpdateFunction('compoundShapeURL'));
elModelAnimationURL.addEventListener('change', createEmitTextPropertyUpdateFunction('animationURL'));
elModelAnimationPlaying.addEventListener('change', createEmitCheckedPropertyUpdateFunction('animationIsPlaying'));
elModelAnimationFPS.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFPS'));
elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex'));
elModelAnimationSettings.addEventListener('change', createEmitTextPropertyUpdateFunction('animationSettings'));
elModelAnimationURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('animation', 'url'));
elModelAnimationPlaying.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation','running'));
elModelAnimationFPS.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation','fps'));
elModelAnimationFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'currentFrame'));
elModelAnimationFirstFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'firstFrame'));
elModelAnimationLastFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'lastFrame'));
elModelAnimationLoop.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'loop'));
elModelAnimationHold.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'hold'));
elModelAnimationStartAutomatically.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'startAutomatically'));
elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures'));
elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text'));
@ -1280,11 +1303,35 @@
</div>
</div>
<div class="model-section property">
<div class="label">Animation Settings</div>
<div class="label">Animation First Frame</div>
<div class="value">
<textarea id="property-model-animation-settings"></textarea>
<input class="coord" type='number' id="property-model-animation-first-frame">
</div>
</div>
<div class="model-section property">
<div class="label">Animation Last Frame</div>
<div class="value">
<input class="coord" type='number' id="property-model-animation-last-frame">
</div>
</div>
<div class="model-section property">
<span class="label">Animation Loop</span>
<span class="value">
<input type='checkbox' id="property-model-animation-loop">
</span>
</div>
<div class="model-section property">
<span class="label">Animation Hold</span>
<span class="value">
<input type='checkbox' id="property-model-animation-hold">
</span>
</div>
<div class="model-section property">
<span class="label">Animation Start Automatically</span>
<span class="value">
<input type='checkbox' id="property-model-animation-start-automatically">
</span>
</div>
<div class="model-section property">
<div class="label">Textures</div>
<div class="value">

View file

@ -26,8 +26,7 @@ EntityPropertyDialogBox = (function () {
var rescalePercentage;
var editModelID = -1;
var previousAnimationIsPlaying;
var previousAnimationFrameIndex;
var previousAnimationSettings;
var previousAnimationCurrentFrame;
that.cleanup = function () {
};
@ -56,18 +55,15 @@ EntityPropertyDialogBox = (function () {
index++;
array.push({ label: "Compound Shape URL:", value: properties.compoundShapeURL });
index++;
array.push({ label: "Animation URL:", value: properties.animationURL });
array.push({ label: "Animation URL:", value: properties.animation.url });
index++;
array.push({ label: "Animation is playing:", type: "checkbox", value: properties.animationIsPlaying });
previousAnimationIsPlaying = properties.animationIsPlaying;
array.push({ label: "Animation is playing:", type: "checkbox", value: properties.animation.running });
previousAnimationIsPlaying = properties.animation.running;
index++;
array.push({ label: "Animation FPS:", value: properties.animationFPS });
array.push({ label: "Animation FPS:", value: properties.animation.fps });
index++;
array.push({ label: "Animation Frame:", value: properties.animationFrameIndex });
previousAnimationFrameIndex = properties.animationFrameIndex;
index++;
array.push({ label: "Animation Settings:", value: properties.animationSettings });
previousAnimationSettings = properties.animationSettings;
array.push({ label: "Animation Frame:", value: properties.animation.currentFrame });
previousAnimationCurrentFrame = properties.animation.currentFrame;
index++;
array.push({ label: "Textures:", value: properties.textures });
index++;
@ -312,30 +308,24 @@ EntityPropertyDialogBox = (function () {
properties.modelURL = array[index++].value;
properties.shapeType = array[index++].value;
properties.compoundShapeURL = array[index++].value;
properties.animationURL = array[index++].value;
properties.animation.url = array[index++].value;
var newAnimationIsPlaying = array[index++].value;
if (previousAnimationIsPlaying != newAnimationIsPlaying) {
properties.animationIsPlaying = newAnimationIsPlaying;
properties.animation.running = newAnimationIsPlaying;
} else {
delete properties.animationIsPlaying;
delete properties.animation.running;
}
properties.animationFPS = array[index++].value;
properties.animation.fps = array[index++].value;
var newAnimationFrameIndex = array[index++].value;
if (previousAnimationFrameIndex != newAnimationFrameIndex) {
properties.animationFrameIndex = newAnimationFrameIndex;
var newAnimationCurrentFrame = array[index++].value;
if (previousAnimationCurrentFrame != newAnimationCurrentFrame) {
properties.animation.currentFrame = newAnimationCurrentFrame;
} else {
delete properties.animationFrameIndex;
delete properties.animation.currentFrame;
}
var newAnimationSettings = array[index++].value;
if (previousAnimationSettings != newAnimationSettings) {
properties.animationSettings = newAnimationSettings;
} else {
delete properties.animationSettings;
}
properties.textures = array[index++].value;
index++; // skip textureNames label
}

View file

@ -51,15 +51,6 @@
this.emitRate = randInt(80, 120);
this.emitStrength = randInt(4.0, 6.0);
this.animationSettings = JSON.stringify({
fps: 10,
frameIndex: 0,
running: true,
firstFrame: 0,
lastFrame: 50,
loop: true
});
this.direction = {
x: randFloat(-0.3, 0.3),
y: 1.0,
@ -85,7 +76,7 @@
var color = colorPalette[colorIndex];
this.emitters.push(Entities.addEntity({
type: "ParticleEffect",
animationSettings: this.animationSettings,
isEmitting: true,
position: this.point,
textures: TEXTURE_PATH,
emitRate: this.emitRate,

View file

@ -72,10 +72,7 @@ var keysToIgnore = [
'marketplaceID',
'collisionSoundURL',
'shapeType',
'animationSettings',
'animationFrameIndex',
'animationIsPlaying',
'animationFPS',
'isEmitting',
'sittingPoints',
'originalTextures'
];

View file

@ -55,15 +55,7 @@ var particleProperties;
function setUp() {
var boxPoint,
spawnPoint,
animation = {
fps: 30,
frameIndex: 0,
running: true,
firstFrame: 0,
lastFrame: 30,
loop: true
};
spawnPoint;
boxPoint = Vec3.sum(MyAvatar.position, Vec3.multiply(4.0, Quat.getFront(Camera.getOrientation())));
boxPoint = Vec3.sum(boxPoint, {
@ -138,8 +130,7 @@ function setUp() {
lifespan: 5.0,
visible: false,
locked: false,
animationSettings: animation,
animationIsPlaying: true,
isEmitting: true,
lifetime: 3600 // 1 hour; just in case
});

View file

@ -11,7 +11,7 @@
gravity: { x: 0, y: 0, z: 0 },
visible: true,
locked: false,
lifetime: 6000 });
lifetime: 6000});
var self = this;
this.timer = Script.setInterval(function () {
var colorProp = { color: { red: Math.random() * 255,
@ -29,20 +29,15 @@
// constructor
function TestFx(color, emitDirection, emitRate, emitStrength, blinkRate) {
var animationSettings = JSON.stringify({ fps: 30,
frameIndex: 0,
running: true,
firstFrame: 0,
lastFrame: 30,
loop: true });
var PI = 3.141593;
var DEG_TO_RAD = PI / 180.0;
this.entity = Entities.addEntity({ type: "ParticleEffect",
animationSettings: animationSettings,
isEmitting: true,
position: spawnPoint,
dimensions: {x: 2, y: 2, z: 2},
emitSpeed: 5,
emitSpeed: 0.05,
maxParticles: 2,
speedSpread: 2,
polarFinish: 30 * DEG_TO_RAD,
emitAcceleration: {x: 0, y: -9.8, z: 0},
@ -58,8 +53,8 @@
this.timer = Script.setInterval(function () {
// flip is playing state
self.isPlaying = !self.isPlaying;
var animProp = { animationIsPlaying: self.isPlaying };
Entities.editEntity(self.entity, animProp);
var emittingProp = { isEmitting: self.isPlaying };
Entities.editEntity(self.entity, emittingProp);
}, (1 / blinkRate) * 1000);
}

View file

@ -384,13 +384,14 @@ function createOverlays() {
}
var TEMPORARY_LIFETIME = 60;
var ANIMATION_SETTINGS = JSON.stringify({
var ANIMATION_SETTINGS = {
url: "http://s3.amazonaws.com/hifi-public/animations/Breakdancing/breakdance_ready.fbx",
fps: 30,
running: true,
loop: true,
firstFrame: 1,
lastFrame: 10000
});
};
var NATURAL_DIMENSIONS = { x: 1.63, y: 1.67, z: 0.31 };
var DIMENSIONS = Vec3.multiply(NATURAL_DIMENSIONS, 0.3);
@ -407,8 +408,7 @@ function createPuppet(model, location) {
type: "Model",
modelURL: model,
registrationPoint: { x: 0.5, y: 0, z: 0.5 },
animationURL: "http://s3.amazonaws.com/hifi-public/animations/Breakdancing/breakdance_ready.fbx",
animationSettings: ANIMATION_SETTINGS,
animation: ANIMATION_SETTINGS,
position: location,
ignoreForCollisions: true,
dimensions: DIMENSIONS,
@ -558,7 +558,7 @@ breakdanceUpdate = function(deltaTime) {
var props = Entities.getEntityProperties(puppetEntityID);
//print("puppetEntityID:" + puppetEntityID + "age:"+props.age);
Entities.editEntity(puppetEntityID, {
animationURL: poses[poseValue].animation,
animation: { url: poses[poseValue].animation },
lifetime: TEMPORARY_LIFETIME + props.age // renew lifetime
});
}

View file

@ -35,8 +35,10 @@
startNearGrab: function() {
Entities.editEntity(this.entityID, {
animationURL: "https://hifi-public.s3.amazonaws.com/models/Bboys/zombie_scream.fbx",
animationFrameIndex: 0
animation: {
url: "https://hifi-public.s3.amazonaws.com/models/Bboys/zombie_scream.fbx",
currentFrame: 0
}
});
Entities.editEntity(_this.entityID, {
@ -65,11 +67,10 @@
if (this.isGrabbed === true && this.hand === this.initialHand) {
this.audioInjector.stop();
Entities.editEntity(this.entityID, {
animationFrameIndex: 0
});
Entities.editEntity(this.entityID, {
animationURL: "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx"
animation: {
url: "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx",
currentFrame: 0
}
});
this.isGrabbed = false;

View file

@ -33,15 +33,6 @@ var originalPosition = null;
var isGrenade = false;
var isBurning = false;
var animationSettings = JSON.stringify({
running: true,
loop: true
});
var explodeAnimationSettings = JSON.stringify({
running: true,
loop: false
});
var GRAVITY = -9.8;
var TIME_TO_EXPLODE = 2500;
var DISTANCE_IN_FRONT_OF_ME = 1.0;
@ -85,7 +76,7 @@ function update() {
// Create fuse particles
particles = Entities.addEntity({
type: "ParticleEffect",
animationSettings: animationSettings,
isEmitting: true,
position: newProperties.position,
textures: 'https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png',
emitRate: 100,
@ -142,7 +133,7 @@ function boom() {
Audio.playSound(boomSound, audioOptions);
Entities.addEntity({
type: "ParticleEffect",
animationSettings: explodeAnimationSettings,
isEmitting: true,
position: properties.position,
textures: 'https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png',
emitRate: 200,

View file

@ -62,20 +62,13 @@
this.enableStream = function () {
var position = Entities.getEntityProperties(this.entityId, "position").position;
var animationSettings = JSON.stringify({
fps: 30,
loop: true,
firstFrame: 1,
lastFrame: 10000,
running: true
});
var PI = 3.141593;
var DEG_TO_RAD = PI / 180.0;
this.paintStream = Entities.addEntity({
type: "ParticleEffect",
name: "streamEffect",
animationSettings: animationSettings,
isEmitting: true,
position: position,
textures: "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png",
emitSpeed: 3,
@ -161,4 +154,4 @@
Entities.deleteEntity(this.paintStream);
}
}
});
});

View file

@ -2758,7 +2758,7 @@ void Application::update(float deltaTime) {
Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
setPalmData(hand, leftHand, deltaTime, LEFT_HAND_INDEX, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK));
setPalmData(hand, rightHand, deltaTime, RIGHT_HAND_INDEX, userInputMapper->getActionState(UserInputMapper::RIGHT_HAND_CLICK));
if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) {
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK),
userInputMapper->getActionState(UserInputMapper::SHIFT), LEFT_HAND_INDEX);
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::RIGHT_HAND_CLICK),

View file

@ -464,7 +464,7 @@ Menu::Menu() {
MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandMouseInput, 0, true);
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::EnableHandMouseInput, 0, false);
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::LowVelocityFilter, 0, true,
qApp, SLOT(setLowVelocityFilter(bool)));
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false);

View file

@ -204,7 +204,7 @@ namespace MenuOption {
const QString FrameTimer = "Show Timer";
const QString FullscreenMirror = "Fullscreen Mirror";
const QString GlowWhenSpeaking = "Glow When Speaking";
const QString HandMouseInput = "Enable Hand Mouse Input";
const QString EnableHandMouseInput = "Enable Hand Controller Mouse Input";
const QString IncreaseAvatarSize = "Increase Avatar Size";
const QString IndependentMode = "Independent Mode";
const QString InputMenu = "Avatar>Input Devices";

View file

@ -1345,11 +1345,11 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl
glm::mat4 headPose = qApp->getActiveDisplayPlugin()->getHeadPose();
glm::mat4 leftEyePose = qApp->getActiveDisplayPlugin()->getEyeToHeadTransform(Eye::Left);
leftEyePose = leftEyePose * headPose;
glm::vec3 leftEyePosition = glm::vec3(leftEyePose[3]);
glm::vec3 leftEyePosition = extractTranslation(leftEyePose);
glm::mat4 rightEyePose = qApp->getActiveDisplayPlugin()->getEyeToHeadTransform(Eye::Right);
rightEyePose = rightEyePose * headPose;
glm::vec3 rightEyePosition = glm::vec3(rightEyePose[3]);
glm::vec3 headPosition = glm::vec3(headPose[3]);
glm::vec3 rightEyePosition = extractTranslation(rightEyePose);
glm::vec3 headPosition = extractTranslation(headPose);
getHead()->renderLookAts(renderArgs,
cameraPosition + getOrientation() * (leftEyePosition - headPosition),

View file

@ -10,6 +10,7 @@
//
#include "MotionTracker.h"
#include "GLMHelpers.h"
// glm::mult(mat43, mat43) just the composition of the 2 matrices assuming they are in fact mat44 with the last raw = { 0, 0, 0, 1 }
@ -177,7 +178,7 @@ void MotionTracker::Frame::setRotation(const glm::quat& rotation) {
}
void MotionTracker::Frame::getRotation(glm::quat& rotation) const {
rotation = glm::quat_cast( _transform);
rotation = glm::quat_cast(_transform);
}
void MotionTracker::Frame::setTranslation(const glm::vec3& translation) {
@ -185,6 +186,6 @@ void MotionTracker::Frame::setTranslation(const glm::vec3& translation) {
}
void MotionTracker::Frame::getTranslation(glm::vec3& translation) const {
translation = glm::vec3(_transform[3]);
translation = extractTranslation(_transform);
}

View file

@ -63,3 +63,22 @@ bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const {
return compositor.calculateRayUICollisionPoint(position, direction, result);
}
glm::mat4 HMDScriptingInterface::getWorldHMDMatrix() const {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
return myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
}
glm::vec3 HMDScriptingInterface::getPosition() const {
if (qApp->getActiveDisplayPlugin()->isHmd()) {
return extractTranslation(getWorldHMDMatrix());
}
return glm::vec3();
}
glm::quat HMDScriptingInterface::getOrientation() const {
if (qApp->getActiveDisplayPlugin()->isHmd()) {
return glm::normalize(glm::quat_cast(getWorldHMDMatrix()));
}
return glm::quat();
}

View file

@ -24,6 +24,8 @@ class QScriptEngine;
class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency {
Q_OBJECT
Q_PROPERTY(bool magnifier READ getMagnifier)
Q_PROPERTY(glm::vec3 position READ getPosition)
Q_PROPERTY(glm::quat orientation READ getOrientation)
public:
HMDScriptingInterface();
static QScriptValue getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine);
@ -34,7 +36,14 @@ public slots:
private:
bool getMagnifier() const;
// Get the position of the HMD
glm::vec3 getPosition() const;
// Get the orientation of the HMD
glm::quat getOrientation() const;
bool getHUDLookAtPosition3D(glm::vec3& result) const;
glm::mat4 getWorldHMDMatrix() const;
};
#endif // hifi_HMDScriptingInterface_h

View file

@ -317,8 +317,8 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
glm::mat4 overlayXfm;
_modelTransform.getMatrix(overlayXfm);
// Only render the hand pointers if the HandMouseInput is enabled
if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
// Only render the hand pointers if the EnableHandMouseInput is enabled
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) {
PalmData& palm = myAvatar->getHand()->getPalms()[i];
@ -436,7 +436,8 @@ void ApplicationCompositor::renderPointers(gpu::Batch& batch) {
_magActive[MOUSE] = _magnifier;
_reticleActive[LEFT_CONTROLLER] = false;
_reticleActive[RIGHT_CONTROLLER] = false;
} else if (qApp->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
} else if (qApp->getLastMouseMoveWasSimulated()
&& Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) {
//only render controller pointer if we aren't already rendering a mouse pointer
_reticleActive[MOUSE] = false;
_magActive[MOUSE] = false;

View file

@ -130,15 +130,15 @@ void Animation::animationParseError(int error, QString str) {
AnimationDetails::AnimationDetails() :
role(), url(), fps(0.0f), priority(0.0f), loop(false), hold(false),
startAutomatically(false), firstFrame(0.0f), lastFrame(0.0f), running(false), frameIndex(0.0f)
startAutomatically(false), firstFrame(0.0f), lastFrame(0.0f), running(false), currentFrame(0.0f)
{
}
AnimationDetails::AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop,
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float frameIndex) :
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame) :
role(role), url(url), fps(fps), priority(priority), loop(loop), hold(hold),
startAutomatically(startAutomatically), firstFrame(firstFrame), lastFrame(lastFrame),
running(running), frameIndex(frameIndex)
running(running), currentFrame(currentFrame)
{
}
@ -155,7 +155,7 @@ QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const Animatio
obj.setProperty("firstFrame", details.firstFrame);
obj.setProperty("lastFrame", details.lastFrame);
obj.setProperty("running", details.running);
obj.setProperty("frameIndex", details.frameIndex);
obj.setProperty("currentFrame", details.currentFrame);
return obj;
}

View file

@ -97,7 +97,7 @@ class AnimationDetails {
public:
AnimationDetails();
AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop,
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float frameIndex);
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame);
QString role;
QUrl url;
@ -109,7 +109,7 @@ public:
float firstFrame;
float lastFrame;
bool running;
float frameIndex;
float currentFrame;
};
Q_DECLARE_METATYPE(AnimationDetails);
QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& event);

View file

@ -53,7 +53,7 @@ void AnimationHandle::setMaskedJoints(const QStringList& maskedJoints) {
void AnimationHandle::setRunning(bool running, bool doRestoreJoints) {
if (running && isRunning() && (getFadePerSecond() >= 0.0f)) {
// if we're already running, this is the same as a restart -- unless we're fading out.
setFrameIndex(getFirstFrame());
setCurrentFrame(getFirstFrame());
return;
}
_animationLoop.setRunning(running);
@ -82,7 +82,7 @@ AnimationHandle::AnimationHandle(RigPointer rig) :
AnimationDetails AnimationHandle::getAnimationDetails() const {
AnimationDetails details(_role, _url, getFPS(), _priority, getLoop(), getHold(),
getStartAutomatically(), getFirstFrame(), getLastFrame(), isRunning(), getFrameIndex());
getStartAutomatically(), getFirstFrame(), getLastFrame(), isRunning(), getCurrentFrame());
return details;
}
@ -97,7 +97,7 @@ void AnimationHandle::setAnimationDetails(const AnimationDetails& details) {
setFirstFrame(details.firstFrame);
setLastFrame(details.lastFrame);
setRunning(details.running);
setFrameIndex(details.frameIndex);
setCurrentFrame(details.currentFrame);
// NOTE: AnimationDetails doesn't support maskedJoints
//setMaskedJoints(const QStringList& maskedJoints);
@ -160,19 +160,19 @@ void AnimationHandle::simulate(float deltaTime) {
}
// blend between the closest two frames
applyFrame(getFrameIndex());
applyFrame(getCurrentFrame());
}
void AnimationHandle::applyFrame(float frameIndex) {
void AnimationHandle::applyFrame(float currentFrame) {
if (!_animation || !_animation->isLoaded()) {
return;
}
const FBXGeometry& animationGeometry = _animation->getGeometry();
int frameCount = animationGeometry.animationFrames.size();
const FBXAnimationFrame& floorFrame = animationGeometry.animationFrames.at((int)glm::floor(frameIndex) % frameCount);
const FBXAnimationFrame& ceilFrame = animationGeometry.animationFrames.at((int)glm::ceil(frameIndex) % frameCount);
float frameFraction = glm::fract(frameIndex);
const FBXAnimationFrame& floorFrame = animationGeometry.animationFrames.at((int)glm::floor(currentFrame) % frameCount);
const FBXAnimationFrame& ceilFrame = animationGeometry.animationFrames.at((int)glm::ceil(currentFrame) % frameCount);
float frameFraction = glm::fract(currentFrame);
for (int i = 0; i < _jointMappings.size(); i++) {
int mapping = _jointMappings.at(i);

View file

@ -92,10 +92,10 @@ public:
float getLastFrame() const { return _animationLoop.getLastFrame(); }
void setRunning(bool running, bool restoreJoints = true);
bool isRunning() const { return _animationLoop.isRunning(); }
bool isRunning() const { return _animationLoop.getRunning(); }
void setFrameIndex(float frameIndex) { _animationLoop.setFrameIndex(frameIndex); }
float getFrameIndex() const { return _animationLoop.getFrameIndex(); }
void setCurrentFrame(float currentFrame) { _animationLoop.setCurrentFrame(currentFrame); }
float getCurrentFrame() const { return _animationLoop.getCurrentFrame(); }
AnimationDetails getAnimationDetails() const;
void setAnimationDetails(const AnimationDetails& details);
@ -103,7 +103,7 @@ public:
void setJointMappings(QVector<int> jointMappings);
QVector<int> getJointMappings(); // computing if necessary
void simulate(float deltaTime);
void applyFrame(float frameIndex);
void applyFrame(float currentFrame);
void replaceMatchingPriorities(float newPriority);
void restoreJoints();
void clearJoints() { _jointMappings.clear(); }

View file

@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <NumericalConstants.h>
#include "AnimationCache.h"
#include "AnimationLoop.h"
@ -22,8 +24,10 @@ AnimationLoop::AnimationLoop() :
_firstFrame(0.0f),
_lastFrame(MAXIMUM_POSSIBLE_FRAME),
_running(false),
_frameIndex(0.0f),
_maxFrameIndexHint(MAXIMUM_POSSIBLE_FRAME)
_currentFrame(0.0f),
_maxFrameIndexHint(MAXIMUM_POSSIBLE_FRAME),
_resetOnRunning(true),
_lastSimulated(usecTimestampNow())
{
}
@ -35,12 +39,14 @@ AnimationLoop::AnimationLoop(const AnimationDetails& animationDetails) :
_firstFrame(animationDetails.firstFrame),
_lastFrame(animationDetails.lastFrame),
_running(animationDetails.running),
_frameIndex(animationDetails.frameIndex)
_currentFrame(animationDetails.currentFrame),
_resetOnRunning(true),
_lastSimulated(usecTimestampNow())
{
}
AnimationLoop::AnimationLoop(float fps, bool loop, bool hold, bool startAutomatically, float firstFrame,
float lastFrame, bool running, float frameIndex) :
float lastFrame, bool running, float currentFrame) :
_fps(fps),
_loop(loop),
_hold(hold),
@ -48,37 +54,44 @@ AnimationLoop::AnimationLoop(float fps, bool loop, bool hold, bool startAutomati
_firstFrame(firstFrame),
_lastFrame(lastFrame),
_running(running),
_frameIndex(frameIndex)
_currentFrame(currentFrame),
_resetOnRunning(true),
_lastSimulated(usecTimestampNow())
{
}
void AnimationLoop::simulateAtTime(quint64 now) {
float deltaTime = (float)(now - _lastSimulated) / (float)USECS_PER_SECOND;
_lastSimulated = now;
simulate(deltaTime);
}
void AnimationLoop::simulate(float deltaTime) {
_frameIndex += deltaTime * _fps;
_currentFrame += deltaTime * _fps;
// If we knew the number of frames from the animation, we'd consider using it here
// animationGeometry.animationFrames.size()
float maxFrame = _maxFrameIndexHint;
float endFrameIndex = qMin(_lastFrame, maxFrame - (_loop ? 0.0f : 1.0f));
float startFrameIndex = qMin(_firstFrame, endFrameIndex);
if ((!_loop && (_frameIndex < startFrameIndex || _frameIndex > endFrameIndex)) || startFrameIndex == endFrameIndex) {
if ((!_loop && (_currentFrame < startFrameIndex || _currentFrame > endFrameIndex)) || startFrameIndex == endFrameIndex) {
// passed the end; apply the last frame
_frameIndex = glm::clamp(_frameIndex, startFrameIndex, endFrameIndex);
_currentFrame = glm::clamp(_currentFrame, startFrameIndex, endFrameIndex);
if (!_hold) {
stop();
}
} else {
// wrap within the the desired range
if (_frameIndex < startFrameIndex) {
_frameIndex = endFrameIndex - glm::mod(endFrameIndex - _frameIndex, endFrameIndex - startFrameIndex);
} else if (_frameIndex > endFrameIndex) {
_frameIndex = startFrameIndex + glm::mod(_frameIndex - startFrameIndex, endFrameIndex - startFrameIndex);
if (_currentFrame < startFrameIndex) {
_currentFrame = endFrameIndex - glm::mod(endFrameIndex - _currentFrame, endFrameIndex - startFrameIndex);
} else if (_currentFrame > endFrameIndex) {
_currentFrame = startFrameIndex + glm::mod(_currentFrame - startFrameIndex, endFrameIndex - startFrameIndex);
}
}
}
void AnimationLoop::setStartAutomatically(bool startAutomatically) {
if ((_startAutomatically = startAutomatically) && !isRunning()) {
if ((_startAutomatically = startAutomatically) && !getRunning()) {
start();
}
}
@ -89,9 +102,14 @@ void AnimationLoop::setRunning(bool running) {
_running = running;
// If we just set running to true, then also reset the frame to the first frame
if (running) {
if (running && (_resetOnRunning)) {
// move back to the beginning
_frameIndex = _firstFrame;
_currentFrame = _firstFrame;
}
// If we just started running, set our
if (_running) {
_lastSimulated = usecTimestampNow();
}
}
}

View file

@ -21,7 +21,7 @@ public:
AnimationLoop();
AnimationLoop(const AnimationDetails& animationDetails);
AnimationLoop(float fps, bool loop, bool hold, bool startAutomatically, float firstFrame,
float lastFrame, bool running, float frameIndex);
float lastFrame, bool running, float currentFrame);
void setFPS(float fps) { _fps = fps; }
float getFPS() const { return _fps; }
@ -41,19 +41,25 @@ public:
void setLastFrame(float lastFrame) { _lastFrame = glm::clamp(lastFrame, 0.0f, MAXIMUM_POSSIBLE_FRAME); }
float getLastFrame() const { return _lastFrame; }
/// by default the AnimationLoop will always reset to the first frame on any call to setRunning
/// this is not desirable in the case of entities with animations, if you don't want the reset
/// to happen then call this method with false;
void setResetOnRunning(bool resetOnRunning) { _resetOnRunning = resetOnRunning; }
void setRunning(bool running);
bool isRunning() const { return _running; }
bool getRunning() const { return _running; }
void setFrameIndex(float frameIndex) { _frameIndex = glm::clamp(frameIndex, _firstFrame, _lastFrame); }
float getFrameIndex() const { return _frameIndex; }
void setCurrentFrame(float currentFrame) { _currentFrame = glm::clamp(currentFrame, _firstFrame, _lastFrame); }
float getCurrentFrame() const { return _currentFrame; }
void setMaxFrameIndexHint(float value) { _maxFrameIndexHint = glm::clamp(value, 0.0f, MAXIMUM_POSSIBLE_FRAME); }
float getMaxFrameIndexHint() const { return _maxFrameIndexHint; }
void start() { setRunning(true); }
void stop() { setRunning(false); }
void simulate(float deltaTime);
void simulate(float deltaTime); /// call this with deltaTime if you as the caller are managing the delta time between calls
void simulateAtTime(quint64 now); /// call this with "now" if you want the animationLoop to handle delta times
private:
float _fps;
bool _loop;
@ -62,8 +68,10 @@ private:
float _firstFrame;
float _lastFrame;
bool _running;
float _frameIndex;
float _currentFrame;
float _maxFrameIndexHint;
bool _resetOnRunning;
quint64 _lastSimulated;
};
#endif // hifi_AnimationLoop_h

View file

@ -46,10 +46,12 @@ bool RenderableModelEntityItem::setProperties(const EntityItemProperties& proper
int RenderableModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
QString oldModelURL = getModelURL();
int bytesRead = ModelEntityItem::readEntitySubclassDataFromBuffer(data, bytesLeftToRead,
args, propertyFlags, overwriteLocalData);
args, propertyFlags,
overwriteLocalData, somethingChanged);
if (oldModelURL != getModelURL()) {
_needsModelReload = true;
}

View file

@ -39,7 +39,8 @@ public:
virtual bool setProperties(const EntityItemProperties& properties);
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
virtual void somethingChangedNotification() {
// FIX ME: this is overly aggressive. We only really need to simulate() if something about

View file

@ -61,11 +61,13 @@ bool RenderableZoneEntityItem::setProperties(const EntityItemProperties& propert
int RenderableZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
changeProperties([&]() {
bytesRead = ZoneEntityItem::readEntitySubclassDataFromBuffer(data, bytesLeftToRead,
args, propertyFlags, overwriteLocalData);
args, propertyFlags,
overwriteLocalData, somethingChanged);
});
return bytesRead;
}

View file

@ -30,7 +30,8 @@ public:
virtual bool setProperties(const EntityItemProperties& properties);
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
virtual void render(RenderArgs* args);
virtual bool contains(const glm::vec3& point) const;

View file

@ -0,0 +1,408 @@
//
// AnimationPropertyGroup.cpp
// libraries/entities/src
//
// Created by Brad Hefta-Gaub on 12/4/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QJsonDocument>
#include <OctreePacketData.h>
#include <AnimationLoop.h>
#include "AnimationPropertyGroup.h"
#include "EntityItemProperties.h"
#include "EntityItemPropertiesMacros.h"
AnimationPropertyGroup::AnimationPropertyGroup() :
CONSTRUCT_PROPERTY(url, QString{}),
CONSTRUCT_PROPERTY(fps, 30.0f),
CONSTRUCT_PROPERTY(running, false),
CONSTRUCT_PROPERTY(loop, true),
CONSTRUCT_PROPERTY(firstFrame, 0.0f),
CONSTRUCT_PROPERTY(lastFrame, AnimationLoop::MAXIMUM_POSSIBLE_FRAME),
CONSTRUCT_PROPERTY(hold, false),
CONSTRUCT_PROPERTY(startAutomatically, false)
{
}
void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_URL, Animation, animation, URL, url);
if (_animationLoop) {
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_FPS, Animation, animation, FPS, fps, _animationLoop->getFPS);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame, _animationLoop->getFPS);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_PLAYING, Animation, animation, Running, running, _animationLoop->getRunning);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_LOOP, Animation, animation, Loop, loop, _animationLoop->getLoop);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame, _animationLoop->getFirstFrame);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame, _animationLoop->getLastFrame);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold, _animationLoop->getHold);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_START_AUTOMATICALLY, Animation, animation, StartAutomatically, startAutomatically, _animationLoop->getStartAutomatically);
} else {
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FPS, Animation, animation, FPS, fps);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_PLAYING, Animation, animation, Running, running);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_LOOP, Animation, animation, Loop, loop);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_START_AUTOMATICALLY, Animation, animation, StartAutomatically, startAutomatically);
}
}
void AnimationPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, url, QString, setURL);
// legacy property support
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationURL, QString, setURL, getURL);
COPY_PROPERTY_FROM_QSCRIPTVALUE_NOCHECK(animationSettings, QString, setFromOldAnimationSettings);
if (_animationLoop) {
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, fps, float, _animationLoop->setFPS);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, currentFrame, float, _animationLoop->setCurrentFrame);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, running, bool, _animationLoop->setRunning);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, loop, bool, _animationLoop->setLoop);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, firstFrame, float, _animationLoop->setFirstFrame);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, lastFrame, float, _animationLoop->setLastFrame);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, hold, bool, _animationLoop->setHold);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, startAutomatically, bool, _animationLoop->setStartAutomatically);
// legacy property support
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationFPS, float, _animationLoop->setFPS, _animationLoop->getFPS);
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationIsPlaying, bool, _animationLoop->setRunning, _animationLoop->getRunning);
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationFrameIndex, float, _animationLoop->setCurrentFrame, _animationLoop->getCurrentFrame);
} else {
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, fps, float, setFPS);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, currentFrame, float, setCurrentFrame);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, running, bool, setRunning);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, loop, bool, setLoop);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, firstFrame, float, setFirstFrame);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, lastFrame, float, setLastFrame);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, hold, bool, setHold);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, startAutomatically, bool, setStartAutomatically);
// legacy property support
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationFPS, float, setFPS, getFPS);
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationIsPlaying, bool, setRunning, getRunning);
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationFrameIndex, float, setCurrentFrame, getCurrentFrame);
}
}
void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) {
// the animations setting is a JSON string that may contain various animation settings.
// if it includes fps, currentFrame, or running, those values will be parsed out and
// will over ride the regular animation settings
float fps = _animationLoop ? _animationLoop->getFPS() : getFPS();
float currentFrame = _animationLoop ? _animationLoop->getCurrentFrame() : getCurrentFrame();
bool running = _animationLoop ? _animationLoop->getRunning() : getRunning();
float firstFrame = _animationLoop ? _animationLoop->getFirstFrame() : getFirstFrame();
float lastFrame = _animationLoop ? _animationLoop->getLastFrame() : getLastFrame();
bool loop = _animationLoop ? _animationLoop->getLoop() : getLoop();
bool hold = _animationLoop ? _animationLoop->getHold() : getHold();
bool startAutomatically = _animationLoop ? _animationLoop->getStartAutomatically() : getStartAutomatically();
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
QJsonObject settingsAsJsonObject = settingsAsJson.object();
QVariantMap settingsMap = settingsAsJsonObject.toVariantMap();
if (settingsMap.contains("fps")) {
fps = settingsMap["fps"].toFloat();
}
// old settings had frameIndex
if (settingsMap.contains("frameIndex")) {
currentFrame = settingsMap["frameIndex"].toFloat();
}
if (settingsMap.contains("running")) {
running = settingsMap["running"].toBool();
}
if (settingsMap.contains("firstFrame")) {
firstFrame = settingsMap["firstFrame"].toFloat();
}
if (settingsMap.contains("lastFrame")) {
lastFrame = settingsMap["lastFrame"].toFloat();
}
if (settingsMap.contains("loop")) {
running = settingsMap["loop"].toBool();
}
if (settingsMap.contains("hold")) {
running = settingsMap["hold"].toBool();
}
if (settingsMap.contains("startAutomatically")) {
running = settingsMap["startAutomatically"].toBool();
}
if (_animationLoop) {
_animationLoop->setFPS(fps);
_animationLoop->setCurrentFrame(currentFrame);
_animationLoop->setRunning(running);
_animationLoop->setFirstFrame(firstFrame);
_animationLoop->setLastFrame(lastFrame);
_animationLoop->setLoop(loop);
_animationLoop->setHold(hold);
_animationLoop->setStartAutomatically(startAutomatically);
} else {
setFPS(fps);
setCurrentFrame(currentFrame);
setRunning(running);
setFirstFrame(firstFrame);
setLastFrame(lastFrame);
setLoop(loop);
setHold(hold);
setStartAutomatically(startAutomatically);
}
}
void AnimationPropertyGroup::debugDump() const {
qDebug() << " AnimationPropertyGroup: ---------------------------------------------";
qDebug() << " url:" << getURL() << " has changed:" << urlChanged();
qDebug() << " fps:" << getFPS() << " has changed:" << fpsChanged();
qDebug() << "currentFrame:" << getCurrentFrame() << " has changed:" << currentFrameChanged();
}
bool AnimationPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, getURL());
if (_animationLoop) {
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, _animationLoop->getFPS());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, _animationLoop->getCurrentFrame());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, _animationLoop->getRunning());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LOOP, _animationLoop->getLoop());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, _animationLoop->getFirstFrame());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, _animationLoop->getLastFrame());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, _animationLoop->getHold());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, _animationLoop->getStartAutomatically());
} else {
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getFPS());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getCurrentFrame());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, getRunning());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LOOP, getLoop());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, getFirstFrame());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, getLastFrame());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, getHold());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, getStartAutomatically());
}
return true;
}
bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes) {
int bytesRead = 0;
bool overwriteLocalData = true;
bool somethingChanged = false;
READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setURL);
if (_animationLoop) {
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, _animationLoop->setFPS);
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, _animationLoop->setCurrentFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, _animationLoop->setRunning);
READ_ENTITY_PROPERTY(PROP_ANIMATION_LOOP, bool, _animationLoop->setLoop);
READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, _animationLoop->setFirstFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, _animationLoop->setLastFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, _animationLoop->setHold);
READ_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, bool, _animationLoop->setStartAutomatically);
} else {
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS);
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setRunning);
READ_ENTITY_PROPERTY(PROP_ANIMATION_LOOP, bool, setLoop);
READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, setFirstFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, setLastFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold);
READ_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, bool, setStartAutomatically);
}
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_URL, URL);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FPS, FPS);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FRAME_INDEX, CurrentFrame);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_PLAYING, Running);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_LOOP, Loop);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FIRST_FRAME, FirstFrame);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_LAST_FRAME, LastFrame);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_HOLD, Hold);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_START_AUTOMATICALLY, StartAutomatically);
processedBytes += bytesRead;
return true;
}
void AnimationPropertyGroup::markAllChanged() {
_urlChanged = true;
_fpsChanged = true;
_currentFrameChanged = true;
_runningChanged = true;
}
EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const {
EntityPropertyFlags changedProperties;
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_URL, url);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FPS, fps);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FRAME_INDEX, currentFrame);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_PLAYING, running);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_LOOP, loop);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FIRST_FRAME, firstFrame);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_LAST_FRAME, lastFrame);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_HOLD, hold);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_START_AUTOMATICALLY, startAutomatically);
return changedProperties;
}
void AnimationPropertyGroup::getProperties(EntityItemProperties& properties) const {
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, URL, getURL);
if (_animationLoop) {
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FPS, _animationLoop->getFPS);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, CurrentFrame, _animationLoop->getCurrentFrame);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Running, _animationLoop->getRunning);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Loop, _animationLoop->getLoop);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FirstFrame, _animationLoop->getFirstFrame);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, LastFrame, _animationLoop->getLastFrame);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Hold, _animationLoop->getHold);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, StartAutomatically, _animationLoop->getStartAutomatically);
} else {
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FPS, getFPS);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, CurrentFrame, getCurrentFrame);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Running, getRunning);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Loop, getLoop);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FirstFrame, getFirstFrame);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, LastFrame, getLastFrame);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Hold, getHold);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, StartAutomatically, getStartAutomatically);
}
}
bool AnimationPropertyGroup::setProperties(const EntityItemProperties& properties) {
bool somethingChanged = false;
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, URL, url, setURL);
if (_animationLoop) {
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FPS, fps, _animationLoop->setFPS);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, CurrentFrame, currentFrame, _animationLoop->setCurrentFrame);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Running, running, _animationLoop->setRunning);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Loop, loop, _animationLoop->setLoop);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FirstFrame, firstFrame, _animationLoop->setFirstFrame);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, LastFrame, lastFrame, _animationLoop->setLastFrame);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Hold, hold, _animationLoop->setHold);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, StartAutomatically, startAutomatically, _animationLoop->setStartAutomatically);
} else {
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FPS, fps, setFPS);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, CurrentFrame, currentFrame, setCurrentFrame);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Running, running, setRunning);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Loop, loop, setLoop);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FirstFrame, firstFrame, setFirstFrame);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, LastFrame, lastFrame, setLastFrame);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Hold, hold, setHold);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, StartAutomatically, startAutomatically, setStartAutomatically);
}
return somethingChanged;
}
EntityPropertyFlags AnimationPropertyGroup::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties;
requestedProperties += PROP_ANIMATION_URL;
requestedProperties += PROP_ANIMATION_FPS;
requestedProperties += PROP_ANIMATION_FRAME_INDEX;
requestedProperties += PROP_ANIMATION_PLAYING;
requestedProperties += PROP_ANIMATION_LOOP;
requestedProperties += PROP_ANIMATION_FIRST_FRAME;
requestedProperties += PROP_ANIMATION_LAST_FRAME;
requestedProperties += PROP_ANIMATION_HOLD;
requestedProperties += PROP_ANIMATION_START_AUTOMATICALLY;
return requestedProperties;
}
void AnimationPropertyGroup::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, getURL());
if (_animationLoop) {
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, _animationLoop->getFPS());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, _animationLoop->getCurrentFrame());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, _animationLoop->getRunning());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LOOP, _animationLoop->getLoop());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, _animationLoop->getFirstFrame());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, _animationLoop->getLastFrame());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, _animationLoop->getHold());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, _animationLoop->getStartAutomatically());
} else {
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getFPS());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getCurrentFrame());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, getRunning());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LOOP, getLoop());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, getFirstFrame());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, getLastFrame());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, getHold());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, getStartAutomatically());
}
}
int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;
READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setURL);
if (_animationLoop) {
// apply new properties to our associated AnimationLoop
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, _animationLoop->setFPS);
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, _animationLoop->setCurrentFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, _animationLoop->setRunning);
READ_ENTITY_PROPERTY(PROP_ANIMATION_LOOP, bool, _animationLoop->setLoop);
READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, _animationLoop->setFirstFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, _animationLoop->setLastFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, _animationLoop->setHold);
READ_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, bool, _animationLoop->setStartAutomatically);
} else {
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS);
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setRunning);
READ_ENTITY_PROPERTY(PROP_ANIMATION_LOOP, bool, setLoop);
READ_ENTITY_PROPERTY(PROP_ANIMATION_FIRST_FRAME, float, setFirstFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_LAST_FRAME, float, setLastFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold);
READ_ENTITY_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, bool, setStartAutomatically);
}
return bytesRead;
}

View file

@ -0,0 +1,92 @@
//
// AnimationPropertyGroup.h
// libraries/entities/src
//
// Created by Brad Hefta-Gaub on 2015/9/30.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AnimationPropertyGroup_h
#define hifi_AnimationPropertyGroup_h
#include <QtScript/QScriptEngine>
#include "PropertyGroup.h"
#include "EntityItemPropertiesMacros.h"
class EntityItemProperties;
class EncodeBitstreamParams;
class OctreePacketData;
class EntityTreeElementExtraEncodeData;
class ReadBitstreamToTreeParams;
class AnimationLoop;
#include <stdint.h>
#include <glm/glm.hpp>
class AnimationPropertyGroup : public PropertyGroup {
public:
AnimationPropertyGroup();
virtual ~AnimationPropertyGroup() {}
void associateWithAnimationLoop(AnimationLoop* animationLoop) { _animationLoop = animationLoop; }
// EntityItemProperty related helpers
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const;
virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings);
virtual void debugDump() const;
virtual bool appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const;
virtual bool decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes);
virtual void markAllChanged();
virtual EntityPropertyFlags getChangedProperties() const;
// EntityItem related helpers
// methods for getting/setting all properties of an entity
virtual void getProperties(EntityItemProperties& propertiesOut) const;
/// returns true if something changed
virtual bool setProperties(const EntityItemProperties& properties);
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const;
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
DEFINE_PROPERTY_REF(PROP_ANIMATION_URL, URL, url, QString);
DEFINE_PROPERTY(PROP_ANIMATION_FPS, FPS, fps, float);
DEFINE_PROPERTY(PROP_ANIMATION_FRAME_INDEX, CurrentFrame, currentFrame, float);
DEFINE_PROPERTY(PROP_ANIMATION_PLAYING, Running, running, bool); // was animationIsPlaying
DEFINE_PROPERTY(PROP_ANIMATION_LOOP, Loop, loop, bool); // was animationSettings.loop
DEFINE_PROPERTY(PROP_ANIMATION_FIRST_FRAME, FirstFrame, firstFrame, float); // was animationSettings.firstFrame
DEFINE_PROPERTY(PROP_ANIMATION_LAST_FRAME, LastFrame, lastFrame, float); // was animationSettings.lastFrame
DEFINE_PROPERTY(PROP_ANIMATION_HOLD, Hold, hold, bool); // was animationSettings.hold
DEFINE_PROPERTY(PROP_ANIMATION_START_AUTOMATICALLY, StartAutomatically, startAutomatically, bool); // was animationSettings.startAutomatically
protected:
void setFromOldAnimationSettings(const QString& value);
AnimationLoop* _animationLoop = nullptr;
};
#endif // hifi_AnimationPropertyGroup_h

View file

@ -63,7 +63,7 @@ void AtmospherePropertyGroup::debugDump() const {
qDebug() << " Has Stars:" << getHasStars() << " has changed:" << hasStarsChanged();
}
bool AtmospherePropertyGroup::appentToEditPacket(OctreePacketData* packetData,
bool AtmospherePropertyGroup::appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
@ -88,6 +88,7 @@ bool AtmospherePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& property
int bytesRead = 0;
bool overwriteLocalData = true;
bool somethingChanged = false;
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_CENTER, glm::vec3, setCenter);
READ_ENTITY_PROPERTY(PROP_ATMOSPHERE_INNER_RADIUS, float, setInnerRadius);
@ -194,7 +195,8 @@ void AtmospherePropertyGroup::appendSubclassData(OctreePacketData* packetData, E
int AtmospherePropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;

View file

@ -57,7 +57,7 @@ public:
virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings);
virtual void debugDump() const;
virtual bool appentToEditPacket(OctreePacketData* packetData,
virtual bool appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
@ -87,7 +87,8 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
DEFINE_PROPERTY_REF(PROP_ATMOSPHERE_CENTER, Center, center, glm::vec3);

View file

@ -65,7 +65,8 @@ bool BoxEntityItem::setProperties(const EntityItemProperties& properties) {
int BoxEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;

View file

@ -39,7 +39,8 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
const rgbColor& getColor() const { return _color; }
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }

View file

@ -403,6 +403,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
bool overwriteLocalData = true; // assume the new content overwrites our local data
quint64 now = usecTimestampNow();
bool somethingChanged = false;
// _created
{
@ -715,7 +716,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
}
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
propertyFlags, overwriteLocalData);
propertyFlags, overwriteLocalData, somethingChanged);
////////////////////////////////////
// WARNING: Do not add stream content here after the subclass. Always add it before the subclass

View file

@ -179,8 +179,9 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData)
{ return 0; }
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged)
{ somethingChanged = false; return 0; }
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) { return false; } // by default entity items don't add to scene

View file

@ -30,6 +30,7 @@
#include "LineEntityItem.h"
#include "PolyLineEntityItem.h"
AnimationPropertyGroup EntityItemProperties::_staticAnimation;
AtmospherePropertyGroup EntityItemProperties::_staticAtmosphere;
SkyboxPropertyGroup EntityItemProperties::_staticSkybox;
StagePropertyGroup EntityItemProperties::_staticStage;
@ -64,10 +65,6 @@ CONSTRUCT_PROPERTY(alphaStart, ParticleEffectEntityItem::DEFAULT_ALPHA_START),
CONSTRUCT_PROPERTY(alphaFinish, ParticleEffectEntityItem::DEFAULT_ALPHA_FINISH),
CONSTRUCT_PROPERTY(modelURL, ""),
CONSTRUCT_PROPERTY(compoundShapeURL, ""),
CONSTRUCT_PROPERTY(animationURL, ""),
CONSTRUCT_PROPERTY(animationFPS, ModelEntityItem::DEFAULT_ANIMATION_FPS),
CONSTRUCT_PROPERTY(animationFrameIndex, ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX),
CONSTRUCT_PROPERTY(animationIsPlaying, ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING),
CONSTRUCT_PROPERTY(registrationPoint, ENTITY_ITEM_DEFAULT_REGISTRATION_POINT),
CONSTRUCT_PROPERTY(angularVelocity, ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY),
CONSTRUCT_PROPERTY(angularDamping, ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING),
@ -79,8 +76,6 @@ CONSTRUCT_PROPERTY(exponent, 0.0f),
CONSTRUCT_PROPERTY(cutoff, ENTITY_ITEM_DEFAULT_CUTOFF),
CONSTRUCT_PROPERTY(locked, ENTITY_ITEM_DEFAULT_LOCKED),
CONSTRUCT_PROPERTY(textures, ""),
CONSTRUCT_PROPERTY(animationSettings, "{\"firstFrame\":0,\"fps\":30,\"frameIndex\":0,\"hold\":false,"
"\"lastFrame\":100000,\"loop\":false,\"running\":false,\"startAutomatically\":false}"),
CONSTRUCT_PROPERTY(userData, ENTITY_ITEM_DEFAULT_USER_DATA),
CONSTRUCT_PROPERTY(simulationOwner, SimulationOwner()),
CONSTRUCT_PROPERTY(text, TextEntityItem::DEFAULT_TEXT),
@ -167,63 +162,6 @@ void EntityItemProperties::calculateNaturalPosition(const glm::vec3& min, const
_naturalPosition = max - halfDimension;
}
bool EntityItemProperties::animationSettingsChanged() const {
return _animationSettingsChanged;
}
void EntityItemProperties::setAnimationSettings(const QString& value) {
// the animations setting is a JSON string that may contain various animation settings.
// if it includes fps, frameIndex, or running, those values will be parsed out and
// will over ride the regular animation settings
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
QJsonObject settingsAsJsonObject = settingsAsJson.object();
QVariantMap settingsMap = settingsAsJsonObject.toVariantMap();
if (settingsMap.contains("fps")) {
float fps = settingsMap["fps"].toFloat();
setAnimationFPS(fps);
}
if (settingsMap.contains("frameIndex")) {
float frameIndex = settingsMap["frameIndex"].toFloat();
setAnimationFrameIndex(frameIndex);
}
if (settingsMap.contains("running")) {
bool running = settingsMap["running"].toBool();
setAnimationIsPlaying(running);
}
_animationSettings = value;
_animationSettingsChanged = true;
}
QString EntityItemProperties::getAnimationSettings() const {
// the animations setting is a JSON string that may contain various animation settings.
// if it includes fps, frameIndex, or running, those values will be parsed out and
// will over ride the regular animation settings
QString value = _animationSettings;
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
QJsonObject settingsAsJsonObject = settingsAsJson.object();
QVariantMap settingsMap = settingsAsJsonObject.toVariantMap();
QVariant fpsValue(getAnimationFPS());
settingsMap["fps"] = fpsValue;
QVariant frameIndexValue(getAnimationFrameIndex());
settingsMap["frameIndex"] = frameIndexValue;
QVariant runningValue(getAnimationIsPlaying());
settingsMap["running"] = runningValue;
settingsAsJsonObject = QJsonObject::fromVariantMap(settingsMap);
QJsonDocument newDocument(settingsAsJsonObject);
QByteArray jsonByteArray = newDocument.toJson(QJsonDocument::Compact);
QString jsonByteString(jsonByteArray);
return jsonByteString;
}
void EntityItemProperties::setCreated(QDateTime &v) {
_created = v.toMSecsSinceEpoch() * 1000; // usec per msec
}
@ -238,6 +176,7 @@ void EntityItemProperties::debugDump() const {
qCDebug(entities) << " _modelURL=" << _modelURL;
qCDebug(entities) << " _compoundShapeURL=" << _compoundShapeURL;
getAnimation().debugDump();
getAtmosphere().debugDump();
getSkybox().debugDump();
@ -355,11 +294,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_ALPHA_FINISH, alphaFinish);
CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL);
CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_URL, animationURL);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_PLAYING, animationIsPlaying);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FRAME_INDEX, animationFrameIndex);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FPS, animationFPS);
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_SETTINGS, animationSettings);
CHECK_PROPERTY_CHANGE(PROP_VISIBLE, visible);
CHECK_PROPERTY_CHANGE(PROP_REGISTRATION_POINT, registrationPoint);
CHECK_PROPERTY_CHANGE(PROP_ANGULAR_VELOCITY, angularVelocity);
@ -426,9 +360,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_Y_P_NEIGHBOR_ID, yPNeighborID);
CHECK_PROPERTY_CHANGE(PROP_Z_P_NEIGHBOR_ID, zPNeighborID);
changedProperties += _stage.getChangedProperties();
changedProperties += _animation.getChangedProperties();
changedProperties += _atmosphere.getChangedProperties();
changedProperties += _skybox.getChangedProperties();
changedProperties += _stage.getChangedProperties();
return changedProperties;
}
@ -519,7 +454,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
// Models only
if (_type == EntityTypes::Model) {
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MODEL_URL, modelURL);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_URL, animationURL);
_animation.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
}
if (_type == EntityTypes::Model || _type == EntityTypes::Zone || _type == EntityTypes::ParticleEffect) {
@ -534,10 +469,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
// Models & Particles
if (_type == EntityTypes::Model || _type == EntityTypes::ParticleEffect) {
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_PLAYING, animationIsPlaying);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FPS, animationFPS);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FRAME_INDEX, animationFrameIndex);
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ANIMATION_SETTINGS, animationSettings, getAnimationSettings());
}
// Lights only
@ -673,11 +604,6 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaFinish, float, setAlphaFinish);
COPY_PROPERTY_FROM_QSCRIPTVALUE(modelURL, QString, setModelURL);
COPY_PROPERTY_FROM_QSCRIPTVALUE(compoundShapeURL, QString, setCompoundShapeURL);
COPY_PROPERTY_FROM_QSCRIPTVALUE(animationURL, QString, setAnimationURL);
COPY_PROPERTY_FROM_QSCRIPTVALUE(animationIsPlaying, bool, setAnimationIsPlaying);
COPY_PROPERTY_FROM_QSCRIPTVALUE(animationFPS, float, setAnimationFPS);
COPY_PROPERTY_FROM_QSCRIPTVALUE(animationFrameIndex, float, setAnimationFrameIndex);
COPY_PROPERTY_FROM_QSCRIPTVALUE(animationSettings, QString, setAnimationSettings);
COPY_PROPERTY_FROM_QSCRIPTVALUE(glowLevel, float, setGlowLevel);
COPY_PROPERTY_FROM_QSCRIPTVALUE(localRenderAlpha, float, setLocalRenderAlpha);
COPY_PROPERTY_FROM_QSCRIPTVALUE(ignoreForCollisions, bool, setIgnoreForCollisions);
@ -696,6 +622,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(shapeType, ShapeType);
COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, float, setMaxParticles);
COPY_PROPERTY_FROM_QSCRIPTVALUE(lifespan, float, setLifespan);
COPY_PROPERTY_FROM_QSCRIPTVALUE(isEmitting, bool, setIsEmitting);
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitRate, float, setEmitRate);
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitSpeed, float, setEmitSpeed);
COPY_PROPERTY_FROM_QSCRIPTVALUE(speedSpread, float, setSpeedSpread);
@ -744,10 +671,10 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
//COPY_PROPERTY_FROM_QSCRIPTVALUE(simulationOwner, ???, setSimulatorPriority);
}
_stage.copyFromScriptValue(object, _defaultSettings);
_animation.copyFromScriptValue(object, _defaultSettings);
_atmosphere.copyFromScriptValue(object, _defaultSettings);
_skybox.copyFromScriptValue(object, _defaultSettings);
_stage.copyFromScriptValue(object, _defaultSettings);
COPY_PROPERTY_FROM_QSCRIPTVALUE(xTextureURL, QString, setXTextureURL);
COPY_PROPERTY_FROM_QSCRIPTVALUE(yTextureURL, QString, setYTextureURL);
@ -828,10 +755,6 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_PROPERTY_TO_MAP(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float);
ADD_PROPERTY_TO_MAP(PROP_MODEL_URL, ModelURL, modelURL, QString);
ADD_PROPERTY_TO_MAP(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString);
ADD_PROPERTY_TO_MAP(PROP_ANIMATION_URL, AnimationURL, animationURL, QString);
ADD_PROPERTY_TO_MAP(PROP_ANIMATION_FPS, AnimationFPS, animationFPS, float);
ADD_PROPERTY_TO_MAP(PROP_ANIMATION_FRAME_INDEX, AnimationFrameIndex, animationFrameIndex, float);
ADD_PROPERTY_TO_MAP(PROP_ANIMATION_PLAYING, AnimationIsPlaying, animationIsPlaying, bool);
ADD_PROPERTY_TO_MAP(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3);
ADD_PROPERTY_TO_MAP(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3);
ADD_PROPERTY_TO_MAP(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float);
@ -843,7 +766,6 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_PROPERTY_TO_MAP(PROP_CUTOFF, Cutoff, cutoff, float);
ADD_PROPERTY_TO_MAP(PROP_LOCKED, Locked, locked, bool);
ADD_PROPERTY_TO_MAP(PROP_TEXTURES, Textures, textures, QString);
ADD_PROPERTY_TO_MAP(PROP_ANIMATION_SETTINGS, AnimationSettings, animationSettings, QString);
ADD_PROPERTY_TO_MAP(PROP_USER_DATA, UserData, userData, QString);
ADD_PROPERTY_TO_MAP(PROP_SIMULATION_OWNER, SimulationOwner, simulationOwner, SimulationOwner);
ADD_PROPERTY_TO_MAP(PROP_TEXT, Text, text, QString);
@ -853,6 +775,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_PROPERTY_TO_MAP(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType);
ADD_PROPERTY_TO_MAP(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32);
ADD_PROPERTY_TO_MAP(PROP_LIFESPAN, Lifespan, lifespan, float);
ADD_PROPERTY_TO_MAP(PROP_EMITTING_PARTICLES, IsEmitting, isEmitting, bool);
ADD_PROPERTY_TO_MAP(PROP_EMIT_RATE, EmitRate, emitRate, float);
ADD_PROPERTY_TO_MAP(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, glm::vec3);
ADD_PROPERTY_TO_MAP(PROP_SPEED_SPREAD, SpeedSpread, speedSpread, glm::vec3);
@ -898,8 +821,15 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_PROPERTY_TO_MAP(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID);
ADD_PROPERTY_TO_MAP(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID);
ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color);
ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_URL, Animation, animation, URL, url);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FPS, Animation, animation, FPS, fps);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_PLAYING, Animation, animation, Running, running);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LOOP, Animation, animation, Loop, loop);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_START_AUTOMATICALLY, Animation, animation, StartAutomatically, startAutomatically);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ATMOSPHERE_CENTER, Atmosphere, atmosphere, Center, center);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ATMOSPHERE_INNER_RADIUS, Atmosphere, atmosphere, InnerRadius, innerRadius);
@ -909,6 +839,9 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_GROUP_PROPERTY_TO_MAP(PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS, Atmosphere, atmosphere, ScatteringWavelengths, scatteringWavelengths);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ATMOSPHERE_HAS_STARS, Atmosphere, atmosphere, HasStars, hasStars);
ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color);
ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url);
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_SUN_MODEL_ENABLED, Stage, stage, SunModelEnabled, sunModelEnabled);
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LATITUDE, Stage, stage, Latitude, latitude);
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LONGITUDE, Stage, stage, Longitude, longitude);
@ -1087,13 +1020,11 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
if (properties.getType() == EntityTypes::Model) {
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, properties.getModelURL());
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, properties.getCompoundShapeURL());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, properties.getAnimationURL());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, properties.getAnimationFPS());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, properties.getAnimationFrameIndex());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, properties.getAnimationIsPlaying());
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, properties.getAnimationSettings());
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)(properties.getShapeType()));
_staticAnimation.setProperties(properties);
_staticAnimation.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
}
if (properties.getType() == EntityTypes::Light) {
@ -1105,13 +1036,10 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
}
if (properties.getType() == EntityTypes::ParticleEffect) {
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, properties.getAnimationFPS());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, properties.getAnimationFrameIndex());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, properties.getAnimationIsPlaying());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, properties.getAnimationSettings());
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures());
APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, properties.getMaxParticles());
APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, properties.getLifespan());
APPEND_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, properties.getIsEmitting());
APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, properties.getEmitRate());
APPEND_ENTITY_PROPERTY(PROP_EMIT_SPEED, properties.getEmitSpeed());
APPEND_ENTITY_PROPERTY(PROP_SPEED_SPREAD, properties.getSpeedSpread());
@ -1143,7 +1071,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, properties.getKeyLightDirection());
_staticStage.setProperties(properties);
_staticStage.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
_staticStage.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)properties.getShapeType());
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, properties.getCompoundShapeURL());
@ -1151,10 +1079,10 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_MODE, (uint32_t)properties.getBackgroundMode());
_staticAtmosphere.setProperties(properties);
_staticAtmosphere.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
_staticAtmosphere.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
_staticSkybox.setProperties(properties);
_staticSkybox.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
_staticSkybox.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
}
if (properties.getType() == EntityTypes::PolyVox) {
@ -1222,7 +1150,6 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
// If any part of the model items didn't fit, then the element is considered partial
if (appendState != OctreeElement::COMPLETED) {
// TODO: handle mechanism for handling partial fitting data!
// add this item into our list for the next appendElementData() pass
//modelTreeElementExtraEncodeData->includedItems.insert(getEntityItemID(), propertiesDidntFit);
@ -1377,13 +1304,10 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
if (properties.getType() == EntityTypes::Model) {
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MODEL_URL, QString, setModelURL);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_URL, QString, setAnimationURL);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FPS, float, setAnimationFPS);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType);
properties.getAnimation().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
}
if (properties.getType() == EntityTypes::Light) {
@ -1395,14 +1319,10 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
}
if (properties.getType() == EntityTypes::ParticleEffect) {
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FPS, float, setAnimationFPS);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, float, setMaxParticles);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFESPAN, float, setLifespan);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMITTING_PARTICLES, bool, setIsEmitting);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_SPEED, float, setEmitSpeed);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SPEED_SPREAD, float, setSpeedSpread);
@ -1534,11 +1454,6 @@ void EntityItemProperties::markAllChanged() {
_alphaChanged = true;
_modelURLChanged = true;
_compoundShapeURLChanged = true;
_animationURLChanged = true;
_animationIsPlayingChanged = true;
_animationFrameIndexChanged = true;
_animationFPSChanged = true;
_animationSettingsChanged = true;
_glowLevelChanged = true;
_localRenderAlphaChanged = true;
_isSpotlightChanged = true;
@ -1593,9 +1508,11 @@ void EntityItemProperties::markAllChanged() {
_keyLightDirectionChanged = true;
_backgroundModeChanged = true;
_stage.markAllChanged();
_animation.markAllChanged();
_atmosphere.markAllChanged();
_skybox.markAllChanged();
_stage.markAllChanged();
_sourceUrlChanged = true;
_voxelVolumeSizeChanged = true;

View file

@ -29,6 +29,7 @@
#include <OctreeConstants.h>
#include <ShapeInfo.h>
#include "AnimationPropertyGroup.h"
#include "AtmospherePropertyGroup.h"
#include "EntityItemID.h"
#include "EntityItemPropertiesMacros.h"
@ -115,10 +116,6 @@ public:
DEFINE_PROPERTY(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float);
DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString);
DEFINE_PROPERTY_REF(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString);
DEFINE_PROPERTY_REF(PROP_ANIMATION_URL, AnimationURL, animationURL, QString);
DEFINE_PROPERTY(PROP_ANIMATION_FPS, AnimationFPS, animationFPS, float);
DEFINE_PROPERTY(PROP_ANIMATION_FRAME_INDEX, AnimationFrameIndex, animationFrameIndex, float);
DEFINE_PROPERTY(PROP_ANIMATION_PLAYING, AnimationIsPlaying, animationIsPlaying, bool);
DEFINE_PROPERTY_REF(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3);
DEFINE_PROPERTY_REF(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3);
DEFINE_PROPERTY(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float);
@ -130,7 +127,6 @@ public:
DEFINE_PROPERTY(PROP_CUTOFF, Cutoff, cutoff, float);
DEFINE_PROPERTY(PROP_LOCKED, Locked, locked, bool);
DEFINE_PROPERTY_REF(PROP_TEXTURES, Textures, textures, QString);
DEFINE_PROPERTY_REF_WITH_SETTER_AND_GETTER(PROP_ANIMATION_SETTINGS, AnimationSettings, animationSettings, QString);
DEFINE_PROPERTY_REF(PROP_USER_DATA, UserData, userData, QString);
DEFINE_PROPERTY_REF(PROP_SIMULATION_OWNER, SimulationOwner, simulationOwner, SimulationOwner);
DEFINE_PROPERTY_REF(PROP_TEXT, Text, text, QString);
@ -140,6 +136,7 @@ public:
DEFINE_PROPERTY_REF_ENUM(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType);
DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32);
DEFINE_PROPERTY(PROP_LIFESPAN, Lifespan, lifespan, float);
DEFINE_PROPERTY(PROP_EMITTING_PARTICLES, IsEmitting, isEmitting, bool);
DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float);
DEFINE_PROPERTY(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, float);
DEFINE_PROPERTY(PROP_SPEED_SPREAD, SpeedSpread, speedSpread, float);
@ -169,6 +166,7 @@ public:
DEFINE_PROPERTY_GROUP(Stage, stage, StagePropertyGroup);
DEFINE_PROPERTY_GROUP(Atmosphere, atmosphere, AtmospherePropertyGroup);
DEFINE_PROPERTY_GROUP(Skybox, skybox, SkyboxPropertyGroup);
DEFINE_PROPERTY_GROUP(Animation, animation, AnimationPropertyGroup);
DEFINE_PROPERTY_REF(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString);
DEFINE_PROPERTY(PROP_LINE_WIDTH, LineWidth, lineWidth, float);
DEFINE_PROPERTY_REF(LINE_POINTS, LinePoints, linePoints, QVector<glm::vec3>);
@ -200,7 +198,6 @@ public:
bool containsBoundsProperties() const { return (_positionChanged || _dimensionsChanged); }
bool containsPositionChange() const { return _positionChanged; }
bool containsDimensionsChange() const { return _dimensionsChanged; }
bool containsAnimationSettingsChange() const { return _animationSettingsChanged; }
float getGlowLevel() const { return _glowLevel; }
float getLocalRenderAlpha() const { return _localRenderAlpha; }
@ -297,9 +294,6 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
if (properties.containsPositionChange()) {
debug << " position:" << properties.getPosition() << "in meters" << "\n";
}
if (properties.containsAnimationSettingsChange()) {
debug << " animationSettings:" << properties.getAnimationSettings() << "\n";
}
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Dimensions, dimensions, "in meters");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Velocity, velocity, "in meters");
@ -326,10 +320,6 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AlphaFinish, alphaFinish, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ModelURL, modelURL, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, CompoundShapeURL, compoundShapeURL, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationURL, animationURL, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationFPS, animationFPS, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationFrameIndex, animationFrameIndex, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationIsPlaying, animationIsPlaying, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, RegistrationPoint, registrationPoint, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AngularVelocity, angularVelocity, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AngularDamping, angularDamping, "");
@ -350,6 +340,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ShapeType, shapeType, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, MaxParticles, maxParticles, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifespan, lifespan, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, IsEmitting, isEmitting, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitRate, emitRate, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitSpeed, emitSpeed, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, SpeedSpread, speedSpread, "");
@ -384,9 +375,10 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
DEBUG_PROPERTY_IF_CHANGED(debug, properties, YPNeighborID, yPNeighborID, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ZPNeighborID, zPNeighborID, "");
properties.getStage().debugDump();
properties.getAnimation().debugDump();
properties.getAtmosphere().debugDump();
properties.getSkybox().debugDump();
properties.getStage().debugDump();
debug << " last edited:" << properties.getLastEdited() << "\n";
debug << " edited ago:" << properties.getEditedAgo() << "\n";

View file

@ -42,6 +42,7 @@
if (overwriteLocalData) { \
S(fromBuffer); \
} \
somethingChanged = true; \
}
#define SKIP_ENTITY_PROPERTY(P,T) \
@ -131,6 +132,18 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const EntityItemID& v)
properties.setProperty(#g, groupProperties); \
}
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(X,G,g,P,p,M) \
if ((desiredProperties.isEmpty() || desiredProperties.getHasProperty(X)) && \
(!skipDefaults || defaultEntityProperties.get##G().get##P() != get##P())) { \
QScriptValue groupProperties = properties.property(#g); \
if (!groupProperties.isValid()) { \
groupProperties = engine->newObject(); \
} \
QScriptValue V = convertScriptValue(engine, M()); \
groupProperties.setProperty(#p, V); \
properties.setProperty(#g, groupProperties); \
}
#define COPY_PROPERTY_TO_QSCRIPTVALUE(p,P) \
if ((_desiredProperties.isEmpty() || _desiredProperties.getHasProperty(p)) && \
(!skipDefaults || defaultEntityProperties._##P != _##P)) { \
@ -152,7 +165,7 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const EntityItemID& v)
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
QScriptValue V = convertScriptValue(engine, G); \
properties.setProperty(#P, V); \
}
}
typedef glm::vec3 glmVec3;
typedef glm::quat glmQuat;
@ -253,43 +266,55 @@ inline xColor xColor_convertFromScriptValue(const QScriptValue& v, bool& isValid
}
#define COPY_PROPERTY_FROM_QSCRIPTVALUE(P, T, S) \
{ \
QScriptValue V = object.property(#P); \
if (V.isValid()) { \
bool isValid = false; \
T newValue = T##_convertFromScriptValue(V, isValid); \
#define COPY_PROPERTY_FROM_QSCRIPTVALUE(P, T, S) \
{ \
QScriptValue V = object.property(#P); \
if (V.isValid()) { \
bool isValid = false; \
T newValue = T##_convertFromScriptValue(V, isValid); \
if (isValid && (_defaultSettings || newValue != _##P)) { \
S(newValue); \
} \
} \
S(newValue); \
} \
} \
}
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(P, T, S, G) \
{ \
QScriptValue V = object.property(#P); \
if (V.isValid()) { \
bool isValid = false; \
T newValue = T##_convertFromScriptValue(V, isValid); \
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(P, T, S, G) \
{ \
QScriptValue V = object.property(#P); \
if (V.isValid()) { \
bool isValid = false; \
T newValue = T##_convertFromScriptValue(V, isValid); \
if (isValid && (_defaultSettings || newValue != G())) { \
S(newValue); \
} \
}\
S(newValue); \
} \
} \
}
#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(G, P, T, S) \
{ \
QScriptValue G = object.property(#G); \
if (G.isValid()) { \
QScriptValue V = G.property(#P); \
if (V.isValid()) { \
bool isValid = false; \
T newValue = T##_convertFromScriptValue(V, isValid); \
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_NOCHECK(P, T, S) \
{ \
QScriptValue V = object.property(#P); \
if (V.isValid()) { \
bool isValid = false; \
T newValue = T##_convertFromScriptValue(V, isValid); \
if (isValid && (_defaultSettings)) { \
S(newValue); \
} \
} \
}
#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(G, P, T, S) \
{ \
QScriptValue G = object.property(#G); \
if (G.isValid()) { \
QScriptValue V = G.property(#P); \
if (V.isValid()) { \
bool isValid = false; \
T newValue = T##_convertFromScriptValue(V, isValid); \
if (isValid && (_defaultSettings || newValue != _##P)) { \
S(newValue); \
} \
} \
} \
S(newValue); \
} \
} \
} \
}
#define COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(P, S) \
@ -305,12 +330,12 @@ inline xColor xColor_convertFromScriptValue(const QScriptValue& v, bool& isValid
_##n(V), \
_##n##Changed(false)
#define DEFINE_PROPERTY_GROUP(N, n, T) \
public: \
#define DEFINE_PROPERTY_GROUP(N, n, T) \
public: \
const T& get##N() const { return _##n; } \
T& get##N() { return _##n; } \
private: \
T _##n; \
T& get##N() { return _##n; } \
private: \
T _##n; \
static T _static##N;
#define ADD_PROPERTY_TO_MAP(P, N, n, T) \

View file

@ -143,6 +143,12 @@ enum EntityPropertyList {
PROP_AZIMUTH_START,
PROP_AZIMUTH_FINISH,
PROP_ANIMATION_LOOP,
PROP_ANIMATION_FIRST_FRAME,
PROP_ANIMATION_LAST_FRAME,
PROP_ANIMATION_HOLD,
PROP_ANIMATION_START_AUTOMATICALLY,
////////////////////////////////////////////////////////////////////////////////////////////////////
// ATTENTION: add new properties to end of list just ABOVE this line
PROP_AFTER_LAST_ITEM,
@ -188,6 +194,10 @@ enum EntityPropertyList {
// other properties which will never overlap with each other.
PROP_SOURCE_URL = PROP_MODEL_URL,
// Aliases/Piggyback properties for Particle Emmitter. These properties intentionally reuse the enum values for
// other properties which will never overlap with each other.
PROP_EMITTING_PARTICLES = PROP_ANIMATION_PLAYING,
// WARNING!!! DO NOT ADD PROPS_xxx here unless you really really meant to.... Add them UP above
};

View file

@ -119,7 +119,8 @@ bool LightEntityItem::setProperties(const EntityItemProperties& properties) {
int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;

View file

@ -41,7 +41,8 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
const rgbColor& getColor() const { return _color; }
xColor getXColor() const {

View file

@ -121,7 +121,8 @@ bool LineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
int LineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;
@ -129,7 +130,6 @@ int LineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
READ_ENTITY_PROPERTY(PROP_LINE_WIDTH, float, setLineWidth);
READ_ENTITY_PROPERTY(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
return bytesRead;
}

View file

@ -39,7 +39,8 @@ class LineEntityItem : public EntityItem {
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
const rgbColor& getColor() const { return _color; }
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }

View file

@ -22,11 +22,6 @@
const QString ModelEntityItem::DEFAULT_MODEL_URL = QString("");
const QString ModelEntityItem::DEFAULT_COMPOUND_SHAPE_URL = QString("");
const QString ModelEntityItem::DEFAULT_ANIMATION_URL = QString("");
const float ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f;
const bool ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING = false;
const float ModelEntityItem::DEFAULT_ANIMATION_FPS = 30.0f;
EntityItemPointer ModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return std::make_shared<ModelEntityItem>(entityID, properties);
@ -35,28 +30,25 @@ EntityItemPointer ModelEntityItem::factory(const EntityItemID& entityID, const E
ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
EntityItem(entityItemID)
{
_animationProperties.associateWithAnimationLoop(&_animationLoop);
_animationLoop.setResetOnRunning(false);
_type = EntityTypes::Model;
setProperties(properties);
_lastAnimated = usecTimestampNow();
_jointMappingCompleted = false;
_lastKnownFrameIndex = -1;
_lastKnownCurrentFrame = -1;
_color[0] = _color[1] = _color[2] = 0;
}
EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(modelURL, getModelURL);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationURL, getAnimationURL);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationIsPlaying, getAnimationIsPlaying);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFrameIndex, getAnimationFrameIndex);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFPS, getAnimationFPS);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(glowLevel, getGlowLevel);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationSettings, getAnimationSettings);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType);
_animationProperties.getProperties(properties);
return properties;
}
@ -67,14 +59,16 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) {
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(modelURL, setModelURL);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationURL, setAnimationURL);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationIsPlaying, setAnimationIsPlaying);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFrameIndex, setAnimationFrameIndex);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFPS, setAnimationFPS);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationSettings, setAnimationSettings);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType);
bool somethingChangedInAnimations = _animationProperties.setProperties(properties);
if (somethingChangedInAnimations) {
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
}
somethingChanged = somethingChanged || somethingChangedInAnimations;
if (somethingChanged) {
bool wantDebug = false;
if (wantDebug) {
@ -91,48 +85,52 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) {
int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;
bool animationPropertiesChanged = false;
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
READ_ENTITY_PROPERTY(PROP_MODEL_URL, QString, setModelURL);
if (args.bitstreamVersion < VERSION_ENTITIES_HAS_COLLISION_MODEL) {
setCompoundShapeURL("");
} else if (args.bitstreamVersion == VERSION_ENTITIES_HAS_COLLISION_MODEL) {
READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
} else {
READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
}
READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setAnimationURL);
// Because we're using AnimationLoop which will reset the frame index if you change it's running state
// we want to read these values in the order they appear in the buffer, but call our setters in an
// order that allows AnimationLoop to preserve the correct frame rate.
float animationFPS = getAnimationFPS();
float animationFrameIndex = getAnimationFrameIndex();
bool animationIsPlaying = getAnimationIsPlaying();
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setAnimationFPS);
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex);
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
if (propertyFlags.getHasProperty(PROP_ANIMATION_PLAYING)) {
if (animationIsPlaying != getAnimationIsPlaying()) {
setAnimationIsPlaying(animationIsPlaying);
}
}
if (propertyFlags.getHasProperty(PROP_ANIMATION_FPS)) {
setAnimationFPS(animationFPS);
}
if (propertyFlags.getHasProperty(PROP_ANIMATION_FRAME_INDEX)) {
setAnimationFrameIndex(animationFrameIndex);
if (args.bitstreamVersion < VERSION_ENTITIES_ANIMATION_PROPERTIES_GROUP) {
READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setAnimationURL);
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setAnimationFPS);
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setAnimationCurrentFrame);
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
}
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings);
if (args.bitstreamVersion < VERSION_ENTITIES_ANIMATION_PROPERTIES_GROUP) {
READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings);
} else {
// Note: since we've associated our _animationProperties with our _animationLoop, the readEntitySubclassDataFromBuffer()
// will automatically read into the animation loop
int bytesFromAnimation = _animationProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
propertyFlags, overwriteLocalData, animationPropertiesChanged);
bytesRead += bytesFromAnimation;
dataAt += bytesFromAnimation;
}
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType);
if (animationPropertiesChanged) {
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
somethingChanged = true;
}
return bytesRead;
}
@ -142,13 +140,9 @@ EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams&
requestedProperties += PROP_MODEL_URL;
requestedProperties += PROP_COMPOUND_SHAPE_URL;
requestedProperties += PROP_ANIMATION_URL;
requestedProperties += PROP_ANIMATION_FPS;
requestedProperties += PROP_ANIMATION_FRAME_INDEX;
requestedProperties += PROP_ANIMATION_PLAYING;
requestedProperties += PROP_ANIMATION_SETTINGS;
requestedProperties += PROP_TEXTURES;
requestedProperties += PROP_SHAPE_TYPE;
requestedProperties += _animationProperties.getEntityProperties(params);
return requestedProperties;
}
@ -166,12 +160,11 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, getModelURL());
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, getAnimationURL());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getAnimationFPS());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getAnimationFrameIndex());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, getAnimationIsPlaying());
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, getAnimationSettings());
_animationProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
}
@ -204,7 +197,7 @@ void ModelEntityItem::mapJoints(const QStringList& modelJointNames) {
return;
}
AnimationPointer myAnimation = getAnimation(_animationURL);
AnimationPointer myAnimation = getAnimation(_animationProperties.getURL());
if (myAnimation && myAnimation->isLoaded()) {
QStringList animationJointNames = myAnimation->getJointNames();
@ -226,25 +219,24 @@ void ModelEntityItem::getAnimationFrame(bool& newFrame,
rotationsResult = _lastKnownFrameDataRotations;
translationsResult = _lastKnownFrameDataTranslations;
}
AnimationPointer myAnimation = getAnimation(_animationURL); // FIXME: this could be optimized
AnimationPointer myAnimation = getAnimation(_animationProperties.getURL()); // FIXME: this could be optimized
if (myAnimation && myAnimation->isLoaded()) {
const QVector<FBXAnimationFrame>& frames = myAnimation->getFramesReference(); // NOTE: getFrames() is too heavy
int frameCount = frames.size();
if (frameCount > 0) {
int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount;
if (animationFrameIndex < 0 || animationFrameIndex > frameCount) {
animationFrameIndex = 0;
int animationCurrentFrame = (int)(glm::floor(getAnimationCurrentFrame())) % frameCount;
if (animationCurrentFrame < 0 || animationCurrentFrame > frameCount) {
animationCurrentFrame = 0;
}
if (animationFrameIndex != _lastKnownFrameIndex) {
_lastKnownFrameIndex = animationFrameIndex;
if (animationCurrentFrame != _lastKnownCurrentFrame) {
_lastKnownCurrentFrame = animationCurrentFrame;
newFrame = true;
const QVector<glm::quat>& rotations = frames[animationFrameIndex].rotations;
const QVector<glm::vec3>& translations = frames[animationFrameIndex].translations;
const QVector<glm::quat>& rotations = frames[animationCurrentFrame].rotations;
const QVector<glm::vec3>& translations = frames[animationCurrentFrame].translations;
_lastKnownFrameDataRotations.resize(_jointMapping.size());
_lastKnownFrameDataTranslations.resize(_jointMapping.size());
@ -276,14 +268,12 @@ bool ModelEntityItem::needsToCallUpdate() const {
}
void ModelEntityItem::update(const quint64& now) {
// only advance the frame index if we're playing
if (getAnimationIsPlaying()) {
float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND;
_lastAnimated = now;
_animationLoop.simulate(deltaTime);
} else {
_lastAnimated = now;
_animationLoop.simulateAtTime(now);
}
EntityItem::update(now); // let our base class handle it's updates...
}
@ -332,25 +322,12 @@ void ModelEntityItem::setCompoundShapeURL(const QString& url) {
void ModelEntityItem::setAnimationURL(const QString& url) {
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
_animationURL = url;
}
void ModelEntityItem::setAnimationFrameIndex(float value) {
#ifdef WANT_DEBUG
if (isAnimatingSomething()) {
qCDebug(entities) << "ModelEntityItem::setAnimationFrameIndex()";
qCDebug(entities) << " value:" << value;
qCDebug(entities) << " was:" << _animationLoop.getFrameIndex();
qCDebug(entities) << " model URL:" << getModelURL();
qCDebug(entities) << " animation URL:" << getAnimationURL();
}
#endif
_animationLoop.setFrameIndex(value);
_animationProperties.setURL(url);
}
void ModelEntityItem::setAnimationSettings(const QString& value) {
// the animations setting is a JSON string that may contain various animation settings.
// if it includes fps, frameIndex, or running, those values will be parsed out and
// if it includes fps, currentFrame, or running, those values will be parsed out and
// will over ride the regular animation settings
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
@ -361,8 +338,9 @@ void ModelEntityItem::setAnimationSettings(const QString& value) {
setAnimationFPS(fps);
}
// old settings used frameIndex
if (settingsMap.contains("frameIndex")) {
float frameIndex = settingsMap["frameIndex"].toFloat();
float currentFrame = settingsMap["frameIndex"].toFloat();
#ifdef WANT_DEBUG
if (isAnimatingSomething()) {
qCDebug(entities) << "ModelEntityItem::setAnimationSettings() calling setAnimationFrameIndex()...";
@ -370,11 +348,11 @@ void ModelEntityItem::setAnimationSettings(const QString& value) {
qCDebug(entities) << " animation URL:" << getAnimationURL();
qCDebug(entities) << " settings:" << value;
qCDebug(entities) << " settingsMap[frameIndex]:" << settingsMap["frameIndex"];
qCDebug(entities" frameIndex: %20.5f", frameIndex);
qCDebug(entities" currentFrame: %20.5f", currentFrame);
}
#endif
setAnimationFrameIndex(frameIndex);
setAnimationCurrentFrame(currentFrame);
}
if (settingsMap.contains("running")) {
@ -409,7 +387,6 @@ void ModelEntityItem::setAnimationSettings(const QString& value) {
setAnimationStartAutomatically(startAutomatically);
}
_animationSettings = value;
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
}
@ -423,47 +400,6 @@ void ModelEntityItem::setAnimationFPS(float value) {
_animationLoop.setFPS(value);
}
QString ModelEntityItem::getAnimationSettings() const {
// the animations setting is a JSON string that may contain various animation settings.
// if it includes fps, frameIndex, or running, those values will be parsed out and
// will over ride the regular animation settings
QString value = _animationSettings;
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
QJsonObject settingsAsJsonObject = settingsAsJson.object();
QVariantMap settingsMap = settingsAsJsonObject.toVariantMap();
QVariant fpsValue(getAnimationFPS());
settingsMap["fps"] = fpsValue;
QVariant frameIndexValue(getAnimationFrameIndex());
settingsMap["frameIndex"] = frameIndexValue;
QVariant runningValue(getAnimationIsPlaying());
settingsMap["running"] = runningValue;
QVariant firstFrameValue(getAnimationFirstFrame());
settingsMap["firstFrame"] = firstFrameValue;
QVariant lastFrameValue(getAnimationLastFrame());
settingsMap["lastFrame"] = lastFrameValue;
QVariant loopValue(getAnimationLoop());
settingsMap["loop"] = loopValue;
QVariant holdValue(getAnimationHold());
settingsMap["hold"] = holdValue;
QVariant startAutomaticallyValue(getAnimationStartAutomatically());
settingsMap["startAutomatically"] = startAutomaticallyValue;
settingsAsJsonObject = QJsonObject::fromVariantMap(settingsMap);
QJsonDocument newDocument(settingsAsJsonObject);
QByteArray jsonByteArray = newDocument.toJson(QJsonDocument::Compact);
QString jsonByteString(jsonByteArray);
return jsonByteString;
}
// virtual
bool ModelEntityItem::shouldBePhysical() const {
return getShapeType() != SHAPE_TYPE_NONE;

View file

@ -42,7 +42,8 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
virtual void update(const quint64& now);
virtual bool needsToCallUpdate() const;
@ -65,10 +66,6 @@ public:
static const QString DEFAULT_COMPOUND_SHAPE_URL;
const QString& getCompoundShapeURL() const { return _compoundShapeURL; }
bool hasAnimation() const { return !_animationURL.isEmpty(); }
static const QString DEFAULT_ANIMATION_URL;
const QString& getAnimationURL() const { return _animationURL; }
void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
void setColor(const xColor& value) {
_color[RED_INDEX] = value.red;
@ -79,15 +76,17 @@ public:
// model related properties
void setModelURL(const QString& url) { _modelURL = url; }
virtual void setCompoundShapeURL(const QString& url);
// Animation related items...
const AnimationPropertyGroup& getAnimationProperties() const { return _animationProperties; }
bool hasAnimation() const { return !_animationProperties.getURL().isEmpty(); }
const QString& getAnimationURL() const { return _animationProperties.getURL(); }
void setAnimationURL(const QString& url);
static const float DEFAULT_ANIMATION_FRAME_INDEX;
void setAnimationFrameIndex(float value);
void setAnimationSettings(const QString& value);
static const bool DEFAULT_ANIMATION_IS_PLAYING;
void setAnimationCurrentFrame(float value) { _animationLoop.setCurrentFrame(value); }
void setAnimationIsPlaying(bool value);
static const float DEFAULT_ANIMATION_FPS;
void setAnimationFPS(float value);
void setAnimationLoop(bool loop) { _animationLoop.setLoop(loop); }
@ -109,10 +108,9 @@ public:
void getAnimationFrame(bool& newFrame, QVector<glm::quat>& rotationsResult, QVector<glm::vec3>& translationsResult);
bool jointsMapped() const { return _jointMappingCompleted; }
bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); }
float getAnimationFrameIndex() const { return _animationLoop.getFrameIndex(); }
bool getAnimationIsPlaying() const { return _animationLoop.getRunning(); }
float getAnimationCurrentFrame() const { return _animationLoop.getCurrentFrame(); }
float getAnimationFPS() const { return _animationLoop.getFPS(); }
QString getAnimationSettings() const;
static const QString DEFAULT_TEXTURES;
const QString& getTextures() const { return _textures; }
@ -121,11 +119,14 @@ public:
virtual bool shouldBePhysical() const;
static void cleanupLoadedAnimations();
private:
void setAnimationSettings(const QString& value); // only called for old bitstream format
protected:
QVector<glm::quat> _lastKnownFrameDataRotations;
QVector<glm::vec3> _lastKnownFrameDataTranslations;
int _lastKnownFrameIndex;
int _lastKnownCurrentFrame;
bool isAnimatingSomething() const;
@ -134,10 +135,9 @@ protected:
QString _modelURL;
QString _compoundShapeURL;
quint64 _lastAnimated;
QString _animationURL;
AnimationPropertyGroup _animationProperties;
AnimationLoop _animationLoop;
QString _animationSettings;
QString _textures;
ShapeType _shapeType = SHAPE_TYPE_NONE;

View file

@ -52,9 +52,6 @@ const float ParticleEffectEntityItem::DEFAULT_ALPHA = 1.0f;
const float ParticleEffectEntityItem::DEFAULT_ALPHA_SPREAD = 0.0f;
const float ParticleEffectEntityItem::DEFAULT_ALPHA_START = DEFAULT_ALPHA;
const float ParticleEffectEntityItem::DEFAULT_ALPHA_FINISH = DEFAULT_ALPHA;
const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f;
const bool ParticleEffectEntityItem::DEFAULT_ANIMATION_IS_PLAYING = false;
const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FPS = 30.0f;
const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000;
const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f;
const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f;
@ -83,9 +80,8 @@ EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID
// our non-pure virtual subclass for now...
ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
EntityItem(entityItemID),
_lastAnimated(usecTimestampNow()),
_animationLoop(),
_animationSettings(),
_lastSimulated(usecTimestampNow()),
_isEmitting(true),
_particleLifetimes(DEFAULT_MAX_PARTICLES, 0.0f),
_particlePositions(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)),
_particleVelocities(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)),
@ -103,7 +99,8 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte
_alphaMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA),
_alphaFinishes(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA),
_particleMaxBound(glm::vec3(1.0f, 1.0f, 1.0f)),
_particleMinBound(glm::vec3(-1.0f, -1.0f, -1.0f)) {
_particleMinBound(glm::vec3(-1.0f, -1.0f, -1.0f))
{
_type = EntityTypes::ParticleEffect;
setColor(DEFAULT_COLOR);
@ -168,14 +165,11 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(EntityPropertyFlags
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationIsPlaying, getAnimationIsPlaying);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFrameIndex, getAnimationFrameIndex);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFPS, getAnimationFPS);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(glowLevel, getGlowLevel);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationSettings, getAnimationSettings);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(maxParticles, getMaxParticles);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifespan, getLifespan);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(isEmitting, getIsEmitting);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitRate, getEmitRate);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitSpeed, getEmitSpeed);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(speedSpread, getSpeedSpread);
@ -208,14 +202,11 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationIsPlaying, setAnimationIsPlaying);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFrameIndex, setAnimationFrameIndex);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFPS, setAnimationFPS);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationSettings, setAnimationSettings);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(maxParticles, setMaxParticles);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifespan, setLifespan);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(isEmitting, setIsEmitting);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitRate, setEmitRate);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitSpeed, setEmitSpeed);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(speedSpread, setSpeedSpread);
@ -255,7 +246,8 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;
@ -265,25 +257,15 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
// Because we're using AnimationLoop which will reset the frame index if you change it's running state
// we want to read these values in the order they appear in the buffer, but call our setters in an
// order that allows AnimationLoop to preserve the correct frame rate.
float animationFPS = getAnimationFPS();
float animationFrameIndex = getAnimationFrameIndex();
bool animationIsPlaying = getAnimationIsPlaying();
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setAnimationFPS);
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex);
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
if (args.bitstreamVersion < VERSION_ENTITIES_ANIMATION_PROPERTIES_GROUP) {
SKIP_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float);
SKIP_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float);
SKIP_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool);
SKIP_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString);
} else {
READ_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, bool, setIsEmitting);
}
if (propertyFlags.getHasProperty(PROP_ANIMATION_PLAYING)) {
if (animationIsPlaying != getAnimationIsPlaying()) {
setAnimationIsPlaying(animationIsPlaying);
}
}
if (propertyFlags.getHasProperty(PROP_ANIMATION_FPS)) {
setAnimationFPS(animationFPS);
}
if (propertyFlags.getHasProperty(PROP_ANIMATION_FRAME_INDEX)) {
setAnimationFrameIndex(animationFrameIndex);
}
READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings);
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType);
READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles);
READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan);
@ -348,13 +330,10 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_COLOR;
requestedProperties += PROP_ANIMATION_FPS;
requestedProperties += PROP_ANIMATION_FRAME_INDEX;
requestedProperties += PROP_ANIMATION_PLAYING;
requestedProperties += PROP_ANIMATION_SETTINGS;
requestedProperties += PROP_SHAPE_TYPE;
requestedProperties += PROP_MAX_PARTICLES;
requestedProperties += PROP_LIFESPAN;
requestedProperties += PROP_EMITTING_PARTICLES;
requestedProperties += PROP_EMIT_RATE;
requestedProperties += PROP_EMIT_ACCELERATION;
requestedProperties += PROP_ACCELERATION_SPREAD;
@ -384,7 +363,7 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea
}
void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
@ -393,10 +372,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getAnimationFPS());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getAnimationFrameIndex());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, getAnimationIsPlaying());
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, getAnimationSettings());
APPEND_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, getIsEmitting());
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, getMaxParticles());
APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, getLifespan());
@ -426,9 +402,9 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, getAzimuthFinish());
}
bool ParticleEffectEntityItem::isAnimatingSomething() const {
// keep animating if there are particles still alive.
return (getAnimationIsPlaying() || getLivingParticleCount() > 0) && getAnimationFPS() != 0.0f;
bool ParticleEffectEntityItem::isEmittingParticles() const {
// keep emitting if there are particles still alive.
return (getIsEmitting() || getLivingParticleCount() > 0);
}
bool ParticleEffectEntityItem::needsToCallUpdate() const {
@ -437,15 +413,10 @@ bool ParticleEffectEntityItem::needsToCallUpdate() const {
void ParticleEffectEntityItem::update(const quint64& now) {
float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND;
_lastAnimated = now;
float deltaTime = (float)(now - _lastSimulated) / (float)USECS_PER_SECOND;
_lastSimulated = now;
// only advance the frame index if we're playing
if (getAnimationIsPlaying()) {
_animationLoop.simulate(deltaTime);
}
if (isAnimatingSomething()) {
if (isEmittingParticles()) {
stepSimulation(deltaTime);
}
@ -468,131 +439,6 @@ void ParticleEffectEntityItem::updateShapeType(ShapeType type) {
}
}
void ParticleEffectEntityItem::setAnimationFrameIndex(float value) {
#ifdef WANT_DEBUG
if (isAnimatingSomething()) {
qCDebug(entities) << "ParticleEffectEntityItem::setAnimationFrameIndex()";
qCDebug(entities) << " value:" << value;
qCDebug(entities) << " was:" << _animationLoop.getFrameIndex();
}
#endif
_animationLoop.setFrameIndex(value);
}
void ParticleEffectEntityItem::setAnimationSettings(const QString& value) {
// the animations setting is a JSON string that may contain various animation settings.
// if it includes fps, frameIndex, or running, those values will be parsed out and
// will over ride the regular animation settings
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
QJsonObject settingsAsJsonObject = settingsAsJson.object();
QVariantMap settingsMap = settingsAsJsonObject.toVariantMap();
if (settingsMap.contains("fps")) {
float fps = settingsMap["fps"].toFloat();
setAnimationFPS(fps);
}
if (settingsMap.contains("frameIndex")) {
float frameIndex = settingsMap["frameIndex"].toFloat();
#ifdef WANT_DEBUG
if (isAnimatingSomething()) {
qCDebug(entities) << "ParticleEffectEntityItem::setAnimationSettings() calling setAnimationFrameIndex()...";
qCDebug(entities) << " settings:" << value;
qCDebug(entities) << " settingsMap[frameIndex]:" << settingsMap["frameIndex"];
qCDebug(entities, " frameIndex: %20.5f", frameIndex);
}
#endif
setAnimationFrameIndex(frameIndex);
}
if (settingsMap.contains("running")) {
bool running = settingsMap["running"].toBool();
if (running != getAnimationIsPlaying()) {
setAnimationIsPlaying(running);
}
}
if (settingsMap.contains("firstFrame")) {
float firstFrame = settingsMap["firstFrame"].toFloat();
setAnimationFirstFrame(firstFrame);
}
if (settingsMap.contains("lastFrame")) {
float lastFrame = settingsMap["lastFrame"].toFloat();
setAnimationLastFrame(lastFrame);
}
if (settingsMap.contains("loop")) {
bool loop = settingsMap["loop"].toBool();
setAnimationLoop(loop);
}
if (settingsMap.contains("hold")) {
bool hold = settingsMap["hold"].toBool();
setAnimationHold(hold);
}
if (settingsMap.contains("startAutomatically")) {
bool startAutomatically = settingsMap["startAutomatically"].toBool();
setAnimationStartAutomatically(startAutomatically);
}
_animationSettings = value;
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
}
void ParticleEffectEntityItem::setAnimationIsPlaying(bool value) {
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
_animationLoop.setRunning(value);
}
void ParticleEffectEntityItem::setAnimationFPS(float value) {
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
_animationLoop.setFPS(value);
}
QString ParticleEffectEntityItem::getAnimationSettings() const {
// the animations setting is a JSON string that may contain various animation settings.
// if it includes fps, frameIndex, or running, those values will be parsed out and
// will over ride the regular animation settings
QString value = _animationSettings;
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
QJsonObject settingsAsJsonObject = settingsAsJson.object();
QVariantMap settingsMap = settingsAsJsonObject.toVariantMap();
QVariant fpsValue(getAnimationFPS());
settingsMap["fps"] = fpsValue;
QVariant frameIndexValue(getAnimationFrameIndex());
settingsMap["frameIndex"] = frameIndexValue;
QVariant runningValue(getAnimationIsPlaying());
settingsMap["running"] = runningValue;
QVariant firstFrameValue(getAnimationFirstFrame());
settingsMap["firstFrame"] = firstFrameValue;
QVariant lastFrameValue(getAnimationLastFrame());
settingsMap["lastFrame"] = lastFrameValue;
QVariant loopValue(getAnimationLoop());
settingsMap["loop"] = loopValue;
QVariant holdValue(getAnimationHold());
settingsMap["hold"] = holdValue;
QVariant startAutomaticallyValue(getAnimationStartAutomatically());
settingsMap["startAutomatically"] = startAutomaticallyValue;
settingsAsJsonObject = QJsonObject::fromVariantMap(settingsMap);
QJsonDocument newDocument(settingsAsJsonObject);
QByteArray jsonByteArray = newDocument.toJson(QJsonDocument::Compact);
QString jsonByteString(jsonByteArray);
return jsonByteString;
}
void ParticleEffectEntityItem::updateRadius(quint32 index, float age) {
_particleRadiuses[index] = Interpolate::interpolate3Points(_radiusStarts[index], _radiusMiddles[index],
_radiusFinishes[index], age);
@ -653,8 +499,8 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
}
}
// emit new particles, but only if animation is playing
if (getAnimationIsPlaying()) {
// emit new particles, but only if we are emmitting
if (isEmittingParticles()) {
float timeLeftInFrame = deltaTime;
while (_timeUntilNextEmit < timeLeftInFrame) {

View file

@ -31,7 +31,7 @@ public:
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
@ -40,7 +40,8 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
virtual void update(const quint64& now);
virtual bool needsToCallUpdate() const;
@ -91,30 +92,9 @@ public:
virtual void debugDump() const;
static const float DEFAULT_ANIMATION_FRAME_INDEX;
void setAnimationFrameIndex(float value);
void setAnimationSettings(const QString& value);
static const bool DEFAULT_ANIMATION_IS_PLAYING;
void setAnimationIsPlaying(bool value);
static const float DEFAULT_ANIMATION_FPS;
void setAnimationFPS(float value);
void setAnimationLoop(bool loop) { _animationLoop.setLoop(loop); }
bool getAnimationLoop() const { return _animationLoop.getLoop(); }
void setAnimationHold(bool hold) { _animationLoop.setHold(hold); }
bool getAnimationHold() const { return _animationLoop.getHold(); }
void setAnimationStartAutomatically(bool startAutomatically) { _animationLoop.setStartAutomatically(startAutomatically); }
bool getAnimationStartAutomatically() const { return _animationLoop.getStartAutomatically(); }
void setAnimationFirstFrame(float firstFrame) { _animationLoop.setFirstFrame(firstFrame); }
float getAnimationFirstFrame() const { return _animationLoop.getFirstFrame(); }
void setAnimationLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); }
float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); }
bool isEmittingParticles() const; /// emitting enabled, and there are particles alive
bool getIsEmitting() const { return _isEmitting; }
void setIsEmitting(bool isEmitting) { _isEmitting = isEmitting; }
static const quint32 DEFAULT_MAX_PARTICLES;
void setMaxParticles(quint32 maxParticles);
@ -192,12 +172,6 @@ public:
void computeAndUpdateDimensions();
bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); }
float getAnimationFrameIndex() const { return _animationLoop.getFrameIndex(); }
float getAnimationFPS() const { return _animationLoop.getFPS(); }
QString getAnimationSettings() const;
static const QString DEFAULT_TEXTURES;
const QString& getTextures() const { return _textures; }
void setTextures(const QString& textures) {
@ -245,9 +219,11 @@ protected:
float _radiusStart = DEFAULT_RADIUS_START;
float _radiusFinish = DEFAULT_RADIUS_FINISH;
float _radiusSpread = DEFAULT_RADIUS_SPREAD;
quint64 _lastAnimated;
AnimationLoop _animationLoop;
QString _animationSettings;
quint64 _lastSimulated;
bool _isEmitting;
QString _textures = DEFAULT_TEXTURES;
bool _texturesChangedFlag = false;
ShapeType _shapeType = SHAPE_TYPE_NONE;

View file

@ -184,8 +184,10 @@ bool PolyLineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
QWriteLocker lock(&_quadReadWriteLock);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
QWriteLocker lock(&_quadReadWriteLock);
int bytesRead = 0;
const unsigned char* dataAt = data;

View file

@ -39,7 +39,8 @@ class PolyLineEntityItem : public EntityItem {
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
const rgbColor& getColor() const { return _color; }
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }

View file

@ -152,7 +152,8 @@ bool PolyVoxEntityItem::setProperties(const EntityItemProperties& properties) {
int PolyVoxEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;

View file

@ -39,7 +39,8 @@ class PolyVoxEntityItem : public EntityItem {
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
// never have a ray intersection pick a PolyVoxEntityItem.
virtual bool supportsDetailedRayIntersection() const { return true; }

View file

@ -59,7 +59,7 @@ public:
virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) = 0;
virtual void debugDump() const { }
virtual bool appentToEditPacket(OctreePacketData* packetData,
virtual bool appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
@ -81,7 +81,6 @@ public:
/// has changed. This will be called with properties change or when new data is loaded from a stream
virtual void somethingChangedNotification() { }
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const = 0;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
@ -94,7 +93,8 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) = 0;
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) = 0;
};
#endif // hifi_PropertyGroup_h

View file

@ -36,7 +36,7 @@ void SkyboxPropertyGroup::debugDump() const {
qDebug() << " URL:" << getURL() << " has changed:" << urlChanged();
}
bool SkyboxPropertyGroup::appentToEditPacket(OctreePacketData* packetData,
bool SkyboxPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
@ -56,6 +56,7 @@ bool SkyboxPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlag
int bytesRead = 0;
bool overwriteLocalData = true;
bool somethingChanged = false;
READ_ENTITY_PROPERTY(PROP_SKYBOX_COLOR, xColor, setColor);
READ_ENTITY_PROPERTY(PROP_SKYBOX_URL, QString, setURL);
@ -121,7 +122,8 @@ void SkyboxPropertyGroup::appendSubclassData(OctreePacketData* packetData, Encod
int SkyboxPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;

View file

@ -37,7 +37,7 @@ public:
virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings);
virtual void debugDump() const;
virtual bool appentToEditPacket(OctreePacketData* packetData,
virtual bool appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
@ -67,7 +67,8 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
glm::vec3 getColorVec3() const {
const quint8 MAX_COLOR = 255;

View file

@ -63,7 +63,8 @@ bool SphereEntityItem::setProperties(const EntityItemProperties& properties) {
int SphereEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;

View file

@ -38,7 +38,8 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
const rgbColor& getColor() const { return _color; }
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }

View file

@ -76,7 +76,7 @@ void StagePropertyGroup::debugDump() const {
qDebug() << " _automaticHourDay:" << _automaticHourDay;
}
bool StagePropertyGroup::appentToEditPacket(OctreePacketData* packetData,
bool StagePropertyGroup::appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
@ -101,6 +101,7 @@ bool StagePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags
int bytesRead = 0;
bool overwriteLocalData = true;
bool somethingChanged = false;
READ_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, bool, setSunModelEnabled);
READ_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, float, setLatitude);
@ -206,7 +207,8 @@ void StagePropertyGroup::appendSubclassData(OctreePacketData* packetData, Encode
int StagePropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;

View file

@ -37,7 +37,7 @@ public:
virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings);
virtual void debugDump() const;
virtual bool appentToEditPacket(OctreePacketData* packetData,
virtual bool appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
@ -67,7 +67,8 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
static const bool DEFAULT_STAGE_SUN_MODEL_ENABLED;
static const float DEFAULT_STAGE_LATITUDE;

View file

@ -84,7 +84,8 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) {
int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;

View file

@ -43,7 +43,8 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,

View file

@ -68,7 +68,8 @@ bool WebEntityItem::setProperties(const EntityItemProperties& properties) {
int WebEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;

View file

@ -42,7 +42,8 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,

View file

@ -129,7 +129,8 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) {
int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;
@ -139,7 +140,7 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setKeyLightDirection);
int bytesFromStage = _stageProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
propertyFlags, overwriteLocalData);
propertyFlags, overwriteLocalData, somethingChanged);
bytesRead += bytesFromStage;
dataAt += bytesFromStage;
@ -149,13 +150,13 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
READ_ENTITY_PROPERTY(PROP_BACKGROUND_MODE, BackgroundMode, setBackgroundMode);
int bytesFromAtmosphere = _atmosphereProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
propertyFlags, overwriteLocalData);
propertyFlags, overwriteLocalData, somethingChanged);
bytesRead += bytesFromAtmosphere;
dataAt += bytesFromAtmosphere;
int bytesFromSkybox = _skyboxProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
propertyFlags, overwriteLocalData);
propertyFlags, overwriteLocalData, somethingChanged);
bytesRead += bytesFromSkybox;
dataAt += bytesFromSkybox;

View file

@ -43,7 +43,8 @@ public:
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged);
xColor getKeyLightColor() const { xColor color = { _keyLightColor[RED_INDEX], _keyLightColor[GREEN_INDEX], _keyLightColor[BLUE_INDEX] }; return color; }
void setKeyLightColor(const xColor& value) {

View file

@ -38,7 +38,9 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::EntityAdd:
case PacketType::EntityEdit:
case PacketType::EntityData:
return VERSION_ENTITIES_PROTOCOL_CHANNELS;
return VERSION_ENTITIES_ANIMATION_PROPERTIES_GROUP;
case PacketType::AvatarData:
case PacketType::BulkAvatarData:
default:
return 16;
}

View file

@ -142,5 +142,6 @@ const PacketVersion VERSION_ENTITIES_PARTICLE_COLOR_PROPERTIES = 42;
const PacketVersion VERSION_ENTITIES_PROTOCOL_HEADER_SWAP = 43;
const PacketVersion VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER = 44;
const PacketVersion VERSION_ENTITIES_PROTOCOL_CHANNELS = 45;
const PacketVersion VERSION_ENTITIES_ANIMATION_PROPERTIES_GROUP = 46;
#endif // hifi_PacketHeaders_h

View file

@ -13,8 +13,7 @@
#include <assert.h>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include "GLMHelpers.h"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/quaternion.hpp>
@ -419,7 +418,7 @@ inline Transform::Mat4& Transform::getRotationScaleMatrixInverse(Mat4& result) c
inline Transform& Transform::evalFromRawMatrix(const Mat4& matrix) {
// for now works only in the case of TRS transformation
if ((matrix[0][3] == 0.0f) && (matrix[1][3] == 0.0f) && (matrix[2][3] == 0.0f) && (matrix[3][3] == 1.0f)) {
setTranslation(Vec3(matrix[3]));
setTranslation(extractTranslation(matrix));
evalFromRawMatrix(Mat3(matrix));
}
return *this;

View file

@ -331,19 +331,10 @@ function createFire() {
var myOrientation = Quat.fromPitchYawRollDegrees(-90, 0, 0.0);
var animationSettings = JSON.stringify({
fps: 30,
running: true,
loop: true,
firstFrame: 1,
lastFrame: 10000
});
var fire = Entities.addEntity({
type: "ParticleEffect",
name: "fire",
animationSettings: animationSettings,
isEmitting: true,
textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png",
position: {
x: 551.45,
@ -406,17 +397,16 @@ function createFire() {
function createCat(position) {
var scriptURL = Script.resolvePath("../examples/toys/cat.js");
var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/Dark_Cat.fbx";
var animationURL = "http://hifi-public.s3.amazonaws.com/ryan/sleeping.fbx";
var animationSettings = JSON.stringify({
var animationSettings = {
url: "http://hifi-public.s3.amazonaws.com/ryan/sleeping.fbx",
running: true,
});
};
var cat = Entities.addEntity({
type: "Model",
modelURL: modelURL,
name: "cat",
script: scriptURL,
animationURL: animationURL,
animationSettings: animationSettings,
animation: animationSettings,
position: position,
rotation: {
w: 0.35020983219146729,
@ -1126,4 +1116,4 @@ function cleanup() {
if (shouldDeleteOnEndScript) {
Script.scriptEnding.connect(cleanup);
}
}