nux-1.16.0
|
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 }