Commit Graph
26 Commits
Author SHA1 Message Date
BFlat b08e9df95c Merge pull request #6478 from dotCooCoo/fix/3d-member-opacity-masks
3D: an opacity mask on a group member masks its solids
2026-11-11 07:44:06 +07:00
dotCooCoo 24155e1f75 3D: an opacity mask on a group member masks its solids
A 3D effect on a group built its solids from the members' paths and
paint and left out each member's opacity mask, and the mask of a group
inside the 3D group. Clipping groups, blends and symbol instances
resolved for the effect lost their masks the same way.

A member, or a group inside the 3D group, with an opacity mask now
gets a scope like one with its own opacity or blending mode, and the
mask goes on the group that holds that member's surfaces. Revolve
applies it with the member's opacity and blending mode; Extrude &
Bevel, Extrude & Bevel (Classic), Inflate and Rotate draw each solid
on its own when a mask is present and put the masked members' solids
in a group with the mask. A resolved clipping group, blend or symbol
instance keeps its mask. A disabled mask is ignored.
2026-11-10 14:30:10 -08:00
dotCooCoo 7dfe2d9d2a 3D: a symbol's 9-slice guides and overrides count before its art is placed
The check that refuses a symbol instance before its art is placed
counted only the symbol's own objects. Placing art through 9-slice
guides can make up to 28 objects of each one, and an instance's
dynamic-symbol overrides can turn a path that would be cut at the
guides into clip groups in every cell it reaches. Such an instance
passed the check, and its art was placed in full before the work
limit refused it.

The check now counts the symbol's own objects first, then the most
objects placing makes (NineSliceMap::most_placed) of the art with the
instance's overrides applied, and refuses the instance with the same
message before anything is placed.
2026-11-10 14:24:33 -08:00
BFlat 349385fd56 Merge pull request #6418 from dotCooCoo/fix/3d-more-object-kinds
3D: effects build from clipping groups, blends and symbol instances
2026-11-11 05:13:37 +07:00
dotCooCoo 9fced9388e 3D: a symbol holding too many objects is refused before its art is placed
A 3D effect on a symbol instance placed a copy of the symbol's whole art
before counting it against the effect's work limit, so a symbol far past
the limit was copied in full on every check and redraw before it was
refused. The symbol's objects are now counted first, and a symbol that
would pass the limit is refused with the same message without being
placed.
2026-11-10 13:18:08 -08:00
dotCooCoo 6e3f04032d 3D: the group refusal lists groups and clipping groups among what it builds from
The message for a group member that can't become a solid now names groups
and clipping groups too. docs/three-d.md states that an image left out of a
clipping group also needs no visible fills or strokes of its own.
2026-11-10 11:48:39 -08:00
dotCooCoo d7845e7068 3D: Rotate keeps each clipped fill in its place among the strokes
Inside a clipping group, the fills of a shape were cut into one piece in
the top fill's place. Rotate turns every fill, so with a fill, a stroke
and a fill, the lower fill was drawn above the stroke. With Rotate, each
fill now becomes its own piece in its own place. Extrude & Bevel, Inflate
and Revolve build from the top fill and keep one piece there, also when
an object changes from Rotate to another 3D type.
2026-11-10 11:16:25 -08:00
dotCooCoo a900653c9c 3D: Inflate limits the work of filling its grid
Inflate's grid clipped every ring of the outline in each cell the
outline crosses and tested every edge for each cell's center, so its
work grew with the outline's points times the cells: a comb of 4,000
teeth (16,002 points) took 1.1 to 1.3 s and one of 16,000 teeth 8.8 to
9.1 s. Inflate now counts that work (the edge index's entries, the edges
its queries look at and the ring points its cells clip) and refuses the
shape with "The 3D surface is too complex; simplify the shape" once it
passes 268,435,456, VectorCraft's own value (about 0.65 s). The index
takes at most 16,777,216 entries (64 MiB). Each row's inside test reads
the sorted crossings of its line, and a cell clips only the rings whose
bounds meet it, so a 65,536-point circle inflates in 0.66 s instead of
1.0 to 1.2 s.

