Add support for boolean shapes

This commit is contained in:
alonso.torres
2025-07-22 11:13:57 +02:00
committed by Andrey Antukh
parent 6176027263
commit cd1be43384
21 changed files with 1386 additions and 119 deletions

View File

@@ -21,10 +21,24 @@
[app.main.data.helpers :as dsh]
[app.main.data.workspace.selection :as dws]
[app.main.data.workspace.shapes :as dwsh]
[app.main.features :as features]
[app.main.store :as st]
[app.render-wasm.api :as wasm.api]
[beicon.v2.core :as rx]
[cuerdas.core :as str]
[potok.v2.core :as ptk]))
(defn update-bool-shape
[shape objects]
(let [content
(if (features/active-feature? @st/state "render-wasm/v1")
(wasm.api/calculate-bool (:bool-type shape) (reverse (:shapes shape)))
(path/calc-bool-content shape objects))]
(-> shape
(path/update-geometry content))))
(set! path/update-bool-shape* update-bool-shape)
(defn- create-bool-shape
[id type name shapes objects]
(let [shape-id
@@ -51,7 +65,7 @@
(-> shape
(merge (select-keys head path/bool-style-properties))
(cts/setup-shape)
(path/update-bool-shape objects))]
(update-bool-shape objects))]
[shape (cph/get-position-on-parent objects (:id head))]))
@@ -67,7 +81,7 @@
(assoc :type :bool)
(assoc :bool-type type)
(merge (select-keys head bool/style-properties))
(path/update-bool-shape objects))))
(update-bool-shape objects))))
(defn create-bool
[type & {:keys [ids force-shape-id]}]

View File

@@ -6,15 +6,24 @@
(ns app.main.data.workspace.path.shapes-to-path
(:require
[app.common.data :as d]
[app.common.files.changes-builder :as pcb]
[app.common.files.helpers :as cph]
[app.common.types.container :as ctn]
[app.common.types.path :as path]
[app.common.types.text :as txt]
[app.main.data.changes :as dch]
[app.main.data.helpers :as dsh]
[app.main.features :as features]
[app.render-wasm.api :as wasm.api]
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(def ^:private dissoc-attrs
[:x :y :width :height
:rx :ry :r1 :r2 :r3 :r4
:metadata])
(defn convert-selected-to-path
([]
(convert-selected-to-path nil))
@@ -22,21 +31,53 @@
(ptk/reify ::convert-selected-to-path
ptk/WatchEvent
(watch [it state _]
(let [page-id (:current-page-id state)
objects (dsh/lookup-page-objects state)
selected (->> (or ids (dsh/lookup-selected state))
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
(if (features/active-feature? state "render-wasm/v1")
(let [page-id (:current-page-id state)
objects (dsh/lookup-page-objects state)
selected
(->> (or ids (dsh/lookup-selected state))
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
children-ids
(into #{}
(mapcat #(cph/get-children-ids objects %))
selected)
children-ids
(into #{}
(mapcat #(cph/get-children-ids objects %))
selected)
changes
(-> (pcb/empty-changes it page-id)
(pcb/with-objects objects)
;; FIXME: use with-objects? true
(pcb/update-shapes selected #(path/convert-to-path % objects))
(pcb/remove-objects children-ids))]
changes
(-> (pcb/empty-changes it page-id)
(pcb/with-objects objects)
(pcb/update-shapes
selected
(fn [shape]
(let [content (wasm.api/shape-to-path (:id shape))]
(-> shape
(assoc :type :path)
(cond-> (cph/text-shape? shape)
(assoc :fills
(->> (txt/node-seq txt/is-text-node? (:content shape))
(map :fills)
(first))))
(cond-> (cph/image-shape? shape)
(assoc :fill-image (get shape :metadata)))
(d/without-keys dissoc-attrs)
(path/update-geometry content)))))
(pcb/remove-objects children-ids))]
(rx/of (dch/commit-changes changes)))
(rx/of (dch/commit-changes changes)))))))
(let [page-id (:current-page-id state)
objects (dsh/lookup-page-objects state)
selected (->> (or ids (dsh/lookup-selected state))
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
children-ids
(into #{}
(mapcat #(cph/get-children-ids objects %))
selected)
changes
(-> (pcb/empty-changes it page-id)
(pcb/with-objects objects)
(pcb/update-shapes selected path/convert-to-path {:with-objects? true})
(pcb/remove-objects children-ids))]
(rx/of (dch/commit-changes changes))))))))

View File

@@ -11,6 +11,7 @@
[app.main.data.workspace.bool :as dwb]
[app.main.data.workspace.path.shapes-to-path :as dwps]
[app.main.data.workspace.shortcuts :as sc]
[app.main.features :as features]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
@@ -36,8 +37,15 @@
(and (= (count selected) 1)
(not (contains? #{:group :bool} (:type (first selected)))))
disabled-bool-btns (or (empty? selected) has-invalid-shapes? first-not-group-like?)
disabled-flatten (or (empty? selected) has-invalid-shapes?)
disabled-bool-btns
(if (features/active-feature? @st/state "render-wasm/v1")
false
(or (empty? selected) has-invalid-shapes? first-not-group-like?))
disabled-flatten
(if (features/active-feature? @st/state "render-wasm/v1")
false
(or (empty? selected) has-invalid-shapes?))
set-bool
(mf/use-fn

View File

@@ -71,8 +71,9 @@
:code code
:icon icon
:permissions (into #{} (map str) permissions)})]
(when (sm/validate ::ctp/registry-entry manifest)
manifest)))
(if (sm/validate ::ctp/registry-entry manifest)
manifest
(.error js/console (clj->js (sm/explain ::ctp/registry-entry manifest))))))
(defn save-to-store
[]

View File

@@ -54,6 +54,7 @@
(def GRID-LAYOUT-ROW-ENTRY-SIZE 5)
(def GRID-LAYOUT-COLUMN-ENTRY-SIZE 5)
(def GRID-LAYOUT-CELL-ENTRY-SIZE 37)
(def RAW-SEGMENT-SIZE 28)
(defn modifier-get-entries-size
"Returns the list of a modifier list in bytes"
@@ -714,6 +715,7 @@
opacity (dm/get-prop shape :opacity)
hidden (dm/get-prop shape :hidden)
content (dm/get-prop shape :content)
bool-type (dm/get-prop shape :bool-type)
grow-type (dm/get-prop shape :grow-type)
blur (dm/get-prop shape :blur)
corners (when (some? (dm/get-prop shape :r1))
@@ -740,6 +742,8 @@
(set-masked masked))
(when (some? blur)
(set-shape-blur blur))
(when (= type :bool)
(set-shape-bool-type bool-type))
(when (and (some? content)
(or (= type :path)
(= type :bool)))
@@ -1053,6 +1057,51 @@
(h/call wasm/internal-module "_free_bytes")
[row column]))
(defn shape-to-path
[id]
(use-shape id)
(let [offset (h/call wasm/internal-module "_current_to_path")
heapu32 (mem/get-heap-u32)
heapu8 (mem/get-heap-u8)
len (aget heapu32 (mem/ptr8->ptr32 offset))
from-offset (+ offset 4)
to-offset (+ offset 4 (* len RAW-SEGMENT-SIZE))
data (js/Uint8Array. (.slice heapu8 from-offset to-offset))
content (path/from-bytes data)]
(h/call wasm/internal-module "_free_bytes")
content))
(defn calculate-bool
[bool-type ids]
(let [num-ids (count ids)
offset (mem/alloc-bytes (* CHILD-ENTRY-SIZE num-ids))
heap (mem/get-heap-u32)]
(loop [entries (seq ids)
current-offset offset]
(when-not (empty? entries)
(let [id (first entries)]
(sr/heapu32-set-uuid id heap (mem/ptr8->ptr32 current-offset))
(recur (rest entries) (+ current-offset CHILD-ENTRY-SIZE))))))
(let [offset (h/call wasm/internal-module "_calculate_bool" (sr/translate-bool-type bool-type))
heapu32 (mem/get-heap-u32)
heapu8 (mem/get-heap-u8)
len (aget heapu32 (mem/ptr8->ptr32 offset))
from-offset (+ offset 4)
to-offset (+ offset 4 (* len RAW-SEGMENT-SIZE))
data (js/Uint8Array. (.slice heapu8 from-offset to-offset))
content (path/from-bytes data)]
(h/call wasm/internal-module "_free_bytes")
content))
(defonce module
(delay
(if (exists? js/dynamicImport)

View File

@@ -168,7 +168,7 @@
:union 0
:difference 1
:intersection 2
:exclusion 3
:exclude 3
0))
(defn translate-blur-type