diff --git a/README.md b/README.md
index 81d5950..7d4d1ec 100644
--- a/README.md
+++ b/README.md
@@ -22,12 +22,14 @@ Licenses: see [LICENSES](./LICENSE).
## Roadmap
- Add tests!
+- Better names for downloads (matching source)
- Model /home fs in shared state. have two clear paths: /libraries for builtins, and /home for user data. State pointing to /libraries paths needs not store the data except if there's overrides (flagged as modifications in the file picker)
- Setup [OPENSCADPATH](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Libraries#Setting_OPENSCADPATH) env var w/ Emscripten to ensure examples will run fine.
- Bundle some official demos and more examples from each library!
- Ask users to contribute recipes to include more libraries, and cool examples that work in the environment
- Drag and drop of files (SCAD, STL, etc) and Zip archives. For assets, auto insert the corresponding import.
- Proper PWA w/ File opening / association to *.scad files
+- Animation rendering (And other formats than STL)
- Compress URL fragment
- Customizer support. Probably by adding --export-json or --export-format=customizer-json to OpenSCAD.
- Mobile (iOS) editing support: switch to https://www.npmjs.com/package/react-codemirror ?
diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx
index 0fad6a5..f0aa477 100644
--- a/src/components/Footer.tsx
+++ b/src/components/Footer.tsx
@@ -113,7 +113,7 @@ export default function Footer({style}: {style?: CSSProperties}) {
{state.output && (
diff --git a/src/components/ViewerPanel.tsx b/src/components/ViewerPanel.tsx
index e7b75b6..730b6b4 100644
--- a/src/components/ViewerPanel.tsx
+++ b/src/components/ViewerPanel.tsx
@@ -3,6 +3,8 @@
import { CSSProperties, forwardRef, useContext, useEffect, useRef, useState } from 'react';
import { ModelContext } from './contexts';
import { StlViewer} from "react-stl-viewer";
+import { ColorPicker } from 'primereact/colorpicker';
+import { defaultModelColor } from '../state/initial-state';
export default function ViewerPanel({className, style}: {className?: string, style?: CSSProperties}) {
const model = useContext(ModelContext);
@@ -21,8 +23,10 @@ export default function ViewerPanel({className, style}: {className?: string, sty
}}>
{state.output?.stlFileURL &&
- }
+ />}
+
+ model.mutate(s => s.view.color = `#${e.value ?? defaultModelColor}`)} />
+
)
diff --git a/src/state/app-state.ts b/src/state/app-state.ts
index 881733f..31a3157 100644
--- a/src/state/app-state.ts
+++ b/src/state/app-state.ts
@@ -20,7 +20,8 @@ export interface State {
} | ({
mode: 'multi',
} & { [K in MultiLayoutComponentId]: boolean })
-
+
+ color: string,
showAxes?: boolean,
showShadows?: boolean,
}
diff --git a/src/state/fragment-state.ts b/src/state/fragment-state.ts
index fe79b5e..5cef40f 100644
--- a/src/state/fragment-state.ts
+++ b/src/state/fragment-state.ts
@@ -2,6 +2,7 @@
import { State } from "./app-state";
import { validateArray, validateBoolean, validateString, validateStringEnum } from "../utils";
+import { defaultModelColor } from "./initial-state";
export function buildUrlForStateParams(state: State) {//partialState: {params: State['params'], view: State['view']}) {
return `${location.protocol}//${location.host}${location.pathname}#${encodeStateParamsAsFragment(state)}`;
@@ -33,6 +34,7 @@ export function readStateFromFragment(): State | null {
viewer: validateBoolean(view?.layout['viewer']),
customizer: validateBoolean(view?.layout['customizer']),
},
+ color: validateString(view?.color, () => defaultModelColor),
showAxes: validateBoolean(view?.layout?.showAxis),
showShadows: validateBoolean(view?.layout?.showShadow),
}
diff --git a/src/state/initial-state.ts b/src/state/initial-state.ts
index adea794..1567e28 100644
--- a/src/state/initial-state.ts
+++ b/src/state/initial-state.ts
@@ -4,6 +4,7 @@ import defaultScad from './default-scad';
import { State } from './app-state';
export const defaultSourcePath = '/playground.scad';
+export const defaultModelColor = '#f9d72c';
export const blankProjectState: State = {
params: {
@@ -12,6 +13,7 @@ export const blankProjectState: State = {
features: [],
},
view: {
+ color: defaultModelColor,
layout: {
mode: 'single',
focus: 'editor'
@@ -37,7 +39,9 @@ export function createInitialState(fs: any, state: State | null) {
editor: true,
viewer: true,
customizer: false,
- } as any
+ } as any,
+
+ color: defaultModelColor,
},
...(state ?? {})
};
diff --git a/src/state/model.ts b/src/state/model.ts
index 736f56c..47ac76d 100644
--- a/src/state/model.ts
+++ b/src/state/model.ts
@@ -51,6 +51,14 @@ export class Model {
this.mutate(s => s.view.logs = value);
}
+ isComponentFullyVisible(id: SingleLayoutComponentId) {
+ if (this.state.view.layout.mode === 'multi') {
+ return this.state.view.layout[id];
+ } else {
+ return this.state.view.layout.focus === id;
+ }
+ }
+
changeLayout(mode: 'multi' | 'single') {
if (this.state.view.layout.mode === mode) return;
this.mutate(s => {
diff --git a/src/utils.ts b/src/utils.ts
index 0c45b87..9ec4cd4 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -83,7 +83,7 @@ export function formatBytes(n: number) {
export function formatMillis(n: number) {
if (n < 1000)
- return `${Math.floor(n)} millis`;
+ return `${Math.floor(n)}ms`;
- return `${Math.floor(n / 100) / 10} sec`;
+ return `${Math.floor(n / 100) / 10}sec`;
}
\ No newline at end of file