@@ -38,6 +38,12 @@ import {
3838 validateDoTickExpressionSource ,
3939 normalizeDoTickExpression ,
4040} from "./do_tick_expression.js" ;
41+ import {
42+ loadAllParticleData ,
43+ getParticleDataByName ,
44+ getParticleEffectNames ,
45+ setBasePath ,
46+ } from "../../particles/particle_data_loader.js" ;
4147
4248( ( ) => {
4349 const EMITTER_TYPE_META = {
@@ -86,6 +92,7 @@ import {
8692 "particle.velSpeedMax" : "速度倍率上限。" ,
8793 "particle.visibleRange" : "可见范围(作用于游戏渲染距离)。" ,
8894
95+ "template.effectClass" : "粒子效果类(决定粒子纹理和渲染方式)。" ,
8996 "template.alpha" : "透明度(0~1)。" ,
9097 "template.light" : "亮度(0~15)。" ,
9198 "template.sign" : "粒子 sign 标识(用于 Command 过滤)。" ,
@@ -137,6 +144,7 @@ import {
137144 "emitter.spiral.axis.x" : "螺旋轴 X(会 normalize)。" ,
138145 "emitter.spiral.axis.y" : "螺旋轴 Y(会 normalize)。" ,
139146 "emitter.spiral.axis.z" : "螺旋轴 Z(会 normalize)。" ,
147+ "template.useTexture" : "预览是否使用纹理渲染;关闭后始终使用纯色点渲染。" ,
140148 } ;
141149
142150 const uid = ( ) => ( Math . random ( ) . toString ( 16 ) . slice ( 2 ) + Date . now ( ) . toString ( 16 ) ) . slice ( 0 , 12 ) ;
@@ -186,6 +194,8 @@ import {
186194 colorEnd : "#d04dff" ,
187195 } ,
188196 template : {
197+ effectClass : "ControlableEndRodEffect" ,
198+ useTexture : true ,
189199 alpha : 1.0 ,
190200 light : 15 ,
191201 faceToCamera : true ,
@@ -209,6 +219,7 @@ import {
209219 emitters : [ makeDefaultEmitterCard ( ) ] ,
210220 playing : true ,
211221 autoPaused : false ,
222+ focusedEmitterId : "" ,
212223 ticksPerSecond : 20 ,
213224 fullscreen : false ,
214225 kotlin : {
@@ -614,6 +625,8 @@ import {
614625
615626
616627 const template = card . template || ( card . template = { } ) ;
628+ template . effectClass = String ( template . effectClass || "ControlableEndRodEffect" ) . trim ( ) ;
629+ template . useTexture = ( template . useTexture !== false ) ;
617630 template . alpha = normalizeNumExpr ( template . alpha , 1.0 , { min : 0 , max : 1 } ) ;
618631 template . light = normalizeNumExpr ( template . light , 15 , { int : true , min : 0 , max : 15 } ) ;
619632 template . faceToCamera = ( template . faceToCamera !== false ) ;
@@ -2410,6 +2423,17 @@ function setVelocitySection($card, mode) {
24102423 } ) ;
24112424 }
24122425
2426+ function buildEffectClassOptionsHtml ( selected ) {
2427+ const dynamicNames = getParticleEffectNames ( ) ;
2428+ const base = [ "ControlableEndRodEffect" , "ControlableCloudEffect" ] ;
2429+ const all = Array . from ( new Set ( [ ...base , ...dynamicNames , String ( selected || "" ) . trim ( ) ] . filter ( Boolean ) ) ) ;
2430+ return all . map ( ( name ) => {
2431+ const pData = getParticleDataByName ( name ) ;
2432+ const label = pData && pData . displayName ? `${ name } (${ pData . displayName } )` : name ;
2433+ return `<option value="${ escapeHtml ( name ) } " ${ name === selected ? "selected" : "" } >${ escapeHtml ( label ) } </option>` ;
2434+ } ) . join ( "" ) ;
2435+ }
2436+
24132437 function renderEmitterList ( ) {
24142438 const $list = $ ( "#emitList" ) ;
24152439 $list . empty ( ) ;
@@ -2589,6 +2613,19 @@ function setVelocitySection($card, mode) {
25892613 ` </div>` ,
25902614
25912615` <div class="panel-subtitle">模板参数(高级)</div>` ,
2616+ ` <div class="field" style="margin-bottom:6px">` ,
2617+ ` <label>粒子效果类</label>` ,
2618+ ` <select class="emitInput" data-key="template.effectClass" data-type="string">` ,
2619+ ` ${ buildEffectClassOptionsHtml ( card . template && card . template . effectClass ) } ` ,
2620+ ` </select>` ,
2621+ ` </div>` ,
2622+ ` <div class="field" style="margin-bottom:6px">` ,
2623+ ` <label>预览纹理渲染</label>` ,
2624+ ` <select class="emitInput" data-key="template.useTexture" data-type="bool">` ,
2625+ ` <option value="1" ${ ( card . template && card . template . useTexture === false ) ? "" : "selected" } >启用</option>` ,
2626+ ` <option value="0" ${ ( card . template && card . template . useTexture === false ) ? "selected" : "" } >关闭</option>` ,
2627+ ` </select>` ,
2628+ ` </div>` ,
25922629` <div class="grid3">` ,
25932630` <div class="field">` ,
25942631` <label>alpha(0~1)</label>` ,
@@ -2836,6 +2873,7 @@ function setVelocitySection($card, mode) {
28362873 $card . find ( '[data-key="externalTemplate"]' ) . val ( card . externalTemplate ? "1" : "0" ) ;
28372874 $card . find ( '[data-key="externalData"]' ) . val ( card . externalData ? "1" : "0" ) ;
28382875 $card . find ( '[data-key="particle.velMode"]' ) . val ( card . particle && card . particle . velMode ? card . particle . velMode : "fixed" ) ;
2876+ $card . find ( '[data-key="template.useTexture"]' ) . val ( ( card . template && card . template . useTexture === false ) ? "0" : "1" ) ;
28392877 $card . find ( '[data-key="template.faceToCamera"]' ) . val ( ( card . template && card . template . faceToCamera === false ) ? "0" : "1" ) ;
28402878 $card . find ( '[data-key="emitter.box.surface"]' ) . val ( card . emitter . box . surface ? "1" : "0" ) ;
28412879
@@ -3071,6 +3109,8 @@ function setVelocitySection($card, mode) {
30713109 }
30723110
30733111 const EXTERNAL_TEMPLATE_SYNC_FIELDS = [
3112+ "template.effectClass" ,
3113+ "template.useTexture" ,
30743114 "template.alpha" ,
30753115 "template.light" ,
30763116 "template.faceToCamera" ,
@@ -7887,6 +7927,7 @@ function setVelocitySection($card, mode) {
78877927 if ( focusedEmitterId !== id ) {
78887928 handleEmitterCollapseFocusChange ( focusedEmitterId , id ) ;
78897929 focusedEmitterId = id ;
7930+ state . focusedEmitterId = id ;
78907931 }
78917932 } ) ;
78927933
@@ -7896,6 +7937,7 @@ function setVelocitySection($card, mode) {
78967937 if ( ! focusedEmitterId ) return ;
78977938 handleEmitterCollapseFocusChange ( focusedEmitterId , null ) ;
78987939 focusedEmitterId = null ;
7940+ state . focusedEmitterId = "" ;
78997941 } ) ;
79007942
79017943 $ ( "#emitList" ) . on ( "click" , ".emitHead" , function ( e ) {
@@ -7943,6 +7985,7 @@ function setVelocitySection($card, mode) {
79437985 return ;
79447986 }
79457987 state . emitters = state . emitters . filter ( ( it ) => it . id !== id ) ;
7988+ if ( state . focusedEmitterId === id ) state . focusedEmitterId = "" ;
79467989 if ( emitterSync ) removeEmitterSyncTarget ( id ) ;
79477990 cardHistory . push ( ) ;
79487991 renderEmitterList ( ) ;
@@ -8754,6 +8797,11 @@ function setVelocitySection($card, mode) {
87548797 syncEmitterBuilderVarContextStorage ( ) ;
87558798 const returnedEmitterId = consumeEmitterBuilderReturnState ( ) ;
87568799
8800+ setBasePath ( "./" ) ;
8801+ loadAllParticleData ( ) . then ( ( ) => {
8802+ renderEmitterList ( ) ;
8803+ } ) ;
8804+
87578805 initPanelTools ( ) ;
87588806 applyStateToForm ( ) ;
87598807 // Queue list page can be the default workspace. Render once to bind
0 commit comments