-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
πβοΈ β Modifying a 3js package for generating worlds on the client
We've got some 3d planets being rendered in javascript, these are based on the initial C# algorithms in Signal-K/starsailors#4, Signal-K/starsailors-boilerplate#1 We've got some plans to generate nfts from this: Signal-K/sytizen#18. The models here are based on the C# model, we'll have an API call setup later so that they're both equivalent to each other directly. Next step is setting up some image exports and saving user data, providing a way for users to export the 3JS graphic to their Supabase storage row. That will be commenced later on tonight. All the fields will be set to be callable via an API & we will compare the output of different Deepnote graphs generated from `lightkurve` to provide further adjustments to either end. One issue is that on the frontend for the generator, some of the components aren't selectable. This is because the original example components were built for a much older version of React>Next. Since these will be callable via a custom API, and the editor will be changed to be a form, that won't be an issue. Docs available at the central issues on signal-k org Signal-K/marketplace#19 Signal-K/marketplace#3 Signal-K/marketplace#7 Signal-K/Silfur#26 -> These will be added to posts on the image/comment sharing part of the site (and later on Lens -> team members can refer to the roadmap) so that will be routed internally.
- Loading branch information
1 parent
36527c8
commit a7e0a3b
Showing
35 changed files
with
2,727 additions
and
129 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { useState, useEffect } from 'react'; | ||
|
||
import Row from 'react-bootstrap/Row'; | ||
import Col from 'react-bootstrap/Col'; | ||
import Form from 'react-bootstrap/Form'; | ||
import Tabs from 'react-bootstrap/Tabs'; | ||
import Tab from 'react-bootstrap/Tabs'; | ||
|
||
import LayerPanel from './panels/LayerPanel'; | ||
import InfoPanel from './panels/InfoPanel'; | ||
|
||
import { useStatePersisted } from '../hooks/use-state-persisted'; | ||
import { PlanetEditorState } from '../hooks/use-planet-editor-state'; | ||
import GraphicsPanel from './panels/GraphicsPanel'; | ||
|
||
const tabClasses = 'border-left border-right border-bottom'; | ||
const tabStyles = { | ||
paddingTop: '10px', | ||
paddingLeft: '6px', | ||
paddingRight: '6px' | ||
}; | ||
|
||
export default function Controls ({ planetState }: { planetState: PlanetEditorState }) { | ||
const [tab, setTab] = useStatePersisted('world-gen:active-tab', 'planet-info-tab'); | ||
console.log(tab); | ||
|
||
return ( | ||
<> | ||
<Row> | ||
<Col> | ||
<Form autoComplete='off' data-lpignore="true"> | ||
<Tabs id='control-tabs' activeKey={tab} onSelect={setTab} className='nav-fill' transition={false}> | ||
<Tab id='planet-info-tab' eventKey='planet-info-tab' title='Info' className={tabClasses} style={tabStyles} tabIndex="-1" > | ||
<InfoPanel {...{ planetState }} /> | ||
</Tab> | ||
<Tab id='layers-tab' eventKey='layers-tab' title='Layers' className={tabClasses} style={{ ...tabStyles, paddingTop: 0, paddingLeft: 0, paddingRight: 0 }} tabIndex="-1"> | ||
<LayerPanel {...{ planetState }} /> | ||
</Tab> | ||
<Tab id='graphics-tab' eventKey='graphics-tab' title='Graphics' className={tabClasses} style={tabStyles} tabIndex="-1"> | ||
<GraphicsPanel {...{ planetState }} /> | ||
</Tab> | ||
</Tabs> | ||
</Form> | ||
</Col> | ||
</Row> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
import Row from 'react-bootstrap/Row'; | ||
import Col from 'react-bootstrap/Col'; | ||
import Form from 'react-bootstrap/Form'; | ||
import Button from 'react-bootstrap/Button'; | ||
import Octicon, { Sync } from '@primer/octicons-react'; | ||
import InputGroup from 'react-bootstrap/InputGroup'; | ||
import Tooltip from 'rc-tooltip'; | ||
import Slider from 'rc-slider'; | ||
import { Vector2, Vector3 } from 'three'; | ||
|
||
|
||
import { randomSeed } from '../services/helpers'; | ||
import { SliderPicker as ColorSlider } from 'react-color'; | ||
|
||
const sliderStyle = { | ||
height: '24px' | ||
}; | ||
|
||
export function TextBox(props: { label: string, value: string, onChange: (value: string) => void }) { | ||
return ( | ||
<Form.Group as={Col}> | ||
<Form.Label><strong>{props.label}:</strong> {props.value + ''}</Form.Label> | ||
<Form.Control type="text" value={props.value + ''} onChange={handleChange} /> | ||
</Form.Group> | ||
); | ||
|
||
function handleChange(e: any) { | ||
props.onChange && props.onChange(e.target.value); | ||
} | ||
} | ||
|
||
export function SeedInput(props: { label?: string, value: string, onChange: (value: string) => void }) { | ||
return ( | ||
<Form.Group as={Col}> | ||
<Form.Label><strong>{props.label || 'Seed'}:</strong></Form.Label> | ||
<InputGroup> | ||
<Form.Control type="input" value={props.value + ''} onChange={handleChange} /> | ||
<InputGroup.Append> | ||
<Button variant="outline-secondary" title='Randomize' onClick={handleRandomization}> | ||
<Octicon icon={Sync} /> | ||
</Button> | ||
</InputGroup.Append> | ||
</InputGroup> | ||
</Form.Group> | ||
); | ||
|
||
function handleRandomization() { | ||
props.onChange && props.onChange(randomSeed()); | ||
} | ||
|
||
function handleChange(e: any) { | ||
props.onChange && props.onChange(e.target.value); | ||
} | ||
} | ||
|
||
export function ColorPicker(props: { label: string, value: string, onChange: (value: string) => void }) { | ||
|
||
return ( | ||
<Form.Group as={Col}> | ||
<Form.Label>{props.label}: {props.value}</Form.Label> | ||
<ColorSlider color={props.value} onChangeComplete={handleChange} /> | ||
</Form.Group> | ||
); | ||
|
||
function handleChange(e: any) { | ||
props.onChange && props.onChange(e.hex.toUpperCase()); | ||
} | ||
} | ||
|
||
export function NumberSlider(props: { label: string, min: number, max: number, step: number, value: number, onChange: (value: number) => void }) { | ||
return ( | ||
<Form.Group as={Col}> | ||
<Form.Label><strong>{props.label}:</strong> {props.value}</Form.Label> | ||
<Slider min={props.min} max={props.max} defaultValue={props.value} step={props.step} onChange={props.onChange} /> | ||
</Form.Group> | ||
); | ||
} | ||
|
||
const VECTOR_LABEL_WIDTH = 3; | ||
export function Vector2Slider({ label, min, max, step, value, onChange }: { label: string, min: Vector2 | number, max: Vector2 | number, step?: Vector2 | number, value: Vector2, onChange: (value: Vector2) => void }) { | ||
step = typeof step === 'undefined' ? 1 : step; | ||
|
||
let vectorMin = typeof min === 'number' ? new Vector2(min, min) : min; | ||
let vectorMax = typeof max === 'number' ? new Vector2(max, max) : max; | ||
let vectorStep = typeof step === 'number' ? new Vector2(step, step) : step; | ||
|
||
return (<Form.Group as={Col}> | ||
<Form.Label className='font-weight-bold mb-0'>{label}:</Form.Label> | ||
<Row> | ||
<Col xs={VECTOR_LABEL_WIDTH}><strong>X:</strong> {value.x}</Col> | ||
<Col className='pl-0'> | ||
<Slider min={vectorMin.x} max={vectorMax.x} defaultValue={value.x} step={vectorStep.x} onChange={handleChange('x')} /> | ||
</Col> | ||
</Row> | ||
<Row> | ||
<Col xs={VECTOR_LABEL_WIDTH}><strong>Y:</strong> {value.y}</Col> | ||
<Col className='pl-0'> | ||
<Slider min={vectorMin.y} max={vectorMax.y} defaultValue={value.y} step={vectorStep.y} onChange={handleChange('y')} /> | ||
</Col> | ||
</Row> | ||
</Form.Group>); | ||
|
||
function handleChange(part: 'x' | 'y') { | ||
return (newValue: number) => { | ||
if (onChange) { | ||
if (part === 'x') { | ||
onChange(new Vector2(newValue, value.y)); | ||
} else { | ||
onChange(new Vector2(value.x, newValue)); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
export function Vector3Slider({ label, min, max, step, value, onChange }: { label: string, min: Vector3 | number, max: Vector3 | number, step?: Vector3 | number, value: Vector3, onChange: (value: Vector3) => void }) { | ||
step = typeof step === 'undefined' ? 1 : step; | ||
|
||
let vectorMin = typeof min === 'number' ? new Vector3(min, min, min) : min; | ||
let vectorMax = typeof max === 'number' ? new Vector3(max, max, max) : max; | ||
let vectorStep = typeof step === 'number' ? new Vector3(step, step, step) : step; | ||
|
||
return (<Form.Group as={Col}> | ||
<Form.Label className='font-weight-bold mb-0'>{label}:</Form.Label> | ||
<Row> | ||
<Col xs={VECTOR_LABEL_WIDTH}><strong>X:</strong> {value.x}</Col> | ||
<Col className='pl-0'> | ||
<Slider min={vectorMin.x} max={vectorMax.x} defaultValue={value.x} step={vectorStep.x} onChange={handleChange('x')} /> | ||
</Col> | ||
</Row> | ||
<Row> | ||
<Col xs={VECTOR_LABEL_WIDTH}><strong>Y:</strong> {value.y}</Col> | ||
<Col className='pl-0'> | ||
<Slider min={vectorMin.y} max={vectorMax.y} defaultValue={value.y} step={vectorStep.y} onChange={handleChange('y')} /> | ||
</Col> | ||
</Row> | ||
<Row> | ||
<Col xs={VECTOR_LABEL_WIDTH}><strong>Z:</strong> {value.z}</Col> | ||
<Col className='pl-0'> | ||
<Slider min={vectorMin.z} max={vectorMax.z} defaultValue={value.z} step={vectorStep.z} onChange={handleChange('z')} /> | ||
</Col> | ||
</Row> | ||
</Form.Group>); | ||
|
||
function handleChange(part: 'x' | 'y' | 'z') { | ||
return (newValue: number) => { | ||
if (onChange) { | ||
switch (part) { | ||
case 'x': | ||
onChange(new Vector3(newValue, value.y, value.z)); | ||
break; | ||
case 'y': | ||
onChange(new Vector3(value.x, newValue, value.z)); | ||
break; | ||
case 'z': | ||
onChange(new Vector3(value.x, value.y, newValue)); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
export function CheckboxInput(props: { label: string, value: boolean, onChange: (value: boolean) => void }) { | ||
|
||
return ( | ||
<Form.Group as={Col}> | ||
<Form.Check type='checkbox' label={props.label} checked={props.value} onChange={handleChange} /> | ||
</Form.Group> | ||
); | ||
|
||
function handleChange(e: any) { | ||
props.onChange && props.onChange(e.target.checked); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
|
||
export default function GitHubCorner() { | ||
return ( | ||
<> | ||
<a href="https://github.com/signal-k" target="_blank" className="github-corner" aria-label="View source on GitHub"> | ||
<svg width="80" height="80" viewBox="0 0 250 250" | ||
style={{position: 'absolute',top: 0, border: 0, right: 0, fill: '#151513', color: '#fff', zIndex: 999}} aria-hidden="true"> | ||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path> | ||
<path | ||
d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" | ||
fill="currentColor" style={{transformOrigin: '130px 106px'}} className="octo-arm"></path> | ||
<path | ||
d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" | ||
fill="currentColor" className="octo-body"></path> | ||
</svg> | ||
</a> | ||
<style jsx>{` | ||
.github-corner:hover .octo-arm { | ||
animation: octocat-wave 560ms ease-in-out | ||
} | ||
@keyframes octocat-wave { | ||
0%, | ||
100% { | ||
transform: rotate(0) | ||
} | ||
20%, | ||
60% { | ||
transform: rotate(-25deg) | ||
} | ||
40%, | ||
80% { | ||
transform: rotate(10deg) | ||
} | ||
} | ||
@media (max-width:500px) { | ||
.github-corner:hover .octo-arm { | ||
animation: none | ||
} | ||
.github-corner .octo-arm { | ||
animation: octocat-wave 560ms ease-in-out | ||
} | ||
} | ||
`}</style> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import Head from "next/head"; | ||
import Container from 'react-bootstrap/Container'; | ||
import GithubCorner from './GithubCorner'; | ||
|
||
export default function Layout(props: {children: any[]}) { | ||
return <> | ||
<Head><title>World Generation</title></Head> | ||
<GithubCorner /> | ||
<Container fluid> | ||
{props.children} | ||
</Container> | ||
</>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
|
||
import { useLayoutEffect, useRef } from 'react'; | ||
import SceneManager from '../services/base-scene-manager'; | ||
|
||
export default function SceneDisplay ({sceneManager}: {sceneManager: SceneManager}) { | ||
const canvasRef = useRef<HTMLCanvasElement>(null); | ||
|
||
if (process.browser) { | ||
useLayoutEffect(() => { | ||
console.log('Starting scene...'); | ||
sceneManager.init(canvasRef.current); | ||
sceneManager.start(); | ||
|
||
return () => { | ||
console.log('Stopping scene...'); | ||
sceneManager.stop(); | ||
}; | ||
}, []); | ||
} | ||
|
||
return <canvas ref={canvasRef} style={{ width: '100%' }} /> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import Link from "next/link"; | ||
import Row from "react-bootstrap/Row"; | ||
import Col from "react-bootstrap/Col"; | ||
import Layout from "./Layout"; | ||
|
||
export default function SubPage ({ header, children }: {header: string, children: any }) { | ||
return ( | ||
<Layout> | ||
<Row> | ||
<Col><h1 className="display-4">Hello {header}</h1></Col> | ||
</Row> | ||
{children} | ||
</Layout> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { CheckboxInput, NumberSlider } from "../FieldEditors"; | ||
import { PlanetEditorState } from "../../hooks/use-planet-editor-state"; | ||
|
||
export default function GraphicsPanel({ planetState }: { planetState: PlanetEditorState }) { | ||
return ( | ||
<> | ||
<NumberSlider label='Resolution' min={2} max={128} step={1} value={planetState.resolution.current} onChange={planetState.resolution.set} /> | ||
<NumberSlider label='Rotate' min={0} max={2} step={0.01} value={planetState.rotate.current} onChange={planetState.rotate.set} /> | ||
<CheckboxInput label='Wireframes' value={planetState.wireframes.current} onChange={planetState.wireframes.set} /> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { PlanetEditorState } from "../../hooks/use-planet-editor-state"; | ||
import { NumberSlider, TextBox, SeedInput, ColorPicker } from "../FieldEditors"; | ||
import Form from "react-bootstrap/Form"; | ||
import Col from 'react-bootstrap/Col'; | ||
|
||
export default function InfoPanel({ planetState }: { planetState: PlanetEditorState }) { | ||
return ( | ||
<> | ||
<Form.Row> | ||
<Form.Group as={Col}> | ||
<TextBox label='Name' value={planetState.name.current} onChange={planetState.name.set} /> | ||
</Form.Group> | ||
<Form.Group as={Col}> | ||
<SeedInput label='Seed' value={planetState.seed.current} onChange={planetState.seed.set} /> | ||
</Form.Group> | ||
</Form.Row> | ||
<Form.Row> | ||
<Form.Group as={Col}> | ||
<NumberSlider label='Radius' min={0.25} max={16} step={0.05} value={planetState.radius.current} onChange={planetState.radius.set} /> | ||
</Form.Group> | ||
</Form.Row> | ||
<Form.Row> | ||
<Form.Group as={Col}> | ||
<NumberSlider label='Sea Level' min={0} max={2} step={0.05} value={planetState.seaLevel.current} onChange={planetState.seaLevel.set} /> | ||
</Form.Group> | ||
</Form.Row> | ||
|
||
|
||
|
||
{/* <ColorPicker label='Color' value={planetState.colors.current} onChange={planetState.colors.set} /> */} | ||
</> | ||
); | ||
} |
Oops, something went wrong.