Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

vuLightDial.cpp

Go to the documentation of this file.
00001 #include "vuLightDial.h"
00002 #include "../vuUtilityWindow.h"
00003 #include <wx/mstream.h>
00004 
00005 #include <iostream.h>
00006 #include <math.h>
00007 
00008 #include "vuColour31a.h"
00009 
00010 #include "bulb.h"
00011 
00012 #ifdef WIN32
00013 #include "wx/msw/winundef.h"
00014 #endif
00015 
00016 #define MIN(a,b) (a<b ? a : b)
00017 #define MAX(a,b) (a>b ? a : b)
00018 
00019 //#ifdef WIN32
00020 //int rint(double d) {
00021 //      return (int) d;
00022 //}
00023 //#endif
00024 
00025 BEGIN_EVENT_TABLE(vuLightDial, wxDialog)
00026     EVT_PAINT(vuLightDial::OnPaint)
00027     EVT_MOUSE_EVENTS(vuLightDial::OnMouseEvent)
00028     EVT_COMMAND_SCROLL(vuLightDial::idLIGHTINT, vuLightDial::OnSlideIntensity)
00029     EVT_BUTTON(vuLightDial::idHIDE, vuLightDial::OnHide)
00030 END_EVENT_TABLE();
00031 
00032 #ifndef HEADERIMG
00033 #define HEADERIMG(varname) varname, varname ## _size
00034 #endif
00035 
00036 //----------------------------------------------------------------------------
00037 //------------------------- The constructor ----------------------------------
00038 //----------------------------------------------------------------------------
00039 
00040 vuLightDial::vuLightDial(wxWindow *parent, vuTFDesignSpec &tf)
00041     : wxDialog(parent,-1, wxString("Light Dial"),
00042                wxDefaultPosition,wxDefaultSize,wxDEFAULT_DIALOG_STYLE),
00043     m_TFunc(tf)
00044 {
00045     m_NLights = 0;
00046     m_WeightX = -1;
00047     m_WeightY = -1;
00048     wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
00049     m_DialArea.width = 200;
00050     m_DialArea.height = 200;
00051     m_DialSpacer = new wxBoxSizer(wxHORIZONTAL);
00052     m_DialSpacer->Add(m_DialArea.width,m_DialArea.height);
00053     sizer->Add(m_DialSpacer);
00054     wxSizer *rightsizer = new wxBoxSizer(wxVERTICAL);
00055     m_LightIntensity = new wxSlider(this,idLIGHTINT,
00056                                     (int)(float(LDIAL_SLDRES)/LDIAL_INTENSITY),
00057                                     0,LDIAL_SLDRES,
00058                                     wxDefaultPosition, 
00059                                     wxSize(20,m_DialArea.height-20),
00060                                     wxSL_VERTICAL);
00061     rightsizer->Add(new wxStaticText(this, -1, "Intensity"),
00062                     0,wxALL|wxALIGN_CENTER,5);
00063     rightsizer->Add(m_LightIntensity,0,wxALL|wxALIGN_CENTER,5);
00064     rightsizer->Add(new wxButton(this,idHIDE,"Hide"),0,wxALL|wxALIGN_CENTER,5);
00065     sizer->Add(rightsizer);
00066     
00067     SetSizer(sizer);
00068     SetAutoLayout(true);
00069     sizer->Layout();
00070     sizer->SetSizeHints(this);
00071     sizer->Fit(this);
00072 
00073     m_DialArea.x = m_DialSpacer->GetPosition().x;
00074     m_DialArea.y = m_DialSpacer->GetPosition().y;
00075     m_IsUpdated = false;
00076 
00077 #ifdef LOAD_IMAGE_FROM_FILE
00078     // try to find the directory with our images
00079     wxString dir;
00080     vuGUI *app = &(wxGetApp());
00081 #ifndef WIN32
00082     if (app != NULL) {
00083         dir = app->argv[0];
00084         dir = dir.BeforeLast('/');
00085     }
00086     if ( wxFile::Exists(dir+"/bulb.png") )
00087         dir = dir+"/";
00088     else if ( wxFile::Exists("./bulb.png") )
00089         dir = "./";
00090     else
00091         wxLogWarning("Can't find image files in directories!");
00092 
00093 #else
00094     if (app != NULL) {
00095         dir = app->argv[0];
00096         dir = dir.BeforeLast('\\');
00097     }
00098     if ( wxFile::Exists(dir+"\\bulb.png") )
00099         dir = dir+"\\";
00100     else if ( wxFile::Exists(".\\bulb.png") )
00101         dir = ".\\";
00102     else
00103         wxLogWarning("Can't find image files in directories!");
00104 #endif
00105 #endif // of LOAD_IMAGE_FROM_FILE
00106 
00107 #if wxUSE_LIBPNG
00108 #ifndef LOAD_IMAGE_FROM_FILE
00109     wxMemoryInputStream mims(HEADERIMG(bulbimg));
00110     wxImage image(mims);
00111 #if wxMINOR_VERSION < 5
00112     m_BulbImg = new wxBitmap( image.ConvertToBitmap() );
00113 #else
00114     m_BulbImg = new wxBitmap( image );
00115 #endif
00116 #else
00117     if ( !image.LoadFile( dir + wxString("bulb.png")) ) {
00118         wxLogError("Can't load PNG image");
00119         m_BulbImg = NULL;
00120     } else {
00121         m_BulbImg = new wxBitmap( image.ConvertToBitmap() );
00122         //writeImageToHeader(image, "bulb.h", "bulbimage");
00123     }
00124 #endif // of LOAD_IMAGE_FROM_FILE
00125 #endif // wxUSE_LIBPNG
00126 }
00127 
00128 void vuLightDial::updateSliders() {
00129     m_LightIntensity->SetValue((int)(m_TFunc.getLightIntensity()*float(LDIAL_SLDRES)/LDIAL_INTENSITY));
00130 #ifndef WIN32
00131     DrawShape();
00132 #endif
00133 }
00134 
00135 #if wxMINOR_VERSION < 5
00136 void vuLightDial::OnHide()
00137 #else
00138 void vuLightDial::OnHide(wxCommandEvent& ev)
00139 #endif
00140 {
00141     EndModal(wxID_OK);
00142     Show(false);        // ?
00143 }
00144 
00145 #if wxMINOR_VERSION < 5
00146 void vuLightDial::OnPaint()
00147 #else
00148 void vuLightDial::OnPaint(wxPaintEvent& event)
00149 #endif
00150 {
00151 #if !defined(__WXMOTIF__) && !defined(WIN32)
00152   wxPaintEvent event;
00153   wxDialog::OnPaint(event);
00154 #endif
00155 
00156   DrawShape();
00157 }
00158 
00159 void vuLightDial::DrawShape()
00160 {
00161   wxPaintDC dc(this);
00162 
00163   dc.BeginDrawing();
00164 
00165   //dc.SetPen(*wxTRANSPARENT_PEN);
00166   dc.SetPen(*wxBLACK_PEN);
00167   wxBrush bgbrush(dc.GetBackground());
00168   dc.SetBrush(bgbrush);
00169   dc.DrawRectangle(m_DialArea.x,m_DialArea.y,
00170                    m_DialArea.width,m_DialArea.height);
00171 
00172   if(!m_TFunc.getNumLights()) return;
00173 
00174   wxPen spen(wxColour(10,20,100),3,wxSOLID);
00175   wxBrush sbrush(wxColour(10,20,100),wxSOLID);
00176   dc.SetPen(spen);
00177   dc.SetBrush(sbrush);
00178   
00179   int radius, cx, cy;
00180   if(m_NLights != (int)m_TFunc.getNumLights())  // redo the shape?
00181   {
00182       m_NLights = (int)m_TFunc.getNumLights();
00183       radius = MIN(m_DialArea.width,m_DialArea.height)/2 - 30;
00184       cx = m_DialArea.x+m_DialArea.width/2;
00185       cy = m_DialArea.y+m_DialArea.height/2;
00186       for(int i=0;i<m_NLights;i++)
00187       {
00188           float fi = i*2*M_PI/m_NLights;
00189           m_LPos[i].x = (int)rint(radius*sin(fi) + cx);
00190           m_LPos[i].y = (int)rint(-radius*cos(fi) + cy);
00191           m_LActive[i] = true;
00192       }
00193   }
00194 
00195   m_CHull.clearPoints();
00196   for(int i=0;i<m_NLights;i++)
00197       if(m_LActive[i])
00198           m_CHull.addPoint(i,m_LPos[i].x, m_LPos[i].y);
00199 
00200   m_NCHull = LDIAL_MAXLIGHTS;
00201   m_CHull.getCHull(m_NCHull, m_LIndices);
00202   for(int h=0;h<m_NCHull;h++) {
00203       m_HullPos[h].x = m_LPos[m_LIndices[h]].x;
00204       m_HullPos[h].y = m_LPos[m_LIndices[h]].y;
00205   }
00206   
00207   //dc.DrawPolygon(m_NLights,m_LPos);
00208   dc.DrawPolygon(m_NCHull,m_HullPos);
00209   
00210   wxPen lpen(wxColour(0,0,0),1,wxDOT);
00211   wxPen npen(wxColour(30,30,30),2,wxSOLID);
00212   wxBrush onbrush(wxColour(100,100,200),wxSOLID);
00213   wxBrush offbrush(wxColour(100,100,100),wxSOLID);
00214   dc.SetPen(lpen);
00215   
00216   for(int l=0;l<m_NLights;l++)
00217   {
00218       dc.SetBrush(m_LActive[l] ? onbrush : offbrush);
00219       int yofs = 0;
00220       if(!m_BulbImg) {
00221           dc.DrawCircle(m_LPos[l].x,m_LPos[l].y,10);
00222       } else {
00223           int xofs = m_BulbImg->GetWidth()/2;
00224           yofs = m_BulbImg->GetHeight()/2;
00225           dc.DrawBitmap( *m_BulbImg, m_LPos[l].x-xofs,m_LPos[l].y-yofs, true );
00226           if(!m_LActive[l]) {
00227             dc.SetPen(npen);
00228             dc.DrawLine(m_LPos[l].x-xofs,m_LPos[l].y-yofs,
00229                         m_LPos[l].x+xofs,m_LPos[l].y+yofs);
00230             dc.DrawLine(m_LPos[l].x-xofs,m_LPos[l].y+yofs,
00231                         m_LPos[l].x+xofs,m_LPos[l].y-yofs);
00232           }
00233       }
00234       char number[1024];
00235       sprintf(number,"%i", l+1);
00236       wxString snumber(number);
00237       wxCoord w,h;
00238       dc.GetTextExtent(snumber,&w,&h);
00239       dc.DrawText(snumber, m_LPos[l].x-(w/2), m_LPos[l].y-(2*yofs/3));
00240   }
00241   
00242   if(m_WeightX >=0 && m_WeightY>=0){
00243       //wxPen lpen(wxColour(240,220,10),7,wxCROSS_HATCH);
00244       wxPen lpen(wxColour(0,0,0),1,wxDOT);
00245       wxBrush lbrush(wxColour(200,200,0),wxSOLID);
00246       dc.SetPen(lpen);
00247       dc.SetBrush(lbrush);
00248       
00249       //dc.DrawPoint(m_WeightX, m_WeightY);
00250       //dc.DrawCheckMark(m_WeightX-5,m_WeightY-5,10,10);
00251       dc.DrawCircle(m_WeightX,m_WeightY,10);
00252       dc.SetPen(wxNullPen);
00253       dc.SetBrush(wxNullBrush);
00254   }
00255   
00256   dc.SetPen(wxNullPen);
00257   dc.SetBrush(wxNullBrush);
00258   dc.EndDrawing();
00259 }
00260 
00261 #if wxMINOR_VERSION < 5
00262 void vuLightDial::OnSlideIntensity()
00263 #else
00264 void vuLightDial::OnSlideIntensity(wxScrollEvent& ev)
00265 #endif
00266 {
00267     float intensity = (LDIAL_SLDRES-m_LightIntensity->GetValue())
00268                         /float(LDIAL_SLDRES)*LDIAL_INTENSITY;
00269     m_TFunc.setLightIntensity(intensity);
00270     m_TFunc.generateLight();
00271     
00272     m_IsUpdated = true;
00273     repaintParent();
00274 }
00275 
00276 #define DNORM(a,b) sqrt(double((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)))
00277 
00278 float vuLightDial::getLj(int j, const wxPoint& x)
00279 {
00280     float lj = 1;
00281     if(!m_LActive[j]) return 0.0;
00282     for(int i=0;i<m_NLights;i++)
00283         if(i!=j && m_LActive[i]) lj *= DNORM(x,m_LPos[i])/DNORM(m_LPos[j],m_LPos[i]);
00284     return lj;
00285 }
00286 
00287 #define RR 15
00288 #define LR 10
00289 
00290 void vuLightDial::OnMouseEvent(wxMouseEvent& event)
00291 {
00292     int mx = (int)event.GetX();
00293     int my = (int)event.GetY();
00294 
00295     static int movlight = -1;
00296     
00297     if(event.ButtonDClick(3))
00298     {
00299         for(int j=0;j<m_NLights;j++) {
00300             if(abs(m_LPos[j].x-mx) < LR &&
00301                abs(m_LPos[j].y-my) < LR)
00302             {
00303                 m_LActive[j] = !m_LActive[j];
00304                 
00305                 reweightLights();
00306                 
00307                 Refresh(false);
00308                 m_IsUpdated = true;
00309                 repaintParent();
00310                 break;
00311             }
00312         }
00313     } else if(event.LeftIsDown())  // && event.Dragging()
00314     {
00315         if ((mx >= m_DialArea.x+RR && 
00316              mx <= (m_DialArea.x + m_DialArea.width-2*RR)) &&
00317             (my >= m_DialArea.y+RR && 
00318              my <= (m_DialArea.y + m_DialArea.height-2*RR)))
00319         {
00320             m_WeightX = mx;
00321             m_WeightY = my;
00322             
00323             reweightLights();
00324             
00325                 Refresh(false);
00326             m_IsUpdated = true;
00327             repaintParent();
00328         }
00329         
00330     } else if(event.Dragging() && event.RightIsDown())
00331     {
00332         if ((movlight >=0) &&
00333             (mx >= m_DialArea.x+RR && 
00334              mx <= (m_DialArea.x + m_DialArea.width-2*RR)) &&
00335             (my >= m_DialArea.y+RR && 
00336              my <= (m_DialArea.y + m_DialArea.height-2*RR)))
00337         {
00338             m_LPos[movlight].x = mx;
00339             m_LPos[movlight].y = my;
00340             m_CHull.addPoint(movlight,m_LPos[movlight].x,m_LPos[movlight].y);
00341 
00342             reweightLights();
00343 
00344                 Refresh(false);
00345             m_IsUpdated = true;
00346             repaintParent();
00347         }
00348     } else if(!event.Dragging() && event.RightIsDown())
00349     {
00350         movlight = -1;
00351         for(int j=0;j<m_NLights;j++) {
00352             if(abs(m_LPos[j].x-mx) < LR &&
00353                abs(m_LPos[j].y-my) < LR)
00354             {
00355                 movlight = j;
00356                 break;
00357             }
00358         }
00359     }
00360 }
00361 
00362 void vuLightDial::reweightLights()
00363 {
00364     int nl = (int)m_TFunc.getNumLights();
00365     float *wl = new float[nl];
00366     float wlsum =0;
00367     
00368 #ifdef MINDISTWEIGHTING
00369     int radius = MIN(m_DialArea.width,m_DialArea.height)/2 - 30;
00370     int cx = m_DialArea.x+m_DialArea.width/2;
00371     int cy = m_DialArea.y+m_DialArea.height/2;
00372             
00373     for(int i=0;i<nl;i++)
00374     {
00375         float fi = i*2*M_PI/nl;
00376         int dx = (int)rint(radius*sin(fi) + cx) - mx;
00377         int dy = (int)rint(-radius*cos(fi) + cy) - my;
00378         wl[i] = dx*dx + dy*dy;
00379         if(wl[i] < 0.00001) wl[i] = 1000000;
00380         else wl[i] = 1/wl[i];
00381         wlsum += wl[i];
00382     }
00383             
00384 #else
00385     if(nl!=m_NLights) return;
00386     for(int j=0;j<nl;j++) {
00387         wl[j] = getLj(j,wxPoint(m_WeightX,m_WeightY));
00388         wlsum += wl[j];
00389     } 
00390 #endif
00391     for(int i=0;i<nl;i++)       //normalize sum
00392         wl[i] /= wlsum;
00393 
00394     float intensity = (LDIAL_SLDRES-m_LightIntensity->GetValue())
00395         /float(LDIAL_SLDRES)*LDIAL_INTENSITY;
00396     m_TFunc.setLightIntensity(intensity);
00397     m_TFunc.weightLights(wl);
00398             
00399     delete wl;
00400 }
00401 
00402 void vuLightDial::repaintParent()
00403 {
00404     ((vuUtilityWindow*)GetParent())->notifyDataChanged();
00405 }
00406 
00407 //----------------------------------------------------------------------------
00408 //----------------------------------------------------------------------------

Generated on Wed Dec 15 21:20:35 2004 for vuVolume by  doxygen 1.3.9.1