Compare commits

...

No commits in common. "gh-pages" and "master" have entirely different histories.

164 changed files with 31418 additions and 769 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
node_modules/
dist/*bundle.js*
dist/app.css
stats.json
demo_parts/*.json

View File

@ -1 +0,0 @@
(self.webpackChunk=self.webpackChunk||[]).push([[245],{245:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>i});const a=async(e,t,r=e.name)=>{const i=[],s=[];for await(const n of e.values()){const e=`${r}/${n.name}`;"file"===n.kind?s.push(n.getFile().then((t=>Object.defineProperty(t,"webkitRelativePath",{configurable:!0,enumerable:!0,get:()=>e})))):"directory"===n.kind&&t&&i.push(a(n,t,e))}return[...(await Promise.all(i)).flat(),...await Promise.all(s)]},i=async(e={})=>{e.recursive=e.recursive||!1;const t=await window.showDirectoryPicker();return a(t,e.recursive)}}}]);

View File

@ -1 +0,0 @@
(self.webpackChunk=self.webpackChunk||[]).push([[448],{800:(e,t,i)=>{"use strict";i.r(t),i.d(t,{default:()=>a});const a=async(e,t={},i=null,a=!1)=>{t.fileName=t.fileName||"Untitled";const s={};if(t.mimeTypes?(t.mimeTypes.push(e.type),t.mimeTypes.map((e=>{s[e]=t.extensions||[]}))):s[e.type]=t.extensions||[],i)try{await i.getFile()}catch(e){if(i=null,a)throw e}const n=i||await window.showSaveFilePicker({suggestedName:t.fileName,types:[{description:t.description||"",accept:s}]}),c=await n.createWritable();return await c.write(e),await c.close(),n}}}]);

View File

@ -1 +0,0 @@
(self.webpackChunk=self.webpackChunk||[]).push([[605],{605:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>r});const r=async(e={})=>(e.recursive=e.recursive||!1,new Promise(((n,t)=>{const r=document.createElement("input");r.type="file",r.webkitdirectory=!0;const i=()=>{window.removeEventListener("pointermove",i),window.removeEventListener("pointerdown",i),window.removeEventListener("keydown",i),t(new DOMException("The user aborted a request.","AbortError"))};window.addEventListener("pointermove",i),window.addEventListener("pointerdown",i),window.addEventListener("keydown",i),r.addEventListener("change",(()=>{window.removeEventListener("pointermove",i),window.removeEventListener("pointerdown",i),window.removeEventListener("keydown",i);let t=Array.from(r.files);e.recursive||(t=t.filter((e=>2===e.webkitRelativePath.split("/").length))),n(t)})),r.click()})))}}]);

View File

@ -1 +0,0 @@
(self.webpackChunk=self.webpackChunk||[]).push([[725],{725:(e,t,i)=>{"use strict";i.r(t),i.d(t,{default:()=>s});const s=async(e,t={},i=null)=>{t.fileName=t.fileName||"Untitled",i=i||await window.chooseFileSystemEntries({type:"save-file",accepts:[{description:t.description||"",mimeTypes:[e.type],extensions:t.extensions||[""]}]});const s=await i.createWritable();return await s.write(e),await s.close(),i}}}]);

View File

@ -1 +0,0 @@
(self.webpackChunk=self.webpackChunk||[]).push([[768],{768:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>o});const o=async(e={})=>new Promise(((n,t)=>{const o=document.createElement("input");o.type="file";const i=[...e.mimeTypes?e.mimeTypes:[],e.extensions?e.extensions:[]].join();o.multiple=e.multiple||!1,o.accept=i||"";const r=()=>{window.removeEventListener("pointermove",r),window.removeEventListener("pointerdown",r),window.removeEventListener("keydown",r),t(new DOMException("The user aborted a request.","AbortError"))};window.addEventListener("pointermove",r),window.addEventListener("pointerdown",r),window.addEventListener("keydown",r),o.addEventListener("change",(()=>{window.removeEventListener("pointermove",r),window.removeEventListener("pointerdown",r),window.removeEventListener("keydown",r),n(o.multiple?o.files:o.files[0])})),o.click()}))}}]);

View File

@ -1 +0,0 @@
(self.webpackChunk=self.webpackChunk||[]).push([[847],{847:(e,s,t)=>{"use strict";t.r(s),t.d(s,{default:()=>n});const i=async e=>{const s=await e.getFile();return s.handle=e,s},n=async(e={})=>{const s={};e.mimeTypes?e.mimeTypes.map((t=>{s[t]=e.extensions||[]})):s["*/*"]=e.extensions||[];const t=await window.showOpenFilePicker({types:[{description:e.description||"",accept:s}],multiple:e.multiple||!1}),n=await Promise.all(t.map(i));return e.multiple?n:n[0]}}}]);

View File

@ -1 +0,0 @@
(self.webpackChunk=self.webpackChunk||[]).push([[94],{94:(e,t,c)=>{"use strict";c.r(t),c.d(t,{default:()=>n});const n=async(e,t={})=>{const c=document.createElement("a");c.download=t.fileName||"Untitled",c.href=URL.createObjectURL(e),c.addEventListener("click",(()=>{setTimeout((()=>URL.revokeObjectURL(c.href)),3e4)})),c.click()}}}]);

View File

@ -1 +0,0 @@
(self.webpackChunk=self.webpackChunk||[]).push([[945],{945:(e,s,t)=>{"use strict";t.r(s),t.d(s,{default:()=>n});const i=async e=>{const s=await e.getFile();return s.handle=e,s},n=async(e={})=>{const s=await window.chooseFileSystemEntries({accepts:[{description:e.description||"",mimeTypes:e.mimeTypes||["*/*"],extensions:e.extensions||[""]}],multiple:e.multiple||!1});return e.multiple?Promise.all(s.map(i)):i(s)}}}]);

View File

@ -1 +0,0 @@
(self.webpackChunk=self.webpackChunk||[]).push([[965],{965:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>i});const s=async(e,t,r=e.name)=>{const i=[],a=[];for await(const n of e.getEntries()){const e=`${r}/${n.name}`;n.isFile?a.push(n.getFile().then((t=>Object.defineProperty(t,"webkitRelativePath",{configurable:!0,enumerable:!0,get:()=>e})))):n.isDirectory&&t&&i.push(s(n,t,e))}return[...(await Promise.all(i)).flat(),...await Promise.all(a)]},i=async(e={})=>{e.recursive=e.recursive||!1;const t=await window.chooseFileSystemEntries({type:"open-directory"});return s(t,e.recursive)}}}]);

File diff suppressed because one or more lines are too long

741
app.css
View File

@ -1,741 +0,0 @@
.bg-transparent {
background-color: transparent;
}
.bg-gray-50 {
--tw-bg-opacity: 1;
background-color: rgba(250, 250, 250, var(--tw-bg-opacity));
}
.bg-gray-100 {
--tw-bg-opacity: 1;
background-color: rgba(245, 245, 245, var(--tw-bg-opacity));
}
.bg-gray-200 {
--tw-bg-opacity: 1;
background-color: rgba(229, 229, 229, var(--tw-bg-opacity));
}
.bg-gray-500 {
--tw-bg-opacity: 1;
background-color: rgba(115, 115, 115, var(--tw-bg-opacity));
}
.bg-gray-600 {
--tw-bg-opacity: 1;
background-color: rgba(82, 82, 82, var(--tw-bg-opacity));
}
.bg-gray-700 {
--tw-bg-opacity: 1;
background-color: rgba(64, 64, 64, var(--tw-bg-opacity));
}
.bg-gray-800 {
--tw-bg-opacity: 1;
background-color: rgba(38, 38, 38, var(--tw-bg-opacity));
}
.bg-green-400 {
--tw-bg-opacity: 1;
background-color: rgba(52, 211, 153, var(--tw-bg-opacity));
}
.bg-green-500 {
--tw-bg-opacity: 1;
background-color: rgba(16, 185, 129, var(--tw-bg-opacity));
}
.hover\:bg-gray-400:hover {
--tw-bg-opacity: 1;
background-color: rgba(163, 163, 163, var(--tw-bg-opacity));
}
.hover\:bg-gray-600:hover {
--tw-bg-opacity: 1;
background-color: rgba(82, 82, 82, var(--tw-bg-opacity));
}
.hover\:bg-green-600:hover {
--tw-bg-opacity: 1;
background-color: rgba(5, 150, 105, var(--tw-bg-opacity));
}
.border-gray-50 {
--tw-border-opacity: 1;
border-color: rgba(250, 250, 250, var(--tw-border-opacity));
}
.border-gray-300 {
--tw-border-opacity: 1;
border-color: rgba(212, 212, 212, var(--tw-border-opacity));
}
.border-gray-500 {
--tw-border-opacity: 1;
border-color: rgba(115, 115, 115, var(--tw-border-opacity));
}
.rounded {
border-radius: 0.25rem;
}
.rounded-lg {
border-radius: 0.5rem;
}
.rounded-xl {
border-radius: 0.75rem;
}
.rounded-full {
border-radius: 9999px;
}
.rounded-t-xl {
border-top-left-radius: 0.75rem;
border-top-right-radius: 0.75rem;
}
.border-0 {
border-width: 0px;
}
.border-2 {
border-width: 2px;
}
.border {
border-width: 1px;
}
.border-t-0 {
border-top-width: 0px;
}
.border-r-0 {
border-right-width: 0px;
}
.border-l-0 {
border-left-width: 0px;
}
.border-r-2 {
border-right-width: 2px;
}
.border-b {
border-bottom-width: 1px;
}
.cursor-pointer {
cursor: pointer;
}
.inline-block {
display: inline-block;
}
.flex {
display: flex;
}
.table {
display: table;
}
.grid {
display: grid;
}
.hidden {
display: none;
}
.flex-col {
flex-direction: column;
}
.items-center {
align-items: center;
}
.justify-start {
justify-content: flex-start;
}
.justify-end {
justify-content: flex-end;
}
.justify-center {
justify-content: center;
}
.flex-1 {
flex: 1 1 0%;
}
.flex-none {
flex: none;
}
.flex-shrink-0 {
flex-shrink: 0;
}
.font-mono {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
.font-bold {
font-weight: 700;
}
.h-2 {
height: 0.5rem;
}
.h-6 {
height: 1.5rem;
}
.h-8 {
height: 2rem;
}
.h-9 {
height: 2.25rem;
}
.h-12 {
height: 3rem;
}
.h-full {
height: 100%;
}
.text-xs {
font-size: 0.75rem;
line-height: 1rem;
}
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
}
.text-base {
font-size: 1rem;
line-height: 1.5rem;
}
.text-lg {
font-size: 1.125rem;
line-height: 1.75rem;
}
.text-xl {
font-size: 1.25rem;
line-height: 1.75rem;
}
.m-auto {
margin: auto;
}
.mx-1 {
margin-left: 0.25rem;
margin-right: 0.25rem;
}
.my-2 {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
.mx-2 {
margin-left: 0.5rem;
margin-right: 0.5rem;
}
.my-auto {
margin-top: auto;
margin-bottom: auto;
}
.mx-auto {
margin-left: auto;
margin-right: auto;
}
.mr-2 {
margin-right: 0.5rem;
}
.mb-2 {
margin-bottom: 0.5rem;
}
.ml-2 {
margin-left: 0.5rem;
}
.mb-4 {
margin-bottom: 1rem;
}
.mr-8 {
margin-right: 2rem;
}
.ml-auto {
margin-left: auto;
}
.focus\:outline-none:focus {
outline: 2px solid transparent;
outline-offset: 2px;
}
.overflow-auto {
overflow: auto;
}
.overflow-hidden {
overflow: hidden;
}
.overflow-visible {
overflow: visible;
}
.overflow-y-auto {
overflow-y: auto;
}
.overflow-x-hidden {
overflow-x: hidden;
}
.p-1 {
padding: 0.25rem;
}
.p-2 {
padding: 0.5rem;
}
.p-3 {
padding: 0.75rem;
}
.p-1\.5 {
padding: 0.375rem;
}
.p-3\.5 {
padding: 0.875rem;
}
.pl-1 {
padding-left: 0.25rem;
}
.absolute {
position: absolute;
}
.relative {
position: relative;
}
.top-0 {
top: 0px;
}
.right-0 {
right: 0px;
}
.bottom-0 {
bottom: 0px;
}
.left-0 {
left: 0px;
}
.right-1 {
right: 0.25rem;
}
.-top-7 {
top: -1.75rem;
}
.-bottom-8 {
bottom: -2rem;
}
.-right-24 {
right: -6rem;
}
.-left-24 {
left: -6rem;
}
.resize {
resize: both;
}
* {
--tw-shadow: 0 0 #0000;
}
* {
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgba(59, 130, 246, 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
}
.fill-current {
fill: currentColor;
}
.text-center {
text-align: center;
}
.text-right {
text-align: right;
}
.text-gray-50 {
--tw-text-opacity: 1;
color: rgba(250, 250, 250, var(--tw-text-opacity));
}
.text-gray-100 {
--tw-text-opacity: 1;
color: rgba(245, 245, 245, var(--tw-text-opacity));
}
.text-gray-200 {
--tw-text-opacity: 1;
color: rgba(229, 229, 229, var(--tw-text-opacity));
}
.text-gray-700 {
--tw-text-opacity: 1;
color: rgba(64, 64, 64, var(--tw-text-opacity));
}
.text-green-500 {
--tw-text-opacity: 1;
color: rgba(16, 185, 129, var(--tw-text-opacity));
}
.text-red-500 {
--tw-text-opacity: 1;
color: rgba(239, 68, 68, var(--tw-text-opacity));
}
.hover\:text-gray-400:hover {
--tw-text-opacity: 1;
color: rgba(163, 163, 163, var(--tw-text-opacity));
}
.hover\:text-green-500:hover {
--tw-text-opacity: 1;
color: rgba(16, 185, 129, var(--tw-text-opacity));
}
.select-none {
user-select: none;
}
.visible {
visibility: visible;
}
.invisible {
visibility: hidden;
}
.whitespace-nowrap {
white-space: nowrap;
}
.w-2 {
width: 0.5rem;
}
.w-10 {
width: 2.5rem;
}
.w-12 {
width: 3rem;
}
.w-48 {
width: 12rem;
}
.w-auto {
width: auto;
}
.w-11\/12 {
width: 91.666667%;
}
.w-full {
width: 100%;
}
.w-min {
width: min-content;
}
.col-span-2 {
grid-column: span 2 / span 2;
}
.transform {
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.transition {
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, transform;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
@keyframes ping {
75%, 100% {
transform: scale(2);
opacity: 0;
}
}
@keyframes pulse {
50% {
opacity: .5;
}
}
@keyframes bounce {
0%, 100% {
transform: translateY(-25%);
animation-timing-function: cubic-bezier(0.8,0,1,1);
}
50% {
transform: none;
animation-timing-function: cubic-bezier(0,0,0.2,1);
}
}
* {
box-sizing: border-box;
scrollbar-color: lightgray #262626;
scrollbar-width: thin;
border-width: 0;
border-style: solid;
}
body {
margin: 0;
height: 100%;
font-family: sans-serif;
overflow: hidden;
--topNavH: 3rem;
--sideNavW: 15rem;
}
#c {
position: absolute;
width: calc(100% - var(--sideNavW));
height: calc(100% - var(--topNavH));
bottom: 0;
right: 0;
}
.topNav {
position: absolute;
height: var(--topNavH);
left:0;
right:0;
top:0;
}
.sideNav {
position: absolute;
top: var(--topNavH);
left: 0;
bottom: 0;
width: var(--sideNavW);
}
.dialog {
position: absolute;
height: var(--topNavH);
left:0;
right:0;
top:0;
}
#labels > div {
position: absolute;
color: white;
}
.btn {
cursor: pointer;
background-color: transparent;
}
.btn:hover {
--tw-bg-opacity: 1;
background-color: rgba(82, 82, 82, var(--tw-bg-opacity));
}
.btn {
fill: currentColor;
}
.btn-green {
cursor: pointer;
background-color: transparent;
fill: currentColor;
--tw-text-opacity: 1;
color: rgba(229, 229, 229, var(--tw-text-opacity));
}
.btn-green:hover {
--tw-text-opacity: 1;
color: rgba(16, 185, 129, var(--tw-text-opacity));
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type=number] {
-moz-appearance: textfield;
/* border:none; */
background-color:transparent;
outline: none;
text-align:right;
}
.arrow {
position: absolute;
bottom: 100%;
left: 50%;
margin-left: -6px;
border: solid 6px transparent;
border-bottom-color: #3F3F46;
border-top: none;
}
.drop-down-top {
top: calc(var(--topNavH) + 6px);
}
.hide-scroll{
scrollbar-width: none; /* Firefox */
}
.hide-scroll::-webkit-scrollbar {
display: none; /* Safari and Chrome */
}
::-webkit-scrollbar {
width: 0.375rem;
background: #262626;
}
::-webkit-scrollbar-thumb {
background: lightgray;
}
@media (min-width: 640px) {
.sm\:text-base {
font-size: 1rem;
line-height: 1.5rem;
}
}
@media (min-width: 768px) {
.md\:flex {
display: flex;
}
.md\:text-xl {
font-size: 1.25rem;
line-height: 1.75rem;
}
}
@media (min-width: 1024px) {
.lg\:flex {
display: flex;
}
.lg\:justify-between {
justify-content: space-between;
}
.lg\:text-base {
font-size: 1rem;
line-height: 1.5rem;
}
.lg\:text-lg {
font-size: 1.125rem;
line-height: 1.75rem;
}
}
@media (min-width: 1280px) {
.xl\:text-lg {
font-size: 1.125rem;
line-height: 1.75rem;
}
.xl\:text-xl {
font-size: 1.25rem;
line-height: 1.75rem;
}
}
@media (min-width: 1536px) {
}

1
demo/cube-with-hole.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,281 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="580"
height="470"
viewBox="0 0 579.99995 470.00002"
version="1.1"
id="svg2112"
inkscape:version="1.0.2 (1.0.2+r75+1)"
sodipodi:docname="feature-screen-diagram.svg"
inkscape:export-filename="/home/howard/Documents/three_again/demo/ui-diagram-labelled.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs2106">
<linearGradient
inkscape:collect="always"
id="linearGradient1400">
<stop
style="stop-color:#000000;stop-opacity:0"
offset="0"
id="stop1396" />
<stop
style="stop-color:#000000;stop-opacity:1"
offset="1"
id="stop1398" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient1344">
<stop
style="stop-color:#000000;stop-opacity:0"
offset="0"
id="stop1340" />
<stop
style="stop-color:#000000;stop-opacity:1"
offset="1"
id="stop1342" />
</linearGradient>
<rect
x="184.93768"
y="398.17691"
width="145.55893"
height="30.240499"
id="rect1171" />
<linearGradient
inkscape:collect="always"
id="linearGradient1042">
<stop
style="stop-color:#000000;stop-opacity:0"
offset="0"
id="stop1038" />
<stop
style="stop-color:#000000;stop-opacity:1"
offset="1"
id="stop1040" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1042"
id="linearGradient1030"
x1="445.22595"
y1="424.96655"
x2="682.62335"
y2="424.96655"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0086706,0,0,1.0122555,-3.8603581,-9.4157352)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1042"
id="linearGradient1091"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.46236616,0,0,0.77071983,-134.78789,198.55535)"
x1="816.16608"
y1="106.28653"
x2="816.16608"
y2="232.19882" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1042"
id="linearGradient1105"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.46236616,0,0,0.77071983,-134.78789,198.55535)"
x1="816.16608"
y1="185.95866"
x2="816.16608"
y2="405.76633" />
<rect
x="184.93768"
y="398.17691"
width="143.17085"
height="33.860397"
id="rect1171-0" />
<rect
x="184.93768"
y="398.17691"
width="156.64307"
height="104.99782"
id="rect1186" />
<rect
x="184.93768"
y="398.17691"
width="170.47702"
height="29.928768"
id="rect1171-0-3" />
<rect
x="184.93768"
y="398.17691"
width="156.64307"
height="104.99782"
id="rect1230" />
<rect
x="184.93768"
y="398.17691"
width="121.1055"
height="33.602245"
id="rect1171-0-0" />
<rect
x="184.93768"
y="398.17691"
width="156.64307"
height="104.99782"
id="rect1230-6" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1400"
id="linearGradient1346"
x1="396.75552"
y1="258.31982"
x2="562.50885"
y2="258.31982"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.84392839,0,0,0.97305033,105.20295,13.440827)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1344"
id="linearGradient1375"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.675829,0,0,0.87460688,89.776288,-404.94328)"
x1="356.03503"
y1="258.31982"
x2="562.54382"
y2="258.31982" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="0.77327252"
inkscape:cx="86.383774"
inkscape:cy="270.02082"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="2069"
inkscape:window-height="1215"
inkscape:window-x="208"
inkscape:window-y="91"
inkscape:window-maximized="0"
units="px" />
<metadata
id="metadata2109">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
style="display:inline">
<g
id="g1097"
transform="translate(-141.06952,-106.88704)">
<image
sodipodi:absref="/home/howard/Documents/three_again/demo/ui-diagram.png"
xlink:href="ui-diagram.png"
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
style="fill:none;fill-opacity:1"
y="141.88704"
x="141.06952"
id="image874"
preserveAspectRatio="none"
height="637"
width="1024" />
</g>
<rect
style="display:inline;fill:none;stroke:#ff8000;stroke-width:4.33957;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect862-6-5"
width="271.57394"
height="43.660435"
x="352.16977"
y="37.169781" />
<rect
style="display:inline;fill:none;stroke:#00aaff;stroke-width:4.463;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect862-6-5-1"
width="381.37656"
height="414.56198"
x="242.23149"
y="85.231499" />
<rect
style="display:inline;fill:none;stroke:#ff00ff;stroke-width:4.03483;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect862-6-5-2"
width="195.96516"
height="43.965168"
x="152.01743"
y="37.017414" />
<rect
style="display:inline;fill:none;stroke:#80ff00;stroke-width:4.19643;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect862-6-5-2-7"
width="235.80357"
height="379.07791"
x="2.0982153"
y="121.09821" />
<text
xml:space="preserve"
id="text1169"
style="font-style:normal;font-weight:normal;font-size:24px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect1171);fill:#000000;fill-opacity:1;stroke:none;"
transform="translate(-94.997535,-272.17773)"><tspan
x="184.9375"
y="419.41211"><tspan
style="font-size:24px;fill:#80ff00;fill-opacity:1">Design Tree</tspan></tspan></text>
<text
xml:space="preserve"
id="text1169-9"
style="font-style:normal;font-weight:normal;font-size:24px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect1171-0);display:inline;fill:#ff00ff;fill-opacity:1;stroke:none;"
transform="translate(-27.292969,-391.17773)"><tspan
x="184.9375"
y="419.41211"><tspan
style="font-size:24px;fill:#ff00ff;fill-opacity:1">Dialog Box</tspan></tspan></text>
<text
xml:space="preserve"
id="text1169-9-6"
style="font-style:normal;font-weight:normal;font-size:24px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect1171-0-3);display:inline;fill:#000000;fill-opacity:1;stroke:none;"
transform="translate(64.722662,-308.17773)"><tspan
x="184.9375"
y="419.41211"><tspan
style="font-size:24px;fill:#00aaff;fill-opacity:1">Canvas</tspan></tspan></text>
<text
xml:space="preserve"
id="text1169-9-2"
style="font-style:normal;font-weight:normal;font-size:24px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect1171-0-0);display:inline;fill:#000000;fill-opacity:1;stroke:none;"
transform="translate(175.13281,-391.17773)"><tspan
x="184.9375"
y="419.41211"><tspan
style="font-size:24px;fill:#ff8000;fill-opacity:1">Toolbar</tspan></tspan></text>
<rect
style="opacity:1;fill:url(#linearGradient1346);fill-opacity:1;stroke:none;stroke-width:3.62476;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1338"
width="140"
height="467.87961"
x="440"
y="30.859051" />
<rect
style="display:inline;fill:url(#linearGradient1375);fill-opacity:1;stroke:none;stroke-width:3.07528;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1338-2"
width="140"
height="381.08569"
x="330"
y="-349.8287"
transform="rotate(90)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
demo/gif/1 (copy).xcf Normal file

