Skip to content

Commit

Permalink
improve theme lookup (#2610)
Browse files Browse the repository at this point in the history
* improve theme lookup

* fix regressions or so

* fix wglmakie

* fix mesh

* precompile

* fix WGLMakie + cleanup primitive docs

* fix wglmakie

* fix wglmakie

* start fixing theming sub figures a bit

* wglmakie needed clear=false

* inherent parent theme, but copy
  • Loading branch information
SimonDanisch committed Jan 26, 2023
1 parent cfe47e8 commit fa5e6b3
Show file tree
Hide file tree
Showing 14 changed files with 130 additions and 109 deletions.
2 changes: 1 addition & 1 deletion CairoMakie/src/primitives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,7 @@ function draw_pattern(ctx, zorder, shading, meshfaces, ts, per_face_col, ns, vs,
Cairo.paint(ctx)
Cairo.destroy(pattern)
end

end

################################################################################
Expand Down
43 changes: 36 additions & 7 deletions MakieCore/src/basic_plots.jl
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ Available algorithms are:
colorrange = (0, 1),
fxaa = true,
inspectable = theme(scene, :inspectable),
space = :data
space = :data,
diffuse=0.4,
specular=0.2,
shininess=32.0f0
)
end

Expand Down Expand Up @@ -210,7 +213,10 @@ Plots a surface, where `(x, y)` define a grid whose heights are the entries in
fxaa = true,
invert_normals = false,
inspectable = theme(scene, :inspectable),
space = :data
space = :data,
diffuse = 0.4,
specular = 0.2,
shininess = 32f0,
)
end

