Open the Edit Block Definition dialog when BEDIT is invoked without an active selection, listing candidate block definitions alphabetically while filtering layout records, anonymous blocks, and external references. Allow typing a new valid block name to start an empty block editor session that only commits to the drawing block table upon explicit save.
The end angle subtracted a whole octant less the end offset, so the arc
in the ISOCP 9 stopped about 45 degrees short and the glyph shrank to
0.68 of the cap height; clockwise arcs and n = 0 (a full circle) drew
nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A save records the entered model viewport (or the sheet) as the layout's
last active viewport, and opening the layout enters it again with its
UCS. Picks up the codec fix that kept a last-active link from being read
as the sheet viewport (codec d57097c, kernel b40fa59, graph 2360341).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every weight under 0.26 mm was clamped to the screen's 1 px floor before
the PDF and SVG exporters saw it, so 0.00, 0.09, 0.13 and 0.25 mm all
plotted alike. The floor now applies on the GPU only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ISOCPEUR, ISOCTEUR and the other aliased names are real fonts; with one
installed, its face draws the text instead of the stroke substitute,
which has no Cyrillic.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In the Block Editor, BVSTATE makes a new visibility state, makes one
current, renames or deletes one; BVHIDE and BVSHOW hide or show the
picked objects in the current state (BVSHOW shows every object of the
block while they are picked). The first use makes the block dynamic.
The states are stored as the format keeps them: a
BLOCKVISIBILITYPARAMETER in the block's ACAD_ENHANCEDBLOCK evaluation
graph with its visibility grip and the grip's two location expressions,
the round-trip purge preventer, AcDbDynamicBlockTrueName /
AcDbDynamicBlockGUID / AcDbBlockRepETag on the definition and element
tags on each of its objects. The definition shows its first state; a
reference given another state gets its own evaluated *U copy, tagged
AcDbBlockRepBTag and linked back through AcDbBlockRepresentation /
AcDbRepData, so it shows that state and the other references do not
change. Saving the block drops erased objects from the states.
Checked: a block authored this way reads back with its states and
reference link from DWG and DXF, and the ODA converter accepts the DWG.
Closes#1566
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
add_layout took the sheet viewport out, so the first viewport added to
the layout afterwards (by automation, or a plugin) was read as the sheet
and the scale pill and paper camera followed it. The sheet now stays and
is fitted to the page when the layout first opens; a layout saved before
that is still written without viewports.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening a layout whose page setup was never filled in took every viewport
out of it, including viewports onto the model a file carries (plenty of
DXF writers leave the paper fields empty). With only the sheet taken out
instead, the next viewport would have been read as the sheet. The sheet
is now fitted to the new page and every other viewport stays.
A layout saved as never opened keeps its state when it already holds a
viewport onto the model (one added by automation), and only its sheet is
taken out otherwise.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The brightness/contrast cache keyed entries by the source buffer's
address without holding it, so a reloaded image whose new buffer landed
at the freed address could be shown with the old file's pixels. Each
entry now holds its source. The new functions had also been inserted
between resolve_image's doc comment and the function, merging that text
into the lookup table's documentation; it is back where it belongs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The web build has no font folder, so a text style whose TrueType file is
not a bundled Noto subset falls back to it. font_register takes the file
from the host page:
{"op":"font_register","file_name":"Brand-Regular.ttf","data_base64":"…"}
The faces join the font database, file_name resolves to the family of
the first face (case-insensitive, without directory, like installed
fonts), and open drawings lay their text out again (fallback glyph
cache cleared, text geometry invalidated per tab). The reply names the
family and the number of faces. Bytes without a face fail with
font_invalid. SysFonts::by_file becomes updatable for this.
Proposed in #1771.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A copied entity used to keep its source's extension-dictionary
handle, so the copy and source shared one tree and edits crossed
between them. In-drawing copy now clones the whole tree onto fresh
handles: dictionary entries, owners, reactors, nested xdictionary
links, and XRecord handle references that land inside the tree are
remapped; references leaving it stay pointed at the originals. A
dangling or missing root leaves the copy without an extension
dictionary rather than sharing. Annotative context trees and the
paste/export clone path are unchanged. Undo stays on the full
snapshot path when a tree is cloned.
Ctrl+click on a polyline selects the segment under the cursor (again to
drop it); several segments can be picked. Only the picked segments are
highlighted, and MOVE, ROTATE, SCALE and MIRROR then change just their
vertices, so the neighbouring segments stretch to follow. Any other
selected objects are transformed whole as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SECTIONCULL keeps only what the selected section object (or the live
section of the space) shows: solids, surfaces and closed meshes are cut
to it with the same planes the live section uses, open meshes are
clipped face by face, and every other object wholly outside it is
erased. Objects across the boundary that cannot be cut stay whole. One
undo step.
The section's bounding planes are gathered once (section_planes) and
shared by the live section and the cull.
Refs #1407
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
COMPARE picks a drawing (or takes its path) and matches its objects with
this drawing's by what they draw: type, layer and tessellated geometry,
so an unchanged copy matches whatever its handle. Objects only here are
outlined in green, objects only in the other drawing in red, over the
current drawing, and Next / Previous zoom from one difference to the
next with a count in the prompt. A moved or edited object shows as one
of each. eXit (or Esc) clears the overlay.
Refs #970
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With the new Associative option on (the default), ARRAYRECT and
ARRAYPOLAR build the array the way the drawing format stores one: the
selected objects move into an anonymous source block, an anonymous
array block holds one ByBlock reference to it per item, an INSERT of
the array block takes their place, and an AcDbAssocAction with an
AcDbAssocArrayActionBody, its three dependencies, the BaseNormal /
Origin / basePoint parameters and the value parameters tie them
together in the model-space network. The array is then edited from
Properties like an array read from a file.
The option flips with AS and is remembered for the session; on a
rotated working plane the commands keep making plain copies. Saving
drops the action of an array whose reference was erased or exploded.
Checked: created arrays reopen as associative with their parameters
and items, and the ODA converter reads the saved DWG without errors.
Refs #1109
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An associative array is an AcDbAssocAction with an
AcDbAssocArrayActionBody, dependencies on the array INSERT, the block
holding the item references and the block holding the source objects,
and value parameters (Items, ItemSpacing, Rows, …). Selecting the array
INSERT now shows its counts and spacings in Properties; changing one
places the items again and rewrites the item references, the body's
item records and the parameter values together, in one undo step, so
the drawing stays associative when saved.
Rectangular arrays follow their RowProfile axis, AxesAngle and base
normal; polar arrays turn about the centre recovered from their first
item, Radius and StartAngle. Both match the stored items of the
associative arrays in the sample drawings (122 of 123 rectangular, all
polar items of the polar samples). Path arrays are shown read-only.
Refs #1109
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A section volume now shows grips on its top and bottom faces, so its
height is pushed and pulled in place like its sides, not only through
the Properties palette. Live sectioning also cuts MESH, polygon mesh and
polyface mesh objects that close a volume, drawing each as the capped
solid it bounds in every visual style.
Refs #1407
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MOVE, ROTATE, SCALE and MIRROR updated a MESH, polygon mesh or polyface
mesh but rebuilt the display only for solids, regions, bodies and
surfaces, so a transformed mesh kept being drawn where it was. Meshes
now go through the same display refresh.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In model space MVSETUP draws the sheet border at the drawing scale
(scale factor, paper width and height) and zooms to it, or switches to
a layout. On a layout it creates viewports in a bounding area (a single
one, a 2x2 engineering set of top/front/right/isometric views, or an
array with spacing), deletes picked objects, and scales picked
viewports to a paper/model unit ratio.
A viewport's fit to the model now measures the model along the
viewport's own view direction, so side and isometric views frame it
too.
Refs #1501
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every further reference to an already expanded block (a translated copy
of the same definition, at the top level or nested) was materialised as
a full copy of every wire, although the GPU already draws those copies
from one shared source with a per-copy offset. Such a copy is now a
single stub wire holding the shared prototype and its offset (stubs nest
inside prototypes, so nested repeats collapse too).
- The block renderer expands stubs into instance references while it
groups by source, so drawing is unchanged.
- Interaction queries expand only the stubs near the query, so snapping,
picking, window and crossing selection see each copy's geometry.
- Plot, boundary detection, viewport projection and entity_wires() get
fully expanded wires; count and reference-edit recolouring expand the
set while they are active.
- OCS_NO_BLOCK_STUBS turns it off.
A drawing with 480 references to a block of 100 nested 50-line blocks
(2.4M lines) now opens with 11k wires instead of 2.4M: peak memory
5.4 GB -> 0.37 GB, wire assembly 2.4 s -> 36 ms, interaction index
3.7 s -> 23 ms. The viewport, a plotted PDF, snaps and selections are
identical with and without stubs, and on five real drawings the view
renders the same.
Refs #1698, #1542
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Delegate INSERT and MINSERT explosion to the document-aware codec implementation, removing duplicate attribute and base-point handling. Update workspace, kernel and graph pins together and cover rotated arrays with a nonzero base.
Introduce would_create_cycle in block_service to prevent recursive block definitions with case-insensitive matching across block records. Enforce cycle refusal at INSERT commit in BEDIT and during block redefinition (redefine_block_raw) with a shared error message. Ensure render-time recursion truncates safely with a one-time session warning on cyclic documents.
Enforce constant attribute flag in ATTEDIT dialog by presenting constant attributes as disabled and ignoring modifications. When exploding an insert, restore block-definition attribute definitions as transformed ATTDEF entities while dropping instance attribute values.
The resident tessellation memo held its own copy of every entity's wires
next to the assembled resident set. Runs now stay only in the set: a memo
entry whose wires the set holds just marks them valid (InSet) and reads
them back through a weak link with the set's layout ranges, so the set
remains uniquely owned for in-place patches. A resident build moves new
tessellations straight into the set (Pending until it is bound); hidden
entities copy their run out before the patch blanks it, and an abandoned
patch hands its half-taken set back for the full build that follows.
Builds whose runs are recoloured afterwards (reference edit, count) keep
owned copies as before.
On a drawing with 2.4M nested block lines: wire assembly 3.7s -> 2.3s,
memory after it 4.6 GB -> 3.8 GB.
Refs #1542, #1698
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In a tilted 3D view a grip followed the cursor onto the screen plane
through the orbit target, so a circle or arc jumped to another radius and
a polyline vertex left its plane. A model-space grip now moves in the UCS
XY plane at its own elevation (the screen plane only when seen edge-on).
A solid stays drawn while its grip moves, and its own edges were still
snap candidates: a cone's base radius landed on its own side. The edited
entities are left out of the grip's snap set.
Fixes#1033
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A layout opens for the first time when its page setup was never
initialized (no paper size, no media name) or it was created in this
session; its page setup is initialized then, and with
LAYOUTCREATEVIEWPORT it gets its first viewport. A layout never opened
is saved with an uninitialized page setup and no viewports, so it gets
its viewport when the file is opened again, here or in the reference.
- Select Viewport for view: a viewport is selected when the pick box
(PICKBOX pixels at the sheet's zoom) touches its frame; a pick well
inside or outside selects nothing and the prompt repeats.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A layout opened for the first time - one whose sheet viewport had to be
made, or one created in this session - gets a viewport centred on the
printable area, 0.8 of its width and height, zoomed to the model's
extents, while LAYOUTCREATEVIEWPORT is on. The profile variable takes
ON/OFF or 1/0 and is kept with the settings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new drawing is metric with metre insertion units, but its annotation
multiplier stayed at Scene::new()'s unitless 1 while opened files and
CANNOSCALE convert paper millimetres into drawing units (0.001 at 1:1).
Annotative text and dimensions were drawn 1000x too large until the
first scale change, then shrank to their real size and looked gone,
also after switching back to 1:1.
One helper now derives the multiplier from the header; new drawings,
file open and every INSUNITS change (UNITS, the units popup, DWGUNITS,
SETVAR) go through it.
Fixes#1674
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hatches are drawn before the wires and write depth, so a transparent
hatch above lines in draw order still hid them through the depth test.
Transparent hatches now go to their own renderer drawn after the wires:
the lines behind show through the blend and the lines in front still
win the depth test.
Fixes#1720
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The background image texture is not an sRGB view: the image is drawn with
its own colours, as the solid and gradient colours are.
- An entered paper-space viewport shows its named visual style (Realistic,
...) in the render-mode picker, and a mode picked there is recorded as the
viewport's visual style.
- The view_background automation action takes offset=x,y and scale=x,y.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
add_entity_clone reset handle, owner and mode but kept the source extension dictionary handle, so a copy claimed a dictionary its document does not own. The clone now gets no extension dictionary, like baked and transformed-block children. Failing-first test included.