tangram
tangram copied to clipboard
Allow draw groups to `freeze` parameter values through sub-layers
OK a couple years later I'm returning to this override issue #576. Here's my latest attempt...
This introduces a freeze keyword to draw groups. When a draw group contains the value freeze: true, any values in that group (only those values defined "locally" in the same immediate block as the freeze keyword) will be "frozen", meaning they will be unaffected by other draw group values, either from child/descendants in the same layer tree, or from parallel/sibling layer trees.
The simplest way to think of this is that it will create a draw group with infinite layer depth, and that is how it is implemented: after all draw groups are merged across both "across" (parallel layer trees) and "down" (layer -> sub-layers) with existing logic, any frozen groups are then additionally applied, as if they were in the next sub-layer down.
On balance, I think this is a helpful solution, but still has potential issues and is just a tricky problem to solve... suggestions welcome! The implementation footprint is small, it's more a matter of getting the logic right (in a way that keeps the implementation simple/performant :)
Basemap override
Returning to one of the common cases where you want to "globally" override one or more values, here is an example that re-colors all roads in an imported Refill:
import:
- https://www.nextzen.org/carto/refill-style/12/refill-style.zip
- https://www.nextzen.org/carto/refill-style/12/themes/label-10.zip
layers:
roads:
override-colors:
draw:
lines:
freeze: true
color: red
outline:
color: darkred
No matter what other draw groups are defined, at the end of the draw group merge process, an additional draw group that looks like this will be applied:
draw:
lines:
color: red
outline:
color: darkred
This yields the following:

Priority
These draw groups are applied with the same priority/specificity as any other layer, so if you have two or more conflicting "frozen" groups...
override-colors2 will win over override-colors, because it has a higher priority due to last-alphabetical-layer-name-wins logic:
layers:
roads:
override-colors:
draw:
lines:
freeze: true
color: red
outline:
color: darkred
override-colors2:
draw:
lines:
freeze: true
color: blue
outline:
color: darkblue
override-colors will win over override-colors2, because it has a higher explicit priority defined:
layers:
roads:
override-colors:
priority: 1
draw:
lines:
freeze: true
color: red
outline:
color: darkred
override-colors2:
priority: 2
draw:
lines:
freeze: true
color: blue
outline:
color: darkblue
Similarly, if a layer marked exclusive matches, it will take precedence.
Freeze at multiple levels
A child layer won't modify values of its frozen ancestor, e.g. in this case, the child layer won't change the color, which will remain frozen as red:
layers:
roads:
override-colors:
draw:
lines:
freeze: true
color: red
outline:
color: darkred
child:
draw:
lines:
color: yellow # has no effect because ancestor layer is frozen
If multiple levels of the tree contain freeze: true, they are merged, but with inverse priority from the normal deepest-level-wins logic: instead, the higher-up/ancestor groups will win (does this make sense, or is it backwards...? I'm trying to think through the use cases). Also as a result, marking a descendant draw group as freeze: false has no effect (though I suppose this could be useful, as a way to say "you definitely cannot override this value"?).
Imports
There's a potential gotcha with imports (which would be likely to be mixed with this feature due to its nature), in that if you are importing an existing draw group and then applying freeze to it, you're also going to freeze the whole draw group, including any properties that were imported -- because import merges happen at the beginning of scene parsing, long before layers are parsed and merged (and it's likely not really practical to change that).
That's why in the example above, a top-level draw group with no filter and adjacent to others was created, called override-colors, rather than just applying freeze to the existing top-level draw group under the roads layer.
Call for comments... @matteblair @nvkelso @meetar @burritojustice
Seems useful, though I find the name freeze confusing. Is there a more common term for this?
Ha, yeah I've always struggled with naming this. Freeze was just the closest conceptual match I could find to what's happening. In CSS there is important, but that is... worse IMO. Happy for alternatives.
From my understanding of the feature maybe final: true is a good name? Maybe too OOP-ish though. Still trying to grok all the cases here.
Yeah, CSS !important, ftw ;) What about?
prevailevaluate_last
Others:
freezefinal
prevail lol
winner: true
On Fri, May 3, 2019 at 3:05 PM Nathaniel V. KELSO [email protected] wrote:
Yeah, CSS !important, ftw ;) What about?
- prevail
- evaluate_last
Others:
- freeze
- final
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/tangrams/tangram/pull/717#issuecomment-489206237, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAECXOMQPJWFYV732DBQWDPTSEGPANCNFSM4HKVNGCQ .
Decided not to pursue this.