nux-1.14.0
SplineCurvePreview.cpp
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "Nux.h"
00024 
00025 #include "NuxGraphics/GpuDevice.h"
00026 #include "NuxGraphics/GLDeviceObjects.h"
00027 #include "NuxGraphics/GLSh_DrawFunction.h"
00028 
00029 #include "Button.h"
00030 #include "Dialog.h"
00031 #include "SplineCurveEditor.h"
00032 #include "SplineCurvePreview.h"
00033 
00034 namespace nux
00035 {
00036 
00037   static const int GRAPH_MARGIN = 1;
00038 
00039   static void ThreadWidgetInitDialog (NThread *thread, void *InitData)
00040   {
00041     VLayout *MainLayout (new VLayout (NUX_TRACKER_LOCATION) );
00042     SplineCurveEditor *SplineControl (new SplineCurveEditor (NUX_TRACKER_LOCATION) );
00043     SplineCurveDialogProxy *splinecurveproxy = static_cast<SplineCurveDialogProxy *> (InitData);
00044 
00045     if (splinecurveproxy)
00046     {
00047       SplineControl->SetControlPoints (splinecurveproxy->GetControlPoints() );
00048       SplineControl->sigCurveChange.connect (sigc::mem_fun (splinecurveproxy, &SplineCurveDialogProxy::RecvDialogChange) );
00049     }
00050     else
00051     {
00052       SplineControl->Reset();
00053       SplineControl->AddKnot (0.0, 0.0);
00054       SplineControl->AddKnot (1.0, 1.0);
00055     }
00056 
00057     HLayout *ButtonLayout = new HLayout (TEXT ("Dialog Buttons"), NUX_TRACKER_LOCATION);
00058 
00059     Button *OkButton = new Button (TEXT ("OK"), NUX_TRACKER_LOCATION);
00060     OkButton->SetMinimumWidth (60);
00061     OkButton->SetMinimumHeight (20);
00062 
00063     Button *CancelButton = new Button (TEXT ("Cancel"), NUX_TRACKER_LOCATION);
00064     CancelButton->SetMinimumWidth (60);
00065     CancelButton->SetMinimumHeight (20);
00066 
00067     //FIXME - OkButton->sigClick.connect (sigc::mem_fun (static_cast<WindowThread *> (thread), &WindowThread::TerminateThread) );
00068     //FIXME - OkButton->sigClick.connect (sigc::bind (sigc::mem_fun (splinecurveproxy, &SplineCurveDialogProxy::RecvDialogOk), SplineControl) );
00069     //FIXME - CancelButton->sigClick.connect (sigc::bind (sigc::mem_fun (splinecurveproxy, &SplineCurveDialogProxy::RecvDialogCancel), SplineControl) );
00070     //FIXME - CancelButton->sigClick.connect (sigc::mem_fun (static_cast<WindowThread *> (thread), &WindowThread::TerminateThread) );
00071 
00072     ButtonLayout->SetHorizontalInternalMargin (6);
00073     ButtonLayout->SetVerticalExternalMargin (2);
00074     ButtonLayout->AddView (OkButton, 0);
00075     ButtonLayout->AddView (CancelButton, 0);
00076 
00077     MainLayout->AddView (SplineControl);
00078     MainLayout->AddLayout (ButtonLayout, 0);
00079     static_cast<WindowThread *> (thread)->SetLayout (MainLayout);
00080 
00081     MainLayout->SetBaseWidth (1);
00082     MainLayout->SetBaseHeight (1);
00083     MainLayout->ComputeLayout2();
00084     static_cast<WindowThread *> (thread)->SetWindowSize (MainLayout->GetBaseWidth(), MainLayout->GetBaseHeight() );
00085 
00086     // Call StopThreadMonitoring in case the dialog was close by clicking the window close button.
00087     //splinecurveproxy->StopThreadMonitoring();
00088   }
00089 
00090   SplineCurveDialogProxy::SplineCurveDialogProxy (bool ModalWindow)
00091     :   m_bDialogChange (false)
00092     ,   m_bDialogRunning (false)
00093     ,   m_ModalWindow (ModalWindow)
00094   {
00095     m_ControlPoints.Reset();
00096   }
00097 
00098   SplineCurveDialogProxy::~SplineCurveDialogProxy()
00099   {
00100   }
00101 
00102   void SplineCurveDialogProxy::Start()
00103   {
00104     m_PreviousControlPoints = m_ControlPoints;
00105 
00106     m_Thread = CreateModalWindowThread (WINDOWSTYLE_TOOL, TEXT ("Spline Curve"), 200, 200, GetWindowThread (),
00107                                         ThreadWidgetInitDialog,
00108                                         this);
00109 
00110     if (m_Thread)
00111     {
00112       m_DialogThreadID = m_Thread->GetThreadId();
00113       m_Thread->Start (0);
00114     }
00115 
00116     m_bDialogRunning = true;
00117   }
00118 
00119   bool SplineCurveDialogProxy::IsActive()
00120   {
00121     return (m_Thread && (m_Thread->GetThreadState() != THREADSTOP) && m_bDialogRunning);
00122   }
00123 
00124   void SplineCurveDialogProxy::RecvDialogOk (SplineCurveEditor *splinecurve)
00125   {
00126     m_ControlPoints = splinecurve->GetControlPoints();
00127     m_PreviousControlPoints = m_ControlPoints;
00128     m_bDialogChange = true;
00129     m_bDialogRunning = false;
00130   }
00131 
00132   void SplineCurveDialogProxy::RecvDialogCancel (SplineCurveEditor *splinecurve)
00133   {
00134     m_ControlPoints = m_PreviousControlPoints;
00135     m_bDialogChange = true;
00136     m_bDialogRunning = false;
00137   }
00138 
00139   void SplineCurveDialogProxy::RecvDialogChange (SplineCurveEditor *splinecurve)
00140   {
00141     m_ControlPoints = splinecurve->GetControlPoints();
00142     m_bDialogChange = true;
00143   }
00144 
00145   void SplineCurveDialogProxy::StopThreadMonitoring()
00146   {
00147     m_ControlPoints = m_PreviousControlPoints;
00148     m_bDialogChange = true;
00149     m_bDialogRunning = false;
00150     m_DialogThreadID = 0;
00151     m_Thread = 0;
00152   }
00153 
00154   const SplineKnot &SplineCurveDialogProxy::GetControlPoints() const
00155   {
00156     return m_ControlPoints;
00157   }
00158 
00159   void SplineCurveDialogProxy::SetControlPoints (const SplineKnot &splineknot)
00160   {
00161     m_ControlPoints = splineknot;
00162   }
00163 
00164   SplineCurvePreview::SplineCurvePreview (NUX_FILE_LINE_DECL)
00165     :   View (NUX_FILE_LINE_PARAM)
00166     ,   m_minX (0.0f)
00167     ,   m_minY (0.0f)
00168     ,   m_maxX (1.0f)
00169     ,   m_maxY (1.0f)
00170   {
00171     SetMinMaxSize (32, 32);
00172     //setSize(200, 100);
00173 
00174     m_control_knot.Reset();
00175     m_CubicSpline.Set (m_control_knot.GetNumKnot(), m_control_knot.GetXArray(), m_control_knot.GetYArray() );
00176 
00177     Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (256, 4, 0, BITFMT_R8G8B8A8);
00178     m_DrawFunctionShader = new GLSh_DrawFunction();
00179 
00180     m_DialogThreadProxy = new SplineCurveDialogProxy (true);
00181 
00182     mouse_click.connect (sigc::mem_fun (this, &SplineCurvePreview::RecvClick) );
00183 
00184     NTextureData image;
00185     MakeCheckBoardImage (image.GetSurface (0), 64, 64, Color (0xff323232), Color (0xff535353), 4, 4);
00186     BaseTexture* BackgroundTexture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture ();
00187     BackgroundTexture->Update (&image);
00188 
00189     TexCoordXForm texxform;
00190     texxform.SetTexCoordType (TexCoordXForm::OFFSET_COORD);
00191     texxform.SetWrap (TEXWRAP_REPEAT, TEXWRAP_REPEAT);
00192     m_BackgroundLayer = new TextureLayer (BackgroundTexture->GetDeviceTexture(), texxform, color::White);
00193 
00194     m_ChangeDetectionTimer = new TimerFunctor();
00195     m_ChangeDetectionTimer->OnTimerExpired.connect (sigc::mem_fun (this, &SplineCurvePreview::RecvTimer) );
00196     m_ChangeTimerHandler = 0;
00197 
00198     BackgroundTexture->UnReference ();
00199   }
00200 
00201   SplineCurvePreview::~SplineCurvePreview()
00202   {
00203     delete m_BackgroundLayer;
00204     delete m_DrawFunctionShader;
00205     delete m_DialogThreadProxy;
00206     delete m_ChangeDetectionTimer;
00207   }
00208 
00209   long SplineCurvePreview::ProcessEvent (IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
00210   {
00211     long ret = TraverseInfo;
00212     ret = PostProcessEvent2 (ievent, ret, ProcessEventInfo);
00213     return ret;
00214   }
00215 
00216   void SplineCurvePreview::Draw (GraphicsEngine &GfxContext, bool force_draw)
00217   {
00218     Geometry base = GetGeometry();
00219 
00220     GetPainter().PaintBackground (GfxContext, base);
00221     GetPainter().Paint2DQuadColor (GfxContext, base, Color (0xFFAAAAAA) );
00222     GetPainter().Paint2DQuadWireframe (GfxContext, base, Color (COLOR_BACKGROUND_SECONDARY) );
00223 
00224     base.OffsetPosition (GRAPH_MARGIN, GRAPH_MARGIN);
00225     base.OffsetSize (-2 * GRAPH_MARGIN, -2 * GRAPH_MARGIN);
00226 
00227     int W = base.GetWidth();
00228     int H = base.GetHeight();
00229     int X = base.x;
00230     int Y = base.y;
00231 
00232     float dX = (m_maxX - m_minX) / (W - 1);
00233 
00234     float x0, y0;
00235     x0 = m_minX;
00236 
00237     if (m_control_knot.GetNumKnot() <= 1)
00238       y0 = 0.0;
00239     else
00240       y0 = m_CubicSpline.Eval (x0);
00241 
00242     GfxContext.PushClippingRectangle (base);
00243 
00244     float tex_dx = (m_maxX - m_minX) / Texture->GetWidth();
00245     SURFACE_LOCKED_RECT lockrect;
00246     Texture->LockRect (0, &lockrect, 0);
00247     BYTE *dest = (BYTE *) lockrect.pBits;
00248 
00249     for (t_s32 i = 0; i < Texture->GetWidth(); i++)
00250     {
00251       float y = 0.0;
00252 
00253       if (m_control_knot.GetNumKnot() <= 1)
00254         y = 0.0;
00255       else
00256         y = m_CubicSpline.Eval (m_minX + i * tex_dx);
00257 
00258       y = (y - m_minY) / (m_maxY - m_minY);
00259 
00260       for (t_s32 j = 0; j < Texture->GetHeight(); j++)
00261       {
00262         dest[4*i + 0 + j *lockrect.Pitch] = 255 * Clamp<float> (y, 0.0f, 1.0f);
00263         dest[4*i + 1 + j *lockrect.Pitch] = 255 * Clamp<float> (y, 0.0f, 1.0f);
00264         dest[4*i + 2 + j *lockrect.Pitch] = 255 * Clamp<float> (y, 0.0f, 1.0f);
00265         dest[4*i + 3 + j *lockrect.Pitch] = 255 * Clamp<float> (y, 0.0f, 1.0f);
00266       }
00267     }
00268 
00269     Texture->UnlockRect (0);
00270 
00271     m_BackgroundLayer->SetGeometry (base);
00272     m_BackgroundLayer->Renderlayer (GfxContext);
00273 
00274     GfxContext.GetRenderStates().SetBlend (TRUE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00275 
00276     m_DrawFunctionShader->SetTextureFunction (Texture);
00277     m_DrawFunctionShader->SetBackgroundColor (Color(0.1f, 0.1f, 0.1f, 0.6f));
00278     m_DrawFunctionShader->Render (X, Y, 0, W, H, GfxContext.GetWindowWidth(), GfxContext.GetWindowHeight() );
00279 
00280     GfxContext.GetRenderStates().EnableLineSmooth (TRUE, 1, GL_FASTEST);   //You need this blending formula to get anti-aliased lines
00281     GfxContext.GetRenderStates().SetColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
00282 
00283     for (int i = 1; i < W; i++)
00284     {
00285       float x1, y1;
00286       x1 = x0 + dX;
00287 
00288       if (m_control_knot.GetNumKnot() <= 1)
00289         y1 = 0.0;
00290       else
00291         y1 = m_CubicSpline.Eval (x1);
00292 
00293       int X0, Y0, X1, Y1;
00294       X0 = X + W * (x0 - m_minX) / (m_maxX - m_minX);
00295       Y0 = Y + H * ( 1 - (y0 - m_minY) / (m_maxY - m_minY) );
00296       X1 = X + W * (x1 - m_minX) / (m_maxX - m_minX);
00297       Y1 = Y + H * ( 1 - (y1 - m_minY) / (m_maxY - m_minY) );
00298       GetPainter().Draw2DLine (GfxContext, X0, Y0, X1, Y1, Color (0xFFFFFFFF) );
00299 
00300       x0 = x1;
00301       y0 = y1;
00302     }
00303 
00304     GfxContext.GetRenderStates().EnableLineSmooth (FALSE);
00305     GfxContext.GetRenderStates().SetBlend (GL_FALSE);
00306     GfxContext.GetRenderStates().SetColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00307 
00308 
00309     GfxContext.PopClippingRectangle();
00310   }
00311 
00312   void SplineCurvePreview::DrawContent (GraphicsEngine &GfxContext, bool force_draw)
00313   {
00314 
00315   }
00316 
00317   void SplineCurvePreview::PostDraw (GraphicsEngine &GfxContext, bool force_draw)
00318   {
00319 
00320   }
00321 
00322   void SplineCurvePreview::SetXAxisBounds (float minX, float maxX)
00323   {
00324     m_minX = minX;
00325     m_maxX = maxX;
00326     QueueDraw();
00327   }
00328 
00329   void SplineCurvePreview::SetYAxisBounds (float minY, float maxY)
00330   {
00331     m_minY = minY;
00332     m_maxY = maxY;
00333     QueueDraw();
00334   }
00335 
00336   void SplineCurvePreview::UpdateGraph()
00337   {
00338     QueueDraw();
00339   }
00340 
00341   void SplineCurvePreview::RecvClick (int x, int y, unsigned long button_flags, unsigned long key_flags)
00342   {
00343     m_DialogThreadProxy->Start();
00344     m_ChangeTimerHandler = GetTimer().AddTimerHandler (33, m_ChangeDetectionTimer, this);
00345   }
00346 
00347   void SplineCurvePreview::RecvTimer (void *v)
00348   {
00349     if (m_DialogThreadProxy->m_bDialogChange && m_DialogThreadProxy->m_bDialogRunning)
00350     {
00351       m_DialogThreadProxy->m_bDialogChange = false;
00352       m_control_knot = m_DialogThreadProxy->GetControlPoints();
00353 
00354       if (m_control_knot.GetNumKnot() == 0)
00355       {
00356         NUX_HARDWARE_BREAK;
00357       }
00358 
00359       m_CubicSpline.Set (m_control_knot.GetNumKnot(), m_control_knot.GetXArray(), m_control_knot.GetYArray() );
00360       QueueDraw();
00361     }
00362 
00363     if (m_DialogThreadProxy->IsActive() )
00364     {
00365       m_ChangeTimerHandler = GetTimer().AddTimerHandler (30, m_ChangeDetectionTimer, this);
00366     }
00367     else
00368     {
00369       if (m_ChangeTimerHandler.IsValid() )
00370         GetTimer().RemoveTimerHandler (m_ChangeTimerHandler);
00371 
00372       m_ChangeTimerHandler = 0;
00373 
00374       m_control_knot = m_DialogThreadProxy->GetControlPoints();
00375 
00376       if (m_control_knot.GetNumKnot() == 0)
00377       {
00378         NUX_HARDWARE_BREAK;
00379       }
00380 
00381       m_CubicSpline.Set (m_control_knot.GetNumKnot(), m_control_knot.GetXArray(), m_control_knot.GetYArray() );
00382 
00383       QueueDraw();
00384     }
00385   }
00386 
00387   void SplineCurvePreview::RecvDialogChange (SplineCurveEditor *splinecurve)
00388   {
00389     //sigSplineChanged.emit(m_control_knot);
00390     QueueDraw();
00391   }
00392 
00393   int SplineCurvePreview::GetNumKnot() const
00394   {
00395     return m_control_knot.GetNumKnot();
00396   }
00397 
00398   SplineKnot::Knot SplineCurvePreview::GetKnot (int i) const
00399   {
00400     return m_control_knot.GetKnot (i);
00401   }
00402 
00403   double SplineCurvePreview::Eval (double t)
00404   {
00405     double val;
00406     int nbKnot = m_control_knot.GetNumKnot();
00407 
00408     if (nbKnot <= 1)
00409       return 0.0;
00410 
00411     if (t < m_control_knot[0].GetX() )
00412       val = m_control_knot[0].GetY();
00413     else if (t > m_control_knot[nbKnot-1].GetX() )
00414       val = m_control_knot[nbKnot-1].GetY();
00415     else
00416       val = m_CubicSpline.Eval (t);
00417 
00418     if (val > m_maxY)
00419       val = m_maxY;
00420 
00421     if (val < m_minY)
00422       val = m_minY;
00423 
00424     return val;
00425   }
00426 
00427   const SplineKnot &SplineCurvePreview::GetControlPoints() const
00428   {
00429     return m_control_knot;
00430   }
00431 
00432   void SplineCurvePreview::SetControlPoints (const SplineKnot &splineknot)
00433   {
00434     m_control_knot = splineknot;
00435     m_CubicSpline.Set (m_control_knot.GetNumKnot(), m_control_knot.GetXArray(), m_control_knot.GetYArray() );
00436   }
00437 
00438   void SplineCurvePreview::Reset()
00439   {
00440     m_control_knot.Reset();
00441     m_CubicSpline.Set (m_control_knot.GetNumKnot(), m_control_knot.GetXArray(), m_control_knot.GetYArray() );
00442   }
00443 
00444   void SplineCurvePreview::AddKnot (double x, double y, bool bSelected)
00445   {
00446     m_control_knot.AddKnot (x, y, bSelected);
00447     m_CubicSpline.Set (m_control_knot.GetNumKnot(), m_control_knot.GetXArray(), m_control_knot.GetYArray() );
00448   }
00449 
00450 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends