Advertisement
snake5

particle system editor

Oct 6th, 2015
442
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 33.96 KB | None | 0 0
  1.  
  2.  
  3. #include <engine.hpp>
  4. #include <enganim.hpp>
  5. #include <edgui.hpp>
  6. #include "edcomui.hpp"
  7.  
  8.  
  9. struct EDGUIMainFrame* g_UIFrame;
  10. SceneHandle g_EdScene;
  11. struct EdParticleSystem* g_EdPS;
  12. struct EdDualGraph* g_UIGraphEd;
  13. struct EDGUISDTexPicker* g_UITexPicker;
  14. struct EDGUIShaderPicker* g_UIShaderPicker;
  15. struct EDGUIMeshPicker* g_UIMeshPicker;
  16. struct EDGUIPSOpenPicker* g_UIPSOpenPicker;
  17. struct EDGUIPSSavePicker* g_UIPSSavePicker;
  18. struct EDGUIPSISFXPicker* g_UIPSISFXPicker;
  19.  
  20.  
  21.  
  22. struct EDGUIShaderPicker : EDGUIRsrcPicker
  23. {
  24.     EDGUIShaderPicker()
  25.     {
  26.         Reload();
  27.     }
  28.     void Reload()
  29.     {
  30.         LOG << "Reloading shaders";
  31.         m_options.clear();
  32.         DirectoryIterator tdi( "shaders" );
  33.         while( tdi.Next() )
  34.         {
  35.             StringView fn = tdi.Name();
  36.             LOG << fn;
  37.             if( !tdi.IsDirectory() )
  38.             {
  39.                 if( fn.ends_with( ".shd" ) && fn.starts_with( "mtl_" ) )
  40.                 {
  41.                     m_options.push_back( fn.part( 4, fn.size() - 8 ) );
  42.                 }
  43.             }
  44.         }
  45.         _Search( m_searchString );
  46.     }
  47. };
  48.  
  49.  
  50. struct EDGUIPSPicker : EDGUIRsrcPicker, IDirEntryHandler
  51. {
  52.     EDGUIPSPicker(){ Reload(); }
  53.     void Reload()
  54.     {
  55.         LOG << "Reloading particle systems";
  56.         m_options.clear();
  57.         FS_IterateDirectory( "psys", this );
  58.         _Search( m_searchString );
  59.     }
  60.     bool HandleDirEntry( const StringView& loc, const StringView& name, bool isdir )
  61.     {
  62.         LOG << "[P]: " << name;
  63.         if( !isdir && name.ends_with( ".psy" ) )
  64.         {
  65.             m_options.push_back( name.part( 0, name.size() - 4 ) );
  66.         }
  67.         return true;
  68.     }
  69.     virtual void _OnChangeZoom()
  70.     {
  71.         EDGUIRsrcPicker::_OnChangeZoom();
  72.         m_itemHeight /= 4;
  73.     }
  74.    
  75.     virtual int OnEvent( EDGUIEvent* e )
  76.     {
  77.         if( e->type == EDGUI_EVENT_PROPCHANGE && e->target == &m_confirm )
  78.         {
  79.             if( m_confirm.m_value == 1 )
  80.             {
  81.                 EDGUIRsrcPicker::_OnPickResource();
  82.             }
  83.             return 1;
  84.         }
  85.         return EDGUIRsrcPicker::OnEvent( e );
  86.     }
  87.    
  88.     EDGUIQuestion m_confirm;
  89. };
  90.  
  91. struct EDGUIPSOpenPicker : EDGUIPSPicker
  92. {
  93.     EDGUIPSOpenPicker()
  94.     {
  95.         caption = "Pick a particle system to open";
  96.         m_confirm.caption = "Do you really want to open the particle system? All unsaved changes will be lost!";
  97.     }
  98.     virtual void _OnPickResource()
  99.     {
  100.         m_confirm.Open( this );
  101.         m_frame->Add( &m_confirm );
  102.     }
  103. };
  104.  
  105. struct EDGUIPSSavePicker : EDGUIPSPicker
  106. {
  107.     EDGUIPSSavePicker()
  108.     {
  109.         caption = "Pick a particle system to save or write the name";
  110.         m_confirm.caption = "Do you really want to overwrite the particle system?";
  111.     }
  112.     virtual void _OnPickResource()
  113.     {
  114.         if( m_options.find_first_at( m_pickedOption ) == NOT_FOUND )
  115.             EDGUIRsrcPicker::_OnPickResource();
  116.         else
  117.         {
  118.             m_confirm.Open( this );
  119.             m_frame->Add( &m_confirm );
  120.         }
  121.     }
  122.     virtual void _OnConfirm()
  123.     {
  124.         _OnPickResource();
  125.     }
  126. };
  127.  
  128. struct EDGUIPSISFXPicker : EDGUIRsrcPicker
  129. {
  130.     EDGUIPSISFXPicker()
  131.     {
  132.         caption = "Pick a particle intersection effect";
  133.         Reload();
  134.     }
  135.     void Reload()
  136.     {
  137.         LOG << "Reloading particle intersection effects";
  138.        
  139.         Name2FXID.clear();
  140.         FXID2Name.clear();
  141.         m_options.clear();
  142.        
  143.         String isfx_data;
  144.         if( FS_LoadTextFile( "editor/psys_isfx.txt", isfx_data ) == false )
  145.         {
  146.             LOG_ERROR << LOG_DATE << "  Failed to load editor/psys_isfx.txt";
  147.             _Search( m_searchString );
  148.             return;
  149.         }
  150.         ConfigReader cr( isfx_data );
  151.         StringView key, value;
  152.         while( cr.Read( key, value ) )
  153.         {
  154.             int id = String_ParseInt( key );
  155.             char bfr[ 32 ];
  156.             sgrx_snprintf( bfr, 32, "%d: ", id );
  157.             String name = bfr;
  158.             name.append( value );
  159.            
  160.             Name2FXID.set( name, id );
  161.             FXID2Name.set( id, name );
  162.             m_options.push_back( name );
  163.         }
  164.        
  165.         LOG << "Loaded " << m_options.size() << " effects!";
  166.        
  167.         _Search( m_searchString );
  168.     }
  169.    
  170.     static int GetFXIDFromName( const StringView& name )
  171.     {
  172.         int* ptr = Name2FXID.getptr( name );
  173.         if( ptr )
  174.             return *ptr;
  175.         return String_ParseInt( name.until( ":" ) );
  176.     }
  177.     static String GetNameFromFXID( int id )
  178.     {
  179.         String* ptr = FXID2Name.getptr( id );
  180.         if( ptr )
  181.             return *ptr;
  182.         char bfr[ 32 ];
  183.         sgrx_snprintf( bfr, 32, "%d: --unknown--" );
  184.         return bfr;
  185.     }
  186.    
  187.     static HashTable< String, int > Name2FXID;
  188.     static HashTable< int, String > FXID2Name;
  189. };
  190. HashTable< String, int > EDGUIPSISFXPicker::Name2FXID;
  191. HashTable< int, String > EDGUIPSISFXPicker::FXID2Name;
  192.  
  193.  
  194. struct EdDualGraph : EDGUIItem
  195. {
  196.     EdDualGraph() :
  197.         m_mouseX(0), m_mouseY(0),
  198.         m_A(false), m_B(false),
  199.         m_data(NULL), m_size(0)
  200.     {}
  201.    
  202.     int OnEvent( EDGUIEvent* e )
  203.     {
  204.         switch( e->type )
  205.         {
  206.         case EDGUI_EVENT_MOUSEMOVE:
  207.             m_mouseX = e->mouse.x;
  208.             m_mouseY = e->mouse.y;
  209.             PaintGraph();
  210.             break;
  211.         case EDGUI_EVENT_BTNDOWN:
  212.             if( e->mouse.button == 0 ) m_A = true;
  213.             if( e->mouse.button == 1 ) m_B = true;
  214.             PaintGraph();
  215.             break;
  216.         case EDGUI_EVENT_BTNUP:
  217.             if( e->mouse.button == 0 ) m_A = false;
  218.             if( e->mouse.button == 1 ) m_B = false;
  219.             PaintGraph();
  220.             break;
  221.         case EDGUI_EVENT_LAYOUT:
  222.             x0 = e->layout.x0 + 8;
  223.             y0 = e->layout.y0 + 8;
  224.             x1 = e->layout.x1 - 8;
  225.             y1 = e->layout.y1 - 8;
  226.             return 1;
  227.         case EDGUI_EVENT_PAINT:
  228.             EDGUIItem::OnEvent( e );
  229.             if( m_data )
  230.             {
  231.                 BatchRenderer& br = GR2D_GetBatchRenderer();
  232.                 br.Reset().Col( 0, 0.5f );
  233.                 br.Quad( x0, y0, x1, y1 );
  234.                 if( m_size > 1 )
  235.                 {
  236.                     br.Col( 0.1f, 0.7f, 0 );
  237.                     br.SetPrimitiveType( PT_LineStrip );
  238.                     for( size_t i = 0; i < m_size; ++i )
  239.                     {
  240.                         float x = x0 + ( x1 - x0 ) * i / (float) ( m_size - 1 );
  241.                         float y = y1 + ( y0 - y1 ) * m_data[ i ].x;
  242.                         br.Pos( x, y );
  243.                     }
  244.                     br.Col( 0.7f, 0.1f, 0 );
  245.                     br.SetPrimitiveType( PT_LineStrip );
  246.                     for( size_t i = 0; i < m_size; ++i )
  247.                     {
  248.                         float x = x0 + ( x1 - x0 ) * i / (float) ( m_size - 1 );
  249.                         float y = y1 + ( y0 - y1 ) * m_data[ i ].y;
  250.                         br.Pos( x, y );
  251.                     }
  252.                     br.Flush();
  253.                 }
  254.             }
  255.             return 1;
  256.         }
  257.         return EDGUIItem::OnEvent( e );
  258.     }
  259.    
  260.     void PaintGraph()
  261.     {
  262.         if( !m_data || !m_size || x1 <= x0 || y1 <= y0 )
  263.             return;
  264.        
  265.         // convert mouse position into graph position
  266.         float x = float( m_mouseX - x0 ) / float( x1 - x0 ) * ( m_size - 1 );
  267.         float y = clamp( float( m_mouseY - y1 ) / float( y0 - y1 ), 0, 1 );
  268.        
  269.         int at = round( clamp( x, 0, m_size - 1 ) );
  270.         if( m_A ) m_data[ at ].x = y;
  271.         if( m_B ) m_data[ at ].y = y;
  272.     }
  273.    
  274.     void SetCurve( Vec2* p, size_t s )
  275.     {
  276.         m_data = p;
  277.         m_size = s;
  278.     }
  279.     void UnsetCurve(){ SetCurve( NULL, 0 ); }
  280.    
  281.     int m_mouseX;
  282.     int m_mouseY;
  283.     bool m_A;
  284.     bool m_B;
  285.    
  286.     Vec2* m_data;
  287.     size_t m_size;
  288. };
  289.  
  290. struct EdEmitCurve : EDGUIGroup
  291. {
  292.     EdEmitCurve( bool open, const StringView& name = StringView() ) :
  293.         EDGUIGroup( open, name ),
  294.         curveSize( 1, 1, 1024 ),
  295.         randomValDvg( V2(0), 2, V2(-100), V2(100) ),
  296.         valueRange( V2(0,1), 2, V2(-1000), V2(1000) )
  297.     {
  298.         editBtn.caption = "Edit curve";
  299.         curveSize.caption = "# of sample points";
  300.         randomValDvg.caption = "Random value/divergence";
  301.         valueRange.caption = "Min./max. values";
  302.        
  303.         Add( &editBtn );
  304.         Add( &curveSize );
  305.         Add( &randomValDvg );
  306.         Add( &valueRange );
  307.     }
  308.    
  309.     void SetValue( ParticleSystem::Emitter::Curve& curve )
  310.     {
  311.         m_curve = &curve;
  312.        
  313.         curveSize.SetValue( curve.values.size() );
  314.         randomValDvg.SetValue( curve.randomValDvg );
  315.         valueRange.SetValue( curve.valueRange );
  316.     }
  317.    
  318.     int OnEvent( EDGUIEvent* e )
  319.     {
  320.         switch( e->type )
  321.         {
  322.         case EDGUI_EVENT_PROPCHANGE:
  323.             if( e->target == &curveSize )
  324.             {
  325.                 int ncs = curveSize.m_value;
  326.                 if( ncs < 1 ) ncs = 1;
  327.                 if( ncs > 1024 ) ncs = 1024;
  328.                 m_curve->values.resize( ncs );
  329.             }
  330.             break;
  331.         case EDGUI_EVENT_PROPEDIT:
  332.             if( e->target == &randomValDvg ) m_curve->randomValDvg = randomValDvg.m_value;
  333.             if( e->target == &valueRange ) m_curve->valueRange = valueRange.m_value;
  334.             break;
  335.         case EDGUI_EVENT_BTNCLICK:
  336.             if( e->target == &editBtn )
  337.             {
  338.                 g_UIGraphEd->SetCurve( m_curve->values.data(), m_curve->values.size() );
  339.             }
  340.             break;
  341.         case EDGUI_EVENT_PAINT:
  342.             EDGUIGroup::OnEvent( e );
  343.             {
  344.                 int rx0 = ( x0 + x1 ) / 2 + 2;
  345.                 int ry0 = y0 + 2;
  346.                 int rx1 = x1 - 2;
  347.                 int ry1 = y0 + EDGUI_THEME_GROUP_HEIGHT - 2;
  348.                
  349.                 BatchRenderer& br = GR2D_GetBatchRenderer();
  350.                 br.Reset().Col( 0, 0.5f );
  351.                 br.Quad( rx0, ry0, rx1, ry1 );
  352.                 if( m_curve->values.size() > 1 )
  353.                 {
  354.                     br.Col( 0.1f, 0.7f, 0 );
  355.                     br.SetPrimitiveType( PT_LineStrip );
  356.                     for( size_t i = 0; i < m_curve->values.size(); ++i )
  357.                     {
  358.                         float x = rx0 + ( rx1 - rx0 ) * i / (float) ( m_curve->values.size() - 1 );
  359.                         float y = ry1 + ( ry0 - ry1 ) * m_curve->values[ i ].x;
  360.                         br.Pos( x, y );
  361.                     }
  362.                     br.Col( 0.7f, 0.1f, 0 );
  363.                     br.SetPrimitiveType( PT_LineStrip );
  364.                     for( size_t i = 0; i < m_curve->values.size(); ++i )
  365.                     {
  366.                         float x = rx0 + ( rx1 - rx0 ) * i / (float) ( m_curve->values.size() - 1 );
  367.                         float y = ry1 + ( ry0 - ry1 ) * m_curve->values[ i ].y;
  368.                         br.Pos( x, y );
  369.                     }
  370.                     br.Flush();
  371.                 }
  372.             }
  373.             return 1;
  374.         }
  375.         return EDGUIGroup::OnEvent( e );
  376.     }
  377.    
  378.     ParticleSystem::Emitter::Curve* m_curve;
  379.    
  380.     EDGUIButton editBtn;
  381.     EDGUIPropInt curveSize;
  382.     EDGUIPropVec2 randomValDvg;
  383.     EDGUIPropVec2 valueRange;
  384. };
  385.  
  386. #define MAX_PARTICLES 10000
  387. #define MAX_TIME 120.0f
  388. #define MAX_POS 8192.0f
  389. #define MAX_NORMAL 100.0f
  390. #define MAX_VEL 100.0f
  391.  
  392. static String GetParticleTexName( const TextureHandle& tex )
  393. {
  394.     if( !tex )
  395.         return String();
  396.     StringView oname = tex->m_key;
  397.     if( oname.starts_with( "textures/particles/" ) && oname.ends_with( ".png" ) )
  398.         return oname.part( sizeof("textures/particles/")-1, oname.size() - (sizeof("textures/particles/.png")-1) );
  399.     // cannot resolve:
  400.     return oname;
  401. }
  402.  
  403. static TextureHandle GetParticleTexHandle( const StringView& sv )
  404. {
  405.     if( !sv )
  406.         return TextureHandle();
  407.     char bfr[ 1024 ] = {0};
  408.     sgrx_snprintf( bfr, 1024, "textures/particles/%.*s.png", TMIN( 980, (int) sv.size() ), sv.data() );
  409.     return GR_GetTexture( bfr );
  410. }
  411.  
  412. struct EdEmitter : EDGUILayoutRow
  413. {
  414.     EdEmitter() :
  415.         grpSpawn( false, "Spawn properties" ),
  416.         spawn_MaxCount( 0, 0, MAX_PARTICLES ),
  417.         spawn_Count( 0, 0, MAX_PARTICLES ),
  418.         spawn_CountExt( 0, 0, MAX_PARTICLES ),
  419.         spawn_TimeExt( V2(0), 2, V2(0), V2(MAX_TIME) ),
  420.        
  421.         grpPosition( false, "Initial position" ),
  422.         create_Pos( V3(0), 2, V3(-MAX_POS), V3(MAX_POS) ),
  423.         create_PosBox( V3(0), 2, V3(0), V3(MAX_POS) ),
  424.         create_PosRadius( 0, 2, 0, MAX_POS ),
  425.        
  426.         grpVelocity( false, "Initial velocity" ),
  427.         create_VelMicroDir( V3(0), 2, V3(-MAX_NORMAL), V3(MAX_NORMAL) ),
  428.         create_VelMicroDvg( 0, 2, 0, 1 ),
  429.         create_VelMicroDistExt( V2(0), 2, V2(-MAX_VEL), V2(MAX_VEL) ),
  430.         create_VelMacroDir( V3(0), 2, V3(-MAX_NORMAL), V3(MAX_NORMAL) ),
  431.         create_VelMacroDvg( 0, 2, 0, 1 ),
  432.         create_VelMacroDistExt( V2(0), 2, V2(-MAX_VEL), V2(MAX_VEL) ),
  433.         create_VelCluster( 0, 0, MAX_PARTICLES ),
  434.         create_VelClusterExt( 0, 0, MAX_PARTICLES ),
  435.        
  436.         grpMisc( false, "Misc. properties" ),
  437.         create_LifetimeExt( V2(0), 2, V2(0), V2(MAX_TIME) ),
  438.         create_AngleDirDvg( V2(0), 2, V2(0,0), V2(360,180) ),
  439.         create_AngleVelDvg( V2(0), 2, V2(-1000), V2(1000) ),
  440.         tick_AngleAcc( 0, 2, -10000, 10000 ),
  441.         tick_GravityMult( 1, 2, 0, 100 ),
  442.         absolute( true ),
  443.        
  444.         grpIsect( false, "Intersection" ),
  445.         isect_Limit( 0, 0, MAX_PARTICLES ),
  446.         isect_Friction( 0, 2, 0, 1 ),
  447.         isect_Bounce( 0, 2, 0, 1 ),
  448.         isect_FXID( g_UIPSISFXPicker, EDGUIPSISFXPicker::GetNameFromFXID( 0 ) ),
  449.         isect_FXChance( 0, 2, 0, 1 ),
  450.         isect_Remove( false ),
  451.        
  452.         grpSizeColor( false, "Size/color curves" ),
  453.         curve_Size( false, "Size" ),
  454.         curve_ColorHue( false, "Color - hue" ),
  455.         curve_ColorSat( false, "Color - saturation" ),
  456.         curve_ColorVal( false, "Color - value" ),
  457.         curve_Opacity( false, "Opacity" ),
  458.        
  459.         grpRender( true, "Rendering data" ),
  460.         render_Texture0( g_UITexPicker, "bullet" ),
  461.         render_Texture1( g_UITexPicker, "" ),
  462.         render_Texture2( g_UITexPicker, "" ),
  463.         render_Texture3( g_UITexPicker, "" ),
  464.         render_Shader( g_UIShaderPicker, "particle" ),
  465.         render_Additive( false ),
  466.         render_Stretch( false ),
  467.        
  468.         m_psys( NULL ), m_emitter( NULL )
  469.     {
  470.         spawn_MaxCount.caption = "Max. particle count";
  471.         spawn_Count.caption = "# of particles to spawn";
  472.         spawn_CountExt.caption = "# + random";
  473.         spawn_TimeExt.caption = "Spawn time / rand.ext.";
  474.        
  475.         create_Pos.caption = "Origin";
  476.         create_PosBox.caption = "Random extents";
  477.         create_PosRadius.caption = "Random radius";
  478.        
  479.         create_VelMicroDir.caption = "V/micro/direction";
  480.         create_VelMicroDvg.caption = "V/micro/divergence";
  481.         create_VelMicroDistExt.caption = "V/micro/dist+rand.ext.";
  482.         create_VelMacroDir.caption = "V/macro/direction";
  483.         create_VelMacroDvg.caption = "V/macro/divergence";
  484.         create_VelMacroDistExt.caption = "V/macro/dist+rand.ext.";
  485.         create_VelCluster.caption = "V - cluster size";
  486.         create_VelClusterExt.caption = "V - cluster rand.ext.";
  487.        
  488.         create_LifetimeExt.caption = "Lifetime + rand.ext.";
  489.         create_AngleDirDvg.caption = "Angle / divergence";
  490.         create_AngleVelDvg.caption = "Angular velocity / divergence";
  491.         tick_AngleAcc.caption = "Angle - acceleration";
  492.         tick_GravityMult.caption = "Gravity mulitplier";
  493.         absolute.caption = "World space";
  494.        
  495.         isect_Limit.caption = "Limit";
  496.         isect_Friction.caption = "Friction";
  497.         isect_Bounce.caption = "Bounce";
  498.         isect_FXID.caption = "Hit FX";
  499.         isect_FXChance.caption = "Hit FX chance";
  500.         isect_Remove.caption = "Remove on hit";
  501.        
  502.         render_Texture0.caption = "Texture #1";
  503.         render_Texture1.caption = "Texture #2";
  504.         render_Texture2.caption = "Texture #3";
  505.         render_Texture3.caption = "Texture #4";
  506.         render_Shader.caption = "Shader";
  507.         render_Additive.caption = "Is additive+unlit?";
  508.         render_Stretch.caption = "Is velocity-stretched?";
  509.        
  510.         grpSpawn.Add( &spawn_MaxCount );
  511.         grpSpawn.Add( &spawn_Count );
  512.         grpSpawn.Add( &spawn_CountExt );
  513.         grpSpawn.Add( &spawn_TimeExt );
  514.         Add( &grpSpawn );
  515.        
  516.         grpPosition.Add( &create_Pos );
  517.         grpPosition.Add( &create_PosBox );
  518.         grpPosition.Add( &create_PosRadius );
  519.         Add( &grpPosition );
  520.        
  521.         grpVelocity.Add( &create_VelMicroDir );
  522.         grpVelocity.Add( &create_VelMicroDvg );
  523.         grpVelocity.Add( &create_VelMicroDistExt );
  524.         grpVelocity.Add( &create_VelMacroDir );
  525.         grpVelocity.Add( &create_VelMacroDvg );
  526.         grpVelocity.Add( &create_VelMacroDistExt );
  527.         grpVelocity.Add( &create_VelCluster );
  528.         grpVelocity.Add( &create_VelClusterExt );
  529.         Add( &grpVelocity );
  530.        
  531.         grpMisc.Add( &create_LifetimeExt );
  532.         grpMisc.Add( &create_AngleDirDvg );
  533.         grpMisc.Add( &create_AngleVelDvg );
  534.         grpMisc.Add( &tick_AngleAcc );
  535.         grpMisc.Add( &tick_GravityMult );
  536.         grpMisc.Add( &absolute );
  537.         Add( &grpMisc );
  538.        
  539.         grpIsect.Add( &isect_Limit );
  540.         grpIsect.Add( &isect_Friction );
  541.         grpIsect.Add( &isect_Bounce );
  542.         grpIsect.Add( &isect_FXID );
  543.         grpIsect.Add( &isect_FXChance );
  544.         grpIsect.Add( &isect_Remove );
  545.         Add( &grpIsect );
  546.        
  547.         grpSizeColor.Add( &curve_Size );
  548.         grpSizeColor.Add( &curve_ColorHue );
  549.         grpSizeColor.Add( &curve_ColorSat );
  550.         grpSizeColor.Add( &curve_ColorVal );
  551.         grpSizeColor.Add( &curve_Opacity );
  552.         Add( &grpSizeColor );
  553.        
  554.         grpRender.Add( &render_Texture0 );
  555.         grpRender.Add( &render_Texture1 );
  556.         grpRender.Add( &render_Texture2 );
  557.         grpRender.Add( &render_Texture3 );
  558.         grpRender.Add( &render_Shader );
  559.         grpRender.Add( &render_Additive );
  560.         grpRender.Add( &render_Stretch );
  561.         Add( &grpRender );
  562.     }
  563.    
  564.     int OnEvent( EDGUIEvent* e )
  565.     {
  566.         switch( e->type )
  567.         {
  568.         case EDGUI_EVENT_PROPEDIT:
  569.             if( e->target == &spawn_MaxCount ){ m_emitter->spawn_MaxCount = spawn_MaxCount.m_value; _U(false); }
  570.             if( e->target == &spawn_Count ){ m_emitter->spawn_Count = spawn_Count.m_value; _U(false); }
  571.             if( e->target == &spawn_CountExt ){ m_emitter->spawn_CountExt = spawn_CountExt.m_value; _U(false); }
  572.             if( e->target == &spawn_TimeExt ){ m_emitter->spawn_TimeExt = spawn_TimeExt.m_value; _U(false); }
  573.            
  574.             if( e->target == &create_Pos ){ m_emitter->create_Pos = create_Pos.m_value; _U(false); }
  575.             if( e->target == &create_PosBox ){ m_emitter->create_PosBox = create_PosBox.m_value; _U(false); }
  576.             if( e->target == &create_PosRadius ){ m_emitter->create_PosRadius = create_PosRadius.m_value; _U(false); }
  577.            
  578.             if( e->target == &create_VelMicroDir ){ m_emitter->create_VelMicroDir = create_VelMicroDir.m_value; _U(false); }
  579.             if( e->target == &create_VelMicroDvg ){ m_emitter->create_VelMicroDvg = create_VelMicroDvg.m_value; _U(false); }
  580.             if( e->target == &create_VelMicroDistExt ){ m_emitter->create_VelMicroDistExt = create_VelMicroDistExt.m_value; _U(false); }
  581.             if( e->target == &create_VelMacroDir ){ m_emitter->create_VelMacroDir = create_VelMacroDir.m_value; _U(false); }
  582.             if( e->target == &create_VelMacroDvg ){ m_emitter->create_VelMacroDvg = create_VelMacroDvg.m_value; _U(false); }
  583.             if( e->target == &create_VelMacroDistExt ){ m_emitter->create_VelMacroDistExt = create_VelMacroDistExt.m_value; _U(false); }
  584.             if( e->target == &create_VelCluster ){ m_emitter->create_VelCluster = create_VelCluster.m_value; _U(false); }
  585.             if( e->target == &create_VelClusterExt ){ m_emitter->create_VelClusterExt = create_VelClusterExt.m_value; _U(false); }
  586.            
  587.             if( e->target == &create_LifetimeExt ){ m_emitter->create_LifetimeExt = create_LifetimeExt.m_value; _U(false); }
  588.             if( e->target == &create_AngleDirDvg ){ m_emitter->create_AngleDirDvg = DEG2RAD( create_AngleDirDvg.m_value ); _U(false); }
  589.             if( e->target == &create_AngleVelDvg ){ m_emitter->create_AngleVelDvg = DEG2RAD( create_AngleVelDvg.m_value ); _U(false); }
  590.             if( e->target == &tick_AngleAcc ){ m_emitter->tick_AngleAcc = DEG2RAD( tick_AngleAcc.m_value ); _U(false); }
  591.             if( e->target == &tick_GravityMult ){ m_emitter->tick_GravityMult = tick_GravityMult.m_value; _U(false); }
  592.             if( e->target == &absolute ){ m_emitter->absolute = absolute.m_value; _U(false); }
  593.            
  594.             if( e->target == &isect_Limit ){ m_emitter->isect_Limit = isect_Limit.m_value; _U(false); }
  595.             if( e->target == &isect_Friction ){ m_emitter->isect_Friction = isect_Friction.m_value; _U(false); }
  596.             if( e->target == &isect_Bounce ){ m_emitter->isect_Bounce = isect_Bounce.m_value; _U(false); }
  597.             if( e->target == &isect_FXID ){ m_emitter->isect_FXID = EDGUIPSISFXPicker::GetFXIDFromName( isect_FXID.m_value ); _U(false); }
  598.             if( e->target == &isect_FXChance ){ m_emitter->isect_FXChance = isect_FXChance.m_value; _U(false); }
  599.             if( e->target == &isect_Remove ){ m_emitter->isect_Remove = isect_Remove.m_value; _U(false); }
  600.            
  601.             if( e->target == &render_Texture0 ){ m_emitter->render_Textures[0] = GetParticleTexHandle( render_Texture0.m_value ); _U(true); }
  602.             if( e->target == &render_Texture1 ){ m_emitter->render_Textures[1] = GetParticleTexHandle( render_Texture1.m_value ); _U(true); }
  603.             if( e->target == &render_Texture2 ){ m_emitter->render_Textures[2] = GetParticleTexHandle( render_Texture2.m_value ); _U(true); }
  604.             if( e->target == &render_Texture3 ){ m_emitter->render_Textures[3] = GetParticleTexHandle( render_Texture3.m_value ); _U(true); }
  605.             if( e->target == &render_Shader ){ m_emitter->render_Shader = render_Shader.m_value; _U(true); }
  606.             if( e->target == &render_Additive ){ m_emitter->render_Additive = render_Additive.m_value; _U(true); }
  607.             if( e->target == &render_Stretch ){ m_emitter->render_Stretch = render_Stretch.m_value; _U(true); }
  608.             break;
  609.         }
  610.         return EDGUILayoutRow::OnEvent( e );
  611.     }
  612.     void _U( bool renderupdate )
  613.     {
  614.         if( renderupdate )
  615.             m_psys->OnRenderUpdate();
  616.     }
  617.    
  618.     void Prepare( ParticleSystem* PS, size_t emid )
  619.     {
  620.         m_psys = PS;
  621.         m_emitter = &PS->emitters[ emid ];
  622.        
  623.         spawn_MaxCount.SetValue( m_emitter->spawn_MaxCount );
  624.         spawn_Count.SetValue( m_emitter->spawn_Count );
  625.         spawn_CountExt.SetValue( m_emitter->spawn_CountExt );
  626.         spawn_TimeExt.SetValue( m_emitter->spawn_TimeExt );
  627.        
  628.         create_Pos.SetValue( m_emitter->create_Pos );
  629.         create_PosBox.SetValue( m_emitter->create_PosBox );
  630.         create_PosRadius.SetValue( m_emitter->create_PosRadius );
  631.    
  632.         create_VelMicroDir.SetValue( m_emitter->create_VelMicroDir );
  633.         create_VelMicroDvg.SetValue( m_emitter->create_VelMicroDvg );
  634.         create_VelMicroDistExt.SetValue( m_emitter->create_VelMicroDistExt );
  635.         create_VelMacroDir.SetValue( m_emitter->create_VelMacroDir );
  636.         create_VelMacroDvg.SetValue( m_emitter->create_VelMacroDvg );
  637.         create_VelMacroDistExt.SetValue( m_emitter->create_VelMacroDistExt );
  638.         create_VelCluster.SetValue( m_emitter->create_VelCluster );
  639.         create_VelClusterExt.SetValue( m_emitter->create_VelClusterExt );
  640.        
  641.         create_LifetimeExt.SetValue( m_emitter->create_LifetimeExt );
  642.         create_AngleDirDvg.SetValue( RAD2DEG( m_emitter->create_AngleDirDvg ) );
  643.         create_AngleVelDvg.SetValue( RAD2DEG( m_emitter->create_AngleVelDvg ) );
  644.         tick_AngleAcc.SetValue( RAD2DEG( m_emitter->tick_AngleAcc ) );
  645.         tick_GravityMult.SetValue( m_emitter->tick_GravityMult );
  646.         absolute.SetValue( m_emitter->absolute );
  647.        
  648.         isect_Limit.SetValue( m_emitter->isect_Limit );
  649.         isect_Friction.SetValue( m_emitter->isect_Friction );
  650.         isect_Bounce.SetValue( m_emitter->isect_Bounce );
  651.         isect_FXID.SetValue( EDGUIPSISFXPicker::GetNameFromFXID( m_emitter->isect_FXID ) );
  652.         isect_FXChance.SetValue( m_emitter->isect_FXChance );
  653.         isect_Remove.SetValue( m_emitter->isect_Remove );
  654.        
  655.         curve_Size.SetValue( m_emitter->curve_Size );
  656.         curve_ColorHue.SetValue( m_emitter->curve_ColorHue );
  657.         curve_ColorSat.SetValue( m_emitter->curve_ColorSat );
  658.         curve_ColorVal.SetValue( m_emitter->curve_ColorVal );
  659.         curve_Opacity.SetValue( m_emitter->curve_Opacity );
  660.        
  661.         render_Texture0.SetValue( GetParticleTexName( m_emitter->render_Textures[0] ) );
  662.         render_Texture1.SetValue( GetParticleTexName( m_emitter->render_Textures[1] ) );
  663.         render_Texture2.SetValue( GetParticleTexName( m_emitter->render_Textures[2] ) );
  664.         render_Texture3.SetValue( GetParticleTexName( m_emitter->render_Textures[3] ) );
  665.         render_Shader.SetValue( m_emitter->render_Shader );
  666.         render_Additive.SetValue( m_emitter->render_Additive );
  667.         render_Stretch.SetValue( m_emitter->render_Stretch );
  668.     }
  669.    
  670.     EDGUIGroup grpSpawn;
  671.     EDGUIPropInt spawn_MaxCount;
  672.     EDGUIPropInt spawn_Count;
  673.     EDGUIPropInt spawn_CountExt;
  674.     EDGUIPropVec2 spawn_TimeExt;
  675.    
  676.     EDGUIGroup grpPosition;
  677.     EDGUIPropVec3 create_Pos;
  678.     EDGUIPropVec3 create_PosBox;
  679.     EDGUIPropFloat create_PosRadius;
  680.    
  681.     EDGUIGroup grpVelocity;
  682.     EDGUIPropVec3 create_VelMicroDir;
  683.     EDGUIPropFloat create_VelMicroDvg;
  684.     EDGUIPropVec2 create_VelMicroDistExt;
  685.     EDGUIPropVec3 create_VelMacroDir;
  686.     EDGUIPropFloat create_VelMacroDvg;
  687.     EDGUIPropVec2 create_VelMacroDistExt;
  688.     EDGUIPropInt create_VelCluster;
  689.     EDGUIPropInt create_VelClusterExt;
  690.    
  691.     EDGUIGroup grpMisc;
  692.     EDGUIPropVec2 create_LifetimeExt;
  693.     EDGUIPropVec2 create_AngleDirDvg;
  694.     EDGUIPropVec2 create_AngleVelDvg;
  695.     EDGUIPropFloat tick_AngleAcc;
  696.     EDGUIPropFloat tick_GravityMult;
  697.     EDGUIPropBool absolute;
  698.    
  699.     EDGUIGroup grpIsect;
  700.     EDGUIPropInt isect_Limit;
  701.     EDGUIPropFloat isect_Friction;
  702.     EDGUIPropFloat isect_Bounce;
  703.     EDGUIPropRsrc isect_FXID;
  704.     EDGUIPropFloat isect_FXChance;
  705.     EDGUIPropBool isect_Remove;
  706.    
  707.     EDGUIGroup grpSizeColor;
  708.     EdEmitCurve curve_Size;
  709.     EdEmitCurve curve_ColorHue;
  710.     EdEmitCurve curve_ColorSat;
  711.     EdEmitCurve curve_ColorVal;
  712.     EdEmitCurve curve_Opacity;
  713.    
  714.     EDGUIGroup grpRender;
  715.     EDGUIPropRsrc render_Texture0;
  716.     EDGUIPropRsrc render_Texture1;
  717.     EDGUIPropRsrc render_Texture2;
  718.     EDGUIPropRsrc render_Texture3;
  719.     EDGUIPropRsrc render_Shader;
  720.     EDGUIPropBool render_Additive;
  721.     EDGUIPropBool render_Stretch;
  722.    
  723.     ParticleSystem* m_psys;
  724.     ParticleSystem::Emitter* m_emitter;
  725. };
  726.  
  727. struct EdParticleSystem : EDGUILayoutRow
  728. {
  729.     EdParticleSystem() :
  730.         m_ctlGroup( true, "Particle system properties" ),
  731.         m_ctlGravity( V3(0,0,-10), 2, V3(-8192), V3(8192) ),
  732.         m_ctlMaxGroupCount( 10, 1, 128 ),
  733.         m_ctlGlobalScale( 1, 2, 0.001f, 1000.0f ),
  734.         m_ctlLooping( true ),
  735.         m_ctlRetriggerTime( V2(1,0.1f), 2, V2(0), V2(1000) )
  736.     {
  737.         tyname = "particlesystem";
  738.        
  739.         m_ctlGroup.caption = "Particle system properties";
  740.         m_ctlGravity.caption = "Gravity";
  741.         m_ctlMaxGroupCount.caption = "# lighting groups";
  742.         m_ctlGlobalScale.caption = "Global scale";
  743.         m_ctlLooping.caption = "Looping";
  744.         m_ctlRetriggerTime.caption = "Retrigger time/ext.";
  745.         m_ctlAddEmitter.caption = "- Add emitter -";
  746.        
  747.         m_ctlGroup.SetOpen( true );
  748.         Add( &m_ctlGroup );
  749.        
  750.         Reset();
  751.     }
  752.    
  753.     int OnEvent( EDGUIEvent* e )
  754.     {
  755.         switch( e->type )
  756.         {
  757.         case EDGUI_EVENT_BTNCLICK:
  758.             for( size_t i = 0; i < m_ctlEmEditBtns.size(); ++i )
  759.             {
  760.                 if( e->target == &m_ctlEmEditBtns[ i ] )
  761.                 {
  762.                     EDGUILayoutRow::OnEvent( e );
  763.                     EditEmitter( i );
  764.                     return 1;
  765.                 }
  766.             }
  767.             if( e->target == &m_ctlAddEmitter )
  768.             {
  769.                 EDGUILayoutRow::OnEvent( e );
  770.                 AddDefaultEmitter();
  771.                 m_psys.OnRenderUpdate();
  772.                 EditEmitter( m_psys.emitters.size() - 1 );
  773.                 return 1;
  774.             }
  775.         case EDGUI_EVENT_PROPEDIT:
  776.             if( e->target == &m_ctlGravity ) m_psys.gravity = m_ctlGravity.m_value;
  777.             if( e->target == &m_ctlMaxGroupCount ) m_psys.maxGroupCount = m_ctlMaxGroupCount.m_value;
  778.             if( e->target == &m_ctlGlobalScale ) m_psys.globalScale = m_ctlGlobalScale.m_value;
  779.             if( e->target == &m_ctlLooping ) m_psys.looping = m_ctlLooping.m_value;
  780.             if( e->target == &m_ctlRetriggerTime ) m_psys.retriggerTimeExt = m_ctlRetriggerTime.m_value;
  781.             return 1;
  782.         }
  783.         return EDGUILayoutRow::OnEvent( e );
  784.     }
  785.    
  786.     void Tick( float dt )
  787.     {
  788.         m_psys.Tick( dt );
  789.         m_psys.PreRender();
  790.     }
  791.    
  792.     void Data2UI()
  793.     {
  794.         m_ctlGroup.Clear();
  795.        
  796.         m_ctlGravity.SetValue( m_psys.gravity );
  797.         m_ctlMaxGroupCount.SetValue( m_psys.maxGroupCount );
  798.         m_ctlGlobalScale.SetValue( m_psys.globalScale );
  799.         m_ctlLooping.SetValue( m_psys.looping );
  800.         m_ctlRetriggerTime.SetValue( m_psys.retriggerTimeExt );
  801.        
  802.         m_ctlGroup.Add( &m_ctlGravity );
  803.         m_ctlGroup.Add( &m_ctlMaxGroupCount );
  804.         m_ctlGroup.Add( &m_ctlGlobalScale );
  805.         m_ctlGroup.Add( &m_ctlLooping );
  806.         m_ctlGroup.Add( &m_ctlRetriggerTime );
  807.        
  808.         m_ctlEmEditBtns.clear();
  809.         m_ctlEmEditBtns.reserve( m_psys.emitters.size() );
  810.         for( size_t i = 0; i < m_psys.emitters.size(); ++i )
  811.         {
  812.             m_ctlEmEditBtns.push_back( EDGUIButton() );
  813.             EDGUIButton& B = m_ctlEmEditBtns.last();
  814.            
  815.             char bfr[32];
  816.             sprintf( bfr, "Emitter #%d", (int)i + 1 );
  817.             B.caption = bfr;
  818.             B.id1 = i;
  819.            
  820.             m_ctlGroup.Add( &B );
  821.         }
  822.        
  823.         m_ctlGroup.Add( &m_ctlAddEmitter );
  824.     }
  825.    
  826.     void Reset()
  827.     {
  828.         m_psys = ParticleSystem();
  829.         AddDefaultEmitter();
  830.        
  831.         m_psys.AddToScene( g_EdScene );
  832.         m_psys.OnRenderUpdate();
  833.         m_psys.SetTransform( Mat4::Identity );
  834.         m_psys.Play();
  835.     }
  836.     void AddDefaultEmitter()
  837.     {
  838.         if( g_UIGraphEd ) // order of initialization
  839.             g_UIGraphEd->UnsetCurve();
  840.         m_psys.emitters.push_back( ParticleSystem::Emitter() );
  841.         ParticleSystem::Emitter& E = m_psys.emitters.last();
  842.         E.curve_ColorVal.valueRange = V2(1);
  843.         E.curve_Opacity.valueRange = V2(0,1);
  844.         Vec2 opa[] = { V2(0,0), V2(1,0), V2(1,0), V2(0,0) };
  845.         E.curve_Opacity.values.append( opa, sizeof(opa)/sizeof(opa[0]) );
  846.         E.curve_Size.valueRange = V2(1);
  847.         E.create_VelMacroDvg = 0.5f;
  848.         E.render_Textures[0] = GR_GetTexture( "textures/particles/spark_fast.png" );
  849.     }
  850.    
  851.     EDGUIItem* GetSystem()
  852.     {
  853.         Data2UI();
  854.         return this;
  855.     }
  856.     EDGUIItem* GetEmitter( size_t which )
  857.     {
  858.         m_ctlEmitter.Prepare( &m_psys, which );
  859.         return &m_ctlEmitter;
  860.     }
  861.    
  862.     void EditEmitter( size_t which );
  863.    
  864.     void Play(){ m_psys.Play(); }
  865.     void Stop(){ m_psys.Stop(); }
  866.     void Trigger(){ m_psys.Trigger(); }
  867.    
  868.     template< class T > void Serialize( T& arch )
  869.     {
  870.         m_psys.Serialize( arch, false );
  871.     }
  872.    
  873.     ParticleSystem m_psys;
  874.    
  875.     EdEmitter m_ctlEmitter;
  876.    
  877.     EDGUIGroup m_ctlGroup;
  878.     EDGUIPropVec3 m_ctlGravity;
  879.     EDGUIPropInt m_ctlMaxGroupCount;
  880.     EDGUIPropFloat m_ctlGlobalScale;
  881.     EDGUIPropBool m_ctlLooping;
  882.     EDGUIPropVec2 m_ctlRetriggerTime;
  883.     Array< EDGUIButton > m_ctlEmEditBtns;
  884.     EDGUIButton m_ctlAddEmitter;
  885. };
  886.  
  887.  
  888.  
  889. struct EDGUIMainFrame : EDGUIFrame, EDGUIRenderView::FrameInterface
  890. {
  891.     EDGUIMainFrame() :
  892.         m_UIMenuSplit( true, 26, 0 ),
  893.         m_UIGraphSplit( true, 0, 0.7f ),
  894.         m_UIParamSplit( false, 0, 0.7f ),
  895.         m_UIRenderView( g_EdScene, this )
  896.     {
  897.         tyname = "mainframe";
  898.        
  899.         g_UIGraphEd = &m_UIGraph;
  900.        
  901.         Add( &m_UIMenuSplit );
  902.         m_UIMenuSplit.SetFirstPane( &m_UIMenuButtons );
  903.         m_UIMenuSplit.SetSecondPane( &m_UIParamSplit );
  904.         m_UIParamSplit.SetFirstPane( &m_UIGraphSplit );
  905.         m_UIParamSplit.SetSecondPane( &m_UIParamScroll );
  906.         m_UIGraphSplit.SetFirstPane( &m_UIRenderView );
  907.         m_UIGraphSplit.SetSecondPane( &m_UIGraph );
  908.         m_UIParamScroll.Add( &m_UIParamList );
  909.        
  910.         // menu
  911.         m_MB_Cat0.caption = "File:";
  912.         m_MBNew.caption = "New";
  913.         m_MBOpen.caption = "Open";
  914.         m_MBSave.caption = "Save";
  915.         m_MBSaveAs.caption = "Save As";
  916.         m_MB_Cat1.caption = "Playback:";
  917.         m_MBPlay.caption = "Play";
  918.         m_MBStop.caption = "Stop";
  919.         m_MBTrigger.caption = "Trigger";
  920.         m_MB_Cat2.caption = "Edit:";
  921.         m_MBEditSystem.caption = "System";
  922.         m_UIMenuButtons.Add( &m_MB_Cat0 );
  923.         m_UIMenuButtons.Add( &m_MBNew );
  924.         m_UIMenuButtons.Add( &m_MBOpen );
  925.         m_UIMenuButtons.Add( &m_MBSave );
  926.         m_UIMenuButtons.Add( &m_MBSaveAs );
  927.         m_UIMenuButtons.Add( &m_MB_Cat1 );
  928.         m_UIMenuButtons.Add( &m_MBPlay );
  929.         m_UIMenuButtons.Add( &m_MBStop );
  930.         m_UIMenuButtons.Add( &m_MBTrigger );
  931.         m_UIMenuButtons.Add( &m_MB_Cat2 );
  932.         m_UIMenuButtons.Add( &m_MBEditSystem );
  933.     }
  934.    
  935.     int OnEvent( EDGUIEvent* e )
  936.     {
  937.         switch( e->type )
  938.         {
  939.         case EDGUI_EVENT_BTNCLICK:
  940.             if(0);
  941.            
  942.             else if( e->target == &m_MBNew ) PS_New();
  943.             else if( e->target == &m_MBOpen ) PS_Open();
  944.             else if( e->target == &m_MBSave ) PS_Save();
  945.             else if( e->target == &m_MBSaveAs ) PS_SaveAs();
  946.            
  947.             else if( e->target == &m_MBPlay ) g_EdPS->Play();
  948.             else if( e->target == &m_MBStop ) g_EdPS->Stop();
  949.             else if( e->target == &m_MBTrigger ) g_EdPS->Trigger();
  950.            
  951.             else if( e->target == &m_MBEditSystem )
  952.             {
  953.                 ClearParamList();
  954.                 AddToParamList( g_EdPS->GetSystem() );
  955.             }
  956.            
  957.             return 1;
  958.            
  959.         case EDGUI_EVENT_PROPCHANGE:
  960.             if( e->target == g_UIPSOpenPicker )
  961.             {
  962.                 PS_Real_Open( g_UIPSOpenPicker->GetValue() );
  963.             }
  964.             if( e->target == g_UIPSSavePicker )
  965.             {
  966.                 PS_Real_Save( g_UIPSSavePicker->GetValue() );
  967.             }
  968.             return 1;
  969.         }
  970.         return EDGUIFrame::OnEvent( e );
  971.     }
  972.    
  973.     bool ViewEvent( EDGUIEvent* e )
  974.     {
  975.         return true;
  976.     }
  977.    
  978.     void DebugDraw()
  979.     {
  980.     }
  981.    
  982.     void AddToParamList( EDGUIItem* item )
  983.     {
  984.         m_UIParamList.Add( item );
  985.     }
  986.     void ClearParamList()
  987.     {
  988.         while( m_UIParamList.m_subitems.size() )
  989.             m_UIParamList.Remove( m_UIParamList.m_subitems.last() );
  990.     }
  991.    
  992.     void ResetEditorState()
  993.     {
  994.         ClearParamList();
  995.     }
  996.     void PS_New()
  997.     {
  998.         m_fileName = "";
  999.         g_EdPS->Reset();
  1000.         ResetEditorState();
  1001.     }
  1002.     void PS_Open()
  1003.     {
  1004.         g_UIPSOpenPicker->Reload();
  1005.         g_UIPSOpenPicker->Open( this, "" );
  1006.         m_frame->Add( g_UIPSOpenPicker );
  1007.     }
  1008.     void PS_Save()
  1009.     {
  1010.         if( m_fileName.size() )
  1011.         {
  1012.             PS_Real_Save( m_fileName );
  1013.         }
  1014.         else
  1015.         {
  1016.             PS_SaveAs();
  1017.         }
  1018.     }
  1019.     void PS_SaveAs()
  1020.     {
  1021.         g_UIPSSavePicker->Reload();
  1022.         g_UIPSSavePicker->Open( this, "" );
  1023.         m_frame->Add( g_UIPSSavePicker );
  1024.     }
  1025.     void PS_Real_Open( const String& str )
  1026.     {
  1027.         LOG << "Trying to open particle system: " << str;
  1028.        
  1029.         char bfr[ 256 ];
  1030.         sgrx_snprintf( bfr, sizeof(bfr), "psys/%.*s.psy", TMIN( (int) str.size(), 200 ), str.data() );
  1031.         ByteArray data;
  1032.         if( !FS_LoadBinaryFile( bfr, data ) )
  1033.         {
  1034.             LOG_ERROR << "FAILED TO LOAD PSYS FILE: " << bfr;
  1035.             return;
  1036.         }
  1037.        
  1038.         ResetEditorState();
  1039.        
  1040.         ByteReader br( &data );
  1041.         g_EdPS->Serialize( br );
  1042.         if( br.error )
  1043.         {
  1044.             LOG_ERROR << "FAILED TO READ PSYS FILE (at " << (int) br.pos << "): " << bfr;
  1045.             return;
  1046.         }
  1047.        
  1048.         m_fileName = str;
  1049.         g_EdPS->Play();
  1050.     }
  1051.     void PS_Real_Save( const String& str )
  1052.     {
  1053.         LOG << "Trying to save particle system: " << str;
  1054.         ByteArray data;
  1055.         ByteWriter bw( &data );
  1056.        
  1057.         bw << *g_EdPS;
  1058.        
  1059.         char bfr[ 256 ];
  1060.         sgrx_snprintf( bfr, sizeof(bfr), "psys/%.*s.psy", TMIN( (int) str.size(), 200 ), str.data() );
  1061.         if( !FS_SaveBinaryFile( bfr, data.data(), data.size() ) )
  1062.         {
  1063.             LOG_ERROR << "FAILED TO SAVE PSYS FILE: " << bfr;
  1064.             return;
  1065.         }
  1066.        
  1067.         m_fileName = str;
  1068.     }
  1069.    
  1070.     String m_fileName;
  1071.    
  1072.     // core layout
  1073.     EDGUILayoutSplitPane m_UIMenuSplit;
  1074.     EDGUILayoutSplitPane m_UIGraphSplit;
  1075.     EDGUILayoutSplitPane m_UIParamSplit;
  1076.     EDGUILayoutColumn m_UIMenuButtons;
  1077.     EDGUIVScroll m_UIParamScroll;
  1078.     EDGUILayoutRow m_UIParamList;
  1079.     EDGUIRenderView m_UIRenderView;
  1080.     EdDualGraph m_UIGraph;
  1081.  
  1082.     // menu
  1083.     EDGUILabel m_MB_Cat0;
  1084.     EDGUIButton m_MBNew;
  1085.     EDGUIButton m_MBOpen;
  1086.     EDGUIButton m_MBSave;
  1087.     EDGUIButton m_MBSaveAs;
  1088.     EDGUILabel m_MB_Cat1;
  1089.     EDGUIButton m_MBPlay;
  1090.     EDGUIButton m_MBStop;
  1091.     EDGUIButton m_MBTrigger;
  1092.     EDGUILabel m_MB_Cat2;
  1093.     EDGUIButton m_MBEditSystem;
  1094. };
  1095.  
  1096. void EdParticleSystem::EditEmitter( size_t which )
  1097. {
  1098.     g_UIFrame->ClearParamList();
  1099.     g_UIFrame->AddToParamList( GetEmitter( which ) );
  1100. }
  1101.  
  1102.  
  1103.  
  1104.  
  1105. struct PSEditor : IGame
  1106. {
  1107.     bool OnInitialize()
  1108.     {
  1109.         GR2D_LoadFont( "core", "fonts/lato-regular.ttf" );
  1110.         GR2D_SetFont( "core", 12 );
  1111.        
  1112.         g_UITexPicker = new EDGUISDTexPicker( "textures/particles" );
  1113.         g_UIShaderPicker = new EDGUIShaderPicker;
  1114.         g_UIMeshPicker = new EDGUIMeshPicker;
  1115.         g_UIPSOpenPicker = new EDGUIPSOpenPicker;
  1116.         g_UIPSSavePicker = new EDGUIPSSavePicker;
  1117.         g_UIPSISFXPicker = new EDGUIPSISFXPicker;
  1118.        
  1119.         // core layout
  1120.         g_EdScene = GR_CreateScene();
  1121.         g_EdScene->camera.position = V3(3);
  1122.         g_EdScene->camera.UpdateMatrices();
  1123.         g_EdPS = new EdParticleSystem;
  1124.         g_UIFrame = new EDGUIMainFrame();
  1125.         g_UIFrame->Resize( GR_GetWidth(), GR_GetHeight() );
  1126.        
  1127.         // param area
  1128.         g_UIFrame->AddToParamList( g_EdPS->GetSystem() );
  1129.        
  1130.         return true;
  1131.     }
  1132.     void OnDestroy()
  1133.     {
  1134.         delete g_UIPSISFXPicker;
  1135.         g_UIPSISFXPicker = NULL;
  1136.         delete g_UIPSSavePicker;
  1137.         g_UIPSSavePicker = NULL;
  1138.         delete g_UIPSOpenPicker;
  1139.         g_UIPSOpenPicker = NULL;
  1140.         delete g_UIMeshPicker;
  1141.         g_UIMeshPicker = NULL;
  1142.         delete g_UIShaderPicker;
  1143.         g_UIShaderPicker = NULL;
  1144.         delete g_UITexPicker;
  1145.         g_UITexPicker = NULL;
  1146.         delete g_UIFrame;
  1147.         g_UIFrame = NULL;
  1148.         delete g_EdPS;
  1149.         g_EdPS = NULL;
  1150.         g_EdScene = NULL;
  1151.     }
  1152.     void OnEvent( const Event& e )
  1153.     {
  1154.         g_UIFrame->EngineEvent( &e );
  1155.     }
  1156.     void OnTick( float dt, uint32_t gametime )
  1157.     {
  1158.         GR2D_SetViewMatrix( Mat4::CreateUI( 0, 0, GR_GetWidth(), GR_GetHeight() ) );
  1159.         g_UIFrame->m_UIRenderView.UpdateCamera( dt );
  1160.         g_EdPS->Tick( dt );
  1161.         g_UIFrame->Draw();
  1162.     }
  1163. }
  1164. g_Game;
  1165.  
  1166.  
  1167. extern "C" EXPORT IGame* CreateGame()
  1168. {
  1169.     return &g_Game;
  1170. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement