From 73a47bb5f364121d3e834f990f13121431389e74 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Wed, 21 May 2014 16:45:02 -0400 Subject: [PATCH 01/18] Start refactoring reference properties. --- Source/DynamicScene/CzmlDataSource.js | 51 ++++++++++++++------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/Source/DynamicScene/CzmlDataSource.js b/Source/DynamicScene/CzmlDataSource.js index b43835ca02f3..12fa36ccda89 100644 --- a/Source/DynamicScene/CzmlDataSource.js +++ b/Source/DynamicScene/CzmlDataSource.js @@ -455,7 +455,6 @@ define([ return; } - var propertyCreated = false; var property = object[propertyName]; var epoch; @@ -470,11 +469,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; @@ -495,7 +493,6 @@ define([ if (!defined(property)) { property = new TimeIntervalCollectionProperty(); object[propertyName] = property; - propertyCreated = true; } if (property instanceof TimeIntervalCollectionProperty) { @@ -513,7 +510,6 @@ define([ interval.data = property; //Create the composite. - propertyCreated = true; property = new CompositeProperty(); object[propertyName] = property; @@ -525,12 +521,11 @@ define([ property.intervals.addInterval(combinedInterval); } - return propertyCreated; + return; } //isSampled && hasInterval if (!defined(property)) { - propertyCreated = true; property = new CompositeProperty(); object[propertyName] = property; } @@ -542,7 +537,6 @@ define([ interval.data = property; //Create the composite. - propertyCreated = true; property = new CompositeProperty(); object[propertyName] = property; @@ -561,7 +555,7 @@ define([ } interval.data.addSamplesPackedArray(unwrappedInterval, epoch); updateInterpolationSettings(packetData, interval.data); - return propertyCreated; + return; } function processPacketData(type, object, propertyName, packetData, interval, sourceUri) { @@ -578,7 +572,11 @@ define([ } } - function processPositionProperty(object, propertyName, packetData, constrainedInterval, sourceUri) { + function checkForReference(packetData) { + return defined(packetData.reference); + } + + function processPositionProperty(object, propertyName, packetData, constrainedInterval, sourceUri, dynamicObjectCollection) { var combinedInterval; var packetInterval = packetData.interval; if (defined(packetInterval)) { @@ -590,6 +588,12 @@ define([ combinedInterval = constrainedInterval; } + var isReference = checkForReference(packetData); + if (isReference) { + object[propertyName] = new ReferenceProperty(dynamicObjectCollection, packetData.reference.id, packetData.reference.path); + return; + } + var referenceFrame = defaultValue(ReferenceFrame[packetData.referenceFrame], undefined); var unwrappedInterval = unwrapCartesianInterval(packetData); var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); @@ -603,7 +607,6 @@ define([ return true; } - var propertyCreated = false; var property = object[propertyName]; var epoch; @@ -618,11 +621,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; @@ -639,7 +641,6 @@ define([ if (!defined(property)) { property = new TimeIntervalCollectionPositionProperty(referenceFrame); object[propertyName] = property; - propertyCreated = true; } if (property instanceof TimeIntervalCollectionPositionProperty && (defined(referenceFrame) && property.referenceFrame === referenceFrame)) { @@ -657,7 +658,6 @@ define([ interval.data = property; //Create the composite. - propertyCreated = true; property = new CompositePositionProperty(property.referenceFrame); object[propertyName] = property; @@ -669,12 +669,11 @@ define([ 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 +683,6 @@ define([ interval.data = property; //Create the composite. - propertyCreated = true; property = new CompositePositionProperty(property.referenceFrame); object[propertyName] = property; @@ -703,20 +701,19 @@ 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); } } @@ -828,7 +825,7 @@ define([ 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); } } @@ -853,7 +850,13 @@ define([ if (defined(references)) { var properties = []; for (i = 0, len = references.length; i < len; i++) { - properties.push(ReferenceProperty.fromString(dynamicObjectCollection, references[i])); + var reference = references[i]; + if (typeof reference === 'string') { + //Backwards compatibility + properties.push(new ReferenceProperty.fromString(dynamicObjectCollection, reference)); + } else { + properties.push(new ReferenceProperty(dynamicObjectCollection, reference.id, reference.path)); + } } var iso8601Interval = vertexPositionsData.interval; From 5f6239d09eb56d029b226f9139e242b7256f7cc7 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Wed, 21 May 2014 21:50:59 -0400 Subject: [PATCH 02/18] Ongoing reference property work. --- Source/DynamicScene/CzmlDataSource.js | 312 ++++++++++++----------- Source/DynamicScene/ReferenceProperty.js | 34 ++- 2 files changed, 186 insertions(+), 160 deletions(-) diff --git a/Source/DynamicScene/CzmlDataSource.js b/Source/DynamicScene/CzmlDataSource.js index 12fa36ccda89..0abcd5ae4840 100644 --- a/Source/DynamicScene/CzmlDataSource.js +++ b/Source/DynamicScene/CzmlDataSource.js @@ -427,7 +427,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,6 +439,11 @@ define([ combinedInterval = constrainedInterval; } + if (defined(packetData.reference)) { + object[propertyName] = new ReferenceProperty(dynamicObjectCollection, packetData.reference.id, packetData.reference.path); + return; + } + var unwrappedInterval = unwrapInterval(type, packetData, sourceUri); var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); var packedLength = defaultValue(type.packedLength, 1); @@ -558,24 +563,20 @@ define([ 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 checkForReference(packetData) { - return defined(packetData.reference); - } - function processPositionProperty(object, propertyName, packetData, constrainedInterval, sourceUri, dynamicObjectCollection) { var combinedInterval; var packetInterval = packetData.interval; @@ -588,8 +589,7 @@ define([ combinedInterval = constrainedInterval; } - var isReference = checkForReference(packetData); - if (isReference) { + if (defined(packetData.reference)) { object[propertyName] = new ReferenceProperty(dynamicObjectCollection, packetData.reference.id, packetData.reference.path); return; } @@ -717,7 +717,7 @@ define([ } } - function processMaterialProperty(object, propertyName, packetData, constrainedInterval, sourceUri) { + function processMaterialProperty(object, propertyName, packetData, constrainedInterval, sourceUri, dynamicObjectCollection) { var combinedInterval; var packetInterval = packetData.interval; if (defined(packetInterval)) { @@ -729,6 +729,11 @@ define([ combinedInterval = constrainedInterval; } + if (defined(packetData.reference)) { + object[propertyName] = new ReferenceProperty(dynamicObjectCollection, packetData.reference.id, packetData.reference.path); + return; + } + var property = object[propertyName]; var existingMaterial; var existingInterval; @@ -760,34 +765,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)) { @@ -797,17 +802,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); } } @@ -818,7 +823,7 @@ 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); } } @@ -832,14 +837,14 @@ define([ 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); } } @@ -899,7 +904,7 @@ define([ } } if (defined(vertexPositionsData.array)) { - processPacketData(Array, dynamicObject, 'vertexPositions', vertexPositionsData); + processPacketData(Array, dynamicObject, 'vertexPositions', vertexPositionsData, undefined, undefined, dynamicObjectCollection); } } } @@ -961,16 +966,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) { @@ -1024,19 +1029,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) { @@ -1055,19 +1060,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) { @@ -1086,12 +1091,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) { @@ -1110,18 +1115,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) { @@ -1140,10 +1145,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) { @@ -1162,14 +1167,14 @@ define([ dynamicObject.path = path = new DynamicPath(); } - processPacketData(Color, path, 'color', pathData.color, interval, sourceUri); - processPacketData(Number, path, 'width', pathData.width, interval, sourceUri); - processPacketData(Color, path, 'outlineColor', pathData.outlineColor, interval, sourceUri); - processPacketData(Number, path, 'outlineWidth', pathData.outlineWidth, interval, sourceUri); - processPacketData(Boolean, path, 'show', pathData.show, 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, path, 'color', pathData.color, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, path, 'width', pathData.width, interval, sourceUri, dynamicObjectCollection); + processPacketData(Color, path, 'outlineColor', pathData.outlineColor, interval, sourceUri, dynamicObjectCollection); + processPacketData(Number, path, 'outlineWidth', pathData.outlineWidth, interval, sourceUri, dynamicObjectCollection); + processPacketData(Boolean, path, 'show', pathData.show, 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); } function processPoint(dynamicObject, packet, dynamicObjectCollection, sourceUri) { @@ -1188,11 +1193,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) { @@ -1211,16 +1216,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) { @@ -1239,19 +1244,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) { @@ -1270,14 +1275,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) { @@ -1324,14 +1329,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 = []; @@ -1350,7 +1355,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) { @@ -1369,12 +1374,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. @@ -1383,10 +1388,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); } } } @@ -1407,11 +1412,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) { @@ -1727,6 +1732,7 @@ define([ * @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. + * @param {DynamicObjectCollection} [dynamicObjectCollection] The collection being processsed. * @returns {Boolean} True if a new property was created, false otherwise. */ CzmlDataSource.processPacketData = processPacketData; @@ -1741,6 +1747,7 @@ define([ * @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. + * @param {DynamicObjectCollection} [dynamicObjectCollection] The collection being processsed. * @returns {Boolean} True if a new property was created, false otherwise. */ CzmlDataSource.processPositionPacketData = processPositionPacketData; @@ -1755,6 +1762,7 @@ define([ * @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. + * @param {DynamicObjectCollection} [dynamicObjectCollection] The collection being processsed. * @returns {Boolean} True if a new property was created, false otherwise. */ CzmlDataSource.processMaterialPacketData = processMaterialPacketData; diff --git a/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index bc756adb03d3..9bebf7ad2224 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -62,7 +62,7 @@ define([ /** * Gets a value indicating if this property is constant. * This property always returns true. - * @memberof ConstantProperty.prototype + * @memberof ReferenceProperty.prototype * @type {Boolean} */ isConstant : { @@ -74,13 +74,24 @@ 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 + * @memberof ReferenceProperty.prototype * @type {Event} */ definitionChanged : { get : function() { return this._definitionChanged; } + }, + /** + * Gets the reference frame that the position is defined in. + * @memberof ReferenceProperty.prototype + * @Type {ReferenceFrame} + */ + referenceFrame : { + get : function() { + var targetProperty = resolve(this); + return defined(targetProperty) ? targetProperty.referenceFrame : undefined; + } } }); @@ -148,16 +159,23 @@ 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'); - 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. + * @memberof MaterialProperty + * @function + * + * @param {JulianDate} time The time for which to retrieve the type. + * @returns {String} The type of material. + */ + ReferenceProperty.prototype.getType = function(time) { + var targetProperty = resolve(this); + return defined(targetProperty) && this._targetObject.isAvailable(time) ? targetProperty.getType(time) : undefined; + }; + /** * Compares this property to the provided property and returns * true if they are equal, false otherwise. From 15f483475fb68ef94ffe470cea33c12376606e73 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Fri, 30 May 2014 11:33:02 -0400 Subject: [PATCH 03/18] Ongoing ReferenceProperty work. --- Source/DynamicScene/CzmlDataSource.js | 14 ++-- Source/DynamicScene/ReferenceProperty.js | 75 ++++++++++++++++++--- Specs/DynamicScene/ReferencePropertySpec.js | 8 +-- 3 files changed, 74 insertions(+), 23 deletions(-) diff --git a/Source/DynamicScene/CzmlDataSource.js b/Source/DynamicScene/CzmlDataSource.js index 0abcd5ae4840..f4cc806d4109 100644 --- a/Source/DynamicScene/CzmlDataSource.js +++ b/Source/DynamicScene/CzmlDataSource.js @@ -440,7 +440,7 @@ define([ } if (defined(packetData.reference)) { - object[propertyName] = new ReferenceProperty(dynamicObjectCollection, packetData.reference.id, packetData.reference.path); + object[propertyName] = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); return; } @@ -590,7 +590,7 @@ define([ } if (defined(packetData.reference)) { - object[propertyName] = new ReferenceProperty(dynamicObjectCollection, packetData.reference.id, packetData.reference.path); + object[propertyName] = new ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); return; } @@ -730,7 +730,7 @@ define([ } if (defined(packetData.reference)) { - object[propertyName] = new ReferenceProperty(dynamicObjectCollection, packetData.reference.id, packetData.reference.path); + object[propertyName] = new ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); return; } @@ -855,13 +855,7 @@ define([ if (defined(references)) { var properties = []; for (i = 0, len = references.length; i < len; i++) { - var reference = references[i]; - if (typeof reference === 'string') { - //Backwards compatibility - properties.push(new ReferenceProperty.fromString(dynamicObjectCollection, reference)); - } else { - properties.push(new ReferenceProperty(dynamicObjectCollection, reference.id, reference.path)); - } + properties.push(ReferenceProperty.fromString(dynamicObjectCollection, references[i])); } var iso8601Interval = vertexPositionsData.interval; diff --git a/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index abdeaf8f466c..8b051738642d 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -27,6 +27,50 @@ define([ return targetProperty; } + function findUnescaped(value, start, delimiter) { + var index; + do { + index = value.indexOf(delimiter, start); + if (index === -1) { + break; + } + + var count = 0; + var place = index - 1; + while (place !== -1 && value[place--] === '\\') { + count++; + } + if (count % 2 === 0) { + return index; + } + start = index + 1; + } while (index !== -1); + return -1; + } + + function trySplit(value, delimiter) { + var indices = []; + var start = 0; + var index; + do { + index = findUnescaped(value, start, delimiter); + if (index !== -1) { + indices.push(index); + start = index + 1; + } + } while (index !== -1); + + var lastIndex = 0; + var result = new Array(indices.length + 1); + for (var i = 0; i < indices.length; i++) { + index = indices[i]; + result[i] = value.substring(lastIndex, index).replace('\\#', '#').replace('\\\\', '\\').replace('\\.', '.'); + lastIndex = index + 1; + } + result[indices.length] = value.substring(lastIndex).replace('\\#', '#').replace('\\\\', '\\').replace('\\.', '.'); + return result; + } + /** * A {@link Property} which transparently links to another property on a provided object. * @@ -117,15 +161,29 @@ define([ } //>>includeEnd('debug'); - var parts = referenceString.split('.'); + var tmp = trySplit(referenceString, '#'); + if (tmp.length !== 2) + { + throw new DeveloperError(); + } + var id = tmp[0]; - //>>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 index = findUnescaped(referenceString, 0, '#') + 1; + var values = trySplit(referenceString.substring(index), '.'); + + if (values.length === 0) { + throw new DeveloperError(); } - //>>includeEnd('debug'); - return new ReferenceProperty(dynamicObjectCollection, parts[0], parts[1]); + for (var i = 0; i < values.length; i++) { + var item = values[i]; + if (!defined(item) || item === '') { + throw new DeveloperError(); + } + } + + return new ReferenceProperty(dynamicObjectCollection, id, values[0]); }; /** @@ -164,9 +222,8 @@ define([ }; /** - * Gets the {@link Material} type at the provided time. - * @memberof MaterialProperty - * @function + * Gets the {@link Material} type at the provided time when the referenced property is a {@link MaterialProperty}. + * @memberof ReferenceProperty * * @param {JulianDate} time The time for which to retrieve the type. * @returns {String} The type of material. diff --git a/Specs/DynamicScene/ReferencePropertySpec.js b/Specs/DynamicScene/ReferencePropertySpec.js index 9f1d51239ec3..ee231d2d6a39 100644 --- a/Specs/DynamicScene/ReferencePropertySpec.js +++ b/Specs/DynamicScene/ReferencePropertySpec.js @@ -15,7 +15,7 @@ defineSuite([ var validTime = JulianDate.fromIso8601('2012'); var invalidTime = JulianDate.fromIso8601('2014'); - var testObjectLink = 'testObject.property'; + var testObjectLink = 'testObject#property'; function createTestObject(dynamicObjectCollection, methodName) { var testObject = dynamicObjectCollection.getOrCreateObject('testObject'); testObject.availability = TimeInterval.fromIso8601('2012/2013'); @@ -48,7 +48,7 @@ defineSuite([ it('fromString throws if missing dynamicObjectCollection parameter', function() { expect(function() { - return ReferenceProperty.fromString(undefined, 'object.property'); + return ReferenceProperty.fromString(undefined, 'object#property'); }).toThrowDeveloperError(); }); @@ -65,14 +65,14 @@ defineSuite([ }); it('getValue throws with undefined time', function() { - var property = ReferenceProperty.fromString(new DynamicObjectCollection(), 'object.property'); + var property = ReferenceProperty.fromString(new DynamicObjectCollection(), 'object#property'); expect(function() { property.getValue(undefined); }).toThrowDeveloperError(); }); it('getValue returned undefined for unresolved property', function() { - var property = ReferenceProperty.fromString(new DynamicObjectCollection(), 'object.property'); + var property = ReferenceProperty.fromString(new DynamicObjectCollection(), 'object#property'); expect(property.getValue(new JulianDate())).toBeUndefined(); }); From 6545b414fae46da488e6af546fdeaed0fdd5d043 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Fri, 30 May 2014 12:19:18 -0400 Subject: [PATCH 04/18] Ongoing ReferenceProperty work Old tests all pass, update simple.czml so that it works again. Add ability to reference sub-properties. --- Apps/CesiumViewer/Gallery/simple.czml | 4 +- Source/DynamicScene/CzmlDataSource.js | 4 +- Source/DynamicScene/ReferenceProperty.js | 56 ++++++++++++++++----- Specs/Data/CZML/simple.czml | 12 ++--- Specs/DynamicScene/ReferencePropertySpec.js | 8 +-- 5 files changed, 57 insertions(+), 27 deletions(-) diff --git a/Apps/CesiumViewer/Gallery/simple.czml b/Apps/CesiumViewer/Gallery/simple.czml index 4da0922c0976..4844bea5003e 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" ] } }, diff --git a/Source/DynamicScene/CzmlDataSource.js b/Source/DynamicScene/CzmlDataSource.js index f4cc806d4109..217de59bc885 100644 --- a/Source/DynamicScene/CzmlDataSource.js +++ b/Source/DynamicScene/CzmlDataSource.js @@ -590,7 +590,7 @@ define([ } if (defined(packetData.reference)) { - object[propertyName] = new ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); + object[propertyName] = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); return; } @@ -730,7 +730,7 @@ define([ } if (defined(packetData.reference)) { - object[propertyName] = new ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); + object[propertyName] = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); return; } diff --git a/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index 8b051738642d..83259719f5f8 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -19,7 +19,21 @@ define([ var resolveBuffer = referenceProperty._dynamicObjectCollection; var targetObject = resolveBuffer.getById(referenceProperty._targetObjectId); if (defined(targetObject)) { - targetProperty = targetObject[referenceProperty._targetPropertyName]; + var names = referenceProperty._targetPropertyNames; + + targetProperty = targetObject[names[0]]; + if (!defined(targetProperty)) { + return undefined; + } + + var length = names.length; + for (var i = 1; i < length; i++) { + targetProperty = targetProperty[names[i]]; + if (!defined(targetProperty)) { + return undefined; + } + } + referenceProperty._targetProperty = targetProperty; referenceProperty._targetObject = targetObject; } @@ -81,7 +95,7 @@ define([ * @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. */ - var ReferenceProperty = function(dynamicObjectCollection, targetObjectId, targetPropertyName) { + var ReferenceProperty = function(dynamicObjectCollection, targetObjectId, targetPropertyNames) { //>>includeStart('debug', pragmas.debug); if (!defined(dynamicObjectCollection)) { throw new DeveloperError('dynamicObjectCollection is required.'); @@ -89,7 +103,7 @@ define([ if (!defined(targetObjectId)) { throw new DeveloperError('targetObjectId is required.'); } - if (!defined(targetPropertyName)) { + if (!defined(targetPropertyNames)) { throw new DeveloperError('targetPropertyName is required.'); } //>>includeEnd('debug'); @@ -98,7 +112,7 @@ define([ this._dynamicObjectCollection = dynamicObjectCollection; this._targetObjectId = targetObjectId; this._targetObject = undefined; - this._targetPropertyName = targetPropertyName; + this._targetPropertyNames = targetPropertyNames; this._definitionChanged = new Event(); }; @@ -162,12 +176,10 @@ define([ //>>includeEnd('debug'); var tmp = trySplit(referenceString, '#'); - if (tmp.length !== 2) - { + if (tmp.length !== 2) { throw new DeveloperError(); } - var id = tmp[0]; - + var identifier = tmp[0]; var index = findUnescaped(referenceString, 0, '#') + 1; var values = trySplit(referenceString.substring(index), '.'); @@ -183,7 +195,7 @@ define([ } } - return new ReferenceProperty(dynamicObjectCollection, id, values[0]); + return new ReferenceProperty(dynamicObjectCollection, identifier, values); }; /** @@ -242,10 +254,28 @@ 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; + } + + if (this._dynamicObjectCollection !== other._dynamicObjectCollection || // + this._targetObjectId !== other._targetObjectId || // + defined(this._targetPropertyNames) !== defined(other._targetPropertyNames) || // + this._targetPropertyNames.length !== other._targetPropertyNames.length) { + return false; + } + + var names = this._targetPropertyNames; + var otherNames = other._targetPropertyNames; + + var length = this._targetPropertyNames.length; + for (var i = 0; i < length; i++) { + if (names[i] !== otherNames[i]) { + return false; + } + } + + return true; }; 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/ReferencePropertySpec.js b/Specs/DynamicScene/ReferencePropertySpec.js index ee231d2d6a39..e8b556aa0f00 100644 --- a/Specs/DynamicScene/ReferencePropertySpec.js +++ b/Specs/DynamicScene/ReferencePropertySpec.js @@ -30,13 +30,13 @@ defineSuite([ it('constructor throws if missing dynamicObjectCollection parameter', function() { expect(function() { - return new ReferenceProperty(undefined, 'object', 'property'); + return new ReferenceProperty(undefined, 'object', ['property']); }).toThrowDeveloperError(); }); it('constructor throws if missing targetObjectId parameter', function() { expect(function() { - return new ReferenceProperty(new DynamicObjectCollection(), undefined, 'property'); + return new ReferenceProperty(new DynamicObjectCollection(), undefined, ['property']); }).toThrowDeveloperError(); }); @@ -94,10 +94,10 @@ defineSuite([ var right = ReferenceProperty.fromString(dynamicObjectCollection, testObjectLink); expect(left.equals(right)).toEqual(true); - right = new ReferenceProperty(dynamicObjectCollection, 'testObject', 'property2'); + right = new ReferenceProperty(dynamicObjectCollection, 'testObject', ['property2']); expect(left.equals(right)).toEqual(false); - right = new ReferenceProperty(dynamicObjectCollection, 'testObject2', 'property'); + right = new ReferenceProperty(dynamicObjectCollection, 'testObject2', ['property']); expect(left.equals(right)).toEqual(false); }); }); \ No newline at end of file From 36fd98bbdc6a5ead20f81c5cf8bc07df1db2ed1b Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Fri, 30 May 2014 15:56:34 -0400 Subject: [PATCH 05/18] Ongoing ReferenceProperty work Completely rewrite tests and refactor implementation to handle sub-properties and definitionChanged events. --- Apps/CesiumViewer/Gallery/simple.czml | 8 +- Source/DynamicScene/ReferenceProperty.js | 164 ++++++++----- Specs/DynamicScene/ReferencePropertySpec.js | 251 ++++++++++++++++---- 3 files changed, 311 insertions(+), 112 deletions(-) diff --git a/Apps/CesiumViewer/Gallery/simple.czml b/Apps/CesiumViewer/Gallery/simple.czml index 4844bea5003e..b2da65a7dc59 100644 --- a/Apps/CesiumViewer/Gallery/simple.czml +++ b/Apps/CesiumViewer/Gallery/simple.czml @@ -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/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index 83259719f5f8..7575fa31b530 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -3,40 +3,50 @@ 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)) { - var names = referenceProperty._targetPropertyNames; + var targetObject = that._targetObject; - targetProperty = targetObject[names[0]]; - if (!defined(targetProperty)) { - return undefined; - } + if (!defined(targetObject)) { + var targetCollection = that._targetCollection; - var length = names.length; - for (var i = 1; i < length; i++) { - targetProperty = targetProperty[names[i]]; - if (!defined(targetProperty)) { - return undefined; - } + 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; - referenceProperty._targetProperty = targetProperty; - referenceProperty._targetObject = targetObject; + targetProperty = targetObject[names[0]]; + if (!defined(targetProperty)) { + throw new RuntimeError('targetProperty could not be resolved.'); + } + + var length = names.length; + for (var i = 1; i < length; i++) { + targetProperty = targetProperty[names[i]]; + if (!defined(targetProperty)) { + throw new RuntimeError('targetProperty could not be resolved.'); + } } + + that._targetProperty = targetProperty; } return targetProperty; } @@ -91,29 +101,31 @@ 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. */ - var ReferenceProperty = function(dynamicObjectCollection, targetObjectId, targetPropertyNames) { + 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)) { + throw new DeveloperError('targetId is required.'); } if (!defined(targetPropertyNames)) { throw new DeveloperError('targetPropertyName is required.'); } //>>includeEnd('debug'); + this._targetCollection = targetCollection; + this._targetId = targetId; + this._targetPropertyNames = targetPropertyNames; this._targetProperty = undefined; - this._dynamicObjectCollection = dynamicObjectCollection; - this._targetObjectId = targetObjectId; this._targetObject = undefined; - this._targetPropertyNames = targetPropertyNames; this._definitionChanged = new Event(); + + targetCollection.collectionChanged.addEventListener(ReferenceProperty.prototype._onCollectionChanged, this); }; defineProperties(ReferenceProperty.prototype, { @@ -147,8 +159,37 @@ define([ */ referenceFrame : { get : function() { - var targetProperty = resolve(this); - return defined(targetProperty) ? targetProperty.referenceFrame : undefined; + return resolve(this).referenceFrame; + } + }, + /** + * Gets the reference frame that the position is defined in. + * @memberof ReferenceProperty.prototype + * @Type {String} + */ + targetId : { + get : function() { + return this._targetId; + } + }, + /** + * Gets the reference frame that the position is defined in. + * @memberof ReferenceProperty.prototype + * @Type {DynamicObjectCollection} + */ + targetCollection : { + get : function() { + return this._targetCollection; + } + }, + /** + * Gets the reference frame that the position is defined in. + * @memberof ReferenceProperty.prototype + * @Type {String[]} + */ + targetPropertyNames : { + get : function() { + return this._targetPropertyNames; } } }); @@ -158,17 +199,17 @@ define([ * be used to resolve it and a string indicating the target object id and property, * delineated by a period. * - * @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. */ - 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.'); @@ -176,26 +217,27 @@ define([ //>>includeEnd('debug'); var tmp = trySplit(referenceString, '#'); - if (tmp.length !== 2) { + var identifier = tmp[0]; + + //>>includeStart('debug', pragmas.debug); + if (tmp.length !== 2 || !defined(identifier) || identifier === '') { throw new DeveloperError(); } - var identifier = tmp[0]; + //>>includeEnd('debug'); var index = findUnescaped(referenceString, 0, '#') + 1; var values = trySplit(referenceString.substring(index), '.'); - if (values.length === 0) { - throw new DeveloperError(); - } - + //>>includeStart('debug', pragmas.debug); for (var i = 0; i < values.length; i++) { var item = values[i]; if (!defined(item) || item === '') { throw new DeveloperError(); } } + //>>includeEnd('debug'); - return new ReferenceProperty(dynamicObjectCollection, identifier, values); + return new ReferenceProperty(targetCollection, identifier, values); }; /** @@ -208,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); }; /** @@ -229,8 +264,7 @@ 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) { - var targetProperty = resolve(this); - return defined(targetProperty) && this._targetObject.isAvailable(time) ? targetProperty.getValueInReferenceFrame(time, referenceFrame, result) : undefined; + return resolve(this).getValueInReferenceFrame(time, referenceFrame, result); }; /** @@ -241,8 +275,7 @@ define([ * @returns {String} The type of material. */ ReferenceProperty.prototype.getType = function(time) { - var targetProperty = resolve(this); - return defined(targetProperty) && this._targetObject.isAvailable(time) ? targetProperty.getType(time) : undefined; + return resolve(this).getType(time); }; /** @@ -258,8 +291,8 @@ define([ return true; } - if (this._dynamicObjectCollection !== other._dynamicObjectCollection || // - this._targetObjectId !== other._targetObjectId || // + if (this._targetCollection !== other._targetCollection || // + this._targetId !== other._targetId || // defined(this._targetPropertyNames) !== defined(other._targetPropertyNames) || // this._targetPropertyNames.length !== other._targetPropertyNames.length) { return false; @@ -278,5 +311,24 @@ define([ 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/DynamicScene/ReferencePropertySpec.js b/Specs/DynamicScene/ReferencePropertySpec.js index e8b556aa0f00..80a012497c80 100644 --- a/Specs/DynamicScene/ReferencePropertySpec.js +++ b/Specs/DynamicScene/ReferencePropertySpec.js @@ -1,103 +1,250 @@ /*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']); }).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('fromString throws with undefined targetCollection', function() { expect(function() { - return ReferenceProperty.fromString(undefined, 'object#property'); + return ReferenceProperty.fromString(undefined, 'objectid#property'); }).toThrowDeveloperError(); }); - it('fromString throws if missing string parameter', function() { + it('fromString throws with undefined referenceString', function() { expect(function() { return ReferenceProperty.fromString(new DynamicObjectCollection(), undefined); }).toThrowDeveloperError(); }); - it('fromString throws if invalid string parameter', function() { + it('fromString throws with invalid referenceString', function() { expect(function() { - return ReferenceProperty.fromString(new DynamicObjectCollection(), 'a.b.c'); + return ReferenceProperty.fromString(new DynamicObjectCollection(), 'foo'); }).toThrowDeveloperError(); - }); - it('getValue throws with undefined time', function() { - var property = ReferenceProperty.fromString(new DynamicObjectCollection(), 'object#property'); expect(function() { - property.getValue(undefined); + return ReferenceProperty.fromString(new DynamicObjectCollection(), 'foo#'); + }).toThrowDeveloperError(); + + expect(function() { + return ReferenceProperty.fromString(new DynamicObjectCollection(), '#bar'); }).toThrowDeveloperError(); }); - it('getValue returned undefined for unresolved property', function() { - var property = ReferenceProperty.fromString(new DynamicObjectCollection(), 'object#property'); - expect(property.getValue(new JulianDate())).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('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 property can not be resolved', function() { + var collection = new DynamicObjectCollection(); + + var testObject = new DynamicObject('testId'); + collection.add(testObject); + + var property = ReferenceProperty.fromString(collection, 'testId#billboard'); + 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 sub-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'); + testObject.billboard = new DynamicBillboard(); + collection.add(testObject); - right = new ReferenceProperty(dynamicObjectCollection, 'testObject2', ['property']); - expect(left.equals(right)).toEqual(false); + var property = ReferenceProperty.fromString(collection, 'testId#billboard.foo'); + expect(function() { + property.getValue(time); + }).toThrowRuntimeError(); }); }); \ No newline at end of file From 61846794bd77872260acebfec10ce14740510e54 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Fri, 30 May 2014 16:35:41 -0400 Subject: [PATCH 06/18] Start adding CZML reference property tests --- Specs/DynamicScene/CzmlDataSourceSpec.js | 91 ++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/Specs/DynamicScene/CzmlDataSourceSpec.js b/Specs/DynamicScene/CzmlDataSourceSpec.js index 60b2fb79033b..3e20b8f36a43 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, @@ -1994,4 +1996,93 @@ 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('CZML can use constant reference properies', 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('CZML can use interval reference properies', 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('CZML can use constant position reference properies', 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)); + }); }); From 6437c69dc7b2b8fb8cbdd06c29f51c6660906842 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Mon, 2 Jun 2014 10:53:21 -0400 Subject: [PATCH 07/18] Specs and implementation for CZML reference property parsing. --- Source/DynamicScene/CzmlDataSource.js | 77 ++++++++++++++---------- Specs/DynamicScene/CzmlDataSourceSpec.js | 70 ++++++++++++++++++++- 2 files changed, 113 insertions(+), 34 deletions(-) diff --git a/Source/DynamicScene/CzmlDataSource.js b/Source/DynamicScene/CzmlDataSource.js index 217de59bc885..9e29e6375b10 100644 --- a/Source/DynamicScene/CzmlDataSource.js +++ b/Source/DynamicScene/CzmlDataSource.js @@ -439,11 +439,7 @@ define([ combinedInterval = constrainedInterval; } - if (defined(packetData.reference)) { - object[propertyName] = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); - return; - } - + var isReference = defined(packetData.reference); var unwrappedInterval = unwrapInterval(type, packetData, sourceUri); var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); var packedLength = defaultValue(type.packedLength, 1); @@ -452,7 +448,9 @@ define([ //Any time a constant value is assigned, it completely blows away anything else. if (!isSampled && !hasInterval) { - if (defined(type.unpack)) { + if (isReference) { + object[propertyName] = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); + } else if (defined(type.unpack)) { object[propertyName] = new ConstantProperty(type.unpack(unwrappedInterval, 0)); } else { object[propertyName] = new ConstantProperty(unwrappedInterval); @@ -488,7 +486,9 @@ define([ if (!isSampled && hasInterval) { //Create a new interval for the constant value. combinedInterval = combinedInterval.clone(); - if (defined(type.unpack)) { + if (isReference) { + combinedInterval.data = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); + } else if (defined(type.unpack)) { combinedInterval.data = type.unpack(unwrappedInterval, 0); } else { combinedInterval.data = unwrappedInterval; @@ -496,16 +496,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; } - 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. @@ -522,7 +526,7 @@ 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); } @@ -589,22 +593,30 @@ define([ combinedInterval = constrainedInterval; } - if (defined(packetData.reference)) { - object[propertyName] = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); - return; - } + var isReference = defined(packetData.reference); - var referenceFrame = defaultValue(ReferenceFrame[packetData.referenceFrame], undefined); - var unwrappedInterval = unwrapCartesianInterval(packetData); + var referenceFrame; + var unwrappedInterval; + var isSampled = false; + var unwrappedIntervalLength; var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); var packedLength = Cartesian3.packedLength; - var unwrappedIntervalLength = defaultValue(unwrappedInterval.length, 1); - var isSampled = (typeof unwrappedInterval !== 'string') && unwrappedIntervalLength > packedLength; + + 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] = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); + } else { + object[propertyName] = new ConstantPositionProperty(Cartesian3.unpack(unwrappedInterval), referenceFrame); + } + return; } var property = object[propertyName]; @@ -635,20 +647,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 = ReferenceProperty.fromString(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; } - 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. @@ -665,7 +685,7 @@ 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); } @@ -729,11 +749,6 @@ define([ combinedInterval = constrainedInterval; } - if (defined(packetData.reference)) { - object[propertyName] = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); - return; - } - var property = object[propertyName]; var existingMaterial; var existingInterval; diff --git a/Specs/DynamicScene/CzmlDataSourceSpec.js b/Specs/DynamicScene/CzmlDataSourceSpec.js index 3e20b8f36a43..3991ff1043d2 100644 --- a/Specs/DynamicScene/CzmlDataSourceSpec.js +++ b/Specs/DynamicScene/CzmlDataSourceSpec.js @@ -1997,7 +1997,7 @@ defineSuite([ expect(dynamicObject.wall.maximumHeights.getValue(Iso8601.MINIMUM_VALUE)).toEqual(czmlRectangle.maximumHeights.array); }); - it('CZML can use constant reference properies', function() { + it('Can use constant reference properties', function() { var time = new JulianDate(); var packets = [{ id : 'targetId', @@ -2023,7 +2023,7 @@ defineSuite([ expect(targetObject.point.pixelSize.getValue(time)).toEqual(referenceObject.point.pixelSize.getValue(time)); }); - it('CZML can use interval reference properies', function() { + it('Can use interval reference properties', function() { var packets = [{ id : 'targetId', point : { @@ -2061,7 +2061,7 @@ defineSuite([ expect(targetObject2.point.pixelSize.getValue(time2)).toEqual(referenceObject.point.pixelSize.getValue(time2)); }); - it('CZML can use constant position reference properies', function() { + it('Can use constant reference properties for position', function() { var time = new JulianDate(); var packets = [{ @@ -2085,4 +2085,68 @@ defineSuite([ 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)); + }); }); From 3463a72208c0b6ab594f2ae7fd9157ed4b7e0cbf Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Mon, 2 Jun 2014 13:19:16 -0400 Subject: [PATCH 08/18] Improve ReferenceProperty documentation. --- CHANGES.md | 3 ++ Source/DynamicScene/ReferenceProperty.js | 46 ++++++++++++++++++++---- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 7457bdfba34a..45279f665786 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ Beta Releases * Breaking changes ([why so many?](https://groups.google.com/forum/#!topic/cesium-dev/Y_mG11IZD9k)) * Replaced `Scene.createTextureAtlas` with `new TextureAtlas`. + * CZML property references now use a `#` symbol to separate identifier from property path. `objectId.position` should now be `objectId#position`. * Removed `CameraFlightPath.createAnimationCartographic`. Code that looked like: var flight = CameraFlightPath.createAnimationCartographic(scene, { @@ -47,6 +48,8 @@ Beta Releases * Added `interleave` option to `Primitive` constructor. * Upgraded JSDoc from 3.0 to 3.3.0-alpha5. The Cesium reference documentation now has a slightly different look and feel. * Upgraded Dojo from 1.9.1 to 1.9.3. NOTE: Dojo is only used in Sandcastle and not required by Cesium. +* `DynamicObject.id` can now include period characters. +* `ReferenceProperty` can now handle sub-properties, for example, `myObject#billboard.scale`. ### b28 - 2014-05-01 diff --git a/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index 7575fa31b530..754f27f9e9c7 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -104,6 +104,38 @@ define([ * @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 = new Cesium.ReferenceProperty.fromString(collection, '\#object\.4#billboard.scale']); + * collection.add(object5); */ var ReferenceProperty = function(targetCollection, targetId, targetPropertyNames) { //>>includeStart('debug', pragmas.debug); @@ -131,7 +163,6 @@ define([ defineProperties(ReferenceProperty.prototype, { /** * Gets a value indicating if this property is constant. - * This property always returns true. * @memberof ReferenceProperty.prototype * @type {Boolean} */ @@ -142,8 +173,7 @@ 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. + * The definition is changed whenever the referenced property's definition is changed. * @memberof ReferenceProperty.prototype * @type {Event} */ @@ -154,6 +184,7 @@ define([ }, /** * 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} */ @@ -163,7 +194,7 @@ define([ } }, /** - * Gets the reference frame that the position is defined in. + * Gets the id of the object being referenced. * @memberof ReferenceProperty.prototype * @Type {String} */ @@ -173,7 +204,7 @@ define([ } }, /** - * Gets the reference frame that the position is defined in. + * Gets the collection containing the object being referenced. * @memberof ReferenceProperty.prototype * @Type {DynamicObjectCollection} */ @@ -183,7 +214,7 @@ define([ } }, /** - * Gets the reference frame that the position is defined in. + * Gets the array of property names used to retrieve the referenced property. * @memberof ReferenceProperty.prototype * @Type {String[]} */ @@ -268,7 +299,8 @@ define([ }; /** - * Gets the {@link Material} type at the provided time when the referenced property is a {@link MaterialProperty}. + * Gets the {@link Material} type at the provided time. + * This method is only valid if the property being referenced is a {@link MaterialProperty}. * @memberof ReferenceProperty * * @param {JulianDate} time The time for which to retrieve the type. From d309c79c5cee4adb9b327aac579c48398ee4a406 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Mon, 2 Jun 2014 13:48:29 -0400 Subject: [PATCH 09/18] More ReferenceProperty cleanup. Also make local CZML references work (though implementation is a little hacky right now) --- Source/DynamicScene/CzmlDataSource.js | 23 ++++++++++++++++++----- Source/DynamicScene/ReferenceProperty.js | 6 +++--- Specs/DynamicScene/CzmlDataSourceSpec.js | 20 ++++++++++++++++++++ 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/Source/DynamicScene/CzmlDataSource.js b/Source/DynamicScene/CzmlDataSource.js index 9e29e6375b10..ec426722eae9 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(); @@ -449,7 +458,7 @@ define([ //Any time a constant value is assigned, it completely blows away anything else. if (!isSampled && !hasInterval) { if (isReference) { - object[propertyName] = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); + object[propertyName] = makeReference(dynamicObjectCollection, packetData.reference); } else if (defined(type.unpack)) { object[propertyName] = new ConstantProperty(type.unpack(unwrappedInterval, 0)); } else { @@ -487,7 +496,7 @@ define([ //Create a new interval for the constant value. combinedInterval = combinedInterval.clone(); if (isReference) { - combinedInterval.data = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); + combinedInterval.data = makeReference(dynamicObjectCollection, packetData.reference); } else if (defined(type.unpack)) { combinedInterval.data = type.unpack(unwrappedInterval, 0); } else { @@ -612,7 +621,7 @@ define([ //Any time a constant value is assigned, it completely blows away anything else. if (!isSampled && !hasInterval) { if (isReference) { - object[propertyName] = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); + object[propertyName] = makeReference(dynamicObjectCollection, packetData.reference); } else { object[propertyName] = new ConstantPositionProperty(Cartesian3.unpack(unwrappedInterval), referenceFrame); } @@ -648,7 +657,7 @@ define([ //Create a new interval for the constant value. combinedInterval = combinedInterval.clone(); if (isReference) { - combinedInterval.data = ReferenceProperty.fromString(dynamicObjectCollection, packetData.reference); + combinedInterval.data = makeReference(dynamicObjectCollection, packetData.reference); } else { combinedInterval.data = Cartesian3.unpack(unwrappedInterval); } @@ -870,7 +879,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; @@ -1434,6 +1443,8 @@ define([ objectId = createGuid(); } + currentId = objectId; + if (packet['delete'] === true) { dynamicObjectCollection.removeById(objectId); } else { @@ -1453,6 +1464,8 @@ define([ updaterFunctions[i](dynamicObject, packet, dynamicObjectCollection, sourceUri); } } + + currentId = undefined; } function loadCzml(dataSource, czml, sourceUri) { diff --git a/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index 754f27f9e9c7..5335753fbd2e 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -235,7 +235,7 @@ define([ * * @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(targetCollection, referenceString) { //>>includeStart('debug', pragmas.debug); @@ -252,7 +252,7 @@ define([ //>>includeStart('debug', pragmas.debug); if (tmp.length !== 2 || !defined(identifier) || identifier === '') { - throw new DeveloperError(); + throw new DeveloperError('invalid referenceString.'); } //>>includeEnd('debug'); @@ -263,7 +263,7 @@ define([ for (var i = 0; i < values.length; i++) { var item = values[i]; if (!defined(item) || item === '') { - throw new DeveloperError(); + throw new DeveloperError('invalid referenceString.'); } } //>>includeEnd('debug'); diff --git a/Specs/DynamicScene/CzmlDataSourceSpec.js b/Specs/DynamicScene/CzmlDataSourceSpec.js index 3991ff1043d2..b1fbc9c401d7 100644 --- a/Specs/DynamicScene/CzmlDataSourceSpec.js +++ b/Specs/DynamicScene/CzmlDataSourceSpec.js @@ -2149,4 +2149,24 @@ defineSuite([ 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)); + }); }); From a85c10480939947a77cb5e642cfaf0598cf628df Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Mon, 2 Jun 2014 13:50:01 -0400 Subject: [PATCH 10/18] Move changes to 1.0. --- CHANGES.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 45279f665786..6ad4531dd48c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,11 +4,17 @@ Change Log Beta Releases ------------- +### 1.0 - 2014-07-01 + +* Breaking changes + * 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`. + ### b29 - 2014-06-02 * Breaking changes ([why so many?](https://groups.google.com/forum/#!topic/cesium-dev/Y_mG11IZD9k)) * Replaced `Scene.createTextureAtlas` with `new TextureAtlas`. - * CZML property references now use a `#` symbol to separate identifier from property path. `objectId.position` should now be `objectId#position`. * Removed `CameraFlightPath.createAnimationCartographic`. Code that looked like: var flight = CameraFlightPath.createAnimationCartographic(scene, { @@ -48,8 +54,6 @@ Beta Releases * Added `interleave` option to `Primitive` constructor. * Upgraded JSDoc from 3.0 to 3.3.0-alpha5. The Cesium reference documentation now has a slightly different look and feel. * Upgraded Dojo from 1.9.1 to 1.9.3. NOTE: Dojo is only used in Sandcastle and not required by Cesium. -* `DynamicObject.id` can now include period characters. -* `ReferenceProperty` can now handle sub-properties, for example, `myObject#billboard.scale`. ### b28 - 2014-05-01 From 8bb4ff835be78c9da6f9a9cc5f696cf246c69609 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Mon, 2 Jun 2014 13:53:27 -0400 Subject: [PATCH 11/18] Update outdated doc. --- Source/DynamicScene/ReferenceProperty.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index 5335753fbd2e..0933ae371ff6 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -227,8 +227,9 @@ define([ /** * 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. + * 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. * * @param {DynamicObject} targetCollection * @param {String} referenceString From b10a636d5a2ebacb2cf0f36ddc60c839cf1c8cd3 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Tue, 3 Jun 2014 10:05:23 -0400 Subject: [PATCH 12/18] Fix crash do to use of undefined variable. --- Source/DynamicScene/CzmlDataSource.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Source/DynamicScene/CzmlDataSource.js b/Source/DynamicScene/CzmlDataSource.js index ec426722eae9..b76bcc6d7178 100644 --- a/Source/DynamicScene/CzmlDataSource.js +++ b/Source/DynamicScene/CzmlDataSource.js @@ -448,12 +448,20 @@ define([ combinedInterval = constrainedInterval; } + var packedLength; + var isSampled; + var unwrappedInterval; + var unwrappedIntervalLength; var isReference = defined(packetData.reference); - var unwrappedInterval = unwrapInterval(type, packetData, sourceUri); 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) { @@ -602,14 +610,13 @@ define([ combinedInterval = constrainedInterval; } - var isReference = defined(packetData.reference); - var referenceFrame; var unwrappedInterval; var isSampled = false; var unwrappedIntervalLength; - var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); var packedLength = Cartesian3.packedLength; + var isReference = defined(packetData.reference); + var hasInterval = defined(combinedInterval) && !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL); if (!isReference) { referenceFrame = defaultValue(ReferenceFrame[packetData.referenceFrame], undefined); From 223c00272abbfd4809df40208b5c196a6b94f979 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Wed, 4 Jun 2014 19:13:50 -0400 Subject: [PATCH 13/18] Minor clean up after merge. --- Source/DynamicScene/ReferenceProperty.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index 88cec396cb68..ffcceb351732 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -189,6 +189,7 @@ define([ * This property is only valid if the referenced property is a {@link PositionProperty}. * @memberof ReferenceProperty.prototype * @Type {ReferenceFrame} + * @readonly */ referenceFrame : { get : function() { @@ -199,6 +200,7 @@ define([ * Gets the id of the object being referenced. * @memberof ReferenceProperty.prototype * @Type {String} + * @readonly */ targetId : { get : function() { @@ -209,6 +211,7 @@ define([ * Gets the collection containing the object being referenced. * @memberof ReferenceProperty.prototype * @Type {DynamicObjectCollection} + * @readonly */ targetCollection : { get : function() { @@ -219,6 +222,7 @@ define([ * Gets the array of property names used to retrieve the referenced property. * @memberof ReferenceProperty.prototype * @Type {String[]} + * @readonly */ targetPropertyNames : { get : function() { @@ -228,7 +232,7 @@ define([ }); /** - * Creates a new reference property given the dynamic object collection that will + * 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. From 528b33f634f46ba15e70f90e593b7d4b314f30bb Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Thu, 5 Jun 2014 11:05:38 -0400 Subject: [PATCH 14/18] Changes after review. --- Source/DynamicScene/CzmlDataSource.js | 27 +++++++++++------------- Source/DynamicScene/ReferenceProperty.js | 8 ++----- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/Source/DynamicScene/CzmlDataSource.js b/Source/DynamicScene/CzmlDataSource.js index b76bcc6d7178..51c40e529094 100644 --- a/Source/DynamicScene/CzmlDataSource.js +++ b/Source/DynamicScene/CzmlDataSource.js @@ -1758,11 +1758,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. - * @param {DynamicObjectCollection} [dynamicObjectCollection] The collection being processsed. - * @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; @@ -1773,11 +1772,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. - * @param {DynamicObjectCollection} [dynamicObjectCollection] The collection being processsed. - * @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; @@ -1788,11 +1786,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. - * @param {DynamicObjectCollection} [dynamicObjectCollection] The collection being processsed. - * @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 ffcceb351732..0eeb32375480 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -33,13 +33,9 @@ define([ var names = that._targetPropertyNames; - targetProperty = targetObject[names[0]]; - if (!defined(targetProperty)) { - throw new RuntimeError('targetProperty could not be resolved.'); - } - + targetProperty = targetObject; var length = names.length; - for (var i = 1; i < length; i++) { + for (var i = 0; i < length; i++) { targetProperty = targetProperty[names[i]]; if (!defined(targetProperty)) { throw new RuntimeError('targetProperty could not be resolved.'); From 4ab926197b5c00cbadb931576aea8e164ac475ba Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Thu, 5 Jun 2014 14:53:16 -0400 Subject: [PATCH 15/18] Changes after review. --- Source/DynamicScene/ReferenceProperty.js | 89 ++++++++------------- Specs/DynamicScene/ReferencePropertySpec.js | 3 +- 2 files changed, 33 insertions(+), 59 deletions(-) diff --git a/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index 0eeb32375480..771bb9996f33 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -47,50 +47,6 @@ define([ return targetProperty; } - function findUnescaped(value, start, delimiter) { - var index; - do { - index = value.indexOf(delimiter, start); - if (index === -1) { - break; - } - - var count = 0; - var place = index - 1; - while (place !== -1 && value[place--] === '\\') { - count++; - } - if (count % 2 === 0) { - return index; - } - start = index + 1; - } while (index !== -1); - return -1; - } - - function trySplit(value, delimiter) { - var indices = []; - var start = 0; - var index; - do { - index = findUnescaped(value, start, delimiter); - if (index !== -1) { - indices.push(index); - start = index + 1; - } - } while (index !== -1); - - var lastIndex = 0; - var result = new Array(indices.length + 1); - for (var i = 0; i < indices.length; i++) { - index = indices[i]; - result[i] = value.substring(lastIndex, index).replace('\\#', '#').replace('\\\\', '\\').replace('\\.', '.'); - lastIndex = index + 1; - } - result[indices.length] = value.substring(lastIndex).replace('\\#', '#').replace('\\\\', '\\').replace('\\.', '.'); - return result; - } - /** * A {@link Property} which transparently links to another property on a provided object. * @@ -130,7 +86,7 @@ define([ * * var object5 = new Cesium.DynamicObject('object5'); * object5.billboard = new Cesium.DynamicBillboard(); - * object5.billboard.scale = new Cesium.ReferenceProperty.fromString(collection, '\#object\.4#billboard.scale']); + * object5.billboard.scale = Cesium.ReferenceProperty.fromString(collection, '\\#object\\.4#billboard.scale'); * collection.add(object5); */ var ReferenceProperty = function(targetCollection, targetId, targetPropertyNames) { @@ -141,8 +97,8 @@ define([ if (!defined(targetId)) { throw new DeveloperError('targetId is required.'); } - if (!defined(targetPropertyNames)) { - throw new DeveloperError('targetPropertyName is required.'); + if (!defined(targetPropertyNames) || targetPropertyNames.length === 0) { + throw new DeveloperError('targetPropertyNames is required.'); } //>>includeEnd('debug'); @@ -250,20 +206,40 @@ define([ } //>>includeEnd('debug'); - var tmp = trySplit(referenceString, '#'); - var identifier = tmp[0]; + var identifier; + var values = []; + + var inIdentifier = true; + var isEscaped = false; + var token = ''; + var i; + for (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; + } + } + values.push(token); //>>includeStart('debug', pragmas.debug); - if (tmp.length !== 2 || !defined(identifier) || identifier === '') { + if (identifier === '' || values.length === 0) { throw new DeveloperError('invalid referenceString.'); } - //>>includeEnd('debug'); - var index = findUnescaped(referenceString, 0, '#') + 1; - var values = trySplit(referenceString.substring(index), '.'); - - //>>includeStart('debug', pragmas.debug); - for (var i = 0; i < values.length; i++) { + for (i = 0; i < values.length; i++) { var item = values[i]; if (!defined(item) || item === '') { throw new DeveloperError('invalid referenceString.'); @@ -324,7 +300,6 @@ define([ if (this._targetCollection !== other._targetCollection || // this._targetId !== other._targetId || // - defined(this._targetPropertyNames) !== defined(other._targetPropertyNames) || // this._targetPropertyNames.length !== other._targetPropertyNames.length) { return false; } diff --git a/Specs/DynamicScene/ReferencePropertySpec.js b/Specs/DynamicScene/ReferencePropertySpec.js index 80a012497c80..15a2e71aa3cc 100644 --- a/Specs/DynamicScene/ReferencePropertySpec.js +++ b/Specs/DynamicScene/ReferencePropertySpec.js @@ -55,9 +55,8 @@ defineSuite([ it('fromString works with escaped values', function() { var collection = new DynamicObjectCollection(); - var objectId = '#identif\\\\#ier.'; + var objectId = '#identif\\#ier.'; var propertyNames = ["propertyName", ".abc\\", "def"]; - var property = ReferenceProperty.fromString(collection, '\\#identif\\\\\\#ier\\.#propertyName.\\.abc\\\\.def'); expect(property.targetCollection).toBe(collection); From 93505e4ae44124c06695b18323daa96a000c7c74 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Thu, 5 Jun 2014 14:58:10 -0400 Subject: [PATCH 16/18] Clean up doc. --- Source/DynamicScene/ReferenceProperty.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index 771bb9996f33..04828733f238 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -187,7 +187,8 @@ define([ * 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. + * property path and . separates sub-properties. If the reference identifier or + * or any sub-properties contains a # . or \ they must be escaped. * * @param {DynamicObject} targetCollection * @param {String} referenceString From 5acc86d8ecd194a13c0d8eca7c16c605d9963415 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Thu, 5 Jun 2014 15:11:23 -0400 Subject: [PATCH 17/18] More cleanup after review. --- Source/DynamicScene/ReferenceProperty.js | 32 ++++++++------------- Specs/DynamicScene/ReferencePropertySpec.js | 12 ++++++++ 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index d404f588532c..eb7c0da4f7fb 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -94,12 +94,18 @@ define([ if (!defined(targetCollection)) { throw new DeveloperError('targetCollection is required.'); } - if (!defined(targetId)) { + if (!defined(targetId) || targetId === '') { throw new DeveloperError('targetId 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('invalid referenceString.'); + } + } //>>includeEnd('debug'); this._targetCollection = targetCollection; @@ -212,8 +218,7 @@ define([ var inIdentifier = true; var isEscaped = false; var token = ''; - var i; - for (i = 0; i < referenceString.length; ++i) { + for (var i = 0; i < referenceString.length; ++i) { var c = referenceString.charAt(i); if (isEscaped) { @@ -234,19 +239,6 @@ define([ } values.push(token); - //>>includeStart('debug', pragmas.debug); - if (identifier === '' || values.length === 0) { - throw new DeveloperError('invalid referenceString.'); - } - - for (i = 0; i < values.length; i++) { - var item = values[i]; - if (!defined(item) || item === '') { - throw new DeveloperError('invalid referenceString.'); - } - } - //>>includeEnd('debug'); - return new ReferenceProperty(targetCollection, identifier, values); }; @@ -297,15 +289,15 @@ define([ return true; } + var names = this._targetPropertyNames; + var otherNames = other._targetPropertyNames; + if (this._targetCollection !== other._targetCollection || // this._targetId !== other._targetId || // - this._targetPropertyNames.length !== other._targetPropertyNames.length) { + names.length !== otherNames.length) { return false; } - var names = this._targetPropertyNames; - var otherNames = other._targetPropertyNames; - var length = this._targetPropertyNames.length; for (var i = 0; i < length; i++) { if (names[i] !== otherNames[i]) { diff --git a/Specs/DynamicScene/ReferencePropertySpec.js b/Specs/DynamicScene/ReferencePropertySpec.js index 15a2e71aa3cc..dca76cd43d26 100644 --- a/Specs/DynamicScene/ReferencePropertySpec.js +++ b/Specs/DynamicScene/ReferencePropertySpec.js @@ -188,6 +188,18 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('constructor throws with empty targetPropertyNames', function() { + expect(function() { + return new ReferenceProperty(new DynamicObjectCollection(), 'objectId', []); + }).toThrowDeveloperError(); + }); + + it('constructor throws with empty targetId', function() { + expect(function() { + return new ReferenceProperty(new DynamicObjectCollection(), '', ['property']); + }).toThrowDeveloperError(); + }); + it('fromString throws with undefined targetCollection', function() { expect(function() { return ReferenceProperty.fromString(undefined, 'objectid#property'); From 0c83811c8f2406a92e138d4d34a10f53c9cef039 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Thu, 5 Jun 2014 15:30:20 -0400 Subject: [PATCH 18/18] Improve error message. --- Source/DynamicScene/ReferenceProperty.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/DynamicScene/ReferenceProperty.js b/Source/DynamicScene/ReferenceProperty.js index eb7c0da4f7fb..668ab0d02e81 100644 --- a/Source/DynamicScene/ReferenceProperty.js +++ b/Source/DynamicScene/ReferenceProperty.js @@ -103,7 +103,7 @@ define([ for (var i = 0; i < targetPropertyNames.length; i++) { var item = targetPropertyNames[i]; if (!defined(item) || item === '') { - throw new DeveloperError('invalid referenceString.'); + throw new DeveloperError('reference contains invalid properties.'); } } //>>includeEnd('debug');