Binary file not shown.

BIN
demo/gif/1.xcf Normal file

Binary file not shown.

BIN
demo/gif/2.xcf Normal file

Binary file not shown.

BIN
demo/gif/3.xcf Normal file

Binary file not shown.

BIN
demo/gif/4.xcf Normal file

Binary file not shown.

BIN
demo/gif/5.xcf Normal file

Binary file not shown.

BIN
demo/gif/6.xcf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

BIN
demo/gif/Untitled.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
demo/gif/combined.xcf Normal file

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
demo/gif/extrude.xcf Normal file

Binary file not shown.

BIN
demo/gif/in.mp4 Normal file

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

BIN
demo/gif/sculpt.xcf Normal file

Binary file not shown.

BIN
demo/gif/sculpt_wide.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
demo/gif/sketch.mp4 Normal file

Binary file not shown.

BIN
demo/gif/sketch.xcf Normal file

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

BIN
demo/gif/wide.xcf Normal file

Binary file not shown.

BIN
demo/image874.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

170
demo/left-click.svg Normal file
View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="left-click.svg"
inkscape:version="1.0.2 (1.0.2+r75+1)"
id="svg8"
version="1.1"
viewBox="0 0 126.99952 185.20821"
height="700"
width="480">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.41960784"
inkscape:pageshadow="2"
inkscape:zoom="0.7549995"
inkscape:cx="171.58915"
inkscape:cy="210.46929"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-others="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="2012"
inkscape:window-height="1206"
inkscape:window-x="461"
inkscape:window-y="87"
inkscape:window-maximized="0"
inkscape:object-nodes="false"
inkscape:snap-nodes="true"
inkscape:pagecheckerboard="false"
inkscape:document-rotation="0"
inkscape:snap-text-baseline="false"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-object-midpoints="false"
inkscape:snap-center="false"
inkscape:snap-to-guides="true">
<sodipodi:guide
position="129.58681,136.23525"
orientation="1,0"
id="guide1020" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Mouse frame (0)"
id="layer1"
inkscape:groupmode="layer"
style="display:inline">
<path
sodipodi:nodetypes="ccssssssccccsssssscc"
inkscape:connector-curvature="0"
d="m 57.143525,34.384496 -0.0013,9.986098 c -4.619332,1.640928 -7.911862,6.034282 -7.911862,11.224912 v 21.40433 c 0,6.587782 5.303559,11.891298 11.891385,11.891298 h 4.756555 c 6.587828,0 11.891386,-5.303516 11.891386,-11.891298 v -21.40433 c 0,-5.20858 -3.315345,-9.614594 -7.958982,-11.230262 l -0.03128,-9.980748 z m -3.156642,0 c -22.398612,0 -40.430706,18.031964 -40.430706,40.430406 v 61.835008 c 0,22.39862 18.032094,40.43072 40.430706,40.43072 h 19.026222 c 22.398612,0 40.430715,-18.0321 40.430715,-40.43072 V 74.814902 c 0,-22.398442 -18.032103,-40.430406 -40.430715,-40.430406 z"
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
id="rect4559" />
</g>
<g
style="display:inline"
inkscape:label="Left click (1)"
id="layer2"
inkscape:groupmode="layer">
<path
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
d="M 46.23194,44.336396 C 32.052243,49.048938 21.880146,62.386753 21.880146,78.188753 V 101.4958 h 41.619849 v -4.972052 h -2.37874 c -10.504585,0 -19.130733,-8.629161 -19.130733,-19.132555 V 55.9867 c 0,-4.456035 1.625405,-8.462768 4.241418,-11.650304 z"
id="rect4605"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscccsssc" />
</g>
<g
inkscape:label="Middle click (2)"
id="layer3"
inkscape:groupmode="layer"
style="display:none">
<rect
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
id="rect4603"
width="13.080523"
height="29.72846"
x="56.959732"
y="51.570152"
rx="4.7565541"
ry="4.7565541" />
</g>
<g
inkscape:label="Right click (3)"
id="layer4"
inkscape:groupmode="layer"
style="display:none">
<path
sodipodi:nodetypes="cscccsssc"
inkscape:connector-curvature="0"
id="path4664"
d="m 80.768052,44.336396 c 14.179695,4.712542 24.351798,18.050357 24.351798,33.852357 V 101.4958 H 63.499996 v -4.972062 h 2.37874 c 10.504583,0 19.130731,-8.629151 19.130731,-19.132545 V 55.9867 c 0,-4.456035 -1.625405,-8.462768 -4.241415,-11.650304 z"
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" />
</g>
<g
inkscape:label="Scroll up (4)"
id="layer5"
inkscape:groupmode="layer"
style="display:none">
<path
id="path4588"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 53.19098,18.360058 63.533489,8.0175498 73.809009,18.293074 M 63.533489,29.640336 V 8.0175498"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
<g
inkscape:label="Scroll down (5)"
id="layer6"
inkscape:groupmode="layer"
style="display:none">
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
d="m 53.19098,105.46811 10.342509,10.3425 10.27552,-10.27552 M 63.533489,94.187874 v 21.622736"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4591" />
</g>
<g
inkscape:label="Scroll left (6)"
id="layer7"
inkscape:groupmode="layer"
style="display:none">
<path
id="path4593"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 33.064815,56.637818 22.722307,66.980326 32.997831,77.25584 M 44.345093,66.980326 H 22.722307"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
<g
inkscape:label="Scroll right (7)"
id="layer8"
inkscape:groupmode="layer"
style="display:none">
<path
id="path4595"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 93.935173,77.25584 104.27769,66.913333 94.002157,56.637818 M 82.654895,66.913333 h 21.622795"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

170
demo/middle-click.svg Normal file
View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="middle-click.svg"
inkscape:version="1.0.2 (1.0.2+r75+1)"
id="svg8"
version="1.1"
viewBox="0 0 126.99952 185.20821"
height="700"
width="480">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.41960784"
inkscape:pageshadow="2"
inkscape:zoom="0.7549995"
inkscape:cx="171.58915"
inkscape:cy="210.46929"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-others="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="2012"
inkscape:window-height="1206"
inkscape:window-x="461"
inkscape:window-y="87"
inkscape:window-maximized="0"
inkscape:object-nodes="false"
inkscape:snap-nodes="true"
inkscape:pagecheckerboard="false"
inkscape:document-rotation="0"
inkscape:snap-text-baseline="false"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-object-midpoints="false"
inkscape:snap-center="false"
inkscape:snap-to-guides="true">
<sodipodi:guide
position="129.58681,136.23525"
orientation="1,0"
id="guide1020" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Mouse frame (0)"
id="layer1"
inkscape:groupmode="layer"
style="display:inline">
<path
sodipodi:nodetypes="ccssssssccccsssssscc"
inkscape:connector-curvature="0"
d="m 57.143525,34.384496 -0.0013,9.986098 c -4.619332,1.640928 -7.911862,6.034282 -7.911862,11.224912 v 21.40433 c 0,6.587782 5.303559,11.891298 11.891385,11.891298 h 4.756555 c 6.587828,0 11.891386,-5.303516 11.891386,-11.891298 v -21.40433 c 0,-5.20858 -3.315345,-9.614594 -7.958982,-11.230262 l -0.03128,-9.980748 z m -3.156642,0 c -22.398612,0 -40.430706,18.031964 -40.430706,40.430406 v 61.835008 c 0,22.39862 18.032094,40.43072 40.430706,40.43072 h 19.026222 c 22.398612,0 40.430715,-18.0321 40.430715,-40.43072 V 74.814902 c 0,-22.398442 -18.032103,-40.430406 -40.430715,-40.430406 z"
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
id="rect4559" />
</g>
<g
style="display:none"
inkscape:label="Left click (1)"
id="layer2"
inkscape:groupmode="layer">
<path
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
d="M 46.23194,44.336396 C 32.052243,49.048938 21.880146,62.386753 21.880146,78.188753 V 101.4958 h 41.619849 v -4.972052 h -2.37874 c -10.504585,0 -19.130733,-8.629161 -19.130733,-19.132555 V 55.9867 c 0,-4.456035 1.625405,-8.462768 4.241418,-11.650304 z"
id="rect4605"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscccsssc" />
</g>
<g
inkscape:label="Middle click (2)"
id="layer3"
inkscape:groupmode="layer"
style="display:inline">
<rect
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
id="rect4603"
width="13.080523"
height="29.72846"
x="56.959732"
y="51.570152"
rx="4.7565541"
ry="4.7565541" />
</g>
<g
inkscape:label="Right click (3)"
id="layer4"
inkscape:groupmode="layer"
style="display:none">
<path
sodipodi:nodetypes="cscccsssc"
inkscape:connector-curvature="0"
id="path4664"
d="m 80.768052,44.336396 c 14.179695,4.712542 24.351798,18.050357 24.351798,33.852357 V 101.4958 H 63.499996 v -4.972062 h 2.37874 c 10.504583,0 19.130731,-8.629151 19.130731,-19.132545 V 55.9867 c 0,-4.456035 -1.625405,-8.462768 -4.241415,-11.650304 z"
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" />
</g>
<g
inkscape:label="Scroll up (4)"
id="layer5"
inkscape:groupmode="layer"
style="display:none">
<path
id="path4588"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 53.19098,18.360058 63.533489,8.0175498 73.809009,18.293074 M 63.533489,29.640336 V 8.0175498"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
<g
inkscape:label="Scroll down (5)"
id="layer6"
inkscape:groupmode="layer"
style="display:none">
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
d="m 53.19098,105.46811 10.342509,10.3425 10.27552,-10.27552 M 63.533489,94.187874 v 21.622736"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4591" />
</g>
<g
inkscape:label="Scroll left (6)"
id="layer7"
inkscape:groupmode="layer"
style="display:none">
<path
id="path4593"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 33.064815,56.637818 22.722307,66.980326 32.997831,77.25584 M 44.345093,66.980326 H 22.722307"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
<g
inkscape:label="Scroll right (7)"
id="layer8"
inkscape:groupmode="layer"
style="display:none">
<path
id="path4595"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 93.935173,77.25584 104.27769,66.913333 94.002157,56.637818 M 82.654895,66.913333 h 21.622795"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

262
demo/mouse.original.svg Normal file
View File

@ -0,0 +1,262 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="mouse.original.svg"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
id="svg8"
version="1.1"
viewBox="0 0 185.20764 211.66653"
height="800"
width="700">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.41960784"
inkscape:pageshadow="2"
inkscape:zoom="1.2553118"
inkscape:cx="344.69956"
inkscape:cy="335.82524"
inkscape:document-units="px"
inkscape:current-layer="layer14"
showgrid="false"
units="px"
inkscape:snap-others="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1916"
inkscape:window-height="1028"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:object-nodes="false"
inkscape:snap-nodes="true"
inkscape:pagecheckerboard="false"
inkscape:document-rotation="0"
inkscape:snap-text-baseline="false"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-object-midpoints="false"
inkscape:snap-center="false"
inkscape:snap-to-guides="true">
<sodipodi:guide
position="152.0289,75.975229"
orientation="1,0"
id="guide1020" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Mouse frame (0)"
id="layer1"
inkscape:groupmode="layer">
<path
sodipodi:nodetypes="ccssssssccccsssssscc"
inkscape:connector-curvature="0"
d="m 57.143525,34.384496 -0.0013,9.986098 c -4.619332,1.640928 -7.911862,6.034282 -7.911862,11.224912 v 21.40433 c 0,6.587782 5.303559,11.891298 11.891385,11.891298 h 4.756555 c 6.587828,0 11.891386,-5.303516 11.891386,-11.891298 v -21.40433 c 0,-5.20858 -3.315345,-9.614594 -7.958982,-11.230262 l -0.03128,-9.980748 z m -3.156642,0 c -22.398612,0 -40.430706,18.031964 -40.430706,40.430406 v 61.835008 c 0,22.39862 18.032094,40.43072 40.430706,40.43072 h 19.026222 c 22.398612,0 40.430715,-18.0321 40.430715,-40.43072 V 74.814902 c 0,-22.398442 -18.032103,-40.430406 -40.430715,-40.430406 z"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill;opacity:1"
id="rect4559" />
</g>
<g
style="display:inline"
inkscape:label="Left click (1)"
id="layer2"
inkscape:groupmode="layer">
<path
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
d="M 46.23194,44.336396 C 32.052243,49.048938 21.880146,62.386753 21.880146,78.188753 V 101.4958 h 41.619849 v -4.972052 h -2.37874 c -10.504585,0 -19.130733,-8.629161 -19.130733,-19.132555 V 55.9867 c 0,-4.456035 1.625405,-8.462768 4.241418,-11.650304 z"
id="rect4605"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscccsssc" />
</g>
<g
inkscape:label="Middle click (2)"
id="layer3"
inkscape:groupmode="layer">
<rect
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
id="rect4603"
width="13.080523"
height="29.72846"
x="56.959732"
y="51.570152"
rx="4.7565541"
ry="4.7565541" />
</g>
<g
inkscape:label="Right click (3)"
id="layer4"
inkscape:groupmode="layer">
<path
sodipodi:nodetypes="cscccsssc"
inkscape:connector-curvature="0"
id="path4664"
d="m 80.768052,44.336396 c 14.179695,4.712542 24.351798,18.050357 24.351798,33.852357 V 101.4958 H 63.499996 v -4.972062 h 2.37874 c 10.504583,0 19.130731,-8.629151 19.130731,-19.132545 V 55.9867 c 0,-4.456035 -1.625405,-8.462768 -4.241415,-11.650304 z"
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" />
</g>
<g
inkscape:label="Scroll up (4)"
id="layer5"
inkscape:groupmode="layer">
<path
id="path4588"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 53.19098,18.360058 63.533489,8.0175498 73.809009,18.293074 M 63.533489,29.640336 V 8.0175498"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
<g
inkscape:label="Scroll down (5)"
id="layer6"
inkscape:groupmode="layer">
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
d="m 53.19098,105.46811 10.342509,10.3425 10.27552,-10.27552 M 63.533489,94.187874 v 21.622736"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4591" />
</g>
<g
inkscape:label="Scroll left (6)"
id="layer7"
inkscape:groupmode="layer">
<path
id="path4593"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 33.064815,56.637818 22.722307,66.980326 32.997831,77.25584 M 44.345093,66.980326 H 22.722307"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
<g
inkscape:label="Scroll right (7)"
id="layer8"
inkscape:groupmode="layer">
<path
id="path4595"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 93.935173,77.25584 104.27769,66.913333 94.002157,56.637818 M 82.654895,66.913333 h 21.622795"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
<g
inkscape:groupmode="layer"
id="layer12"
inkscape:label="Ctrl (8)">
<g
id="text943"
style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583">
<path
style="fill:#ffffff;stroke-width:0.264583"
d="m 146.52541,52.879491 v 2.128035 q -1.01906,-0.949124 -2.17799,-1.41869 -1.14894,-0.469566 -2.44774,-0.469566 -2.55764,0 -3.91638,1.568551 -1.35875,1.55856 -1.35875,4.515829 0,2.947277 1.35875,4.515828 1.35874,1.558561 3.91638,1.558561 1.2988,0 2.44774,-0.469567 1.15893,-0.469566 2.17799,-1.418689 v 2.108053 q -1.05902,0.719335 -2.24793,1.079003 -1.17891,0.359668 -2.49769,0.359668 -3.38687,0 -5.33507,-2.06809 -1.9482,-2.07808 -1.9482,-5.664767 0,-3.596678 1.9482,-5.664768 1.9482,-2.07808 5.33507,-2.07808 1.33876,0 2.51768,0.359668 1.1889,0.349677 2.22794,1.059021 z"
id="path1588" />
<path
d="m 151.38092,52.280045 v 3.177065 h 3.7865 v 1.428681 h -3.7865 v 6.074389 q 0,1.368735 0.36966,1.758375 0.37965,0.389641 1.52859,0.389641 h 1.88825 v 1.538578 h -1.88825 q -2.12804,0 -2.93729,-0.789271 -0.80925,-0.799261 -0.80925,-2.897323 v -6.074389 h -1.34875 V 55.45711 h 1.34875 v -3.177065 z"
style="fill:#ffffff;stroke-width:0.264583"
id="path1590" />
<path
d="m 164.0692,57.175523 q -0.30971,-0.179834 -0.67937,-0.25976 -0.35967,-0.08992 -0.79926,-0.08992 -1.55856,0 -2.39779,1.019059 -0.82923,1.009068 -0.82923,2.907314 v 5.894555 h -1.84829 V 55.45711 h 1.84829 v 1.738395 q 0.57946,-1.019059 1.50861,-1.508607 0.92914,-0.499538 2.25791,-0.499538 0.18982,0 0.41961,0.02997 0.22979,0.01998 0.50953,0.06994 z"
style="fill:#ffffff;stroke-width:0.264583"
id="path1592" />
<path
d="m 165.99742,51.101134 h 1.8383 v 15.54564 h -1.8383 z"
style="fill:#ffffff;stroke-width:0.264583"
id="path1594" />
</g>
<rect
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2.9;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect953"
width="45.843319"
height="27.083668"
x="129.10742"
y="45.476986"
ry="0.18775558" />
</g>
<g
inkscape:groupmode="layer"
id="layer14"
inkscape:label="Alt (9)">
<g
id="text947"
style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583">
<path
d="m 144.38377,99.443142 -2.73747,7.423148 h 5.48493 z m -1.13895,-1.988163 h 2.28789 l 5.68475,14.916221 h -2.09807 l -1.35874,-3.82646 h -6.72379 l -1.35875,3.82646 h -2.12803 z"
style="fill:#ffffff;stroke-width:0.264583"
id="path1597" />
<path
d="m 153.31552,96.82556 h 1.8383 v 15.54564 h -1.8383 z"
style="fill:#ffffff;stroke-width:0.264583"
id="path1599" />
<path
d="m 160.81859,98.004471 v 3.177069 h 3.7865 v 1.42868 h -3.7865 v 6.07439 q 0,1.36873 0.36966,1.75837 0.37965,0.38964 1.52858,0.38964 h 1.88826 v 1.53858 h -1.88826 q -2.12803,0 -2.93728,-0.78927 -0.80926,-0.79926 -0.80926,-2.89732 v -6.07439 h -1.34875 v -1.42868 h 1.34875 v -3.177069 z"
style="fill:#ffffff;stroke-width:0.264583"
id="path1601" />
</g>
<rect
ry="0.18775558"
y="91.383667"
x="132.16098"
height="27.083672"
width="39.736214"
id="rect953-4"
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2.89999;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
inkscape:groupmode="layer"
id="layer13"
inkscape:label="Shift (10)">
<g
id="text951"
style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583">
<path
d="m 139.23953,144.18143 v 1.96819 q -1.14894,-0.5495 -2.168,-0.81925 -1.01906,-0.26975 -1.96818,-0.26975 -1.64848,0 -2.54765,0.63941 -0.88918,0.63941 -0.88918,1.81832 0,0.98909 0.58946,1.49862 0.59944,0.49954 2.25791,0.80925 l 1.21888,0.24977 q 2.25791,0.4296 3.32692,1.5186 1.07901,1.079 1.07901,2.89732 0,2.168 -1.45866,3.28696 -1.44866,1.11897 -4.25606,1.11897 -1.05903,0 -2.25792,-0.23978 -1.1889,-0.23978 -2.46772,-0.70934 v -2.07808 q 1.22887,0.68936 2.40778,1.03904 1.17891,0.34967 2.31786,0.34967 1.7284,0 2.66753,-0.67937 0.93913,-0.67937 0.93913,-1.93821 0,-1.09898 -0.67937,-1.71841 -0.66938,-0.61943 -2.20796,-0.92914 l -1.22886,-0.23978 q -2.25792,-0.44959 -3.26699,-1.4087 -1.00906,-0.95911 -1.00906,-2.66754 0,-1.97817 1.38871,-3.11712 1.39871,-1.13894 3.84645,-1.13894 1.04903,0 2.13803,0.18982 1.08899,0.18983 2.22794,0.56947 z"
style="fill:#ffffff;stroke-width:0.264583"
id="path1604" />
<path
d="m 152.50727,151.85435 v 6.75376 h -1.8383 v -6.69382 q 0,-1.58853 -0.61943,-2.3778 -0.61943,-0.78927 -1.85828,-0.78927 -1.48863,0 -2.34783,0.94912 -0.85921,0.94912 -0.85921,2.58761 v 6.32416 h -1.84829 v -15.54564 h 1.84829 v 6.09437 q 0.65939,-1.00907 1.54857,-1.50861 0.89917,-0.49954 2.06809,-0.49954 1.92822,0 2.91731,1.1989 0.98908,1.1889 0.98908,3.50676 z"
style="fill:#ffffff;stroke-width:0.264583"
id="path1606" />
<path
d="m 156.17389,147.41844 h 1.8383 v 11.18967 h -1.8383 z m 0,-4.35597 h 1.8383 v 2.32785 h -1.8383 z"
style="fill:#ffffff;stroke-width:0.264583"
id="path1608" />
<path
d="m 167.5234,143.06247 v 1.52859 h -1.75837 q -0.98909,0 -1.37873,0.39963 -0.37965,0.39963 -0.37965,1.43867 v 0.98908 h 3.0272 v 1.42868 h -3.0272 v 9.76099 h -1.84829 v -9.76099 h -1.75838 v -1.42868 h 1.75838 v -0.77928 q 0,-1.86827 0.8692,-2.71749 0.86919,-0.8592 2.75745,-0.8592 z"
style="fill:#ffffff;stroke-width:0.264583"
id="path1610" />
<path
d="m 170.52063,144.24138 v 3.17706 h 3.78651 v 1.42868 h -3.78651 v 6.07439 q 0,1.36874 0.36966,1.75838 0.37965,0.38964 1.52859,0.38964 h 1.88826 v 1.53858 h -1.88826 q -2.12803,0 -2.93729,-0.78927 -0.80925,-0.79926 -0.80925,-2.89733 v -6.07439 h -1.34875 v -1.42868 h 1.34875 v -3.17706 z"
style="fill:#ffffff;stroke-width:0.264583"
id="path1612" />
</g>
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2.89999;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect953-4-3"
width="55.559566"
height="26.966721"
x="124.2493"
y="137.1413"
ry="0.18775558" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

13
demo/mouse.svg Normal file
View File

@ -0,0 +1,13 @@
<svg width="700" height="800" version="1.1" viewBox="0 0 185.21 211.67" xmlns="http://www.w3.org/2000/svg">
<path d="m57.144 34.384-0.0013 9.9861c-4.6193 1.6409-7.9119 6.0343-7.9119 11.225v21.404c0 6.5878 5.3036 11.891 11.891 11.891h4.7566c6.5878 0 11.891-5.3035 11.891-11.891v-21.404c0-5.2086-3.3153-9.6146-7.959-11.23l-0.03128-9.9807zm-3.1566 0c-22.399 0-40.431 18.032-40.431 40.43v61.835c0 22.399 18.032 40.431 40.431 40.431h19.026c22.399 0 40.431-18.032 40.431-40.431v-61.835c0-22.398-18.032-40.43-40.431-40.43z" fill="none" stroke="#fff" stroke-linecap="round" stroke-width="5.9457" style="paint-order:markers stroke fill"/>
<path d="m46.232 44.336c-14.18 4.7125-24.352 18.05-24.352 33.852v23.307h41.62v-4.9721h-2.3787c-10.505 0-19.131-8.6292-19.131-19.133v-21.404c0-4.456 1.6254-8.4628 4.2414-11.65z" fill="#fff" style="paint-order:markers stroke fill"/>
<rect x="56.96" y="51.57" width="13.081" height="29.728" rx="4.7566" ry="4.7566" fill="#fff" style="paint-order:markers stroke fill"/>
<path d="m80.768 44.336c14.18 4.7125 24.352 18.05 24.352 33.852v23.307h-41.62v-4.9721h2.3787c10.505 0 19.131-8.6292 19.131-19.133v-21.404c0-4.456-1.6254-8.4628-4.2414-11.65z" fill="#fff" style="paint-order:markers stroke fill"/>
<path d="m53.191 18.36 10.343-10.343 10.276 10.276m-10.276 11.347v-21.623" fill="none" stroke="#fff" stroke-width="5.9457"/>
<path d="m53.191 105.47 10.343 10.342 10.276-10.276m-10.276-11.347v21.623" fill="none" stroke="#fff" stroke-width="5.9457"/>
<path d="m33.065 56.638-10.343 10.343 10.276 10.276m11.347-10.276h-21.623" fill="none" stroke="#fff" stroke-width="5.9457"/>
<path d="m93.935 77.256 10.343-10.343-10.276-10.276m-11.347 10.276h21.623" fill="none" stroke="#fff" stroke-width="5.9457"/>
<g><g fill="#fff" stroke-width=".26458" aria-label="Ctrl"><path d="m146.53 52.879v2.128q-1.0191-0.94912-2.178-1.4187-1.1489-0.46957-2.4477-0.46957-2.5576 0-3.9164 1.5686-1.3588 1.5586-1.3588 4.5158 0 2.9473 1.3588 4.5158 1.3587 1.5586 3.9164 1.5586 1.2988 0 2.4477-0.46957 1.1589-0.46957 2.178-1.4187v2.1081q-1.059 0.71934-2.2479 1.079-1.1789 0.35967-2.4977 0.35967-3.3869 0-5.3351-2.0681-1.9482-2.0781-1.9482-5.6648 0-3.5967 1.9482-5.6648 1.9482-2.0781 5.3351-2.0781 1.3388 0 2.5177 0.35967 1.1889 0.34968 2.2279 1.059z"/><path d="m151.38 52.28v3.1771h3.7865v1.4287h-3.7865v6.0744q0 1.3687 0.36966 1.7584 0.37965 0.38964 1.5286 0.38964h1.8882v1.5386h-1.8882q-2.128 0-2.9373-0.78927-0.80925-0.79926-0.80925-2.8973v-6.0744h-1.3488v-1.4287h1.3488v-3.1771z"/><path d="m164.07 57.176q-0.30971-0.17983-0.67937-0.25976-0.35967-0.08992-0.79926-0.08992-1.5586 0-2.3978 1.0191-0.82923 1.0091-0.82923 2.9073v5.8946h-1.8483v-11.19h1.8483v1.7384q0.57946-1.0191 1.5086-1.5086 0.92914-0.49954 2.2579-0.49954 0.18982 0 0.41961 0.02997 0.22979 0.01998 0.50953 0.06994z"/><path d="m166 51.101h1.8383v15.546h-1.8383z"/></g><rect x="129.11" y="45.477" width="45.843" height="27.084" ry=".18776" fill="none" stroke="#fff" stroke-linejoin="round" stroke-width="2.9"/></g>
<g><g fill="#fff" stroke-width=".26458" aria-label="Alt"><path d="m144.38 99.443-2.7375 7.4231h5.4849zm-1.139-1.9882h2.2879l5.6848 14.916h-2.0981l-1.3587-3.8265h-6.7238l-1.3588 3.8265h-2.128z"/><path d="m153.32 96.826h1.8383v15.546h-1.8383z"/><path d="m160.82 98.004v3.1771h3.7865v1.4287h-3.7865v6.0744q0 1.3687 0.36966 1.7584 0.37965 0.38964 1.5286 0.38964h1.8883v1.5386h-1.8883q-2.128 0-2.9373-0.78927-0.80926-0.79926-0.80926-2.8973v-6.0744h-1.3488v-1.4287h1.3488v-3.1771z"/></g><rect x="132.16" y="91.384" width="39.736" height="27.084" ry=".18776" fill="none" stroke="#fff" stroke-linejoin="round" stroke-width="2.9"/></g>
<g><g fill="#fff" stroke-width=".26458" aria-label="Shift"><path d="m139.24 144.18v1.9682q-1.1489-0.5495-2.168-0.81925t-1.9682-0.26975q-1.6485 0-2.5476 0.63941-0.88918 0.63941-0.88918 1.8183 0 0.98909 0.58946 1.4986 0.59944 0.49954 2.2579 0.80925l1.2189 0.24977q2.2579 0.4296 3.3269 1.5186 1.079 1.079 1.079 2.8973 0 2.168-1.4587 3.287-1.4487 1.119-4.2561 1.119-1.059 0-2.2579-0.23978-1.1889-0.23978-2.4677-0.70934v-2.0781q1.2289 0.68936 2.4078 1.039 1.1789 0.34967 2.3179 0.34967 1.7284 0 2.6675-0.67937t0.93913-1.9382q0-1.099-0.67937-1.7184-0.66938-0.61943-2.208-0.92914l-1.2289-0.23978q-2.2579-0.44959-3.267-1.4087-1.0091-0.95911-1.0091-2.6675 0-1.9782 1.3887-3.1171 1.3987-1.1389 3.8464-1.1389 1.049 0 2.138 0.18982 1.089 0.18983 2.2279 0.56947z"/><path d="m152.51 151.85v6.7538h-1.8383v-6.6938q0-1.5885-0.61943-2.3778t-1.8583-0.78927q-1.4886 0-2.3478 0.94912-0.85921 0.94912-0.85921 2.5876v6.3242h-1.8483v-15.546h1.8483v6.0944q0.65939-1.0091 1.5486-1.5086 0.89917-0.49954 2.0681-0.49954 1.9282 0 2.9173 1.1989 0.98908 1.1889 0.98908 3.5068z"/><path d="m156.17 147.42h1.8383v11.19h-1.8383zm0-4.356h1.8383v2.3278h-1.8383z"/><path d="m167.52 143.06v1.5286h-1.7584q-0.98909 0-1.3787 0.39963-0.37965 0.39963-0.37965 1.4387v0.98908h3.0272v1.4287h-3.0272v9.761h-1.8483v-9.761h-1.7584v-1.4287h1.7584v-0.77928q0-1.8683 0.8692-2.7175 0.86919-0.8592 2.7574-0.8592z"/><path d="m170.52 144.24v3.1771h3.7865v1.4287h-3.7865v6.0744q0 1.3687 0.36966 1.7584 0.37965 0.38964 1.5286 0.38964h1.8883v1.5386h-1.8883q-2.128 0-2.9373-0.78927-0.80925-0.79926-0.80925-2.8973v-6.0744h-1.3488v-1.4287h1.3488v-3.1771z"/></g><rect x="124.25" y="137.14" width="55.56" height="26.967" ry=".18776" fill="none" stroke="#fff" stroke-linejoin="round" stroke-width="2.9"/></g>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB

