mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-13 14:53:15 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into orange
This commit is contained in:
commit
c9cb768945
75 changed files with 1917 additions and 1414 deletions
|
@ -18,7 +18,7 @@ Script.include("../libraries/utils.js");
|
|||
// these tune time-averaging and "on" value for analog trigger
|
||||
//
|
||||
|
||||
var TRIGGER_SMOOTH_RATIO = 0.7;
|
||||
var TRIGGER_SMOOTH_RATIO = 0.1; // 0.0 disables smoothing of trigger value
|
||||
var TRIGGER_ON_VALUE = 0.2;
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
@ -26,7 +26,7 @@ var TRIGGER_ON_VALUE = 0.2;
|
|||
// distant manipulation
|
||||
//
|
||||
|
||||
var DISTANCE_HOLDING_RADIUS_FACTOR = 4; // multiplied by distance between hand and object
|
||||
var DISTANCE_HOLDING_RADIUS_FACTOR = 5; // multiplied by distance between hand and object
|
||||
var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position
|
||||
var DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR = 2.0; // object rotates this much more than hand did
|
||||
var NO_INTERSECT_COLOR = {red: 10, green: 10, blue: 255}; // line color when pick misses
|
||||
|
@ -37,14 +37,14 @@ var LINE_LENGTH = 500;
|
|||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// close grabbing
|
||||
// near grabbing
|
||||
//
|
||||
|
||||
var GRAB_RADIUS = 0.3; // if the ray misses but an object is this close, it will still be selected
|
||||
var CLOSE_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position
|
||||
var CLOSE_GRABBING_VELOCITY_SMOOTH_RATIO = 0.9; // adjust time-averaging of held object's velocity
|
||||
var CLOSE_PICK_MAX_DISTANCE = 0.6; // max length of pick-ray for close grabbing to be selected
|
||||
|
||||
var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position
|
||||
var NEAR_GRABBING_VELOCITY_SMOOTH_RATIO = 1.0; // adjust time-averaging of held object's velocity. 1.0 to disable.
|
||||
var NEAR_PICK_MAX_DISTANCE = 0.6; // max length of pick-ray for close grabbing to be selected
|
||||
var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -65,10 +65,12 @@ var LIFETIME = 10;
|
|||
// states for the state machine
|
||||
var STATE_SEARCHING = 0;
|
||||
var STATE_DISTANCE_HOLDING = 1;
|
||||
var STATE_CLOSE_GRABBING = 2;
|
||||
var STATE_CONTINUE_CLOSE_GRABBING = 3;
|
||||
var STATE_RELEASE = 4;
|
||||
var STATE_CONTINUE_DISTANCE_HOLDING = 2;
|
||||
var STATE_NEAR_GRABBING = 3;
|
||||
var STATE_CONTINUE_NEAR_GRABBING = 4;
|
||||
var STATE_RELEASE = 5;
|
||||
|
||||
var GRAB_USER_DATA_KEY = "grabKey";
|
||||
|
||||
function controller(hand, triggerAction) {
|
||||
this.hand = hand;
|
||||
|
@ -86,7 +88,7 @@ function controller(hand, triggerAction) {
|
|||
this.actionID = null; // action this script created...
|
||||
this.grabbedEntity = null; // on this entity.
|
||||
this.grabbedVelocity = ZERO_VEC; // rolling average of held object's velocity
|
||||
this.state = 0; // 0 = searching, 1 = distanceHolding, 2 = closeGrabbing
|
||||
this.state = 0;
|
||||
this.pointer = null; // entity-id of line object
|
||||
this.triggerValue = 0; // rolling average of trigger value
|
||||
|
||||
|
@ -98,11 +100,14 @@ function controller(hand, triggerAction) {
|
|||
case STATE_DISTANCE_HOLDING:
|
||||
this.distanceHolding();
|
||||
break;
|
||||
case STATE_CLOSE_GRABBING:
|
||||
this.closeGrabbing();
|
||||
case STATE_CONTINUE_DISTANCE_HOLDING:
|
||||
this.continueDistanceHolding();
|
||||
break;
|
||||
case STATE_CONTINUE_CLOSE_GRABBING:
|
||||
this.continueCloseGrabbing();
|
||||
case STATE_NEAR_GRABBING:
|
||||
this.nearGrabbing();
|
||||
break;
|
||||
case STATE_CONTINUE_NEAR_GRABBING:
|
||||
this.continueNearGrabbing();
|
||||
break;
|
||||
case STATE_RELEASE:
|
||||
this.release();
|
||||
|
@ -175,9 +180,9 @@ function controller(hand, triggerAction) {
|
|||
var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
var intersectionDistance = Vec3.distance(handControllerPosition, intersection.intersection);
|
||||
this.grabbedEntity = intersection.entityID;
|
||||
if (intersectionDistance < CLOSE_PICK_MAX_DISTANCE) {
|
||||
if (intersectionDistance < NEAR_PICK_MAX_DISTANCE) {
|
||||
// the hand is very close to the intersected object. go into close-grabbing mode.
|
||||
this.state = STATE_CLOSE_GRABBING;
|
||||
this.state = STATE_NEAR_GRABBING;
|
||||
} else {
|
||||
// the hand is far from the intersected object. go into distance-holding mode
|
||||
this.state = STATE_DISTANCE_HOLDING;
|
||||
|
@ -201,13 +206,49 @@ function controller(hand, triggerAction) {
|
|||
if (this.grabbedEntity === null) {
|
||||
this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
|
||||
} else {
|
||||
this.state = STATE_CLOSE_GRABBING;
|
||||
this.state = STATE_NEAR_GRABBING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.distanceHolding = function() {
|
||||
var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm));
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position","rotation"]);
|
||||
|
||||
// add the action and initialize some variables
|
||||
this.currentObjectPosition = grabbedProperties.position;
|
||||
this.currentObjectRotation = grabbedProperties.rotation;
|
||||
this.currentObjectTime = Date.now();
|
||||
this.handPreviousPosition = handControllerPosition;
|
||||
this.handPreviousRotation = handRotation;
|
||||
|
||||
this.actionID = Entities.addAction("spring", this.grabbedEntity, {
|
||||
targetPosition: this.currentObjectPosition,
|
||||
linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
||||
targetRotation: this.currentObjectRotation,
|
||||
angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME
|
||||
});
|
||||
if (this.actionID == NULL_ACTION_ID) {
|
||||
this.actionID = null;
|
||||
}
|
||||
|
||||
if (this.actionID != null) {
|
||||
this.state = STATE_CONTINUE_DISTANCE_HOLDING;
|
||||
this.activateEntity(this.grabbedEntity);
|
||||
Entities.callEntityMethod(this.grabbedEntity, "startDistantGrab");
|
||||
|
||||
if (this.hand === RIGHT_HAND) {
|
||||
Entities.callEntityMethod(this.grabbedEntity, "setRightHand");
|
||||
} else {
|
||||
Entities.callEntityMethod(this.grabbedEntity, "setLeftHand");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.continueDistanceHolding = function() {
|
||||
if (!this.triggerSmoothedSqueezed()) {
|
||||
this.state = STATE_RELEASE;
|
||||
return;
|
||||
|
@ -216,53 +257,45 @@ function controller(hand, triggerAction) {
|
|||
var handPosition = this.getHandPosition();
|
||||
var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm));
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity);
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation"]);
|
||||
|
||||
this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR);
|
||||
|
||||
if (this.actionID === null) {
|
||||
// first time here since trigger pulled -- add the action and initialize some variables
|
||||
this.currentObjectPosition = grabbedProperties.position;
|
||||
this.currentObjectRotation = grabbedProperties.rotation;
|
||||
this.handPreviousPosition = handControllerPosition;
|
||||
this.handPreviousRotation = handRotation;
|
||||
// the action was set up on a previous call. update the targets.
|
||||
var radius = Math.max(Vec3.distance(this.currentObjectPosition,
|
||||
handControllerPosition) * DISTANCE_HOLDING_RADIUS_FACTOR,
|
||||
DISTANCE_HOLDING_RADIUS_FACTOR);
|
||||
|
||||
this.actionID = Entities.addAction("spring", this.grabbedEntity, {
|
||||
targetPosition: this.currentObjectPosition,
|
||||
linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
||||
targetRotation: this.currentObjectRotation,
|
||||
angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME
|
||||
});
|
||||
if (this.actionID == NULL_ACTION_ID) {
|
||||
this.actionID = null;
|
||||
}
|
||||
} else {
|
||||
// the action was set up on a previous call. update the targets.
|
||||
var radius = Math.max(Vec3.distance(this.currentObjectPosition,
|
||||
handControllerPosition) * DISTANCE_HOLDING_RADIUS_FACTOR,
|
||||
DISTANCE_HOLDING_RADIUS_FACTOR);
|
||||
var handMoved = Vec3.subtract(handControllerPosition, this.handPreviousPosition);
|
||||
this.handPreviousPosition = handControllerPosition;
|
||||
var superHandMoved = Vec3.multiply(handMoved, radius);
|
||||
|
||||
var handMoved = Vec3.subtract(handControllerPosition, this.handPreviousPosition);
|
||||
this.handPreviousPosition = handControllerPosition;
|
||||
var superHandMoved = Vec3.multiply(handMoved, radius);
|
||||
this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, superHandMoved);
|
||||
var newObjectPosition = Vec3.sum(this.currentObjectPosition, superHandMoved);
|
||||
var deltaPosition = Vec3.subtract(newObjectPosition, this.currentObjectPosition); // meters
|
||||
var now = Date.now();
|
||||
var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds
|
||||
this.computeReleaseVelocity(deltaPosition, deltaTime, false);
|
||||
|
||||
// this doubles hand rotation
|
||||
var handChange = Quat.multiply(Quat.slerp(this.handPreviousRotation, handRotation,
|
||||
DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR),
|
||||
Quat.inverse(this.handPreviousRotation));
|
||||
this.handPreviousRotation = handRotation;
|
||||
this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation);
|
||||
this.currentObjectPosition = newObjectPosition;
|
||||
this.currentObjectTime = now;
|
||||
|
||||
Entities.updateAction(this.grabbedEntity, this.actionID, {
|
||||
targetPosition: this.currentObjectPosition, linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
||||
targetRotation: this.currentObjectRotation, angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME
|
||||
});
|
||||
}
|
||||
// this doubles hand rotation
|
||||
var handChange = Quat.multiply(Quat.slerp(this.handPreviousRotation, handRotation,
|
||||
DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR),
|
||||
Quat.inverse(this.handPreviousRotation));
|
||||
this.handPreviousRotation = handRotation;
|
||||
this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation);
|
||||
|
||||
Entities.callEntityMethod(this.grabbedEntity, "continueDistantGrab");
|
||||
|
||||
Entities.updateAction(this.grabbedEntity, this.actionID, {
|
||||
targetPosition: this.currentObjectPosition, linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
||||
targetRotation: this.currentObjectRotation, angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.closeGrabbing = function() {
|
||||
this.nearGrabbing = function() {
|
||||
if (!this.triggerSmoothedSqueezed()) {
|
||||
this.state = STATE_RELEASE;
|
||||
return;
|
||||
|
@ -270,7 +303,9 @@ function controller(hand, triggerAction) {
|
|||
|
||||
this.lineOff();
|
||||
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity);
|
||||
this.activateEntity(this.grabbedEntity);
|
||||
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, "position");
|
||||
|
||||
var handRotation = this.getHandRotation();
|
||||
var handPosition = this.getHandPosition();
|
||||
|
@ -278,52 +313,69 @@ function controller(hand, triggerAction) {
|
|||
var objectRotation = grabbedProperties.rotation;
|
||||
var offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
|
||||
|
||||
this.currentObjectPosition = grabbedProperties.position;
|
||||
this.currentObjectTime = Date.now();
|
||||
var offset = Vec3.subtract(this.currentObjectPosition, handPosition);
|
||||
currentObjectPosition = grabbedProperties.position;
|
||||
var offset = Vec3.subtract(currentObjectPosition, handPosition);
|
||||
var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset);
|
||||
|
||||
this.actionID = Entities.addAction("hold", this.grabbedEntity, {
|
||||
hand: this.hand == RIGHT_HAND ? "right" : "left",
|
||||
timeScale: CLOSE_GRABBING_ACTION_TIMEFRAME,
|
||||
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
||||
relativePosition: offsetPosition,
|
||||
relativeRotation: offsetRotation
|
||||
});
|
||||
if (this.actionID == NULL_ACTION_ID) {
|
||||
this.actionID = null;
|
||||
} else {
|
||||
this.state = STATE_CONTINUE_CLOSE_GRABBING;
|
||||
this.state = STATE_CONTINUE_NEAR_GRABBING;
|
||||
Entities.callEntityMethod(this.grabbedEntity, "startNearGrab");
|
||||
if (this.hand === RIGHT_HAND) {
|
||||
Entities.callEntityMethod(this.grabbedEntity, "setRightHand");
|
||||
} else {
|
||||
Entities.callEntityMethod(this.grabbedEntity, "setLeftHand");
|
||||
}
|
||||
}
|
||||
|
||||
this.currentHandControllerPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
this.currentObjectTime = Date.now();
|
||||
}
|
||||
|
||||
|
||||
this.continueCloseGrabbing = function() {
|
||||
this.continueNearGrabbing = function() {
|
||||
if (!this.triggerSmoothedSqueezed()) {
|
||||
this.state = STATE_RELEASE;
|
||||
return;
|
||||
}
|
||||
|
||||
// keep track of the measured velocity of the held object
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity);
|
||||
var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
var now = Date.now();
|
||||
|
||||
var deltaPosition = Vec3.subtract(grabbedProperties.position, this.currentObjectPosition); // meters
|
||||
var deltaPosition = Vec3.subtract(handControllerPosition, this.currentHandControllerPosition); // meters
|
||||
var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds
|
||||
this.computeReleaseVelocity(deltaPosition, deltaTime, true);
|
||||
|
||||
if (deltaTime > 0.0) {
|
||||
this.currentHandControllerPosition = handControllerPosition;
|
||||
this.currentObjectTime = now;
|
||||
Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab");
|
||||
}
|
||||
|
||||
|
||||
this.computeReleaseVelocity = function(deltaPosition, deltaTime, useMultiplier) {
|
||||
if (deltaTime > 0.0 && !vec3equal(deltaPosition, ZERO_VEC)) {
|
||||
var grabbedVelocity = Vec3.multiply(deltaPosition, 1.0 / deltaTime);
|
||||
// don't update grabbedVelocity if the trigger is off. the smoothing of the trigger
|
||||
// value would otherwise give the held object time to slow down.
|
||||
if (this.triggerSqueezed()) {
|
||||
this.grabbedVelocity =
|
||||
Vec3.sum(Vec3.multiply(this.grabbedVelocity,
|
||||
(1.0 - CLOSE_GRABBING_VELOCITY_SMOOTH_RATIO)),
|
||||
Vec3.multiply(grabbedVelocity, CLOSE_GRABBING_VELOCITY_SMOOTH_RATIO));
|
||||
(1.0 - NEAR_GRABBING_VELOCITY_SMOOTH_RATIO)),
|
||||
Vec3.multiply(grabbedVelocity, NEAR_GRABBING_VELOCITY_SMOOTH_RATIO));
|
||||
}
|
||||
|
||||
if (useMultiplier) {
|
||||
this.grabbedVelocity = Vec3.multiply(this.grabbedVelocity, RELEASE_VELOCITY_MULTIPLIER);
|
||||
}
|
||||
}
|
||||
|
||||
this.currentObjectPosition = grabbedProperties.position;
|
||||
this.currentObjectTime = now;
|
||||
}
|
||||
|
||||
|
||||
|
@ -332,11 +384,13 @@ function controller(hand, triggerAction) {
|
|||
|
||||
if (this.grabbedEntity != null && this.actionID != null) {
|
||||
Entities.deleteAction(this.grabbedEntity, this.actionID);
|
||||
Entities.callEntityMethod(this.grabbedEntity, "releaseGrab");
|
||||
}
|
||||
|
||||
// the action will tend to quickly bring an object's velocity to zero. now that
|
||||
// the action is gone, set the objects velocity to something the holder might expect.
|
||||
Entities.editEntity(this.grabbedEntity, {velocity: this.grabbedVelocity});
|
||||
this.deactivateEntity(this.grabbedEntity);
|
||||
|
||||
this.grabbedVelocity = ZERO_VEC;
|
||||
this.grabbedEntity = null;
|
||||
|
@ -348,6 +402,22 @@ function controller(hand, triggerAction) {
|
|||
this.cleanup = function() {
|
||||
release();
|
||||
}
|
||||
|
||||
this.activateEntity = function(entity) {
|
||||
var data = {
|
||||
activated: true,
|
||||
avatarId: MyAvatar.sessionUUID
|
||||
};
|
||||
setEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, data);
|
||||
}
|
||||
|
||||
this.deactivateEntity = function(entity) {
|
||||
var data = {
|
||||
activated: false,
|
||||
avatarId: null
|
||||
};
|
||||
setEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ var PARTICLE_MAX_SIZE = 2.50;
|
|||
var LIFETIME = 600;
|
||||
var boxes = [];
|
||||
|
||||
var ids = Entities.findEntities({ x: 512, y: 512, z: 512 }, 50);
|
||||
var ids = Entities.findEntities(MyAvatar.position, 50);
|
||||
for (var i = 0; i < ids.length; i++) {
|
||||
var id = ids[i];
|
||||
var properties = Entities.getEntityProperties(id);
|
||||
|
@ -33,10 +33,10 @@ for (var x = 0; x < SIDE_SIZE; x++) {
|
|||
var gray = Math.random() * 155;
|
||||
var cube = Math.random() > 0.5;
|
||||
var color = { red: 100 + gray, green: 100 + gray, blue: 100 + gray };
|
||||
var position = { x: 512 + x * 0.2, y: 512 + y * 0.2, z: 512 + z * 0.2};
|
||||
var position = Vec3.sum(MyAvatar.position, { x: x * 0.2, y: y * 0.2, z: z * 0.2});
|
||||
var radius = Math.random() * 0.1;
|
||||
boxes.push(Entities.addEntity({
|
||||
type: cube ? "Box" : "Sphere",
|
||||
type: cube ? "Box" : "Box",
|
||||
name: "PerfTest",
|
||||
position: position,
|
||||
dimensions: { x: radius, y: radius, z: radius },
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
//
|
||||
|
||||
(function() {
|
||||
Script.include("../libraries/utils.js");
|
||||
|
||||
var _this;
|
||||
|
||||
|
@ -24,39 +23,29 @@
|
|||
|
||||
DetectGrabbed.prototype = {
|
||||
|
||||
// update() will be called regulary, because we've hooked the update signal in our preload() function
|
||||
// we will check out userData for the grabData. In the case of the hydraGrab script, it will tell us
|
||||
// if we're currently being grabbed and if the person grabbing us is the current interfaces avatar.
|
||||
// we will watch this for state changes and print out if we're being grabbed or released when it changes.
|
||||
update: function() {
|
||||
var GRAB_USER_DATA_KEY = "grabKey";
|
||||
setRightHand: function () {
|
||||
print("I am being held in a right hand... entity:" + this.entityID);
|
||||
},
|
||||
setLeftHand: function () {
|
||||
print("I am being held in a left hand... entity:" + this.entityID);
|
||||
},
|
||||
|
||||
// because the update() signal doesn't have a valid this, we need to use our memorized _this to access our entityID
|
||||
var entityID = _this.entityID;
|
||||
startDistantGrab: function () {
|
||||
print("I am being distance held... entity:" + this.entityID);
|
||||
},
|
||||
continueDistantGrab: function () {
|
||||
print("I continue to be distance held... entity:" + this.entityID);
|
||||
},
|
||||
|
||||
// we want to assume that if there is no grab data, then we are not being grabbed
|
||||
var defaultGrabData = { activated: false, avatarId: null };
|
||||
startNearGrab: function () {
|
||||
print("I was just grabbed... entity:" + this.entityID);
|
||||
},
|
||||
continueNearGrab: function () {
|
||||
print("I am still being grabbed... entity:" + this.entityID);
|
||||
},
|
||||
|
||||
// this handy function getEntityCustomData() is available in utils.js and it will return just the specific section
|
||||
// of user data we asked for. If it's not available it returns our default data.
|
||||
var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, defaultGrabData);
|
||||
|
||||
// if the grabData says we're being grabbed, and the owner ID is our session, then we are being grabbed by this interface
|
||||
if (grabData.activated && grabData.avatarId == MyAvatar.sessionUUID) {
|
||||
|
||||
// remember we're being grabbed so we can detect being released
|
||||
_this.beingGrabbed = true;
|
||||
|
||||
// print out that we're being grabbed
|
||||
print("I'm being grabbed...");
|
||||
|
||||
} else if (_this.beingGrabbed) {
|
||||
|
||||
// if we are not being grabbed, and we previously were, then we were just released, remember that
|
||||
// and print out a message
|
||||
_this.beingGrabbed = false;
|
||||
print("I'm was released...");
|
||||
}
|
||||
releaseGrab: function () {
|
||||
print("I was released... entity:" + this.entityID);
|
||||
},
|
||||
|
||||
// preload() will be called when the entity has become visible (or known) to the interface
|
||||
|
@ -65,14 +54,6 @@
|
|||
// * connecting to the update signal so we can check our grabbed state
|
||||
preload: function(entityID) {
|
||||
this.entityID = entityID;
|
||||
Script.update.connect(this.update);
|
||||
},
|
||||
|
||||
// unload() will be called when our entity is no longer available. It may be because we were deleted,
|
||||
// or because we've left the domain or quit the application. In all cases we want to unhook our connection
|
||||
// to the update signal
|
||||
unload: function(entityID) {
|
||||
Script.update.disconnect(this.update);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -6,11 +6,14 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
vec3toStr = function (v, digits) {
|
||||
vec3toStr = function(v, digits) {
|
||||
if (!digits) { digits = 3; }
|
||||
return "{ " + v.x.toFixed(digits) + ", " + v.y.toFixed(digits) + ", " + v.z.toFixed(digits)+ " }";
|
||||
}
|
||||
|
||||
vec3equal = function(v0, v1) {
|
||||
return (v0.x == v1.x) && (v0.y == v1.y) && (v0.z == v1.z);
|
||||
}
|
||||
|
||||
colorMix = function(colorA, colorB, mix) {
|
||||
var result = {};
|
||||
|
@ -60,7 +63,7 @@ setEntityUserData = function(id, data) {
|
|||
// FIXME do non-destructive modification of the existing user data
|
||||
getEntityUserData = function(id) {
|
||||
var results = null;
|
||||
var properties = Entities.getEntityProperties(id);
|
||||
var properties = Entities.getEntityProperties(id, "userData");
|
||||
if (properties.userData) {
|
||||
try {
|
||||
results = JSON.parse(properties.userData);
|
||||
|
@ -175,4 +178,4 @@ pointInExtents = function(point, minPoint, maxPoint) {
|
|||
return (point.x >= minPoint.x && point.x <= maxPoint.x) &&
|
||||
(point.y >= minPoint.y && point.y <= maxPoint.y) &&
|
||||
(point.z >= minPoint.z && point.z <= maxPoint.z);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1063,7 +1063,7 @@ void Application::paintGL() {
|
|||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
|
||||
|
||||
RenderArgs renderArgs(_gpuContext, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(),
|
||||
RenderArgs renderArgs(_gpuContext, getEntities(), getViewFrustum(), lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||
|
||||
|
@ -3562,7 +3562,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
(RenderArgs::DebugFlags) (renderDebugFlags | (int)RenderArgs::RENDER_DEBUG_SIMULATION_OWNERSHIP);
|
||||
}
|
||||
renderArgs->_debugFlags = renderDebugFlags;
|
||||
_entities.render(renderArgs);
|
||||
//ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, pendingChanges);
|
||||
}
|
||||
}
|
||||
|
@ -3648,14 +3647,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
sceneInterface->setEngineDrawnOverlay3DItems(engineRC->_numDrawnOverlay3DItems);
|
||||
}
|
||||
|
||||
if (!selfAvatarOnly) {
|
||||
// give external parties a change to hook in
|
||||
{
|
||||
PerformanceTimer perfTimer("inWorldInterface");
|
||||
emit renderingInWorldInterface();
|
||||
}
|
||||
}
|
||||
|
||||
activeRenderingThread = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -347,9 +347,6 @@ signals:
|
|||
/// Fired when we're simulating; allows external parties to hook in.
|
||||
void simulating(float deltaTime);
|
||||
|
||||
/// Fired when we're rendering in-world interface elements; allows external parties to hook in.
|
||||
void renderingInWorldInterface();
|
||||
|
||||
/// Fired when the import window is closed
|
||||
void importDone();
|
||||
|
||||
|
|
|
@ -22,8 +22,10 @@ GlobalServicesScriptingInterface::GlobalServicesScriptingInterface() {
|
|||
connect(&accountManager, &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut);
|
||||
|
||||
_downloading = false;
|
||||
connect(Application::getInstance(), &Application::renderingInWorldInterface,
|
||||
this, &GlobalServicesScriptingInterface::checkDownloadInfo);
|
||||
QTimer* checkDownloadTimer = new QTimer(this);
|
||||
connect(checkDownloadTimer, &QTimer::timeout, this, &GlobalServicesScriptingInterface::checkDownloadInfo);
|
||||
const int CHECK_DOWNLOAD_INTERVAL = MSECS_PER_SECOND / 2;
|
||||
checkDownloadTimer->start(CHECK_DOWNLOAD_INTERVAL);
|
||||
|
||||
auto discoverabilityManager = DependencyManager::get<DiscoverabilityManager>();
|
||||
connect(discoverabilityManager.data(), &DiscoverabilityManager::discoverabilityModeChanged,
|
||||
|
|
|
@ -153,6 +153,11 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar
|
|||
++constraintItr;
|
||||
}
|
||||
} else {
|
||||
// clear the accumulators before we start the IK solver
|
||||
for (auto& accumulatorPair: _accumulators) {
|
||||
accumulatorPair.second.clear();
|
||||
}
|
||||
|
||||
// compute absolute poses that correspond to relative target poses
|
||||
AnimPoseVec absolutePoses;
|
||||
computeAbsolutePoses(absolutePoses);
|
||||
|
@ -165,8 +170,8 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar
|
|||
quint64 expiry = usecTimestampNow() + MAX_IK_TIME;
|
||||
do {
|
||||
largestError = 0.0f;
|
||||
int lowestMovedIndex = _relativePoses.size();
|
||||
for (auto& target: targets) {
|
||||
int lowestMovedIndex = _relativePoses.size() - 1;
|
||||
int tipIndex = target.index;
|
||||
AnimPose targetPose = target.pose;
|
||||
int rootIndex = target.rootIndex;
|
||||
|
@ -226,7 +231,8 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar
|
|||
glm::inverse(absolutePoses[pivotIndex].rot);
|
||||
}
|
||||
}
|
||||
_relativePoses[pivotIndex].rot = newRot;
|
||||
// store the rotation change in the accumulator
|
||||
_accumulators[pivotIndex].add(newRot);
|
||||
}
|
||||
// this joint has been changed so we check to see if it has the lowest index
|
||||
if (pivotIndex < lowestMovedIndex) {
|
||||
|
@ -243,36 +249,47 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar
|
|||
if (largestError < error) {
|
||||
largestError = error;
|
||||
}
|
||||
|
||||
if (lowestMovedIndex <= _maxTargetIndex && lowestMovedIndex < tipIndex) {
|
||||
// only update the absolutePoses that matter: those between lowestMovedIndex and _maxTargetIndex
|
||||
for (int i = lowestMovedIndex; i <= _maxTargetIndex; ++i) {
|
||||
int parentIndex = _skeleton->getParentIndex(i);
|
||||
if (parentIndex != -1) {
|
||||
absolutePoses[i] = absolutePoses[parentIndex] * _relativePoses[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// finally set the relative rotation of the tip to agree with absolute target rotation
|
||||
int parentIndex = _skeleton->getParentIndex(tipIndex);
|
||||
if (parentIndex != -1) {
|
||||
// compute tip's new parent-relative rotation
|
||||
// Q = Qp * q --> q' = Qp^ * Q
|
||||
glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot) * targetPose.rot;
|
||||
RotationConstraint* constraint = getConstraint(tipIndex);
|
||||
if (constraint) {
|
||||
constraint->apply(newRelativeRotation);
|
||||
// TODO: ATM the final rotation target just fails but we need to provide
|
||||
// feedback to the IK system so that it can adjust the bones up the skeleton
|
||||
// to help this rotation target get met.
|
||||
}
|
||||
_relativePoses[tipIndex].rot = newRelativeRotation;
|
||||
absolutePoses[tipIndex].rot = targetPose.rot;
|
||||
}
|
||||
}
|
||||
++numLoops;
|
||||
|
||||
// harvest accumulated rotations and apply the average
|
||||
for (auto& accumulatorPair: _accumulators) {
|
||||
RotationAccumulator& accumulator = accumulatorPair.second;
|
||||
if (accumulator.size() > 0) {
|
||||
_relativePoses[accumulatorPair.first].rot = accumulator.getAverage();
|
||||
accumulator.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// only update the absolutePoses that need it: those between lowestMovedIndex and _maxTargetIndex
|
||||
for (int i = lowestMovedIndex; i <= _maxTargetIndex; ++i) {
|
||||
int parentIndex = _skeleton->getParentIndex(i);
|
||||
if (parentIndex != -1) {
|
||||
absolutePoses[i] = absolutePoses[parentIndex] * _relativePoses[i];
|
||||
}
|
||||
}
|
||||
} while (largestError > ACCEPTABLE_RELATIVE_ERROR && numLoops < MAX_IK_LOOPS && usecTimestampNow() < expiry);
|
||||
|
||||
// finally set the relative rotation of each tip to agree with absolute target rotation
|
||||
for (auto& target: targets) {
|
||||
int tipIndex = target.index;
|
||||
int parentIndex = _skeleton->getParentIndex(tipIndex);
|
||||
if (parentIndex != -1) {
|
||||
AnimPose targetPose = target.pose;
|
||||
// compute tip's new parent-relative rotation
|
||||
// Q = Qp * q --> q' = Qp^ * Q
|
||||
glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot) * targetPose.rot;
|
||||
RotationConstraint* constraint = getConstraint(tipIndex);
|
||||
if (constraint) {
|
||||
constraint->apply(newRelativeRotation);
|
||||
// TODO: ATM the final rotation target just fails but we need to provide
|
||||
// feedback to the IK system so that it can adjust the bones up the skeleton
|
||||
// to help this rotation target get met.
|
||||
}
|
||||
_relativePoses[tipIndex].rot = newRelativeRotation;
|
||||
absolutePoses[tipIndex].rot = targetPose.rot;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _relativePoses;
|
||||
}
|
||||
|
@ -628,6 +645,7 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele
|
|||
|
||||
_maxTargetIndex = 0;
|
||||
|
||||
_accumulators.clear();
|
||||
if (skeleton) {
|
||||
initConstraints();
|
||||
} else {
|
||||
|
|
|
@ -12,8 +12,13 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "AnimNode.h"
|
||||
|
||||
#include "RotationAccumulator.h"
|
||||
|
||||
class RotationConstraint;
|
||||
|
||||
class AnimInverseKinematics : public AnimNode {
|
||||
|
@ -24,7 +29,6 @@ public:
|
|||
|
||||
void loadDefaultPoses(const AnimPoseVec& poses);
|
||||
void loadPoses(const AnimPoseVec& poses);
|
||||
const AnimPoseVec& getRelativePoses() const { return _relativePoses; }
|
||||
void computeAbsolutePoses(AnimPoseVec& absolutePoses) const;
|
||||
|
||||
void setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar);
|
||||
|
@ -60,6 +64,7 @@ protected:
|
|||
};
|
||||
|
||||
std::map<int, RotationConstraint*> _constraints;
|
||||
std::map<int, RotationAccumulator> _accumulators;
|
||||
std::vector<IKTargetVar> _targetVarVec;
|
||||
AnimPoseVec _defaultRelativePoses; // poses of the relaxed state
|
||||
AnimPoseVec _relativePoses; // current relative poses
|
||||
|
|
27
libraries/animation/src/RotationAccumulator.cpp
Normal file
27
libraries/animation/src/RotationAccumulator.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// RotationAccumulator.h
|
||||
//
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "RotationAccumulator.h"
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
void RotationAccumulator::add(glm::quat rotation) {
|
||||
// make sure both quaternions are on the same hyper-hemisphere before we add them linearly (lerp)
|
||||
_rotationSum += copysignf(1.0f, glm::dot(_rotationSum, rotation)) * rotation;
|
||||
++_numRotations;
|
||||
}
|
||||
|
||||
glm::quat RotationAccumulator::getAverage() {
|
||||
return (_numRotations > 0) ? glm::normalize(_rotationSum) : glm::quat();
|
||||
}
|
||||
|
||||
void RotationAccumulator::clear() {
|
||||
_rotationSum *= 0.0f;
|
||||
_numRotations = 0;
|
||||
}
|
32
libraries/animation/src/RotationAccumulator.h
Normal file
32
libraries/animation/src/RotationAccumulator.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// RotationAccumulator.h
|
||||
//
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_RotationAccumulator_h
|
||||
#define hifi_RotationAccumulator_h
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
class RotationAccumulator {
|
||||
public:
|
||||
RotationAccumulator() : _rotationSum(0.0f, 0.0f, 0.0f, 0.0f), _numRotations(0) { }
|
||||
|
||||
int size() const { return _numRotations; }
|
||||
|
||||
void add(glm::quat rotation);
|
||||
|
||||
glm::quat getAverage();
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
glm::quat _rotationSum;
|
||||
int _numRotations;
|
||||
};
|
||||
|
||||
#endif // hifi_RotationAccumulator_h
|
|
@ -52,9 +52,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
|||
_lastMouseEventValid(false),
|
||||
_viewState(viewState),
|
||||
_scriptingServices(scriptingServices),
|
||||
_displayElementChildProxies(false),
|
||||
_displayModelBounds(false),
|
||||
_displayModelElementProxy(false),
|
||||
_dontDoPrecisionPicking(false)
|
||||
{
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Model, RenderableModelEntityItem::factory)
|
||||
|
@ -112,6 +110,7 @@ void EntityTreeRenderer::init() {
|
|||
_scriptingServices->getControllerScriptingInterface());
|
||||
_scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine);
|
||||
_entitiesScriptEngine->runInThread();
|
||||
DependencyManager::get<EntityScriptingInterface>()->setEntitiesScriptEngine(_entitiesScriptEngine);
|
||||
}
|
||||
|
||||
// make sure our "last avatar position" is something other than our current position, so that on our
|
||||
|
@ -151,6 +150,7 @@ void EntityTreeRenderer::update() {
|
|||
}
|
||||
|
||||
}
|
||||
deleteReleasedModels();
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::checkEnterLeaveEntities() {
|
||||
|
@ -167,12 +167,41 @@ void EntityTreeRenderer::checkEnterLeaveEntities() {
|
|||
_tree->withReadLock([&] {
|
||||
std::static_pointer_cast<EntityTree>(_tree)->findEntities(avatarPosition, radius, foundEntities);
|
||||
|
||||
// Whenever you're in an intersection between zones, we will always choose the smallest zone.
|
||||
_bestZone = NULL; // NOTE: Is this what we want?
|
||||
_bestZoneVolume = std::numeric_limits<float>::max();
|
||||
|
||||
// create a list of entities that actually contain the avatar's position
|
||||
foreach(EntityItemPointer entity, foundEntities) {
|
||||
if (entity->contains(avatarPosition)) {
|
||||
entitiesContainingAvatar << entity->getEntityItemID();
|
||||
|
||||
// if this entity is a zone, use this time to determine the bestZone
|
||||
if (entity->getType() == EntityTypes::Zone) {
|
||||
float entityVolumeEstimate = entity->getVolumeEstimate();
|
||||
if (entityVolumeEstimate < _bestZoneVolume) {
|
||||
_bestZoneVolume = entityVolumeEstimate;
|
||||
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entity);
|
||||
} else if (entityVolumeEstimate == _bestZoneVolume) {
|
||||
if (!_bestZone) {
|
||||
_bestZoneVolume = entityVolumeEstimate;
|
||||
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entity);
|
||||
} else {
|
||||
// in the case of the volume being equal, we will use the
|
||||
// EntityItemID to deterministically pick one entity over the other
|
||||
if (entity->getEntityItemID() < _bestZone->getEntityItemID()) {
|
||||
_bestZoneVolume = entityVolumeEstimate;
|
||||
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
applyZonePropertiesToScene(_bestZone);
|
||||
|
||||
});
|
||||
|
||||
// Note: at this point we don't need to worry about the tree being locked, because we only deal with
|
||||
|
@ -307,27 +336,6 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
|
|||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::render(RenderArgs* renderArgs) {
|
||||
|
||||
if (_tree && !_shuttingDown) {
|
||||
renderArgs->_renderer = this;
|
||||
_tree->withReadLock([&] {
|
||||
// Whenever you're in an intersection between zones, we will always choose the smallest zone.
|
||||
_bestZone = NULL; // NOTE: Is this what we want?
|
||||
_bestZoneVolume = std::numeric_limits<float>::max();
|
||||
|
||||
// FIX ME: right now the renderOperation does the following:
|
||||
// 1) determining the best zone (not really rendering)
|
||||
// 2) render the debug cell details
|
||||
// we should clean this up
|
||||
_tree->recurseTreeWithOperation(renderOperation, renderArgs);
|
||||
|
||||
applyZonePropertiesToScene(_bestZone);
|
||||
});
|
||||
}
|
||||
deleteReleasedModels(); // seems like as good as any other place to do some memory cleanup
|
||||
}
|
||||
|
||||
const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(EntityItemPointer entityItem) {
|
||||
const FBXGeometry* result = NULL;
|
||||
|
||||
|
@ -372,121 +380,6 @@ const FBXGeometry* EntityTreeRenderer::getCollisionGeometryForEntity(EntityItemP
|
|||
return result;
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::renderElementProxy(EntityTreeElementPointer entityTreeElement, RenderArgs* args) {
|
||||
auto deferredLighting = DependencyManager::get<DeferredLightingEffect>();
|
||||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
Transform transform;
|
||||
|
||||
glm::vec3 elementCenter = entityTreeElement->getAACube().calcCenter();
|
||||
float elementSize = entityTreeElement->getScale();
|
||||
|
||||
auto drawWireCube = [&](glm::vec3 offset, float size, glm::vec4 color) {
|
||||
transform.setTranslation(elementCenter + offset);
|
||||
batch.setModelTransform(transform);
|
||||
deferredLighting->renderWireCube(batch, size, color);
|
||||
};
|
||||
|
||||
drawWireCube(glm::vec3(), elementSize, glm::vec4(1.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
if (_displayElementChildProxies) {
|
||||
// draw the children
|
||||
float halfSize = elementSize / 2.0f;
|
||||
float quarterSize = elementSize / 4.0f;
|
||||
|
||||
drawWireCube(glm::vec3(-quarterSize, -quarterSize, -quarterSize), halfSize, glm::vec4(1.0f, 1.0f, 0.0f, 1.0f));
|
||||
drawWireCube(glm::vec3(quarterSize, -quarterSize, -quarterSize), halfSize, glm::vec4(1.0f, 0.0f, 1.0f, 1.0f));
|
||||
drawWireCube(glm::vec3(-quarterSize, quarterSize, -quarterSize), halfSize, glm::vec4(0.0f, 1.0f, 0.0f, 1.0f));
|
||||
drawWireCube(glm::vec3(-quarterSize, -quarterSize, quarterSize), halfSize, glm::vec4(0.0f, 0.0f, 1.0f, 1.0f));
|
||||
drawWireCube(glm::vec3(quarterSize, quarterSize, quarterSize), halfSize, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
drawWireCube(glm::vec3(-quarterSize, quarterSize, quarterSize), halfSize, glm::vec4(0.0f, 0.5f, 0.5f, 1.0f));
|
||||
drawWireCube(glm::vec3(quarterSize, -quarterSize, quarterSize), halfSize, glm::vec4(0.5f, 0.0f, 0.0f, 1.0f));
|
||||
drawWireCube(glm::vec3(quarterSize, quarterSize, -quarterSize), halfSize, glm::vec4(0.0f, 0.5f, 0.0f, 1.0f));
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::renderProxies(EntityItemPointer entity, RenderArgs* args) {
|
||||
bool isShadowMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE;
|
||||
if (!isShadowMode && _displayModelBounds) {
|
||||
PerformanceTimer perfTimer("renderProxies");
|
||||
|
||||
AACube maxCube = entity->getMaximumAACube();
|
||||
AACube minCube = entity->getMinimumAACube();
|
||||
AABox entityBox = entity->getAABox();
|
||||
|
||||
glm::vec3 maxCenter = maxCube.calcCenter();
|
||||
glm::vec3 minCenter = minCube.calcCenter();
|
||||
glm::vec3 entityBoxCenter = entityBox.calcCenter();
|
||||
glm::vec3 entityBoxScale = entityBox.getScale();
|
||||
|
||||
auto deferredLighting = DependencyManager::get<DeferredLightingEffect>();
|
||||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
Transform transform;
|
||||
|
||||
// draw the max bounding cube
|
||||
transform.setTranslation(maxCenter);
|
||||
batch.setModelTransform(transform);
|
||||
deferredLighting->renderWireCube(batch, maxCube.getScale(), glm::vec4(1.0f, 1.0f, 0.0f, 1.0f));
|
||||
|
||||
// draw the min bounding cube
|
||||
transform.setTranslation(minCenter);
|
||||
batch.setModelTransform(transform);
|
||||
deferredLighting->renderWireCube(batch, minCube.getScale(), glm::vec4(0.0f, 1.0f, 0.0f, 1.0f));
|
||||
|
||||
// draw the entityBox bounding box
|
||||
transform.setTranslation(entityBoxCenter);
|
||||
transform.setScale(entityBoxScale);
|
||||
batch.setModelTransform(transform);
|
||||
deferredLighting->renderWireCube(batch, 1.0f, glm::vec4(0.0f, 0.0f, 1.0f, 1.0f));
|
||||
|
||||
// Rotated bounding box
|
||||
batch.setModelTransform(entity->getTransformToCenter());
|
||||
deferredLighting->renderWireCube(batch, 1.0f, glm::vec4(1.0f, 0.0f, 1.0f, 1.0f));
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::renderElement(OctreeElementPointer element, RenderArgs* args) {
|
||||
// actually render it here...
|
||||
// we need to iterate the actual entityItems of the element
|
||||
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
|
||||
|
||||
|
||||
bool isShadowMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE;
|
||||
|
||||
if (!isShadowMode && _displayModelElementProxy && entityTreeElement->size() > 0) {
|
||||
renderElementProxy(entityTreeElement, args);
|
||||
}
|
||||
|
||||
entityTreeElement->forEachEntity([&](EntityItemPointer entityItem) {
|
||||
if (entityItem->isVisible()) {
|
||||
// NOTE: Zone Entities are a special case we handle here...
|
||||
if (entityItem->getType() == EntityTypes::Zone) {
|
||||
if (entityItem->contains(_viewState->getAvatarPosition())) {
|
||||
float entityVolumeEstimate = entityItem->getVolumeEstimate();
|
||||
if (entityVolumeEstimate < _bestZoneVolume) {
|
||||
_bestZoneVolume = entityVolumeEstimate;
|
||||
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entityItem);
|
||||
} else if (entityVolumeEstimate == _bestZoneVolume) {
|
||||
if (!_bestZone) {
|
||||
_bestZoneVolume = entityVolumeEstimate;
|
||||
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entityItem);
|
||||
} else {
|
||||
// in the case of the volume being equal, we will use the
|
||||
// EntityItemID to deterministically pick one entity over the other
|
||||
if (entityItem->getEntityItemID() < _bestZone->getEntityItemID()) {
|
||||
_bestZoneVolume = entityVolumeEstimate;
|
||||
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entityItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
float EntityTreeRenderer::getSizeScale() const {
|
||||
return _viewState->getSizeScale();
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ public:
|
|||
virtual char getMyNodeType() const { return NodeType::EntityServer; }
|
||||
virtual PacketType getMyQueryMessageType() const { return PacketType::EntityQuery; }
|
||||
virtual PacketType getExpectedPacketType() const { return PacketType::EntityData; }
|
||||
virtual void renderElement(OctreeElementPointer element, RenderArgs* args);
|
||||
virtual float getSizeScale() const;
|
||||
virtual int getBoundaryLevelAdjust() const;
|
||||
virtual void setTree(OctreePointer newTree);
|
||||
|
@ -53,7 +52,6 @@ public:
|
|||
void processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode);
|
||||
|
||||
virtual void init();
|
||||
virtual void render(RenderArgs* renderArgs) override;
|
||||
|
||||
virtual const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem);
|
||||
virtual const Model* getModelForEntityItem(EntityItemPointer entityItem);
|
||||
|
@ -114,9 +112,7 @@ public slots:
|
|||
void updateEntityRenderStatus(bool shouldRenderEntities);
|
||||
|
||||
// optional slots that can be wired to menu items
|
||||
void setDisplayElementChildProxies(bool value) { _displayElementChildProxies = value; }
|
||||
void setDisplayModelBounds(bool value) { _displayModelBounds = value; }
|
||||
void setDisplayModelElementProxy(bool value) { _displayModelElementProxy = value; }
|
||||
void setDontDoPrecisionPicking(bool value) { _dontDoPrecisionPicking = value; }
|
||||
|
||||
protected:
|
||||
|
@ -130,11 +126,9 @@ private:
|
|||
void addEntityToScene(EntityItemPointer entity);
|
||||
|
||||
void applyZonePropertiesToScene(std::shared_ptr<ZoneEntityItem> zone);
|
||||
void renderElementProxy(EntityTreeElementPointer entityTreeElement, RenderArgs* args);
|
||||
void checkAndCallPreload(const EntityItemID& entityID, const bool reload = false);
|
||||
|
||||
QList<Model*> _releasedModels;
|
||||
void renderProxies(EntityItemPointer entity, RenderArgs* args);
|
||||
RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
|
||||
bool precisionPicking);
|
||||
|
||||
|
@ -157,9 +151,7 @@ private:
|
|||
MouseEvent _lastMouseEvent;
|
||||
AbstractViewStateInterface* _viewState;
|
||||
AbstractScriptingServicesInterface* _scriptingServices;
|
||||
bool _displayElementChildProxies;
|
||||
bool _displayModelBounds;
|
||||
bool _displayModelElementProxy;
|
||||
bool _dontDoPrecisionPicking;
|
||||
|
||||
bool _shuttingDown = false;
|
||||
|
|
|
@ -39,9 +39,6 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
|
|||
PerformanceTimer perfTimer("RenderableBoxEntityItem::render");
|
||||
Q_ASSERT(getType() == EntityTypes::Box);
|
||||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
batch.setModelTransform(getTransformToCenter()); // we want to include the scale as well
|
||||
glm::vec4 cubeColor(toGlm(getXColor()), getLocalRenderAlpha());
|
||||
|
||||
if (!_procedural) {
|
||||
_procedural.reset(new Procedural(this->getUserData()));
|
||||
|
@ -54,11 +51,15 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
|
|||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
}
|
||||
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
glm::vec4 cubeColor(toGlm(getXColor()), getLocalRenderAlpha());
|
||||
|
||||
if (_procedural->ready()) {
|
||||
batch.setModelTransform(getTransformToCenter()); // we want to include the scale as well
|
||||
_procedural->prepare(batch, this->getDimensions());
|
||||
DependencyManager::get<GeometryCache>()->renderSolidCube(batch, 1.0f, _procedural->getColor(cubeColor));
|
||||
} else {
|
||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidCube(batch, 1.0f, cubeColor);
|
||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidCubeInstance(batch, getTransformToCenter(), cubeColor);
|
||||
}
|
||||
|
||||
RenderableDebugableEntityItem::render(this, args);
|
||||
|
|
|
@ -358,8 +358,8 @@ bool RenderableModelEntityItem::needsToCallUpdate() const {
|
|||
return _needsInitialSimulation || ModelEntityItem::needsToCallUpdate();
|
||||
}
|
||||
|
||||
EntityItemProperties RenderableModelEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = ModelEntityItem::getProperties(); // get the properties from our base class
|
||||
EntityItemProperties RenderableModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = ModelEntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
if (_originalTexturesRead) {
|
||||
properties.setTextureNames(_originalTextures);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
|
||||
virtual ~RenderableModelEntityItem();
|
||||
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
|
|
|
@ -32,14 +32,14 @@ AtmospherePropertyGroup::AtmospherePropertyGroup() {
|
|||
_hasStars = true;
|
||||
}
|
||||
|
||||
void AtmospherePropertyGroup::copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, Center, center);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, InnerRadius, innerRadius);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, OuterRadius, outerRadius);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, MieScattering, mieScattering);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, RayleighScattering, rayleighScattering);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, ScatteringWavelengths, scatteringWavelengths);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, HasStars, hasStars);
|
||||
void AtmospherePropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ATMOSPHERE_CENTER, Atmosphere, atmosphere, Center, center);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ATMOSPHERE_INNER_RADIUS, Atmosphere, atmosphere, InnerRadius, innerRadius);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ATMOSPHERE_OUTER_RADIUS, Atmosphere, atmosphere, OuterRadius, outerRadius);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ATMOSPHERE_MIE_SCATTERING, Atmosphere, atmosphere, MieScattering, mieScattering);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ATMOSPHERE_RAYLEIGH_SCATTERING, Atmosphere, atmosphere, RayleighScattering, rayleighScattering);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS, Atmosphere, atmosphere, ScatteringWavelengths, scatteringWavelengths);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ATMOSPHERE_HAS_STARS, Atmosphere, atmosphere, HasStars, hasStars);
|
||||
}
|
||||
|
||||
void AtmospherePropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
virtual ~AtmospherePropertyGroup() {}
|
||||
|
||||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const;
|
||||
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;
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@ BoxEntityItem::BoxEntityItem(const EntityItemID& entityItemID, const EntityItemP
|
|||
setProperties(properties);
|
||||
}
|
||||
|
||||
EntityItemProperties BoxEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
EntityItemProperties BoxEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
|
||||
properties._color = getXColor();
|
||||
properties._colorChanged = false;
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
|
|
25
libraries/entities/src/EntitiesScriptEngineProvider.h
Normal file
25
libraries/entities/src/EntitiesScriptEngineProvider.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// EntitiesScriptEngineProvider.h
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on Sept. 18, 2015
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
// TODO: How will we handle collision callbacks with Entities
|
||||
//
|
||||
|
||||
#ifndef hifi_EntitiesScriptEngineProvider_h
|
||||
#define hifi_EntitiesScriptEngineProvider_h
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include "EntityItemID.h"
|
||||
|
||||
class EntitiesScriptEngineProvider {
|
||||
public:
|
||||
virtual void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName) = 0;
|
||||
};
|
||||
|
||||
#endif // hifi_EntitiesScriptEngineProvider_h
|
|
@ -1019,8 +1019,10 @@ quint64 EntityItem::getExpiry() const {
|
|||
return _created + (quint64)(_lifetime * (float)USECS_PER_SECOND);
|
||||
}
|
||||
|
||||
EntityItemProperties EntityItem::getProperties() const {
|
||||
EntityItemProperties properties;
|
||||
EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EncodeBitstreamParams params; // unknown
|
||||
EntityPropertyFlags propertyFlags = desiredProperties.isEmpty() ? getEntityProperties(params) : desiredProperties;
|
||||
EntityItemProperties properties(propertyFlags);
|
||||
properties._id = getID();
|
||||
properties._idSet = true;
|
||||
properties._created = _created;
|
||||
|
|
|
@ -131,7 +131,7 @@ public:
|
|||
EntityItemID getEntityItemID() const { return EntityItemID(_id); }
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
|
||||
/// returns true if something changed
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
|
|
@ -36,7 +36,7 @@ StagePropertyGroup EntityItemProperties::_staticStage;
|
|||
|
||||
EntityPropertyList PROP_LAST_ITEM = (EntityPropertyList)(PROP_AFTER_LAST_ITEM - 1);
|
||||
|
||||
EntityItemProperties::EntityItemProperties() :
|
||||
EntityItemProperties::EntityItemProperties(EntityPropertyFlags desiredProperties) :
|
||||
|
||||
CONSTRUCT_PROPERTY(visible, ENTITY_ITEM_DEFAULT_VISIBLE),
|
||||
CONSTRUCT_PROPERTY(position, 0.0f),
|
||||
|
@ -140,7 +140,8 @@ _localRenderAlphaChanged(false),
|
|||
|
||||
_defaultSettings(true),
|
||||
_naturalDimensions(1.0f, 1.0f, 1.0f),
|
||||
_naturalPosition(0.0f, 0.0f, 0.0f)
|
||||
_naturalPosition(0.0f, 0.0f, 0.0f),
|
||||
_desiredProperties(desiredProperties)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -423,105 +424,159 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
EntityItemProperties defaultEntityProperties;
|
||||
|
||||
if (_idSet) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(id, _id.toString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(id, _id.toString());
|
||||
}
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(type, EntityTypes::getEntityTypeName(_type));
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(position);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(dimensions);
|
||||
if (!skipDefaults) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(naturalDimensions); // gettable, but not settable
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(naturalPosition);
|
||||
}
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(rotation);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(velocity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(gravity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(acceleration);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(damping);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(restitution);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(friction);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(density);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(lifetime);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(type, EntityTypes::getEntityTypeName(_type));
|
||||
auto created = QDateTime::fromMSecsSinceEpoch(getCreated() / 1000.0f, Qt::UTC); // usec per msec
|
||||
created.setTimeSpec(Qt::OffsetFromUTC);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(created, created.toString(Qt::ISODate));
|
||||
|
||||
if (!skipDefaults || _lifetime != defaultEntityProperties._lifetime) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(age, getAge()); // gettable, but not settable
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable
|
||||
}
|
||||
|
||||
auto created = QDateTime::fromMSecsSinceEpoch(getCreated() / 1000.0f, Qt::UTC); // usec per msec
|
||||
created.setTimeSpec(Qt::OffsetFromUTC);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(created, created.toString(Qt::ISODate));
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_POSITION, position);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DIMENSIONS, dimensions);
|
||||
if (!skipDefaults) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DIMENSIONS, naturalDimensions); // gettable, but not settable
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_POSITION, naturalPosition);
|
||||
}
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ROTATION, rotation);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VELOCITY, velocity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAVITY, gravity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ACCELERATION, acceleration);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DAMPING, damping);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RESTITUTION, restitution);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FRICTION, friction);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DENSITY, density);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LIFETIME, lifetime);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SCRIPT, script);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SCRIPT_TIMESTAMP, scriptTimestamp);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_REGISTRATION_POINT, registrationPoint);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANGULAR_VELOCITY, angularVelocity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANGULAR_DAMPING, angularDamping);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VISIBLE, visible);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IGNORE_FOR_COLLISIONS, ignoreForCollisions);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLLISIONS_WILL_MOVE, collisionsWillMove);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_HREF, href);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DESCRIPTION, description);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FACE_CAMERA, faceCamera);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ACTION_DATA, actionData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCKED, locked);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USER_DATA, userData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MARKETPLACE_ID, marketplaceID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_NAME, name);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLLISION_SOUND_URL, collisionSoundURL);
|
||||
|
||||
// Boxes, Spheres, Light, Line, Model(??), Particle, PolyLine
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR, color);
|
||||
|
||||
// Particles only
|
||||
if (_type == EntityTypes::ParticleEffect) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAX_PARTICLES, maxParticles);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LIFESPAN, lifespan);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_RATE, emitRate);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_VELOCITY, emitVelocity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VELOCITY_SPREAD, velocitySpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_ACCELERATION, emitAcceleration);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ACCELERATION_SPREAD, accelerationSpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARTICLE_RADIUS, particleRadius);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RADIUS_SPREAD, radiusSpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RADIUS_START, radiusStart);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RADIUS_FINISH, radiusFinish);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR_SPREAD, colorSpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR_START, colorStart);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR_FINISH, colorFinish);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_SPREAD, alphaSpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_START, alphaStart);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_FINISH, alphaFinish);
|
||||
}
|
||||
|
||||
// Models only
|
||||
if (_type == EntityTypes::Model) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MODEL_URL, modelURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_URL, animationURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures);
|
||||
}
|
||||
|
||||
|
||||
if (_type == EntityTypes::Model || _type == EntityTypes::Zone || _type == EntityTypes::ParticleEffect) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, getShapeTypeAsString());
|
||||
}
|
||||
|
||||
// Models & Particles
|
||||
if (_type == EntityTypes::Model || _type == EntityTypes::ParticleEffect) {
|
||||
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
|
||||
if (_type == EntityTypes::Light) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IS_SPOTLIGHT, isSpotlight);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_INTENSITY, intensity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EXPONENT, exponent);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CUTOFF, cutoff);
|
||||
}
|
||||
|
||||
// Text only
|
||||
if (_type == EntityTypes::Text) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXT, text);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_HEIGHT, lineHeight);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_TEXT_COLOR, textColor, getTextColor());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BACKGROUND_COLOR, backgroundColor, getBackgroundColor());
|
||||
}
|
||||
|
||||
// Zones only
|
||||
if (_type == EntityTypes::Zone) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_COLOR, keyLightColor);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_INTENSITY, keyLightIntensity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_AMBIENT_INTENSITY, keyLightAmbientIntensity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_DIRECTION, keyLightDirection);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BACKGROUND_MODE, backgroundMode, getBackgroundModeAsString());
|
||||
|
||||
_stage.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
|
||||
_atmosphere.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
|
||||
_skybox.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
|
||||
}
|
||||
|
||||
// Web only
|
||||
if (_type == EntityTypes::Web) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOURCE_URL, sourceUrl);
|
||||
}
|
||||
|
||||
// PolyVoxel only
|
||||
if (_type == EntityTypes::PolyVox) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VOXEL_VOLUME_SIZE, voxelVolumeSize);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VOXEL_DATA, voxelData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VOXEL_SURFACE_STYLE, voxelSurfaceStyle);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_X_TEXTURE_URL, xTextureURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Y_TEXTURE_URL, yTextureURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Z_TEXTURE_URL, zTextureURL);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_X_N_NEIGHBOR_ID, xNNeighborID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Y_N_NEIGHBOR_ID, yNNeighborID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Z_N_NEIGHBOR_ID, zNNeighborID);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_X_P_NEIGHBOR_ID, xPNeighborID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Y_P_NEIGHBOR_ID, yPNeighborID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Z_P_NEIGHBOR_ID, zPNeighborID);
|
||||
}
|
||||
|
||||
// Lines & PolyLines
|
||||
if (_type == EntityTypes::Line || _type == EntityTypes::PolyLine) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_WIDTH, lineWidth);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_POINTS, linePoints);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_NORMALS, normals);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_STROKE_WIDTHS, strokeWidths);
|
||||
}
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(script);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(scriptTimestamp);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(registrationPoint);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(angularVelocity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(angularDamping);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(visible);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(color);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(colorSpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(colorStart);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(colorFinish);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(alpha);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(alphaSpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(alphaStart);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(alphaFinish);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(modelURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(compoundShapeURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationIsPlaying);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationFPS);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationFrameIndex);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(animationSettings, getAnimationSettings());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(glowLevel);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(ignoreForCollisions);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(collisionsWillMove);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(isSpotlight);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(intensity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(exponent);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(cutoff);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(locked);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(textures);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(userData);
|
||||
//COPY_PROPERTY_TO_QSCRIPTVALUE(simulationOwner); // TODO: expose this for JSON saves?
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(text);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(textColor, getTextColor());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(backgroundColor, getBackgroundColor());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(shapeType, getShapeTypeAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(maxParticles);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(lifespan);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(emitRate);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(emitVelocity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(velocitySpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(emitAcceleration);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(accelerationSpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(radiusSpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(radiusStart);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(radiusFinish);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(name);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(collisionSoundURL);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightColor);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightIntensity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightAmbientIntensity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightDirection);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(backgroundMode, getBackgroundModeAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(sourceUrl);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(voxelVolumeSize);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(voxelData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(voxelSurfaceStyle);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(lineWidth);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(linePoints);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(href);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(description);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(faceCamera);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(actionData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(normals);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(strokeWidths);
|
||||
|
||||
// Sitting properties support
|
||||
if (!skipDefaults) {
|
||||
|
@ -534,7 +589,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
sittingPoints.setProperty(i, sittingPoint);
|
||||
}
|
||||
sittingPoints.setProperty("length", _sittingPoints.size());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(sittingPoints, sittingPoints); // gettable, but not settable
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(sittingPoints, sittingPoints); // gettable, but not settable
|
||||
}
|
||||
|
||||
if (!skipDefaults) {
|
||||
|
@ -556,21 +611,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(originalTextures, textureNamesList); // gettable, but not settable
|
||||
}
|
||||
|
||||
_stage.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties);
|
||||
_atmosphere.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties);
|
||||
_skybox.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(xTextureURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(yTextureURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(zTextureURL);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(xNNeighborID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(yNNeighborID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(zNNeighborID);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(xPNeighborID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(yPNeighborID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(zPNeighborID);
|
||||
// FIXME - I don't think these properties are supported any more
|
||||
//COPY_PROPERTY_TO_QSCRIPTVALUE(glowLevel);
|
||||
//COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
@ -709,6 +752,155 @@ void EntityItemPropertiesFromScriptValueHonorReadOnly(const QScriptValue &object
|
|||
}
|
||||
|
||||
|
||||
QScriptValue EntityPropertyFlagsToScriptValue(QScriptEngine* engine, const EntityPropertyFlags& flags) {
|
||||
return EntityItemProperties::entityPropertyFlagsToScriptValue(engine, flags);
|
||||
QScriptValue result = engine->newObject();
|
||||
return result;
|
||||
}
|
||||
|
||||
void EntityPropertyFlagsFromScriptValue(const QScriptValue& object, EntityPropertyFlags& flags) {
|
||||
EntityItemProperties::entityPropertyFlagsFromScriptValue(object, flags);
|
||||
}
|
||||
|
||||
|
||||
QScriptValue EntityItemProperties::entityPropertyFlagsToScriptValue(QScriptEngine* engine, const EntityPropertyFlags& flags) {
|
||||
QScriptValue result = engine->newObject();
|
||||
return result;
|
||||
}
|
||||
|
||||
static QHash<QString, EntityPropertyList> _propertyStringsToEnums;
|
||||
|
||||
void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue& object, EntityPropertyFlags& flags) {
|
||||
static std::once_flag initMap;
|
||||
|
||||
std::call_once(initMap, [](){
|
||||
ADD_PROPERTY_TO_MAP(PROP_VISIBLE, Visible, visible, bool);
|
||||
ADD_PROPERTY_TO_MAP(PROP_POSITION, Position, position, glm::vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ROTATION, Rotation, rotation, glm::quat);
|
||||
ADD_PROPERTY_TO_MAP(PROP_DENSITY, Density, density, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_VELOCITY, Velocity, velocity, glm::vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_GRAVITY, Gravity, gravity, glm::vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ACCELERATION, Acceleration, acceleration, glm::vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_DAMPING, Damping, damping, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_RESTITUTION, Restitution, restitution, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_FRICTION, Friction, friction, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_LIFETIME, Lifetime, lifetime, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_SCRIPT, Script, script, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COLOR, Color, color, xColor);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COLOR_START, ColorStart, colorStart, xColor);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COLOR_FINISH, ColorFinish, colorFinish, xColor);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ALPHA, Alpha, alpha, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ALPHA_START, AlphaStart, alphaStart, float);
|
||||
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);
|
||||
ADD_PROPERTY_TO_MAP(PROP_IGNORE_FOR_COLLISIONS, IgnoreForCollisions, ignoreForCollisions, bool);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COLLISIONS_WILL_MOVE, CollisionsWillMove, collisionsWillMove, bool);
|
||||
ADD_PROPERTY_TO_MAP(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool);
|
||||
ADD_PROPERTY_TO_MAP(PROP_INTENSITY, Intensity, intensity, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_EXPONENT, Exponent, exponent, float);
|
||||
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);
|
||||
ADD_PROPERTY_TO_MAP(PROP_LINE_HEIGHT, LineHeight, lineHeight, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_TEXT_COLOR, TextColor, textColor, xColor);
|
||||
ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor);
|
||||
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_EMIT_RATE, EmitRate, emitRate, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_EMIT_VELOCITY, EmitVelocity, emitVelocity, glm::vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_VELOCITY_SPREAD, VelocitySpread, velocitySpread, glm::vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ACCELERATION_SPREAD, AccelerationSpread, accelerationSpread, glm::vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_RADIUS_SPREAD, RadiusSpread, radiusSpread, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_RADIUS_START, RadiusStart, radiusStart, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor);
|
||||
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_AMBIENT_INTENSITY, KeyLightAmbientIntensity, keyLightAmbientIntensity, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLightDirection, keyLightDirection, glm::vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray);
|
||||
ADD_PROPERTY_TO_MAP(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t);
|
||||
ADD_PROPERTY_TO_MAP(PROP_NAME, Name, name, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_MODE, BackgroundMode, backgroundMode, BackgroundMode);
|
||||
ADD_PROPERTY_TO_MAP(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_LINE_WIDTH, LineWidth, lineWidth, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_LINE_POINTS, LinePoints, linePoints, QVector<glm::vec3>);
|
||||
ADD_PROPERTY_TO_MAP(PROP_HREF, Href, href, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_DESCRIPTION, Description, description, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ACTION_DATA, ActionData, actionData, QByteArray);
|
||||
ADD_PROPERTY_TO_MAP(PROP_NORMALS, Normals, normals, QVector<glm::vec3>);
|
||||
ADD_PROPERTY_TO_MAP(PROP_STROKE_WIDTHS, StrokeWidths, strokeWidths, QVector<float>);
|
||||
ADD_PROPERTY_TO_MAP(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_Z_TEXTURE_URL, ZTextureURL, zTextureURL, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_X_N_NEIGHBOR_ID, XNNeighborID, xNNeighborID, EntityItemID);
|
||||
ADD_PROPERTY_TO_MAP(PROP_Y_N_NEIGHBOR_ID, YNNeighborID, yNNeighborID, EntityItemID);
|
||||
ADD_PROPERTY_TO_MAP(PROP_Z_N_NEIGHBOR_ID, ZNNeighborID, zNNeighborID, EntityItemID);
|
||||
ADD_PROPERTY_TO_MAP(PROP_X_P_NEIGHBOR_ID, XPNeighborID, xPNeighborID, EntityItemID);
|
||||
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_ATMOSPHERE_CENTER, Atmosphere, atmosphere, Center, center);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ATMOSPHERE_INNER_RADIUS, Atmosphere, atmosphere, InnerRadius, innerRadius);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ATMOSPHERE_OUTER_RADIUS, Atmosphere, atmosphere, OuterRadius, outerRadius);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ATMOSPHERE_MIE_SCATTERING, Atmosphere, atmosphere, MieScattering, mieScattering);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ATMOSPHERE_RAYLEIGH_SCATTERING, Atmosphere, atmosphere, RayleighScattering, rayleighScattering);
|
||||
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_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);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_ALTITUDE, Stage, stage, Altitude, altitude);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_DAY, Stage, stage, Day, day);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_HOUR, Stage, stage, Hour, hour);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_AUTOMATIC_HOURDAY, Stage, stage, AutomaticHourDay, automaticHourDay);
|
||||
|
||||
// FIXME - these are not yet handled
|
||||
//ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64);
|
||||
|
||||
});
|
||||
|
||||
if (object.isString()) {
|
||||
if (_propertyStringsToEnums.contains(object.toString())) {
|
||||
flags << _propertyStringsToEnums[object.toString()];
|
||||
}
|
||||
} else if (object.isArray()) {
|
||||
quint32 length = object.property("length").toInt32();
|
||||
for (quint32 i = 0; i < length; i++) {
|
||||
QString propertyName = object.property(i).toString();
|
||||
if (_propertyStringsToEnums.contains(propertyName)) {
|
||||
flags << _propertyStringsToEnums[propertyName];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement support for edit packets that can span an MTU sized buffer. We need to implement a mechanism for the
|
||||
// encodeEntityEditPacket() method to communicate the the caller which properties couldn't fit in the buffer. Similar
|
||||
// to how we handle this in the Octree streaming case.
|
||||
|
|
|
@ -58,7 +58,7 @@ class EntityItemProperties {
|
|||
friend class PolyVoxEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
friend class PolyLineEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
public:
|
||||
EntityItemProperties();
|
||||
EntityItemProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags());
|
||||
virtual ~EntityItemProperties();
|
||||
|
||||
EntityTypes::EntityType getType() const { return _type; }
|
||||
|
@ -67,6 +67,9 @@ public:
|
|||
virtual QScriptValue copyToScriptValue(QScriptEngine* engine, bool skipDefaults) const;
|
||||
virtual void copyFromScriptValue(const QScriptValue& object, bool honorReadOnly);
|
||||
|
||||
static QScriptValue entityPropertyFlagsToScriptValue(QScriptEngine* engine, const EntityPropertyFlags& flags);
|
||||
static void entityPropertyFlagsFromScriptValue(const QScriptValue& object, EntityPropertyFlags& flags);
|
||||
|
||||
// editing related features supported by all entities
|
||||
quint64 getLastEdited() const { return _lastEdited; }
|
||||
float getEditedAgo() const /// Elapsed seconds since this entity was last edited
|
||||
|
@ -259,13 +262,19 @@ private:
|
|||
QStringList _textureNames;
|
||||
glm::vec3 _naturalDimensions;
|
||||
glm::vec3 _naturalPosition;
|
||||
|
||||
EntityPropertyFlags _desiredProperties; // if set will narrow scopes of copy/to/from to just these properties
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(EntityItemProperties);
|
||||
QScriptValue EntityItemPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties);
|
||||
QScriptValue EntityItemNonDefaultPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties);
|
||||
void EntityItemPropertiesFromScriptValueIgnoreReadOnly(const QScriptValue &object, EntityItemProperties& properties);
|
||||
void EntityItemPropertiesFromScriptValueHonorReadOnly(const QScriptValue &object, EntityItemProperties& properties);
|
||||
void EntityItemPropertiesFromScriptValueIgnoreReadOnly(const QScriptValue& object, EntityItemProperties& properties);
|
||||
void EntityItemPropertiesFromScriptValueHonorReadOnly(const QScriptValue& object, EntityItemProperties& properties);
|
||||
|
||||
Q_DECLARE_METATYPE(EntityPropertyFlags);
|
||||
QScriptValue EntityPropertyFlagsToScriptValue(QScriptEngine* engine, const EntityPropertyFlags& flags);
|
||||
void EntityPropertyFlagsFromScriptValue(const QScriptValue& object, EntityPropertyFlags& flags);
|
||||
|
||||
|
||||
// define these inline here so the macros work
|
||||
|
|
|
@ -111,8 +111,9 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const QByteArray& v) {
|
|||
inline QScriptValue convertScriptValue(QScriptEngine* e, const EntityItemID& v) { return QScriptValue(QUuid(v).toString()); }
|
||||
|
||||
|
||||
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(G,g,P,p) \
|
||||
if (!skipDefaults || defaultEntityProperties.get##G().get##P() != get##P()) { \
|
||||
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(X,G,g,P,p) \
|
||||
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(); \
|
||||
|
@ -122,8 +123,9 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const EntityItemID& v)
|
|||
properties.setProperty(#g, groupProperties); \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE(P) \
|
||||
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE(p,P) \
|
||||
if ((_desiredProperties.isEmpty() || _desiredProperties.getHasProperty(p)) && \
|
||||
(!skipDefaults || defaultEntityProperties._##P != _##P)) { \
|
||||
QScriptValue V = convertScriptValue(engine, _##P); \
|
||||
properties.setProperty(#P, V); \
|
||||
}
|
||||
|
@ -131,12 +133,19 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const EntityItemID& v)
|
|||
#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(P, G) \
|
||||
properties.setProperty(#P, G);
|
||||
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(P, G) \
|
||||
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(p, P, G) \
|
||||
if ((_desiredProperties.isEmpty() || _desiredProperties.getHasProperty(p)) && \
|
||||
(!skipDefaults || defaultEntityProperties._##P != _##P)) { \
|
||||
QScriptValue V = convertScriptValue(engine, G); \
|
||||
properties.setProperty(#P, V); \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(P, G) \
|
||||
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
|
||||
QScriptValue V = convertScriptValue(engine, G); \
|
||||
properties.setProperty(#P, V); \
|
||||
}
|
||||
|
||||
typedef glm::vec3 glmVec3;
|
||||
typedef glm::quat glmQuat;
|
||||
typedef QVector<glm::vec3> qVectorVec3;
|
||||
|
@ -296,6 +305,12 @@ inline xColor xColor_convertFromScriptValue(const QScriptValue& v, bool& isValid
|
|||
T _##n; \
|
||||
static T _static##N;
|
||||
|
||||
#define ADD_PROPERTY_TO_MAP(P, N, n, T) \
|
||||
_propertyStringsToEnums[#n] = P;
|
||||
|
||||
#define ADD_GROUP_PROPERTY_TO_MAP(P, G, g, N, n) \
|
||||
_propertyStringsToEnums[#g "." #n] = P;
|
||||
|
||||
#define DEFINE_PROPERTY(P, N, n, T) \
|
||||
public: \
|
||||
T get##N() const { return _##n; } \
|
||||
|
|
|
@ -12,33 +12,8 @@
|
|||
#ifndef hifi_EntityPropertyFlags_h
|
||||
#define hifi_EntityPropertyFlags_h
|
||||
|
||||
/*
|
||||
#include <stdint.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/extented_min_max.hpp>
|
||||
|
||||
#include <QtScript/QScriptEngine>
|
||||
#include <QtCore/QObject>
|
||||
#include <QVector>
|
||||
#include <QString>
|
||||
|
||||
#include <AACube.h>
|
||||
#include <FBXReader.h> // for SittingPoint
|
||||
*/
|
||||
|
||||
#include <PropertyFlags.h>
|
||||
|
||||
/*
|
||||
#include <OctreeConstants.h>
|
||||
#include <ShapeInfo.h>
|
||||
|
||||
#include "AtmospherePropertyGroup.h"
|
||||
#include "EntityItemID.h"
|
||||
#include "EntityItemPropertiesMacros.h"
|
||||
#include "EntityTypes.h"
|
||||
*/
|
||||
|
||||
enum EntityPropertyList {
|
||||
PROP_PAGED_PROPERTY,
|
||||
PROP_CUSTOM_PROPERTIES_INCLUDED,
|
||||
|
@ -190,6 +165,7 @@ enum EntityPropertyList {
|
|||
PROP_STAGE_ALTITUDE = PROP_SPECULAR_COLOR_UNUSED,
|
||||
PROP_STAGE_DAY = PROP_LINEAR_ATTENUATION_UNUSED,
|
||||
PROP_STAGE_HOUR = PROP_QUADRATIC_ATTENUATION_UNUSED,
|
||||
PROP_STAGE_AUTOMATIC_HOURDAY = PROP_ANIMATION_FRAME_INDEX,
|
||||
PROP_ATMOSPHERE_CENTER = PROP_MAX_PARTICLES,
|
||||
PROP_ATMOSPHERE_INNER_RADIUS = PROP_LIFESPAN,
|
||||
PROP_ATMOSPHERE_OUTER_RADIUS = PROP_EMIT_RATE,
|
||||
|
@ -200,7 +176,6 @@ enum EntityPropertyList {
|
|||
PROP_BACKGROUND_MODE = PROP_MODEL_URL,
|
||||
PROP_SKYBOX_COLOR = PROP_ANIMATION_URL,
|
||||
PROP_SKYBOX_URL = PROP_ANIMATION_FPS,
|
||||
PROP_STAGE_AUTOMATIC_HOURDAY = PROP_ANIMATION_FRAME_INDEX,
|
||||
|
||||
// Aliases/Piggyback properties for Web. These properties intentionally reuse the enum values for
|
||||
// other properties which will never overlap with each other.
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "EntityScriptingInterface.h"
|
||||
|
||||
#include "EntityItemID.h"
|
||||
#include <VariantMapToScriptValue.h>
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
|
@ -100,12 +101,17 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
|
|||
}
|
||||
|
||||
EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identity) {
|
||||
EntityPropertyFlags noSpecificProperties;
|
||||
return getEntityProperties(identity, noSpecificProperties);
|
||||
}
|
||||
|
||||
EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identity, EntityPropertyFlags desiredProperties) {
|
||||
EntityItemProperties results;
|
||||
if (_entityTree) {
|
||||
_entityTree->withReadLock([&] {
|
||||
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(identity));
|
||||
if (entity) {
|
||||
results = entity->getProperties();
|
||||
results = entity->getProperties(desiredProperties);
|
||||
|
||||
// TODO: improve sitting points and naturalDimensions in the future,
|
||||
// for now we've included the old sitting points model behavior for entity types that are models
|
||||
|
@ -211,6 +217,14 @@ void EntityScriptingInterface::deleteEntity(QUuid id) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityScriptingInterface::callEntityMethod(QUuid id, const QString& method) {
|
||||
if (_entitiesScriptEngine) {
|
||||
EntityItemID entityID{ id };
|
||||
_entitiesScriptEngine->callEntityScriptMethod(entityID, method);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QUuid EntityScriptingInterface::findClosestEntity(const glm::vec3& center, float radius) const {
|
||||
EntityItemID result;
|
||||
if (_entityTree) {
|
||||
|
|
|
@ -20,18 +20,19 @@
|
|||
#include <Octree.h>
|
||||
#include <OctreeScriptingInterface.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "PolyVoxEntityItem.h"
|
||||
#include "LineEntityItem.h"
|
||||
#include "PolyLineEntityItem.h"
|
||||
#include "EntityTree.h"
|
||||
|
||||
#include "EntityEditPacketSender.h"
|
||||
#include "EntitiesScriptEngineProvider.h"
|
||||
|
||||
|
||||
class EntityTree;
|
||||
class MouseEvent;
|
||||
|
||||
|
||||
class RayToEntityIntersectionResult {
|
||||
public:
|
||||
RayToEntityIntersectionResult();
|
||||
|
@ -63,6 +64,7 @@ public:
|
|||
|
||||
void setEntityTree(EntityTreePointer modelTree);
|
||||
EntityTreePointer getEntityTree() { return _entityTree; }
|
||||
void setEntitiesScriptEngine(EntitiesScriptEngineProvider* engine) { _entitiesScriptEngine = engine; }
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -78,6 +80,7 @@ public slots:
|
|||
/// gets the current model properties for a specific model
|
||||
/// this function will not find return results in script engine contexts which don't have access to models
|
||||
Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid entityID);
|
||||
Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid identity, EntityPropertyFlags desiredProperties);
|
||||
|
||||
/// edits a model updating only the included properties, will return the identified EntityItemID in case of
|
||||
/// successful edit, if the input entityID is for an unknown model this function will have no effect
|
||||
|
@ -86,6 +89,11 @@ public slots:
|
|||
/// deletes a model
|
||||
Q_INVOKABLE void deleteEntity(QUuid entityID);
|
||||
|
||||
/// Allows a script to call a method on an entity's script. The method will execute in the entity script
|
||||
/// engine. If the entity does not have an entity script or the method does not exist, this call will have
|
||||
/// no effect.
|
||||
Q_INVOKABLE void callEntityMethod(QUuid entityID, const QString& method);
|
||||
|
||||
/// finds the closest model to the center point, within the radius
|
||||
/// will return a EntityItemID.isKnownID = false if no models are in the radius
|
||||
/// this function will not find any models in script engine contexts which don't have access to models
|
||||
|
@ -180,6 +188,7 @@ private:
|
|||
bool precisionPicking);
|
||||
|
||||
EntityTreePointer _entityTree;
|
||||
EntitiesScriptEngineProvider* _entitiesScriptEngine = nullptr;
|
||||
};
|
||||
|
||||
#endif // hifi_EntityScriptingInterface_h
|
||||
|
|
|
@ -56,8 +56,8 @@ void LightEntityItem::setDimensions(const glm::vec3& value) {
|
|||
}
|
||||
|
||||
|
||||
EntityItemProperties LightEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
EntityItemProperties LightEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(isSpotlight, getIsSpotlight);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
|
||||
|
|
|
@ -26,7 +26,7 @@ public:
|
|||
virtual void setDimensions(const glm::vec3& value);
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
|
||||
|
|
|
@ -43,9 +43,9 @@ LineEntityItem::LineEntityItem(const EntityItemID& entityItemID, const EntityIte
|
|||
|
||||
}
|
||||
|
||||
EntityItemProperties LineEntityItem::getProperties() const {
|
||||
EntityItemProperties LineEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
|
||||
|
||||
properties._color = getXColor();
|
||||
|
|
|
@ -22,8 +22,8 @@ class LineEntityItem : public EntityItem {
|
|||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
|
|
|
@ -43,8 +43,8 @@ ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID, const EntityI
|
|||
_color[0] = _color[1] = _color[2] = 0;
|
||||
}
|
||||
|
||||
EntityItemProperties ModelEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
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);
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
|
|
|
@ -147,8 +147,8 @@ void ParticleEffectEntityItem::computeAndUpdateDimensions() {
|
|||
}
|
||||
|
||||
|
||||
EntityItemProperties ParticleEffectEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
EntityItemProperties ParticleEffectEntityItem::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(alpha, getAlpha);
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of this entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
|
||||
|
|
|
@ -45,9 +45,9 @@ _strokeWidths(QVector<float>(0.0f))
|
|||
setProperties(properties);
|
||||
}
|
||||
|
||||
EntityItemProperties PolyLineEntityItem::getProperties() const {
|
||||
EntityItemProperties PolyLineEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
QWriteLocker lock(&_quadReadWriteLock);
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
|
||||
|
||||
properties._color = getXColor();
|
||||
|
|
|
@ -23,7 +23,7 @@ class PolyLineEntityItem : public EntityItem {
|
|||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
|
|
|
@ -104,8 +104,8 @@ const glm::vec3& PolyVoxEntityItem::getVoxelVolumeSize() const {
|
|||
}
|
||||
|
||||
|
||||
EntityItemProperties PolyVoxEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
EntityItemProperties PolyVoxEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelVolumeSize, getVoxelVolumeSize);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelData, getVoxelData);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelSurfaceStyle, getVoxelSurfaceStyle);
|
||||
|
|
|
@ -23,7 +23,7 @@ class PolyVoxEntityItem : public EntityItem {
|
|||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
virtual ~PropertyGroup() {}
|
||||
|
||||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const = 0;
|
||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const = 0;
|
||||
virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) = 0;
|
||||
virtual void debugDump() const { }
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ SkyboxPropertyGroup::SkyboxPropertyGroup() {
|
|||
_url = QString();
|
||||
}
|
||||
|
||||
void SkyboxPropertyGroup::copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Skybox, skybox, Color, color);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Skybox, skybox, URL, url);
|
||||
void SkyboxPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_SKYBOX_URL, Skybox, skybox, URL, url);
|
||||
}
|
||||
|
||||
void SkyboxPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
virtual ~SkyboxPropertyGroup() {}
|
||||
|
||||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const;
|
||||
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;
|
||||
|
||||
|
|
|
@ -37,8 +37,8 @@ SphereEntityItem::SphereEntityItem(const EntityItemID& entityItemID, const Entit
|
|||
_volumeMultiplier *= PI / 6.0f;
|
||||
}
|
||||
|
||||
EntityItemProperties SphereEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
EntityItemProperties SphereEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
properties.setColor(getXColor());
|
||||
return properties;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
|
||||
|
|
|
@ -36,14 +36,14 @@ StagePropertyGroup::StagePropertyGroup() {
|
|||
_automaticHourDay = false;
|
||||
}
|
||||
|
||||
void StagePropertyGroup::copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, SunModelEnabled, sunModelEnabled);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Latitude, latitude);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Longitude, longitude);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Altitude, altitude);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Day, day);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, Hour, hour);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Stage, stage, AutomaticHourDay, automaticHourDay);
|
||||
void StagePropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_STAGE_SUN_MODEL_ENABLED, Stage, stage, SunModelEnabled, sunModelEnabled);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_STAGE_LATITUDE, Stage, stage, Latitude, latitude);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_STAGE_LONGITUDE, Stage, stage, Longitude, longitude);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_STAGE_ALTITUDE, Stage, stage, Altitude, altitude);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_STAGE_DAY, Stage, stage, Day, day);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_STAGE_HOUR, Stage, stage, Hour, hour);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_STAGE_AUTOMATIC_HOURDAY, Stage, stage, AutomaticHourDay, automaticHourDay);
|
||||
}
|
||||
|
||||
void StagePropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
virtual ~StagePropertyGroup() {}
|
||||
|
||||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const;
|
||||
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;
|
||||
|
||||
|
|
|
@ -47,8 +47,8 @@ void TextEntityItem::setDimensions(const glm::vec3& value) {
|
|||
EntityItem::setDimensions(glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH));
|
||||
}
|
||||
|
||||
EntityItemProperties TextEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
EntityItemProperties TextEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(text, getText);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight);
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; }
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
|
|
|
@ -40,8 +40,8 @@ void WebEntityItem::setDimensions(const glm::vec3& value) {
|
|||
EntityItem::setDimensions(glm::vec3(value.x, value.y, WEB_ENTITY_ITEM_FIXED_DEPTH));
|
||||
}
|
||||
|
||||
EntityItemProperties WebEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
EntityItemProperties WebEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(sourceUrl, getSourceUrl);
|
||||
return properties;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ public:
|
|||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; }
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
|
|
|
@ -73,8 +73,8 @@ EnvironmentData ZoneEntityItem::getEnvironmentData() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
EntityItemProperties ZoneEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
EntityItemProperties ZoneEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightColor, getKeyLightColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightIntensity, getKeyLightIntensity);
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include <string.h>
|
||||
|
||||
#include "Batch.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(NSIGHT_FOUND)
|
||||
#include "nvToolsExt.h"
|
||||
|
||||
|
@ -302,4 +302,28 @@ void Batch::enableSkybox(bool enable) {
|
|||
|
||||
bool Batch::isSkyboxEnabled() const {
|
||||
return _enableSkybox;
|
||||
}
|
||||
}
|
||||
|
||||
void Batch::setupNamedCalls(const std::string& instanceName, NamedBatchData::Function function) {
|
||||
NamedBatchData& instance = _namedData[instanceName];
|
||||
++instance._count;
|
||||
instance._function = function;
|
||||
}
|
||||
|
||||
BufferPointer Batch::getNamedBuffer(const std::string& instanceName, uint8_t index) {
|
||||
NamedBatchData& instance = _namedData[instanceName];
|
||||
if (instance._buffers.size() <= index) {
|
||||
instance._buffers.resize(index + 1);
|
||||
}
|
||||
if (!instance._buffers[index]) {
|
||||
instance._buffers[index].reset(new Buffer());
|
||||
}
|
||||
return instance._buffers[index];
|
||||
}
|
||||
|
||||
void Batch::preExecute() {
|
||||
for (auto& mapItem : _namedData) {
|
||||
mapItem.second.process(*this);
|
||||
}
|
||||
_namedData.clear();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#define hifi_gpu_Batch_h
|
||||
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
|
||||
#include "Framebuffer.h"
|
||||
#include "Pipeline.h"
|
||||
|
@ -38,16 +40,42 @@ enum ReservedSlot {
|
|||
TRANSFORM_CAMERA_SLOT = 7,
|
||||
};
|
||||
|
||||
// The named batch data provides a mechanism for accumulating data into buffers over the course
|
||||
// of many independent calls. For instance, two objects in the scene might both want to render
|
||||
// a simple box, but are otherwise unaware of each other. The common code that they call to render
|
||||
// the box can create buffers to store the rendering parameters for each box and register a function
|
||||
// that will be called with the accumulated buffer data when the batch commands are finally
|
||||
// executed against the backend
|
||||
|
||||
|
||||
class Batch {
|
||||
public:
|
||||
typedef Stream::Slot Slot;
|
||||
|
||||
struct NamedBatchData {
|
||||
using BufferPointers = std::vector<BufferPointer>;
|
||||
using Function = std::function<void(gpu::Batch&, NamedBatchData&)>;
|
||||
|
||||
std::once_flag _once;
|
||||
BufferPointers _buffers;
|
||||
size_t _count{ 0 };
|
||||
Function _function;
|
||||
|
||||
void process(Batch& batch) {
|
||||
_function(batch, *this);
|
||||
}
|
||||
};
|
||||
|
||||
using NamedBatchDataMap = std::map<std::string, NamedBatchData>;
|
||||
|
||||
Batch();
|
||||
explicit Batch(const Batch& batch);
|
||||
~Batch();
|
||||
|
||||
void clear();
|
||||
|
||||
void preExecute();
|
||||
|
||||
// Batches may need to override the context level stereo settings
|
||||
// if they're performing framebuffer copy operations, like the
|
||||
// deferred lighting resolution mechanism
|
||||
|
@ -67,6 +95,12 @@ public:
|
|||
void drawInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbVertices, uint32 startVertex = 0, uint32 startInstance = 0);
|
||||
void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbIndices, uint32 startIndex = 0, uint32 startInstance = 0);
|
||||
|
||||
|
||||
void setupNamedCalls(const std::string& instanceName, NamedBatchData::Function function);
|
||||
BufferPointer getNamedBuffer(const std::string& instanceName, uint8_t index = 0);
|
||||
|
||||
|
||||
|
||||
// Input Stage
|
||||
// InputFormat
|
||||
// InputBuffers
|
||||
|
@ -291,6 +325,8 @@ public:
|
|||
FramebufferCaches _framebuffers;
|
||||
QueryCaches _queries;
|
||||
|
||||
NamedBatchDataMap _namedData;
|
||||
|
||||
bool _enableStereo{ true };
|
||||
bool _enableSkybox{ false };
|
||||
|
||||
|
|
|
@ -120,6 +120,18 @@ enum Dimension {
|
|||
MAT4,
|
||||
NUM_DIMENSIONS,
|
||||
};
|
||||
|
||||
// Count (of scalars) in an Element for a given Dimension
|
||||
static const int LOCATION_COUNT[NUM_DIMENSIONS] = {
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
3,
|
||||
4,
|
||||
};
|
||||
|
||||
// Count (of scalars) in an Element for a given Dimension
|
||||
static const int DIMENSION_COUNT[NUM_DIMENSIONS] = {
|
||||
1,
|
||||
|
@ -127,8 +139,8 @@ static const int DIMENSION_COUNT[NUM_DIMENSIONS] = {
|
|||
3,
|
||||
4,
|
||||
4,
|
||||
9,
|
||||
16,
|
||||
3,
|
||||
4,
|
||||
};
|
||||
|
||||
// Semantic of an Element
|
||||
|
@ -184,6 +196,7 @@ public:
|
|||
|
||||
Dimension getDimension() const { return (Dimension)_dimension; }
|
||||
uint8 getDimensionCount() const { return DIMENSION_COUNT[(Dimension)_dimension]; }
|
||||
uint8 getLocationCount() const { return LOCATION_COUNT[(Dimension)_dimension]; }
|
||||
|
||||
Type getType() const { return (Type)_type; }
|
||||
bool isNormalized() const { return (getType() >= NFLOAT); }
|
||||
|
|
|
@ -191,6 +191,9 @@ void GLBackend::renderPassDraw(Batch& batch) {
|
|||
}
|
||||
|
||||
void GLBackend::render(Batch& batch) {
|
||||
// Finalize the batch by moving all the instanced rendering into the command buffer
|
||||
batch.preExecute();
|
||||
|
||||
_stereo._skybox = batch.isSkyboxEnabled();
|
||||
// Allow the batch to override the rendering stereo settings
|
||||
// for things like full framebuffer copy operations (deferred lighting passes)
|
||||
|
@ -316,7 +319,19 @@ void GLBackend::do_drawInstanced(Batch& batch, uint32 paramOffset) {
|
|||
}
|
||||
|
||||
void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) {
|
||||
(void) CHECK_GL_ERROR();
|
||||
updateInput();
|
||||
updateTransform();
|
||||
updatePipeline();
|
||||
|
||||
GLint numInstances = batch._params[paramOffset + 4]._uint;
|
||||
GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 3]._uint];
|
||||
uint32 numIndices = batch._params[paramOffset + 2]._uint;
|
||||
uint32 startIndex = batch._params[paramOffset + 1]._uint;
|
||||
uint32 startInstance = batch._params[paramOffset + 0]._uint;
|
||||
GLenum glType = _elementTypeToGLType[_input._indexBufferType];
|
||||
|
||||
glDrawElementsInstanced(mode, numIndices, glType, nullptr, numInstances);
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void GLBackend::do_resetStages(Batch& batch, uint32 paramOffset) {
|
||||
|
@ -603,11 +618,16 @@ void Batch::_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
|
|||
DO_IT_NOW(_glColor4f, 4);
|
||||
}
|
||||
void GLBackend::do_glColor4f(Batch& batch, uint32 paramOffset) {
|
||||
// TODO Replace this with a proper sticky Input attribute buffer with frequency 0
|
||||
glVertexAttrib4f( gpu::Stream::COLOR,
|
||||
|
||||
glm::vec4 newColor(
|
||||
batch._params[paramOffset + 3]._float,
|
||||
batch._params[paramOffset + 2]._float,
|
||||
batch._params[paramOffset + 1]._float,
|
||||
batch._params[paramOffset + 0]._float);
|
||||
batch._params[paramOffset + 0]._float);
|
||||
|
||||
if (_input._colorAttribute != newColor) {
|
||||
_input._colorAttribute = newColor;
|
||||
glVertexAttrib4fv(gpu::Stream::COLOR, &_input._colorAttribute.r);
|
||||
}
|
||||
(void) CHECK_GL_ERROR();
|
||||
}
|
||||
|
|
|
@ -278,6 +278,8 @@ protected:
|
|||
Offsets _bufferStrides;
|
||||
std::vector<GLuint> _bufferVBOs;
|
||||
|
||||
glm::vec4 _colorAttribute{ 0.0f };
|
||||
|
||||
BufferPointer _indexBuffer;
|
||||
Offset _indexBufferOffset;
|
||||
Type _indexBufferType;
|
||||
|
|
|
@ -160,7 +160,10 @@ void GLBackend::updateInput() {
|
|||
if (_input._format) {
|
||||
for (auto& it : _input._format->getAttributes()) {
|
||||
const Stream::Attribute& attrib = (it).second;
|
||||
newActivation.set(attrib._slot);
|
||||
uint8_t locationCount = attrib._element.getLocationCount();
|
||||
for (int i = 0; i < locationCount; ++i) {
|
||||
newActivation.set(attrib._slot + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,14 +214,19 @@ void GLBackend::updateInput() {
|
|||
const Stream::Attribute& attrib = attributes.at(channel._slots[i]);
|
||||
GLuint slot = attrib._slot;
|
||||
GLuint count = attrib._element.getDimensionCount();
|
||||
uint8_t locationCount = attrib._element.getLocationCount();
|
||||
GLenum type = _elementTypeToGLType[attrib._element.getType()];
|
||||
GLuint stride = strides[bufferNum];
|
||||
GLenum perLocationStride = strides[bufferNum];
|
||||
GLuint stride = perLocationStride * locationCount;
|
||||
GLuint pointer = attrib._offset + offsets[bufferNum];
|
||||
GLboolean isNormalized = attrib._element.isNormalized();
|
||||
|
||||
glVertexAttribPointer(slot, count, type, isNormalized, stride,
|
||||
reinterpret_cast<GLvoid*>(pointer));
|
||||
|
||||
for (int j = 0; j < locationCount; ++j) {
|
||||
glVertexAttribPointer(slot + j, count, type, isNormalized, stride,
|
||||
reinterpret_cast<GLvoid*>(pointer + perLocationStride * j));
|
||||
glVertexAttribDivisor(slot + j, attrib._frequency);
|
||||
}
|
||||
|
||||
// TODO: Support properly the IAttrib version
|
||||
|
||||
(void) CHECK_GL_ERROR();
|
||||
|
|
|
@ -75,6 +75,11 @@ void makeBindings(GLBackend::GLShader* shader) {
|
|||
glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "inSkinClusterWeight");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "inInstanceTransform");
|
||||
if (loc >= 0 && loc != gpu::Stream::INSTANCE_XFM) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::INSTANCE_XFM, "inInstanceTransform");
|
||||
}
|
||||
|
||||
// Link again to take into account the assigned attrib location
|
||||
glLinkProgram(glprogram);
|
||||
|
||||
|
|
|
@ -18,4 +18,5 @@ in vec4 inTangent;
|
|||
in vec4 inSkinClusterIndex;
|
||||
in vec4 inSkinClusterWeight;
|
||||
in vec4 inTexCoord1;
|
||||
in mat4 inInstanceTransform;
|
||||
<@endif@>
|
||||
|
|
|
@ -139,6 +139,11 @@ public:
|
|||
// \return the number of bytes copied
|
||||
Size append(Size size, const Byte* data);
|
||||
|
||||
template <typename T>
|
||||
Size append(const T& t) {
|
||||
return append(sizeof(t), reinterpret_cast<const Byte*>(&t));
|
||||
}
|
||||
|
||||
// Access the sysmem object.
|
||||
const Sysmem& getSysmem() const { assert(_sysmem); return (*_sysmem); }
|
||||
Sysmem& editSysmem() { assert(_sysmem); return (*_sysmem); }
|
||||
|
|
|
@ -35,11 +35,12 @@ public:
|
|||
SKIN_CLUSTER_INDEX = 5,
|
||||
SKIN_CLUSTER_WEIGHT = 6,
|
||||
TEXCOORD1 = 7,
|
||||
INSTANCE_XFM = 8,
|
||||
INSTANCE_SCALE = 9,
|
||||
INSTANCE_TRANSLATE = 10,
|
||||
INSTANCE_SCALE = 8,
|
||||
INSTANCE_TRANSLATE = 9,
|
||||
INSTANCE_XFM = 10,
|
||||
|
||||
NUM_INPUT_SLOTS,
|
||||
// Instance XFM is a mat4, and as such takes up 4 slots
|
||||
NUM_INPUT_SLOTS = INSTANCE_XFM + 4,
|
||||
};
|
||||
|
||||
typedef uint8 Slot;
|
||||
|
|
|
@ -53,6 +53,15 @@ TransformCamera getTransformCamera() {
|
|||
}
|
||||
<@endfunc@>
|
||||
|
||||
<@func transformInstancedModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@>
|
||||
<!// Equivalent to the following but hoppefully a tad more accurate
|
||||
//return camera._projection * camera._view * object._model * pos; !>
|
||||
{ // transformModelToClipPos
|
||||
vec4 _eyepos = (inInstanceTransform * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0);
|
||||
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos;
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
<@func $transformModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@>
|
||||
<!// Equivalent to the following but hoppefully a tad more accurate
|
||||
//return camera._projection * camera._view * object._model * pos; !>
|
||||
|
@ -65,12 +74,31 @@ TransformCamera getTransformCamera() {
|
|||
}
|
||||
<@endfunc@>
|
||||
|
||||
<@func $transformInstancedModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@>
|
||||
<!// Equivalent to the following but hoppefully a tad more accurate
|
||||
//return camera._projection * camera._view * object._model * pos; !>
|
||||
{ // transformModelToClipPos
|
||||
vec4 _worldpos = (inInstanceTransform * <$modelPos$>);
|
||||
<$eyePos$> = (<$cameraTransform$>._view * _worldpos);
|
||||
vec4 _eyepos =(inInstanceTransform * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0);
|
||||
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos;
|
||||
// <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>);
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
|
||||
<@func transformModelToWorldPos(objectTransform, modelPos, worldPos)@>
|
||||
{ // transformModelToWorldPos
|
||||
<$worldPos$> = (<$objectTransform$>._model * <$modelPos$>);
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
<@func transformInstancedModelToWorldPos(objectTransform, modelPos, worldPos)@>
|
||||
{ // transformModelToWorldPos
|
||||
<$worldPos$> = (inInstanceTransform * <$modelPos$>);
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
<@func transformModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@>
|
||||
{ // transformModelToEyeDir
|
||||
vec3 mr0 = vec3(<$objectTransform$>._modelInverse[0].x, <$objectTransform$>._modelInverse[1].x, <$objectTransform$>._modelInverse[2].x);
|
||||
|
@ -85,6 +113,21 @@ TransformCamera getTransformCamera() {
|
|||
}
|
||||
<@endfunc@>
|
||||
|
||||
<@func transformInstancedModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@>
|
||||
{ // transformModelToEyeDir
|
||||
mat4 modelInverse = inverse(inInstanceTransform);
|
||||
vec3 mr0 = vec3(modelInverse[0].x, modelInverse[1].x, modelInverse[2].x);
|
||||
vec3 mr1 = vec3(modelInverse[0].y, modelInverse[1].y, modelInverse[2].y);
|
||||
vec3 mr2 = vec3(modelInverse[0].z, modelInverse[1].z, modelInverse[2].z);
|
||||
|
||||
vec3 mvc0 = vec3(dot(<$cameraTransform$>._viewInverse[0].xyz, mr0), dot(<$cameraTransform$>._viewInverse[0].xyz, mr1), dot(<$cameraTransform$>._viewInverse[0].xyz, mr2));
|
||||
vec3 mvc1 = vec3(dot(<$cameraTransform$>._viewInverse[1].xyz, mr0), dot(<$cameraTransform$>._viewInverse[1].xyz, mr1), dot(<$cameraTransform$>._viewInverse[1].xyz, mr2));
|
||||
vec3 mvc2 = vec3(dot(<$cameraTransform$>._viewInverse[2].xyz, mr0), dot(<$cameraTransform$>._viewInverse[2].xyz, mr1), dot(<$cameraTransform$>._viewInverse[2].xyz, mr2));
|
||||
|
||||
<$eyeDir$> = vec3(dot(mvc0, <$modelDir$>), dot(mvc1, <$modelDir$>), dot(mvc2, <$modelDir$>));
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
<@func transformEyeToWorldDir(cameraTransform, eyeDir, worldDir)@>
|
||||
{ // transformEyeToWorldDir
|
||||
<$worldDir$> = vec3(<$cameraTransform$>._viewInverse * vec4(<$eyeDir$>.xyz, 0.0));
|
||||
|
|
|
@ -42,7 +42,7 @@ const unsigned int GRIP_BUTTON = 1U << 2;
|
|||
const unsigned int TRACKPAD_BUTTON = 1U << 3;
|
||||
const unsigned int TRIGGER_BUTTON = 1U << 4;
|
||||
|
||||
const float CONTROLLER_LENGTH_OFFSET = 0.175f;
|
||||
const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches
|
||||
const QString CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b";
|
||||
|
||||
const QString ViveControllerManager::NAME = "OpenVR";
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
virtual char getMyNodeType() const = 0;
|
||||
virtual PacketType getMyQueryMessageType() const = 0;
|
||||
virtual PacketType getExpectedPacketType() const = 0;
|
||||
virtual void renderElement(OctreeElementPointer element, RenderArgs* args) = 0;
|
||||
virtual void renderElement(OctreeElementPointer element, RenderArgs* args) { }
|
||||
virtual float getSizeScale() const { return DEFAULT_OCTREE_SIZE_SCALE; }
|
||||
virtual int getBoundaryLevelAdjust() const { return 0; }
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -37,15 +37,22 @@ public:
|
|||
void init(AbstractViewStateInterface* viewState);
|
||||
|
||||
/// Sets up the state necessary to render static untextured geometry with the simple program.
|
||||
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
|
||||
gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
|
||||
bool emmisive = false, bool depthBias = false);
|
||||
|
||||
/// Sets up the state necessary to render static untextured geometry with the simple program.
|
||||
void bindInstanceProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
|
||||
bool emmisive = false, bool depthBias = false);
|
||||
|
||||
//// Renders a solid sphere with the simple program.
|
||||
void renderSolidSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color);
|
||||
|
||||
//// Renders a wireframe sphere with the simple program.
|
||||
void renderWireSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color);
|
||||
|
||||
//// Renders a solid cube using instancing. Transform should include scaling.
|
||||
void renderSolidCubeInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color);
|
||||
|
||||
//// Renders a solid cube with the simple program.
|
||||
void renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color);
|
||||
|
||||
|
|
|
@ -691,28 +691,31 @@ void GeometryCache::renderVertices(gpu::Batch& batch, gpu::Primitive primitiveTy
|
|||
}
|
||||
}
|
||||
|
||||
void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color) {
|
||||
Vec2Pair colorKey(glm::vec2(color.x, color.y), glm::vec2(color.z, color.y));
|
||||
const int FLOATS_PER_VERTEX = 3;
|
||||
const int VERTICES_PER_FACE = 4;
|
||||
const int NUMBER_OF_FACES = 6;
|
||||
const int TRIANGLES_PER_FACE = 2;
|
||||
const int VERTICES_PER_TRIANGLE = 3;
|
||||
const int vertices = NUMBER_OF_FACES * VERTICES_PER_FACE;
|
||||
const int indices = NUMBER_OF_FACES * TRIANGLES_PER_FACE * VERTICES_PER_TRIANGLE;
|
||||
const int vertexPoints = vertices * FLOATS_PER_VERTEX;
|
||||
const int VERTEX_STRIDE = sizeof(GLfloat) * FLOATS_PER_VERTEX * 2; // vertices and normals
|
||||
const int NORMALS_OFFSET = sizeof(GLfloat) * FLOATS_PER_VERTEX;
|
||||
static const int FLOATS_PER_VERTEX = 3;
|
||||
static const int VERTICES_PER_TRIANGLE = 3;
|
||||
|
||||
static const int CUBE_NUMBER_OF_FACES = 6;
|
||||
static const int CUBE_VERTICES_PER_FACE = 4;
|
||||
static const int CUBE_TRIANGLES_PER_FACE = 2;
|
||||
static const int CUBE_VERTICES = CUBE_NUMBER_OF_FACES * CUBE_VERTICES_PER_FACE;
|
||||
static const int CUBE_VERTEX_POINTS = CUBE_VERTICES * FLOATS_PER_VERTEX;
|
||||
static const int CUBE_INDICES = CUBE_NUMBER_OF_FACES * CUBE_TRIANGLES_PER_FACE * VERTICES_PER_TRIANGLE;
|
||||
|
||||
static const gpu::Element CUBE_POSITION_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||
static const gpu::Element CUBE_NORMAL_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||
static const gpu::Element CUBE_COLOR_ELEMENT{ gpu::VEC4, gpu::NUINT8, gpu::RGBA };
|
||||
static const gpu::Element INSTANCE_XFM_ELEMENT{ gpu::MAT4, gpu::FLOAT, gpu::XYZW };
|
||||
|
||||
gpu::BufferPointer GeometryCache::getCubeVertices(float size) {
|
||||
if (!_solidCubeVertices.contains(size)) {
|
||||
auto verticesBuffer = std::make_shared<gpu::Buffer>();
|
||||
_solidCubeVertices[size] = verticesBuffer;
|
||||
|
||||
GLfloat* vertexData = new GLfloat[vertexPoints * 2]; // vertices and normals
|
||||
GLfloat* vertexData = new GLfloat[CUBE_VERTEX_POINTS * 2]; // vertices and normals
|
||||
GLfloat* vertex = vertexData;
|
||||
float halfSize = size / 2.0f;
|
||||
|
||||
static GLfloat cannonicalVertices[vertexPoints] =
|
||||
static GLfloat cannonicalVertices[CUBE_VERTEX_POINTS] =
|
||||
{ 1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, // v0,v1,v2,v3 (front)
|
||||
1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, // v0,v3,v4,v5 (right)
|
||||
1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, // v0,v5,v6,v1 (top)
|
||||
|
@ -721,7 +724,7 @@ void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::ve
|
|||
1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1 }; // v4,v7,v6,v5 (back)
|
||||
|
||||
// normal array
|
||||
static GLfloat cannonicalNormals[vertexPoints] =
|
||||
static GLfloat cannonicalNormals[CUBE_VERTEX_POINTS] =
|
||||
{ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0,v1,v2,v3 (front)
|
||||
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0,v3,v4,v5 (right)
|
||||
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v0,v5,v6,v1 (top)
|
||||
|
@ -733,7 +736,7 @@ void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::ve
|
|||
GLfloat* cannonicalVertex = &cannonicalVertices[0];
|
||||
GLfloat* cannonicalNormal = &cannonicalNormals[0];
|
||||
|
||||
for (int i = 0; i < vertices; i++) {
|
||||
for (int i = 0; i < CUBE_VERTICES; i++) {
|
||||
// vertices
|
||||
*(vertex++) = halfSize * *cannonicalVertex++;
|
||||
*(vertex++) = halfSize * *cannonicalVertex++;
|
||||
|
@ -744,90 +747,121 @@ void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::ve
|
|||
*(vertex++) = *cannonicalNormal++;
|
||||
*(vertex++) = *cannonicalNormal++;
|
||||
}
|
||||
|
||||
verticesBuffer->append(sizeof(GLfloat) * vertexPoints * 2, (gpu::Byte*) vertexData);
|
||||
verticesBuffer->append(sizeof(GLfloat) * CUBE_VERTEX_POINTS * 2, (gpu::Byte*) vertexData);
|
||||
}
|
||||
|
||||
return _solidCubeVertices[size];
|
||||
}
|
||||
|
||||
gpu::BufferPointer GeometryCache::getSolidCubeIndices() {
|
||||
if (!_solidCubeIndexBuffer) {
|
||||
static GLubyte cannonicalIndices[indices] =
|
||||
{ 0, 1, 2, 2, 3, 0, // front
|
||||
static GLubyte cannonicalIndices[CUBE_INDICES] = { 0, 1, 2, 2, 3, 0, // front
|
||||
4, 5, 6, 6, 7, 4, // right
|
||||
8, 9,10, 10,11, 8, // top
|
||||
12,13,14, 14,15,12, // left
|
||||
16,17,18, 18,19,16, // bottom
|
||||
20,21,22, 22,23,20 }; // back
|
||||
|
||||
|
||||
auto indexBuffer = std::make_shared<gpu::Buffer>();
|
||||
_solidCubeIndexBuffer = indexBuffer;
|
||||
|
||||
|
||||
_solidCubeIndexBuffer->append(sizeof(cannonicalIndices), (gpu::Byte*) cannonicalIndices);
|
||||
}
|
||||
return _solidCubeIndexBuffer;
|
||||
}
|
||||
|
||||
|
||||
void GeometryCache::setupCubeVertices(gpu::Batch& batch, gpu::BufferPointer& verticesBuffer) {
|
||||
static const int VERTEX_STRIDE = sizeof(GLfloat) * FLOATS_PER_VERTEX * 2; // vertices and normals
|
||||
static const int NORMALS_OFFSET = sizeof(GLfloat) * FLOATS_PER_VERTEX;
|
||||
|
||||
gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), VERTEX_STRIDE, CUBE_POSITION_ELEMENT);
|
||||
gpu::BufferView normalsView(verticesBuffer, NORMALS_OFFSET, verticesBuffer->getSize(), VERTEX_STRIDE, CUBE_NORMAL_ELEMENT);
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, verticesView);
|
||||
batch.setInputBuffer(gpu::Stream::NORMAL, normalsView);
|
||||
}
|
||||
|
||||
void GeometryCache::renderSolidCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
|
||||
static gpu::Stream::FormatPointer streamFormat;
|
||||
if (!streamFormat) {
|
||||
streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
||||
streamFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, CUBE_POSITION_ELEMENT, 0);
|
||||
streamFormat->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, CUBE_NORMAL_ELEMENT);
|
||||
streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, CUBE_COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
||||
streamFormat->setAttribute(gpu::Stream::INSTANCE_XFM, gpu::Stream::INSTANCE_XFM, INSTANCE_XFM_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
|
||||
}
|
||||
batch.setInputFormat(streamFormat);
|
||||
|
||||
gpu::BufferView colorView(colorBuffer, CUBE_COLOR_ELEMENT);
|
||||
batch.setInputBuffer(gpu::Stream::COLOR, colorView);
|
||||
|
||||
gpu::BufferView instanceXfmView(transformBuffer, 0, transformBuffer->getSize(), INSTANCE_XFM_ELEMENT);
|
||||
batch.setInputBuffer(gpu::Stream::INSTANCE_XFM, instanceXfmView);
|
||||
|
||||
gpu::BufferPointer verticesBuffer = getCubeVertices(1.0);
|
||||
setupCubeVertices(batch, verticesBuffer);
|
||||
batch.setIndexBuffer(gpu::UINT8, getSolidCubeIndices(), 0);
|
||||
batch.drawIndexedInstanced(count, gpu::TRIANGLES, CUBE_INDICES);
|
||||
}
|
||||
|
||||
|
||||
void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color) {
|
||||
Vec2Pair colorKey(glm::vec2(color.x, color.y), glm::vec2(color.z, color.y));
|
||||
if (!_solidCubeColors.contains(colorKey)) {
|
||||
auto colorBuffer = std::make_shared<gpu::Buffer>();
|
||||
_solidCubeColors[colorKey] = colorBuffer;
|
||||
|
||||
const int NUM_COLOR_SCALARS_PER_CUBE = 24;
|
||||
int compactColor = ((int(color.x * 255.0f) & 0xFF)) |
|
||||
((int(color.y * 255.0f) & 0xFF) << 8) |
|
||||
((int(color.z * 255.0f) & 0xFF) << 16) |
|
||||
((int(color.w * 255.0f) & 0xFF) << 24);
|
||||
int colors[NUM_COLOR_SCALARS_PER_CUBE] = { compactColor, compactColor, compactColor, compactColor,
|
||||
compactColor, compactColor, compactColor, compactColor,
|
||||
compactColor, compactColor, compactColor, compactColor,
|
||||
compactColor, compactColor, compactColor, compactColor,
|
||||
compactColor, compactColor, compactColor, compactColor,
|
||||
compactColor, compactColor, compactColor, compactColor };
|
||||
|
||||
int colors[CUBE_VERTICES] = {
|
||||
compactColor, compactColor, compactColor, compactColor,
|
||||
compactColor, compactColor, compactColor, compactColor,
|
||||
compactColor, compactColor, compactColor, compactColor,
|
||||
compactColor, compactColor, compactColor, compactColor,
|
||||
compactColor, compactColor, compactColor, compactColor,
|
||||
compactColor, compactColor, compactColor, compactColor
|
||||
};
|
||||
colorBuffer->append(sizeof(colors), (gpu::Byte*) colors);
|
||||
}
|
||||
gpu::BufferPointer verticesBuffer = _solidCubeVertices[size];
|
||||
gpu::BufferPointer colorBuffer = _solidCubeColors[colorKey];
|
||||
|
||||
const int VERTICES_SLOT = 0;
|
||||
const int NORMALS_SLOT = 1;
|
||||
const int COLOR_SLOT = 2;
|
||||
static gpu::Stream::FormatPointer streamFormat;
|
||||
static gpu::Element positionElement, normalElement, colorElement;
|
||||
if (!streamFormat) {
|
||||
streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
||||
streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||
streamFormat->setAttribute(gpu::Stream::NORMAL, NORMALS_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
|
||||
streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||
positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element;
|
||||
normalElement = streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element;
|
||||
colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element;
|
||||
streamFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, CUBE_POSITION_ELEMENT, 0);
|
||||
streamFormat->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, CUBE_NORMAL_ELEMENT);
|
||||
streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, CUBE_COLOR_ELEMENT);
|
||||
}
|
||||
|
||||
|
||||
gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), VERTEX_STRIDE, positionElement);
|
||||
gpu::BufferView normalsView(verticesBuffer, NORMALS_OFFSET, verticesBuffer->getSize(), VERTEX_STRIDE, normalElement);
|
||||
gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
|
||||
|
||||
batch.setInputFormat(streamFormat);
|
||||
batch.setInputBuffer(VERTICES_SLOT, verticesView);
|
||||
batch.setInputBuffer(NORMALS_SLOT, normalsView);
|
||||
batch.setInputBuffer(COLOR_SLOT, colorView);
|
||||
batch.setIndexBuffer(gpu::UINT8, _solidCubeIndexBuffer, 0);
|
||||
batch.drawIndexed(gpu::TRIANGLES, indices);
|
||||
|
||||
gpu::BufferView colorView(colorBuffer, CUBE_COLOR_ELEMENT);
|
||||
batch.setInputBuffer(gpu::Stream::COLOR, colorView);
|
||||
|
||||
gpu::BufferPointer verticesBuffer = getCubeVertices(size);
|
||||
setupCubeVertices(batch, verticesBuffer);
|
||||
|
||||
batch.setIndexBuffer(gpu::UINT8, getSolidCubeIndices(), 0);
|
||||
batch.drawIndexed(gpu::TRIANGLES, CUBE_INDICES);
|
||||
}
|
||||
|
||||
|
||||
void GeometryCache::renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color) {
|
||||
Vec2Pair colorKey(glm::vec2(color.x, color.y),glm::vec2(color.z, color.y));
|
||||
const int FLOATS_PER_VERTEX = 3;
|
||||
const int VERTICES_PER_EDGE = 2;
|
||||
const int TOP_EDGES = 4;
|
||||
const int BOTTOM_EDGES = 4;
|
||||
const int SIDE_EDGES = 4;
|
||||
const int vertices = 8;
|
||||
const int indices = (TOP_EDGES + BOTTOM_EDGES + SIDE_EDGES) * VERTICES_PER_EDGE;
|
||||
static const int WIRE_CUBE_VERTICES_PER_EDGE = 2;
|
||||
static const int WIRE_CUBE_TOP_EDGES = 4;
|
||||
static const int WIRE_CUBE_BOTTOM_EDGES = 4;
|
||||
static const int WIRE_CUBE_SIDE_EDGES = 4;
|
||||
static const int WIRE_CUBE_VERTICES = 8;
|
||||
static const int WIRE_CUBE_INDICES = (WIRE_CUBE_TOP_EDGES + WIRE_CUBE_BOTTOM_EDGES + WIRE_CUBE_SIDE_EDGES) * WIRE_CUBE_VERTICES_PER_EDGE;
|
||||
|
||||
if (!_cubeVerticies.contains(size)) {
|
||||
auto verticesBuffer = std::make_shared<gpu::Buffer>();
|
||||
_cubeVerticies[size] = verticesBuffer;
|
||||
|
||||
int vertexPoints = vertices * FLOATS_PER_VERTEX;
|
||||
GLfloat* vertexData = new GLfloat[vertexPoints]; // only vertices, no normals because we're a wire cube
|
||||
static const int WIRE_CUBE_VERTEX_POINTS = WIRE_CUBE_VERTICES * FLOATS_PER_VERTEX;
|
||||
GLfloat* vertexData = new GLfloat[WIRE_CUBE_VERTEX_POINTS]; // only vertices, no normals because we're a wire cube
|
||||
GLfloat* vertex = vertexData;
|
||||
float halfSize = size / 2.0f;
|
||||
|
||||
|
@ -836,15 +870,15 @@ void GeometryCache::renderWireCube(gpu::Batch& batch, float size, const glm::vec
|
|||
1,-1, 1, 1,-1,-1, -1,-1,-1, -1,-1, 1 // v4, v5, v6, v7 (bottom)
|
||||
};
|
||||
|
||||
for (int i = 0; i < vertexPoints; i++) {
|
||||
for (int i = 0; i < WIRE_CUBE_VERTEX_POINTS; i++) {
|
||||
vertex[i] = cannonicalVertices[i] * halfSize;
|
||||
}
|
||||
|
||||
verticesBuffer->append(sizeof(GLfloat) * vertexPoints, (gpu::Byte*) vertexData); // I'm skeptical that this is right
|
||||
verticesBuffer->append(sizeof(GLfloat) * WIRE_CUBE_VERTEX_POINTS, (gpu::Byte*) vertexData); // I'm skeptical that this is right
|
||||
}
|
||||
|
||||
if (!_wireCubeIndexBuffer) {
|
||||
static GLubyte cannonicalIndices[indices] = {
|
||||
static GLubyte cannonicalIndices[WIRE_CUBE_INDICES] = {
|
||||
0, 1, 1, 2, 2, 3, 3, 0, // (top)
|
||||
4, 5, 5, 6, 6, 7, 7, 4, // (bottom)
|
||||
0, 4, 1, 5, 2, 6, 3, 7, // (side edges)
|
||||
|
@ -892,7 +926,7 @@ void GeometryCache::renderWireCube(gpu::Batch& batch, float size, const glm::vec
|
|||
batch.setInputBuffer(VERTICES_SLOT, verticesView);
|
||||
batch.setInputBuffer(COLOR_SLOT, colorView);
|
||||
batch.setIndexBuffer(gpu::UINT8, _wireCubeIndexBuffer, 0);
|
||||
batch.drawIndexed(gpu::LINES, indices);
|
||||
batch.drawIndexed(gpu::LINES, WIRE_CUBE_INDICES);
|
||||
}
|
||||
|
||||
void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id) {
|
||||
|
|
|
@ -136,6 +136,11 @@ public:
|
|||
virtual QSharedPointer<Resource> createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
|
||||
bool delayLoad, const void* extra);
|
||||
|
||||
gpu::BufferPointer getCubeVertices(float size);
|
||||
void setupCubeVertices(gpu::Batch& batch, gpu::BufferPointer& verticesBuffer);
|
||||
|
||||
gpu::BufferPointer getSolidCubeIndices();
|
||||
|
||||
void renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec3& color, bool solid = true, int id = UNKNOWN_ID)
|
||||
{ renderSphere(batch, radius, slices, stacks, glm::vec4(color, 1.0f), solid, id); }
|
||||
|
||||
|
@ -144,6 +149,7 @@ public:
|
|||
void renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color);
|
||||
void renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
|
||||
void renderSolidCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer);
|
||||
void renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color);
|
||||
void renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color);
|
||||
void renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
uniform bool Instanced = false;
|
||||
// the interpolated normal
|
||||
|
||||
out vec3 _normal;
|
||||
|
@ -33,6 +34,11 @@ void main(void) {
|
|||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
|
||||
if (Instanced) {
|
||||
<$transformInstancedModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
<$transformInstancedModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
|
||||
} else {
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
|
||||
}
|
||||
}
|
|
@ -280,6 +280,7 @@ void ScriptEngine::init() {
|
|||
_controllerScriptingInterface->registerControllerTypes(this);
|
||||
}
|
||||
|
||||
qScriptRegisterMetaType(this, EntityPropertyFlagsToScriptValue, EntityPropertyFlagsFromScriptValue);
|
||||
qScriptRegisterMetaType(this, EntityItemPropertiesToScriptValue, EntityItemPropertiesFromScriptValueHonorReadOnly);
|
||||
qScriptRegisterMetaType(this, EntityItemIDtoScriptValue, EntityItemIDfromScriptValue);
|
||||
qScriptRegisterMetaType(this, RayToEntityIntersectionResultToScriptValue, RayToEntityIntersectionResultFromScriptValue);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <AvatarHashMap.h>
|
||||
#include <LimitedNodeList.h>
|
||||
#include <EntityItemID.h>
|
||||
#include <EntitiesScriptEngineProvider.h>
|
||||
|
||||
#include "AbstractControllerScriptingInterface.h"
|
||||
#include "ArrayBufferClass.h"
|
||||
|
@ -46,7 +47,7 @@ public:
|
|||
QScriptValue scriptObject;
|
||||
};
|
||||
|
||||
class ScriptEngine : public QScriptEngine, public ScriptUser {
|
||||
class ScriptEngine : public QScriptEngine, public ScriptUser, public EntitiesScriptEngineProvider {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScriptEngine(const QString& scriptContents = NO_SCRIPT,
|
||||
|
|
|
@ -45,6 +45,7 @@ public:
|
|||
_maxFlag(INT_MIN), _minFlag(INT_MAX), _trailingFlipped(false), _encodedLength(0) { decode(fromEncoded); }
|
||||
|
||||
void clear() { _flags.clear(); _maxFlag = INT_MIN; _minFlag = INT_MAX; _trailingFlipped = false; _encodedLength = 0; }
|
||||
bool isEmpty() const { return _maxFlag == INT_MIN && _minFlag == INT_MAX && _trailingFlipped == false && _encodedLength == 0; }
|
||||
|
||||
Enum firstFlag() const { return (Enum)_minFlag; }
|
||||
Enum lastFlag() const { return (Enum)_maxFlag; }
|
||||
|
|
Loading…
Reference in a new issue