react-godot-shader-preview 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/GodotMaterialPreview.css +43 -8
- package/dist/GodotMaterialPreviewView.js +3 -1
- package/dist/style.css +43 -8
- package/godot/embed.html +4 -2
- package/godot/index.html +1 -1
- package/package.json +1 -1
|
@@ -14,19 +14,33 @@
|
|
|
14
14
|
display: flex;
|
|
15
15
|
flex-direction: column;
|
|
16
16
|
min-width: 0;
|
|
17
|
+
max-width: 100%;
|
|
18
|
+
height: 100%;
|
|
19
|
+
max-height: 100%;
|
|
20
|
+
min-height: 0;
|
|
17
21
|
}
|
|
18
22
|
|
|
19
|
-
.rgs-previewWrap {
|
|
23
|
+
.rgs-previewWrap {
|
|
24
|
+
max-width: 100%;
|
|
25
|
+
min-width: 0;
|
|
26
|
+
flex: 1 1 0;
|
|
27
|
+
min-height: 0;
|
|
28
|
+
display: flex;
|
|
29
|
+
align-items: center;
|
|
30
|
+
justify-content: center;
|
|
31
|
+
}
|
|
20
32
|
|
|
21
33
|
.rgs-preview {
|
|
22
|
-
width: 100%;
|
|
23
|
-
padding-bottom: 100%;
|
|
24
|
-
height: 0;
|
|
25
34
|
position: relative;
|
|
26
35
|
overflow: hidden;
|
|
27
36
|
border: 1px solid var(--rgs-b);
|
|
28
37
|
border-radius: 6px;
|
|
29
38
|
background: #000;
|
|
39
|
+
aspect-ratio: 1;
|
|
40
|
+
height: 100%;
|
|
41
|
+
width: auto;
|
|
42
|
+
max-width: 100%;
|
|
43
|
+
max-height: 100%;
|
|
30
44
|
}
|
|
31
45
|
|
|
32
46
|
.rgs-canvas {
|
|
@@ -41,15 +55,28 @@
|
|
|
41
55
|
|
|
42
56
|
.rgs-mouseBlockOverlay { position: absolute; inset: 0; z-index: 5; pointer-events: auto; cursor: default; }
|
|
43
57
|
|
|
44
|
-
/*
|
|
58
|
+
/* Overlay layer: same size as preview so mode strip and loading overlay are positioned correctly */
|
|
59
|
+
.rgs-previewOverlays {
|
|
60
|
+
position: absolute;
|
|
61
|
+
inset: 0;
|
|
62
|
+
z-index: 8;
|
|
63
|
+
pointer-events: none;
|
|
64
|
+
padding: 12px;
|
|
65
|
+
box-sizing: border-box;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.rgs-previewOverlays > * { pointer-events: auto; }
|
|
69
|
+
|
|
70
|
+
/* Mode strip (sphere/plane): positioned inside overlay padding so it never gets clipped */
|
|
45
71
|
.rgs-modeStrip {
|
|
46
72
|
position: absolute;
|
|
47
73
|
bottom: 8px;
|
|
48
74
|
right: 8px;
|
|
75
|
+
left: auto;
|
|
76
|
+
top: auto;
|
|
49
77
|
display: flex;
|
|
50
78
|
gap: 4px;
|
|
51
79
|
z-index: 10;
|
|
52
|
-
pointer-events: auto;
|
|
53
80
|
}
|
|
54
81
|
|
|
55
82
|
.rgs-modeStripButton {
|
|
@@ -81,8 +108,16 @@
|
|
|
81
108
|
z-index: 10;
|
|
82
109
|
}
|
|
83
110
|
|
|
84
|
-
/* Status */
|
|
85
|
-
.rgs-
|
|
111
|
+
/* Status: fixed-height slot so canvas size does not change when status appears */
|
|
112
|
+
.rgs-statusBarSlot {
|
|
113
|
+
flex: 0 0 auto;
|
|
114
|
+
display: flex;
|
|
115
|
+
align-items: center;
|
|
116
|
+
margin-top: 8px;
|
|
117
|
+
min-height: 32px;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.rgs-statusBar { display: flex; align-items: center; min-height: 32px; }
|
|
86
121
|
.rgs-statusSuccess, .rgs-statusError { padding: 8px 12px; border-radius: 4px; font-size: 13px; }
|
|
87
122
|
.rgs-statusSuccess { background: var(--rgs-ok); color: var(--rgs-ok-fg); }
|
|
88
123
|
.rgs-statusError { background: var(--rgs-err); color: var(--rgs-err-fg); }
|
|
@@ -12,11 +12,13 @@ const cn = {
|
|
|
12
12
|
preview: 'rgs-preview',
|
|
13
13
|
canvas: 'rgs-canvas',
|
|
14
14
|
mouseBlockOverlay: 'rgs-mouseBlockOverlay',
|
|
15
|
+
previewOverlays: 'rgs-previewOverlays',
|
|
15
16
|
modeStrip: 'rgs-modeStrip',
|
|
16
17
|
modeStripButton: 'rgs-modeStripButton',
|
|
17
18
|
modeStripButtonActive: 'rgs-modeStripButtonActive',
|
|
18
19
|
loadingOverlay: 'rgs-loadingOverlay',
|
|
19
20
|
statusBar: 'rgs-statusBar',
|
|
21
|
+
statusBarSlot: 'rgs-statusBarSlot',
|
|
20
22
|
statusSuccess: 'rgs-statusSuccess',
|
|
21
23
|
statusError: 'rgs-statusError',
|
|
22
24
|
paramsPanel: 'rgs-paramsPanel',
|
|
@@ -41,7 +43,7 @@ const cn = {
|
|
|
41
43
|
paramSelect: 'rgs-paramSelect',
|
|
42
44
|
};
|
|
43
45
|
export function GodotMaterialPreviewView({ iframeRef, embedUrl, previewWidth, showMeshSwitch, allowMouseInteraction, showParameters, status, godotLoading, uniforms, samplerState, displayMode, setDisplayMode, updateUniform, updateSampler, setParameter, className, }) {
|
|
44
|
-
return (_jsxs("div", { className: `${cn.root} ${className ?? ''}`, style: { flex: `0 0 ${previewWidth}px` }, children: [_jsx("div", { className: cn.previewWrap, children: _jsxs("div", { className: cn.preview, children: [_jsx("iframe", { ref: iframeRef, src: embedUrl, title: "Shader preview", className: cn.canvas }), !allowMouseInteraction && _jsx("div", { className: cn.mouseBlockOverlay, "aria-hidden": true }), showMeshSwitch && (_jsxs("div", { className: cn.modeStrip, role: "group", "aria-label": "Preview display mode", children: [_jsx("button", { type: "button", className: `${cn.modeStripButton} ${displayMode === 'Circle' ? cn.modeStripButtonActive : ''}`, onClick: () => setDisplayMode('Circle'), title: "Sphere", "aria-pressed": displayMode === 'Circle', "aria-label": "Sphere", children: _jsx(CircleIcon, {}) }), _jsx("button", { type: "button", className: `${cn.modeStripButton} ${displayMode === 'Plane' ? cn.modeStripButtonActive : ''}`, onClick: () => setDisplayMode('Plane'), title: "Plane", "aria-pressed": displayMode === 'Plane', "aria-label": "Plane", children: _jsx(DiamondIcon, {}) })] })), godotLoading && (_jsx("div", { className: cn.loadingOverlay, children: _jsx("div", { children: status?.message ?? 'Loading...' }) }))] }) }),
|
|
46
|
+
return (_jsxs("div", { className: `${cn.root} ${className ?? ''}`, style: { flex: `0 0 ${previewWidth}px` }, children: [_jsx("div", { className: cn.previewWrap, children: _jsxs("div", { className: cn.preview, children: [_jsx("iframe", { ref: iframeRef, src: embedUrl, title: "Shader preview", className: cn.canvas }), !allowMouseInteraction && _jsx("div", { className: cn.mouseBlockOverlay, "aria-hidden": true }), _jsxs("div", { className: cn.previewOverlays, children: [showMeshSwitch && (_jsxs("div", { className: cn.modeStrip, role: "group", "aria-label": "Preview display mode", children: [_jsx("button", { type: "button", className: `${cn.modeStripButton} ${displayMode === 'Circle' ? cn.modeStripButtonActive : ''}`, onClick: () => setDisplayMode('Circle'), title: "Sphere", "aria-pressed": displayMode === 'Circle', "aria-label": "Sphere", children: _jsx(CircleIcon, {}) }), _jsx("button", { type: "button", className: `${cn.modeStripButton} ${displayMode === 'Plane' ? cn.modeStripButtonActive : ''}`, onClick: () => setDisplayMode('Plane'), title: "Plane", "aria-pressed": displayMode === 'Plane', "aria-label": "Plane", children: _jsx(DiamondIcon, {}) })] })), godotLoading && (_jsx("div", { className: cn.loadingOverlay, children: _jsx("div", { children: status?.message ?? 'Loading...' }) }))] })] }) }), _jsx("div", { className: cn.statusBarSlot, children: status && !godotLoading ? (_jsx("span", { className: status.error ? cn.statusError : cn.statusSuccess, children: status.message })) : null }), showParameters && (_jsxs("div", { className: cn.paramsPanel, children: [_jsx("div", { className: cn.paramsTitle, children: uniforms.length > 0 ? 'Shader parameters' : 'Parameters' }), uniforms.length > 0 ? (uniforms.map((u, i) => (_jsx(ParamRow, { u: u, i: i, samplerState: samplerState, updateUniform: updateUniform, updateSampler: updateSampler, setParameter: setParameter }, u.name)))) : (_jsx("p", { className: cn.paramsPlaceholder, children: "Load a shader with uniform variables to see and edit parameters here." }))] }))] }));
|
|
45
47
|
}
|
|
46
48
|
function ParamRow({ u, i, samplerState, updateUniform, updateSampler, setParameter }) {
|
|
47
49
|
const state = samplerState[u.name] ?? DEFAULT_SAMPLER_STATE;
|
package/dist/style.css
CHANGED
|
@@ -14,19 +14,33 @@
|
|
|
14
14
|
display: flex;
|
|
15
15
|
flex-direction: column;
|
|
16
16
|
min-width: 0;
|
|
17
|
+
max-width: 100%;
|
|
18
|
+
height: 100%;
|
|
19
|
+
max-height: 100%;
|
|
20
|
+
min-height: 0;
|
|
17
21
|
}
|
|
18
22
|
|
|
19
|
-
.rgs-previewWrap {
|
|
23
|
+
.rgs-previewWrap {
|
|
24
|
+
max-width: 100%;
|
|
25
|
+
min-width: 0;
|
|
26
|
+
flex: 1 1 0;
|
|
27
|
+
min-height: 0;
|
|
28
|
+
display: flex;
|
|
29
|
+
align-items: center;
|
|
30
|
+
justify-content: center;
|
|
31
|
+
}
|
|
20
32
|
|
|
21
33
|
.rgs-preview {
|
|
22
|
-
width: 100%;
|
|
23
|
-
padding-bottom: 100%;
|
|
24
|
-
height: 0;
|
|
25
34
|
position: relative;
|
|
26
35
|
overflow: hidden;
|
|
27
36
|
border: 1px solid var(--rgs-b);
|
|
28
37
|
border-radius: 6px;
|
|
29
38
|
background: #000;
|
|
39
|
+
aspect-ratio: 1;
|
|
40
|
+
height: 100%;
|
|
41
|
+
width: auto;
|
|
42
|
+
max-width: 100%;
|
|
43
|
+
max-height: 100%;
|
|
30
44
|
}
|
|
31
45
|
|
|
32
46
|
.rgs-canvas {
|
|
@@ -41,15 +55,28 @@
|
|
|
41
55
|
|
|
42
56
|
.rgs-mouseBlockOverlay { position: absolute; inset: 0; z-index: 5; pointer-events: auto; cursor: default; }
|
|
43
57
|
|
|
44
|
-
/*
|
|
58
|
+
/* Overlay layer: same size as preview so mode strip and loading overlay are positioned correctly */
|
|
59
|
+
.rgs-previewOverlays {
|
|
60
|
+
position: absolute;
|
|
61
|
+
inset: 0;
|
|
62
|
+
z-index: 8;
|
|
63
|
+
pointer-events: none;
|
|
64
|
+
padding: 12px;
|
|
65
|
+
box-sizing: border-box;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.rgs-previewOverlays > * { pointer-events: auto; }
|
|
69
|
+
|
|
70
|
+
/* Mode strip (sphere/plane): positioned inside overlay padding so it never gets clipped */
|
|
45
71
|
.rgs-modeStrip {
|
|
46
72
|
position: absolute;
|
|
47
73
|
bottom: 8px;
|
|
48
74
|
right: 8px;
|
|
75
|
+
left: auto;
|
|
76
|
+
top: auto;
|
|
49
77
|
display: flex;
|
|
50
78
|
gap: 4px;
|
|
51
79
|
z-index: 10;
|
|
52
|
-
pointer-events: auto;
|
|
53
80
|
}
|
|
54
81
|
|
|
55
82
|
.rgs-modeStripButton {
|
|
@@ -81,8 +108,16 @@
|
|
|
81
108
|
z-index: 10;
|
|
82
109
|
}
|
|
83
110
|
|
|
84
|
-
/* Status */
|
|
85
|
-
.rgs-
|
|
111
|
+
/* Status: fixed-height slot so canvas size does not change when status appears */
|
|
112
|
+
.rgs-statusBarSlot {
|
|
113
|
+
flex: 0 0 auto;
|
|
114
|
+
display: flex;
|
|
115
|
+
align-items: center;
|
|
116
|
+
margin-top: 8px;
|
|
117
|
+
min-height: 32px;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.rgs-statusBar { display: flex; align-items: center; min-height: 32px; }
|
|
86
121
|
.rgs-statusSuccess, .rgs-statusError { padding: 8px 12px; border-radius: 4px; font-size: 13px; }
|
|
87
122
|
.rgs-statusSuccess { background: var(--rgs-ok); color: var(--rgs-ok-fg); }
|
|
88
123
|
.rgs-statusError { background: var(--rgs-err); color: var(--rgs-err-fg); }
|
package/godot/embed.html
CHANGED
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
<title>React Godot Shader Preview</title>
|
|
7
7
|
<style>
|
|
8
8
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
9
|
-
html, body { width: 100%; height: 100%; overflow: hidden; background: #000; }
|
|
10
|
-
#godot-canvas { display: block; width: 100%; height: 100%; object-fit:
|
|
9
|
+
html, body { width: 100%; height: 100%; overflow: hidden; background: #000; display: flex; align-items: center; justify-content: center; }
|
|
10
|
+
#godot-canvas { display: block; max-width: 100%; max-height: 100%; width: 100% !important; height: 100% !important; object-fit: contain; cursor: grab;
|
|
11
|
+
/* Override Godot engine inline positioning/sizing so flex centering works */
|
|
12
|
+
position: relative !important; left: auto !important; top: auto !important; min-width: 0 !important; }
|
|
11
13
|
</style>
|
|
12
14
|
</head>
|
|
13
15
|
<body>
|
package/godot/index.html
CHANGED
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
.viewer-preview-wrap { flex: 0 0 320px; max-width: 100%; min-width: 0; }
|
|
47
47
|
.viewer-preview { width: 100%; padding-bottom: 100%; height: 0; position: relative; overflow: hidden; border: 1px solid #444; border-radius: 6px; background: #000; }
|
|
48
48
|
@media (max-width: 700px) { .viewer-row { flex-direction: column; } .viewer-preview-wrap { flex: 0 0 auto; width: 100%; max-width: 400px; } }
|
|
49
|
-
#godot-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; object-fit:
|
|
49
|
+
#godot-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; object-fit: contain; }
|
|
50
50
|
.status { padding: 8px 12px; border-radius: 4px; font-size: 13px; margin-top: 8px; }
|
|
51
51
|
.status.success { background: #1e3a1e; color: #8fef8f; }
|
|
52
52
|
.status.error { background: #3a1e1e; color: #ef8f8f; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-godot-shader-preview",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "React component for live Godot shader preview via WebAssembly. Load shader code, switch mesh (sphere/plane), edit uniforms and samplers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|