170
demo/right-click.svg Normal file
View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="right-click.svg"
inkscape:version="1.0.2 (1.0.2+r75+1)"
id="svg8"
version="1.1"
viewBox="0 0 126.99952 185.20821"
height="700"
width="480">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.41960784"
inkscape:pageshadow="2"
inkscape:zoom="0.7549995"
inkscape:cx="171.58915"
inkscape:cy="210.46929"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-others="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="2012"
inkscape:window-height="1206"
inkscape:window-x="462"
inkscape:window-y="87"
inkscape:window-maximized="0"
inkscape:object-nodes="false"
inkscape:snap-nodes="true"
inkscape:pagecheckerboard="false"
inkscape:document-rotation="0"
inkscape:snap-text-baseline="false"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-object-midpoints="false"
inkscape:snap-center="false"
inkscape:snap-to-guides="true">
<sodipodi:guide
position="129.58681,136.23525"
orientation="1,0"
id="guide1020" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Mouse frame (0)"
id="layer1"
inkscape:groupmode="layer"
style="display:inline">
<path
sodipodi:nodetypes="ccssssssccccsssssscc"
inkscape:connector-curvature="0"
d="m 57.143525,34.384496 -0.0013,9.986098 c -4.619332,1.640928 -7.911862,6.034282 -7.911862,11.224912 v 21.40433 c 0,6.587782 5.303559,11.891298 11.891385,11.891298 h 4.756555 c 6.587828,0 11.891386,-5.303516 11.891386,-11.891298 v -21.40433 c 0,-5.20858 -3.315345,-9.614594 -7.958982,-11.230262 l -0.03128,-9.980748 z m -3.156642,0 c -22.398612,0 -40.430706,18.031964 -40.430706,40.430406 v 61.835008 c 0,22.39862 18.032094,40.43072 40.430706,40.43072 h 19.026222 c 22.398612,0 40.430715,-18.0321 40.430715,-40.43072 V 74.814902 c 0,-22.398442 -18.032103,-40.430406 -40.430715,-40.430406 z"
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
id="rect4559" />
</g>
<g
style="display:none"
inkscape:label="Left click (1)"
id="layer2"
inkscape:groupmode="layer">
<path
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
d="M 46.23194,44.336396 C 32.052243,49.048938 21.880146,62.386753 21.880146,78.188753 V 101.4958 h 41.619849 v -4.972052 h -2.37874 c -10.504585,0 -19.130733,-8.629161 -19.130733,-19.132555 V 55.9867 c 0,-4.456035 1.625405,-8.462768 4.241418,-11.650304 z"
id="rect4605"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscccsssc" />
</g>
<g
inkscape:label="Middle click (2)"
id="layer3"
inkscape:groupmode="layer"
style="display:none">
<rect
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
id="rect4603"
width="13.080523"
height="29.72846"
x="56.959732"
y="51.570152"
rx="4.7565541"
ry="4.7565541" />
</g>
<g
inkscape:label="Right click (3)"
id="layer4"
inkscape:groupmode="layer"
style="display:inline">
<path
sodipodi:nodetypes="cscccsssc"
inkscape:connector-curvature="0"
id="path4664"
d="m 80.768052,44.336396 c 14.179695,4.712542 24.351798,18.050357 24.351798,33.852357 V 101.4958 H 63.499996 v -4.972062 h 2.37874 c 10.504583,0 19.130731,-8.629151 19.130731,-19.132545 V 55.9867 c 0,-4.456035 -1.625405,-8.462768 -4.241415,-11.650304 z"
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" />
</g>
<g
inkscape:label="Scroll up (4)"
id="layer5"
inkscape:groupmode="layer"
style="display:none">
<path
id="path4588"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 53.19098,18.360058 63.533489,8.0175498 73.809009,18.293074 M 63.533489,29.640336 V 8.0175498"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
<g
inkscape:label="Scroll down (5)"
id="layer6"
inkscape:groupmode="layer"
style="display:none">
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
d="m 53.19098,105.46811 10.342509,10.3425 10.27552,-10.27552 M 63.533489,94.187874 v 21.622736"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4591" />
</g>
<g
inkscape:label="Scroll left (6)"
id="layer7"
inkscape:groupmode="layer"
style="display:none">
<path
id="path4593"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 33.064815,56.637818 22.722307,66.980326 32.997831,77.25584 M 44.345093,66.980326 H 22.722307"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
<g
inkscape:label="Scroll right (7)"
id="layer8"
inkscape:groupmode="layer"
style="display:none">
<path
id="path4595"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 93.935173,77.25584 104.27769,66.913333 94.002157,56.637818 M 82.654895,66.913333 h 21.622795"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

170
demo/scroll.svg Normal file
View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="scroll.svg"
inkscape:version="1.0.2 (1.0.2+r75+1)"
id="svg8"
version="1.1"
viewBox="0 0 126.99952 185.20821"
height="700"
width="480">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.41960784"
inkscape:pageshadow="2"
inkscape:zoom="0.7549995"
inkscape:cx="171.58915"
inkscape:cy="210.46929"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-others="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="2012"
inkscape:window-height="1206"
inkscape:window-x="461"
inkscape:window-y="87"
inkscape:window-maximized="0"
inkscape:object-nodes="false"
inkscape:snap-nodes="true"
inkscape:pagecheckerboard="false"
inkscape:document-rotation="0"
inkscape:snap-text-baseline="false"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-object-midpoints="false"
inkscape:snap-center="false"
inkscape:snap-to-guides="true">
<sodipodi:guide
position="129.58681,136.23525"
orientation="1,0"
id="guide1020" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Mouse frame (0)"
id="layer1"
inkscape:groupmode="layer"
style="display:inline">
<path
sodipodi:nodetypes="ccssssssccccsssssscc"
inkscape:connector-curvature="0"
d="m 57.143525,34.384496 -0.0013,9.986098 c -4.619332,1.640928 -7.911862,6.034282 -7.911862,11.224912 v 21.40433 c 0,6.587782 5.303559,11.891298 11.891385,11.891298 h 4.756555 c 6.587828,0 11.891386,-5.303516 11.891386,-11.891298 v -21.40433 c 0,-5.20858 -3.315345,-9.614594 -7.958982,-11.230262 l -0.03128,-9.980748 z m -3.156642,0 c -22.398612,0 -40.430706,18.031964 -40.430706,40.430406 v 61.835008 c 0,22.39862 18.032094,40.43072 40.430706,40.43072 h 19.026222 c 22.398612,0 40.430715,-18.0321 40.430715,-40.43072 V 74.814902 c 0,-22.398442 -18.032103,-40.430406 -40.430715,-40.430406 z"
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
id="rect4559" />
</g>
<g
style="display:none"
inkscape:label="Left click (1)"
id="layer2"
inkscape:groupmode="layer">
<path
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
d="M 46.23194,44.336396 C 32.052243,49.048938 21.880146,62.386753 21.880146,78.188753 V 101.4958 h 41.619849 v -4.972052 h -2.37874 c -10.504585,0 -19.130733,-8.629161 -19.130733,-19.132555 V 55.9867 c 0,-4.456035 1.625405,-8.462768 4.241418,-11.650304 z"
id="rect4605"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscccsssc" />
</g>
<g
inkscape:label="Middle click (2)"
id="layer3"
inkscape:groupmode="layer"
style="display:none">
<rect
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
id="rect4603"
width="13.080523"
height="29.72846"
x="56.959732"
y="51.570152"
rx="4.7565541"
ry="4.7565541" />
</g>
<g
inkscape:label="Right click (3)"
id="layer4"
inkscape:groupmode="layer"
style="display:none">
<path
sodipodi:nodetypes="cscccsssc"
inkscape:connector-curvature="0"
id="path4664"
d="m 80.768052,44.336396 c 14.179695,4.712542 24.351798,18.050357 24.351798,33.852357 V 101.4958 H 63.499996 v -4.972062 h 2.37874 c 10.504583,0 19.130731,-8.629151 19.130731,-19.132545 V 55.9867 c 0,-4.456035 -1.625405,-8.462768 -4.241415,-11.650304 z"
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.94569;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" />
</g>
<g
inkscape:label="Scroll up (4)"
id="layer5"
inkscape:groupmode="layer"
style="display:inline">
<path
id="path4588"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 53.19098,18.360058 63.533489,8.0175498 73.809009,18.293074 M 63.533489,29.640336 V 8.0175498"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
<g
inkscape:label="Scroll down (5)"
id="layer6"
inkscape:groupmode="layer"
style="display:inline">
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
d="m 53.19098,105.46811 10.342509,10.3425 10.27552,-10.27552 M 63.533489,94.187874 v 21.622736"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4591" />
</g>
<g
inkscape:label="Scroll left (6)"
id="layer7"
inkscape:groupmode="layer"
style="display:none">
<path
id="path4593"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 33.064815,56.637818 22.722307,66.980326 32.997831,77.25584 M 44.345093,66.980326 H 22.722307"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
<g
inkscape:label="Scroll right (7)"
id="layer8"
inkscape:groupmode="layer"
style="display:none">
<path
id="path4595"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:5.94569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 93.935173,77.25584 104.27769,66.913333 94.002157,56.637818 M 82.654895,66.913333 h 21.622795"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
demo/sketch-screen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
demo/ui-diagram.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

107
demo/user-guide.md Normal file
View File

@ -0,0 +1,107 @@
const basicWorkflowTS = [
10, 'Sketching on a plane',
10, 'Extruding a sketch to a solid',
10, 'Sketch on a face of a solid',
10, 'Peforming boolean operation between solids',
]
const editWorkflowTS = [
10, 'opening a file from disk',
10, 'editing an existing sketch',
10, 'accepting the edit and exiting',
]
const exportTS = [
10, 'selecting a body for export',
10, 'initiate export',
10, 'loading exported stl into 3dprint slicer',
10, 'result',
]
s
Turn the shapes you drew into 3D solids
Combine multiple solids to form more complex solids
uplaod your design to a 3d printer
navigation tip
offer to watch three video demos
General Workflow for part creation
Specify a sketch plane
Draw a closed loop shape
Extrude 2D sketch
the program consists of 4 major areas labelled below
Dialog Box
Normally hidden. This box appears when the user is adding or editting a sketch or extrusion
input area: This specifies the extrusion amount
flip icon: This flips the extrusion direction
green check: When clicked the program will proceed with adding or editting a sketch/extrusion
red x: allows the user to bail out of adding or editting a sketch/extrusion
Toolbar
sketch: Initiates a new sketch, before clicking this button, the user must first select a plane, or three points on existing extrusions to define a sketch plane.
extrude: Intiates new extrusion dialog. before clickin gthis button. The user must firs select a sketch to extrude from
boolean add: Creates a new solid that is a boolean union or two selected solids.
boolean subtract: Creates a new solid that is a boolean subtraction of the second selected solid from the first selected solid.
boolean add: Creates a new solid that is a boolean intersection or two selected solids.
new document: Wipes the current workspace and starts a fresh document
save: saves current document. on the inital save the user can specify save location and file name
open: loads an existing document from the local disk.
STL: Exports selected solid to 3d print friendly stl format
extrude: creates a new extrusion from the current sketch.
line: initiates line sketch mode. Subsequent clicks on the canvas define the vertices of the line segment chain.
arc: initiates arc sketch mode. Subsequently, a three click sequence on the canvas spefies the arc shape. The first sets the start point, the seconds the endpoint, and the third the radius.
dimension: allows hte user to add distance or angle constraints to the sketch. When 2 points, or 1 point and 1 line are selected, a distance contraint is added. When two lines are selected, an angle constraint is added
coincident: Adds a coincident contraint between two points, or a line and a point
vertical: adds a vertical constraint the the selected line, or two selected points
horizontal: adds a horizontal constraint the the selected line, or two selected points
tangent: adds a tangent constraint between selected two arcs, or a line and a arc. The selected entities must first between connected by a coicident contraint on their endpoints
User can click this again or escape to exit this mode
Design Tree

View File

View File

BIN
dist/basic-workflow.mp4 vendored Normal file

Binary file not shown.

BIN
dist/export-to-3dprint.mp4 vendored Normal file

Binary file not shown.

BIN
dist/extrude.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

BIN
dist/headphone-stand.json.gz vendored Normal file

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -23,7 +23,7 @@
<div id="stats"></div>
<script src="app.bundle.js"></script>
<script src="scene.bundle.js"></script>
<!-- <script src="solver.js"></script> -->
<script src="solver.js"></script>
<script src="gunzip.min.js"></script>
</body>

BIN
dist/load-file-and-edit.mp4 vendored Normal file

Binary file not shown.

View File

View File

BIN
dist/sculpt.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
dist/site_preview.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View File

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 178 KiB

View File

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

1
dist/solver.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/solver.wasm vendored Normal file

Binary file not shown.

483
extlib/csg-lib.js Normal file
View File

