this repo has no description

rendering changes + qol updates + more todos

phaz.uk 3de4485c adb5c83a

verified
Changed files
+93 -46
public
src
+1
public/assets/icons/circle-info-solid-full.svg
··· 1 + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path fill="#fff" d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM288 224C288 206.3 302.3 192 320 192C337.7 192 352 206.3 352 224C352 241.7 337.7 256 320 256C302.3 256 288 241.7 288 224zM280 288L328 288C341.3 288 352 298.7 352 312L352 400L360 400C373.3 400 384 410.7 384 424C384 437.3 373.3 448 360 448L280 448C266.7 448 256 437.3 256 424C256 410.7 266.7 400 280 400L304 400L304 336L280 336C266.7 336 256 325.3 256 312C256 298.7 266.7 288 280 288z"/></svg>
+18 -8
src/App.tsx
··· 2 2 import "./App.css"; 3 3 import { renderBackgroundGrid, renderContextMenu, renderNodes, renderNullTab, renderTempDrawing } from "./renderer"; 4 4 import { lerp } from "./utils/lerp"; 5 - import { Node, NodeIO, NodeIOResolveAnyTypes } from "./structs/node"; 5 + import { Node, NodeIO, NodeIOCanCast, NodeIOResolveAnyTypes } from "./structs/node"; 6 6 import { isPointInRect, isPointInRectApplyOffset, screenToWorldSpace } from "./utils/interections"; 7 7 import { ControlBar } from "./components/ControlBar"; 8 8 import { CanvasContextMenu } from "./ContextMenu/Canvas"; ··· 13 13 import { ConfirmationPopup } from "./components/ConfirmationPopup"; 14 14 15 15 let App = () => { 16 - // TODO: Delete selected node when delete key is pressed 17 16 // TODO: Keybind system 17 + // TODO: Delete selected node when delete key is pressed 18 + // TODO: Copy / paste 18 19 // TODO: Add undo / redo -ing 20 + // TODO: Multi-select 19 21 20 22 let [ selectedNode, setSelectedNode ] = createSignal<Node | null>(null); 21 23 ··· 123 125 return; 124 126 } 125 127 128 + if(e.shiftKey){ 129 + // TODO: Multi-select 130 + return; 131 + } 132 + 126 133 if(contextMenu.visible){ 127 134 let submenus: ContextMenu[] = []; 128 135 contextMenu.items.map(x => x.menu ? submenus.push(x.menu): null); ··· 161 168 162 169 if(isPointInRectApplyOffset(canvas, { x: offset[0], y: offset[1], scale }, 163 170 e.clientX, e.clientY, 164 - node.x, node.y, node.w, node.h 171 + node.x - 20, node.y, node.w + 40, node.h 165 172 )){ 166 173 node.outputs.map(( output, i ) => { 167 174 if(isPointInRectApplyOffset(canvas, { x: offset[0], y: offset[1], scale }, 168 175 e.clientX, e.clientY, 169 - node.x + (node.w - 30), 176 + node.x + (node.w - 10), 170 177 node.y + 50 + (30 * i), 171 178 20, 20 172 179 )){ 173 180 output.index = i; 174 181 175 - drawingTo = [ node.x + (node.w - 30), node.y + 50 + (30 * i) ]; 182 + drawingTo = [ 183 + node.x + (node.w - 10), 184 + node.y + 50 + (30 * i) 185 + ]; 176 186 drawingFrom = output; 177 187 178 188 isDrawing = true; ··· 183 193 node.inputs.map(( input, i ) => { 184 194 if(isPointInRectApplyOffset(canvas, { x: offset[0], y: offset[1], scale }, 185 195 e.clientX, e.clientY, 186 - node.x + 10, 196 + node.x - 10, 187 197 node.y + 50 + (30 * i), 188 198 20, 20 189 199 )){ ··· 285 295 node.inputs.map(( input, i ) => { 286 296 if(isPointInRectApplyOffset(canvas, { x: offset[0], y: offset[1], scale }, 287 297 e.clientX, e.clientY, 288 - node.x + 10, 298 + node.x - 10, 289 299 node.y + 50 + (30 * i), 290 300 20, 20 291 301 )){ ··· 297 307 drawingFrom!.connections.indexOf(input) === -1 && 298 308 ( 299 309 toType === null || 300 - fromType === toType 310 + NodeIOCanCast(fromType, toType) 301 311 ) 302 312 ){ 303 313 drawingFrom!.connections.push(input);
+2 -2
src/Nodes/OSCTrigger.tsx
··· 10 10 typeId: 'osctrigger', 11 11 12 12 w: 200, 13 - h: 50, 13 + h: 55, 14 14 15 15 statics: [ 16 16 { ··· 83 83 } 84 84 }); 85 85 86 - node.h = 60 + (parameters.length + 1) * 30; 86 + node.h = 65 + (parameters.length + 1) * 30; 87 87 NodeManager.Instance.UpdateConfig(); 88 88 } 89 89 };
+3
src/components/TabMenu.css
··· 117 117 border-radius: 5px; 118 118 transition: 0.1s; 119 119 background: transparent; 120 + cursor: pointer; 121 + user-select: none; 122 + -webkit-user-select: none; 120 123 } 121 124 122 125 .tab-icon-bar img:hover{
+4 -1
src/components/TabMenu.tsx
··· 4 4 import { NodeManager } from '../Mangers/NodeManager'; 5 5 import { Tab } from '../structs/Tab'; 6 6 import { SettingsMenu } from './SettingsMenu'; 7 + import { openUrl } from '@tauri-apps/plugin-opener'; 7 8 8 9 export let TabMenu = () => { 9 10 let [ tabImportOpen, setTabImportOpen ] = createSignal(false); ··· 25 26 <Show when={settingsOpen()}> 26 27 <SettingsMenu close={() => setSettingsOpen(false)} /> 27 28 </Show> 28 - 29 + 29 30 <div class="tab-menu"> 30 31 <div class="tab-container"> 31 32 <For each={Object.values(tabs())}> ··· 86 87 87 88 <div class="tab-icon-bar"> 88 89 <img src="/assets/icons/gear-solid-full.svg" width="25" onClick={() => setSettingsOpen(true)} /> 90 + <div style={{ width: 'calc(100% - 50px)' }}></div> 91 + <img src="/assets/icons/circle-info-solid-full.svg" width="25" onClick={() => openUrl('https://github.com/phaze-the-dumb/VRCMacros/wiki')} /> 89 92 </div> 90 93 </div> 91 94 </>
+58 -35
src/renderer.ts
··· 63 63 let nodeX = Math.round(node.x / 10) * 10; 64 64 let nodeY = Math.round(node.y / 10) * 10; 65 65 66 - ctx.fillStyle = '#1f2129'; 67 - ctx.strokeStyle = node.selected ? '#004696ff' : '#fff5'; 66 + ctx.fillStyle = '#343742ff'; 67 + ctx.strokeStyle = node.selected ? '#004696ff' : '#fff0'; 68 68 ctx.lineWidth = 5 * position.scale; 69 69 70 70 // Draw Node Box ··· 75 75 node.h * position.scale, 76 76 10 * position.scale); 77 77 78 + ctx.shadowColor = '#0005'; 79 + ctx.shadowBlur = 10; 80 + 78 81 ctx.stroke(); 79 82 ctx.fill(); 83 + 84 + ctx.shadowBlur = 0; 80 85 81 86 // Draw Node Name 82 87 ctx.fillStyle = '#fff'; 83 - ctx.font = (25 * position.scale) + 'px Comic Mono'; 88 + ctx.font = (25 * position.scale) + 'px Rubik'; 84 89 ctx.textAlign = 'center'; 85 90 86 91 ctx.fillText(node.name, ··· 89 94 ); 90 95 91 96 // Draw Inputs 92 - ctx.font = (15 * position.scale) + 'px Comic Mono'; 97 + ctx.font = (15 * position.scale) + 'px Rubik'; 93 98 ctx.textAlign = 'left'; 94 99 95 100 node.inputs.map(( input, i ) => { 96 101 ctx.fillStyle = NodeIOLinkColours(input); 97 - ctx.fillRect( 98 - (nodeX + 10 + startX + position.x) * position.scale, 99 - (nodeY + 50 + (30 * i) + startY + position.y) * position.scale, 100 - 20 * position.scale, 20 * position.scale 101 - ) 102 + 103 + ctx.beginPath(); 104 + ctx.arc( 105 + (nodeX - 10 + startX + 10 + position.x) * position.scale, 106 + (nodeY + 50 + (30 * i) + startY + 10 + position.y) * position.scale, 107 + 7 * position.scale, 108 + 0, 109 + Math.PI * 2, 110 + ); 111 + ctx.fill(); 102 112 103 113 ctx.fillText(input.name, 104 - (nodeX + 35 + startX + position.x) * position.scale, 114 + (nodeX + 15 + startX + position.x) * position.scale, 105 115 (nodeY + 53 + (30 * i) + startY + position.y) * position.scale, 106 116 ) 107 117 }) ··· 111 121 112 122 node.outputs.map(( output, i ) => { 113 123 ctx.fillStyle = NodeIOLinkColours(output); 114 - ctx.fillRect( 115 - (nodeX + (node.w - 30) + startX + position.x) * position.scale, 116 - (nodeY + 50 + (30 * i) + startY + position.y) * position.scale, 117 - 20 * position.scale, 20 * position.scale 118 - ) 124 + 125 + ctx.beginPath(); 126 + ctx.arc( 127 + (nodeX + (node.w - 10) + startX + 10 + position.x) * position.scale, 128 + (nodeY + 50 + (30 * i) + startY + 10 + position.y) * position.scale, 129 + 7 * position.scale, 130 + 0, 131 + Math.PI * 2, 132 + ); 133 + ctx.fill(); 119 134 120 135 ctx.fillText(output.name, 121 - (nodeX + (node.w - 35) + startX + position.x) * position.scale, 136 + (nodeX + (node.w - 15) + startX + position.x) * position.scale, 122 137 (nodeY + 53 + (30 * i) + startY + position.y) * position.scale, 123 138 ) 124 139 }) ··· 131 146 node.outputs.map(( output, i ) => { 132 147 output.connections.map(partner => { 133 148 ctx.strokeStyle = NodeIOLinkColours(output); 149 + ctx.lineWidth = 3 * position.scale; 150 + 134 151 drawCurve(ctx, 135 - (nodeX + (node.w - 30) + 10 + startX + position.x) * position.scale, 152 + (nodeX + (node.w - 10) + 10 + startX + position.x) * position.scale, 136 153 (nodeY + 50 + (30 * i) + 10 + startY + position.y) * position.scale, 137 - ((Math.round(partner.parent.x / 10) * 10) + 20 + startX + position.x) * position.scale, 154 + ((Math.round(partner.parent.x / 10) * 10) + startX + position.x) * position.scale, 138 155 ((Math.round(partner.parent.y / 10) * 10) + 60 + (30 * partner.index) + startY + position.y) * position.scale, 139 156 ); 140 157 ctx.stroke(); ··· 148 165 contextMenu: ContextMenu 149 166 ) => { 150 167 if(contextMenu.visible){ 151 - ctx.font = '20px Arial'; 168 + ctx.font = '20px Rubik'; 152 169 ctx.textBaseline = 'top'; 153 170 ctx.textAlign = 'left'; 154 171 ··· 192 209 let startX = canvas.width / -2; 193 210 let startY = canvas.height / -2; 194 211 195 - ctx.fillStyle = '#f00'; 212 + // DEBUG STUFF 213 + // ctx.fillStyle = '#f00'; 196 214 197 - ctx.fillRect( 198 - (drawingTo[0] + 10 + startX + position.x) * position.scale, 199 - (drawingTo[1] + 10 + startY + position.y) * position.scale, 200 - 10, 10 201 - ); 215 + // ctx.fillRect( 216 + // (drawingTo[0] + 10 + startX + position.x) * position.scale, 217 + // (drawingTo[1] + 10 + startY + position.y) * position.scale, 218 + // 10, 10 219 + // ); 202 220 203 - ctx.fillRect( 204 - (drawingFrom.parent.x + (drawingFrom.parent.w - 30) + 10 + startX + position.x) * position.scale, 205 - (drawingFrom.parent.y + 50 + (30 * drawingFrom.index) + 10 + startY + position.y) * position.scale, 206 - 10, 10 207 - ); 221 + // ctx.fillRect( 222 + // (drawingFrom.parent.x + (drawingFrom.parent.w - 10) + 10 + startX + position.x) * position.scale, 223 + // (drawingFrom.parent.y + 50 + (30 * drawingFrom.index) + 10 + startY + position.y) * position.scale, 224 + // 10, 10 225 + // ); 208 226 209 227 ctx.strokeStyle = NodeIOLinkColours(drawingFrom); 228 + ctx.lineWidth = 3 * position.scale; 229 + 230 + let nodeX = Math.round(drawingFrom.parent.x / 10) * 10; 231 + let nodeY = Math.round(drawingFrom.parent.y / 10) * 10; 232 + 210 233 drawCurve(ctx, 211 - (drawingFrom.parent.x + (drawingFrom.parent.w - 30) + 10 + startX + position.x) * position.scale, 212 - (drawingFrom.parent.y + 50 + (30 * drawingFrom.index) + 10 + startY + position.y) * position.scale, 234 + (nodeX + (drawingFrom.parent.w - 10) + 10 + startX + position.x) * position.scale, 235 + (nodeY + 50 + (30 * drawingFrom.index) + 10 + startY + position.y) * position.scale, 213 236 (drawingTo[0] + 10 + startX + position.x) * position.scale, 214 237 (drawingTo[1] + 10 + startY + position.y) * position.scale, 215 238 ); ··· 239 262 ) => { 240 263 ctx.fillStyle = '#fff'; 241 264 242 - ctx.font = '20px Arial'; 265 + ctx.font = '20px Rubik'; 243 266 ctx.textBaseline = 'middle'; 244 267 ctx.textAlign = 'center'; 245 268 246 269 let textX = lerp((canvas.width / -2) + 200, canvas.width / 2, 0.5); 247 270 let textY = lerp((canvas.height / -2) + 40, canvas.height / 2, 0.5); 248 271 249 - ctx.font = '40px Arial'; 272 + ctx.font = '40px Rubik'; 250 273 ctx.fillText('Welcome to VRCMacros', textX, textY); 251 274 252 - ctx.font = '20px Arial'; 275 + ctx.font = '20px Rubik'; 253 276 ctx.fillText('Create a new tab to get started!', textX, textY + 40); 254 277 } 255 278
+7
src/structs/node.ts
··· 74 74 ParameterList = 10 75 75 } 76 76 77 + export let NodeIOCanCast = ( input: NodeType | null, output: NodeType | null ): boolean => { 78 + if(input === output)return true; 79 + if(!input || !output)return false; 80 + 81 + return false; 82 + } 83 + 77 84 export let NodeIOResolveAnyTypes = ( nodeio: NodeIO ): NodeType | null => { 78 85 if(nodeio.type > 0 && nodeio.type < 6){ 79 86 // It's a base type