=== Yee3DPrint - 3D Print Calculator ===
Tags: 3d printing, woocommerce, stl, configurator, checkout
Contributors: addonsorg
Requires at least: 6.5
Tested up to: 7.1
Requires PHP: 7.4
Requires Plugins: woocommerce
Stable tag: 1.3.14
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Private 3D model uploads, five independent option catalogs, instant configuration prices and WooCommerce checkout.

== Description ==

Insert the Yee3DPrint block in the WordPress editor or place [yeekit_3d] on a page. Both render the same PHP configurator on the storefront. The Yee3DPrint → Settings tabs separate print options, model preview, uploads, cloud PrusaSlicer analysis, and checkout. Model preview settings control scene colors, top and bottom light positions, ground, grid, fog, XYZ axes, build volume box, automatic rotation, camera fit on resize or scale changes, optional auto scaling, shadows, and visibility of File units, Scale controls and Model Stats. The Disable display setting hides a catalog and excludes it from required selections and pricing. Customers upload a model, inspect it in 3D and choose print options. Checkout mode adds the priced model to WooCommerce and opens checkout; Cart and checkout mode shows separate Add to cart and Checkout buttons. Add to cart keeps the customer on the configurator with a View cart link, while Checkout opens payment directly. Estimate-and-request mode shows an estimated subtotal and collects contact details without creating a cart item. Request-price mode collects contact details without displaying or requiring a configured price. The configurator is independent of WooCommerce products and variations.

Cloud PrusaSlicer analysis is an optional publisher-hosted SaaS feature. The shop enables it and may enter a purchase code under Settings → Cloud PrusaSlicer analysis. The plugin creates a private token automatically and registers the shop with the publisher service, which verifies the shop's public HTTPS WordPress endpoint. The plugin checks purchase codes with add-ons.org before saving; the SaaS server checks them again before granting licensed quota. Without a code, each registered site has 50 successful test analyses total. Any active, unexpired purchase code grants 5,000 successful analyses per UTC month, shared across sites using that code. The SaaS server enforces the quota; when it is exhausted, the shop must contact add-ons.org. The plugin defaults to the publisher's HTTPS analysis domain. Existing publisher-provisioned tokens continue to work. Token rotation and paid plans beyond 5,000 calls are not implemented yet.

The Main color setting under Yee3DPrint → Settings → Print options sets the accent color for both step layouts, including buttons, selected controls and progress indicators.

When a selected service has a blank or unusable price, a Material costs zero, or the whole configuration totals zero, the configurator replaces cart and checkout actions with a price-request form. Explicitly configured zero-price Printers, Coatings, Post-processings and Infills are free options and do not block checkout when the configuration has a positive total. Print Quality is a specification, not a separately priced service. The server verifies the selection and saves a quote when pricing is incomplete. Existing cart items are removed if their current catalog prices change to require a quote.

Yee3DPrint → Settings appears first in the plugin's submenu. Catalog examples are optional: activation creates no Materials, Printers, Coatings, Post-processings or Infills. The Sample data tab reports catalog counts and creates or removes 3D-printing and CNC-cutting examples independently. Sample 3D materials start at 1 currency unit per cm³; sample CNC materials start at 1 currency unit per cm of cutting path. Sample machines and print options include example prices; 3D materials include density, and the CNC machine includes engraving and speed settings. Running Create again fills marked older zero-price samples while preserving nonzero prices entered by the shop. Removal moves only marked sample options to Trash; catalog options created by the shop are kept. The Print options tab has 3D-printing and CNC-cutting views; the CNC view omits Coatings display and Infills display because those controls apply only to 3D printing.

The Request price settings tab remains available for every checkout behavior because an unpriced service can switch any calculated checkout to a price request. Opening it after selecting a new request mode saves that mode first. The tab controls whether Full name, Company, Phone and Notes are required, optional or hidden on the request form. Customer email always remains required. The shop can enable an email notification, set its recipient and customize its subject with a {quote_id} placeholder. The notification contains the request details and a protected admin link to the saved quote; it does not attach or expose the model file. If sending fails, the quote remains saved and its detail page shows the notification failure.

The read-only Yee3DPrint → Settings → Pricing guide tab explains zero prices, each catalog option's pricing rule, per-gram materials, setup fees, quantity, and checkout behavior with an example.

