一键启动停止项目
This commit is contained in:
1 parent
96ee180564
commit
88cdcdfb02
11 files changed
+233
-8
No files matched your search
@@ -15,6 +15,7 @@ vite.config.d.ts
|
|||||||
.vite/
|
.vite/
|
||||||
.cache/
|
.cache/
|
||||||
coverage/
|
coverage/
|
||||||
|
/.run/
|
||||||
# Logs
|
# Logs
|
||||||
*.log
|
*.log
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
.stage-wrap[data-v-646aa9bd]{position:relative;width:100%;height:100%;overflow:hidden}.stage-holder[data-v-646aa9bd]{width:100%;height:100%;cursor:grab;touch-action:none;background-color:#0e1219;outline:none}.stage-holder.grid[data-v-646aa9bd]{background:conic-gradient(#141a26 90deg,transparent 90deg 180deg,#141a26 180deg 270deg,transparent 270deg);background-size:28px 28px}.stage-holder[data-v-646aa9bd]:active{cursor:grabbing}.topbar[data-v-646aa9bd]{position:absolute;top:10px;left:10px;right:10px;display:flex;align-items:center;gap:10px;padding:8px 12px;background:#141420d9;border-radius:10px;border:1px solid rgba(255,255,255,.08);font-size:12px;color:#aab;z-index:5;flex-wrap:wrap}.topbar input[type=range][data-v-646aa9bd]{background:#1a1a28;border:1px solid #2e2e44;color:#dde;border-radius:5px}.tool-group[data-v-646aa9bd]{display:flex;gap:6px;margin-left:6px;padding-left:12px;border-left:1px solid #2a2a3c}.tool-btn[data-v-646aa9bd]{width:30px;height:26px;background:#1e1e2e;border:1px solid #2e2e44;border-radius:6px;color:#aab;font-size:14px;cursor:pointer;display:flex;align-items:center;justify-content:center}.tool-btn[data-v-646aa9bd]:hover{background:#2b3a5c;color:#fff}.tool-btn.on[data-v-646aa9bd]{background:#3a5a8c;color:#fff;border-color:#5a7ab8}.background-menu[data-v-646aa9bd]{position:relative;flex:0 0 auto}.background-btn[data-v-646aa9bd]{height:28px;padding:0 11px;border:1px solid #3a4963;border-radius:6px;background:#202a3b;color:#cbd7ed;font-size:12px;cursor:pointer}.background-btn[data-v-646aa9bd]:hover,.background-btn.on[data-v-646aa9bd]{border-color:#7774ff;background:#343b63;color:#fff}.background-panel[data-v-646aa9bd]{position:absolute;top:calc(100% + 9px);right:0;width:248px;box-sizing:border-box;padding:10px;border:1px solid #343b50;border-radius:9px;background:#141420fa;color:#aeb8cc;box-shadow:0 8px 24px #0000007a;z-index:12}.background-upload[data-v-646aa9bd]{width:100%;height:30px;border:1px solid #5652b5;border-radius:6px;background:#4540a0;color:#fff;cursor:pointer}.background-upload[data-v-646aa9bd]:hover{border-color:#8982ff;background:#554dc2}.background-clear[data-v-646aa9bd]{width:100%;height:28px;margin-top:6px;border:1px solid #70404a;border-radius:6px;background:#512a33;color:#efb5bd;cursor:pointer}.background-clear[data-v-646aa9bd]:hover:not(:disabled){border-color:#b65b6a;background:#6a303b;color:#fff}.background-clear[data-v-646aa9bd]:disabled{opacity:.42;cursor:not-allowed}.background-file-input[data-v-646aa9bd]{display:none}.background-file-name[data-v-646aa9bd]{margin:7px 2px 9px;overflow:hidden;color:#737f98;font-size:10px;text-overflow:ellipsis;white-space:nowrap}.background-position-row[data-v-646aa9bd]{display:grid;grid-template-columns:1fr 1fr;gap:8px}.background-position-row label[data-v-646aa9bd]{display:flex;align-items:center;gap:5px;color:#8995ad;font-size:11px}.background-position-row input[data-v-646aa9bd]{width:0;min-width:0;flex:1;box-sizing:border-box;height:28px;padding:0 6px;border:1px solid #343e55;border-radius:5px;background:#101522;color:#e1e6f2}.background-opacity-row[data-v-646aa9bd]{display:grid;grid-template-columns:46px 1fr 34px;align-items:center;gap:7px;margin-top:10px;font-size:11px}.background-opacity-row input[data-v-646aa9bd]{min-width:0;accent-color:#675de0}.background-opacity-row b[data-v-646aa9bd]{color:#aeb8cc;font-size:10px;text-align:right;font-variant-numeric:tabular-nums}.help-btn[data-v-646aa9bd]{height:28px;margin-left:auto;padding:0 11px;flex:0 0 auto;border:1px solid #3a4963;border-radius:6px;background:#202a3b;color:#cbd7ed;font-size:12px;font-weight:700;cursor:pointer}.help-btn[data-v-646aa9bd]:hover,.help-btn.on[data-v-646aa9bd]{border-color:#7774ff;background:#343b63;color:#fff}.zoom-pct[data-v-646aa9bd]{margin-left:0;font-variant-numeric:tabular-nums;color:#9aa;min-width:44px;text-align:center}.help-overlay[data-v-646aa9bd]{position:absolute;top:0;right:0;bottom:0;left:0;z-index:40;display:flex;align-items:center;justify-content:center;padding:72px 24px 28px;box-sizing:border-box;background:#05080fb8;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.help-dialog[data-v-646aa9bd]{width:min(820px,100%);max-height:100%;display:flex;flex-direction:column;overflow:hidden;border:1px solid #3a4864;border-radius:14px;background:#141a27;color:#b8c3d8;box-shadow:0 22px 70px #0000009e}.help-head[data-v-646aa9bd]{display:flex;align-items:flex-start;justify-content:space-between;gap:18px;padding:18px 20px 15px;border-bottom:1px solid #2b354a;background:linear-gradient(135deg,#202942,#181e2d)}.help-head h2[data-v-646aa9bd]{margin:0;color:#eef2ff;font-size:19px}.help-head p[data-v-646aa9bd]{margin:5px 0 0;color:#7786a3;font-size:11px}.help-close[data-v-646aa9bd]{width:28px;height:28px;flex:0 0 28px;border:1px solid #43516b;border-radius:6px;background:#273249;color:#ccd7ed;cursor:pointer}.help-close[data-v-646aa9bd]:hover{border-color:#7774ff;background:#3b4670;color:#fff}.help-body[data-v-646aa9bd]{min-height:0;overflowLine truncated
|
.stage-wrap[data-v-1b609e97]{position:relative;width:100%;height:100%;overflow:hidden}.stage-holder[data-v-1b609e97]{width:100%;height:100%;cursor:grab;touch-action:none;background-color:#0e1219;outline:none}.stage-holder.grid[data-v-1b609e97]{background:conic-gradient(#141a26 90deg,transparent 90deg 180deg,#141a26 180deg 270deg,transparent 270deg);background-size:28px 28px}.stage-holder[data-v-1b609e97]:active{cursor:grabbing}.topbar[data-v-1b609e97]{position:absolute;top:10px;left:10px;right:10px;display:flex;align-items:center;gap:10px;padding:8px 12px;background:#141420d9;border-radius:10px;border:1px solid rgba(255,255,255,.08);font-size:12px;color:#aab;z-index:5;flex-wrap:wrap}.topbar input[type=range][data-v-1b609e97]{background:#1a1a28;border:1px solid #2e2e44;color:#dde;border-radius:5px}.tool-group[data-v-1b609e97]{display:flex;gap:6px;margin-left:6px;padding-left:12px;border-left:1px solid #2a2a3c}.tool-btn[data-v-1b609e97]{width:30px;height:26px;background:#1e1e2e;border:1px solid #2e2e44;border-radius:6px;color:#aab;font-size:14px;cursor:pointer;display:flex;align-items:center;justify-content:center}.tool-btn[data-v-1b609e97]:hover{background:#2b3a5c;color:#fff}.tool-btn.on[data-v-1b609e97]{background:#3a5a8c;color:#fff;border-color:#5a7ab8}.background-menu[data-v-1b609e97]{position:relative;flex:0 0 auto}.background-btn[data-v-1b609e97]{height:28px;padding:0 11px;border:1px solid #3a4963;border-radius:6px;background:#202a3b;color:#cbd7ed;font-size:12px;cursor:pointer}.background-btn[data-v-1b609e97]:hover,.background-btn.on[data-v-1b609e97]{border-color:#7774ff;background:#343b63;color:#fff}.background-panel[data-v-1b609e97]{position:absolute;top:calc(100% + 9px);right:0;width:248px;box-sizing:border-box;padding:10px;border:1px solid #343b50;border-radius:9px;background:#141420fa;color:#aeb8cc;box-shadow:0 8px 24px #0000007a;z-index:12}.background-upload[data-v-1b609e97]{width:100%;height:30px;border:1px solid #5652b5;border-radius:6px;background:#4540a0;color:#fff;cursor:pointer}.background-upload[data-v-1b609e97]:hover{border-color:#8982ff;background:#554dc2}.background-clear[data-v-1b609e97]{width:100%;height:28px;margin-top:6px;border:1px solid #70404a;border-radius:6px;background:#512a33;color:#efb5bd;cursor:pointer}.background-clear[data-v-1b609e97]:hover:not(:disabled){border-color:#b65b6a;background:#6a303b;color:#fff}.background-clear[data-v-1b609e97]:disabled{opacity:.42;cursor:not-allowed}.background-file-input[data-v-1b609e97]{display:none}.background-file-name[data-v-1b609e97]{margin:7px 2px 9px;overflow:hidden;color:#737f98;font-size:10px;text-overflow:ellipsis;white-space:nowrap}.background-position-row[data-v-1b609e97]{display:grid;grid-template-columns:1fr 1fr;gap:8px}.background-position-row label[data-v-1b609e97]{display:flex;align-items:center;gap:5px;color:#8995ad;font-size:11px}.background-position-row input[data-v-1b609e97]{width:0;min-width:0;flex:1;box-sizing:border-box;height:28px;padding:0 6px;border:1px solid #343e55;border-radius:5px;background:#101522;color:#e1e6f2}.background-opacity-row[data-v-1b609e97]{display:grid;grid-template-columns:46px 1fr 34px;align-items:center;gap:7px;margin-top:10px;font-size:11px}.background-opacity-row input[data-v-1b609e97]{min-width:0;accent-color:#675de0}.background-opacity-row b[data-v-1b609e97]{color:#aeb8cc;font-size:10px;text-align:right;font-variant-numeric:tabular-nums}.help-btn[data-v-1b609e97]{height:28px;margin-left:auto;padding:0 11px;flex:0 0 auto;border:1px solid #3a4963;border-radius:6px;background:#202a3b;color:#cbd7ed;font-size:12px;font-weight:700;cursor:pointer}.help-btn[data-v-1b609e97]:hover,.help-btn.on[data-v-1b609e97]{border-color:#7774ff;background:#343b63;color:#fff}.zoom-pct[data-v-1b609e97]{margin-left:0;font-variant-numeric:tabular-nums;color:#9aa;min-width:44px;text-align:center}.help-overlay[data-v-1b609e97]{position:absolute;top:0;right:0;bottom:0;left:0;z-index:40;display:flex;align-items:center;justify-content:center;padding:72px 24px 28px;box-sizing:border-box;background:#05080fb8;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.help-dialog[data-v-1b609e97]{width:min(820px,100%);max-height:100%;display:flex;flex-direction:column;overflow:hidden;border:1px solid #3a4864;border-radius:14px;background:#141a27;color:#b8c3d8;box-shadow:0 22px 70px #0000009e}.help-head[data-v-1b609e97]{display:flex;align-items:flex-start;justify-content:space-between;gap:18px;padding:18px 20px 15px;border-bottom:1px solid #2b354a;background:linear-gradient(135deg,#202942,#181e2d)}.help-head h2[data-v-1b609e97]{margin:0;color:#eef2ff;font-size:19px}.help-head p[data-v-1b609e97]{margin:5px 0 0;color:#7786a3;font-size:11px}.help-close[data-v-1b609e97]{width:28px;height:28px;flex:0 0 28px;border:1px solid #43516b;border-radius:6px;background:#273249;color:#ccd7ed;cursor:pointer}.help-close[data-v-1b609e97]:hover{border-color:#7774ff;background:#3b4670;color:#fff}.help-body[data-v-1b609e97]{min-height:0;overflowLine truncated
|
||||||
@@ -1165,7 +1165,7 @@ void main(void)\r
|
|||||||
font-weight: ${t.weight};
|
font-weight: ${t.weight};
|
||||||
font-style: ${t.style};
|
font-style: ${t.style};
|
||||||
font-display: ${t.display};
|
font-display: ${t.display};
|
||||||
}`,this._stylesheet)}get stylesheet(){return this._stylesheet}set stylesheet(e){this._stylesheet!==e&&(this._stylesheet=e,this.styleID++)}normalizeColor(e){return Array.isArray(e)&&(e=o_(e)),typeof e=="number"?r_(e):e}dropShadowToCSS(){let e=this.normalizeColor(this.dropShadowColor);const t=this.dropShadowAlpha,s=Math.round(Math.cos(this.dropShadowAngle)*this.dropShadowDistance),n=Math.round(Math.sin(this.dropShadowAngle)*this.dropShadowDistance);e.startsWith("#")&&t<1&&(e+=(t*255|0).toString(16).padStart(2,"0"));const r=`${s}px ${n}px`;return this.dropShadowBlur>0?`text-shadow: ${r} ${this.dropShadowBlur}px ${e}`:`text-shadow: ${r} ${e}`}reset(){Object.assign(this,qr.defaultOptions)}onBeforeDraw(){const{fontsDirty:e}=this;return this.fontsDirty=!1,this.isSafari&&this._fonts.length>0&&e?new Promise(t=>setTimeout(t,100)):Promise.resolve()}get isSafari(){const{userAgent:e}=Ve.ADAPTER.getNavigator();return/^((?!chrome|android).)*safari/i.test(e)}set fillGradientStops(e){console.warn("[HTMLTextStyle] fillGradientStops is not supported by HTMLText")}get fillGradientStops(){return super.fillGradientStops}set fillGradientType(e){console.warn("[HTMLTextStyle] fillGradientType is not supported by HTMLText")}get fillGradientType(){return super.fillGradientType}set miterLimit(e){console.warn("[HTMLTextStyle] miterLimit is not supported by HTMLText")}get miterLimit(){return super.miterLimit}set trim(e){console.warn("[HTMLTextStyle] trim is not supported by HTMLText")}get trim(){return super.trim}set textBaseline(e){console.warn("[HTMLTextStyle] textBaseline is not supported by HTMLText")}get textBaseline(){return super.textBaseline}set leading(e){console.warn("[HTMLTextStyle] leading is not supported by HTMLText")}get leading(){return super.leading}set lineJoin(e){console.warn("[HTMLTextStyle] lineJoin is not supported by HTMLText")}get lineJoin(){return super.lineJoin}};_d.availableFonts={},_d.defaultOptions={align:"left",breakWords:!1,dropShadow:!1,dropShadowAlpha:1,dropShadowAngle:Math.PI/6,dropShadowBlur:0,dropShadowColor:"black",dropShadowDistance:5,fill:"black",fontFamily:"Arial",fontSize:26,fontStyle:"normal",fontVariant:"normal",fontWeight:"normal",letterSpacing:0,lineHeight:0,padding:0,stroke:"black",strokeThickness:0,whiteSpace:"normal",wordWrap:!1,wordWrapWidth:100};let xu=_d;const Ja=class Kr extends Qn{constructor(e="",t={}){super(et.EMPTY),this._text=null,this._style=null,this._autoResolution=!0,this.localStyleID=-1,this.dirty=!1,this._updateID=0,this.ownsStyle=!1;const s=new Image,n=et.from(s,{scaleMode:Ve.SCALE_MODE,resourceOptions:{autoLoad:!1}});n.orig=new lt,n.trim=new lt,this.texture=n;const r="http://www.w3.org/2000/svg",o="http://www.w3.org/1999/xhtml",a=document.createElementNS(r,"svg"),h=document.createElementNS(r,"foreignObject"),l=document.createElementNS(o,"div"),c=document.createElementNS(o,"style");h.setAttribute("width","10000"),h.setAttribute("height","10000"),h.style.overflow="hidden",a.appendChild(h),this.maxWidth=Kr.defaultMaxWidth,this.maxHeight=Kr.defaultMaxHeight,this._domElement=l,this._styleElement=c,this._svgRoot=a,this._foreignObject=h,this._foreignObject.appendChild(c),this._foreignObject.appendChild(l),this._image=s,this._loadImage=new Image,this._autoResolution=Kr.defaultAutoResolution,this._resolution=Kr.defaultResolution??Ve.RESOLUTION,this.text=e,this.style=t}measureText(e){var c,u;const{text:t,style:s,resolution:n}=Object.assign({text:this._text,style:this._style,resolution:this._resolution},e);Object.assign(this._domElement,{innerHTML:t,style:s.toCSS(n)}),this._styleElement.textContent=s.toGlobalCSS(),document.body.appendChild(this._svgRoot);const r=this._domElement.getBoundingClientRect();this._svgRoot.remove();const{width:o,height:a}=r;(o>this.maxWidth||a>this.maxHeight)&&console.warn("[HTMLText] Large expanse of text, increase HTMLText.maxWidth or HTMLText.maxHeight property.");const h=Math.min(this.maxWidth,Math.ceil(o)),l=Math.min(this.maxHeight,Math.ceil(a));return this._svgRoot.setAttribute("width",h.toString()),this._svgRoot.setAttribute("height",l.toString()),t!==this._text&&(this._domElement.innerHTML=this._text),s!==this._style&&(Object.assign(this._domElement,{style:(c=this._style)==null?void 0:c.toCSS(n)}),this._styleElement.textContent=(u=this._style)==null?void 0:u.toGlobalCSS()),{width:h+s.padding*2,height:l+s.padding*2}}async updateText(e=!0){const{style:t,_image:s,_loadImage:n}=this;if(this.localStyleID!==t.styleID&&(this.dirty=!0,this.localStyleID=t.styleID),!this.dirty&&e)return;const{width:r,height:o}=this.measureText();s.width=n.width=Math.ceil(Math.max(1,r)),s.height=n.height=Math.ceil(Math.max(1,o)),this._updateID++;const a=this._updateID;await new Promise(h=>{n.onload=async()=>{if(a<this._updateID){h();return}await t.onBeforeDraw(),s.src=n.src,n.onload=null,n.src="",this.updateTexture(),h()};const l=new XMLSerializer().serializeToString(this._svgRoot);n.src=`data:image/svg+xml;charset=utf8,${encodeURIComponent(l)}`})}get source(){ret
Line truncated
|
}`,this._stylesheet)}get stylesheet(){return this._stylesheet}set stylesheet(e){this._stylesheet!==e&&(this._stylesheet=e,this.styleID++)}normalizeColor(e){return Array.isArray(e)&&(e=o_(e)),typeof e=="number"?r_(e):e}dropShadowToCSS(){let e=this.normalizeColor(this.dropShadowColor);const t=this.dropShadowAlpha,s=Math.round(Math.cos(this.dropShadowAngle)*this.dropShadowDistance),n=Math.round(Math.sin(this.dropShadowAngle)*this.dropShadowDistance);e.startsWith("#")&&t<1&&(e+=(t*255|0).toString(16).padStart(2,"0"));const r=`${s}px ${n}px`;return this.dropShadowBlur>0?`text-shadow: ${r} ${this.dropShadowBlur}px ${e}`:`text-shadow: ${r} ${e}`}reset(){Object.assign(this,qr.defaultOptions)}onBeforeDraw(){const{fontsDirty:e}=this;return this.fontsDirty=!1,this.isSafari&&this._fonts.length>0&&e?new Promise(t=>setTimeout(t,100)):Promise.resolve()}get isSafari(){const{userAgent:e}=Ve.ADAPTER.getNavigator();return/^((?!chrome|android).)*safari/i.test(e)}set fillGradientStops(e){console.warn("[HTMLTextStyle] fillGradientStops is not supported by HTMLText")}get fillGradientStops(){return super.fillGradientStops}set fillGradientType(e){console.warn("[HTMLTextStyle] fillGradientType is not supported by HTMLText")}get fillGradientType(){return super.fillGradientType}set miterLimit(e){console.warn("[HTMLTextStyle] miterLimit is not supported by HTMLText")}get miterLimit(){return super.miterLimit}set trim(e){console.warn("[HTMLTextStyle] trim is not supported by HTMLText")}get trim(){return super.trim}set textBaseline(e){console.warn("[HTMLTextStyle] textBaseline is not supported by HTMLText")}get textBaseline(){return super.textBaseline}set leading(e){console.warn("[HTMLTextStyle] leading is not supported by HTMLText")}get leading(){return super.leading}set lineJoin(e){console.warn("[HTMLTextStyle] lineJoin is not supported by HTMLText")}get lineJoin(){return super.lineJoin}};_d.availableFonts={},_d.defaultOptions={align:"left",breakWords:!1,dropShadow:!1,dropShadowAlpha:1,dropShadowAngle:Math.PI/6,dropShadowBlur:0,dropShadowColor:"black",dropShadowDistance:5,fill:"black",fontFamily:"Arial",fontSize:26,fontStyle:"normal",fontVariant:"normal",fontWeight:"normal",letterSpacing:0,lineHeight:0,padding:0,stroke:"black",strokeThickness:0,whiteSpace:"normal",wordWrap:!1,wordWrapWidth:100};let xu=_d;const Ja=class Kr extends Qn{constructor(e="",t={}){super(et.EMPTY),this._text=null,this._style=null,this._autoResolution=!0,this.localStyleID=-1,this.dirty=!1,this._updateID=0,this.ownsStyle=!1;const s=new Image,n=et.from(s,{scaleMode:Ve.SCALE_MODE,resourceOptions:{autoLoad:!1}});n.orig=new lt,n.trim=new lt,this.texture=n;const r="http://www.w3.org/2000/svg",o="http://www.w3.org/1999/xhtml",a=document.createElementNS(r,"svg"),h=document.createElementNS(r,"foreignObject"),l=document.createElementNS(o,"div"),c=document.createElementNS(o,"style");h.setAttribute("width","10000"),h.setAttribute("height","10000"),h.style.overflow="hidden",a.appendChild(h),this.maxWidth=Kr.defaultMaxWidth,this.maxHeight=Kr.defaultMaxHeight,this._domElement=l,this._styleElement=c,this._svgRoot=a,this._foreignObject=h,this._foreignObject.appendChild(c),this._foreignObject.appendChild(l),this._image=s,this._loadImage=new Image,this._autoResolution=Kr.defaultAutoResolution,this._resolution=Kr.defaultResolution??Ve.RESOLUTION,this.text=e,this.style=t}measureText(e){var c,u;const{text:t,style:s,resolution:n}=Object.assign({text:this._text,style:this._style,resolution:this._resolution},e);Object.assign(this._domElement,{innerHTML:t,style:s.toCSS(n)}),this._styleElement.textContent=s.toGlobalCSS(),document.body.appendChild(this._svgRoot);const r=this._domElement.getBoundingClientRect();this._svgRoot.remove();const{width:o,height:a}=r;(o>this.maxWidth||a>this.maxHeight)&&console.warn("[HTMLText] Large expanse of text, increase HTMLText.maxWidth or HTMLText.maxHeight property.");const h=Math.min(this.maxWidth,Math.ceil(o)),l=Math.min(this.maxHeight,Math.ceil(a));return this._svgRoot.setAttribute("width",h.toString()),this._svgRoot.setAttribute("height",l.toString()),t!==this._text&&(this._domElement.innerHTML=this._text),s!==this._style&&(Object.assign(this._domElement,{style:(c=this._style)==null?void 0:c.toCSS(n)}),this._styleElement.textContent=(u=this._style)==null?void 0:u.toGlobalCSS()),{width:h+s.padding*2,height:l+s.padding*2}}async updateText(e=!0){const{style:t,_image:s,_loadImage:n}=this;if(this.localStyleID!==t.styleID&&(this.dirty=!0,this.localStyleID=t.styleID),!this.dirty&&e)return;const{width:r,height:o}=this.measureText();s.width=n.width=Math.ceil(Math.max(1,r)),s.height=n.height=Math.ceil(Math.max(1,o)),this._updateID++;const a=this._updateID;await new Promise(h=>{n.onload=async()=>{if(a<this._updateID){h();return}await t.onBeforeDraw(),s.src=n.src,n.onload=null,n.src="",this.updateTexture(),h()};const l=new XMLSerializer().serializeToString(this._svgRoot);n.src=`data:image/svg+xml;charset=utf8,${encodeURIComponent(l)}`})}get source(){ret
Line truncated
|
||||||
attribute vec2 aVertexPosition;
|
attribute vec2 aVertexPosition;
|
||||||
attribute vec2 aTextureCoord;
|
attribute vec2 aTextureCoord;
|
||||||
|
|
||||||
@@ -1235,4 +1235,4 @@ void main(void){
|
|||||||
gl_FragColor.a = color.a * vColor.a;
|
gl_FragColor.a = color.a * vColor.a;
|
||||||
gl_FragColor.rgb = ((color.a - 1.0) * vDarkColor.a + 1.0 - color.rgb) * vDarkColor.rgb + color.rgb * vColor.rgb;
|
gl_FragColor.rgb = ((color.a - 1.0) * vDarkColor.a + 1.0 - color.rgb) * vDarkColor.rgb + color.rgb * vColor.rgb;
|
||||||
}
|
}
|
||||||
`;class ox extends Bn{constructor(e){super(e),this.shaderGenerator=new hv(DA,NA),this.geometryClass=LA,this.vertexSize=7}packInterleavedGeometry(e,t,s,n,r){const{uint32View:o,float32View:a}=t,h=n/this.vertexSize,l=e.uvs,c=e.indices,u=e.vertexData,f=e._texture.baseTexture._batchLocation,d=Math.min(e.worldAlpha,1),m=At.shared.setValue(e._tintRGB).toPremultiplied(d,!0),g=At.shared.setValue(e._darkTintRGB).premultiply(d,!0).toPremultiplied(1,!1);for(let b=0;b<u.length;b+=2)a[n++]=u[b],a[n++]=u[b+1],a[n++]=l[b],a[n++]=l[b+1],o[n++]=m,o[n++]=g,a[n++]=f;for(let b=0;b<c.length;b++)s[r++]=h+c[b]}}A(ox,"extension",{name:"darkTintBatch",type:Oe.RendererPlugin});He.add(ox);class UA{constructor(){A(this,"container",new gi);A(this,"entries",new Map)}sync(e,t,s){var n;for(const[r,o]of this.entries)e.some(a=>a.id===r)||(this.container.removeChild(o.root),o.root.destroy({children:!0}),this.entries.delete(r));for(const r of e){const o=EE(r.id);let a=this.entries.get(r.id);if(a&&a.assetVersion!==r.assetVersion&&!o&&(this.container.removeChild(a.root),a.root.destroy({children:!0}),this.entries.delete(r.id),a=void 0),(!a||a.assetVersion!==r.assetVersion)&&o){a&&(this.container.removeChild(a.root),a.root.destroy({children:!0}));const f=new gi,d=new Rd({skeletonData:o.skeletonData,autoUpdate:!1,darkTint:!1});o.skeletonData.defaultSkin&&d.skeleton.setSkin(o.skeletonData.defaultSkin),d.skeleton.setSlotsToSetupPose(),f.addChild(d),this.container.addChild(f),a={root:f,spine:d,assetVersion:r.assetVersion,animation:""},this.entries.set(r.id,a)}if(!a)continue;const h=a.root,l=a.spine,c=r.visible!==!1&&r.enabled;h.visible=c,h.renderable=c,h.position.set(r.x,-r.y),h.rotation=-r.rotation*Math.PI/180,h.scale.set(r.scaleX,r.scaleY),a.animation!==r.selectedAnimation&&(a.animation=r.selectedAnimation,l.skeleton.setToSetupPose(),l.state.clearTracks(),a.animation&&l.state.setAnimation(0,a.animation,!1));const u=l.state.getCurrent(0);if(u){const f=((n=r.animations.find(m=>m.name===r.selectedAnimation))==null?void 0:n.duration)||0,d=Math.max(0,t/Math.max(1,s)-r.timeOffset);u.trackTime=f>0?Math.min(d,f):d}l.update(0)}}getBoneWorldTransform(e,t){const s=this.entries.get(e),n=s==null?void 0:s.spine.skeleton.findBone(t);if(!s||!n||!n.active)return null;const r=s.root,o=Math.cos(r.rotation),a=Math.sin(r.rotation),h=o*r.scale.x,l=-a*r.scale.y,c=a*r.scale.x,u=o*r.scale.y,f=h*n.a+l*n.c,d=h*n.b+l*n.d,m=c*n.a+u*n.c,g=c*n.b+u*n.d,b=r.position.x+h*n.worldX+l*n.worldY,_=r.position.y+c*n.worldX+u*n.worldY;return{x:b,y:-_,rotation:-Math.atan2(m,f)*180/Math.PI,scaleX:Math.max(1e-4,Math.hypot(f,m)),scaleY:Math.max(1e-4,Math.hypot(d,g))}}destroy(){for(const e of this.entries.values())e.root.removeFromParent(),e.root.destroy({children:!0});this.entries.clear(),this.container.removeFromParent(),this.container.destroy({children:!0})}}function Yn(i,e,t){const s=Number(i[e]);return Number.isFinite(s)?s:t}function ki(i,e,t,s){i[e]==null&&(i[e]=Yn(i,t,s))}function pf(i,e,t){if(typeof i.curve!="number")return;const s=Yn(i,"time",0),r=Yn(e,"time",0)-s,o=i.curve,a=Yn(i,"c2",0),h=Yn(i,"c3",1),l=Yn(i,"c4",1);i.curve=t.flatMap(([c,u])=>[s+r*o,c+(u-c)*a,s+r*h,c+(u-c)*l]),delete i.c2,delete i.c3,delete i.c4}function Wn(i,e){if(Array.isArray(i))for(let t=0;t<i.length-1;t++){const s=i[t],n=i[t+1];pf(s,n,e.map(({key:r,fallback:o})=>[Yn(s,r,o),Yn(n,r,o)]))}}function VA(i){if(Array.isArray(i))for(let e=0;e<i.length-1;e++)pf(i[e],i[e+1],[[0,1]])}function Yr(i,e){const t=typeof i=="string"?i.replace(/^#/,""):"",s=t.length===6?`${t}ff`:t.padEnd(8,"f").slice(0,8),n=[0,2,4,6].map(r=>Number.parseInt(s.slice(r,r+2),16)/255);return e?n:n.slice(0,3)}function dg(i,e){if(Array.isArray(i))for(let t=0;t<i.length-1;t++){const s=i[t],n=i[t+1],r=e?[...Yr(s.light,!0),...Yr(s.dark,!1)]:Yr(s.color,!0),o=e?[...Yr(n.light,!0),...Yr(n.dark,!1)]:Yr(n.color,!0);pf(s,n,r.map((a,h)=>[a,o[h]]))}}function XA(i){for(const e of i.bones||[])e.inherit==null&&e.transform!=null&&(e.inherit=e.transform);for(const e of i.transform||[])ki(e,"mixRotate","rotateMix",1),ki(e,"mixX","translateMix",1),e.mixY==null&&(e.mixY=e.mixX),ki(e,"mixScaleX","scaleMix",1),e.mixScaleY==null&&(e.mixScaleY=e.mixScaleX),ki(e,"mixShearY","shearMix",1);for(const e of i.path||[])ki(e,"mixRotate","rotateMix",1),ki(e,"mixX","translateMix",1),e.mixY==null&&(e.mixY=e.mixX)}function YA(i){for(const e of i.skins||[])for(const t of Object.values(e.attachments||{}))for(const s of Object.values(t||{}))s.parent!=null&&s.timelines==null&&s.deform!=null&&(s.timelines=s.deform)}function $A(i){for(const e of Object.values(i.slots||{}))e.color&&!e.rgba&&(e.rgba=e.color,delete e.color),e.twoColor&&!e.rgba2&&(e.rgba2=e.twoColor,delete e.twoColor),dg(e.rgba,!1),dg(e.rgba2,!0)}function GA(i){for(const e of Object.values(i.bones||{})){for(const t of e.rotate||[])ki(t,"value","angle",0);Wn(e.rotate,[{key:"value",fallback:0}]),Wn(e.translate,[{key:"x",fallback:0},{key:"y",fallback:0}]),Wn(e.scale,[{key:"x",fallback:1},{key:"y",fallback:1}]),Wn(e.shear,[{key:"x",fa
Line truncated
|
`;class ox extends Bn{constructor(e){super(e),this.shaderGenerator=new hv(DA,NA),this.geometryClass=LA,this.vertexSize=7}packInterleavedGeometry(e,t,s,n,r){const{uint32View:o,float32View:a}=t,h=n/this.vertexSize,l=e.uvs,c=e.indices,u=e.vertexData,f=e._texture.baseTexture._batchLocation,d=Math.min(e.worldAlpha,1),m=At.shared.setValue(e._tintRGB).toPremultiplied(d,!0),g=At.shared.setValue(e._darkTintRGB).premultiply(d,!0).toPremultiplied(1,!1);for(let b=0;b<u.length;b+=2)a[n++]=u[b],a[n++]=u[b+1],a[n++]=l[b],a[n++]=l[b+1],o[n++]=m,o[n++]=g,a[n++]=f;for(let b=0;b<c.length;b++)s[r++]=h+c[b]}}A(ox,"extension",{name:"darkTintBatch",type:Oe.RendererPlugin});He.add(ox);class UA{constructor(){A(this,"container",new gi);A(this,"entries",new Map)}sync(e,t,s){var n;for(const[r,o]of this.entries)e.some(a=>a.id===r)||(this.container.removeChild(o.root),o.root.destroy({children:!0}),this.entries.delete(r));for(const r of e){const o=EE(r.id);let a=this.entries.get(r.id);if(a&&a.assetVersion!==r.assetVersion&&!o&&(this.container.removeChild(a.root),a.root.destroy({children:!0}),this.entries.delete(r.id),a=void 0),(!a||a.assetVersion!==r.assetVersion)&&o){a&&(this.container.removeChild(a.root),a.root.destroy({children:!0}));const f=new gi,d=new Rd({skeletonData:o.skeletonData,autoUpdate:!1,darkTint:!1});o.skeletonData.defaultSkin&&d.skeleton.setSkin(o.skeletonData.defaultSkin),d.skeleton.setSlotsToSetupPose(),f.addChild(d),this.container.addChild(f),a={root:f,spine:d,assetVersion:r.assetVersion,animation:""},this.entries.set(r.id,a)}if(!a)continue;const h=a.root,l=a.spine,c=r.visible!==!1&&r.enabled;h.visible=c,h.renderable=c,h.position.set(r.x,-r.y),h.rotation=-r.rotation*Math.PI/180,h.scale.set(r.scaleX,r.scaleY),a.animation!==r.selectedAnimation&&(a.animation=r.selectedAnimation,l.skeleton.setToSetupPose(),l.state.clearTracks(),a.animation&&l.state.setAnimation(0,a.animation,!1));const u=l.state.getCurrent(0);if(u){const f=((n=r.animations.find(m=>m.name===r.selectedAnimation))==null?void 0:n.duration)||0,d=Math.max(0,t/Math.max(1,s)-r.timeOffset);u.trackTime=f>0?Math.min(d,f):d}l.update(0)}}getBoneWorldTransform(e,t){const s=this.entries.get(e),n=s==null?void 0:s.spine.skeleton.findBone(t);if(!s||!n||!n.active)return null;const r=s.root,o=Math.cos(r.rotation),a=Math.sin(r.rotation),h=o*r.scale.x,l=-a*r.scale.y,c=a*r.scale.x,u=o*r.scale.y,f=h*n.a+l*n.c,d=h*n.b+l*n.d,m=c*n.a+u*n.c,g=c*n.b+u*n.d,b=r.position.x+h*n.worldX+l*n.worldY,_=r.position.y+c*n.worldX+u*n.worldY;return{x:b,y:-_,rotation:-Math.atan2(m,f)*180/Math.PI,scaleX:Math.max(1e-4,Math.hypot(f,m)),scaleY:Math.max(1e-4,Math.hypot(d,g))}}destroy(){for(const e of this.entries.values())e.root.removeFromParent(),e.root.destroy({children:!0});this.entries.clear(),this.container.removeFromParent(),this.container.destroy({children:!0})}}function Yn(i,e,t){const s=Number(i[e]);return Number.isFinite(s)?s:t}function ki(i,e,t,s){i[e]==null&&(i[e]=Yn(i,t,s))}function pf(i,e,t){if(typeof i.curve!="number")return;const s=Yn(i,"time",0),r=Yn(e,"time",0)-s,o=i.curve,a=Yn(i,"c2",0),h=Yn(i,"c3",1),l=Yn(i,"c4",1);i.curve=t.flatMap(([c,u])=>[s+r*o,c+(u-c)*a,s+r*h,c+(u-c)*l]),delete i.c2,delete i.c3,delete i.c4}function Wn(i,e){if(Array.isArray(i))for(let t=0;t<i.length-1;t++){const s=i[t],n=i[t+1];pf(s,n,e.map(({key:r,fallback:o})=>[Yn(s,r,o),Yn(n,r,o)]))}}function VA(i){if(Array.isArray(i))for(let e=0;e<i.length-1;e++)pf(i[e],i[e+1],[[0,1]])}function Yr(i,e){const t=typeof i=="string"?i.replace(/^#/,""):"",s=t.length===6?`${t}ff`:t.padEnd(8,"f").slice(0,8),n=[0,2,4,6].map(r=>Number.parseInt(s.slice(r,r+2),16)/255);return e?n:n.slice(0,3)}function dg(i,e){if(Array.isArray(i))for(let t=0;t<i.length-1;t++){const s=i[t],n=i[t+1],r=e?[...Yr(s.light,!0),...Yr(s.dark,!1)]:Yr(s.color,!0),o=e?[...Yr(n.light,!0),...Yr(n.dark,!1)]:Yr(n.color,!0);pf(s,n,r.map((a,h)=>[a,o[h]]))}}function XA(i){for(const e of i.bones||[])e.inherit==null&&e.transform!=null&&(e.inherit=e.transform);for(const e of i.transform||[])ki(e,"mixRotate","rotateMix",1),ki(e,"mixX","translateMix",1),e.mixY==null&&(e.mixY=e.mixX),ki(e,"mixScaleX","scaleMix",1),e.mixScaleY==null&&(e.mixScaleY=e.mixScaleX),ki(e,"mixShearY","shearMix",1);for(const e of i.path||[])ki(e,"mixRotate","rotateMix",1),ki(e,"mixX","translateMix",1),e.mixY==null&&(e.mixY=e.mixX)}function YA(i){for(const e of i.skins||[])for(const t of Object.values(e.attachments||{}))for(const s of Object.values(t||{}))s.parent!=null&&s.timelines==null&&s.deform!=null&&(s.timelines=s.deform)}function $A(i){for(const e of Object.values(i.slots||{}))e.color&&!e.rgba&&(e.rgba=e.color,delete e.color),e.twoColor&&!e.rgba2&&(e.rgba2=e.twoColor,delete e.twoColor),dg(e.rgba,!1),dg(e.rgba2,!0)}function GA(i){for(const e of Object.values(i.bones||{})){for(const t of e.rotate||[])ki(t,"value","angle",0);Wn(e.rotate,[{key:"value",fallback:0}]),Wn(e.translate,[{key:"x",fallback:0},{key:"y",fallback:0}]),Wn(e.scale,[{key:"x",fallback:1},{key:"y",fallback:1}]),Wn(e.shear,[{key:"x",fa
Line truncated
|
||||||
Vendored
+2
-2
@@ -8,8 +8,8 @@
|
|||||||
html, body { margin: 0; padding: 0; background: #111; color: #eee; font-family: system-ui, -apple-system, sans-serif; }
|
html, body { margin: 0; padding: 0; background: #111; color: #eee; font-family: system-ui, -apple-system, sans-serif; }
|
||||||
#app { display: flex; flex-direction: column; height: 100vh; }
|
#app { display: flex; flex-direction: column; height: 100vh; }
|
||||||
</style>
|
</style>
|
||||||
<script type="module" crossorigin src="/assets/index-DujVfZi9.js"></script>
|
<script type="module" crossorigin src="/assets/index-CnGkEkb-.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-nUMfzhFe.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-CSwdbBmn.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ export const useParticleStore = defineStore('particle', {
|
|||||||
// 与 Spine 编辑器默认时间基准对齐:1 秒 = 30 帧。
|
// 与 Spine 编辑器默认时间基准对齐:1 秒 = 30 帧。
|
||||||
timeline: { playing: true, loop: true, frame: 0, totalFrames: 60, fps: 30, recorded: false, animation: 'animation', animations: ['animation'] } as TimelineState,
|
timeline: { playing: true, loop: true, frame: 0, totalFrames: 60, fps: 30, recorded: false, animation: 'animation', animations: ['animation'] } as TimelineState,
|
||||||
settings: {
|
settings: {
|
||||||
parameterPanelOnRight: false,
|
parameterPanelOnRight: true,
|
||||||
tickEnabled: false,
|
tickEnabled: false,
|
||||||
axisFontSize: 12,
|
axisFontSize: 12,
|
||||||
tickWidth: 1,
|
tickWidth: 1,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
<span>Spine粒子编辑器</span>
|
<span>Spine粒子编辑器-Yeomai</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="panel-scroll">
|
<div class="panel-scroll">
|
||||||
|
|||||||
+1
-1
@@ -209,7 +209,7 @@ const canvasFocused = ref(false)
|
|||||||
function toggleTool(t: '' | 'translate' | 'rotate' | 'scale') { activeTool.value = activeTool.value === t ? '' : t }
|
function toggleTool(t: '' | 'translate' | 'rotate' | 'scale') { activeTool.value = activeTool.value === t ? '' : t }
|
||||||
|
|
||||||
if (!(store.settings.undoLimit > 0)) store.settings.undoLimit = 20
|
if (!(store.settings.undoLimit > 0)) store.settings.undoLimit = 20
|
||||||
if (store.settings.parameterPanelOnRight == null) store.settings.parameterPanelOnRight = false
|
if (store.settings.parameterPanelOnRight == null) store.settings.parameterPanelOnRight = true
|
||||||
if (!Number.isFinite(store.settings.backgroundX)) store.settings.backgroundX = 0
|
if (!Number.isFinite(store.settings.backgroundX)) store.settings.backgroundX = 0
|
||||||
if (!Number.isFinite(store.settings.backgroundY)) store.settings.backgroundY = 0
|
if (!Number.isFinite(store.settings.backgroundY)) store.settings.backgroundY = 0
|
||||||
if (!Number.isFinite(store.settings.backgroundOpacity)) store.settings.backgroundOpacity = 1
|
if (!Number.isFinite(store.settings.backgroundOpacity)) store.settings.backgroundOpacity = 1
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
setlocal
|
||||||
|
|
||||||
|
set "PROJECT_DIR=%~dp0"
|
||||||
|
set "RUN_DIR=%PROJECT_DIR%.run"
|
||||||
|
set "PID_FILE=%RUN_DIR%\spine-particle-windows.pid"
|
||||||
|
|
||||||
|
cd /d "%PROJECT_DIR%"
|
||||||
|
|
||||||
|
if not exist "%PID_FILE%" (
|
||||||
|
echo 没有发现由“启动项目-Windows.bat”启动的项目进程。
|
||||||
|
exit /b 0
|
||||||
|
)
|
||||||
|
|
||||||
|
set /p SERVER_PID=<"%PID_FILE%"
|
||||||
|
powershell -NoProfile -Command ^
|
||||||
|
"$process=Get-CimInstance Win32_Process -Filter ('ProcessId = ' + $env:SERVER_PID) -ErrorAction SilentlyContinue;" ^
|
||||||
|
"if ($null -eq $process) { exit 2 };" ^
|
||||||
|
"$expected=(Join-Path $env:PROJECT_DIR 'node_modules\vite\bin\vite.js');" ^
|
||||||
|
"if ($process.CommandLine -notlike ('*' + $expected + '*')) { exit 3 };" ^
|
||||||
|
"Stop-Process -Id ([int]$env:SERVER_PID) -Force; exit 0"
|
||||||
|
|
||||||
|
set "STOP_RESULT=%ERRORLEVEL%"
|
||||||
|
if "%STOP_RESULT%"=="3" (
|
||||||
|
echo PID 已被其他程序占用,为避免误关进程,本次未执行停止操作。
|
||||||
|
del /q "%PID_FILE%" >nul 2>&1
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
del /q "%PID_FILE%" >nul 2>&1
|
||||||
|
if "%STOP_RESULT%"=="2" (
|
||||||
|
echo 项目已经停止。
|
||||||
|
) else if "%STOP_RESULT%"=="0" (
|
||||||
|
echo 项目已停止。
|
||||||
|
) else (
|
||||||
|
echo 停止项目失败,请检查 PowerShell 权限。
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
exit /b 0
|
||||||
Executable
+46
@@ -0,0 +1,46 @@
|
|||||||
|
#!/bin/zsh
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
PROJECT_DIR="${0:A:h}"
|
||||||
|
RUN_DIR="$PROJECT_DIR/.run"
|
||||||
|
PID_FILE="$RUN_DIR/spine-particle.pid"
|
||||||
|
|
||||||
|
cd "$PROJECT_DIR" || exit 1
|
||||||
|
|
||||||
|
if [[ ! -f "$PID_FILE" ]]; then
|
||||||
|
echo "没有发现由“启动项目.command”启动的项目进程。"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
SERVER_PID="$(tr -dc '0-9' < "$PID_FILE")"
|
||||||
|
if [[ -z "$SERVER_PID" ]] || ! kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
echo "项目已经停止。"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
SERVER_COMMAND="$(ps -p "$SERVER_PID" -o command= 2>/dev/null || true)"
|
||||||
|
if [[ "$SERVER_COMMAND" != *"$PROJECT_DIR/node_modules/vite/"* ]]; then
|
||||||
|
echo "PID 已被其他程序占用,为避免误关进程,本次未执行停止操作。"
|
||||||
|
echo "当前进程:$SERVER_COMMAND"
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
read "?按回车键关闭窗口..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "正在停止 Spine粒子编辑器..."
|
||||||
|
kill "$SERVER_PID" 2>/dev/null || true
|
||||||
|
for _ in {1..20}; do
|
||||||
|
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
echo "项目已停止。"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 0.1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "普通停止未响应,正在强制结束该项目进程..."
|
||||||
|
kill -KILL "$SERVER_PID" 2>/dev/null || true
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
echo "项目已停止。"
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
setlocal
|
||||||
|
|
||||||
|
set "PROJECT_DIR=%~dp0"
|
||||||
|
set "RUN_DIR=%PROJECT_DIR%.run"
|
||||||
|
set "PID_FILE=%RUN_DIR%\spine-particle-windows.pid"
|
||||||
|
set "OUT_LOG=%RUN_DIR%\spine-particle-windows.log"
|
||||||
|
set "ERROR_LOG=%RUN_DIR%\spine-particle-windows-error.log"
|
||||||
|
set "PROJECT_URL=http://127.0.0.1:5173/"
|
||||||
|
|
||||||
|
if not exist "%RUN_DIR%" mkdir "%RUN_DIR%"
|
||||||
|
cd /d "%PROJECT_DIR%"
|
||||||
|
|
||||||
|
if exist "%PID_FILE%" (
|
||||||
|
set /p SERVER_PID=<"%PID_FILE%"
|
||||||
|
powershell -NoProfile -Command "if (Get-Process -Id $env:SERVER_PID -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }"
|
||||||
|
if not errorlevel 1 (
|
||||||
|
echo Spine粒子编辑器已经在运行,正在打开页面:
|
||||||
|
echo %PROJECT_URL%
|
||||||
|
start "" "%PROJECT_URL%"
|
||||||
|
exit /b 0
|
||||||
|
)
|
||||||
|
del /q "%PID_FILE%" >nul 2>&1
|
||||||
|
)
|
||||||
|
|
||||||
|
where npm >nul 2>&1
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo 未找到 npm,请先安装 Node.js:
|
||||||
|
echo https://nodejs.org/
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if not exist "%PROJECT_DIR%node_modules\vite\bin\vite.js" (
|
||||||
|
echo 首次运行,正在安装项目依赖...
|
||||||
|
call npm install
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo 依赖安装失败,请检查网络或 npm 配置。
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 正在启动 Spine粒子编辑器...
|
||||||
|
powershell -NoProfile -Command ^
|
||||||
|
"$node=(Get-Command node).Source; $vite=Join-Path $env:PROJECT_DIR 'node_modules\vite\bin\vite.js';" ^
|
||||||
|
"$arguments=@($vite,'--host','127.0.0.1','--port','5173','--strictPort');" ^
|
||||||
|
"$process=Start-Process -FilePath $node -ArgumentList $arguments -WorkingDirectory $env:PROJECT_DIR -RedirectStandardOutput $env:OUT_LOG -RedirectStandardError $env:ERROR_LOG -WindowStyle Hidden -PassThru;" ^
|
||||||
|
"Set-Content -Path $env:PID_FILE -Value $process.Id -Encoding ascii"
|
||||||
|
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo 项目启动失败。
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
set /p SERVER_PID=<"%PID_FILE%"
|
||||||
|
timeout /t 2 /nobreak >nul
|
||||||
|
powershell -NoProfile -Command "if (Get-Process -Id $env:SERVER_PID -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }"
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo 项目启动失败,错误日志如下:
|
||||||
|
if exist "%ERROR_LOG%" type "%ERROR_LOG%"
|
||||||
|
del /q "%PID_FILE%" >nul 2>&1
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 启动成功:%PROJECT_URL%
|
||||||
|
start "" "%PROJECT_URL%"
|
||||||
|
exit /b 0
|
||||||
Executable
+64
@@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/zsh
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
PROJECT_DIR="${0:A:h}"
|
||||||
|
RUN_DIR="$PROJECT_DIR/.run"
|
||||||
|
PID_FILE="$RUN_DIR/spine-particle.pid"
|
||||||
|
LOG_FILE="$RUN_DIR/spine-particle.log"
|
||||||
|
URL="http://127.0.0.1:5173/"
|
||||||
|
|
||||||
|
mkdir -p "$RUN_DIR"
|
||||||
|
cd "$PROJECT_DIR" || exit 1
|
||||||
|
|
||||||
|
if [[ -f "$PID_FILE" ]]; then
|
||||||
|
RUNNING_PID="$(tr -dc '0-9' < "$PID_FILE")"
|
||||||
|
if [[ -n "$RUNNING_PID" ]] && kill -0 "$RUNNING_PID" 2>/dev/null; then
|
||||||
|
echo "Spine粒子编辑器已经在运行,正在打开页面:"
|
||||||
|
echo "$URL"
|
||||||
|
open "$URL"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v npm >/dev/null 2>&1; then
|
||||||
|
echo "未找到 npm,请先安装 Node.js。"
|
||||||
|
echo "https://nodejs.org/"
|
||||||
|
read "?按回车键关闭窗口..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -x "$PROJECT_DIR/node_modules/.bin/vite" ]]; then
|
||||||
|
echo "首次运行,正在安装项目依赖..."
|
||||||
|
npm install || {
|
||||||
|
echo "依赖安装失败,请检查网络或 npm 配置。"
|
||||||
|
read "?按回车键关闭窗口..."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "正在启动 Spine粒子编辑器..."
|
||||||
|
nohup "$PROJECT_DIR/node_modules/.bin/vite" --host 127.0.0.1 --port 5173 --strictPort > "$LOG_FILE" 2>&1 &
|
||||||
|
SERVER_PID=$!
|
||||||
|
echo "$SERVER_PID" > "$PID_FILE"
|
||||||
|
|
||||||
|
for _ in {1..60}; do
|
||||||
|
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||||
|
echo "项目启动失败,日志如下:"
|
||||||
|
tail -n 30 "$LOG_FILE"
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
read "?按回车键关闭窗口..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if curl -fsS "$URL" >/dev/null 2>&1; then
|
||||||
|
echo "启动成功:$URL"
|
||||||
|
open "$URL"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 0.25
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "项目启动超时,请查看日志:$LOG_FILE"
|
||||||
|
read "?按回车键关闭窗口..."
|
||||||
|
exit 1
|
||||||
Reference in new issue
Block a user