diff --git a/Apps/CesiumViewer/Gallery/simple.czml b/Apps/CesiumViewer/Gallery/simple.czml index 4da0922c0976..b2da65a7dc59 100644 --- a/Apps/CesiumViewer/Gallery/simple.czml +++ b/Apps/CesiumViewer/Gallery/simple.czml @@ -3866,8 +3866,8 @@ }, "vertexPositions":{ "references":[ - "Satellite/Geoeye1.position", - "Satellite/ISS.position" + "Satellite/Geoeye1#position", + "Satellite/ISS#position" ] } }, @@ -3946,8 +3946,8 @@ }, "vertexPositions":{ "references":[ - "Facility/AGI.position", - "Satellite/ISS.position" + "Facility/AGI#position", + "Satellite/ISS#position" ] } }, @@ -3966,8 +3966,8 @@ }, "vertexPositions":{ "references":[ - "Facility/AGI.position", - "Satellite/Geoeye1/Sensor/Sensor.position" + "Facility/AGI#position", + "Satellite/Geoeye1/Sensor/Sensor#position" ] } } diff --git a/CHANGES.md b/CHANGES.md index 7eccbbb0a300..8ab34fa04552 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,9 @@ Beta Releases * Replaced `Scene.scene2D.projection` property with read-only `Scene.mapProjection`. Set this with the `mapProjection` option for the `Viewer`, `CesiumWidget`, or `Scene` constructors. * `Scene` constructor function now takes an `options` parameter instead of individual parameters. * Replaced `color`, `outlineColor`, and `outlineWidth` in `DynamicPath` with a `material` property. + * CZML property references now use a `#` symbol to separate identifier from property path. `objectId.position` should now be `objectId#position`. +* `DynamicObject.id` can now include period characters. +* `ReferenceProperty` can now handle sub-properties, for example, `myObject#billboard.scale`. * Added `Cesium.VERSION` to the combined `Cesium.js` file. * Fixed support for embedded resources in glTF models. * Added 'PolylineGlowMaterialProperty' which enables data sources to use the PolylineGlow material. diff --git a/Source/DynamicScene/CzmlDataSource.js b/Source/DynamicScene/CzmlDataSource.js index 9c91be963ec9..73c83391c6fb 100644 --- a/Source/DynamicScene/CzmlDataSource.js +++ b/Source/DynamicScene/CzmlDataSource.js @@ -141,6 +141,15 @@ define([ TimeIntervalCollectionProperty) { "use strict"; + var currentId; + + function makeReference(collection, referenceString) { + if (referenceString[0] === '#') { + referenceString = currentId + referenceString; + } + return ReferenceProperty.fromString(collection, referenceString); + } + //This class is a workaround for CZML represented as two properties which get turned into a single Cartesian2 property once loaded. var Cartesian2WrapperProperty = function() { this._definitionChanged = new Event(); @@ -427,7 +436,7 @@ define([ } } - function processProperty(type, object, propertyName, packetData, constrainedInterval, sourceUri) { + function processProperty(type, object, propertyName, packetData, constrainedInterval, sourceUri, dynamicObjectCollection) { var combinedInterval; var packetInterval = packetData.interval; if (defined(packetInterval)) { @@ -439,15 +448,26 @@ define([ combinedInterval = constrainedInterval; } - var unwrappedInterval = unwrapInterval(type, packetData, sourceUri); + var packedLength; + var isSampled; + var unwrappedInterval; + var unwrappedIntervalLength; + var isReference = defined(packetData.reference); var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); - var packedLength = defaultValue(type.packedLength, 1); - var unwrappedIntervalLength = defaultValue(unwrappedInterval.length, 1); - var isSampled = !defined(packetData.array) && (typeof unwrappedInterval !== 'string') && unwrappedIntervalLength > packedLength; + + if (!isReference) { + unwrappedInterval = unwrapInterval(type, packetData, sourceUri); + packedLength = defaultValue(type.packedLength, 1); + unwrappedIntervalLength = defaultValue(unwrappedInterval.length, 1); + isSampled = !defined(packetData.array) && (typeof unwrappedInterval !== 'string') && unwrappedIntervalLength > packedLength; + } + //Any time a constant value is assigned, it completely blows away anything else. if (!isSampled && !hasInterval) { - if (defined(type.unpack)) { + if (isReference) { + object[propertyName] = makeReference(dynamicObjectCollection, packetData.reference); + } else if (defined(type.unpack)) { object[propertyName] = new ConstantProperty(type.unpack(unwrappedInterval, 0)); } else { object[propertyName] = new ConstantProperty(unwrappedInterval); @@ -455,7 +475,6 @@ define([ return; } - var propertyCreated = false; var property = object[propertyName]; var epoch; @@ -470,11 +489,10 @@ define([ if (!(property instanceof SampledProperty)) { property = new SampledProperty(type); object[propertyName] = property; - propertyCreated = true; } property.addSamplesPackedArray(unwrappedInterval, epoch); updateInterpolationSettings(packetData, property); - return propertyCreated; + return; } var interval; @@ -485,7 +503,9 @@ define([ if (!isSampled && hasInterval) { //Create a new interval for the constant value. combinedInterval = combinedInterval.clone(); - if (defined(type.unpack)) { + if (isReference) { + combinedInterval.data = makeReference(dynamicObjectCollection, packetData.reference); + } else if (defined(type.unpack)) { combinedInterval.data = type.unpack(unwrappedInterval, 0); } else { combinedInterval.data = unwrappedInterval; @@ -493,17 +513,20 @@ define([ //If no property exists, simply use a new interval collection if (!defined(property)) { - property = new TimeIntervalCollectionProperty(); + if (isReference) { + property = new CompositeProperty(); + } else { + property = new TimeIntervalCollectionProperty(); + } object[propertyName] = property; - propertyCreated = true; } - if (property instanceof TimeIntervalCollectionProperty) { + if (!isReference && property instanceof TimeIntervalCollectionProperty) { //If we create a collection, or it already existed, use it. property.intervals.addInterval(combinedInterval); } else if (property instanceof CompositeProperty) { //If the collection was already a CompositeProperty, use it. - combinedInterval.data = new ConstantProperty(combinedInterval.data); + combinedInterval.data = isReference ? combinedInterval.data : new ConstantProperty(combinedInterval.data); property.intervals.addInterval(combinedInterval); } else { //Otherwise, create a CompositeProperty but preserve the existing data. @@ -513,7 +536,6 @@ define([ interval.data = property; //Create the composite. - propertyCreated = true; property = new CompositeProperty(); object[propertyName] = property; @@ -521,16 +543,15 @@ define([ property.intervals.addInterval(interval); //Change the new data to a ConstantProperty and add it. - combinedInterval.data = new ConstantProperty(combinedInterval.data); + combinedInterval.data = isReference ? combinedInterval.data : new ConstantProperty(combinedInterval.data); property.intervals.addInterval(combinedInterval); } - return propertyCreated; + return; } //isSampled && hasInterval if (!defined(property)) { - propertyCreated = true; property = new CompositeProperty(); object[propertyName] = property; } @@ -542,7 +563,6 @@ define([ interval.data = property; //Create the composite. - propertyCreated = true; property = new CompositeProperty(); object[propertyName] = property; @@ -561,24 +581,24 @@ define([ } interval.data.addSamplesPackedArray(unwrappedInterval, epoch); updateInterpolationSettings(packetData, interval.data); - return propertyCreated; + return; } - function processPacketData(type, object, propertyName, packetData, interval, sourceUri) { + function processPacketData(type, object, propertyName, packetData, interval, sourceUri, dynamicObjectCollection) { if (!defined(packetData)) { return; } if (isArray(packetData)) { for (var i = 0, len = packetData.length; i < len; i++) { - processProperty(type, object, propertyName, packetData[i], interval, sourceUri); + processProperty(type, object, propertyName, packetData[i], interval, sourceUri, dynamicObjectCollection); } } else { - processProperty(type, object, propertyName, packetData, interval, sourceUri); + processProperty(type, object, propertyName, packetData, interval, sourceUri, dynamicObjectCollection); } } - function processPositionProperty(object, propertyName, packetData, constrainedInterval, sourceUri) { + function processPositionProperty(object, propertyName, packetData, constrainedInterval, sourceUri, dynamicObjectCollection) { var combinedInterval; var packetInterval = packetData.interval; if (defined(packetInterval)) { @@ -590,20 +610,31 @@ define([ combinedInterval = constrainedInterval; } - var referenceFrame = defaultValue(ReferenceFrame[packetData.referenceFrame], undefined); - var unwrappedInterval = unwrapCartesianInterval(packetData); - var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); + var referenceFrame; + var unwrappedInterval; + var isSampled = false; + var unwrappedIntervalLength; var packedLength = Cartesian3.packedLength; - var unwrappedIntervalLength = defaultValue(unwrappedInterval.length, 1); - var isSampled = (typeof unwrappedInterval !== 'string') && unwrappedIntervalLength > packedLength; + var isReference = defined(packetData.reference); + var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); + + if (!isReference) { + referenceFrame = defaultValue(ReferenceFrame[packetData.referenceFrame], undefined); + unwrappedInterval = unwrapCartesianInterval(packetData); + unwrappedIntervalLength = defaultValue(unwrappedInterval.length, 1); + isSampled = unwrappedIntervalLength > packedLength; + } //Any time a constant value is assigned, it completely blows away anything else. if (!isSampled && !hasInterval) { - object[propertyName] = new ConstantPositionProperty(Cartesian3.unpack(unwrappedInterval), referenceFrame); - return true; + if (isReference) { + object[propertyName] = makeReference(dynamicObjectCollection, packetData.reference); + } else { + object[propertyName] = new ConstantPositionProperty(Cartesian3.unpack(unwrappedInterval), referenceFrame); + } + return; } - var propertyCreated = false; var property = object[propertyName]; var epoch; @@ -618,11 +649,10 @@ define([ if (!(property instanceof SampledPositionProperty) || (defined(referenceFrame) && property.referenceFrame !== referenceFrame)) { property = new SampledPositionProperty(referenceFrame); object[propertyName] = property; - propertyCreated = true; } property.addSamplesPackedArray(unwrappedInterval, epoch); updateInterpolationSettings(packetData, property); - return propertyCreated; + return; } var interval; @@ -633,21 +663,28 @@ define([ if (!isSampled && hasInterval) { //Create a new interval for the constant value. combinedInterval = combinedInterval.clone(); - combinedInterval.data = Cartesian3.unpack(unwrappedInterval); + if (isReference) { + combinedInterval.data = makeReference(dynamicObjectCollection, packetData.reference); + } else { + combinedInterval.data = Cartesian3.unpack(unwrappedInterval); + } //If no property exists, simply use a new interval collection if (!defined(property)) { - property = new TimeIntervalCollectionPositionProperty(referenceFrame); + if (isReference) { + property = new CompositePositionProperty(referenceFrame); + } else { + property = new TimeIntervalCollectionPositionProperty(referenceFrame); + } object[propertyName] = property; - propertyCreated = true; } - if (property instanceof TimeIntervalCollectionPositionProperty && (defined(referenceFrame) && property.referenceFrame === referenceFrame)) { + if (!isReference && property instanceof TimeIntervalCollectionPositionProperty && (defined(referenceFrame) && property.referenceFrame === referenceFrame)) { //If we create a collection, or it already existed, use it. property.intervals.addInterval(combinedInterval); } else if (property instanceof CompositePositionProperty) { //If the collection was already a CompositePositionProperty, use it. - combinedInterval.data = new ConstantPositionProperty(combinedInterval.data, referenceFrame); + combinedInterval.data = isReference ? combinedInterval.data : new ConstantPositionProperty(combinedInterval.data, referenceFrame); property.intervals.addInterval(combinedInterval); } else { //Otherwise, create a CompositePositionProperty but preserve the existing data. @@ -657,7 +694,6 @@ define([ interval.data = property; //Create the composite. - propertyCreated = true; property = new CompositePositionProperty(property.referenceFrame); object[propertyName] = property; @@ -665,16 +701,15 @@ define([ property.intervals.addInterval(interval); //Change the new data to a ConstantPositionProperty and add it. - combinedInterval.data = new ConstantPositionProperty(combinedInterval.data, referenceFrame); + combinedInterval.data = isReference ? combinedInterval.data : new ConstantPositionProperty(combinedInterval.data, referenceFrame); property.intervals.addInterval(combinedInterval); } - return propertyCreated; + return; } //isSampled && hasInterval if (!defined(property)) { - propertyCreated = true; property = new CompositePositionProperty(referenceFrame); object[propertyName] = property; } else if (!(property instanceof CompositePositionProperty)) { @@ -684,7 +719,6 @@ define([ interval.data = property; //Create the composite. - propertyCreated = true; property = new CompositePositionProperty(property.referenceFrame); object[propertyName] = property; @@ -703,24 +737,23 @@ define([ } interval.data.addSamplesPackedArray(unwrappedInterval, epoch); updateInterpolationSettings(packetData, interval.data); - return propertyCreated; } - function processPositionPacketData(object, propertyName, packetData, interval, sourceUri) { + function processPositionPacketData(object, propertyName, packetData, interval, sourceUri, dynamicObjectCollection) { if (!defined(packetData)) { return; } if (isArray(packetData)) { for (var i = 0, len = packetData.length; i < len; i++) { - processPositionProperty(object, propertyName, packetData[i], interval, sourceUri); + processPositionProperty(object, propertyName, packetData[i], interval, sourceUri, dynamicObjectCollection); } } else { - processPositionProperty(object, propertyName, packetData, interval, sourceUri); + processPositionProperty(object, propertyName, packetData, interval, sourceUri, dynamicObjectCollection); } } - function processMaterialProperty(object, propertyName, packetData, constrainedInterval, sourceUri) { + function processMaterialProperty(object, propertyName, packetData, constrainedInterval, sourceUri, dynamicObjectCollection) { var combinedInterval; var packetInterval = packetData.interval; if (defined(packetInterval)) { @@ -763,34 +796,34 @@ define([ existingMaterial = new ColorMaterialProperty(); } materialData = packetData.solidColor; - processPacketData(Color, existingMaterial, 'color', materialData.color); + processPacketData(Color, existingMaterial, 'color', materialData.color, undefined, undefined, dynamicObjectCollection); } else if (defined(packetData.grid)) { if (!(existingMaterial instanceof GridMaterialProperty)) { existingMaterial = new GridMaterialProperty(); } materialData = packetData.grid; - processPacketData(Color, existingMaterial, 'color', materialData.color, undefined, sourceUri); - processPacketData(Number, existingMaterial, 'cellAlpha', materialData.cellAlpha, undefined, sourceUri); - existingMaterial.lineThickness = combineIntoCartesian2(existingMaterial.lineThickness, materialData.rowThickness, materialData.columnThickness); - existingMaterial.lineOffset = combineIntoCartesian2(existingMaterial.lineOffset, materialData.rowOffset, materialData.columnOffset); - existingMaterial.lineCount = combineIntoCartesian2(existingMaterial.lineCount, materialData.rowCount, materialData.columnCount); + processPacketData(Color, existingMaterial, 'color', materialData.color, undefined, sourceUri, dynamicObjectCollection); + processPacketData(Number, existingMaterial, 'cellAlpha', materialData.cellAlpha, undefined, sourceUri, dynamicObjectCollection); + existingMaterial.lineThickness = combineIntoCartesian2(existingMaterial.lineThickness, materialData.rowThickness, materialData.columnThickness, undefined, undefined, dynamicObjectCollection); + existingMaterial.lineOffset = combineIntoCartesian2(existingMaterial.lineOffset, materialData.rowOffset, materialData.columnOffset, undefined, undefined, dynamicObjectCollection); + existingMaterial.lineCount = combineIntoCartesian2(existingMaterial.lineCount, materialData.rowCount, materialData.columnCount, undefined, undefined, dynamicObjectCollection); } else if (defined(packetData.image)) { if (!(existingMaterial instanceof ImageMaterialProperty)) { existingMaterial = new ImageMaterialProperty(); } materialData = packetData.image; - processPacketData(Image, existingMaterial, 'image', materialData.image, undefined, sourceUri); + processPacketData(Image, existingMaterial, 'image', materialData.image, undefined, sourceUri, dynamicObjectCollection); existingMaterial.repeat = combineIntoCartesian2(existingMaterial.repeat, materialData.horizontalRepeat, materialData.verticalRepeat); } else if (defined(packetData.stripe)) { if (!(existingMaterial instanceof StripeMaterialProperty)) { existingMaterial = new StripeMaterialProperty(); } materialData = packetData.stripe; - processPacketData(StripeOrientation, existingMaterial, 'orientation', materialData.orientation, undefined, sourceUri); - processPacketData(Color, existingMaterial, 'evenColor', materialData.evenColor, undefined, sourceUri); - processPacketData(Color, existingMaterial, 'oddColor', materialData.oddColor, undefined, sourceUri); - processPacketData(Number, existingMaterial, 'offset', materialData.offset, undefined, sourceUri); - processPacketData(Number, existingMaterial, 'repeat', materialData.repeat, undefined, sourceUri); + processPacketData(StripeOrientation, existingMaterial, 'orientation', materialData.orientation, undefined, sourceUri, dynamicObjectCollection); + processPacketData(Color, existingMaterial, 'evenColor', materialData.evenColor, undefined, sourceUri, dynamicObjectCollection); + processPacketData(Color, existingMaterial, 'oddColor', materialData.oddColor, undefined, sourceUri, dynamicObjectCollection); + processPacketData(Number, existingMaterial, 'offset', materialData.offset, undefined, sourceUri, dynamicObjectCollection); + processPacketData(Number, existingMaterial, 'repeat', materialData.repeat, undefined, sourceUri, dynamicObjectCollection); } if (defined(existingInterval)) { @@ -800,17 +833,17 @@ define([ } } - function processMaterialPacketData(object, propertyName, packetData, interval, sourceUri) { + function processMaterialPacketData(object, propertyName, packetData, interval, sourceUri, dynamicObjectCollection) { if (!defined(packetData)) { return; } if (isArray(packetData)) { for (var i = 0, len = packetData.length; i < len; i++) { - processMaterialProperty(object, propertyName, packetData[i], interval, sourceUri); + processMaterialProperty(object, propertyName, packetData[i], interval, sourceUri, dynamicObjectCollection); } } else { - processMaterialProperty(object, propertyName, packetData, interval, sourceUri); + processMaterialProperty(object, propertyName, packetData, interval, sourceUri, dynamicObjectCollection); } } @@ -821,28 +854,28 @@ define([ function processDescription(dynamicObject, packet, dynamicObjectCollection, sourceUri) { var descriptionData = packet.description; if (defined(descriptionData)) { - processPacketData(String, dynamicObject, 'description', descriptionData, undefined, sourceUri); + processPacketData(String, dynamicObject, 'description', descriptionData, undefined, sourceUri, dynamicObjectCollection); } } function processPosition(dynamicObject, packet, dynamicObjectCollection, sourceUri) { var positionData = packet.position; if (defined(positionData)) { - processPositionPacketData(dynamicObject, 'position', positionData, undefined, sourceUri); + processPositionPacketData(dynamicObject, 'position', positionData, undefined, sourceUri, dynamicObjectCollection); } } function processViewFrom(dynamicObject, packet, dynamicObjectCollection, sourceUri) { var viewFromData = packet.viewFrom; if (defined(viewFromData)) { - processPacketData(Cartesian3, dynamicObject, 'viewFrom', viewFromData, undefined, sourceUri); + processPacketData(Cartesian3, dynamicObject, 'viewFrom', viewFromData, undefined, sourceUri, dynamicObjectCollection); } } function processOrientation(dynamicObject, packet, dynamicObjectCollection, sourceUri) { var orientationData = packet.orientation; if (defined(orientationData)) { - processPacketData(Quaternion, dynamicObject, 'orientation', orientationData, undefined, sourceUri); + processPacketData(Quaternion, dynamicObject, 'orientation', orientationData, undefined, sourceUri, dynamicObjectCollection); } } @@ -853,7 +886,7 @@ define([ if (defined(references)) { var properties = []; for (i = 0, len = references.length; i < len; i++) { - properties.push(ReferenceProperty.fromString(dynamicObjectCollection, references[i])); + properties.push(makeReference(dynamicObjectCollection, references[i])); } var iso8601Interval = vertexPositionsData.interval; @@ -896,7 +929,7 @@ define([ } } if (defined(vertexPositionsData.array)) { - processPacketData(Array, dynamicObject, 'vertexPositions', vertexPositionsData); + processPacketData(Array, dynamicObject, 'vertexPositions', vertexPositionsData, undefined, undefined, dynamicObjectCollection); } } } @@ -958,16 +991,16 @@ define([ dynamicObject.billboard = billboard = new DynamicBillboard(); } - processPacketData(Color, billboard, 'color', billboardData.color, interval, sourceUri); - processPacketData(Cartesian3, billboard, 'eyeOffset', billboardData.eyeOffset, interval, sourceUri); - processPacketData(HorizontalOrigin, billboard, 'horizontalOrigin', billboardData.horizontalOrigin, interval, sourceUri); - processPacketData(Image, billboard, 'image', billboardData.image, interval, sourceUri); - processPacketData(Cartesian2, billboard, 'pixelOffset', billboardData.pixelOffset, interval, sourceUri); - processPacketData(Number, billboard, 'scale', billboardData.scale, interval, sourceUri); - processPacketData(Number, billboard, 'rotation', billboardData.rotation, interval, sourceUri); - processPacketData(Cartesian3, billboard, 'alignedAxis', billboardData.alignedAxis, interval, sourceUri); - processPacketData(Boolean, billboard, 'show', billboardData.show, interval, sourceUri); - processPacketData(VerticalOrigin, billboard, 'verticalOrigin', billboardData.verticalOrigin, interval, sourceUri); + processPacketData(Color, billboard, 'color', billboardData.color, interval, sourceUri, dynamicObjectCollection); + processPacketData(Cartesian3, billboard, 'eyeOffset', billboardData.eyeOffset, interval, sourceUri, dynamicObjectCollection); + processPacketData(HorizontalOrigin, billboard, 'horizontalOrigin', billboardData.horizontalOrigin, interval, sourceUri, dynamicObjectCollection); + processPacketData(Image, billboard, 'image', billboardData.image, interval, sourceUri, dynamicObjectCollection); + processPacketData(Cartesian2, billboard, 'pixelOffset', billboardData.pixelOffset, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, billboard, 'scale', billboardData.scale, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, billboard, 'rotation', billboardData.rotation, interval, sourceUri, dynamicObjectCollection); + processPacketData(Cartesian3, billboard, 'alignedAxis', billboardData.alignedAxis, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, billboard, 'show', billboardData.show, interval, sourceUri, dynamicObjectCollection); + processPacketData(VerticalOrigin, billboard, 'verticalOrigin', billboardData.verticalOrigin, interval, sourceUri, dynamicObjectCollection); } function processClock(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1021,19 +1054,19 @@ define([ dynamicObject.cone = cone = new DynamicCone(); } - processPacketData(Boolean, cone, 'show', coneData.show, interval, sourceUri); - processPacketData(Number, cone, 'radius', coneData.radius, interval, sourceUri); - processPacketData(Boolean, cone, 'showIntersection', coneData.showIntersection, interval, sourceUri); - processPacketData(Color, cone, 'intersectionColor', coneData.intersectionColor, interval, sourceUri); - processPacketData(Number, cone, 'intersectionWidth', coneData.intersectionWidth, interval, sourceUri); - processPacketData(Number, cone, 'innerHalfAngle', coneData.innerHalfAngle, interval, sourceUri); - processPacketData(Number, cone, 'outerHalfAngle', coneData.outerHalfAngle, interval, sourceUri); - processPacketData(Number, cone, 'minimumClockAngle', coneData.minimumClockAngle, interval, sourceUri); - processPacketData(Number, cone, 'maximumClockAngle', coneData.maximumClockAngle, interval, sourceUri); - processMaterialPacketData(cone, 'capMaterial', coneData.capMaterial, interval, sourceUri); - processMaterialPacketData(cone, 'innerMaterial', coneData.innerMaterial, interval, sourceUri); - processMaterialPacketData(cone, 'outerMaterial', coneData.outerMaterial, interval, sourceUri); - processMaterialPacketData(cone, 'silhouetteMaterial', coneData.silhouetteMaterial, interval, sourceUri); + processPacketData(Boolean, cone, 'show', coneData.show, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, cone, 'radius', coneData.radius, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, cone, 'showIntersection', coneData.showIntersection, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, cone, 'intersectionColor', coneData.intersectionColor, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, cone, 'intersectionWidth', coneData.intersectionWidth, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, cone, 'innerHalfAngle', coneData.innerHalfAngle, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, cone, 'outerHalfAngle', coneData.outerHalfAngle, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, cone, 'minimumClockAngle', coneData.minimumClockAngle, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, cone, 'maximumClockAngle', coneData.maximumClockAngle, interval, sourceUri, dynamicObjectCollection); + processMaterialPacketData(cone, 'capMaterial', coneData.capMaterial, interval, sourceUri, dynamicObjectCollection); + processMaterialPacketData(cone, 'innerMaterial', coneData.innerMaterial, interval, sourceUri, dynamicObjectCollection); + processMaterialPacketData(cone, 'outerMaterial', coneData.outerMaterial, interval, sourceUri, dynamicObjectCollection); + processMaterialPacketData(cone, 'silhouetteMaterial', coneData.silhouetteMaterial, interval, sourceUri, dynamicObjectCollection); } function processEllipse(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1052,19 +1085,19 @@ define([ dynamicObject.ellipse = ellipse = new DynamicEllipse(); } - processPacketData(Boolean, ellipse, 'show', ellipseData.show, interval, sourceUri); - processPacketData(Number, ellipse, 'rotation', ellipseData.rotation, interval, sourceUri); - processPacketData(Number, ellipse, 'semiMajorAxis', ellipseData.semiMajorAxis, interval, sourceUri); - processPacketData(Number, ellipse, 'semiMinorAxis', ellipseData.semiMinorAxis, interval, sourceUri); - processPacketData(Number, ellipse, 'height', ellipseData.height, interval, sourceUri); - processPacketData(Number, ellipse, 'extrudedHeight', ellipseData.extrudedHeight, interval, sourceUri); - processPacketData(Number, ellipse, 'granularity', ellipseData.granularity, interval, sourceUri); - processPacketData(Number, ellipse, 'stRotation', ellipseData.stRotation, interval, sourceUri); - processMaterialPacketData(ellipse, 'material', ellipseData.material, interval, sourceUri); - processPacketData(Boolean, ellipse, 'fill', ellipseData.fill, interval, sourceUri); - processPacketData(Boolean, ellipse, 'outline', ellipseData.outline, interval, sourceUri); - processPacketData(Color, ellipse, 'outlineColor', ellipseData.outlineColor, interval, sourceUri); - processPacketData(Number, ellipse, 'numberOfVerticalLines', ellipseData.numberOfVerticalLines, interval, sourceUri); + processPacketData(Boolean, ellipse, 'show', ellipseData.show, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, ellipse, 'rotation', ellipseData.rotation, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, ellipse, 'semiMajorAxis', ellipseData.semiMajorAxis, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, ellipse, 'semiMinorAxis', ellipseData.semiMinorAxis, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, ellipse, 'height', ellipseData.height, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, ellipse, 'extrudedHeight', ellipseData.extrudedHeight, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, ellipse, 'granularity', ellipseData.granularity, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, ellipse, 'stRotation', ellipseData.stRotation, interval, sourceUri, dynamicObjectCollection); + processMaterialPacketData(ellipse, 'material', ellipseData.material, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, ellipse, 'fill', ellipseData.fill, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, ellipse, 'outline', ellipseData.outline, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, ellipse, 'outlineColor', ellipseData.outlineColor, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, ellipse, 'numberOfVerticalLines', ellipseData.numberOfVerticalLines, interval, sourceUri, dynamicObjectCollection); } function processEllipsoid(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1083,12 +1116,12 @@ define([ dynamicObject.ellipsoid = ellipsoid = new DynamicEllipsoid(); } - processPacketData(Boolean, ellipsoid, 'show', ellipsoidData.show, interval, sourceUri); - processPacketData(Cartesian3, ellipsoid, 'radii', ellipsoidData.radii, interval, sourceUri); - processMaterialPacketData(ellipsoid, 'material', ellipsoidData.material, interval, sourceUri); - processPacketData(Boolean, ellipsoid, 'fill', ellipsoidData.fill, interval, sourceUri); - processPacketData(Boolean, ellipsoid, 'outline', ellipsoidData.outline, interval, sourceUri); - processPacketData(Color, ellipsoid, 'outlineColor', ellipsoidData.outlineColor, interval, sourceUri); + processPacketData(Boolean, ellipsoid, 'show', ellipsoidData.show, interval, sourceUri, dynamicObjectCollection); + processPacketData(Cartesian3, ellipsoid, 'radii', ellipsoidData.radii, interval, sourceUri, dynamicObjectCollection); + processMaterialPacketData(ellipsoid, 'material', ellipsoidData.material, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, ellipsoid, 'fill', ellipsoidData.fill, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, ellipsoid, 'outline', ellipsoidData.outline, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, ellipsoid, 'outlineColor', ellipsoidData.outlineColor, interval, sourceUri, dynamicObjectCollection); } function processLabel(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1107,18 +1140,18 @@ define([ dynamicObject.label = label = new DynamicLabel(); } - processPacketData(Color, label, 'fillColor', labelData.fillColor, interval, sourceUri); - processPacketData(Color, label, 'outlineColor', labelData.outlineColor, interval, sourceUri); - processPacketData(Number, label, 'outlineWidth', labelData.outlineWidth, interval, sourceUri); - processPacketData(Cartesian3, label, 'eyeOffset', labelData.eyeOffset, interval, sourceUri); - processPacketData(HorizontalOrigin, label, 'horizontalOrigin', labelData.horizontalOrigin, interval, sourceUri); - processPacketData(String, label, 'text', labelData.text, interval, sourceUri); - processPacketData(Cartesian2, label, 'pixelOffset', labelData.pixelOffset, interval, sourceUri); - processPacketData(Number, label, 'scale', labelData.scale, interval, sourceUri); - processPacketData(Boolean, label, 'show', labelData.show, interval, sourceUri); - processPacketData(VerticalOrigin, label, 'verticalOrigin', labelData.verticalOrigin, interval, sourceUri); - processPacketData(String, label, 'font', labelData.font, interval, sourceUri); - processPacketData(LabelStyle, label, 'style', labelData.style, interval, sourceUri); + processPacketData(Color, label, 'fillColor', labelData.fillColor, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, label, 'outlineColor', labelData.outlineColor, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, label, 'outlineWidth', labelData.outlineWidth, interval, sourceUri, dynamicObjectCollection); + processPacketData(Cartesian3, label, 'eyeOffset', labelData.eyeOffset, interval, sourceUri, dynamicObjectCollection); + processPacketData(HorizontalOrigin, label, 'horizontalOrigin', labelData.horizontalOrigin, interval, sourceUri, dynamicObjectCollection); + processPacketData(String, label, 'text', labelData.text, interval, sourceUri, dynamicObjectCollection); + processPacketData(Cartesian2, label, 'pixelOffset', labelData.pixelOffset, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, label, 'scale', labelData.scale, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, label, 'show', labelData.show, interval, sourceUri, dynamicObjectCollection); + processPacketData(VerticalOrigin, label, 'verticalOrigin', labelData.verticalOrigin, interval, sourceUri, dynamicObjectCollection); + processPacketData(String, label, 'font', labelData.font, interval, sourceUri, dynamicObjectCollection); + processPacketData(LabelStyle, label, 'style', labelData.style, interval, sourceUri, dynamicObjectCollection); } function processModel(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1137,10 +1170,10 @@ define([ dynamicObject.model = model = new DynamicModel(); } - processPacketData(Boolean, model, 'show', modelData.show, interval, sourceUri); - processPacketData(Number, model, 'scale', modelData.scale, interval, sourceUri); - processPacketData(Number, model, 'minimumPixelSize', modelData.minimumPixelSize, interval, sourceUri); - processPacketData(Uri, model, 'uri', modelData.gltf, interval, sourceUri); + processPacketData(Boolean, model, 'show', modelData.show, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, model, 'scale', modelData.scale, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, model, 'minimumPixelSize', modelData.minimumPixelSize, interval, sourceUri, dynamicObjectCollection); + processPacketData(Uri, model, 'uri', modelData.gltf, interval, sourceUri, dynamicObjectCollection); } function processPath(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1187,14 +1220,14 @@ define([ path.material = materialToProcess; } - processPacketData(Boolean, path, 'show', pathData.show, interval, sourceUri); - processPacketData(Number, path, 'width', pathData.width, interval, sourceUri); - processPacketData(Number, path, 'resolution', pathData.resolution, interval, sourceUri); - processPacketData(Number, path, 'leadTime', pathData.leadTime, interval, sourceUri); - processPacketData(Number, path, 'trailTime', pathData.trailTime, interval, sourceUri); - processPacketData(Color, materialToProcess, 'color', pathData.color, interval, sourceUri); - processPacketData(Color, materialToProcess, 'outlineColor', pathData.outlineColor, interval, sourceUri); - processPacketData(Number, materialToProcess, 'outlineWidth', pathData.outlineWidth, interval, sourceUri); + processPacketData(Boolean, path, 'show', pathData.show, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, path, 'width', pathData.width, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, path, 'resolution', pathData.resolution, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, path, 'leadTime', pathData.leadTime, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, path, 'trailTime', pathData.trailTime, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, materialToProcess, 'color', pathData.color, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, materialToProcess, 'outlineColor', pathData.outlineColor, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, materialToProcess, 'outlineWidth', pathData.outlineWidth, interval, sourceUri, dynamicObjectCollection); } function processPoint(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1213,11 +1246,11 @@ define([ dynamicObject.point = point = new DynamicPoint(); } - processPacketData(Color, point, 'color', pointData.color, interval, sourceUri); - processPacketData(Number, point, 'pixelSize', pointData.pixelSize, interval, sourceUri); - processPacketData(Color, point, 'outlineColor', pointData.outlineColor, interval, sourceUri); - processPacketData(Number, point, 'outlineWidth', pointData.outlineWidth, interval, sourceUri); - processPacketData(Boolean, point, 'show', pointData.show, interval, sourceUri); + processPacketData(Color, point, 'color', pointData.color, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, point, 'pixelSize', pointData.pixelSize, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, point, 'outlineColor', pointData.outlineColor, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, point, 'outlineWidth', pointData.outlineWidth, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, point, 'show', pointData.show, interval, sourceUri, dynamicObjectCollection); } function processPolygon(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1236,16 +1269,16 @@ define([ dynamicObject.polygon = polygon = new DynamicPolygon(); } - processPacketData(Boolean, polygon, 'show', polygonData.show, interval, sourceUri); - processMaterialPacketData(polygon, 'material', polygonData.material, interval, sourceUri); - processPacketData(Number, polygon, 'height', polygonData.height, interval, sourceUri); - processPacketData(Number, polygon, 'extrudedHeight', polygonData.extrudedHeight, interval, sourceUri); - processPacketData(Number, polygon, 'granularity', polygonData.granularity, interval, sourceUri); - processPacketData(Number, polygon, 'stRotation', polygonData.stRotation, interval, sourceUri); - processPacketData(Boolean, polygon, 'fill', polygonData.fill, interval, sourceUri); - processPacketData(Boolean, polygon, 'outline', polygonData.outline, interval, sourceUri); - processPacketData(Color, polygon, 'outlineColor', polygonData.outlineColor, interval, sourceUri); - processPacketData(Boolean, polygon, 'perPositionHeight', polygonData.perPositionHeight, interval, sourceUri); + processPacketData(Boolean, polygon, 'show', polygonData.show, interval, sourceUri, dynamicObjectCollection); + processMaterialPacketData(polygon, 'material', polygonData.material, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, polygon, 'height', polygonData.height, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, polygon, 'extrudedHeight', polygonData.extrudedHeight, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, polygon, 'granularity', polygonData.granularity, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, polygon, 'stRotation', polygonData.stRotation, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, polygon, 'fill', polygonData.fill, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, polygon, 'outline', polygonData.outline, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, polygon, 'outlineColor', polygonData.outlineColor, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, polygon, 'perPositionHeight', polygonData.perPositionHeight, interval, sourceUri, dynamicObjectCollection); } function processRectangle(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1264,19 +1297,19 @@ define([ dynamicObject.rectangle = rectangle = new DynamicRectangle(); } - processPacketData(Boolean, rectangle, 'show', rectangleData.show, interval, sourceUri); - processPacketData(Rectangle, rectangle, 'coordinates', rectangleData.coordinates, interval, sourceUri); - processMaterialPacketData(rectangle, 'material', rectangleData.material, interval, sourceUri); - processPacketData(Number, rectangle, 'height', rectangleData.height, interval, sourceUri); - processPacketData(Number, rectangle, 'extrudedHeight', rectangleData.extrudedHeight, interval, sourceUri); - processPacketData(Number, rectangle, 'granularity', rectangleData.granularity, interval, sourceUri); - processPacketData(Number, rectangle, 'rotation', rectangleData.rotation, interval, sourceUri); - processPacketData(Number, rectangle, 'stRotation', rectangleData.stRotation, interval, sourceUri); - processPacketData(Boolean, rectangle, 'fill', rectangleData.fill, interval, sourceUri); - processPacketData(Boolean, rectangle, 'outline', rectangleData.outline, interval, sourceUri); - processPacketData(Color, rectangle, 'outlineColor', rectangleData.outlineColor, interval, sourceUri); - processPacketData(Boolean, rectangle, 'closeBottom', rectangleData.closeBottom, interval, sourceUri); - processPacketData(Boolean, rectangle, 'closeTop', rectangleData.closeTop, interval, sourceUri); + processPacketData(Boolean, rectangle, 'show', rectangleData.show, interval, sourceUri, dynamicObjectCollection); + processPacketData(Rectangle, rectangle, 'coordinates', rectangleData.coordinates, interval, sourceUri, dynamicObjectCollection); + processMaterialPacketData(rectangle, 'material', rectangleData.material, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, rectangle, 'height', rectangleData.height, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, rectangle, 'extrudedHeight', rectangleData.extrudedHeight, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, rectangle, 'granularity', rectangleData.granularity, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, rectangle, 'rotation', rectangleData.rotation, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, rectangle, 'stRotation', rectangleData.stRotation, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, rectangle, 'fill', rectangleData.fill, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, rectangle, 'outline', rectangleData.outline, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, rectangle, 'outlineColor', rectangleData.outlineColor, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, rectangle, 'closeBottom', rectangleData.closeBottom, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, rectangle, 'closeTop', rectangleData.closeTop, interval, sourceUri, dynamicObjectCollection); } function processWall(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1295,14 +1328,14 @@ define([ dynamicObject.wall = wall = new DynamicWall(); } - processPacketData(Boolean, wall, 'show', wallData.show, interval, sourceUri); - processMaterialPacketData(wall, 'material', wallData.material, interval, sourceUri); - processPacketData(Array, wall, 'minimumHeights', wallData.minimumHeights, interval, sourceUri); - processPacketData(Array, wall, 'maximumHeights', wallData.maximumHeights, interval, sourceUri); - processPacketData(Number, wall, 'granularity', wallData.granularity, interval, sourceUri); - processPacketData(Boolean, wall, 'fill', wallData.fill, interval, sourceUri); - processPacketData(Boolean, wall, 'outline', wallData.outline, interval, sourceUri); - processPacketData(Color, wall, 'outlineColor', wallData.outlineColor, interval, sourceUri); + processPacketData(Boolean, wall, 'show', wallData.show, interval, sourceUri, dynamicObjectCollection); + processMaterialPacketData(wall, 'material', wallData.material, interval, sourceUri, dynamicObjectCollection); + processPacketData(Array, wall, 'minimumHeights', wallData.minimumHeights, interval, sourceUri, dynamicObjectCollection); + processPacketData(Array, wall, 'maximumHeights', wallData.maximumHeights, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, wall, 'granularity', wallData.granularity, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, wall, 'fill', wallData.fill, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, wall, 'outline', wallData.outline, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, wall, 'outlineColor', wallData.outlineColor, interval, sourceUri, dynamicObjectCollection); } function processPolyline(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1349,14 +1382,14 @@ define([ polyline.material = materialToProcess; } - processPacketData(Boolean, polyline, 'show', polylineData.show, interval, sourceUri); - processPacketData(Number, polyline, 'width', polylineData.width, interval, sourceUri); - processPacketData(Color, materialToProcess, 'color', polylineData.color, interval, sourceUri); - processPacketData(Color, materialToProcess, 'outlineColor', polylineData.outlineColor, interval, sourceUri); - processPacketData(Number, materialToProcess, 'outlineWidth', polylineData.outlineWidth, interval, sourceUri); + processPacketData(Boolean, polyline, 'show', polylineData.show, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, polyline, 'width', polylineData.width, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, materialToProcess, 'color', polylineData.color, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, materialToProcess, 'outlineColor', polylineData.outlineColor, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, materialToProcess, 'outlineWidth', polylineData.outlineWidth, interval, sourceUri, dynamicObjectCollection); } - function processDirectionData(pyramid, directions, interval, sourceUri) { + function processDirectionData(pyramid, directions, interval, sourceUri, dynamicObjectCollection) { var i; var len; var values = []; @@ -1375,7 +1408,7 @@ define([ } directions.array = values; } - processPacketData(Array, pyramid, 'directions', directions, interval, sourceUri); + processPacketData(Array, pyramid, 'directions', directions, interval, sourceUri, dynamicObjectCollection); } function processPyramid(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1394,12 +1427,12 @@ define([ dynamicObject.pyramid = pyramid = new DynamicPyramid(); } - processPacketData(Boolean, pyramid, 'show', pyramidData.show, interval, sourceUri); - processPacketData(Number, pyramid, 'radius', pyramidData.radius, interval, sourceUri); - processPacketData(Boolean, pyramid, 'showIntersection', pyramidData.showIntersection, interval, sourceUri); - processPacketData(Color, pyramid, 'intersectionColor', pyramidData.intersectionColor, interval, sourceUri); - processPacketData(Number, pyramid, 'intersectionWidth', pyramidData.intersectionWidth, interval, sourceUri); - processMaterialPacketData(pyramid, 'material', pyramidData.material, interval, sourceUri); + processPacketData(Boolean, pyramid, 'show', pyramidData.show, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, pyramid, 'radius', pyramidData.radius, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, pyramid, 'showIntersection', pyramidData.showIntersection, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, pyramid, 'intersectionColor', pyramidData.intersectionColor, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, pyramid, 'intersectionWidth', pyramidData.intersectionWidth, interval, sourceUri, dynamicObjectCollection); + processMaterialPacketData(pyramid, 'material', pyramidData.material, interval, sourceUri, dynamicObjectCollection); //The directions property is a special case value that can be an array of unitSpherical or unit Cartesians. //We pre-process this into Spherical instances and then process it like any other array. @@ -1408,10 +1441,10 @@ define([ if (isArray(directions)) { var length = directions.length; for (var i = 0; i < length; i++) { - processDirectionData(pyramid, directions[i], interval, sourceUri); + processDirectionData(pyramid, directions[i], interval, sourceUri, dynamicObjectCollection); } } else { - processDirectionData(pyramid, directions, interval, sourceUri); + processDirectionData(pyramid, directions, interval, sourceUri, dynamicObjectCollection); } } } @@ -1432,11 +1465,11 @@ define([ dynamicObject.vector = vector = new DynamicVector(); } - processPacketData(Color, vector, 'color', vectorData.color, interval, sourceUri); - processPacketData(Boolean, vector, 'show', vectorData.show, interval, sourceUri); - processPacketData(Number, vector, 'width', vectorData.width, interval, sourceUri); - processPacketData(Cartesian3, vector, 'direction', vectorData.direction, interval, sourceUri); - processPacketData(Number, vector, 'length', vectorData.length, interval, sourceUri); + processPacketData(Color, vector, 'color', vectorData.color, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, vector, 'show', vectorData.show, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, vector, 'width', vectorData.width, interval, sourceUri, dynamicObjectCollection); + processPacketData(Cartesian3, vector, 'direction', vectorData.direction, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, vector, 'length', vectorData.length, interval, sourceUri, dynamicObjectCollection); } function processCzmlPacket(packet, dynamicObjectCollection, updaterFunctions, sourceUri, dataSource) { @@ -1445,6 +1478,8 @@ define([ objectId = createGuid(); } + currentId = objectId; + if (packet['delete'] === true) { dynamicObjectCollection.removeById(objectId); } else { @@ -1464,6 +1499,8 @@ define([ updaterFunctions[i](dynamicObject, packet, dynamicObjectCollection, sourceUri); } } + + currentId = undefined; } function loadCzml(dataSource, czml, sourceUri) { @@ -1747,10 +1784,10 @@ define([ * @param {Function} type The constructor function for the property being processed. * @param {Object} object The object on which the property will be added or updated. * @param {String} propertyName The name of the property on the object. - * @param {Object} packetData The CZML packet being processed.y - * @param {TimeInterval} [interval] A constraining interval for which the data is valid. - * @param {String} [sourceUri] The originating uri of the data being processed. - * @returns {Boolean} True if a new property was created, false otherwise. + * @param {Object} packetData The CZML packet being processed. + * @param {TimeInterval} interval A constraining interval for which the data is valid. + * @param {String} sourceUri The originating uri of the data being processed. + * @param {DynamicObjectCollection} dynamicObjectCollection The collection being processsed. */ CzmlDataSource.processPacketData = processPacketData; @@ -1761,10 +1798,10 @@ define([ * * @param {Object} object The object on which the property will be added or updated. * @param {String} propertyName The name of the property on the object. - * @param {Object} packetData The CZML packet being processed.y - * @param {TimeInterval} [interval] A constraining interval for which the data is valid. - * @param {String} [sourceUri] The originating uri of the data being processed. - * @returns {Boolean} True if a new property was created, false otherwise. + * @param {Object} packetData The CZML packet being processed. + * @param {TimeInterval} interval A constraining interval for which the data is valid. + * @param {String} sourceUri The originating uri of the data being processed. + * @param {DynamicObjectCollection} dynamicObjectCollection The collection being processsed. */ CzmlDataSource.processPositionPacketData = processPositionPacketData; @@ -1775,10 +1812,10 @@ define([ * * @param {Object} object The object on which the property will be added or updated. * @param {String} propertyName The name of the property on the object. - * @param {Object} packetData The CZML packet being processed.y - * @param {TimeInterval} [interval] A constraining interval for which the data is valid. - * @param {String} [sourceUri] The originating uri of the data being processed. - * @returns {Boolean} True if a new property was created, false otherwise. + * @param {Object} packetData The CZML packet being processed. + * @param {TimeInterval} interval A constraining interval for which the data is valid. + * @param {String} sourceUri The originating uri of the data being processed. + * @param {DynamicObjectCollection} dynamicObjectCollection The collection being processsed. */ CzmlDataSource.processMaterialPacketData = processMaterialPacketData; diff --git a/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index ed904615ab78..668ab0d02e81 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -3,26 +3,46 @@ define([ '../Core/defined', '../Core/defineProperties', '../Core/DeveloperError', + '../Core/RuntimeError', '../Core/Event', './Property' ], function( defined, defineProperties, DeveloperError, + RuntimeError, Event, Property) { "use strict"; - function resolve(referenceProperty) { - var targetProperty = referenceProperty._targetProperty; + function resolve(that) { + var targetProperty = that._targetProperty; if (!defined(targetProperty)) { - var resolveBuffer = referenceProperty._dynamicObjectCollection; - var targetObject = resolveBuffer.getById(referenceProperty._targetObjectId); - if (defined(targetObject)) { - targetProperty = targetObject[referenceProperty._targetPropertyName]; - referenceProperty._targetProperty = targetProperty; - referenceProperty._targetObject = targetObject; + var targetObject = that._targetObject; + + if (!defined(targetObject)) { + var targetCollection = that._targetCollection; + + targetObject = targetCollection.getById(that._targetId); + if (!defined(targetObject)) { + throw new RuntimeError('target object could not be resolved.'); + } + targetObject.definitionChanged.addEventListener(ReferenceProperty.prototype._onTargetObjectDefinitionChanged, that); + that._targetObject = targetObject; + } + + var names = that._targetPropertyNames; + + targetProperty = targetObject; + var length = names.length; + for (var i = 0; i < length; i++) { + targetProperty = targetProperty[names[i]]; + if (!defined(targetProperty)) { + throw new RuntimeError('targetProperty could not be resolved.'); + } } + + that._targetProperty = targetProperty; } return targetProperty; } @@ -33,37 +53,75 @@ define([ * @alias ReferenceProperty * @constructor * - * @param {DynamicObjectCollection} dynamicObjectCollection The object collection which will be used to resolve the reference. - * @param {String} targetObjectId The id of the object which is being referenced. - * @param {String} targetPropertyName The name of the property on the target object which we will use. + * @param {targetCollection} targetCollection The object collection which will be used to resolve the reference. + * @param {String} targetId The id of the object which is being referenced. + * @param {String} targetPropertyNames The name of the property on the target object which we will use. + * + * @example + * var collection = new Cesium.DynamicObjectCollection(); + * + * //Create a new object and assign a billboard scale. + * var object1 = new Cesium.DynamicObject('object1'); + * object1.billboard = new Cesium.DynamicBillboard(); + * object1.billboard.scale = new ConstantProperty(2.0); + * collection.add(object1); + * + * //Create a second object and reference the scale from the first one. + * var object2 = new Cesium.DynamicObject('object2'); + * object2.model = new Cesium.DynamicModel(); + * object2.model.scale = new Cesium.ReferenceProperty(collection, 'object1', ['billboard', 'scale']); + * collection.add(object2); + * + * //Create a third object, but use the fromString helper function. + * var object3 = new Cesium.DynamicObject('object3'); + * object3.billboard = new Cesium.DynamicBillboard(); + * object3.billboard.scale = Cesium.ReferenceProperty.fromString(collection, 'object1#billboard.scale']); + * collection.add(object3); + * + * //You can refer to an object with a # or . in id and property names by escaping them. + * var object4 = new Cesium.DynamicObject('#object.4'); + * object4.billboard = new Cesium.DynamicBillboard(); + * object4.billboard.scale = new ConstantProperty(2.0); + * collection.add(object4); + * + * var object5 = new Cesium.DynamicObject('object5'); + * object5.billboard = new Cesium.DynamicBillboard(); + * object5.billboard.scale = Cesium.ReferenceProperty.fromString(collection, '\\#object\\.4#billboard.scale'); + * collection.add(object5); */ - var ReferenceProperty = function(dynamicObjectCollection, targetObjectId, targetPropertyName) { + var ReferenceProperty = function(targetCollection, targetId, targetPropertyNames) { //>>includeStart('debug', pragmas.debug); - if (!defined(dynamicObjectCollection)) { - throw new DeveloperError('dynamicObjectCollection is required.'); + if (!defined(targetCollection)) { + throw new DeveloperError('targetCollection is required.'); } - if (!defined(targetObjectId)) { - throw new DeveloperError('targetObjectId is required.'); + if (!defined(targetId) || targetId === '') { + throw new DeveloperError('targetId is required.'); } - if (!defined(targetPropertyName)) { - throw new DeveloperError('targetPropertyName is required.'); + if (!defined(targetPropertyNames) || targetPropertyNames.length === 0) { + throw new DeveloperError('targetPropertyNames is required.'); + } + for (var i = 0; i < targetPropertyNames.length; i++) { + var item = targetPropertyNames[i]; + if (!defined(item) || item === '') { + throw new DeveloperError('reference contains invalid properties.'); + } } //>>includeEnd('debug'); + this._targetCollection = targetCollection; + this._targetId = targetId; + this._targetPropertyNames = targetPropertyNames; this._targetProperty = undefined; - this._dynamicObjectCollection = dynamicObjectCollection; - this._targetObjectId = targetObjectId; this._targetObject = undefined; - this._targetPropertyName = targetPropertyName; this._definitionChanged = new Event(); + + targetCollection.collectionChanged.addEventListener(ReferenceProperty.prototype._onCollectionChanged, this); }; defineProperties(ReferenceProperty.prototype, { /** * Gets a value indicating if this property is constant. - * This property always returns true. - * @memberof ConstantProperty.prototype - * + * @memberof ReferenceProperty.prototype * @type {Boolean} * @readonly */ @@ -74,10 +132,8 @@ define([ }, /** * Gets the event that is raised whenever the definition of this property changes. - * The definition is changed whenever setValue is called with data different - * than the current value. - * @memberof ConstantProperty.prototype - * + * The definition is changed whenever the referenced property's definition is changed. + * @memberof ReferenceProperty.prototype * @type {Event} * @readonly */ @@ -85,39 +141,105 @@ define([ get : function() { return this._definitionChanged; } + }, + /** + * Gets the reference frame that the position is defined in. + * This property is only valid if the referenced property is a {@link PositionProperty}. + * @memberof ReferenceProperty.prototype + * @Type {ReferenceFrame} + * @readonly + */ + referenceFrame : { + get : function() { + return resolve(this).referenceFrame; + } + }, + /** + * Gets the id of the object being referenced. + * @memberof ReferenceProperty.prototype + * @Type {String} + * @readonly + */ + targetId : { + get : function() { + return this._targetId; + } + }, + /** + * Gets the collection containing the object being referenced. + * @memberof ReferenceProperty.prototype + * @Type {DynamicObjectCollection} + * @readonly + */ + targetCollection : { + get : function() { + return this._targetCollection; + } + }, + /** + * Gets the array of property names used to retrieve the referenced property. + * @memberof ReferenceProperty.prototype + * @Type {String[]} + * @readonly + */ + targetPropertyNames : { + get : function() { + return this._targetPropertyNames; + } } }); /** - * Creates a new reference property given the dynamic object collection that will - * be used to resolve it and a string indicating the target object id and property, - * delineated by a period. + * Creates a new instance given the dynamic object collection that will + * be used to resolve it and a string indicating the target object id and property. + * The format of the string is "objectId#foo.bar", where # separates the id from + * property path and . separates sub-properties. If the reference identifier or + * or any sub-properties contains a # . or \ they must be escaped. * - * @param {DynamicObject} dynamicObjectCollection + * @param {DynamicObject} targetCollection * @param {String} referenceString * @returns A new instance of ReferenceProperty. * - * @exception {DeveloperError} referenceString must contain a single period delineating the target object ID and property name. + * @exception {DeveloperError} invalid referenceString. */ - ReferenceProperty.fromString = function(dynamicObjectCollection, referenceString) { + ReferenceProperty.fromString = function(targetCollection, referenceString) { //>>includeStart('debug', pragmas.debug); - if (!defined(dynamicObjectCollection)) { - throw new DeveloperError('dynamicObjectCollection is required.'); + if (!defined(targetCollection)) { + throw new DeveloperError('targetCollection is required.'); } if (!defined(referenceString)) { throw new DeveloperError('referenceString is required.'); } //>>includeEnd('debug'); - var parts = referenceString.split('.'); + var identifier; + var values = []; - //>>includeStart('debug', pragmas.debug); - if (parts.length !== 2) { - throw new DeveloperError('referenceString must contain a single . delineating the target object ID and property name.'); + var inIdentifier = true; + var isEscaped = false; + var token = ''; + for (var i = 0; i < referenceString.length; ++i) { + var c = referenceString.charAt(i); + + if (isEscaped) { + token += c; + isEscaped = false; + } else if (c === '\\') { + isEscaped = true; + } else if (inIdentifier && c === '#') { + identifier = token; + inIdentifier = false; + token = ''; + } else if (!inIdentifier && c === '.') { + values.push(token); + token = ''; + } else { + token += c; + } } - //>>includeEnd('debug'); + values.push(token); - return new ReferenceProperty(dynamicObjectCollection, parts[0], parts[1]); + return new ReferenceProperty(targetCollection, identifier, values); }; /** @@ -128,14 +250,7 @@ define([ * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied. */ ReferenceProperty.prototype.getValue = function(time, result) { - //>>includeStart('debug', pragmas.debug); - if (!defined(time)) { - throw new DeveloperError('time is required.'); - } - //>>includeEnd('debug'); - - var targetProperty = resolve(this); - return defined(targetProperty) && this._targetObject.isAvailable(time) ? targetProperty.getValue(time, result) : undefined; + return resolve(this).getValue(time, result); }; /** @@ -148,14 +263,18 @@ define([ * @returns {Cartesian3} The modified result parameter or a new instance if the result parameter was not supplied. */ ReferenceProperty.prototype.getValueInReferenceFrame = function(time, referenceFrame, result) { - //>>includeStart('debug', pragmas.debug); - if (!defined(time)) { - throw new DeveloperError('time is required.'); - } - //>>includeEnd('debug'); + return resolve(this).getValueInReferenceFrame(time, referenceFrame, result); + }; - var targetProperty = resolve(this); - return defined(targetProperty) && this._targetObject.isAvailable(time) ? targetProperty.getValueInReferenceFrame(time, referenceFrame, result) : undefined; + /** + * Gets the {@link Material} type at the provided time. + * This method is only valid if the property being referenced is a {@link MaterialProperty}. + * + * @param {JulianDate} time The time for which to retrieve the type. + * @returns {String} The type of material. + */ + ReferenceProperty.prototype.getType = function(time) { + return resolve(this).getType(time); }; /** @@ -166,10 +285,46 @@ define([ * @returns {Boolean} true if left and right are equal, false otherwise. */ ReferenceProperty.prototype.equals = function(other) { - return this === other || // - (this._dynamicObjectCollection === other._dynamicObjectCollection && // - this._targetObjectId === other._targetObjectId && // - this._targetPropertyName === other._targetPropertyName); + if (this === other) { + return true; + } + + var names = this._targetPropertyNames; + var otherNames = other._targetPropertyNames; + + if (this._targetCollection !== other._targetCollection || // + this._targetId !== other._targetId || // + names.length !== otherNames.length) { + return false; + } + + var length = this._targetPropertyNames.length; + for (var i = 0; i < length; i++) { + if (names[i] !== otherNames[i]) { + return false; + } + } + + return true; + }; + + ReferenceProperty.prototype._onTargetObjectDefinitionChanged = function(targetObject, name, value, oldValue) { + if (this._targetPropertyNames[0] === name) { + this._targetProperty = undefined; + this._definitionChanged.raiseEvent(this); + } + }; + + ReferenceProperty.prototype._onCollectionChanged = function(collection, added, removed) { + var targetObject = this._targetObject; + if (defined(targetObject)) { + if (removed.indexOf(targetObject) === -1) { + targetObject.definitionChanged.removeEventListener(ReferenceProperty.prototype._onTargetObjectDefinitionChanged, this); + this._targetProperty = undefined; + this._targetObject = undefined; + this._definitionChanged.raiseEvent(this); + } + } }; return ReferenceProperty; diff --git a/Specs/Data/CZML/simple.czml b/Specs/Data/CZML/simple.czml index 238cd386628c..22e84b237ba5 100644 --- a/Specs/Data/CZML/simple.czml +++ b/Specs/Data/CZML/simple.czml @@ -2798,8 +2798,8 @@ }, "vertexPositions":{ "references":[ - "/Application/STK/Scenario/simple/Facility/AGI.position", - "/Application/STK/Scenario/simple/Satellite/ISS.position" + "/Application/STK/Scenario/simple/Facility/AGI#position", + "/Application/STK/Scenario/simple/Satellite/ISS#position" ] } }, @@ -2903,8 +2903,8 @@ }, "vertexPositions":{ "references":[ - "/Application/STK/Scenario/simple/Satellite/Geoeye1.position", - "/Application/STK/Scenario/simple/Satellite/ISS.position" + "/Application/STK/Scenario/simple/Satellite/Geoeye1#position", + "/Application/STK/Scenario/simple/Satellite/ISS#position" ] } }, @@ -3016,8 +3016,8 @@ }, "vertexPositions":{ "references":[ - "/Application/STK/Scenario/simple/Satellite/ISS.position", - "/Application/STK/Scenario/simple/Satellite/Landsat7.position" + "/Application/STK/Scenario/simple/Satellite/ISS#position", + "/Application/STK/Scenario/simple/Satellite/Landsat7#position" ] } }, diff --git a/Specs/DynamicScene/CzmlDataSourceSpec.js b/Specs/DynamicScene/CzmlDataSourceSpec.js index 719bba60a2d3..b2ac86a80c74 100644 --- a/Specs/DynamicScene/CzmlDataSourceSpec.js +++ b/Specs/DynamicScene/CzmlDataSourceSpec.js @@ -19,6 +19,7 @@ defineSuite([ 'Core/Spherical', 'Core/TimeInterval', 'DynamicScene/DynamicObjectCollection', + 'DynamicScene/ReferenceProperty', 'Scene/HorizontalOrigin', 'Scene/LabelStyle', 'Scene/VerticalOrigin', @@ -43,6 +44,7 @@ defineSuite([ Spherical, TimeInterval, DynamicObjectCollection, + ReferenceProperty, HorizontalOrigin, LabelStyle, VerticalOrigin, @@ -1992,4 +1994,177 @@ defineSuite([ expect(dynamicObject.wall.minimumHeights.getValue(Iso8601.MINIMUM_VALUE)).toEqual(czmlRectangle.minimumHeights.array); expect(dynamicObject.wall.maximumHeights.getValue(Iso8601.MINIMUM_VALUE)).toEqual(czmlRectangle.maximumHeights.array); }); + + it('Can use constant reference properties', function() { + var time = new JulianDate(); + var packets = [{ + id : 'targetId', + point : { + pixelSize : 1.0 + } + }, { + id : 'referenceId', + point : { + pixelSize : { + reference : 'targetId#point.pixelSize' + } + } + }]; + + var dataSource = new CzmlDataSource(); + dataSource.load(packets); + + var targetObject = dataSource.dynamicObjects.getById('targetId'); + var referenceObject = dataSource.dynamicObjects.getById('referenceId'); + + expect(referenceObject.point.pixelSize instanceof ReferenceProperty).toBe(true); + expect(targetObject.point.pixelSize.getValue(time)).toEqual(referenceObject.point.pixelSize.getValue(time)); + }); + + it('Can use interval reference properties', function() { + var packets = [{ + id : 'targetId', + point : { + pixelSize : 1.0 + } + }, { + id : 'targetId2', + point : { + pixelSize : 2.0 + } + }, { + id : 'referenceId', + point : { + pixelSize : [{ + interval : '2012/2013', + reference : 'targetId#point.pixelSize' + }, { + interval : '2013/2014', + reference : 'targetId2#point.pixelSize' + }] + } + }]; + + var time1 = JulianDate.fromIso8601('2012'); + var time2 = JulianDate.fromIso8601('2014'); + + var dataSource = new CzmlDataSource(); + dataSource.load(packets); + + var targetObject = dataSource.dynamicObjects.getById('targetId'); + var targetObject2 = dataSource.dynamicObjects.getById('targetId2'); + var referenceObject = dataSource.dynamicObjects.getById('referenceId'); + + expect(targetObject.point.pixelSize.getValue(time1)).toEqual(referenceObject.point.pixelSize.getValue(time1)); + expect(targetObject2.point.pixelSize.getValue(time2)).toEqual(referenceObject.point.pixelSize.getValue(time2)); + }); + + it('Can use constant reference properties for position', function() { + var time = new JulianDate(); + + var packets = [{ + id : 'targetId', + position : { + cartesian : [1.0, 2.0, 3.0] + } + }, { + id : 'referenceId', + position : { + reference : 'targetId#position' + } + }]; + + var dataSource = new CzmlDataSource(); + dataSource.load(packets); + + var targetObject = dataSource.dynamicObjects.getById('targetId'); + var referenceObject = dataSource.dynamicObjects.getById('referenceId'); + + expect(referenceObject.position instanceof ReferenceProperty).toBe(true); + expect(targetObject.position.getValue(time)).toEqual(referenceObject.position.getValue(time)); + }); + + it('Can use interval reference properties for positions', function() { + var time = new JulianDate(); + + var packets = [{ + id : 'targetId', + position : { + cartesian : [1.0, 2.0, 3.0] + } + }, { + id : 'targetId2', + position : { + cartesian : [4.0, 5.0, 6.0] + } + }, { + id : 'referenceId', + position : [{ + interval : '2012/2013', + reference : 'targetId#position' + }, { + interval : '2013/2014', + reference : 'targetId2#position' + }] + }]; + + var time1 = JulianDate.fromIso8601('2012'); + var time2 = JulianDate.fromIso8601('2014'); + + var dataSource = new CzmlDataSource(); + dataSource.load(packets); + + var targetObject = dataSource.dynamicObjects.getById('targetId'); + var targetObject2 = dataSource.dynamicObjects.getById('targetId2'); + var referenceObject = dataSource.dynamicObjects.getById('referenceId'); + + expect(targetObject.position.getValue(time1)).toEqual(referenceObject.position.getValue(time1)); + expect(targetObject2.position.getValue(time2)).toEqual(referenceObject.position.getValue(time2)); + }); + + it('Can reference properties before they exist.', function() { + var time = new JulianDate(); + var packets = [{ + id : 'referenceId', + point : { + pixelSize : { + reference : 'targetId#point.pixelSize' + } + } + }, { + id : 'targetId', + point : { + pixelSize : 1.0 + } + }]; + + var dataSource = new CzmlDataSource(); + dataSource.load(packets); + + var targetObject = dataSource.dynamicObjects.getById('targetId'); + var referenceObject = dataSource.dynamicObjects.getById('referenceId'); + + expect(referenceObject.point.pixelSize instanceof ReferenceProperty).toBe(true); + expect(targetObject.point.pixelSize.getValue(time)).toEqual(referenceObject.point.pixelSize.getValue(time)); + }); + + it('Can reference local properties.', function() { + var time = new JulianDate(); + var packet = { + id : 'testObject', + point : { + pixelSize : 1.0, + outlineWidth : { + reference : '#point.pixelSize' + } + } + }; + + var dataSource = new CzmlDataSource(); + dataSource.load(packet); + + var targetObject = dataSource.dynamicObjects.getById('testObject'); + expect(targetObject.point.outlineWidth instanceof ReferenceProperty).toBe(true); + expect(targetObject.point.outlineWidth.getValue(time)).toEqual(targetObject.point.pixelSize.getValue(time)); + }); }); diff --git a/Specs/DynamicScene/ReferencePropertySpec.js b/Specs/DynamicScene/ReferencePropertySpec.js index 9f1d51239ec3..dca76cd43d26 100644 --- a/Specs/DynamicScene/ReferencePropertySpec.js +++ b/Specs/DynamicScene/ReferencePropertySpec.js @@ -1,103 +1,261 @@ /*global defineSuite*/ defineSuite([ 'DynamicScene/ReferenceProperty', + 'Core/Cartesian3', + 'Core/Color', 'Core/JulianDate', + 'Core/ReferenceFrame', 'Core/TimeInterval', + 'DynamicScene/ColorMaterialProperty', + 'DynamicScene/ConstantProperty', + 'DynamicScene/ConstantPositionProperty', + 'DynamicScene/DynamicObject', + 'DynamicScene/DynamicBillboard', 'DynamicScene/DynamicObjectCollection' ], function( ReferenceProperty, + Cartesian3, + Color, JulianDate, + ReferenceFrame, TimeInterval, + ColorMaterialProperty, + ConstantProperty, + ConstantPositionProperty, + DynamicObject, + DynamicBillboard, DynamicObjectCollection) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ - var validTime = JulianDate.fromIso8601('2012'); - var invalidTime = JulianDate.fromIso8601('2014'); - - var testObjectLink = 'testObject.property'; - function createTestObject(dynamicObjectCollection, methodName) { - var testObject = dynamicObjectCollection.getOrCreateObject('testObject'); - testObject.availability = TimeInterval.fromIso8601('2012/2013'); - testObject.property = {}; - testObject.property[methodName] = function(time, result) { - result.expectedTime = time; - result.expectedValue = true; - return result; - }; - return testObject; - } - - it('constructor throws if missing dynamicObjectCollection parameter', function() { + var time = new JulianDate(); + + it('constructor sets expected values', function() { + var collection = new DynamicObjectCollection(); + var objectId = 'testId'; + var propertyNames = ['foo', 'bar', 'baz']; + var property = new ReferenceProperty(collection, objectId, propertyNames); + + expect(property.targetCollection).toBe(collection); + expect(property.targetId).toEqual(objectId); + expect(property.targetPropertyNames).toEqual(propertyNames); + }); + + it('fromString sets expected values', function() { + var collection = new DynamicObjectCollection(); + var objectId = 'testId'; + var propertyNames = ['foo', 'bar', 'baz']; + + var property = ReferenceProperty.fromString(collection, 'testId#foo.bar.baz'); + + expect(property.targetCollection).toBe(collection); + expect(property.targetId).toEqual(objectId); + expect(property.targetPropertyNames).toEqual(propertyNames); + }); + + it('fromString works with escaped values', function() { + var collection = new DynamicObjectCollection(); + var objectId = '#identif\\#ier.'; + var propertyNames = ["propertyName", ".abc\\", "def"]; + var property = ReferenceProperty.fromString(collection, '\\#identif\\\\\\#ier\\.#propertyName.\\.abc\\\\.def'); + + expect(property.targetCollection).toBe(collection); + expect(property.targetId).toEqual(objectId); + expect(property.targetPropertyNames).toEqual(propertyNames); + }); + + it('properly tracks resolved property', function() { + var testObject = new DynamicObject('testId'); + testObject.billboard = new DynamicBillboard(); + testObject.billboard.scale = new ConstantProperty(5); + + var collection = new DynamicObjectCollection(); + collection.add(testObject); + + //Basic property resolution + var property = ReferenceProperty.fromString(collection, 'testId#billboard.scale'); + expect(property.referenceFrame).toBeUndefined(); + expect(property.isConstant).toEqual(true); + expect(property.getValue(time)).toEqual(5); + + var listener = jasmine.createSpy('listener'); + property.definitionChanged.addEventListener(listener); + + //Change to exist target property is reflected in reference. + testObject.billboard.scale.setValue(6); + expect(property.isConstant).toEqual(true); + expect(property.getValue(time)).toEqual(6); + expect(listener).toHaveBeenCalledWith(property); + listener.reset(); + + //Assignment of new leaf property to existing target is reflected in reference. + testObject.billboard.scale = new ConstantProperty(7); + expect(property.isConstant).toEqual(true); + expect(property.getValue(time)).toEqual(7); + expect(listener).toHaveBeenCalledWith(property); + listener.reset(); + + //Assignment of non-leaf property to existing target is reflected in reference. + testObject.billboard = new DynamicBillboard(); + testObject.billboard.scale = new ConstantProperty(8); + expect(property.isConstant).toEqual(true); + expect(property.getValue(time)).toEqual(8); + expect(listener).toHaveBeenCalledWith(property); + listener.reset(); + + //Removing an adding a new object is properly referenced. + collection.remove(testObject); + + var testObject2 = new DynamicObject('testId'); + testObject2.billboard = new DynamicBillboard(); + testObject2.billboard.scale = new ConstantProperty(9); + collection.add(testObject2); + expect(property.isConstant).toEqual(true); + expect(property.getValue(time)).toEqual(9); + expect(listener).toHaveBeenCalledWith(property); + listener.reset(); + }); + + it('works with position properties', function() { + var testObject = new DynamicObject('testId'); + testObject.position = new ConstantPositionProperty(new Cartesian3(1, 2, 3), ReferenceFrame.FIXED); + + var collection = new DynamicObjectCollection(); + collection.add(testObject); + + //Basic property resolution + var property = ReferenceProperty.fromString(collection, 'testId#position'); + expect(property.isConstant).toEqual(true); + expect(property.referenceFrame).toEqual(ReferenceFrame.FIXED); + expect(property.getValue(time)).toEqual(testObject.position.getValue(time)); + expect(property.getValueInReferenceFrame(time, ReferenceFrame.INERTIAL)).toEqual(testObject.position.getValueInReferenceFrame(time, ReferenceFrame.INERTIAL)); + }); + + it('works with material properties', function() { + var testObject = new DynamicObject('testId'); + testObject.addProperty('testMaterial'); + testObject.testMaterial = ColorMaterialProperty.fromColor(Color.WHITE); + + var collection = new DynamicObjectCollection(); + collection.add(testObject); + + //Basic property resolution + var property = ReferenceProperty.fromString(collection, 'testId#testMaterial'); + expect(property.isConstant).toEqual(true); + expect(property.getType(time)).toEqual(testObject.testMaterial.getType(time)); + expect(property.getValue(time)).toEqual(testObject.testMaterial.getValue(time)); + }); + + it('equals works', function() { + var dynamicObjectCollection = new DynamicObjectCollection(); + + var left = ReferenceProperty.fromString(dynamicObjectCollection, 'objectId#foo.bar'); + var right = ReferenceProperty.fromString(dynamicObjectCollection, 'objectId#foo.bar'); + expect(left.equals(right)).toEqual(true); + + //collection differs + right = ReferenceProperty.fromString(new DynamicObjectCollection(), 'objectId#foo.bar'); + expect(left.equals(right)).toEqual(false); + + //target id differs + right = ReferenceProperty.fromString(dynamicObjectCollection, 'otherObjectId#foo.bar'); + expect(left.equals(right)).toEqual(false); + + //number of sub-properties differ + right = ReferenceProperty.fromString(dynamicObjectCollection, 'objectId#foo'); + expect(left.equals(right)).toEqual(false); + + //sub-properties of same length differ + right = ReferenceProperty.fromString(dynamicObjectCollection, 'objectId#foo.baz'); + expect(left.equals(right)).toEqual(false); + }); + + it('constructor throws with undefined targetCollection', function() { expect(function() { - return new ReferenceProperty(undefined, 'object', 'property'); + return new ReferenceProperty(undefined, 'objectid', ['property']); }).toThrowDeveloperError(); }); - it('constructor throws if missing targetObjectId parameter', function() { + it('constructor throws with undefined targetId', function() { expect(function() { - return new ReferenceProperty(new DynamicObjectCollection(), undefined, 'property'); + return new ReferenceProperty(new DynamicObjectCollection(), undefined, ['property']); }).toThrowDeveloperError(); }); - it('constructor throws if missing targetPropertyName parameter', function() { + it('constructor throws with undefined targetPropertyNames', function() { expect(function() { - return new ReferenceProperty(new DynamicObjectCollection(), 'object', undefined); + return new ReferenceProperty(new DynamicObjectCollection(), 'objectId', undefined); }).toThrowDeveloperError(); }); - it('fromString throws if missing dynamicObjectCollection parameter', function() { + it('constructor throws with empty targetPropertyNames', function() { expect(function() { - return ReferenceProperty.fromString(undefined, 'object.property'); + return new ReferenceProperty(new DynamicObjectCollection(), 'objectId', []); }).toThrowDeveloperError(); }); - it('fromString throws if missing string parameter', function() { + it('constructor throws with empty targetId', function() { expect(function() { - return ReferenceProperty.fromString(new DynamicObjectCollection(), undefined); + return new ReferenceProperty(new DynamicObjectCollection(), '', ['property']); }).toThrowDeveloperError(); }); - it('fromString throws if invalid string parameter', function() { + it('fromString throws with undefined targetCollection', function() { expect(function() { - return ReferenceProperty.fromString(new DynamicObjectCollection(), 'a.b.c'); + return ReferenceProperty.fromString(undefined, 'objectid#property'); }).toThrowDeveloperError(); }); - it('getValue throws with undefined time', function() { - var property = ReferenceProperty.fromString(new DynamicObjectCollection(), 'object.property'); + it('fromString throws with undefined referenceString', function() { expect(function() { - property.getValue(undefined); + return ReferenceProperty.fromString(new DynamicObjectCollection(), undefined); }).toThrowDeveloperError(); }); - it('getValue returned undefined for unresolved property', function() { - var property = ReferenceProperty.fromString(new DynamicObjectCollection(), 'object.property'); - expect(property.getValue(new JulianDate())).toBeUndefined(); + it('fromString throws with invalid referenceString', function() { + expect(function() { + return ReferenceProperty.fromString(new DynamicObjectCollection(), 'foo'); + }).toThrowDeveloperError(); + + expect(function() { + return ReferenceProperty.fromString(new DynamicObjectCollection(), 'foo#'); + }).toThrowDeveloperError(); + + expect(function() { + return ReferenceProperty.fromString(new DynamicObjectCollection(), '#bar'); + }).toThrowDeveloperError(); }); - it('Resolves getValue property on collection', function() { - var dynamicObjectCollection = new DynamicObjectCollection(); - createTestObject(dynamicObjectCollection, 'getValue'); - var property = ReferenceProperty.fromString(dynamicObjectCollection, testObjectLink); - var result = {}; - expect(property.getValue(validTime, result)).toEqual(result); - expect(result.expectedValue).toEqual(true); - expect(result.expectedTime).toEqual(validTime); - expect(property.getValue(invalidTime, result)).toBeUndefined(); + it('throws RuntimeError if targetId can not be resolved', function() { + var collection = new DynamicObjectCollection(); + var property = ReferenceProperty.fromString(collection, 'testId#foo.bar'); + expect(function() { + property.getValue(time); + }).toThrowRuntimeError(); }); - it('equals works', function() { - var dynamicObjectCollection = new DynamicObjectCollection(); - createTestObject(dynamicObjectCollection, 'getValue'); - var left = ReferenceProperty.fromString(dynamicObjectCollection, testObjectLink); - var right = ReferenceProperty.fromString(dynamicObjectCollection, testObjectLink); - expect(left.equals(right)).toEqual(true); + it('throws RuntimeError if property can not be resolved', function() { + var collection = new DynamicObjectCollection(); - right = new ReferenceProperty(dynamicObjectCollection, 'testObject', 'property2'); - expect(left.equals(right)).toEqual(false); + var testObject = new DynamicObject('testId'); + collection.add(testObject); - right = new ReferenceProperty(dynamicObjectCollection, 'testObject2', 'property'); - expect(left.equals(right)).toEqual(false); + var property = ReferenceProperty.fromString(collection, 'testId#billboard'); + expect(function() { + property.getValue(time); + }).toThrowRuntimeError(); + }); + + it('throws RuntimeError if sub-property can not be resolved', function() { + var collection = new DynamicObjectCollection(); + + var testObject = new DynamicObject('testId'); + testObject.billboard = new DynamicBillboard(); + collection.add(testObject); + + var property = ReferenceProperty.fromString(collection, 'testId#billboard.foo'); + expect(function() { + property.getValue(time); + }).toThrowRuntimeError(); }); }); \ No newline at end of file