@ -0,0 +1,483 @@
// ## License
//
// Copyright (c) 2011 Evan Wallace (http://madebyevan.com/), under the MIT license.
// THREE.js rework by thrax
// # class CSG
// Holds a binary space partition tree representing a 3D solid. Two solids can
// be combined using the `union()`, `subtract()`, and `intersect()` methods.
class CSG {
constructor() {
this.polygons = [];
}
clone() {
let csg = new CSG();
csg.polygons = this.polygons.map(function(p) {
return p.clone();
});
return csg;
}
toPolygons() {
return this.polygons;
}
union(csg) {
let a = new Node(this.clone().polygons);
let b = new Node(csg.clone().polygons);
a.clipTo(b);
b.clipTo(a);
b.invert();
b.clipTo(a);
b.invert();
a.build(b.allPolygons());
return CSG.fromPolygons(a.allPolygons());
}
subtract(csg) {
let a = new Node(this.clone().polygons);
let b = new Node(csg.clone().polygons);
a.invert();
a.clipTo(b);
b.clipTo(a);
b.invert();
b.clipTo(a);
b.invert();
a.build(b.allPolygons());
a.invert();
return CSG.fromPolygons(a.allPolygons());
}
intersect(csg) {
let a = new Node(this.clone().polygons);
let b = new Node(csg.clone().polygons);
a.invert();
b.clipTo(a);
b.invert();
a.clipTo(b);
b.clipTo(a);
a.build(b.allPolygons());
a.invert();
return CSG.fromPolygons(a.allPolygons());
}
// Return a new CSG solid with solid and empty space switched. This solid is
// not modified.
inverse() {
let csg = this.clone();
csg.polygons.forEach(p=>p.flip());
return csg;
}
}
// Construct a CSG solid from a list of `Polygon` instances.
CSG.fromPolygons=function(polygons) {
let csg = new CSG();
csg.polygons = polygons;
return csg;
}
// # class Vector
// Represents a 3D vector.
//
// Example usage:
//
// new CSG.Vector(1, 2, 3);
class Vector {
constructor(x=0, y=0, z=0) {
this.x=x;
this.y=y;
this.z=z;
}
copy(v){
this.x=v.x;
this.y=v.y;
this.z=v.z;
return this
}
clone() {
return new Vector(this.x,this.y,this.z)
}
negate() {
this.x*=-1;
this.y*=-1;
this.z*=-1;
return this
}
add(a) {
this.x+=a.x
this.y+=a.y
this.z+=a.z
return this;
}
sub(a) {
this.x-=a.x
this.y-=a.y
this.z-=a.z
return this
}
times(a) {
this.x*=a
this.y*=a
this.z*=a
return this
}
dividedBy(a) {
this.x/=a
this.y/=a
this.z/=a
return this
}
lerp(a, t) {
return this.add(tv0.copy(a).sub(this).times(t))
}
unit() {
return this.dividedBy(this.length())
}
length(){
return Math.sqrt((this.x**2)+(this.y**2)+(this.z**2))
}
normalize(){
return this.unit()
}
cross(b) {
let a = this;
const ax = a.x, ay = a.y, az = a.z;
const bx = b.x, by = b.y, bz = b.z;
this.x = ay * bz - az * by;
this.y = az * bx - ax * bz;
this.z = ax * by - ay * bx;
return this;
}
dot(b){
return (this.x*b.x)+(this.y*b.y)+(this.z*b.z)
}
}
//Temporaries used to avoid internal allocation..
let tv0=new Vector()
let tv1=new Vector()
// # class Vertex
// Represents a vertex of a polygon. Use your own vertex class instead of this
// one to provide additional features like texture coordinates and vertex
// colors. Custom vertex classes need to provide a `pos` property and `clone()`,
// `flip()`, and `interpolate()` methods that behave analogous to the ones
// defined by `CSG.Vertex`. This class provides `normal` so convenience
// functions like `CSG.sphere()` can return a smooth vertex normal, but `normal`
// is not used anywhere else.
class Vertex {
constructor(pos, normal, uv, color) {
this.pos = new Vector().copy(pos);
this.normal = new Vector().copy(normal);
this.uv = new Vector().copy(uv);
this.uv.z=0;
color && (this.color = new Vector().copy(color));
}
clone() {
return new Vertex(this.pos,this.normal,this.uv,this.color);
}
// Invert all orientation-specific data (e.g. vertex normal). Called when the
// orientation of a polygon is flipped.
flip() {
this.normal.negate();
}
// Create a new vertex between this vertex and `other` by linearly
// interpolating all properties using a parameter of `t`. Subclasses should
// override this to interpolate additional properties.
interpolate(other, t) {
return new Vertex(this.pos.clone().lerp(other.pos, t),this.normal.clone().lerp(other.normal, t),this.uv.clone().lerp(other.uv, t), this.color&&other.color&&this.color.clone().lerp(other.color,t))
}
}
;
// # class Plane
// Represents a plane in 3D space.
class Plane {
constructor(normal, w) {
this.normal = normal;
this.w = w;
}
clone() {
return new Plane(this.normal.clone(),this.w);
}
flip() {
this.normal.negate();
this.w = -this.w;
}
// Split `polygon` by this plane if needed, then put the polygon or polygon
// fragments in the appropriate lists. Coplanar polygons go into either
// `coplanarFront` or `coplanarBack` depending on their orientation with
// respect to this plane. Polygons in front or in back of this plane go into
// either `front` or `back`.
splitPolygon(polygon, coplanarFront, coplanarBack, front, back) {
const COPLANAR = 0;
const FRONT = 1;
const BACK = 2;
const SPANNING = 3;
// Classify each point as well as the entire polygon into one of the above
// four classes.
let polygonType = 0;
let types = [];
for (let i = 0; i < polygon.vertices.length; i++) {
let t = this.normal.dot(polygon.vertices[i].pos) - this.w;
let type = (t < -Plane.EPSILON) ? BACK : (t > Plane.EPSILON) ? FRONT : COPLANAR;
polygonType |= type;
types.push(type);
}
// Put the polygon in the correct list, splitting it when necessary.
switch (polygonType) {
case COPLANAR:
(this.normal.dot(polygon.plane.normal) > 0 ? coplanarFront : coplanarBack).push(polygon);
break;
case FRONT:
front.push(polygon);
break;
case BACK:
back.push(polygon);
break;
case SPANNING:
let f = []
, b = [];
for (let i = 0; i < polygon.vertices.length; i++) {
let j = (i + 1) % polygon.vertices.length;
let ti = types[i]
, tj = types[j];
let vi = polygon.vertices[i]
, vj = polygon.vertices[j];
if (ti != BACK)
f.push(vi);
if (ti != FRONT)
b.push(ti != BACK ? vi.clone() : vi);
if ((ti | tj) == SPANNING) {
let t = (this.w - this.normal.dot(vi.pos)) / this.normal.dot(tv0.copy(vj.pos).sub(vi.pos));
let v = vi.interpolate(vj, t);
f.push(v);
b.push(v.clone());
}
}
if (f.length >= 3)
front.push(new Polygon(f,polygon.shared));
if (b.length >= 3)
back.push(new Polygon(b,polygon.shared));
break;
}
}
}
// `Plane.EPSILON` is the tolerance used by `splitPolygon()` to decide if a
// point is on the plane.
Plane.EPSILON = 1e-5;
Plane.fromPoints = function(a, b, c) {
let n = tv0.copy(b).sub(a).cross(tv1.copy(c).sub(a)).normalize()
return new Plane(n.clone(),n.dot(a));
}
// # class Polygon
// Represents a convex polygon. The vertices used to initialize a polygon must
// be coplanar and form a convex loop. They do not have to be `Vertex`
// instances but they must behave similarly (duck typing can be used for
// customization).
//
// Each convex polygon has a `shared` property, which is shared between all
// polygons that are clones of each other or were split from the same polygon.
// This can be used to define per-polygon properties (such as surface color).
class Polygon {
constructor(vertices, shared) {
this.vertices = vertices;
this.shared = shared;
this.plane = Plane.fromPoints(vertices[0].pos, vertices[1].pos, vertices[2].pos);
}
clone() {
return new Polygon(this.vertices.map(v=>v.clone()),this.shared);
}
flip() {
this.vertices.reverse().map(v=>v.flip())
this.plane.flip();
}
}
// # class Node
// Holds a node in a BSP tree. A BSP tree is built from a collection of polygons
// by picking a polygon to split along. That polygon (and all other coplanar
// polygons) are added directly to that node and the other polygons are added to
// the front and/or back subtrees. This is not a leafy BSP tree since there is
// no distinction between internal and leaf nodes.
class Node {
constructor(polygons) {
this.plane = null;
this.front = null;
this.back = null;
this.polygons = [];
if (polygons)
this.build(polygons);
}
clone() {
let node = new Node();
node.plane = this.plane && this.plane.clone();
node.front = this.front && this.front.clone();
node.back = this.back && this.back.clone();
node.polygons = this.polygons.map(p=>p.clone());
return node;
}
// Convert solid space to empty space and empty space to solid space.
invert() {
for (let i = 0; i < this.polygons.length; i++)
this.polygons[i].flip();
this.plane && this.plane.flip();
this.front && this.front.invert();
this.back && this.back.invert();
let temp = this.front;
this.front = this.back;
this.back = temp;
}
// Recursively remove all polygons in `polygons` that are inside this BSP
// tree.
clipPolygons(polygons) {
if (!this.plane)
return polygons.slice();
let front = []
, back = [];
for (let i = 0; i < polygons.length; i++) {
this.plane.splitPolygon(polygons[i], front, back, front, back);
}
if (this.front)
front = this.front.clipPolygons(front);
if (this.back)
back = this.back.clipPolygons(back);
else
back = [];
return front.concat(back);
}
// Remove all polygons in this BSP tree that are inside the other BSP tree
// `bsp`.
clipTo(bsp) {
this.polygons = bsp.clipPolygons(this.polygons);
if (this.front)
this.front.clipTo(bsp);
if (this.back)
this.back.clipTo(bsp);
}
// Return a list of all polygons in this BSP tree.
allPolygons() {
let polygons = this.polygons.slice();
if (this.front)
polygons = polygons.concat(this.front.allPolygons());
if (this.back)
polygons = polygons.concat(this.back.allPolygons());
return polygons;
}
// Build a BSP tree out of `polygons`. When called on an existing tree, the
// new polygons are filtered down to the bottom of the tree and become new
// nodes there. Each set of polygons is partitioned using the first polygon
// (no heuristic is used to pick a good split).
build(polygons) {
if (!polygons.length)
return;
if (!this.plane)
this.plane = polygons[0].plane.clone();
let front = []
, back = [];
for (let i = 0; i < polygons.length; i++) {
this.plane.splitPolygon(polygons[i], this.polygons, this.polygons, front, back);
}
if (front.length) {
if (!this.front)
this.front = new Node();
this.front.build(front);
}
if (back.length) {
if (!this.back)
this.back = new Node();
this.back.build(back);
}
}
}
CSG.fromJSON=function(json){
return CSG.fromPolygons(json.polygons.map(p=>new Polygon(p.vertices.map(v=> new Vertex(v.pos,v.normal,v.uv)),p.shared)))
}
export {CSG,Vertex,Vector,Polygon,Plane}
// Return a new CSG solid representing space in either this solid or in the
// solid `csg`. Neither this solid nor the solid `csg` are modified.
//
// A.union(B)
//
// +-------+ +-------+
// | | | |
// | A | | |
// | +--+----+ = | +----+
// +----+--+ | +----+ |
// | B | | |
// | | | |
// +-------+ +-------+
//
// Return a new CSG solid representing space in this solid but not in the
// solid `csg`. Neither this solid nor the solid `csg` are modified.
//
// A.subtract(B)
//
// +-------+ +-------+
// | | | |
// | A | | |
// | +--+----+ = | +--+
// +----+--+ | +----+
// | B |
// | |
// +-------+
//
// Return a new CSG solid representing space both this solid and in the
// solid `csg`. Neither this solid nor the solid `csg` are modified.
//
// A.intersect(B)
//
// +-------+
// | |
// | A |
// | +--+----+ = +--+
// +----+--+ | +--+
// | B |
// | |
// +-------+
//

104
extlib/cubicBezier.js Normal file
View File

@ -0,0 +1,104 @@
/**
* https://github.com/gre/bezier-easing
* BezierEasing - use bezier curve for transition easing function
* by Gaëtan Renaudeau 2014 - 2015 MIT License
*/
// These values are established by empiricism with tests (tradeoff: performance VS precision)
var NEWTON_ITERATIONS = 4;
var NEWTON_MIN_SLOPE = 0.001;
var SUBDIVISION_PRECISION = 0.0000001;
var SUBDIVISION_MAX_ITERATIONS = 10;
var kSplineTableSize = 11;
var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
var float32ArraySupported = typeof Float32Array === 'function';
function A(aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
function B(aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
function C(aA1) { return 3.0 * aA1; }
// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
function calcBezier(aT, aA1, aA2) { return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; }
// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
function getSlope(aT, aA1, aA2) { return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); }
function binarySubdivide(aX, aA, aB, mX1, mX2) {
var currentX, currentT, i = 0;
do {
currentT = aA + (aB - aA) / 2.0;
currentX = calcBezier(currentT, mX1, mX2) - aX;
if (currentX > 0.0) {
aB = currentT;
} else {
aA = currentT;
}
} while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
return currentT;
}
function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) {
for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
var currentSlope = getSlope(aGuessT, mX1, mX2);
if (currentSlope === 0.0) {
return aGuessT;
}
var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
aGuessT -= currentX / currentSlope;
}
return aGuessT;
}
function LinearEasing(x) {
return x;
}
export const Bezier = function (mX1, mY1, mX2, mY2) {
if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) {
throw new Error('bezier x values must be in [0, 1] range');
}
if (mX1 === mY1 && mX2 === mY2) {
return LinearEasing;
}
// Precompute samples table
var sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
for (var i = 0; i < kSplineTableSize; ++i) {
sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
}
function getTForX(aX) {
var intervalStart = 0.0;
var currentSample = 1;
var lastSample = kSplineTableSize - 1;
for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
intervalStart += kSampleStepSize;
}
--currentSample;
// Interpolate to provide an initial guess for t
var dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);
var guessForT = intervalStart + dist * kSampleStepSize;
var initialSlope = getSlope(guessForT, mX1, mX2);
if (initialSlope >= NEWTON_MIN_SLOPE) {
return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
} else if (initialSlope === 0.0) {
return guessForT;
} else {
return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
}
}
return function BezierEasing(x) {
// Because JavaScript number are imprecise, we should guarantee the extremes are right.
if (x === 0 || x === 1) {
return x;
}
return calcBezier(getTForX(x), mY1, mY2);
};
};

168
extlib/stats.module.js Normal file
View File

@ -0,0 +1,168 @@
var Stats = function () {
var mode = 0;
var container = document.createElement('div');
container.style.cssText =
'position:fixed;bottom:0;left:0;cursor:pointer;opacity:0.9;z-index:10000';
container.addEventListener('click', function (event) {
event.preventDefault();
showPanel(++mode % container.children.length);
}, false);
//
function addPanel(panel) {
container.appendChild(panel.dom);
return panel;
}
function showPanel(id) {
for (var i = 0; i < container.children.length; i++) {
container.children[i].style.display = i === id ? 'block' : 'none';
}
mode = id;
}
//
var beginTime = (performance || Date).now(), prevTime = beginTime, frames = 0;
var fpsPanel = addPanel(new Stats.Panel('FPS', '#0ff', '#002'));
var msPanel = addPanel(new Stats.Panel('MS', '#0f0', '#020'));
if (self.performance && self.performance.memory) {
var memPanel = addPanel(new Stats.Panel('MB', '#f08', '#201'));
}
showPanel(0);
return {
REVISION: 16,
dom: container,
addPanel: addPanel,
showPanel: showPanel,
begin: function () {
beginTime = (performance || Date).now();
},
end: function () {
frames++;
var time = (performance || Date).now();
msPanel.update(time - beginTime, 200);
if (time >= prevTime + 1000) {
fpsPanel.update((frames * 1000) / (time - prevTime), 100);
prevTime = time;
frames = 0;
if (memPanel) {
var memory = performance.memory;
memPanel.update(memory.usedJSHeapSize / 1048576, memory.jsHeapSizeLimit / 1048576);
}
}
return time;
},
update: function () {
beginTime = this.end();
},
// Backwards Compatibility
domElement: container,
setMode: showPanel
};
};
Stats.Panel = function (name, fg, bg) {
var min = Infinity, max = 0, round = Math.round;
var PR = round(window.devicePixelRatio || 1);
var WIDTH = 80 * PR, HEIGHT = 48 * PR,
TEXT_X = 3 * PR, TEXT_Y = 2 * PR,
GRAPH_X = 3 * PR, GRAPH_Y = 15 * PR,
GRAPH_WIDTH = 74 * PR, GRAPH_HEIGHT = 30 * PR;
var canvas = document.createElement('canvas');
canvas.width = WIDTH;
canvas.height = HEIGHT;
canvas.style.cssText = 'width:80px;height:48px';
var context = canvas.getContext('2d');
context.font = 'bold ' + (9 * PR) + 'px Helvetica,Arial,sans-serif';
context.textBaseline = 'top';
context.fillStyle = bg;
context.fillRect(0, 0, WIDTH, HEIGHT);
context.fillStyle = fg;
context.fillText(name, TEXT_X, TEXT_Y);
context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT);
context.fillStyle = bg;
context.globalAlpha = 0.9;
context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT);
return {
dom: canvas,
update: function (value, maxValue) {
min = Math.min(min, value);
max = Math.max(max, value);
context.fillStyle = bg;
context.globalAlpha = 1;
context.fillRect(0, 0, WIDTH, GRAPH_Y);
context.fillStyle = fg;
context.fillText(round(value) + ' ' + name + ' (' + round(min) + '-' + round(max) + ')', TEXT_X, TEXT_Y);
context.drawImage(canvas, GRAPH_X + PR, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT, GRAPH_X, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT);
context.fillRect(GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT);
context.fillStyle = bg;
context.globalAlpha = 0.9;
context.fillRect(GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, round((1 - (value / maxValue)) * GRAPH_HEIGHT));
}
};
};
export default Stats;

209
extlib/stl.js Normal file
View File

@ -0,0 +1,209 @@
import {
Vector3
} from '../node_modules/three/src/Three';
/**
* Usage:
* var exporter = new STLExporter();
*
* // second argument is a list of options
* var data = exporter.parse( mesh, { binary: true } );
*
*/
var STLExporter = function () {};
STLExporter.prototype = {
constructor: STLExporter,
parse: function ( scene, options ) {
if ( options === undefined ) options = {};
var binary = options.binary !== undefined ? options.binary : false;
//
var objects = [];
var triangles = 0;
scene.traverse( function ( object ) {
if ( object.isMesh ) {
var geometry = object.geometry;
if ( geometry.isBufferGeometry !== true ) {
throw new Error( 'THREE.STLExporter: Geometry is not of type THREE.BufferGeometry.' );
}
var index = geometry.index;
var positionAttribute = geometry.getAttribute( 'position' );
triangles += ( index !== null ) ? ( index.count / 3 ) : ( positionAttribute.count / 3 );
objects.push( {
object3d: object,
geometry: geometry
} );
}
} );
var output;
var offset = 80; // skip header
if ( binary === true ) {
var bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4;
var arrayBuffer = new ArrayBuffer( bufferLength );
output = new DataView( arrayBuffer );
output.setUint32( offset, triangles, true ); offset += 4;
} else {
output = '';
output += 'solid exported\n';
}
var vA = new Vector3();
var vB = new Vector3();
var vC = new Vector3();
var cb = new Vector3();
var ab = new Vector3();
var normal = new Vector3();
for ( var i = 0, il = objects.length; i < il; i ++ ) {
var object = objects[ i ].object3d;
var geometry = objects[ i ].geometry;
var index = geometry.index;
var positionAttribute = geometry.getAttribute( 'position' );
if ( index !== null ) {
// indexed geometry
for ( var j = 0; j < index.count; j += 3 ) {
var a = index.getX( j + 0 );
var b = index.getX( j + 1 );
var c = index.getX( j + 2 );
writeFace( a, b, c, positionAttribute, object );
}
} else {
// non-indexed geometry
for ( var j = 0; j < positionAttribute.count; j += 3 ) {
var a = j + 0;
var b = j + 1;
var c = j + 2;
writeFace( a, b, c, positionAttribute, object );
}
}
}
if ( binary === false ) {
output += 'endsolid exported\n';
}
return output;
function writeFace( a, b, c, positionAttribute, object ) {
vA.fromBufferAttribute( positionAttribute, a );
vB.fromBufferAttribute( positionAttribute, b );
vC.fromBufferAttribute( positionAttribute, c );
if ( object.isSkinnedMesh === true ) {
object.boneTransform( a, vA );
object.boneTransform( b, vB );
object.boneTransform( c, vC );
}
vA.applyMatrix4( object.matrixWorld );
vB.applyMatrix4( object.matrixWorld );
vC.applyMatrix4( object.matrixWorld );
writeNormal( vA, vB, vC );
writeVertex( vA );
writeVertex( vB );
writeVertex( vC );
if ( binary === true ) {
output.setUint16( offset, 0, true ); offset += 2;
} else {
output += '\t\tendloop\n';
output += '\tendfacet\n';
}
}
function writeNormal( vA, vB, vC ) {
cb.subVectors( vC, vB );
ab.subVectors( vA, vB );
cb.cross( ab ).normalize();
normal.copy( cb ).normalize();
if ( binary === true ) {
output.setFloat32( offset, normal.x, true ); offset += 4;
output.setFloat32( offset, normal.y, true ); offset += 4;
output.setFloat32( offset, normal.z, true ); offset += 4;
} else {
output += '\tfacet normal ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
output += '\t\touter loop\n';
}
}
function writeVertex( vertex ) {
if ( binary === true ) {
output.setFloat32( offset, vertex.x, true ); offset += 4;
output.setFloat32( offset, vertex.y, true ); offset += 4;
output.setFloat32( offset, vertex.z, true ); offset += 4;
} else {
output += '\t\t\tvertex ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
}
}
}
};
export { STLExporter };

200
extlib/three-csg.js Normal file
View File