Expand Down Expand Up @@ -320,9 +326,9 @@ Plots a 3D or 2D mesh. Supported `mesh_object`s include `Mesh` types from [Geome
- `colormap::Union{Symbol, Vector{<:Colorant}} = :viridis` sets the colormap that is sampled for numeric `color`s.
- `colorrange::Tuple{<:Real, <:Real}` sets the values representing the start and end points of `colormap`.
- `nan_color::Union{Symbol, <:Colorant} = RGBAf(0,0,0,0)` sets a replacement color for `color = NaN`.
- `lowclip::Union{Automatic, Symbol, <:Colorant} = automatic` sets a color for any value below the colorrange.
- `highclip::Union{Automatic, Symbol, <:Colorant} = automatic` sets a color for any value above the colorrange.
- `space::Symbol = :data` sets the transformation space for vertex positions. See `Makie.spaces()` for possible inputs.
- `lowclip::Union{Nothing, Symbol, <:Colorant} = nothing` sets a color for any value below the colorrange.
- `highclip::Union{Nothing, Symbol, <:Colorant} = nothing` sets a color for any value above the colorrange.
- `interpolate::Bool = true` wether color=Matrix gets interpolated or not
### Generic 3D
Expand All @@ -348,7 +354,10 @@ Plots a 3D or 2D mesh. Supported `mesh_object`s include `Mesh` types from [Geome
fxaa = true,
inspectable = theme(scene, :inspectable),
cycle = [:color => :patchcolor],
space = :data
space = :data,
diffuse = 0.4,
specular = 0.2,
shininess = 32f0,
)
end

Expand Down Expand Up @@ -387,6 +396,8 @@ Plots a marker for each element in `(x, y, z)`, `(x, y)`, or `positions`.
- `colormap::Union{Symbol, Vector{<:Colorant}} = :viridis` sets the colormap that is sampled for numeric `color`s.
- `colorrange::Tuple{<:Real, <:Real}` sets the values representing the start and end points of `colormap`.
- `nan_color::Union{Symbol, <:Colorant} = RGBAf(0,0,0,0)` sets a replacement color for `color = NaN`.
- `lowclip::Union{Automatic, Symbol, <:Colorant} = automatic` sets a color for any value below the colorrange.
- `highclip::Union{Automatic, Symbol, <:Colorant} = automatic` sets a color for any value above the colorrange.
- `space::Symbol = :data` sets the transformation space for positions of markers. See `Makie.spaces()` for possible inputs.
"""
@recipe(Scatter, positions) do scene
Expand All @@ -395,6 +406,10 @@ Plots a marker for each element in `(x, y, z)`, `(x, y)`, or `positions`.
color = theme(scene, :markercolor),
colormap = theme(scene, :colormap),
colorrange = automatic,
lowclip = automatic,
highclip = automatic,
nan_color = :transparent,

marker = theme(scene, :marker),
markersize = theme(scene, :markersize),

Expand Down Expand Up @@ -446,6 +461,8 @@ Plots a mesh for each element in `(x, y, z)`, `(x, y)`, or `positions` (similar
- `colormap::Union{Symbol, Vector{<:Colorant}} = :viridis` sets the colormap that is sampled for numeric `color`s.
- `colorrange::Tuple{<:Real, <:Real}` sets the values representing the start and end points of `colormap`.
- `nan_color::Union{Symbol, <:Colorant} = RGBAf(0,0,0,0)` sets a replacement color for `color = NaN`.
- `lowclip::Union{Automatic, Symbol, <:Colorant} = automatic` sets a color for any value below the colorrange.
- `highclip::Union{Automatic, Symbol, <:Colorant} = automatic` sets a color for any value above the colorrange.
- `space::Symbol = :data` sets the transformation space for the positions of meshes. See `Makie.spaces()` for possible inputs.
### Generic 3D
Expand All @@ -462,6 +479,10 @@ Plots a mesh for each element in `(x, y, z)`, `(x, y)`, or `positions` (similar
color = :black,
colormap = theme(scene, :colormap),
colorrange = automatic,
lowclip = automatic,
highclip = automatic,
nan_color = :transparent,

marker = :Sphere,
markersize = 0.1,
rotations = 0.0,
Expand All @@ -471,6 +492,9 @@ Plots a mesh for each element in `(x, y, z)`, `(x, y)`, or `positions` (similar
fxaa = true,
inspectable = theme(scene, :inspectable),
cycle = [:color],
diffuse = 0.4,
specular = 0.2,
shininess = 32f0,
)
end

Expand Down Expand Up @@ -555,8 +579,8 @@ Plots polygons, which are defined by
### Specific to `Poly`
- `lowclip::Union{Nothing, Symbol, <:Colorant} = nothing` sets a color for any value below the colorrange.
- `highclip::Union{Nothing, Symbol, <:Colorant} = nothing` sets a color for any value above the colorrange.
- `lowclip::Union{Automatic, Symbol, <:Colorant} = automatic` sets a color for any value below the colorrange.
- `highclip::Union{Automatic, Symbol, <:Colorant} = automatic` sets a color for any value above the colorrange.
- `strokecolor::Union{Symbol, <:Colorant} = :black` sets the color of the outline around a marker.
- `strokewidth::Real = 0` sets the width of the outline around a marker.
- `linestyle::Union{Nothing, Symbol, Vector} = nothing` sets the pattern of the line (e.g. `:solid`, `:dot`, `:dashdot`)
Expand All @@ -572,6 +596,8 @@ Plots polygons, which are defined by
- `colormap::Union{Symbol, Vector{<:Colorant}} = [:black, :white` sets the colormap that is sampled for numeric `color`s.
- `colorrange::Tuple{<:Real, <:Real}` sets the values representing the start and end points of `colormap`.
- `nan_color::Union{Symbol, <:Colorant} = RGBAf(0,0,0,0)` sets a replacement color for `color = NaN`.
- `lowclip::Union{Automatic, Symbol, <:Colorant} = automatic` sets a color for any value below the colorrange.
- `highclip::Union{Automatic, Symbol, <:Colorant} = automatic` sets a color for any value above the colorrange.
- `space::Symbol = :data` sets the transformation space for the position of the image. See `Makie.spaces()` for possible inputs.
- `cycle::Vector{Symbol} = [:color => :patchcolor]` sets which attributes to cycle when creating multiple plots.
- `shading = false` enables lighting.
Expand Down Expand Up @@ -623,6 +649,9 @@ end
quality = 32,
inspectable = theme(scene, :inspectable),
markerspace = :pixel,
diffuse=0.4,
specular=0.2,
shininess=32.0f0
)
)
attr[:fxaa] = automatic
Expand Down
21 changes: 16 additions & 5 deletions WGLMakie/src/imagelike.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ using Makie: el32convert, surface_normals, get_dim
nothing_or_color(c) = to_color(c)
nothing_or_color(c::Nothing) = RGBAf(0, 0, 0, 1)

lift_or(f, x) = f(x)
lift_or(f, x::Observable) = lift(f, x)

function draw_mesh(mscene::Scene, mesh, plot; uniforms...)
uniforms = Dict(uniforms)
filter!(kv -> !(kv[2] isa Function), uniforms)
Expand Down Expand Up @@ -33,6 +36,9 @@ function draw_mesh(mscene::Scene, mesh, plot; uniforms...)
return transpose(inv(v[i, i] * m[i, i]))
end

for key in (:diffuse, :specular, :shininess, :backlight)
uniforms[key] = lift_or(x -> convert_attribute(x, Key{key}()), uniforms[key])
end
# id + picking gets filled in JS, needs to be here to emit the correct shader uniforms
uniforms[:picking] = false
uniforms[:object_id] = UInt32(0)
Expand Down Expand Up @@ -128,9 +134,9 @@ function create_shader(mscene::Scene, plot::Union{Heatmap, Image})
return draw_mesh(mscene, mesh, plot_attributes;
uniform_color=color, color=false,
normals=Vec3f(0), shading=false,
diffuse=plot.diffuse, specular=plot.specular,
diffuse=Vec3f(0), specular=Vec3f(0),
shininess=0f0,
colorrange=haskey(plot, :colorrange) ? plot.colorrange : false,
shininess=plot.shininess,
highclip=get_color(plot, :highclip),
lowclip=get_color(plot, :lowclip),
nan_color=get_color(plot, :nan_color),
Expand All @@ -152,6 +158,11 @@ function create_shader(mscene::Scene, plot::Volume)

modelinv = lift(inv, model2)
algorithm = lift(x -> Cuint(convert_attribute(x, key"algorithm"())), plot.algorithm)

diffuse = lift(x -> convert_attribute(x, Key{:diffuse}()), plot.diffuse)
specular = lift(x -> convert_attribute(x, Key{:specular}()), plot.specular)
shininess = lift(x -> convert_attribute(x, Key{:shininess}()), plot.shininess)

uniforms = Dict{Symbol, Any}(
:volumedata => Sampler(lift(Makie.el32convert, vol)),
:modelinv => modelinv,
Expand All @@ -161,9 +172,9 @@ function create_shader(mscene::Scene, plot::Volume)
:isorange => lift(Float32, plot.isorange),
:absorption => lift(Float32, get(plot, :absorption, Observable(1.0f0))),
:algorithm => algorithm,
:diffuse => plot.diffuse,
:specular => plot.specular,
:shininess => plot.shininess,
:diffuse => diffuse,
:specular => specular,
:shininess => shininess,
:model => model2,
:depth_shift => get(plot, :depth_shift, Observable(0.0f0)),
# these get filled in later by serialization, but we need them
Expand Down
2 changes: 1 addition & 1 deletion WGLMakie/src/meshes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ function create_shader(scene::Scene, plot::Makie.Mesh)
uniforms[:shading] = plot.shading

for key in (:diffuse, :specular, :shininess, :backlight)
uniforms[key] = plot[key]
uniforms[key] = lift(x-> convert_attribute(x, Key{key}()), plot[key])
end

faces = facebuffer(mesh_signal)
Expand Down
4 changes: 1 addition & 3 deletions docs/documentation/fonts.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The default theme has the following fonts set:

```julia:fonts2
using Makie
Makie.current_default_theme()[:fonts]
Makie.theme(:fonts)
```
\show{fonts2}

Expand Down Expand Up @@ -56,5 +56,3 @@ f
Currently, Makie does not have the ability to draw emoji or other color fonts.
This is due to the implementation of text drawing in GLMakie and WGLMakie, which relies on signed distance fields that can only be used to render monochrome glyphs, but not arbitrary bitmaps.
If you want to use emoji as scatter markers, consider using images (you will need to find suitable images separately, you cannot easily extract emoji from fonts with Makie).


15 changes: 3 additions & 12 deletions src/Makie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -296,20 +296,10 @@ function __init__()
# This mutates module-level state so it could mess up other libraries using
# GridLayoutBase at the same time as Makie, which is unlikely, though
GridLayoutBase.DEFAULT_COLGAP_GETTER[] = function()
ct = Makie.current_default_theme()
if haskey(ct, :colgap)
ct[:colgap][]
else
GridLayoutBase.DEFAULT_COLGAP[]
end
return convert(Float64, to_value(Makie.theme(:colgap; default=GridLayoutBase.DEFAULT_COLGAP[])))
end
GridLayoutBase.DEFAULT_ROWGAP_GETTER[] = function()
ct = Makie.current_default_theme()
if haskey(ct, :rowgap)
ct[:rowgap][]
else
GridLayoutBase.DEFAULT_ROWGAP[]
end
return convert(Float64, to_value(Makie.theme(:rowgap; default=GridLayoutBase.DEFAULT_ROWGAP[])))
end
# fonts aren't cacheable by precompilation, so we need to empty it on load!
empty!(FONT_CACHE)
Expand Down Expand Up @@ -339,4 +329,5 @@ export PointLight, EnvironmentLight, AmbientLight, SSAO

include("precompiles.jl")


end # module
5 changes: 4 additions & 1 deletion src/conversions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ convert_attribute(c, ::key"strokecolor") = to_color(c)
convert_attribute(x::Nothing, ::key"linestyle") = x

# `AbstractVector{<:AbstractFloat}` for denoting sequences of fill/nofill. e.g.
#
#
# [0.5, 0.8, 1.2] will result in 0.5 filled, 0.3 unfilled, 0.4 filled. 1.0 unit is one linewidth!
convert_attribute(A::AbstractVector, ::key"linestyle") = A

Expand Down Expand Up @@ -1285,3 +1285,6 @@ end
function convert_attribute(value::AbstractGeometry, ::key"marker", ::key"meshscatter")
return normal_mesh(value)
end

convert_attribute(value, ::key"diffuse") = Vec3f(value)
convert_attribute(value, ::key"specular") = Vec3f(value)
7 changes: 3 additions & 4 deletions src/figures.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,9 @@ to_rectsides(t::Tuple{Any, Any, Any, Any}) = GridLayoutBase.RectSides{Float32}(t
function Figure(; kwargs...)

kwargs_dict = Dict(kwargs)
padding = pop!(kwargs_dict, :figure_padding, current_default_theme()[:figure_padding])
padding = pop!(kwargs_dict, :figure_padding, theme(:figure_padding))
scene = Scene(; camera=campixel!, kwargs_dict...)
padding = padding isa Observable ? padding : Observable{Any}(padding)

padding = convert(Observable{Any}, padding)
alignmode = lift(Outside to_rectsides, padding)

layout = GridLayout(scene)
Expand Down Expand Up @@ -144,7 +143,7 @@ function resize_to_layout!(fig::Figure)
# it is assumed that all plot objects have been added at this point,
# but it's possible the limits have not been updated, yet,
# so without `update_state_before_display!` it's possible that the layout
# is optimized for the wrong ticks
# is optimized for the wrong ticks
update_state_before_display!(fig)
bbox = GridLayoutBase.tight_bbox(fig.layout)
new_size = (widths(bbox)...,)
Expand Down
12 changes: 2 additions & 10 deletions src/interfaces.jl
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
function default_theme(scene)
Attributes(
# color = theme(scene, :color),
linewidth = 1,
return Attributes(
transformation = automatic,
model = automatic,
visible = true,
transparency = false,
overdraw = false,
diffuse = Vec3f(0.4),
specular = Vec3f(0.2),
shininess = 32f0,
nan_color = RGBAf(0,0,0,0),
ssao = false,
inspectable = theme(scene, :inspectable),
inspectable = true,
depth_shift = 0f0,
space = :data
)
end



function color_and_colormap!(plot, intensity = plot[:color])
if isa(intensity[], AbstractArray{<: Number})
haskey(plot, :colormap) || error("Plot $(typeof(plot)) needs to have a colormap to allow the attribute color to be an array of numbers")
Expand Down
9 changes: 4 additions & 5 deletions src/makielayout/blocks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ macro Block(name::Symbol, body::Expr = Expr(:block))

function Makie.default_attribute_values(::Type{$(name)}, scene::Union{Scene, Nothing})
sceneattrs = scene === nothing ? Attributes() : theme(scene)
curdeftheme = Makie.current_default_theme()

curdeftheme = deepcopy(CURRENT_DEFAULT_THEME)
$(make_attr_dict_expr(attrs, :sceneattrs, :curdeftheme))
end

Expand Down Expand Up @@ -298,7 +297,7 @@ function _block(T::Type{<:Block}, fig_or_scene::Union{Figure, Scene},

# first sort out all user kwargs that correspond to block attributes
kwdict = Dict(kwargs)

if haskey(kwdict, :textsize)
throw(ArgumentError("The attribute `textsize` has been renamed to `fontsize` in Makie v0.19. Please change all occurrences of `textsize` to `fontsize` or revert back to an earlier version."))
end
Expand All @@ -317,8 +316,7 @@ function _block(T::Type{<:Block}, fig_or_scene::Union{Figure, Scene},
# and also the `Block = (...` style attributes from scene and global theme
default_attrs = default_attribute_values(T, topscene)
typekey_scene_attrs = get(theme(topscene), nameof(T), Attributes())::Attributes
typekey_attrs = get(Makie.current_default_theme(), nameof(T), Attributes())::Attributes

typekey_attrs = theme(nameof(T); default=Attributes())::Attributes
# make a final attribute dictionary using different priorities
# for the different themes
attributes = Dict{Symbol, Any}()
Expand Down Expand Up @@ -366,6 +364,7 @@ function _block(T::Type{<:Block}, fig_or_scene::Union{Figure, Scene},
# for this it seems to be necessary to zero-out a possible non-zero
# origin of the parent
lift(Makie.zero_origin, topscene.px_area),
clear=false,
camera = campixel!
)

Expand Down
12 changes: 7 additions & 5 deletions src/makielayout/blocks/axis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function update_axis_camera(camera::Camera, t, lims, xrev::Bool, yrev::Bool)
farclip = 10_000f0

# we are computing transformed camera position, so this isn't space dependent
tlims = Makie.apply_transform(t, lims)
tlims = Makie.apply_transform(t, lims)

left, bottom = minimum(tlims)
right, top = maximum(tlims)
Expand Down Expand Up @@ -676,13 +676,15 @@ function get_cycle_for_plottype(allattrs, P)::Cycle

plottheme = Makie.default_theme(nothing, P)

cdt = Makie.current_default_theme()
cycle_raw = if haskey(allattrs, :cycle)
allattrs.cycle[]
elseif haskey(cdt, psym) && haskey(cdt[psym], :cycle)
cdt[psym].cycle[]
else
haskey(plottheme, :cycle) ? plottheme.cycle[] : nothing
global_theme_cycle = theme(psym)
if !isnothing(global_theme_cycle) && haskey(global_theme_cycle, :cycle)
global_theme_cycle.cycle[]
else
haskey(plottheme, :cycle) ? plottheme.cycle[] : nothing
end
end

if isnothing(cycle_raw)
Expand Down
2 changes: 1 addition & 1 deletion src/makielayout/defaultattributes.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function inherit(scene, attr::Symbol, default_value)
if haskey(scene.theme, attr)
lift(identity, scene.theme[attr])
Observable(to_value(scene.theme[attr]))
else
inherit(scene.parent, attr, default_value)
end
Expand Down

0 comments on commit fa5e6b3

Please sign in to comment.