feat: implement settings
This commit is contained in:
@ -78,7 +78,7 @@ export interface RuntimeExecutor {
|
||||
* @param graph - The graph to execute
|
||||
* @returns The result of the execution
|
||||
*/
|
||||
execute: (graph: Graph) => unknown;
|
||||
execute: (graph: Graph, settings: Record<string, unknown>) => unknown;
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,7 +22,7 @@ type NodeInputBoolean = {
|
||||
|
||||
type NodeInputSelect = {
|
||||
type: "select";
|
||||
labels: string[];
|
||||
options: string[];
|
||||
value?: number;
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ pub struct NodeInputBoolean {
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct NodeInputSelect {
|
||||
pub labels: Vec<String>,
|
||||
pub options: Vec<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub value: Option<usize>,
|
||||
}
|
||||
@ -130,4 +130,3 @@ pub struct NodeType {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub outputs: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
|
@ -12,11 +12,11 @@
|
||||
</script>
|
||||
|
||||
{#if input.type === "float"}
|
||||
<Float {id} bind:value />
|
||||
<Float {id} bind:value min={input?.min} max={input?.max} />
|
||||
{:else if input.type === "integer"}
|
||||
<Integer {id} bind:value />
|
||||
<Integer {id} bind:value min={input?.min} max={input?.max} />
|
||||
{:else if input.type === "boolean"}
|
||||
<Checkbox {id} bind:value />
|
||||
{:else if input.type === "select"}
|
||||
<Select {id} bind:value labels={input.labels} />
|
||||
<Select {id} bind:value options={input.options} />
|
||||
{/if}
|
||||
|
@ -49,6 +49,8 @@ body {
|
||||
--background-color-darker: #101010;
|
||||
--text-color: #aeaeae;
|
||||
|
||||
color: var(--text-color);
|
||||
|
||||
background-color: var(--background-color-darker);
|
||||
}
|
||||
|
||||
|
@ -1,60 +1,13 @@
|
||||
<script lang="ts">
|
||||
export let value: boolean;
|
||||
|
||||
$: if (typeof value === "string") {
|
||||
value = value === "true";
|
||||
} else if (typeof value === "number") {
|
||||
value = value === 1;
|
||||
}
|
||||
|
||||
export let id: string;
|
||||
</script>
|
||||
|
||||
<input {id} type="checkbox" bind:checked={value} />
|
||||
|
||||
<style>
|
||||
input[type="checkbox"] {
|
||||
/* Add if not using autoprefixer */
|
||||
-webkit-appearance: none;
|
||||
/* Remove most all native input styles */
|
||||
appearance: none;
|
||||
/* For iOS < 15 */
|
||||
background-color: var(--form-background);
|
||||
/* Not removed via appearance */
|
||||
margin: 0;
|
||||
|
||||
font: inherit;
|
||||
color: currentColor;
|
||||
width: 1.15em;
|
||||
height: 1.15em;
|
||||
border: 0.15em solid currentColor;
|
||||
border-radius: 0.15em;
|
||||
transform: translateY(-0.075em);
|
||||
|
||||
display: grid;
|
||||
place-content: center;
|
||||
}
|
||||
|
||||
input[type="checkbox"]::before {
|
||||
content: "";
|
||||
width: 0.65em;
|
||||
height: 0.65em;
|
||||
clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
|
||||
transform: scale(0);
|
||||
transform-origin: bottom left;
|
||||
transition: 120ms transform ease-in-out;
|
||||
box-shadow: inset 1em 1em var(--form-control-color);
|
||||
/* Windows High Contrast Mode */
|
||||
background-color: CanvasText;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked::before {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:focus {
|
||||
outline: max(2px, 0.15em) solid currentColor;
|
||||
outline-offset: max(2px, 0.15em);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:disabled {
|
||||
--form-control-color: var(--form-control-disabled);
|
||||
|
||||
color: var(--form-control-disabled);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,20 +1,169 @@
|
||||
<svelte:options accessors />
|
||||
|
||||
<script lang="ts">
|
||||
export let value: number = 0;
|
||||
export let min = 0;
|
||||
export let max = 10;
|
||||
import { createEventDispatcher } from "svelte";
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
// Styling
|
||||
export let min: number | undefined = undefined;
|
||||
export let max: number | undefined = undefined;
|
||||
export let step = 1;
|
||||
export let id: string;
|
||||
export let value = 0;
|
||||
|
||||
if (!value) {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
let inputEl: HTMLInputElement;
|
||||
let wrapper: HTMLDivElement;
|
||||
$: value !== undefined && update();
|
||||
|
||||
let prev = -1;
|
||||
function update() {
|
||||
if (prev === value) return;
|
||||
prev = value;
|
||||
dispatch("change", parseFloat(value + ""));
|
||||
}
|
||||
|
||||
$: width = Number.isFinite(value)
|
||||
? Math.max((value?.toString().length ?? 1) * 8, 30) + "px"
|
||||
: "20px";
|
||||
|
||||
function handleChange(change: number) {
|
||||
value = Math.max(
|
||||
min ?? -Infinity,
|
||||
Math.min(+value + change, max ?? Infinity),
|
||||
);
|
||||
}
|
||||
|
||||
let downX = 0;
|
||||
let downV = 0;
|
||||
let rect: DOMRect;
|
||||
|
||||
function handleMouseDown(ev: MouseEvent) {
|
||||
ev.preventDefault();
|
||||
|
||||
downV = value;
|
||||
downX = ev.clientX;
|
||||
rect = wrapper.getBoundingClientRect();
|
||||
|
||||
window.removeEventListener("mousemove", handleMouseMove);
|
||||
window.addEventListener("mousemove", handleMouseMove);
|
||||
window.addEventListener("mouseup", handleMouseUp);
|
||||
document.body.style.cursor = "ew-resize";
|
||||
}
|
||||
|
||||
function handleMouseUp() {
|
||||
if (downV === value) {
|
||||
inputEl.focus();
|
||||
} else {
|
||||
inputEl.blur();
|
||||
}
|
||||
|
||||
document.body.style.cursor = "unset";
|
||||
window.removeEventListener("mouseup", handleMouseUp);
|
||||
window.removeEventListener("mousemove", handleMouseMove);
|
||||
}
|
||||
|
||||
function handleMouseMove(ev: MouseEvent) {
|
||||
if (!ev.ctrlKey && typeof min === "number" && typeof max === "number") {
|
||||
const vx = (ev.clientX - rect.left) / rect.width;
|
||||
value = Math.max(Math.min(Math.floor(min + (max - min) * vx), max), min);
|
||||
} else {
|
||||
const vx = ev.clientX - downX;
|
||||
value = downV + Math.floor(vx / 10);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<input {id} type="number" bind:value {min} {max} {step} />
|
||||
<div
|
||||
class="component-wrapper"
|
||||
bind:this={wrapper}
|
||||
role="slider"
|
||||
tabindex="0"
|
||||
aria-valuenow={value}
|
||||
on:mousedown={handleMouseDown}
|
||||
on:mouseup={handleMouseUp}
|
||||
>
|
||||
{#if typeof min !== "undefined" && typeof max !== "undefined"}
|
||||
<span
|
||||
class="overlay"
|
||||
style={`width: ${Math.min((value - min) / (max - min), 1) * 100}%`}
|
||||
/>
|
||||
{/if}
|
||||
<button on:click={() => handleChange(-step)}>-</button>
|
||||
<input
|
||||
bind:value
|
||||
bind:this={inputEl}
|
||||
{step}
|
||||
{max}
|
||||
{min}
|
||||
type="number"
|
||||
style={`width:${width};`}
|
||||
/>
|
||||
|
||||
<button on:click={() => handleChange(+step)}>+</button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
input {
|
||||
background: var(--background-color-lighter);
|
||||
color: var(--text-color);
|
||||
.component-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
background-color: var(--background-color-lighter, #4b4b4b);
|
||||
border-radius: 2px;
|
||||
user-select: none;
|
||||
transition: box-shadow 0.3s ease;
|
||||
box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.2);
|
||||
outline: none !important;
|
||||
overflow: hidden;
|
||||
border-radius: var(--border-radius, 2px);
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
-webkit-appearance: textfield;
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
cursor: pointer;
|
||||
font-size: 1em;
|
||||
font-family: var(--font-family);
|
||||
padding: 0.8em 1em;
|
||||
border-radius: 5px;
|
||||
padding-top: 8px;
|
||||
flex: 1;
|
||||
width: 72%;
|
||||
}
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
height: 100%;
|
||||
background-color: var(--text-color);
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
line-height: 0px;
|
||||
margin: 0;
|
||||
color: var(--text-color);
|
||||
margin-inline: 6px;
|
||||
}
|
||||
|
||||
div input[type="number"] {
|
||||
color: var(--text-color);
|
||||
background-color: transparent;
|
||||
padding: var(--padding, 6px);
|
||||
padding-inline: 0px;
|
||||
text-align: center;
|
||||
border: none;
|
||||
border-style: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
export let labels: string[] = [];
|
||||
export let options: string[] = [];
|
||||
export let value: number = 0;
|
||||
export let id: string;
|
||||
</script>
|
||||
|
||||
<select {id} bind:value>
|
||||
{#each labels as label, i}
|
||||
{#each options as label, i}
|
||||
<option value={i}>{label}</option>
|
||||
{/each}
|
||||
</select>
|
||||
|
@ -1,3 +1,5 @@
|
||||
use crate::log;
|
||||
|
||||
use super::{create_geometry_data, wrap_geometry_data};
|
||||
use glam::{Mat4, Quat, Vec3};
|
||||
|
||||
@ -65,9 +67,11 @@ pub fn extrude_path(input_path: &[i32], res_x: usize) -> Vec<i32> {
|
||||
let i_index_offset = index_offset + j * 6;
|
||||
let i_position_offset = position_offset + j;
|
||||
|
||||
log!("i: {}, j: {}, i_index_offset: {}, i_position_offset: {} res_x: {}", i, j, i_index_offset, i_position_offset,res_x);
|
||||
|
||||
if j == res_x - 1 {
|
||||
indices[i_index_offset ] = (i_position_offset + 1) as i32;
|
||||
indices[i_index_offset + 1] = (i_position_offset - res_x + 1) as i32;
|
||||
indices[i_index_offset + 1] = (i_position_offset + 1 - res_x) as i32;
|
||||
indices[i_index_offset + 2] = (i_position_offset) as i32;
|
||||
indices[i_index_offset + 3] = (i_position_offset) as i32;
|
||||
indices[i_index_offset + 4] = (i_position_offset + res_x) as i32;
|
||||
|
@ -7,6 +7,7 @@ pub use helpers::*;
|
||||
pub use tree::*;
|
||||
pub mod geometry;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
#[macro_export]
|
||||
macro_rules! log {
|
||||
($($arg:tt)*) => {{
|
||||
@ -15,6 +16,14 @@ macro_rules! log {
|
||||
}}
|
||||
}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[macro_export]
|
||||
macro_rules! log {
|
||||
($($arg:tt)*) => {{
|
||||
// This will expand to nothing in release builds
|
||||
}};
|
||||
}
|
||||
|
||||
pub fn set_panic_hook() {
|
||||
// When the `console_error_panic_hook` feature is enabled, we can call the
|
||||
// `set_panic_hook` function at least once during initialization, and then
|
||||
|
Reference in New Issue
Block a user