@ -0,0 +1,200 @@
"use strict"
import * as THREE from '../node_modules/three/src/Three';
import { CSG, Vertex, Polygon } from "./csg-lib.js"
CSG.fromGeometry = function (geom, objectIndex) {
if (!geom.isBufferGeometry) {
console.error("Unsupported CSG input type:" + geom.type)
return
}
let polys = []
let posattr = geom.attributes.position
let normalattr = geom.attributes.normal
let uvattr = geom.attributes.uv
let colorattr = geom.attributes.color
let index;
if (geom.index)
index = geom.index.array;
else {
index = new Array((posattr.array.length / posattr.itemSize) | 0);
for (let i = 0; i < index.length; i++)
index[i] = i
}
let triCount = (index.length / 3) | 0
polys = new Array(triCount)
for (let i = 0, pli = 0, l = index.length; i < l; i += 3,
pli++) {
let vertices = new Array(3)
for (let j = 0; j < 3; j++) {
let vi = index[i + j]
let vp = vi * 3;
let vt = vi * 2;
let x = posattr.array[vp]
let y = posattr.array[vp + 1]
let z = posattr.array[vp + 2]
let nx = normalattr.array[vp]
let ny = normalattr.array[vp + 1]
let nz = normalattr.array[vp + 2]
let u = uvattr.array[vt]
let v = uvattr.array[vt + 1]
vertices[j] = new Vertex({
x,
y,
z
}, {
x: nx,
y: ny,
z: nz
}, {
x: u,
y: v,
z: 0
}, colorattr && { x: colorattr.array[vt], y: colorattr.array[vt + 1], z: colorattr.array[vt + 2] });
}
polys[pli] = new Polygon(vertices, objectIndex)
}
return CSG.fromPolygons(polys)
}
let ttvv0 = new THREE.Vector3()
let tmpm3 = new THREE.Matrix3();
CSG.fromMesh = function (mesh, objectIndex) {
let csg = CSG.fromGeometry(mesh.geometry, objectIndex)
tmpm3.getNormalMatrix(mesh.matrix);
for (let i = 0; i < csg.polygons.length; i++) {
let p = csg.polygons[i]
for (let j = 0; j < p.vertices.length; j++) {
let v = p.vertices[j]
v.pos.copy(ttvv0.copy(v.pos).applyMatrix4(mesh.matrix));
v.normal.copy(ttvv0.copy(v.normal).applyMatrix3(tmpm3))
}
}
return csg;
}
let nbuf3 = (ct) => {
return {
top: 0,
array: new Float32Array(ct),
write: function (v) { (this.array[this.top++] = v.x); (this.array[this.top++] = v.y); (this.array[this.top++] = v.z); }
}
}
let nbuf2 = (ct) => {
return {
top: 0,
array: new Float32Array(ct),
write: function (v) { (this.array[this.top++] = v.x); (this.array[this.top++] = v.y) }
}
}
CSG.toMesh = function (csg, toMatrix, toMaterial) {
let ps = csg.polygons;
let geom;
let g2;
if (0) //Old geometry path...
{
geom = new Geometry();
let vs = geom.vertices;
let fvuv = geom.faceVertexUvs[0]
for (let i = 0; i < ps.length; i++) {
let p = ps[i]
let pvs = p.vertices;
let v0 = vs.length;
let pvlen = pvs.length
for (let j = 0; j < pvlen; j++)
vs.push(new THREE.Vector3().copy(pvs[j].pos))
for (let j = 3; j <= pvlen; j++) {
let fc = new THREE.Face3();
let fuv = []
fvuv.push(fuv)
let fnml = fc.vertexNormals;
fc.a = v0;
fc.b = v0 + j - 2;
fc.c = v0 + j - 1;
fnml.push(new THREE.Vector3().copy(pvs[0].normal))
fnml.push(new THREE.Vector3().copy(pvs[j - 2].normal))
fnml.push(new THREE.Vector3().copy(pvs[j - 1].normal))
fuv.push(new THREE.Vector3().copy(pvs[0].uv))
fuv.push(new THREE.Vector3().copy(pvs[j - 2].uv))
fuv.push(new THREE.Vector3().copy(pvs[j - 1].uv))
fc.normal = new THREE.Vector3().copy(p.plane.normal)
geom.faces.push(fc)
}
}
geom = new THREE.BufferGeometry().fromGeometry(geom)
geom.verticesNeedUpdate = geom.elementsNeedUpdate = geom.normalsNeedUpdate = true;
}
if (1) { //BufferGeometry path
let triCount = 0;
ps.forEach(p => triCount += (p.vertices.length - 2))
geom = new THREE.BufferGeometry()
let vertices = nbuf3(triCount * 3 * 3)
let normals = nbuf3(triCount * 3 * 3)
let uvs = nbuf2(triCount * 2 * 3)
let colors;
let grps = []
ps.forEach(p => {
let pvs = p.vertices
let pvlen = pvs.length
if (p.shared !== undefined) {
if (!grps[p.shared]) grps[p.shared] = []
}
if (pvlen && pvs[0].color !== undefined) {
if (!colors) colors = nbuf3(triCount * 3 * 3);
}
for (let j = 3; j <= pvlen; j++) {
(p.shared !== undefined) && (grps[p.shared].push(vertices.top / 3, (vertices.top / 3) + 1, (vertices.top / 3) + 2));
vertices.write(pvs[0].pos)
vertices.write(pvs[j - 2].pos)
vertices.write(pvs[j - 1].pos)
normals.write(pvs[0].normal)
normals.write(pvs[j - 2].normal)
normals.write(pvs[j - 1].normal)
uvs.write(pvs[0].uv)
uvs.write(pvs[j - 2].uv)
uvs.write(pvs[j - 1].uv)
colors && (colors.write(pvs[0].color) || colors.write(pvs[j - 2].color) || colors.write(pvs[j - 1].color))
}
}
)
geom.setAttribute('position', new THREE.BufferAttribute(vertices.array, 3));
geom.setAttribute('normal', new THREE.BufferAttribute(normals.array, 3));
geom.setAttribute('uv', new THREE.BufferAttribute(uvs.array, 2));
colors && geom.setAttribute('color', new THREE.BufferAttribute(colors.array, 3));
if (grps.length) {
let index = []
let gbase = 0;
for (let gi = 0; gi < grps.length; gi++) {
geom.addGroup(gbase, grps[gi].length, gi)
gbase += grps[gi].length
index = index.concat(grps[gi]);
}
geom.setIndex(index)
}
g2 = geom;
}
let inv = new THREE.Matrix4().copy(toMatrix).invert();
geom.applyMatrix4(inv);
geom.computeBoundingSphere();
geom.computeBoundingBox();
let m = new THREE.Mesh(geom, toMaterial);
m.matrix.copy(toMatrix);
m.matrix.decompose(m.position, m.quaternion, m.scale)
m.rotation.setFromQuaternion(m.quaternion)
m.updateMatrixWorld();
m.castShadow = m.receiveShadow = true;
return m
}
export default CSG

759
extlib/trackball.js Normal file
View File

