Extending Cesium Viewer Widget

I'm creating an app that wraps the functionality of the Cesium Viewer Widget by overlaying some UI elements and adding some custom business logic, and I was wondering what the best way would be to incorporate the Cesium and Cesium Viewer Widget into my project.

Right now my build script just copies the files from the CesiumViewer app that is in the release zip file, but I noticed I'm having issues if I need to modify anything in the widget (add functions, remove buttons, etc.). Sometimes I can modify things in the widget, but other things seem to be integrated into the dojo.js file in the dojo directory of the CesiumViewer app. Should I be running the Cesium build script within my build instead, or doing something else entirely?

Thanks,

Jon

Hi Jon,

The Cesium Viewer Widget is unfortunately one of the rougher edges of Cesium at the moment, but there’s been a lot of recent discussion about how to improve things. The Dojo-based CesiumViewerWidget was always intended to be merely one of several options for building applications, though we haven’t managed to build those alternatives yet.

Scott,

Thank you for the quick reply. We were previously not using a framework to build the javascript side of our application, but I’ve since created a dojo-based build for our javascript, referencing the Cesium (b13) AMD modules directly, as you suggested.

It works well, and the minified/optimized production build works great, but we’re seeing a strange issue when we try and run the app from the unbuilt javascript. Everything works as in production, but we have some code which highlights a polygon when the user clicks on it which is not working as expected. In the development mode, Cesium crashes when a user clicks on a polygon. The stack trace I get is:

  1. Uncaught TypeError: Cannot assign to read only property ‘red’ of (1, 1, 0, 1) CzmlColor.js:99

  2. CzmlColor.getValueCzmlColor.js:99

  3. DynamicProperty.getValueDynamicProperty.js:241

  4. DynamicColorMaterial.getValueDynamicColorMaterial.js:73

  5. DynamicMaterialProperty.getValueDynamicMaterialProperty.js:72

  6. DynamicPolygonVisualizer._updateObjectDynamicPolygonVisualizer.js:231

  7. DynamicPolygonVisualizer.updateDynamicPolygonVisualizer.js:104

  8. VisualizerCollection.updateVisualizerCollection.js:119

  9. declare.updateCesiumViewerWidget.js:1067

  10. updateAndRenderCesiumViewerWidget.js:1209

And here is the highlight code:

onObjectSelected : function(selectedObject)

{

var selected = selectedObject !== undefined;

widget.highlightObject(selectedObject);

var objectSelected = selected && selectedObject.material && selectedObject.material.uniforms;

if (objectSelected)

{

selectedObject.material.uniforms.color = Color.YELLOW;

selectedObjectId = selectedObject.dynamicObject.id;

}

}

Any ideas? I can open a new thread if you think it’s not related to my build. Again, this code works in the production build.

Thanks again,

Jon

Try changing

selectedObject.material.uniforms.color = Color.YELLOW;

to

selectedObject.material.uniforms.color = Color.YELLOW.clone(selectedObject.material.uniforms.color);

Color.YELLOW is a frozen object, so it can’t be modified. The CZML processing is trying to modify selectedObject.material.uniforms.color rather than assign it (for performance reasons) which is leading to this problem. I think we can probably change the way visualizers work to avoid issues like this in the future, but in general it’s a good idea to clone constants rather than assign them directly because you never know who might want to change that value later.

Thanks, I’ll try that tonight!

Jon

Unfortunately this isn’t working. No more crashing, but now there’s no change in color.

I notice that if I create primitives on the globe I can highlight/unhighlight them fine, but these objects, which are loaded from CZML, don’t seem to respond to any changes in their display properties.

Jon

I suspect the problem now is that the CZML visualizers are overwriting the color each frame with the color that the CZML data specifies. The visualizers don’t know that you’ve intentionally overridden the color, so each update it calculates what the color is supposed to be for the current time and sets it.

In the future, we’ll have some API for overriding CZML properties, but for now, I can think of two workarounds:

  1. Instead of changing the color when the object is selected, change the color of the selected object later, during the update function, after the call to this.visualizers.update(currentTime);. That way your overrides happen after the visualizers set the state of the primitives.

  2. (more complicated) Maintain two DynamicObjectCollections, one for the CZML data, and one for client-side overrides. Combine those two collections into a CompositeDynamicObjectCollection, and give that composite collection to the visualizers. Then, you can create dynamic properties for your objects in the client-side collection that can return calculated values. This is how our “Lots of Satellites” demo does highlighting. Some example code:

var clientObjects = new DynamicObjectCollection();

var satellites = new DynamicObjectCollection();

var compositeCollection = new CompositeDynamicObjectCollection([satellites, clientObjects]);

Scott,

Makes sense. As a quick fix we implemented your first option, but since in the future (imminently) we’ll need to add things like allowing the user to select multiple CZML objects at a time, we’re going to write some more custom code, probably like your second option, to handle that and add it to the CesiumViewerWidget. I’ll keep you updated and let you know what we come up with.

Jon

Success (for now). I ended up adding the following functions to the CesiumViewerWidget:

/**

  • Highlight an object in the scene, usually in response to a click or hover.