Show demo is enabled by default. It displays an Explore the Demo card above the File units and Scale controls; the card hides when a model loads and returns when the model is removed. The bundled 10 mm cube always loads with mm file units, yielding 1 cm³ at 100% scale; it is only sent to the shop if the customer submits its configuration. Materials and Coatings use the color palette display by default. These settings remain editable under Print options.

Yee3DPrint → Quotes and Orders lists uploaded models, including those awaiting checkout. Its submenu counter and list labels show which quotes and orders have not been viewed; opening a record's details marks it viewed. Open a model to see its saved statistics and print options, customer name and email, and a link to its WooCommerce order when checkout is complete.

**DEMO** : [https://demo.add-ons.org/3d-print/3d-printing-service/](https://demo.add-ons.org/3d-print/3d-printing-service/)

The Yee3DPrint admin menu contains five separate post types:
* Materials: configurable base-price basis, up to 20 editable extra-price rows, preview color, and optional layer-height override.
* Printers: price per piece, one setup fee per uploaded model, build volume, editable Print Quality choices with layer heights, compatible materials.
* Coatings: optional single selection, price per piece, compatible materials.
* Post-processings: optional multiple selections with checkboxes, or a single selection with radio/dropdown; price per piece, compatible materials.
* Infills: percentage, price per piece, compatible materials.

Use the post title for the option name. A Material's Enabled setting controls whether it appears in the configurator, regardless of its editor status; trashed and auto-draft materials remain excluded. The other four catalogs still require published entries. A zero-priced Material requires a price request; an explicitly zero-priced non-material option is free, while a blank non-material price requires a request. Options with unsupported model-based pricing remain selectable for a price request. No material restriction means all materials. The server checks the selected IDs, enabled state, prices where needed, and material compatibility before accepting a model. The Print configuration panel stays visible but its controls are locked until a valid model is loaded. Removing the model clears the selections and locks them again.

The configurator unlocks each required step in sequence. Settings → Print options → First print option chooses Materials first or Printers first. Once the first option is chosen, the second list shows only compatible entries. Compatibility uses both the Material's allowed Printers and the Printer's allowed Materials; an empty restriction list permits all. Changing an earlier choice clears incompatible later choices.

Edit each Printer's Print Quality choices under Build Volume & Specs using the Add quality and Remove buttons. Existing printers start with Standard and High Quality choices based on their default layer height. With only one available Printer, the frontend selects it automatically and hides the Printer control. With one Quality choice for that Printer, the frontend also hides Print Quality and applies that choice automatically; with multiple Quality choices, customers choose Quality without seeing a redundant Printer selector. The effective layer height is saved with the quote.

Pricing: sum of selected option prices multiplied by quantity, plus material and printer setup fees once per uploaded model. Material base prices and repeater extras can use server-calculated geometry (solid volume, bounding volume/XY, surface area, removed volume), actual or volumetric weight, and cloud-analyzed support volume or print time. Supported ASCII DXF drawings require a Laser Cutting material and machine. Customers choose Cut, Engrave or Ignore for each DXF layer. Cut length is measured on the server and can use a Material price per centimeter; Engrave length uses the machine's engraving price per centimeter. A blank engraving rate prevents automatic checkout for drawings with engraved layers. For DXF, fixed and cutting-path Material rules apply; 3D-only rules such as gram and volume are skipped. Set a cutting-path rule if you want a nonzero DXF Material charge. The +% extra applies to the Material subtotal. Price entries follow the WooCommerce currency and tax-entry setting. WooCommerce calculates tax, coupons and payments. The frontend subtotal is an estimate; the server recalculates prices when the model is submitted and again when WooCommerce calculates the cart. Changing a catalog price before checkout can therefore change an open cart total. Setup is a separate taxable fee and is not multiplied by quantity.

A hidden internal simple product transports each model into the WooCommerce cart. It stays out of the shop catalog, storefront search and core product sitemap, and its direct product URL returns 404. Each upload is a separate cart line with its own private file, settings and price snapshot. The product cannot be purchased directly without a validated upload. Configure shipping/tax behavior through WooCommerce; the model's physical shipping weight is not inferred. Payment uses installed WooCommerce payment methods. Classic checkout, Cart/Checkout Blocks and HPOS use native WooCommerce APIs. Deactivation drafts the internal service product; a later configured upload restores it.

Preview formats:
* STL: ASCII and binary geometry.
* OBJ: geometry only, no external MTL or textures.
* 3MF: core meshes, components, build transforms and units. Preview uses the selected material color. Advanced extensions, textures, slicer settings and external component references are not supported.
* STEP/STP: bundled OpenCascade WebAssembly conversion, normalized to millimeters.

Under Yee3DPrint → Settings → Uploads and limits, choose which formats customers may upload. STL, OBJ, 3MF, STEP, STP and DXF are enabled by default; DWG is off by default. STP uses the STEP importer. Supported ASCII DXF drawings up to 5 MB show a 2D preview and a separate laser-cutting configurator. The optional sample data includes an editable Default Laser Cutter plus Plywood 3 mm and Acrylic 3 mm materials priced at 1 currency unit per cm of cutting path. The sample machine's engraving rate is 0 and can be changed. Print Quality, Coatings and Infill are excluded from DXF orders. The original drawing and chosen layer operations are verified again on the server when submitted. This reader supports LINE, CIRCLE, ARC, ELLIPSE, straight LWPOLYLINE and SPLINE entities. Drawings with unsupported entities, including inserted blocks and bulged polylines, can still use the manual quote form. DWG remains manual quote only. The frontend format label and file picker follow the setting, and the server checks the same list when accepting uploads. Disabling a format does not delete existing private models.

View rotation is not a production orientation setting. Original model bytes are preserved; the file's unit at upload and the scale are saved separately. After upload, the mm/cm/in control converts the displayed X/Y/Z sizes without changing physical dimensions, volume, price or scale. The selected unit before upload sets the source unit for STL, OBJ and DXF files; the bundled demo cube uses mm. Editing any X/Y/Z size updates the uniform scale and the other two sizes. Model Stats show bounding dimensions and volume, triangle count, surface area, and solid-mesh volume when the preview mesh is closed and manifold (up to 150,000 triangles per mesh for the topology check). Without a slicer, model weight is a solid-volume estimate when the selected Material has density configured. When cloud PrusaSlicer analysis is enabled and the publisher endpoint is configured, the browser sends a temporary millimeter STL to the shop site, which forwards it to the publisher service. It then shows sliced material usage, support volume, print time, and a filament-weight estimate when density is configured. The publisher service receives model geometry and bounded printer settings; its retention and privacy terms must be supplied before launch. This is an FDM estimate based on the selected Material, Printer, and Infill settings. Build-volume warnings use browser estimates, not a server-certified manufacturability check. There is no automatic mesh repair or printer control.

At configuration submission, available Model Stats are saved with the private quote and copied to the WooCommerce order line item. The admin pages read that saved snapshot without reopening or analyzing the 3D file. Unavailable estimates remain blank; older orders show only fields that were previously stored.

Privacy: originals are stored in a private database table, never public Media Library URLs. Shop managers and authenticated order owners can download them. Guests can purchase but do not receive a publicly accessible file link. When cloud analysis is enabled, temporary model geometry and bounded print settings are sent to the publisher service. A purchase code entered in Settings is stored in WordPress options, checked with add-ons.org, and sent privately to the publisher analysis service; the latter stores only its hash and a monthly usage count. When disabled, the model is not sent to that service. All viewer assets are bundled locally. WooCommerce collects customer billing/shipping information at checkout; the plugin associates the resulting order with its models. A salted IP hash is retained briefly for upload throttling. WordPress privacy export/erase covers model metadata; order-linked records require shop review before erasure.

Files expire after the configured retention period (default 90 days), except files associated with active orders. WordPress cron must run for cleanup. Uninstall preserves data unless YEEKIT_DELETE_DATA is explicitly set to true. That option deletes plugin catalog entries, model records, files, settings and the internal service product. WooCommerce orders are never deleted by uninstall.

== Installation ==

1. Activate WooCommerce and Yee3DPrint for WooCommerce.
2. Activation does not create catalog options. Open Yee3DPrint → Settings → Sample data to create editable examples, or add your own options from the catalog menus. Settings shows a notice when the catalog is empty.
3. Sample options are marked so the Sample data tab can move them to Trash without removing your own catalog entries. Review sample prices and printer specifications before taking paid orders.
4. Insert the Yee3DPrint block in a page, or add [yeekit_3d].
5. Configure WooCommerce payment methods, shipping and taxes. Test a model with a test-mode gateway before accepting real payments.

PHP ZipArchive is required for 3MF. The browser needs WebGL and WebAssembly. Cloud analysis requires the publisher to configure an HTTPS SaaS endpoint; the customer PHP server does not need PrusaSlicer. The shop can disable the service under Yee3DPrint → Settings. Printer settings control nozzle diameter, layer height, speed and automatic supports; Infill settings control percentage and pattern; Material settings control filament diameter and density. The file limit is the smaller of the plugin limit (default 10 MB, configurable up to 20 MB) and the server PHP upload limits. Ensure the database packet size and backups support model blobs. Network-wide multisite activation is blocked; activate separately per site.

== Frequently Asked Questions ==

= Does this price depend on model volume or print duration? =
It can. Set a Material base-price basis or add Extra price rows for model volume, surface area, weight, support material, print hours or DXF laser-cutting path. The server recalculates 3D geometry, verifies supported 2D DXF cutting paths, and requests publisher-hosted PrusaSlicer analysis for support/time rules before priced checkout. Other DXF entities and DWG require a manual price request.

= Does preview guarantee printability? =
No. Review your service policies and production workflow. Preview dimensions and build-volume warnings are estimates.

= Why might a valid model fail to preview? =
A 45-second worker timeout, two million triangle limit and bounded 3MF archives apply. 3MF allows at most 256 entries, 64 MB expanded data and 8 MB per model XML. Browser memory/device limits also apply.

== Development and source ==

The complete human-readable source for the generated browser files is included in this plugin: src/frontend.js and src/model-stats.mjs generate assets/frontend.js; src/model-worker.js generates assets/model-worker.js. Build tooling and pinned dependencies are included in package.json and package-lock.json. From the plugin directory, run `npm ci` followed by `npm run build` to regenerate both browser assets and their license notices. The build uses esbuild and Three.js 0.186.0. Do not package node_modules. No runtime CDN is used. Cloud analysis runs on a separate publisher-hosted service.

Third-party browser code bundled into these assets: Three.js 0.186.0, MIT, https://github.com/mrdoob/three.js; its fflate module contains fflate 0.8.2, MIT, https://github.com/101arrowz/fflate. See assets/frontend.js.LEGAL.txt, assets/model-worker.js.LEGAL.txt and assets/license.three.txt. STEP preview also uses occt-import-js 0.0.23 and OpenCascade (LGPL 2.1 with the OpenCascade exception), source at https://github.com/kovacsv/occt-import-js and https://github.com/Open-Cascade-SAS/OCCT; see assets/license.occt-import-js.txt, assets/license.occt.txt and assets/license.occt-exception.txt. The occt-import-js.js and occt-import-js.wasm files match the published occt-import-js 0.0.23 npm package byte for byte and are not generated by this plugin's npm build.

== Changelog ==

= 1.3.14 =
* Restore the original model download handler for shop managers and authenticated order owners.
* Require a nonce before a quote is marked as viewed when its details are opened.

= 1.3.13 =
* Count unviewed private quotes and orders in the admin submenu and mark a quote viewed when its details are opened.

= 1.3.12 =
* Ship editable browser source, pinned build tooling, third-party notices and the STEP loader with the installable plugin.

= 1.3.11 =
* Label required print choices and form fields, and name incomplete choices beside checkout actions.

= 1.3.9 =
* Keep the optional None choice and coating swatches on one wrapping palette row.

= 1.3.8 =
* Give opt-in 3D and CNC sample options example prices and technical settings; refill marked older zero-price samples when Create is rerun.

= 1.3.7 =
* Treat explicitly configured zero-price Printers and other non-material options as free so they do not block a positively priced configuration from checkout.

= 1.3.6 =
* Show the subtotal of priced print options while required choices remain open or an unpriced service requires a manual quote.

= 1.3.5 =
* Register the public shop proof route in the active source plugin so the analysis server can verify a WordPress installation.

= 1.3.4 =
* Explain when automatic shop registration fails because WordPress is running on HTTP or localhost.

= 1.3.3 =
* Create a private site token automatically and register enabled shops with the publisher SaaS using an HTTPS challenge proof; no wp-config token is required.

= 1.3.2 =
* Price new sample 3D materials at 1 per cm³ and sample CNC materials at 1 per cm of cutting path; update untouched zero-price sample materials when Create is rerun.
* Show an explicit storefront analysis status when Cloud PrusaSlicer is disabled or the shop has no provisioned credential.

= 1.3.1 =
* Remove the redundant Connection status notice from Cloud analysis settings.

= 1.3.0 =
* Add purchase-code verification in Cloud analysis settings and a SaaS-enforced allowance of 5,000 successful analyses per UTC month per valid code, while retaining the 50-call trial.

= 1.2.99 =
* Separate sample catalog creation and removal into 3D-printing and CNC-cutting sets; hide Coatings and Infills display settings in the CNC-cutting view.

= 1.2.98 =
* Keep the internal WooCommerce checkout product out of storefront listings, search and the core sitemap; return 404 for its direct page while preserving configurator checkout.

= 1.2.97 =
* Add a dynamic Yee3DPrint Gutenberg block that shares the shortcode's PHP storefront renderer.

= 1.2.96 =
* Remove the explanatory no-price notice from the storefront while keeping the automatic price-request flow.

= 1.2.95 =
* Route configurations with an unpriced or zero-priced selected service to a price request instead of WooCommerce cart or checkout.

= 1.2.94 =
* Move Settings to the top of the Yeekit submenu and make sample catalog creation optional, with empty-catalog notice and marked-sample removal.

= 1.2.90 =
* Enable the demo, Material color palette and DXF upload by default; seed an editable laser cutter and two CNC cutting materials.
* Support PHP 7.4 by replacing PHP 8-only string helpers and lower the declared minimum PHP version.

= 1.2.89 =
* Use [yeekit_3d] as the sole configurator shortcode and update the existing configurator page.

= 1.2.88 =
* Match the WooCommerce Orders submenu counter markup and styling for unviewed quotes and orders.

= 1.2.87 =
* Show the number of unviewed 3D quotes and orders in the admin submenu, label unviewed rows, and mark a record viewed only when its details are opened.

= 1.2.86 =
* Add separate subject and content templates for shop and customer price-request emails, with placeholders and fields that hide when their email is disabled.

= 1.2.85 =
* Add an opt-in customer confirmation email for saved price requests, disabled by default and independent of shop notifications.

= 1.2.84 =
* Include the saved model or drawing, selected options, available statistics, and customer notes in WooCommerce order emails and shop price-request notifications.

= 1.2.83 =
* Remove redundant explanatory copy from the DXF cutting flow while retaining a clear checkout consent label and all cutting controls.

= 1.2.82 =
* Explain when a 3D upload has no compatible 3D printer and prevent CNC machine Quality choices from appearing in the print flow. Return a specific server error for missing printer selection.

= 1.2.80 =
* Expanded Model preview settings with configurable scene colors, light positions, ground, grid, fog, XYZ axes, build volume box, auto-rotation, camera fit on resize or scale changes, auto scaling, shadows, and optional File units, Scale and Model Stats controls.

= 1.2.79 =
* Allow a custom demo model upload when Show demo is enabled, conditionally show its setting and Step style, accept preset or merchant-added extensions for private manual quotes, and support centimeters as a file unit.

= 1.2.78 =
* Show server-verifiable DXF total path, path count, bounding-box XY area and material-thickness-based box volume. Laser machines can set cut speed, engrave speed and setup time for an estimated job duration. Persist these statistics with quotes and orders.

= 1.2.77 =
* Hide empty or unavailable cutting configuration groups after a DXF upload. Keep the configuration warning when a required laser machine is missing, and omit the lone ungrouped material label.

= 1.2.76 =
* Separate DXF laser-cutting configuration from 3D printing: filter materials and machines by technology, omit Quality and Infill, and choose Cut, Engrave or Ignore per DXF layer.
* Recheck selected DXF layer lengths on the server, charge engraving with a machine-specific per-centimeter rate, and show cutting details in quotes and WooCommerce orders.

= 1.2.75 =
* Refine the DXF 2D viewer, show its cutting-path statistic without 3D-only fields, and keep its scale and file-unit controls in the normal configurator.

= 1.2.74 =
* Apply only fixed and measured cutting-path Material rules to DXF drawings. Other 3D Material rules do not prevent the DXF checkout flow.

= 1.2.73 =
* Preview supported ASCII DXF drawings as 2D linework and calculate cutting length on the shop server. Recheck the original at submission and allow Material cutting-path prices through WooCommerce checkout. Retain the manual quote fallback for unsupported DXF entities and DWG.

= 1.2.72 =
* Replace customer-side local PrusaSlicer setup with an optional publisher-hosted analysis client. Show monthly usage from the service and keep its endpoint out of shop settings. The publisher must configure the HTTPS service and enforce the trial allowance before this feature can run.

= 1.2.71 =
* Move Local PrusaSlicer analysis into its own settings tab with a purchase-code setup gate and per-customer request counts. Disable slicer-dependent pricing and runtime analysis until setup is complete.

= 1.2.70 =
* Split the fallback build volume into compact X, Y and Z settings while retaining the stored comma-separated value.

= 1.2.69 =
* Save the customer-selected 3D preview as a private quote thumbnail and show it in Quotes and Orders and quote details.

= 1.2.68 =
* Clarify the DXF/DWG manual-quote state in the model viewer and verify private quote storage end to end.

= 1.2.67 =
* Add per-format upload settings with STEP/STP displayed separately. Optional DXF/DWG uploads create private manual price requests without 3D preview or automatic pricing.

= 1.2.66 =
* Load Settings assets using the actual WordPress submenu hook so Request price appears immediately when selected.

= 1.2.65 =
* Reveal the Request price settings tab as soon as Checkout behavior changes to a request mode and save that selection when opening the tab.

= 1.2.64 =
* Add conditional Request price settings for customer fields and shop email notifications. Save Company with quotes and validate configured field requirements on the server.

= 1.2.63 =
* Use Material Enabled to control frontend visibility regardless of editor status; remove the conflicting helper text.

= 1.2.62 =
* Show only Add extra price when a Material has no Extra price rows; create the first row on demand.

= 1.2.61 =
* Keep the original Material Base price row and update only its Calculation choices to match the supported Extra price measurements.

= 1.2.60 =
* Add Material Base price measurement choices while preserving previously saved prices and calculation modes.

= 1.2.59 =
* Replace the three fixed Material extras with an editable repeater (up to 20 rows), preserve legacy prices, and price supported geometry and local slicer measurements from server-calculated values.

= 1.2.58 =
* Calculate per-gram Material extras alongside a fixed or per-gram base price using verified model weight; show a clear message when material density is missing.

= 1.2.57 =
* Refresh the admin settings and catalog editor tabs with clearer active states, responsive spacing, and card-style content panels.

= 1.2.56 =
* Show Material base price and its pricing basis together on one row in the admin editor.

= 1.2.55 =
* Add a read-only Pricing guide tab to Settings with the current checkout formula, option rules, zero-price behavior, and an example.

= 1.2.54 =
* Seed a new shop's editable print catalog with material color palettes, a printer with two qualities, five coatings and post-processings, and infills from 0% to 100%. Keep existing catalogs unchanged.

= 1.2.53 =
* Auto-select and hide a single available Printer; show only Quality choices when that Printer has multiple choices, and hide both selectors when it has one Quality.

= 1.2.52 =
* Make the frontend demo card more compact, including its thumbnail and typography.

= 1.2.51 =
* Place the demo card above model measurements, hide it after a model loads, and show it again when the model is removed.

= 1.2.50 =
* Show separate Add to cart and Checkout buttons in the Cart and checkout behavior. Add to cart stays on the configurator with a View cart link; Checkout opens payment.

= 1.2.49 =
* Add an optional frontend demo card and bundled 10 mm cube that opens in the 3D configurator.

= 1.2.48 =
* Add a Cart and checkout behavior that calculates the price, adds the model to WooCommerce and opens the cart before payment.

= 1.2.47 =
* Put a Scale slider before the numeric percentage field and keep both controls synchronized with model dimensions.

= 1.2.46 =
* Add a Main color setting that applies to buttons, selected controls, progress and active steps across standard and accordion layouts.

= 1.2.45 =
* Add a selectable numbered Accordion steps layout, with expandable unlocked steps and a Finalize panel.

= 1.2.44 =
* Add optional Multi-step configuration with automatic single-choice advancement, Back/Next navigation and a final review. Remove the default Post-processings icon.

= 1.2.43 =
* Show file-read progress while loading a model preview and actual upload progress at checkout, followed by clear preview and server-processing states.

= 1.2.42 =
* Ignore empty or non-text group metadata when building admin group suggestions, avoiding PHP deprecation notices.

= 1.2.41 =
* Remove unnecessary trailing decimal zeros from numeric option and Material fields in admin, including previously saved values.

= 1.2.40 =
* Reanalyze an FFF/FDM model when the customer changes Print Quality, with loading feedback and reuse of previously calculated results. Explain when the selected printer technology cannot use local PrusaSlicer analysis.

= 1.2.39 =
* Replace Printer Print Quality text input with repeatable name and layer-height rows. Hide the frontend quality step for printers with one choice and apply that choice automatically to pricing, analysis and saved quotes.

= 1.2.38 =
* Show each non-color print option's Photo URL as its frontend icon, falling back to the bundled 3D printing image when no photo is set.

= 1.2.37 =
* Unlock print-configuration steps in the configured Materials-first or Printers-first order. Filter printer choices by the selected material and material choices by the selected printer, using compatibility rules from both catalogs.

= 1.2.36 =
* Add a server-rendered Print Quality choice grouped by Printer. Each Printer can set its own names and layer heights; the chosen quality controls local slicing and is saved with quotes and WooCommerce orders.

= 1.2.35 =
* Use the Printer layer height for local PrusaSlicer analysis, or the Material layer height when it has a valid override. Save the effective FDM layer height with each submitted quote.

= 1.2.34 =
* Apply the selected Coating color and surface appearance to the 3D preview; return to the Material appearance when no Coating is selected.

= 1.2.33 =
* Split Settings into Print options, Model preview, Uploads and analysis, and Checkout tabs. Add a configurable model shadow and shadow direction in the 3D preview.

= 1.2.32 =
* Add direct WooCommerce checkout, estimated-price request, and price request modes with a customer contact form and saved quote details.

= 1.2.31 =
* Add Settings for Materials/Printers display order and the destination after adding a priced model to the WooCommerce cart.

= 1.2.30 =
* Analyze committed model settings, run one slicer request at a time, reuse results, and show loading feedback for slicer-dependent statistics.

= 1.2.28 =
* Match the File units label typography and spacing to Scale (%).

= 1.2.27 =
* Let customers switch file units after uploading any supported format, and edit X/Y/Z model sizes to update uniform scale and preview.

= 1.2.26 =
* Replace the frontend File units dropdown with mm/in radio buttons, preselected from the admin Default file unit setting. Embedded-unit 3MF and STEP models continue to use their file units.

= 1.2.25 =
* Restore the always-visible corner X/Y/Z orientation widget and remove the axes drawn through the model.

= 1.2.24 =
* Draw X/Y/Z axes and labels directly in the 3D model scene, instead of in a corner overlay.

= 1.2.23 =
* Keep the X/Y/Z orientation indicator visible in the 3D preview before upload, while viewing a model, and after removing it.

= 1.2.22 =
* Add a color-coded X/Y/Z orientation indicator to the customer 3D preview that follows model view rotation.

= 1.2.21 =
* Use the existing quote/model list as the sole Yee3DPrint → Quotes and Orders screen. Remove the duplicate 3D order list and its detail screen.
* Keep WooCommerce order links on each quote and in its detail page.

= 1.2.20 =
* Remove the 3D viewer from Yeekit quote and order admin details, and show Model Stats from stored data instead.
* Save available model statistics with each uploaded quote and snapshot them on the WooCommerce order line item; show them in the WooCommerce order model panel.

= 1.2.19 =
* Put each private model and its interactive 3D preview together in a left-side review card on Yeekit quote and order details.
* Reduce Yeekit customer/order details to customer name, email and a link to the full WooCommerce order.

= 1.2.18 =
* Show 3D orders in a dedicated Yee3DPrint → Quotes and Orders table, with status views, search, sorting and pagination backed by WooCommerce order data.
* Open each 3D order on a separate detail screen with customer, payment, totals and individual model information. Keep uploaded models in the separate Quotes screen.

= 1.2.17 =
* Open Yee3DPrint → Quotes and Orders in the native WooCommerce Orders table, scoped to orders containing a Yee3DPrint model. Preserve the scope across status tabs, search and filters.
* Keep uploaded model quotes in a separate Yee3DPrint → Quotes screen, including files awaiting checkout. Index new WooCommerce orders for the filtered view.

= 1.2.16 =
* Rename the admin submenu to Quotes and Orders and replace expandable quote cards with a paginated order-style list and searchable quote IDs or filenames.
* Open each quote on its own detail screen; show model dimensions, print options and WooCommerce customer fields separately. Separate print options in the WooCommerce order model panel too.

= 1.2.15 =
* Add the visible Yee3DPrint → Báo giá và đơn hàng submenu and show the WooCommerce customer in each quote summary.
* Add an HPOS-compatible model and print configuration panel to WooCommerce order editing, with private model links.

= 1.2.14 =
* Link quotes from both classic checkout and WooCommerce Checkout Block orders, then show live WooCommerce customer, address, status, total and payment details in Yeekit admin.

= 1.2.13 =
* Calculate per-gram material prices from the uploaded model geometry and material density, including server-side checkout and WooCommerce cart recalculation.
* Hide zero-priced option amounts and the zero setup fee in the configurator.

= 1.2.12 =
* Treat blank catalog prices as zero in the configurator and server-side WooCommerce pricing, while keeping nonzero unsupported model-based rates unavailable for checkout.
* Fix model dimensions sent to the cart endpoint and use its checkout redirect. Initialize the WooCommerce cart in REST requests and restore missing private model storage before saving an upload.

= 1.2.11 =
* Keep Print configuration visible while locking its controls until a valid model loads; removing the model clears and locks selections again. Restore Disable display mode to hiding a catalog.

= 1.2.10 =
* Temporarily kept groups visible when their display setting was Disable; superseded in 1.2.11.

= 1.2.9 =
* Show published Yeekit Printer, Coating and other catalog entries even when prices are incomplete. Allow preview selection while keeping checkout blocked for incomplete or unsupported prices.
* Clear configuration selections when a model is removed.

= 1.2.8 =
* Add optional local PrusaSlicer analysis for sliced material and support volumes, filament weight, and print time. Use catalog settings and a temporary preview mesh; keep WooCommerce pricing unchanged.

= 1.2.7 =
* Add configurable default file unit and frontend Model Stats from preview geometry, with density-based solid weight where available.

= 1.2.6 =
* Add per-catalog display settings and Disable to hide all five option groups. Post-processings support checkboxes, radio, or dropdown; Infills support a selectable list or dropdown.

= 1.2.5 =
* Add selectable grouped dropdown, radio list, and grouped color palette displays for Materials.

= 1.2.4 =
* Move upload size, retention, and fallback build volume to a dedicated Settings submenu.

= 1.2.3 =
* Show materials with missing or analysis-based prices as unavailable, and restore legacy catalog options in the frontend and checkout validation.

= 1.2.2 =
* Group materials inside one PHP-rendered select and display saved material colors in its enhanced chooser.

= 1.2.1 =
* Render the shortcode form and catalog options in PHP; use JavaScript for 3D preview, filtering, pricing and upload.

= 1.1.0 =
* Independent shortcode configurator with five separate catalog post types.
* Authoritative configuration pricing, immutable cart snapshots and native WooCommerce checkout/order integration.
* Setup fee per upload, material compatibility rules and private model downloads.

= 1.0.0 =
* Initial 3D preview and quotation prototype.

Material settings: fixed per-piece base + three fixed/percentage extras, minimum material charge per piece, and material setup per uploaded model. A blank base price counts as zero. Percentage extras apply to the base material price only. Compatibility restrictions apply in both directions. Slicer profiles and physical properties are stored for shop reference. Local slicing provides Model Stats; nonzero measurement-based rules still need a verified checkout pricing pipeline.