@ -0,0 +1,759 @@
import {
EventDispatcher,
MOUSE,
Quaternion,
Vector2,
Vector3
} from '../node_modules/three/src/Three';
var TrackballControls = function ( object, domElement ) {
if ( domElement === undefined ) console.warn( 'THREE.TrackballControls: The second parameter "domElement" is now mandatory.' );
if ( domElement === document ) console.error( 'THREE.TrackballControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' );
var scope = this;
var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
this.object = object;
this.domElement = domElement;
// API
this.enabled = true;
this.screen = { left: 0, top: 0, width: 0, height: 0 };
this.rotateSpeed = 3.0;
this.zoomSpeed = 1.2;
this.panSpeed = 2;
this.noRotate = false;
this.noZoom = false;
this.noPan = false;
this.staticMoving = true;
this.dynamicDampingFactor = 0.2;
this.minDistance = 0;
this.maxDistance = Infinity;
this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
this.mouseButtons = { LEFT: null, MIDDLE: MOUSE.PAN, RIGHT: MOUSE.ROTATE };
// internals
this.target = new Vector3();
var EPS = 0.000001;
var lastPosition = new Vector3();
var lastZoom = 1;
var _state = STATE.NONE,
_keyState = STATE.NONE,
_eye = new Vector3(),
_movePrev = new Vector2(),
_moveCurr = new Vector2(),
_lastAxis = new Vector3(),
_lastAngle = 0,
_zoomStart = new Vector2(),
_zoomEnd = new Vector2(),
_touchZoomDistanceStart = 0,
_touchZoomDistanceEnd = 0,
_panStart = new Vector2(),
_panEnd = new Vector2();
// for reset
this.target0 = this.target.clone();
this.position0 = this.object.position.clone();
this.up0 = this.object.up.clone();
this.zoom0 = this.object.zoom;
// events
var changeEvent = { type: 'change' };
var startEvent = { type: 'start' };
var endEvent = { type: 'end' };
// methods
this.handleResize = function () {
var box = scope.domElement.getBoundingClientRect();
// adjustments come from similar code in the jquery offset() function
var d = scope.domElement.ownerDocument.documentElement;
scope.screen.left = box.left + window.pageXOffset - d.clientLeft;
scope.screen.top = box.top + window.pageYOffset - d.clientTop;
scope.screen.width = box.width;
scope.screen.height = box.height;
};
var getMouseOnScreen = ( function () {
var vector = new Vector2();
return function getMouseOnScreen( pageX, pageY ) {
vector.set(
( pageX - scope.screen.left ) / scope.screen.width,
( pageY - scope.screen.top ) / scope.screen.height
);
return vector;
};
}() );
var getMouseOnCircle = ( function () {
var vector = new Vector2();
return function getMouseOnCircle( pageX, pageY ) {
vector.set(
( ( pageX - scope.screen.width * 0.5 - scope.screen.left ) / ( scope.screen.width * 0.5 ) ),
( ( scope.screen.height + 2 * ( scope.screen.top - pageY ) ) / scope.screen.width ) // screen.width intentional
);
return vector;
};
}() );
this.rotateCamera = ( function () {
var axis = new Vector3(),
quaternion = new Quaternion(),
eyeDirection = new Vector3(),
objectUpDirection = new Vector3(),
objectSidewaysDirection = new Vector3(),
moveDirection = new Vector3(),
angle;
return function rotateCamera() {
moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );
angle = moveDirection.length();
if ( angle ) {
_eye.copy( scope.object.position ).sub( scope.target );
eyeDirection.copy( _eye ).normalize();
objectUpDirection.copy( scope.object.up ).normalize();
objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize();
objectUpDirection.setLength( _moveCurr.y - _movePrev.y );
objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x );
moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) );
axis.crossVectors( moveDirection, _eye ).normalize();
angle *= scope.rotateSpeed;
quaternion.setFromAxisAngle( axis, angle );
_eye.applyQuaternion( quaternion );
scope.object.up.applyQuaternion( quaternion );
_lastAxis.copy( axis );
_lastAngle = angle;
} else if ( ! scope.staticMoving && _lastAngle ) {
_lastAngle *= Math.sqrt( 1.0 - scope.dynamicDampingFactor );
_eye.copy( scope.object.position ).sub( scope.target );
quaternion.setFromAxisAngle( _lastAxis, _lastAngle );
_eye.applyQuaternion( quaternion );
scope.object.up.applyQuaternion( quaternion );
}
_movePrev.copy( _moveCurr );
};
}() );
this.zoomCamera = function () {
var factor;
if ( _state === STATE.TOUCH_ZOOM_PAN ) {
factor = _touchZoomDistanceEnd / _touchZoomDistanceStart;
_touchZoomDistanceStart = _touchZoomDistanceEnd;
if ( scope.object.isPerspectiveCamera ) {
_eye.multiplyScalar( factor );
} else if ( scope.object.isOrthographicCamera ) {
scope.object.zoom *= factor;
scope.object.updateProjectionMatrix();
} else {
console.warn( 'THREE.TrackballControls: Unsupported camera type' );
}
} else {
factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * scope.zoomSpeed;
if ( factor !== 1.0 && factor > 0.0 ) {
if ( scope.object.isPerspectiveCamera ) {
_eye.multiplyScalar( factor );
} else if ( scope.object.isOrthographicCamera ) {
scope.object.zoom /= factor;
scope.object.updateProjectionMatrix();
} else {
console.warn( 'THREE.TrackballControls: Unsupported camera type' );
}
}
if ( scope.staticMoving ) {
_zoomStart.copy( _zoomEnd );
} else {
_zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
}
}
};
this.panCamera = ( function () {
var mouseChange = new Vector2(),
objectUp = new Vector3(),
pan = new Vector3();
return function panCamera() {
mouseChange.copy( _panEnd ).sub( _panStart );
if ( mouseChange.lengthSq() ) {
if ( scope.object.isOrthographicCamera ) {
var scale_x = ( scope.object.right - scope.object.left ) / scope.object.zoom / scope.domElement.clientWidth;
var scale_y = ( scope.object.top - scope.object.bottom ) / scope.object.zoom / scope.domElement.clientWidth;
mouseChange.x *= scale_x;
mouseChange.y *= scale_y;
}
// mouseChange.multiplyScalar( _eye.length() * scope.panSpeed );
mouseChange.multiplyScalar( _eye.length() * 1/577*scope.domElement.clientWidth);
pan.copy( _eye ).cross( scope.object.up ).setLength( mouseChange.x );
pan.add( objectUp.copy( scope.object.up ).setLength( mouseChange.y ) );
scope.object.position.add( pan );
scope.target.add( pan );
if ( scope.staticMoving ) {
_panStart.copy( _panEnd );
} else {
_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( scope.dynamicDampingFactor ) );
}
}
};
}() );
this.checkDistances = function () {
if ( ! scope.noZoom || ! scope.noPan ) {
if ( _eye.lengthSq() > scope.maxDistance * scope.maxDistance ) {
scope.object.position.addVectors( scope.target, _eye.setLength( scope.maxDistance ) );
_zoomStart.copy( _zoomEnd );
}
if ( _eye.lengthSq() < scope.minDistance * scope.minDistance ) {
scope.object.position.addVectors( scope.target, _eye.setLength( scope.minDistance ) );
_zoomStart.copy( _zoomEnd );
}
}
};
this.update = function () {
_eye.subVectors( scope.object.position, scope.target );
if ( ! scope.noRotate ) {
scope.rotateCamera();
}
if ( ! scope.noZoom ) {
scope.zoomCamera();
}
if ( ! scope.noPan ) {
scope.panCamera();
}
scope.object.position.addVectors( scope.target, _eye );
if ( scope.object.isPerspectiveCamera ) {
scope.checkDistances();
scope.object.lookAt( scope.target );
if ( lastPosition.distanceToSquared( scope.object.position ) > EPS ) {
scope.dispatchEvent( changeEvent );
lastPosition.copy( scope.object.position );
}
} else if ( scope.object.isOrthographicCamera ) {
scope.object.lookAt( scope.target );
if ( lastPosition.distanceToSquared( scope.object.position ) > EPS || lastZoom !== scope.object.zoom ) {
scope.dispatchEvent( changeEvent );
lastPosition.copy( scope.object.position );
lastZoom = scope.object.zoom;
}
} else {
console.warn( 'THREE.TrackballControls: Unsupported camera type' );
}
};
this.reset = function () {
_state = STATE.NONE;
_keyState = STATE.NONE;
scope.target.copy( scope.target0 );
scope.object.position.copy( scope.position0 );
scope.object.up.copy( scope.up0 );
scope.object.zoom = scope.zoom0;
scope.object.updateProjectionMatrix();
_eye.subVectors( scope.object.position, scope.target );
scope.object.lookAt( scope.target );
scope.dispatchEvent( changeEvent );
lastPosition.copy( scope.object.position );
lastZoom = scope.object.zoom;
};
// listeners
function onPointerDown( event ) {
if ( scope.enabled === false ) return;
switch ( event.pointerType ) {
case 'mouse':
case 'pen':
onMouseDown( event );
break;
// TODO touch
}
}
function onPointerMove( event ) {
if ( scope.enabled === false ) return;
switch ( event.pointerType ) {
case 'mouse':
case 'pen':
onMouseMove( event );
break;
// TODO touch
}
}
function onPointerUp( event ) {
if ( scope.enabled === false ) return;
switch ( event.pointerType ) {
case 'mouse':
case 'pen':
onMouseUp( event );
break;
// TODO touch
}
}
function keydown( event ) {
if ( scope.enabled === false ) return;
window.removeEventListener( 'keydown', keydown );
if ( _keyState !== STATE.NONE ) {
return;
} else if ( event.keyCode === scope.keys[ STATE.ROTATE ] && ! scope.noRotate ) {
_keyState = STATE.ROTATE;
} else if ( event.keyCode === scope.keys[ STATE.ZOOM ] && ! scope.noZoom ) {
_keyState = STATE.ZOOM;
} else if ( event.keyCode === scope.keys[ STATE.PAN ] && ! scope.noPan ) {
_keyState = STATE.PAN;
}
}
function keyup() {
if ( scope.enabled === false ) return;
_keyState = STATE.NONE;
window.addEventListener( 'keydown', keydown );
}
function onMouseDown( event ) {
event.preventDefault();
event.stopPropagation();
if ( _state === STATE.NONE ) {
switch ( event.button ) {
case 0:
_state = scope.mouseButtons.LEFT;
break;
case 1:
_state = scope.mouseButtons.MIDDLE;
break;
case 2:
if (event.ctrlKey) {
_state = scope.mouseButtons.MIDDLE;
} else {
_state = scope.mouseButtons.RIGHT;
}
break;
default:
_state = STATE.NONE;
}
}
var state = ( _keyState !== STATE.NONE ) ? _keyState : _state;
if ( state === STATE.ROTATE && ! scope.noRotate ) {
_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
_movePrev.copy( _moveCurr );
} else if ( state === STATE.ZOOM && ! scope.noZoom ) {
_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
_zoomEnd.copy( _zoomStart );
} else if ( state === STATE.PAN && ! scope.noPan ) {
_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
_panEnd.copy( _panStart );
}
scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
scope.dispatchEvent( startEvent );
}
function onMouseMove( event ) {
if ( scope.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
var state = ( _keyState !== STATE.NONE ) ? _keyState : _state;
if ( state === STATE.ROTATE && ! scope.noRotate ) {
_movePrev.copy( _moveCurr );
_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
} else if ( state === STATE.ZOOM && ! scope.noZoom ) {
_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
} else if ( state === STATE.PAN && ! scope.noPan ) {
_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
}
scope.update()
}
function onMouseUp( event ) {
if ( scope.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
_state = STATE.NONE;
scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
scope.dispatchEvent( endEvent );
}
function mousewheel( event ) {
if ( scope.enabled === false ) return;
if ( scope.noZoom === true ) return;
event.preventDefault();
event.stopPropagation();
switch ( event.deltaMode ) {
case 2:
// Zoom in pages
_zoomStart.y -= event.deltaY * 0.025;
break;
case 1:
// Zoom in lines
_zoomStart.y -= event.deltaY * 0.01;
break;
default:
// undefined, 0, assume pixels
_zoomStart.y -= event.deltaY * 0.00025;
break;
}
scope.update()
scope.dispatchEvent( startEvent );
scope.dispatchEvent( endEvent );
}
function touchstart( event ) {
if ( scope.enabled === false ) return;
event.preventDefault();
switch ( event.touches.length ) {
case 1:
_state = STATE.TOUCH_ROTATE;
_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
_movePrev.copy( _moveCurr );
break;
default: // 2 or more
_state = STATE.TOUCH_ZOOM_PAN;
var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
_panStart.copy( getMouseOnScreen( x, y ) );
_panEnd.copy( _panStart );
break;
}
scope.dispatchEvent( startEvent );
}
function touchmove( event ) {
if ( scope.enabled === false ) return;
event.preventDefault();
event.stopPropagation();
switch ( event.touches.length ) {
case 1:
_movePrev.copy( _moveCurr );
_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
break;
default: // 2 or more
var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
_panEnd.copy( getMouseOnScreen( x, y ) );
break;
}
scope.update()
}
function touchend( event ) {
if ( scope.enabled === false ) return;
switch ( event.touches.length ) {
case 0:
_state = STATE.NONE;
break;
case 1:
_state = STATE.TOUCH_ROTATE;
_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
_movePrev.copy( _moveCurr );
break;
}
scope.dispatchEvent( endEvent );
}
function contextmenu( event ) {
if ( scope.enabled === false ) return;
event.preventDefault();
}
this.dispose = function () {
scope.domElement.removeEventListener( 'contextmenu', contextmenu );
scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
scope.domElement.removeEventListener( 'wheel', mousewheel );
scope.domElement.removeEventListener( 'touchstart', touchstart );
scope.domElement.removeEventListener( 'touchend', touchend );
scope.domElement.removeEventListener( 'touchmove', touchmove );
scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
window.removeEventListener( 'keydown', keydown );
window.removeEventListener( 'keyup', keyup );
};
this.domElement.addEventListener( 'contextmenu', contextmenu );
this.domElement.addEventListener( 'pointerdown', onPointerDown );
this.domElement.addEventListener( 'wheel', mousewheel );
this.domElement.addEventListener( 'touchstart', touchstart );
this.domElement.addEventListener( 'touchend', touchend );
this.domElement.addEventListener( 'touchmove', touchmove );
this.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
this.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
window.addEventListener( 'keydown', keydown );
window.addEventListener( 'keyup', keyup );
this.handleResize();
// force an update at start
this.update();
};
TrackballControls.prototype = Object.create( EventDispatcher.prototype );
TrackballControls.prototype.constructor = TrackballControls;
export { TrackballControls };

28
https/localhost-key.pem Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDyMGwhoISvPn3Q
QBJbSHZSTM8mGgK4DwY0REvnzvZPycGOdqBRumPqDExUmDGZehDvPB9KS5rITIac
sDe/IkNB438tyvjxpwT959G0DaGf282/KsT1V7NlkHp6voP5NfzJLl4h2suzzTrF
bYiftcaTn86PhaTpHnInBOiNrDcOv3vJmDn0fUICiGD3m0q6i7G3dsNuJDCMOXMi
oCL46g4WIUiLU3uTfhHaKzDsUW+gKu6Q0sEwVd1GzTz7S4Xde77hUAjapHOFuFT8
D8WF4Ze7pZNfKx3CnQmY3dyHWjZu0GgQuypF2IXk93Q9IYts3U3phq0WzPcq4L3d
6qVsZsbbAgMBAAECggEAa5QUxA8gQROaIUIEpWWXoVEbBsqxAH8z+02HBg4JnUF6
Z8TLy+HmddVGpqEADzOIiCwFniPdOjG77afc61rV01Oxb27ki7rr3bj2jmsrqu2h
A9SErpJpTqkRrqonxzAy/E5LY/BjYZe9DmtsL7032uU2hMwRh7eNb0Wf4yZnQnXw
2aGajqF7i1R50B1uBlh/EeS+3+nR9O5YSi9abyHsYxGz8l+wSvA5uLv0dkP7xWBb
8PmMN87wEbZDV4jJyyJw4VhaFvMgjwwboTDcOgOnrGOAN31991LtBAt6ypSeOndo
Tvl4xfYA1Gs6mgCx+LtRnSoPVKj3ziLw/tdezgsT4QKBgQD4YizViNoD4HqwnDdQ
NopSMSw0gJGRw4NFvAm1Ci2WjOv1cBQaorRwu+nYfyaRlkaHcG3dHr24DW4VcUY8
VnZBRq6SvmmuXCenHXiXOykWFXFfxZSJT1svfllpAXdAPcQm5luIIYV/eGg8gBJt
OjECNFYObDMGrM03A2G3i+jxUQKBgQD5nZ8Lz5ANhZd9DEu7hJcIiBh6m7Z3JujW
U9DTDvZ51MzThgJRC2A6dU8mcJfZo3Wa+Pv1xsz0OjjG+83bMNJB0OVff5laaU50
eApOp5XsNHGzcjYoxSxxztCd7UFtf4Bu33yGDN91B8WQY1c++BpZQ4XCG8AKFzdI
HqQAAaDKawKBgQCzRvFDYxaxK6qCpQ6LmAI4lwNoFdB8HFk40SNUh7cl7is1qSLp
oryIjimYORZWiNf5VB4INvMK0K6/TVY7oNCUBvdkNYnD7wIz7eKnjWz3YpzFWq/+
d8fCPPk+AG/Zb3uP9D7mwANCYV8jI/Go4xKSm8HtgQ1HaRxp88fpGlQVMQKBgQD3
uAxR/VAZiz2WtPAnjWMR7XZVn1iKkQu7P/zaqFvE9oG7XZ/I7EA4Y5kELfMU4tpg
zL3H4N4fdfRIzTYzVBUliflIN+ppxl48ybB49Gmdu0Incq368gq0eymfwQgQcdt0
rMf4hKfyjZ7sNxorfK8xbQg+ZanEmdub8ASTmQoINwKBgHnT+FJyuhvrcnMMhS4Q
G8wvL1gbnQCBUd8+ouc9vbfE8eXFQVyGuqjToPQcKxl9rjha4X9gNw9yWa5zxOhX
5LEmewUMo1LfaryhBt08Mc2CeIbFTEveqj3Ajhn1t9wW03X7+8A8E0sPBLzpDnr0
yRyKZKdn91/5P6r1MztY2LQh
-----END PRIVATE KEY-----

24
https/localhost.pem Normal file
View File

@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIID9DCCAlygAwIBAgIQKfKuWsppHxEm8FuAqgxhpjANBgkqhkiG9w0BAQsFADBP
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExEjAQBgNVBAsMCWhvd2Fy
ZEBocDEZMBcGA1UEAwwQbWtjZXJ0IGhvd2FyZEBocDAeFw0yMTA0MTgwNjIxMjZa
Fw0yMzA3MTgwNjIxMjZaMD0xJzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBj
ZXJ0aWZpY2F0ZTESMBAGA1UECwwJaG93YXJkQGhwMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEA8jBsIaCErz590EASW0h2UkzPJhoCuA8GNERL5872T8nB
jnagUbpj6gxMVJgxmXoQ7zwfSkuayEyGnLA3vyJDQeN/Lcr48acE/efRtA2hn9vN
vyrE9VezZZB6er6D+TX8yS5eIdrLs806xW2In7XGk5/Oj4Wk6R5yJwTojaw3Dr97
yZg59H1CAohg95tKuouxt3bDbiQwjDlzIqAi+OoOFiFIi1N7k34R2isw7FFvoCru
kNLBMFXdRs08+0uF3Xu+4VAI2qRzhbhU/A/FheGXu6WTXysdwp0JmN3ch1o2btBo
ELsqRdiF5Pd0PSGLbN1N6YatFsz3KuC93eqlbGbG2wIDAQABo14wXDAOBgNVHQ8B
Af8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHwYDVR0jBBgwFoAU1LipvY+p
DhxjE8UP8QpCiAfmI3kwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEB
CwUAA4IBgQAaGHY+H63/Q7MQmRyKG3eTaW8al2pzd7MejiNSDt9R+2KeiMwmzvC8
OlslfNviatLfMqaOA5WrdpifblVRqjXZyblqeaswlA5S0gzx4JLr7yKtb4FVlwpa
Iv3/cOJB0HXEhJoWKTSKAFXgjqxUSaRbSX2tQRiRNE72shc9J5cYP3AMCloC3PUG
pbEyo+08cEHIUoZBMmjSFB2cB8JQijs3iDSCCGILCzjV0/33I0RfoFWIZZPIYFON
1zDYmaXWmpd7GAsl1rHE9o835HnyqGFy+IOovxVufSqzzRX8JlOzCzKioIfq4EjC
FLpNlZ0snDovZ6AmmH3UL1Nk2N/0WaLrrgnr58qtBqao1x1DdhcjGymjPFRyqItI
4yNnlKpaYHk5W/Z8zm8Pb1b/tCBmdlFyYyBmqkRSOqcwS/eGmV9BFZJrdU1XM4fH
0kyIOt9bDZcZWvwOcD94TUz9FNu18GDUhqBrqPAYSMlaJpe60pPiPcsE21/2usqi
H6s/L19rZxE=
-----END CERTIFICATE-----

26
https/rootCA.pem Normal file
View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEbjCCAtagAwIBAgIRAKm5AjBIhGb5Ln0os/kCDC4wDQYJKoZIhvcNAQELBQAw
TzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMRIwEAYDVQQLDAlob3dh
cmRAaHAxGTAXBgNVBAMMEG1rY2VydCBob3dhcmRAaHAwHhcNMjEwNDE4MDYxNTM5
WhcNMzEwNDE4MDYxNTM5WjBPMR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQg
Q0ExEjAQBgNVBAsMCWhvd2FyZEBocDEZMBcGA1UEAwwQbWtjZXJ0IGhvd2FyZEBo
cDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKhLnt2Krsa5m+NqqjjX
J5SF9Nm0SGWI89g6nRiJVc2guKFZDXiV0xDz9SFj8Md5ZlX71MtO/3ACx67/VgN4
As5+yFDEl6ulvesjZR81Xu2aGnR602SmL8Y3Q6sZUTvB3qgjQJExmEzv7ypo6PNX
Uh8Hj1/7qviHsGE8nYn7jfiy8eSnwq57p67UCFKvahBmUMEMHythcXq/zcWUJ5Dw
qjiQJNLUFcIN3Hl7J8QNtskds1Zt+N9TLS8my+cE91JG8T1JnwOn/zWJ1cnTEdls
yQIfbb2/INlkyuTvPkJHKggCrDzmVCxhLpD2aFQ2Qu8RtjmbNN/B7YEUJP8SLrv7
lWUV7Ic5HQmS+/q27TXOm4z8HWX1GlCzoaj5VyLaPZf62eRIBunGXcvp1GcXLbiy
GCo6+Tz7RiwBX3DpH70Rz8pbz9R/LOPLa2uhlB+r7oCxpqTWrl96l+gxohfnntti
adE5cZDS8/0ITgjXcPAezNHELlJYJSuIewOVzEOr9BYpOQIDAQABo0UwQzAOBgNV
HQ8BAf8EBAMCAgQwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU1LipvY+p
DhxjE8UP8QpCiAfmI3kwDQYJKoZIhvcNAQELBQADggGBAAUDatXb+z8Fb9hz8CHX
CNrHXlppy6/gQvVdQ02SkFVCOqemVCdZPUCM3jAUciXZJapHQNiTam8lTi6muC9m
fHYv1xBXoWc/S7Y8BOpce1R76QEMwEHfqNetquAlFgLmmTuESXMUi1eJJobvS2zS
QLqYfx8AUkZPqDHQnJ5ZVBYqKPFTN9NKg0iR/UHJSt3tUOMyVnkx5lMRZFrUEue1
l+twzi0+Lhx11Sjx69kDd8qtGYvedcxKacR722LdiR8/YoHFoa3va/CBmLFH63oJ
k+10wNhm7eiubOaBvVit+uORS2ur26/1vFF72TLFTtXCF3mDG8P/6HB0fPzXRliI
cXdoO5+955KS6p+ZmjoMY37NNsnIZ0q3Zd6gj3I+dvhnW1XysDCEWsAiI0BQqC9d
AeZ3LqBbHIyJBantXQqpmAq9+vrYe/oUq0pwhC4cMwpAwE5pvGZgN0nt6acwrr5i
dLW6a1E571sfFFj2zC20kjwL3Sg9E2jSbMFOIiJopdT39Q==
-----END CERTIFICATE-----

89
icon/extrude_master.svg Normal file
View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg1011"
width="512"
height="512"
viewBox="0 0 512 512"
sodipodi:docname="extrude_master.svg"
inkscape:version="1.0.2 (1.0.2+r75+1)">
<metadata
id="metadata1017">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs1015">
<marker
style="overflow:visible"
id="TriangleOutS"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="TriangleOutS"
inkscape:isstock="true">
<path
transform="scale(0.2)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
id="path1864" />
</marker>
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1388"
inkscape:window-height="925"
id="namedview1013"
showgrid="false"
inkscape:zoom="0.99748433"
inkscape:cx="33.096245"
inkscape:cy="336.19496"
inkscape:window-x="867"
inkscape:window-y="417"
inkscape:window-maximized="0"
inkscape:current-layer="svg1011"
inkscape:snap-global="true"
inkscape:document-rotation="0" />
<g
inkscape:groupmode="layer"
inkscape:label="Image"
id="g1019" />
<path
id="path941"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.71671808;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
d="M 256,0 144,144.00007 h 64 V 384 h 96 V 144.80193 l 64,-1.60386 z"
sodipodi:nodetypes="cccccccc" />
<path
style="fill:none;stroke:#000000;stroke-width:32;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 256,288 16,384 256,496 496,384 Z"
id="path840"
sodipodi:nodetypes="ccccc" />
<rect
style="fill:#000000;fill-opacity:1;stroke-width:32.8023;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.716718"
id="rect873"
width="160"
height="158.28497"
x="176"
y="223.93156" />
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
icon/icon-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

BIN
icon/icon-24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

BIN
icon/icon-32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 B

BIN
icon/icon-64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

98
icon/icon-text.svg Normal file
View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="452.45901"
height="96"
viewBox="0 0 452.45901 96.000008"
version="1.1"
id="svg2112"
inkscape:version="1.0.2 (1.0.2+r75+1)"
sodipodi:docname="icon-text.svg">
<defs
id="defs2106">
<rect
x="645.90955"
y="45.977581"
width="248.2307"
height="71.300766"
id="rect943" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.5149474"
inkscape:cx="218.61618"
inkscape:cy="175.47211"
inkscape:document-units="px"
inkscape:current-layer="g2625"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="1747"
inkscape:window-height="1199"
inkscape:window-x="729"
inkscape:window-y="154"
inkscape:window-maximized="0"
units="px" />
<metadata
id="metadata2109">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
id="g2625"
transform="translate(46.477595,53.03882)">
<g
id="g842"
transform="matrix(0.17281172,0,0,0.17281172,-21.424361,-37.007371)">
<g
id="g921"
transform="translate(-36.094691,-12.655916)">
<path
style="fill:#34d399;fill-opacity:0.698039;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 51.316614,84.370759 164.499996,-95.000008 164.5,95.000008 -164.5,95.000041 z"
id="path2578"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#34d399;fill-opacity:0.698039;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 401.16781,121 0.0224,189.96118 -164.52241,94.96118 -0.0224,-189.96118 z"
id="path2578-3"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#34d399;fill-opacity:0.698039;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 194.52241,405.92236 30,310.96118 30.022413,121 194.54483,215.96118 Z"
id="path2578-6"
sodipodi:nodetypes="ccccc" />
</g>
</g>
<text
xml:space="preserve"
id="text941"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect943);fill:#000000;fill-opacity:1;stroke:none;"
transform="matrix(1.8120726,0,0,1.8120726,-1109.4801,-131.27905)"><tspan
x="645.91016"
y="83.286208"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono'">three.cad</tspan></tspan></text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

