mirror of
https://github.com/penpot/penpot.git
synced 2026-02-13 07:02:58 +00:00
wip
This commit is contained in:
@@ -79,6 +79,7 @@
|
||||
"date-fns": "^2.30.0",
|
||||
"draft-js": "^0.11.7",
|
||||
"eventsource-parser": "^1.1.1",
|
||||
"gl-matrix": "^3.4.3",
|
||||
"highlight.js": "^11.8.0",
|
||||
"js-beautify": "^1.14.9",
|
||||
"jszip": "^3.10.1",
|
||||
|
||||
@@ -261,7 +261,13 @@
|
||||
(:y (first selected-shapes))
|
||||
(:y selected-frame))
|
||||
|
||||
rule-area-size (/ rules/rule-area-size zoom)]
|
||||
rule-area-size (/ rules/rule-area-size zoom)
|
||||
|
||||
;; Aquí podemos configurar como queremos que sea el renderizado:
|
||||
;; - "gl" Utilizando sólo WebGL2
|
||||
;; - "svg" Utilizando sólo SVG
|
||||
;; - "both" Utilizando ambos
|
||||
renderer "both"]
|
||||
|
||||
(hooks/setup-dom-events zoom disable-paste in-viewport? workspace-read-only?)
|
||||
(hooks/setup-viewport-size vport viewport-ref)
|
||||
@@ -305,54 +311,56 @@
|
||||
|
||||
[:& top-bar/top-bar]]
|
||||
|
||||
[:svg.render-shapes
|
||||
{:id "render"
|
||||
:xmlns "http://www.w3.org/2000/svg"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns:penpot "https://penpot.app/xmlns"
|
||||
:preserveAspectRatio "xMidYMid meet"
|
||||
:key (str "render" page-id)
|
||||
:width (:width vport 0)
|
||||
:height (:height vport 0)
|
||||
:view-box (utils/format-viewbox vbox)
|
||||
:style {:background-color background
|
||||
:pointer-events "none"}
|
||||
:fill "none"}
|
||||
(when (or (= renderer "svg") (= renderer "both"))
|
||||
[:svg.render-shapes
|
||||
{:id "render"
|
||||
:xmlns "http://www.w3.org/2000/svg"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns:penpot "https://penpot.app/xmlns"
|
||||
:preserveAspectRatio "xMidYMid meet"
|
||||
:key (str "render" page-id)
|
||||
:width (:width vport 0)
|
||||
:height (:height vport 0)
|
||||
:view-box (utils/format-viewbox vbox)
|
||||
:style {:background-color background
|
||||
:pointer-events "none"}
|
||||
:fill "none"}
|
||||
|
||||
[:defs
|
||||
[:linearGradient {:id "frame-placeholder-gradient"}
|
||||
[:animateTransform
|
||||
{:attributeName "gradientTransform"
|
||||
:type "translate"
|
||||
:from "-1 0"
|
||||
:to "1 0"
|
||||
:dur "2s"
|
||||
:repeatCount "indefinite"}]
|
||||
[:stop {:offset "0%" :stop-color (str "color-mix(in srgb-linear, " background " 90%, #777)") :stop-opacity 1}]
|
||||
[:stop {:offset "50%" :stop-color (str "color-mix(in srgb-linear, " background " 80%, #777)") :stop-opacity 1}]
|
||||
[:stop {:offset "100%" :stop-color (str "color-mix(in srgb-linear, " background " 90%, #777)") :stop-opacity 1}]]]
|
||||
[:defs
|
||||
[:linearGradient {:id "frame-placeholder-gradient"}
|
||||
[:animateTransform
|
||||
{:attributeName "gradientTransform"
|
||||
:type "translate"
|
||||
:from "-1 0"
|
||||
:to "1 0"
|
||||
:dur "2s"
|
||||
:repeatCount "indefinite"}]
|
||||
[:stop {:offset "0%" :stop-color (str "color-mix(in srgb-linear, " background " 90%, #777)") :stop-opacity 1}]
|
||||
[:stop {:offset "50%" :stop-color (str "color-mix(in srgb-linear, " background " 80%, #777)") :stop-opacity 1}]
|
||||
[:stop {:offset "100%" :stop-color (str "color-mix(in srgb-linear, " background " 90%, #777)") :stop-opacity 1}]]]
|
||||
|
||||
(when (dbg/enabled? :show-export-metadata)
|
||||
[:& use/export-page {:options options}])
|
||||
(when (dbg/enabled? :show-export-metadata)
|
||||
[:& use/export-page {:options options}])
|
||||
|
||||
;; We need a "real" background shape so layer transforms work properly in firefox
|
||||
[:rect {:width (:width vbox 0)
|
||||
:height (:height vbox 0)
|
||||
:x (:x vbox 0)
|
||||
:y (:y vbox 0)
|
||||
:fill background}]
|
||||
;; We need a "real" background shape so layer transforms work properly in firefox
|
||||
[:rect {:width (:width vbox 0)
|
||||
:height (:height vbox 0)
|
||||
:x (:x vbox 0)
|
||||
:y (:y vbox 0)
|
||||
:fill background}]
|
||||
|
||||
[:& (mf/provider ctx/current-vbox) {:value vbox'}
|
||||
[:& (mf/provider use/include-metadata-ctx) {:value (dbg/enabled? :show-export-metadata)}
|
||||
;; Render root shape
|
||||
[:& shapes/root-shape {:key page-id
|
||||
:objects base-objects
|
||||
:active-frames @active-frames}]]]]
|
||||
[:& (mf/provider ctx/current-vbox) {:value vbox'}
|
||||
[:& (mf/provider use/include-metadata-ctx) {:value (dbg/enabled? :show-export-metadata)}
|
||||
;; Render root shape
|
||||
[:& shapes/root-shape {:key page-id
|
||||
:objects base-objects
|
||||
:active-frames @active-frames}]]]])
|
||||
|
||||
;; IT's MAGIC!
|
||||
[gl/canvas {:objects base-objects
|
||||
:active-frames @active-frames
|
||||
:vbox vbox}]
|
||||
(when (or (= renderer "gl") (= renderer "both"))
|
||||
[gl/canvas {:objects base-objects
|
||||
:active-frames @active-frames
|
||||
:vbox vbox}])
|
||||
|
||||
[:svg.viewport-controls
|
||||
{:xmlns "http://www.w3.org/2000/svg"
|
||||
|
||||
@@ -2,87 +2,129 @@
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require-macros [app.util.gl.macros :refer [slurp]])
|
||||
(:require
|
||||
["gl-matrix" :as glm]
|
||||
[app.common.math :as math]
|
||||
[app.util.gl :as gl]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def CANVAS_CONTEXT_ID "webgl2")
|
||||
(def CANVAS_CONTEXT_ID "webgl2")
|
||||
|
||||
(def default-vertex-shader (slurp "src/app/util/gl/shaders/default.v.glsl"))
|
||||
(def default-fragment-shader (slurp "src/app/util/gl/shaders/default.f.glsl"))
|
||||
(def default-vertex-shader (slurp "src/app/util/gl/shaders/default.v.glsl"))
|
||||
(def default-fragment-shader (slurp "src/app/util/gl/shaders/default.f.glsl"))
|
||||
|
||||
#_(def shaders (js/Map.))
|
||||
(def programs (js/Map.))
|
||||
#_(def textures (js/Map.))
|
||||
#_(def framebuffers (js/Map.))
|
||||
#_(def shaders (js/Map.))
|
||||
(def programs (js/Map.))
|
||||
#_(def textures (js/Map.))
|
||||
#_(def framebuffers (js/Map.))
|
||||
|
||||
(defn parse-color-hex
|
||||
[color opacity]
|
||||
(let [r (str/slice color 1 3)
|
||||
g (str/slice color 3 5)
|
||||
b (str/slice color 5 7)]
|
||||
#js [(/ (js/parseInt r 16) 255.0)
|
||||
(/ (js/parseInt g 16) 255.0)
|
||||
(/ (js/parseInt b 16) 255.0)
|
||||
opacity]))
|
||||
(defn parse-color-hex
|
||||
"Parses a color string and returns a vector with the RGBA values."
|
||||
[color opacity]
|
||||
(let [r (str/slice color 1 3)
|
||||
g (str/slice color 3 5)
|
||||
b (str/slice color 5 7)]
|
||||
#js [(/ (js/parseInt r 16) 255.0)
|
||||
(/ (js/parseInt g 16) 255.0)
|
||||
(/ (js/parseInt b 16) 255.0)
|
||||
opacity]))
|
||||
|
||||
(defn parse-color
|
||||
[color opacity]
|
||||
(cond
|
||||
(str/starts-with? color "#")
|
||||
(parse-color-hex color opacity)
|
||||
(defn parse-color
|
||||
"Parses a color string and returns a vector with the RGBA values."
|
||||
[color opacity]
|
||||
(cond
|
||||
(str/starts-with? color "#")
|
||||
(parse-color-hex color opacity)
|
||||
|
||||
:else
|
||||
#js [0.0 0.0 0.0 1.0]))
|
||||
:else
|
||||
#js [0.0 0.0 0.0 1.0]))
|
||||
|
||||
(defn resize-canvas-to
|
||||
[canvas width height]
|
||||
(let [resized-width (not= (.-width canvas) width)
|
||||
resized-height (not= (.-height canvas) height)
|
||||
resized (or resized-width resized-height)]
|
||||
(when resized-width
|
||||
(set! (.-width canvas) width))
|
||||
(when resized-height
|
||||
(set! (.-height canvas) height))
|
||||
resized))
|
||||
(defn get-object-type-as-int
|
||||
"Returns the object type as an integer."
|
||||
[object]
|
||||
(case (:type object)
|
||||
:rect 0
|
||||
:circle 1
|
||||
:group 2
|
||||
:path 3
|
||||
:text 4
|
||||
:image 5
|
||||
:svg-raw 6
|
||||
:bool 7
|
||||
:frame 8))
|
||||
|
||||
(defn resize-canvas
|
||||
[canvas]
|
||||
(let [width (math/floor (.-clientWidth canvas))
|
||||
height (math/floor (.-clientHeight canvas))]
|
||||
(resize-canvas-to canvas width height)))
|
||||
(defn resize-canvas-to
|
||||
"Resize canvas to specific coordinates."
|
||||
[canvas width height]
|
||||
(let [resized-width (not= (.-width canvas) width)
|
||||
resized-height (not= (.-height canvas) height)
|
||||
resized (or resized-width resized-height)]
|
||||
(when resized-width
|
||||
(set! (.-width canvas) width))
|
||||
(when resized-height
|
||||
(set! (.-height canvas) height))
|
||||
resized))
|
||||
|
||||
(defn prepare-gl
|
||||
[gl]
|
||||
(let [default-program (gl/create-program-from-sources gl default-vertex-shader default-fragment-shader)]
|
||||
(.set programs "default" default-program)))
|
||||
(defn resize-canvas
|
||||
"Resizes the canvas intrinsic size to the element size."
|
||||
[canvas]
|
||||
(let [width (math/floor (.-clientWidth canvas))
|
||||
height (math/floor (.-clientHeight canvas))]
|
||||
(resize-canvas-to canvas width height)))
|
||||
|
||||
(defn prepare-gl
|
||||
"Prepares the WebGL context for rendering."
|
||||
[gl]
|
||||
(let [default-program (gl/create-program-from-sources gl default-vertex-shader default-fragment-shader)]
|
||||
(.set programs "default" default-program)))
|
||||
|
||||
(defn render-gl
|
||||
"Renders the whole document to the canvas."
|
||||
[gl objects vbox]
|
||||
(.clearColor gl 1.0 0.0 1.0 0)
|
||||
(.clear gl (.-COLOR_BUFFER_BIT gl))
|
||||
(let [projection (.create glm/mat3)
|
||||
projection (.projection glm/mat3 projection (:width vbox) (:height vbox))]
|
||||
|
||||
(.viewport gl 0 0 (.-width (.-canvas gl)) (.-height (.-canvas gl)))
|
||||
(.clearColor gl 1.0 0.0 1.0 0.5)
|
||||
(.clear gl (.-COLOR_BUFFER_BIT gl))
|
||||
|
||||
(.useProgram gl (.get programs "default"))
|
||||
(.uniform4f gl (.getUniformLocation gl (.get programs "default") "u_vbox") (:x vbox) (:y vbox) (:width vbox) (:height vbox))
|
||||
(.viewport gl 0 0 (.-width (.-canvas gl)) (.-height (.-canvas gl)))
|
||||
|
||||
(.enable gl (.-BLEND gl))
|
||||
(.blendFunc gl (.-SRC_ALPHA gl) (.-ONE_MINUS_SRC_ALPHA gl))
|
||||
;; Enable alpha blending
|
||||
(.enable gl (.-BLEND gl))
|
||||
(.blendFunc gl (.-SRC_ALPHA gl) (.-ONE_MINUS_SRC_ALPHA gl))
|
||||
|
||||
(doseq [[_ object] objects]
|
||||
(let [selrect (:selrect object)
|
||||
x (:x selrect)
|
||||
y (:y selrect)
|
||||
width (:width selrect)
|
||||
height (:height selrect)]
|
||||
(doseq [fill (reverse (:fills object))]
|
||||
(do
|
||||
(.uniform4fv gl (.getUniformLocation gl (.get programs "default") "u_color") (parse-color (:fill-color fill) (:fill-opacity fill)))
|
||||
(.uniform2f gl (.getUniformLocation gl (.get programs "default") "u_size") width height)
|
||||
(.uniform2f gl (.getUniformLocation gl (.get programs "default") "u_position") x y)
|
||||
(.drawArrays gl (.-TRIANGLE_STRIP gl) 0 4))))))
|
||||
(.useProgram gl (.get programs "default"))
|
||||
(println "---------------> vbox" (:x vbox) (:width vbox) (:y vbox) (:height vbox))
|
||||
(.uniformMatrix3fv gl (.getUniformLocation gl (.get programs "default") "u_projection") false projection)
|
||||
(.uniform4f gl (.getUniformLocation gl (.get programs "default") "u_vbox") (:x vbox) (:y vbox) (:width vbox) (:height vbox))
|
||||
|
||||
(doseq [[_ object] objects]
|
||||
(let [selrect (:selrect object)
|
||||
x (:x selrect)
|
||||
y (:y selrect)
|
||||
width (:width selrect)
|
||||
height (:height selrect)
|
||||
rotation (:rotation object)
|
||||
;; Tengo que encontrar la forma de "reordenar la matriz" para que funcione la
|
||||
;; rotación.
|
||||
;; transform (:transform object)
|
||||
;; {a :a b :b c :c d :d e :e f :f} transform
|
||||
;; matrix #_(js/Float32Array. #js [a c 0 b d 0 0 0 1])
|
||||
matrix (js/Float32Array. #js [1 0 0 0 1 0 0 0 1])
|
||||
fill (first (:fills object))]
|
||||
(js/console.log "fill" fill)
|
||||
(js/console.log "matrix" matrix)
|
||||
(.uniform1i gl (.getUniformLocation gl (.get programs "default") "u_type") (get-object-type-as-int object))
|
||||
(.uniform2f gl (.getUniformLocation gl (.get programs "default") "u_size") width height)
|
||||
(.uniform2f gl (.getUniformLocation gl (.get programs "default") "u_position") x y)
|
||||
(.uniform1f gl (.getUniformLocation gl (.get programs "default") "u_rotation") (/ (* rotation js/Math.PI) 180.0))
|
||||
#_(.uniformMatrix3fv gl (.getUniformLocation gl (.get programs "default") "u_transform") false matrix)
|
||||
;; NOTA: Esto es sólo aplicable en objetos que poseen fills (los textos no
|
||||
;; poseen fills).
|
||||
(doseq [fill (reverse (:fills object))]
|
||||
(do
|
||||
(.uniform4fv gl (.getUniformLocation gl (.get programs "default") "u_color") (parse-color (:fill-color fill) (:fill-opacity fill)))
|
||||
(.drawArrays gl (.-TRIANGLE_STRIP gl) 0 4)))))))
|
||||
|
||||
(mf/defc canvas
|
||||
"A canvas element with a WebGL context."
|
||||
@@ -91,7 +133,21 @@
|
||||
(let [objects (unchecked-get props "objects")
|
||||
vbox (unchecked-get props "vbox")
|
||||
canvas-ref (mf/use-ref nil)
|
||||
gl-ref (mf/use-ref nil)]
|
||||
gl-ref (mf/use-ref nil)
|
||||
|
||||
on-context-lost
|
||||
(mf/use-fn (fn []
|
||||
(mf/set-ref-val! gl-ref nil)))
|
||||
|
||||
on-context-restore
|
||||
(mf/use-fn (fn []
|
||||
(let [canvas (mf/ref-val canvas-ref)]
|
||||
(when (some? canvas)
|
||||
(let [gl (.getContext canvas CANVAS_CONTEXT_ID)]
|
||||
(mf/set-ref-val! gl-ref gl)
|
||||
(resize-canvas canvas)
|
||||
(prepare-gl gl)
|
||||
(render-gl gl objects vbox))))))]
|
||||
|
||||
(mf/with-effect [objects vbox]
|
||||
(let [gl (mf/ref-val gl-ref)]
|
||||
@@ -101,15 +157,24 @@
|
||||
(mf/with-effect [canvas-ref]
|
||||
(let [canvas (mf/ref-val canvas-ref)]
|
||||
(when (some? canvas)
|
||||
(.addEventListener canvas "webglcontextlost" on-context-lost)
|
||||
(.addEventListener canvas "webglcontextrestore" on-context-restore)
|
||||
(let [gl (.getContext canvas CANVAS_CONTEXT_ID)]
|
||||
(mf/set-ref-val! gl-ref gl)
|
||||
(resize-canvas canvas)
|
||||
(prepare-gl gl)
|
||||
(render-gl gl objects vbox)))))
|
||||
(render-gl gl objects vbox))))
|
||||
|
||||
;; unmount
|
||||
(fn []
|
||||
(let [canvas (mf/ref-val canvas-ref)]
|
||||
(when (some? canvas)
|
||||
(.removeEventListener canvas "webglcontextlost" on-context-lost)
|
||||
(.removeEventListener canvas "webglcontextrestore" on-context-restore)))))
|
||||
|
||||
[:canvas {:class (stl/css :canvas)
|
||||
:ref canvas-ref}]))
|
||||
|
||||
;; TODO
|
||||
;; TODO
|
||||
;; - blend modes
|
||||
;; - strokes
|
||||
;; - strokes
|
||||
|
||||
@@ -1,18 +1,50 @@
|
||||
#version 300 es
|
||||
|
||||
const int type_rect = 0;
|
||||
const int type_circle = 1;
|
||||
const int type_group = 2;
|
||||
const int type_path = 3;
|
||||
const int type_text = 4;
|
||||
const int type_image = 5;
|
||||
const int type_svg_raw = 6;
|
||||
const int type_bool = 7;
|
||||
const int type_frame = 8;
|
||||
|
||||
precision highp float;
|
||||
|
||||
// in vec2 v_texCoord;
|
||||
|
||||
// uniform sampler2D u_texture;
|
||||
uniform vec4 u_color;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
in vec2 v_texCoord;
|
||||
|
||||
uniform int u_type;
|
||||
uniform vec4 u_color;
|
||||
|
||||
void main() {
|
||||
// fragColor = texture(u_framebuffer, v_texCoord) + texture(u_texture, v_texCoord);
|
||||
// fragColor = texture(u_texture, v_texCoord);
|
||||
// Pintamos rosita
|
||||
fragColor = u_color;
|
||||
// fragColor = vec4(1.0, 0.0, 1.0, 1.0);
|
||||
// Si es un rect o un frame, simplemente asignamos el color al fragColor.
|
||||
if (u_type == type_rect || u_type == type_frame) {
|
||||
fragColor = u_color;
|
||||
// Si es un circulo, comprobamos que el pixel este dentro del circulo, en caso
|
||||
// contrario descartamos el pixel.
|
||||
} else if (u_type == type_circle) {
|
||||
if (length(v_texCoord - 0.5) > 0.5) {
|
||||
discard;
|
||||
}
|
||||
if(length(v_texCoord - 0.5f) > 0.45f) {
|
||||
|
||||
fragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
} else if(length(v_texCoord - 0.5f) > 0.4f) {
|
||||
fragColor = vec4(1.0f, 0.0f, 1.0f, 1.0f);
|
||||
} else {
|
||||
fragColor = u_color;
|
||||
}
|
||||
// Para cualquier otro elemento no soportado pintamos una especie de rejilla
|
||||
// raruna.
|
||||
} else {
|
||||
fragColor = vec4(
|
||||
round(mod(v_texCoord.x, 0.1) * 10.0),
|
||||
round(mod(v_texCoord.y, .1) * 10.0),
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -5,47 +5,46 @@ precision highp float;
|
||||
uniform vec4 u_vbox;
|
||||
uniform vec2 u_position;
|
||||
uniform vec2 u_size;
|
||||
uniform float u_rotation;
|
||||
uniform mat3 u_projection;
|
||||
|
||||
// out vec2 v_texCoord;
|
||||
out vec2 v_texCoord;
|
||||
|
||||
vec2 get_vertex_position(int id) {
|
||||
if(id == 0) {
|
||||
return vec2(0.0f, 0.0f);
|
||||
return vec2(-1.0, -1.0);
|
||||
} else if(id == 1) {
|
||||
return vec2(1.0f, 0.0f);
|
||||
return vec2(1.0, -1.0);
|
||||
} else if(id == 2) {
|
||||
return vec2(0.0f, 1.0f);
|
||||
return vec2(-1.0, 1.0);
|
||||
} else if(id == 3) {
|
||||
return vec2(1.0f, 1.0f);
|
||||
return vec2(1.0, 1.0);
|
||||
} else {
|
||||
return vec2(0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
vec2 get_tex_position(int id) {
|
||||
if(id == 0) {
|
||||
return vec2(0.0f, 1.0f);
|
||||
} else if(id == 1) {
|
||||
return vec2(1.0f, 1.0f);
|
||||
} else if(id == 2) {
|
||||
return vec2(0.0f, 0.0f);
|
||||
} else if(id == 3) {
|
||||
return vec2(1.0f, 0.0f);
|
||||
} else {
|
||||
return vec2(0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
vec2 from(vec2 v, vec2 min, vec2 max) {
|
||||
return (v - min) / (max - min);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 center = u_size * 0.5;
|
||||
vec2 position = u_position - vec2(u_vbox.xy);
|
||||
|
||||
float c = cos(u_rotation);
|
||||
float s = sin(u_rotation);
|
||||
|
||||
mat2 rotation = mat2(c, s, -s, c);
|
||||
mat2 scale = mat2(
|
||||
u_size.x * 0.5, 0.0f,
|
||||
0.0f, u_size.y * 0.5
|
||||
);
|
||||
mat2 rotation_scale = rotation * scale;
|
||||
|
||||
vec2 vertex = get_vertex_position(gl_VertexID);
|
||||
vec2 position = vertex * from(u_size, vec2(0), u_vbox.zw) + from(u_position, u_vbox.xy, u_vbox.xy + u_vbox.zw); // 0,1
|
||||
gl_Position = vec4(mix(vec2(-1.0, 1.0), vec2(1.0, -1.0), position), 0.0f, 1.0f);
|
||||
// gl_Position = vec4(((get_base_position(gl_VertexID) * u_size + u_position) / u_vbox.zw), 0.0f, 1.0f);
|
||||
// v_texCoord = get_tex_position(gl_VertexID);
|
||||
|
||||
vec2 vertex_rotated_scaled = rotation_scale * vertex;
|
||||
vec2 vertex_positioned = center + vertex_rotated_scaled + position;
|
||||
|
||||
vec3 projected = u_projection * vec3(vertex_positioned, 1.0);
|
||||
|
||||
gl_Position = vec4(projected, 1.0f);
|
||||
v_texCoord = (vertex + 1.0) * 0.5;
|
||||
}
|
||||
@@ -7587,6 +7587,7 @@ __metadata:
|
||||
draft-js: "npm:^0.11.7"
|
||||
eventsource-parser: "npm:^1.1.1"
|
||||
gettext-parser: "npm:^7.0.1"
|
||||
gl-matrix: "npm:^3.4.3"
|
||||
gulp: "npm:4.0.2"
|
||||
gulp-cached: "npm:^1.1.1"
|
||||
gulp-concat: "npm:^2.6.1"
|
||||
@@ -7891,6 +7892,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"gl-matrix@npm:^3.4.3":
|
||||
version: 3.4.3
|
||||
resolution: "gl-matrix@npm:3.4.3"
|
||||
checksum: c8ee6e2ce2d089b4ba4ae13ec9d4cb99bf2abe5f68f0cb08d94bbd8bafbec13aacc7230b86539ce5ca01b79226ea8c3194f971f5ca0c81838bc5e4e619dc398e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"glob-parent@npm:^3.1.0":
|
||||
version: 3.1.0
|
||||
resolution: "glob-parent@npm:3.1.0"
|
||||
|
||||
Reference in New Issue
Block a user