The effects test of a stroke past the limits uses 40,000 corners, so its
outline passes the 65,536 points a solid takes.

Docs: docs/three-d.md, docs/mcp.md.
2026-11-10 10:43:24 -08:00
dotCooCoo 711b776fae 3D: deep clipping paths and deep groups in resolved art are refused
A clipping path nested past the depth limit, and a group at the limit
that holds further groups, are refused before they are walked, instead
of being followed to any depth. The clipping path's check follows the
members its outline is built from: the first member of a nested
clipping group and the shown members of other groups. The group check
skips hidden members and treats a compound path as one shape, as the
solid builder does.
2026-11-10 00:59:41 -08:00
dotCooCoo d3055e264e 3D: an image a clipping group hides wholly does not refuse its 3D effect
An image in a clipping group whose bounds lie wholly outside the clipping
path's bounds draws nothing, so a 3D effect leaves it out instead of
refusing it. An image with effects, fills or strokes of its own, or one in
a group with effects inside the clipping group, is still refused, since
those can draw it inside the clip.
2026-11-10 00:44:03 -08:00
dotCooCoo cca1977a64 3D: clipped groups keep their members' transparency and count their pieces
- When a group's geometry effects reshape its members inside a clipping
  group, each member's piece goes back into groups with the opacity and
  blending mode of the groups it was in.
- A clipped shape's pieces (its fills and each stroke) are counted against
  the 4,096-object and work limits before they are cut.
2026-11-10 00:36:07 -08:00
dotCooCoo bad4b986f5 3D: resolving art for a 3D effect has a work limit and keeps geometry effects
- Resolving the symbol instances, blends and clipping groups a 3D effect
  builds from counts every object it visits or makes and stops past
  262,144 with an error. Nested symbol instances that end in hidden art
  are refused instead of being expanded at every level. Each object is
  visited once; a group is no longer walked again for each level above it.
- A symbol instance, blend or clipping group inside a 3D group keeps its
  appearance, so its geometry effects reshape the art it shows. A nested
  group's geometry effects now reshape its members inside a 3D group too,
  and inside a clipping group they apply before the clip cuts the art.
- Hidden members and guides of a group inside a clipping group build no
  solid.
- Tests cover an empty clipping group, a blend set to no steps, an
  instance of an empty symbol, a symbol holding a clipping group, the
  paint-copy budget across resolved art, and art past the limits drawing
  as it does without the effect.
2026-11-10 00:29:58 -08:00
dotCooCoo f0dad6010f 3D: effects build from clipping groups, blends and symbol instances
Extrude & Bevel, Extrude & Bevel (Classic), Inflate, Rotate and Revolve
now apply to a clipping group (or a layer with a clipping mask), a blend
or a symbol instance, alone or inside a group or layer. The solid is
built from the art the object shows: the art inside the clipping path
(fills cut to the clip, strokes as their outlines cut to the clip), the
blend's keys and steps, and the symbol's art where the instance places
it. Validation, the canvas, bounds, Expand Appearance, Rasterize and
assets.add3D read the same art from the document.

An image is refused, alone or in a group, with a message to trace it
first with Object > Image Trace > Make. A missing symbol, a symbol that
holds an instance of itself, art nested more than 64 levels deep and
more than 4,096 objects are refused. The refusal messages change, and
their rows change in every catalog.

Docs: docs/three-d.md, docs/revolve.md, docs/mcp.md,
docs/target-app-parity.md.
2026-11-09 23:22:20 -08:00
dotCooCoo 2e81086c38 Revolve: a nested group's opacity applies once to its members together
The opacity of a group inside a revolved group was multiplied into each member's surface, so where members overlap they drew darker than the group does without the effect. A member or group with opacity below 100% or a blending mode other than Normal now holds its members' surfaces in one group with that opacity and mode.
2026-11-09 18:30:41 -08:00
dotCooCoo d8d73495bb Revolve: a group member's blending mode applies to its surface
A member of a group with Revolve drew its surface in Normal mode whatever its own blending mode or that of a group it is in. Each mode now applies once, to the member's surface or to the surfaces of the group that has it, nested as the groups are. Expand Appearance keeps every face of a blended member.
2026-11-09 18:05:17 -08:00
dotCooCoo bd5ea2a1bf Merge main into feat/plugin-effect-paint 2026-11-08 17:59:33 -08:00
dotCooCoo a7fc513a0c Merge main into feat/3d-classic-extrude-bevel 2026-11-08 15:34:06 -08:00
dotCooCoo 11703bd350 Merge main into feat/plugin-effect-paint 2026-11-08 12:56:42 -08:00
dotCooCoo b9d999fe26 Asset Export: the 3D mesh triangle limit bounds memory across objects
The 2,000,000-triangle limit on a 3D object's meshes is now checked as
each mesh is built, so an object past it is refused before the rest of
its meshes are built:

- Revolve counts each fill's and stroke's mesh as it builds it, instead
  of building every one first.
- Inflate still solves every shape's membrane at once (the eye depends
  on the highest puff), but builds each solid only when its mesh is
  reached (inflate_meshes), so a refused object leaves the later
  solids unbuilt.
- All the objects of one 3D asset share one budget
  (three_d_meshes_of), so assets.export3D refuses an asset whose
  objects pass the limit together.
2026-11-09 03:08:23 +07:00
dotCooCoo 64817c2e8c Merge main into feat/plugin-effect-paint 2026-11-08 10:46:47 -08:00
dotCooCoo b568977af4 Asset Export: 3D objects export as USDA, USDZ, glTF or OBJ meshes
Squashed from #6168 onto main.
2026-11-09 00:29:05 +07:00
dotCooCoo f384d27bee 3D (Classic): the solids test checks the classic faces' hue
every_solid_draws_shaded_faces_and_leaves_the_source_editable no longer
skips the color check for Extrude & Bevel (Classic). Its faces must be
the fill's red or the stroke's black, shaded, or lightened toward white
by the Plastic highlight, which keeps r - g to r - b at 6 to 7.
2026-11-08 06:35:38 -08:00
dotCooCoo d8afed1562 Plug-ins: painted pieces keep their swatches in Pathfinder and baked art
Pathfinder effects, compound shapes, Expand Appearance and pattern
expansion now pass the document to the effects they evaluate, so a
painted piece that names a swatch or pattern takes part as drawn instead
of being refused. A path with a painted effect takes part in Pathfinder
and compound shapes as its pieces, each with its own paint, inside the
path's opacity and blend mode.

The renderer's kept effect art and live evaluations now count the
document's swatch and pattern names for objects with a plug-in effect,
so deleting or restoring a swatch a piece names redraws the object.
2026-11-08 05:52:39 -08:00
dotCooCoo 5a4c3e12a5 3D (Classic): Extrude & Bevel (Classic) extrudes art with Wireframe, No Shading, Diffuse and Plastic surfaces
Effect > 3D and Materials > 3D (Classic) > Extrude & Bevel (Classic)... applies
`threeD.classicExtrude`, a live effect built on the Extrude & Bevel solid. It
takes Extrude Depth, Cap, a bevel with Height and Bevel Extent In or Out, the
Position presets, rotation and Perspective, and draws the faces with the
Wireframe, No Shading, Diffuse or Plastic surface: one to ten lights, Ambient
Light, Highlight Intensity and Size, Blend Steps, a Black, Custom or no Shading
Color, and Draw Hidden Faces. Invalid parameters are refused with an error.
2026-11-07 15:02:39 -08:00
Don Omondi 3f7f743ddb 3D effects: Extrude & Bevel, Inflate and Rotate apply to groups
A 3D effect on a group or layer builds a solid from every path,
compound path and type in it, all turned about one shared axis, as the
public docs describe for groups. Fixes #4506.
2026-11-07 00:17:14 +07:00
aiongg 0d282bad01 refactor(effects): move solids.rs tests to solids/tests.rs 2026-10-26 18:33:15 +00:00