mirror of
https://github.com/penpot/penpot.git
synced 2026-03-21 18:03:47 +00:00
✨ Add support for boolean shapes
This commit is contained in:
committed by
Andrey Antukh
parent
6176027263
commit
cd1be43384
@@ -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]}]
|
||||
|
||||
@@ -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))))))))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
[]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
:union 0
|
||||
:difference 1
|
||||
:intersection 2
|
||||
:exclusion 3
|
||||
:exclude 3
|
||||
0))
|
||||
|
||||
(defn translate-blur-type
|
||||
|
||||
Reference in New Issue
Block a user