A paste into a layer of another texture set set the session's target
to the new effect, so a later stroke in the active set could commit to
it. The target now changes only for a paste into the active set. The
layer and effect row menus offered Paste effect only while a layer was
already selected, though a click selects the row first; they now check
the clipboard alone.
With an effect selected, Delete removed its whole layer and Ctrl+D
duplicated the layer. Both now act on the effect, like the clipboard
shortcuts; effect commands default to the selected effect.
An effect's context menu copies, cuts and pastes it, and Ctrl+C,
Ctrl+X and Ctrl+V act on a selected effect (pasting a copied one above
the selected effect, or on top of the selected content or mask).
Painted strokes come along, resampled to the target set; generators
and other one-stack effects go to their stack, and a fill reading an
anchor point needs one below its new layer. effect.copy, effect.cut
and effect.paste share the layer clipboard.
The History panel lists every undone step too (dimmed, next first) and
a click on any step goes back or forward to it, the current one
highlighted. edit.undo and edit.redo take {steps?} for the same jump.
Undoing an effect's add or duplicate took the selected effect away and
left the selection on it, so the row lost its highlight and strokes had
no target. The selection now falls back to the stack the effect was in.
After Cancel or a bake error the app re-queued the same Auto-rebake on the next frame, forever, because a set only counted as up to date after a successful bake. Session::bake_abandoned records the set being baked and the queued ones as seen; cancel_bake and the bake error paths call it. Also drops a useless into_iter() and an unreachable branch in bake.autoRebake.
Each mesh map slot of the Texture Set Settings takes an image resource:
drop one from the Assets panel on the slot, or pick it from the slot's
menu, which also clears the slot. The image is resampled to the size of
the set's other mesh maps (or its bake size), its values read as data,
a normal map in the project's normal format.
textureSet.meshMap.set {ts?, map, image} and
textureSet.meshMap.clear {ts?, map} give agents the same.
uvtiling is clamped to 0.001..=1000, the range layer.fill.projection accepts. Image files are capped by resource_cmds::MAX_BYTES instead of a second copy of the number.
The .mtlx tags colour textures with the export's colour space: srgb_texture, lin_rec709, acescg, or lin_ap0_scene for ACES2065-1 (MaterialX 1.39 has no AP0 space; the export warns). A colour map packed into one channel (L) is not converted and now says so. The $colorSpace variable's description lists every value.
Float files (EXR, HDR) hold linear values, so their colour maps are tagged lin_rec709 instead of srgb_texture. The .mtlx goes through formats::write_atomic, and a set whose name sanitises to an earlier set's file name is skipped with a warning instead of overwriting it.
Effect rows in the layer stack can be dragged within their stack (a
drop lands above the row, or below it from its lower half), and their
context menu duplicates an effect just above itself, painted pixels
included. effect.move {effect, index} and effect.duplicate {effect}
give agents the same.
Nine procedural materials for the shelf: three metals from measured
reflectance (zinc with crystalline spangles), bark with deep furrows,
fine-grained sand, mud with glossy wet patches, ice with cloudy air
pockets under transmission, and snow and bone with a little subsurface
scattering.
A neighbourhood field covers the bounding box of its tiles, and a
scattered sample spans the whole set, so on an 8K set a blur below the
levels effect evaluated everything. With such a filter below, each
sampled tile now builds its own field.
Three adjustment filters for masks and content: Histogram Scan slides a
ramp through the values (contrast narrows it to a step), Histogram Range
squeezes them towards a position, and Histogram Shift offsets them with
wrap-around. Names and parameters are translated into all nine other UI
languages.
An odd tile stride: a power of two divides the row length on
power-of-two sets and read the same few columns. A mask is planned on
its own, so a paint layer with nothing painted still shows its mask's
histogram.
The Levels effect's properties now show a histogram of its input, the
mask below it or (on layer content) a channel picked above it, with the
input range marked. effect.histogram {effect, channel?, bins?} gives
agents the same counts. Large sets are sampled (at most 256 tiles), so
the cost stays flat up to 8K.
UV island fill grew the island through shared vertex indices. Imported
meshes often split vertices along hard edges, or give every face its
own, while the UVs run on; the fill then stopped at single polygons.
Triangles that share an edge in UV space now form the island.
Fixes#51.
Carbon Fiber, Fabric Cotton, Denim and Velvet were all the same plain
weave in different colours. A new Twill weave pattern (2/2: diagonal
ribs, the weft darker than the warp) now gives Denim its diagonal and
Carbon Fiber its light and dark tows under a clear coat; Velvet is a
soft pile with no weave under its sheen; Fabric Cotton keeps the plain
weave. Twill weave is also a fill pattern, translated into all nine
other UI languages.
Fixes#97.
An eye menu above the list shows, hides or inverts every texture set;
the focus button shows only the active one, and shows them all again
when pressed a second time. textureSet.visibility {mode} does the same
for agents.
Fixes#72.
Alt+click on a channel of a fill's or the brush's Material section turns
that channel on and every other one off (one undo step for a fill).
tool.material and layer.fill.set take solo: true for the same.
Fixes#74.