Styling Tilesets


One of the most important aspects of rendering your data is control over how it's presented. Styling for Tilesets is limited as they're an optimized way to render large amounts of data, but there are still some options available.

Within this article we'll cover how to manage Styles for Tileset Menu Items.

Style records

The most commonly used process is setting up a Style through our Operator app then pointing your Menu Item at the record's ID.

Tilesets are collections of Entities which may be different types. The Menu Item will let you map Entity Types to Styles, and you can also set a default Style for the Tileset as a whole.

Warning, it is highly recommended to avoid Styles that require attributes for your Tileset as a whole as it will require larger amounts of data to be downloaded and processed. It's best to get as specific as you can with the Entity Type mapping.

Typescript
Javascript
import { MenuItemCreator } from "bruce-cesium";
import { ObjectUtils } from "bruce-models";

// If set to "0" then it'll load the default Style for the Entity Type.
// Eg: if an Entity has the Entity Type "Building" then it'll use the Building's default Style.
const someStyleId = 1;

// Let's try render one of our Tilesets using this record:
MenuItemCreator.RenderMenuItems({
    viewer: viewer,
    menuItems: [
        {
            // This can be any string ID, just as long as it doesn't clash with other Menu Items.
            // If you're lazy and testing stuff, you can simply use the ID: "1" or similar.
            id: ObjectUtils.UId(),
            // Caption is useful in case a UI panel renders your Menu Item.
            Caption: "Assembly-A",
            Type: "ModelTileset",
            tileset: {
                TilesetID: "my-tileset-id"
            },
            // This is your fallback Style when no specific Entity Type mapping is found.
            // Set this to 0 so that it'll use the Entity Type's default Style.
            styleId: 0,
            StyleMapping: [
                {
                    "EntityTypeID": "some-entity-type-id",
                    "StyleID": someStyleId
                }
            ],
            // This is a setting to control how the Style colour blends with the model's original colour.
            // Some textures don't blend very well with the Style colour so we can favour the Style colour more.
            StyleBlending: {
                // Hightlight = 0, replace = 1, mix = 2.
                blendMode: 2,
                // 1 = 100% style colour. 0 = original model colour.
                blendPercent: 0.8
            }
        }
    ]
});

If you'd like to let the user pick a Style from what is available. You can request the information like so:

Typescript
Javascript
import { Style } from "bruce-models";

Style.GetList({}).then((data) => {
    // There are other kinds of Styles so let's ensure we only let the user pick from entity ones.
    const entityStyles = data.styles.filter(x => !x.Type || x.Type == Style.EType.Entity);
    console.log("Entity Styles", entityStyles);

    // Styles have a "Name" property for the user to choose from,
    // then an "ID" property for you to pass to the Menu Item.
});

Programmatic Styles

We of course allow you to avoid having to deal with Style records and define your own programmatically.
We will cover the Style syntax in a separate article. Below is an example of how to use it.

Please note that the current version only lets you write programmatic Styles per-Entity-Type rather than the Tileset as a whole.

Typescript
Javascript
import { MenuItemCreator } from "bruce-cesium";
import { ObjectUtils, PathUtils, Calculator } from "bruce-models";

const style = {
    modelStyle: {
    // Set to customize so we directly know that we should be colouring your model.
    customize: true,
    fillColor: [
        {
            value: {
                // The Wrap utility ensures the path will be readable by the style calculator.
                // If your attribute is nested, simply pass the path array into the function, eg: ["location", "longitude"].
                field: PathUtils.Wrap(["Example"]),
                // The mapping type is a simple mapping of values to colours.
                // In this case we're looking for two specific example values and assigning them colours.
                values: [
                    {
                        fieldValue: "A",
                        appliedValue: "#DC143C"
                    },
                    {
                        fieldValue: "B",
                        appliedValue: "#7FFF00"
                    }
                ]
            },
            type: Calculator.EValueType.Mapping
        },
        // Optional default if no above options resolved into anything.
        // Remove if you don't want stuff coloured when the above mapping isn't found.
        {
            value: "rgba(255, 255, 255, 0.4)",
            type: Calculator.EValueType.Color
        }
    ]
};

MenuItemCreator.RenderMenuItems({
    viewer: viewer,
    menuItems: [
        {
            id: ObjectUtils.UId(),
            Caption: "Assembly-A",
            Type: "ModelTileset",
            tileset: {
                TilesetID: "my-tileset-id"
            },
            styleId: 0,
            StyleMapping: [
                {
                    EntityTypeID: "some-entity-type-id",
                    // Set this to -1 to use a programmatic Style.
                    StyleID: -1,
                    // Define the Style JSON here.
                    // This will outline a basic style which colours models where the attribute "Example" is set to "A" or "B".
                    Style: style
                }
            ],
            StyleBlending: {
                blendMode: 2,
                blendPercent: 0.8
            }
        }
    ]
});

If you'd like re-render your Entity in the scene so the Style is refreshed, read through the Entity Interaction documentation.

Changing Styles

Recently we've added the ability to change what Styles are enabled within a Menu Item. That way if your setup is user driven you don't have to re-enable the Menu Item to update your Entities.

Below is a simple example where we change the Style of a Menu Item after it's been created.

Typescript
Javascript
import { Calculator, PathUtils, Style } from "bruce-models";

const menuItem = manager.GetEnabledItem("my-menu-item-id");
const renderManager = menuItem.renderManager;

// Style that will look at the "temperature" attribute and colour things red if it's between 60 and 200.
// It will fall back to white if the condition is not met.
// Pure white in the render engine means no colouring.

const style = {
    ID: -1,
    Name: "Colour hot areas",
    Settings: {
        modelStyle: {
            customize: true,
            fillColor: [
                {
                    type: Calculator.EValueType.Mapping,
                    value: {
                        field: PathUtils.Wrap(["temperature]),
                        values: [{
                            fieldValue: "60-200",
                            appliedValue: "red"
                        }]
                    }
                },
                {
                    type: Calculator.EValueType.Input,
                    value: "white"
                }
            ]
        }
    } as Style.IEntitySettings,
    Type: Style.EType.Entity
};

renderManager.Styler.UpdateStyleMapping({
    // No per Type options.
    styleMapping: [],
    // -1 means don't use default styles for unspecified Entity Types.
    fallbackStyleId: -1,
    // Let's style all Entities with the attribute.
    fallbackStyle: style
});

If you'd like re-render your Entity in the scene so the Style is refreshed, read through the Entity Interaction documentation.