103
icon/icon.svg Normal file
View File

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 24 24"
viewBox="0 0 24 24"
fill="black"
width="24px"
height="24px"
version="1.1"
id="svg26"
sodipodi:docname="icon.svg"
inkscape:version="1.0.2 (1.0.2+r75+1)">
<metadata
id="metadata32">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs30" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1623"
inkscape:window-height="1236"
id="namedview28"
showgrid="false"
inkscape:zoom="21.184428"
inkscape:cx="16.030816"
inkscape:cy="15.296979"
inkscape:window-x="426"
inkscape:window-y="92"
inkscape:window-maximized="0"
inkscape:current-layer="svg26"
inkscape:document-rotation="0"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
position="-3.6819497,21.6"
orientation="0,1"
id="guide842"
inkscape:label=""
inkscape:locked="false"
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="-1.0857031,2.4"
orientation="0,1"
id="guide846"
inkscape:label=""
inkscape:locked="false"
inkscape:color="rgb(0,0,255)" />
</sodipodi:namedview>
<circle
style="fill:#a6a6a6;stroke-width:0.05;stroke-linecap:round"
id="path927"
cx="12"
cy="12"
r="12" />
<g
id="g875"
transform="matrix(1.2,0,0,1.2,-2.4,-2.4)">
<g
id="g868"
style="fill:#5ccff0;fill-opacity:1">
<polygon
opacity=".3"
points="13,17.17 17,14.87 17,10.24 13,12.57 "
id="polygon6"
style="opacity:1;fill:#5ccff0;fill-opacity:1" />
<polygon
opacity=".3"
points="12,6.25 8.04,8.53 12,10.84 15.96,8.53 "
id="polygon8"
style="opacity:1;fill:#5ccff0;fill-opacity:1" />
<polygon
opacity=".3"
points="7,14.87 11,17.17 11,12.57 7,10.24 "
id="polygon10"
style="opacity:1;fill:#5ccff0;fill-opacity:1" />
</g>
<path
d="M 19,14.87 V 9.13 C 19,8.41 18.62,7.75 18,7.4 L 13,4.52 C 12.69,4.34 12.35,4.25 12,4.25 c -0.35,0 -0.69,0.09 -1,0.27 L 6,7.39 C 5.38,7.75 5,8.41 5,9.13 v 5.74 c 0,0.72 0.38,1.38 1,1.73 l 5,2.88 c 0.31,0.18 0.65,0.27 1,0.27 0.35,0 0.69,-0.09 1,-0.27 l 5,-2.88 c 0.62,-0.35 1,-1.01 1,-1.73 z m -8,2.3 -4,-2.3 v -4.63 l 4,2.33 z M 12,10.84 8.04,8.53 12,6.25 15.96,8.53 Z m 5,4.03 -4,2.3 v -4.6 l 4,-2.33 z"
id="path20" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

83
icon/icon2.svg Normal file
View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 511.99999 512.00002"
version="1.1"
id="svg2112"
inkscape:version="1.0.2 (1.0.2+r75+1)"
sodipodi:docname="icon2.svg">
<defs
id="defs2106" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.46475524"
inkscape:cx="27.339669"
inkscape:cy="128.43857"
inkscape:document-units="px"
inkscape:current-layer="g2625"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="1514"
inkscape:window-height="1199"
inkscape:window-x="705"
inkscape:window-y="83"
inkscape:window-maximized="0"
units="px" />
<metadata
id="metadata2109">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
id="g2625"
transform="translate(46.477595,53.03882)">
<g
id="g842"
transform="matrix(1.1095676,0,0,1.1095676,10.354561,-2.2984399)">
<g
id="g921"
transform="translate(-36.094691,-12.655916)">
<path
style="fill:#10b981;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 51.316614,84.370759 164.499996,-95.000008 164.5,95.000008 -164.5,95.000041 z"
id="path2578"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#10b981;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 401.16781,121 0.0224,189.96118 -164.52241,94.96118 -0.0224,-189.96118 z"
id="path2578-3"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#10b981;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 194.52241,405.92236 30,310.96118 30.022413,121 194.54483,215.96118 Z"
id="path2578-6"
sodipodi:nodetypes="ccccc" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

124
icon/icon_text.svg Normal file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="452.45901"
height="96"
viewBox="0 0 452.45901 96.000008"
version="1.1"
id="svg2112"
inkscape:version="1.0.2 (1.0.2+r75+1)"
sodipodi:docname="icon_text.svg">
<defs
id="defs2106">
<rect
x="645.90955"
y="45.977581"
width="248.2307"
height="71.300766"
id="rect943" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.53561479"
inkscape:cx="-4.052236"
inkscape:cy="331.25679"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="1747"
inkscape:window-height="1199"
inkscape:window-x="241"
inkscape:window-y="125"
inkscape:window-maximized="0"
units="px" />
<metadata
id="metadata2109">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
aria-label="three.cad"
transform="matrix(1.8120726,0,0,1.8120726,-1064.5195,-78.240227)"
id="text941"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect943);fill:#000000;fill-opacity:1;stroke:none">
<path
d="m 655.63016,64.726208 h 7.84 v 2.76 h -7.84 v 8.64 q 0,1.4 0.2,2.28 0.2,0.88 0.64,1.44 0.48,0.52 1.2,0.72 0.72,0.2 1.76,0.2 1.44,0 2.32,-0.24 0.88,-0.24 1.68,-0.64 l 0.48,2.8 q -0.56,0.24 -1.8,0.64 -1.2,0.4 -3,0.4 -2.08,0 -3.4,-0.48 -1.32,-0.48 -2.08,-1.44 -0.72,-0.96 -1,-2.36 -0.28,-1.44 -0.28,-3.32 v -8.64 h -3.92 v -2.76 h 3.92 v -5.2 l 3.28,-0.56 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono'"
id="path842" />
<path
d="m 668.75008,83.286208 v -27.16 l 3.32,-0.56 v 9.44 q 0.8,-0.32 1.8,-0.48 1,-0.2 1.96,-0.2 2.12,0 3.52,0.64 1.44,0.6 2.28,1.72 0.84,1.12 1.2,2.68 0.36,1.56 0.36,3.44 v 10.48 h -3.28 v -9.76 q 0,-3.44 -0.96,-4.84 -0.96,-1.44 -3.44,-1.44 -1.04,0 -2.04,0.24 -0.96,0.2 -1.4,0.4 v 15.4 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono'"
id="path844" />
<path
d="m 690.19,83.286208 v -17.56 q 4.08,-1.4 8.24,-1.4 1.28,0 2.44,0.12 1.16,0.08 2.56,0.4 l -0.6,2.92 q -1.28,-0.36 -2.28,-0.44 -0.96,-0.12 -2.12,-0.12 -2.44,0 -4.96,0.68 v 15.4 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono'"
id="path846" />
<path
d="m 716.26993,64.286208 q 3.76,0 5.8,2.36 2.04,2.32 2.04,7.08 v 1.16 h -13.28 q 0.2,2.88 1.88,4.4 1.72,1.48 4.8,1.48 1.76,0 3,-0.28 1.24,-0.28 1.88,-0.6 l 0.44,2.8 q -0.6,0.32 -2.16,0.68 -1.56,0.36 -3.52,0.36 -2.4,0 -4.24,-0.72 -1.8,-0.76 -3,-2.04 -1.2,-1.28 -1.8,-3.04 -0.6,-1.8 -0.6,-3.88 0,-2.48 0.76,-4.32 0.76,-1.84 2,-3.04 1.24,-1.2 2.8,-1.8 1.56,-0.6 3.2,-0.6 z m 4.48,7.92 q 0,-2.36 -1.24,-3.72 -1.24,-1.4 -3.28,-1.4 -1.16,0 -2.12,0.44 -0.92,0.44 -1.6,1.16 -0.68,0.72 -1.08,1.64 -0.4,0.92 -0.52,1.88 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono'"
id="path848" />
<path
d="m 736.26985,64.286208 q 3.76,0 5.8,2.36 2.04,2.32 2.04,7.08 v 1.16 h -13.28 q 0.2,2.88 1.88,4.4 1.72,1.48 4.8,1.48 1.76,0 3,-0.28 1.24,-0.28 1.88,-0.6 l 0.44,2.8 q -0.6,0.32 -2.16,0.68 -1.56,0.36 -3.52,0.36 -2.4,0 -4.24,-0.72 -1.8,-0.76 -3,-2.04 -1.2,-1.28 -1.8,-3.04 -0.6,-1.8 -0.6,-3.88 0,-2.48 0.76,-4.32 0.76,-1.84 2,-3.04 1.24,-1.2 2.8,-1.8 1.56,-0.6 3.2,-0.6 z m 4.48,7.92 q 0,-2.36 -1.24,-3.72 -1.24,-1.4 -3.28,-1.4 -1.16,0 -2.12,0.44 -0.92,0.44 -1.6,1.16 -0.68,0.72 -1.08,1.64 -0.4,0.92 -0.52,1.88 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono'"
id="path850" />
<path
d="m 758.86977,80.726208 q 0,1.2 -0.8,2.12 -0.8,0.92 -2.12,0.92 -1.36,0 -2.16,-0.92 -0.8,-0.92 -0.8,-2.12 0,-1.24 0.8,-2.16 0.8,-0.92 2.16,-0.92 1.32,0 2.12,0.92 0.8,0.92 0.8,2.16 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono'"
id="path852" />
<path
d="m 767.8697,74.046208 q 0,-2.52 0.8,-4.36 0.8,-1.84 2.2,-3.04 1.4,-1.2 3.24,-1.76 1.88,-0.6 4,-0.6 1.36,0 2.68,0.2 1.36,0.16 2.88,0.64 l -0.76,2.84 q -1.32,-0.48 -2.44,-0.6 -1.08,-0.16 -2.2,-0.16 -1.44,0 -2.72,0.4 -1.28,0.36 -2.24,1.2 -0.92,0.8 -1.48,2.12 -0.56,1.28 -0.56,3.12 0,1.76 0.52,3.04 0.52,1.24 1.44,2.08 0.96,0.8 2.28,1.2 1.32,0.4 2.92,0.4 1.28,0 2.44,-0.12 1.2,-0.16 2.6,-0.64 l 0.48,2.76 q -1.4,0.52 -2.84,0.72 -1.44,0.24 -3.12,0.24 -2.24,0 -4.12,-0.6 -1.84,-0.64 -3.2,-1.84 -1.32,-1.2 -2.08,-3 -0.72,-1.84 -0.72,-4.24 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono'"
id="path854" />
<path
d="m 796.10962,80.926208 q 1.24,0 2.2,-0.08 1,-0.08 1.64,-0.2 v -5.52 q -0.64,-0.2 -1.56,-0.32 -0.88,-0.12 -1.88,-0.12 -0.92,0 -1.8,0.16 -0.88,0.12 -1.56,0.48 -0.68,0.36 -1.12,0.96 -0.44,0.56 -0.44,1.44 0,1.8 1.2,2.52 1.24,0.68 3.32,0.68 z m -0.32,-16.64 q 2.08,0 3.48,0.52 1.44,0.52 2.32,1.44 0.88,0.92 1.24,2.24 0.36,1.32 0.36,2.88 v 11.6 q -1.16,0.2 -3.08,0.48 -1.88,0.28 -3.88,0.28 -1.52,0 -2.96,-0.28 -1.44,-0.24 -2.56,-0.88 -1.12,-0.68 -1.8,-1.84 -0.68,-1.16 -0.68,-2.96 0,-1.6 0.68,-2.68 0.72,-1.12 1.8,-1.8 1.12,-0.68 2.52,-0.96 1.44,-0.32 2.88,-0.32 1.96,0 3.84,0.44 v -0.92 q 0,-0.84 -0.2,-1.6 -0.16,-0.8 -0.68,-1.44 -0.48,-0.64 -1.36,-1 -0.84,-0.4 -2.2,-0.4 -1.72,0 -3,0.24 -1.28,0.24 -1.96,0.48 l -0.4,-2.72 q 0.68,-0.32 2.24,-0.56 1.6,-0.24 3.4,-0.24 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono'"
id="path856" />
<path
d="m 819.74955,68.646208 q -0.56,-0.52 -1.64,-0.96 -1.08,-0.48 -2.24,-0.48 -1.32,0 -2.28,0.52 -0.92,0.52 -1.52,1.44 -0.6,0.88 -0.88,2.16 -0.28,1.24 -0.28,2.68 0,3.24 1.52,5 1.52,1.76 3.96,1.76 1.24,0 2.08,-0.12 0.88,-0.12 1.28,-0.24 z m 0,-12.52 3.32,-0.56 v 27.2 q -1.08,0.32 -2.76,0.64 -1.68,0.32 -3.92,0.32 -2,0 -3.64,-0.68 -1.64,-0.68 -2.8,-1.92 -1.16,-1.28 -1.8,-3.08 -0.64,-1.8 -0.64,-4.04 0,-2.16 0.52,-3.92 0.56,-1.8 1.6,-3.08 1.04,-1.28 2.48,-2 1.48,-0.72 3.36,-0.72 1.48,0 2.6,0.36 1.12,0.36 1.68,0.76 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono'"
id="path858" />
</g>
<g
id="g921"
transform="matrix(0.16834106,0,0,0.16834106,18.949768,14.727969)">
<path
style="fill:#34d399;fill-opacity:0.698039;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 51.316614,84.370759 164.499996,-95.000008 164.5,95.000008 -164.5,95.000041 z"
id="path2578"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#34d399;fill-opacity:0.698039;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 401.16781,121 0.0224,189.96118 -164.52241,94.96118 -0.0224,-189.96118 z"
id="path2578-3"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#34d399;fill-opacity:0.698039;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 194.52241,405.92236 30,310.96118 30.022413,121 194.54483,215.96118 Z"
id="path2578-6"
sodipodi:nodetypes="ccccc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.6 KiB

2469
icon/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

18
icon/package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "icon",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@svgr/core": "^5.5.0",
"@svgr/plugin-jsx": "^5.5.0",
"@svgr/plugin-prettier": "^5.5.0",
"@svgr/plugin-svgo": "^5.5.0"
}
}

19
icon/svg-to-favicon Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env bash
svg=./svgr_raw/logo.svg
size=(16 24 32 64)
out=""
for i in ${size[@]}; do
inkscape --export-filename="./icon-$i.png" $svg -w $i -h $i
out+="icon-$i.png "
done
size=(192 512)
for i in ${size[@]}; do
inkscape --export-filename="./icon-$i.png" $svg -w $i -h $i
done
convert $out favicon.ico
mv favicon.ico icon-192.png icon-512.png ../dist

44
icon/svg-to-jsx.js Normal file
View File

@ -0,0 +1,44 @@
const { default: svgr } = require('@svgr/core')
const fs = require('fs')
const dir = './svgr_raw/'
async function main() {
const output = ['import * as React from "react";']
const names = []
try {
const files = await fs.promises.readdir(dir);
for (const file of files) {
console.log(file)
const res = await fs.promises.readFile(dir+file, 'utf-8')
let name = file.split('.')[0]
name = name[0].toUpperCase() + name.slice(1)
names.push(name)
const jsx = await svgr(res, { icon: true,
plugins: ['@svgr/plugin-svgo', '@svgr/plugin-jsx', '@svgr/plugin-prettier'],
replaceAttrValues: { '#000': 'currentColor' }
}, { componentName: name })
const split = jsx.split('\n')
output.push(split.slice(1,split.length-2).join('\n'))
}
output.push(`export { ${names.join(', ')} };`)
const data = fs.writeFileSync('../src/react/icons.jsx', output.join(''))
} catch (err) {
console.error(err);
}
}
main()

124
icon/svgr_raw/arc.svg Normal file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16.000001"
version="1.1"
id="svg2112"
inkscape:version="1.0.2 (1.0.2+r75+1)"
sodipodi:docname="arc.svg">
<defs
id="defs2106" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="10.270466"
inkscape:cx="-9.1074268"
inkscape:cy="19.96038"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="1514"
inkscape:window-height="1199"
inkscape:window-x="550"
inkscape:window-y="74"
inkscape:window-maximized="0"
units="px"
inkscape:snap-object-midpoints="true"
inkscape:snap-text-baseline="true"
inkscape:snap-center="true"
inkscape:snap-global="false" />
<metadata
id="metadata2109">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;fill-opacity:0.7;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none"
id="path1525"
sodipodi:type="arc"
sodipodi:cx="1.75"
sodipodi:cy="14.25"
sodipodi:rx="12.5"
sodipodi:ry="12.5"
sodipodi:start="4.8869219"
sodipodi:end="5.2708943"
sodipodi:arc-type="arc"
d="M 3.9206022,1.9399031 A 12.5,12.5 0 0 1 8.3739904,3.6493985"
sodipodi:open="true" />
<rect
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1542-6-7"
width="2"
height="2"
x="0.75"
y="0.75" />
<rect
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1542-6-5"
width="2"
height="2"
x="13.24998"
y="13.25" />
<rect
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1542-6-3"
width="2"
height="2"
x="9.4330788"
y="4.3360553" />
<rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.0328;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1542-6-6"
width="0.80000001"
height="4"
x="1.35"
y="12"
ry="0" />
<rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.1547;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1542-6-6-7"
width="0.80000001"
height="4"
x="-14.65"
y="0"
ry="0"
transform="rotate(-90)" />
<path
style="fill:none;fill-opacity:0.7;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none"
id="path1525-3"
sodipodi:type="arc"
sodipodi:cx="1.75"
sodipodi:cy="14.25"
sodipodi:rx="12.5"
sodipodi:ry="12.5"
sodipodi:start="5.6897734"
sodipodi:end="6.1261057"
sodipodi:arc-type="arc"
sodipodi:open="true"
d="M 12.11297,7.2600891 A 12.5,12.5 0 0 1 14.096104,12.29457" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16.000001"
version="1.1"
id="svg2112"
inkscape:version="1.0.2 (1.0.2+r75+1)"
sodipodi:docname="coincident.svg">
<defs
id="defs2106" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="19.921568"
inkscape:cx="1.0216501"
inkscape:cy="10.08649"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="1514"
inkscape:window-height="964"
inkscape:window-x="749"
inkscape:window-y="270"
inkscape:window-maximized="0"
units="px"
inkscape:snap-object-midpoints="true"
inkscape:snap-text-baseline="true"
inkscape:snap-center="true" />
<metadata
id="metadata2109">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1542-6-5-6-2"
width="2"
height="2"
x="7"
y="7" />
<path
style="fill:none;stroke:#000000;stroke-width:0.982777;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 1.8474908,14.153035 6.1524276,9.8474375"
id="path835"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.982777;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 9.8474908,6.1530346 14.152427,1.8474375"
id="path835-3"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1.51049;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 10.033977,10.0341 3.932517,3.931609"
id="path895" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

Some files were not shown because too many files have changed in this diff Show More