]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/tools/radiant/LightDlg.cpp
hello world
[icculus/iodoom3.git] / neo / tools / radiant / LightDlg.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include "qe3.h"
33 #include "Radiant.h"
34 #include "../../game/game.h"
35 #include "../comafx/DialogColorPicker.h"
36 #include "LightDlg.h"
37
38 #ifdef ID_DEBUG_MEMORY
39 #undef new
40 #undef DEBUG_NEW
41 #define DEBUG_NEW new
42 #endif
43
44
45 void CLightInfo::Defaults() {
46         pointLight = true;
47         fallOff = 1;
48         strTexture = "";
49         equalRadius = true;
50         explicitStartEnd = false;
51         lightRadius.Zero();
52         lightTarget.Zero();
53         lightRight.Zero();
54         lightUp.Zero();
55         lightStart.Zero();
56         lightEnd.Zero();
57         lightCenter.Zero();
58         hasCenter = false;
59         isParallel = false;
60         castShadows = true;
61         castSpecular = true;
62         castDiffuse = true;
63         rotate = false;
64         strobe = false;
65         rotateSpeed = 0;
66         strobeSpeed = 0;
67         color[0] = color[1] = color[2] = 255;
68         fogDensity[0] = fogDensity[1] = fogDensity[2] = 0;
69         fog = false;
70         lightRadius[0] = lightRadius[1] = lightRadius[2] = 300;
71 }
72
73
74 void CLightInfo::DefaultPoint() {
75         idVec3 oldColor = color;
76         Defaults();
77         color = oldColor;
78         pointLight = true;
79 }
80
81 void CLightInfo::DefaultProjected() {
82         idVec3 oldColor = color;
83         Defaults();
84         color = oldColor;
85         pointLight = false;
86         lightTarget[2] = -256;
87         lightUp[1] = -128;
88         lightRight[0] = -128;
89 }
90
91 void CLightInfo::FromDict( const idDict *e ) {
92
93         lightRadius.Zero();
94         lightTarget.Zero();
95         lightRight.Zero();
96         lightUp.Zero();
97         lightStart.Zero();
98         lightEnd.Zero();
99         lightCenter.Zero();
100
101         castShadows = !e->GetBool("noshadows");
102         castSpecular = !e->GetBool("nospecular");
103         castDiffuse = !e->GetBool("nodiffuse");
104         fallOff = e->GetFloat("falloff");
105         strTexture = e->GetString("texture");
106
107         isParallel = e->GetBool("parallel");
108
109         if (!e->GetVector("_color", "", color)) {
110                 color[0] = color[1] = color[2] = 1;
111         }
112         // windows needs 0-255 scale
113         color[0] *= 255;
114         color[1] *= 255;
115         color[2] *= 255;
116
117         if (e->GetVec4("fog", "", fogDensity)) {
118                 fog = true;
119         } else {
120                 fog = false;
121         }
122
123         if (e->GetVector("light_right","", lightRight)) {
124                 // projected light
125                 pointLight = false;
126                 e->GetVector("light_target", "", lightTarget);
127                 e->GetVector("light_up", "", lightUp);
128                 if (e->GetVector("light_start", "", lightStart)) {
129                         // explicit start and end points
130                         explicitStartEnd = true;
131                         if (!e->GetVector("light_end", "", lightEnd)) {
132                                 // no end, use target
133                                 VectorCopy(lightTarget, lightEnd);
134                         }
135                 } else {
136                         explicitStartEnd = false;
137                         // create a start a quarter of the way to the target
138                         lightStart = lightTarget * 0.25;
139                         VectorCopy(lightTarget, lightEnd);
140                 }
141         } else {
142                 pointLight = true;
143                 if (e->GetVector("light_radius", "", lightRadius)) {
144                         equalRadius = false;
145                 } else {
146                         float radius = e->GetFloat("light");
147                         if (radius == 0) {
148                                 radius = 300;
149                         }
150                         lightRadius[0] = lightRadius[1] = lightRadius[2] = radius;
151                         equalRadius = true;
152                 }
153                 if (e->GetVector("light_center", "", lightCenter)) {
154                         hasCenter = true;
155                 }
156         }
157 }
158
159 void CLightInfo::ToDictFromDifferences ( idDict *e, const idDict *differences ) {
160     for ( int i = 0 ; i < differences->GetNumKeyVals () ; i ++ ) {
161         const idKeyValue *kv = differences->GetKeyVal( i );
162         
163         if ( kv->GetValue().Length() > 0 ) {
164             e->Set ( kv->GetKey() ,kv->GetValue() );
165                 } else {
166                 e->Delete ( kv->GetKey() );
167                 }
168
169         common->Printf( "Applied difference: %s %s\n" , kv->GetKey().c_str() , kv->GetValue().c_str() );
170     }
171 }
172
173 //write all info to a dict, regardless of light type
174 void CLightInfo::ToDictWriteAllInfo( idDict *e ) {
175     e->Set("noshadows", (!castShadows) ? "1" : "0");
176         e->Set("nospecular", (!castSpecular) ? "1" : "0");
177         e->Set("nodiffuse", (!castDiffuse) ? "1" : "0");
178
179         e->SetFloat("falloff",fallOff);
180         
181         if (strTexture.GetLength() > 0 ) {
182                 e->Set("texture", strTexture);
183         }
184
185         idVec3 temp = color;
186         temp /= 255;
187         e->SetVector("_color", temp);
188
189         if (!equalRadius) {
190                 e->Set("light_radius", va("%g %g %g", lightRadius[0], lightRadius[1], lightRadius[2]));
191         } else {
192                 e->Set("light_radius", va("%g %g %g", lightRadius[0], lightRadius[0], lightRadius[0]));
193         }
194
195         e->Set("light_center", va("%g %g %g", lightCenter[0], lightCenter[1], lightCenter[2]));
196     e->Set("parallel", isParallel?"1":"0");
197
198     e->Set("light_target", va("%g %g %g", lightTarget[0], lightTarget[1], lightTarget[2]));
199         e->Set("light_up", va("%g %g %g", lightUp[0], lightUp[1], lightUp[2]));
200         e->Set("light_right", va("%g %g %g", lightRight[0], lightRight[1], lightRight[2]));
201     e->Set("light_start", va("%g %g %g", lightStart[0], lightStart[1], lightStart[2]));
202         e->Set("light_end", va("%g %g %g", lightEnd[0], lightEnd[1], lightEnd[2]));
203 }
204
205 void CLightInfo::ToDict( idDict *e ) {
206
207         e->Delete("noshadows");
208         e->Delete("nospecular");
209         e->Delete("nodiffuse");
210         e->Delete("falloff");
211         e->Delete("parallel");
212         e->Delete("texture");
213         e->Delete("_color");
214         e->Delete("fog");
215         e->Delete("light_target");
216         e->Delete("light_right");
217         e->Delete("light_up");
218         e->Delete("light_start");
219         e->Delete("light_end");
220         e->Delete("light_radius");
221         e->Delete("light_center");
222         e->Delete("light");
223
224         e->Set("noshadows", (!castShadows) ? "1" : "0");
225         e->Set("nospecular", (!castSpecular) ? "1" : "0");
226         e->Set("nodiffuse", (!castDiffuse) ? "1" : "0");
227
228         e->SetFloat("falloff",fallOff);
229         
230         if (strTexture.GetLength() > 0) {
231                 e->Set("texture", strTexture);
232         }
233
234         idVec3 temp = color;
235         temp /= 255;
236         e->SetVector("_color", temp);
237
238         if (fog) {
239                 e->Set("fog", va("%g %g %g %g", fogDensity[0]/255.0, fogDensity[1]/255.0, fogDensity[2]/255.0, fogDensity[3]/255.0));
240         }
241
242         if (pointLight) {
243                 if (!equalRadius) {
244                         e->Set("light_radius", va("%g %g %g", lightRadius[0], lightRadius[1], lightRadius[2]));
245                 } else {
246                         e->Set("light_radius", va("%g %g %g", lightRadius[0], lightRadius[0], lightRadius[0]));
247                 }
248
249                 if (hasCenter) {
250                         e->Set("light_center", va("%g %g %g", lightCenter[0], lightCenter[1], lightCenter[2]));
251                 }
252
253                 if (isParallel) {
254                         e->Set("parallel", "1");
255                 }
256         } else {
257                 e->Set("light_target", va("%g %g %g", lightTarget[0], lightTarget[1], lightTarget[2]));
258                 e->Set("light_up", va("%g %g %g", lightUp[0], lightUp[1], lightUp[2]));
259                 e->Set("light_right", va("%g %g %g", lightRight[0], lightRight[1], lightRight[2]));
260                 if (explicitStartEnd) {
261                         e->Set("light_start", va("%g %g %g", lightStart[0], lightStart[1], lightStart[2]));
262                         e->Set("light_end", va("%g %g %g", lightEnd[0], lightEnd[1], lightEnd[2]));
263                 }
264         }
265 }
266
267 CLightInfo::CLightInfo() {
268         Defaults();
269 }
270
271
272
273 /////////////////////////////////////////////////////////////////////////////
274 // CLightDlg dialog
275
276 CLightDlg *g_LightDialog = NULL;
277
278
279 CLightDlg::CLightDlg(CWnd* pParent /*=NULL*/)
280         : CDialog(CLightDlg::IDD, pParent)
281 {
282         //{{AFX_DATA_INIT(CLightDlg)
283         m_bEqualRadius = FALSE;
284         m_bExplicitFalloff = FALSE;
285         m_bPointLight = FALSE;
286         m_bCheckProjected = FALSE;
287         m_fFallloff = 0.0f;
288         m_nFalloff = -1;
289         m_bRotate = FALSE;
290         m_bShadows = FALSE;
291         m_bSpecular = FALSE;
292         m_bDiffuse = FALSE;
293         m_fEndX = 0.0f;
294         m_fEndY = 0.0f;
295         m_fEndZ = 0.0f;
296         m_fRadiusX = 0.0f;
297         m_fRadiusY = 0.0f;
298         m_fRadiusZ = 0.0f;
299         m_fRightX = 0.0f;
300         m_fRightY = 0.0f;
301         m_fRightZ = 0.0f;
302         m_fRotate = 0.0f;
303         m_fStartX = 0.0f;
304         m_fStartY = 0.0f;
305         m_fStartZ = 0.0f;
306         m_fTargetX = 0.0f;
307         m_fTargetY = 0.0f;
308         m_fTargetZ = 0.0f;
309         m_fUpX = 0.0f;
310         m_fUpY = 0.0f;
311         m_fUpZ = 0.0f;
312         m_hasCenter = FALSE;
313         m_centerX = 0.0f;
314         m_centerY = 0.0f;
315         m_centerZ = 0.0f;
316     m_bIsParallel = FALSE;
317         //}}AFX_DATA_INIT
318         m_drawMaterial = new idGLDrawableMaterial();
319 }
320
321 CLightDlg::~CLightDlg() {
322         delete m_drawMaterial;
323 }
324
325 void CLightDlg::DoDataExchange(CDataExchange* pDX)
326 {
327         CDialog::DoDataExchange(pDX);
328         //{{AFX_DATA_MAP(CLightDlg)
329         if ( com_editorActive ) {
330                 DDX_Control(pDX, IDC_LIGHTPREVIEW, m_wndPreview);
331         }
332         DDX_Control(pDX, IDC_COMBO_TEXTURE, m_wndLights);
333         DDX_Check(pDX, IDC_CHECK_EQUALRADIUS, m_bEqualRadius);
334         DDX_Check(pDX, IDC_CHECK_EXPLICITFALLOFF, m_bExplicitFalloff);
335         DDX_Check(pDX, IDC_CHECK_POINT, m_bPointLight);
336         DDX_Check(pDX, IDC_CHECK_PROJECTED, m_bCheckProjected);
337         DDX_Radio(pDX, IDC_RADIO_FALLOFF, m_nFalloff);
338         DDX_Check(pDX, IDC_CHECK_SHADOWS, m_bShadows);
339         DDX_Check(pDX, IDC_CHECK_SPECULAR, m_bSpecular);
340         DDX_Check(pDX, IDC_CHECK_DIFFUSE, m_bDiffuse);
341     DDX_Check(pDX , IDC_CHECK_PARALLEL , m_bIsParallel );
342         DDX_Text(pDX, IDC_EDIT_ENDX, m_fEndX);
343         DDX_Text(pDX, IDC_EDIT_ENDY, m_fEndY);
344         DDX_Text(pDX, IDC_EDIT_ENDZ, m_fEndZ);
345         DDX_Text(pDX, IDC_EDIT_RADIUSX, m_fRadiusX);
346         DDX_Text(pDX, IDC_EDIT_RADIUSY, m_fRadiusY);
347         DDX_Text(pDX, IDC_EDIT_RADIUSZ, m_fRadiusZ);
348         DDX_Text(pDX, IDC_EDIT_RIGHTX, m_fRightX);
349         DDX_Text(pDX, IDC_EDIT_RIGHTY, m_fRightY);
350         DDX_Text(pDX, IDC_EDIT_RIGHTZ, m_fRightZ);
351         DDX_Text(pDX, IDC_EDIT_STARTX, m_fStartX);
352         DDX_Text(pDX, IDC_EDIT_STARTY, m_fStartY);
353         DDX_Text(pDX, IDC_EDIT_STARTZ, m_fStartZ);
354         DDX_Text(pDX, IDC_EDIT_TARGETX, m_fTargetX);
355         DDX_Text(pDX, IDC_EDIT_TARGETY, m_fTargetY);
356         DDX_Text(pDX, IDC_EDIT_TARGETZ, m_fTargetZ);
357         DDX_Text(pDX, IDC_EDIT_UPX, m_fUpX);
358         DDX_Text(pDX, IDC_EDIT_UPY, m_fUpY);
359         DDX_Text(pDX, IDC_EDIT_UPZ, m_fUpZ);
360         DDX_Check(pDX, IDC_CHECK_CENTER, m_hasCenter);
361         DDX_Text(pDX, IDC_EDIT_CENTERX, m_centerX);
362         DDX_Text(pDX, IDC_EDIT_CENTERY, m_centerY);
363         DDX_Text(pDX, IDC_EDIT_CENTERZ, m_centerZ);
364         //}}AFX_DATA_MAP
365 }
366
367
368 BEGIN_MESSAGE_MAP(CLightDlg, CDialog)
369         //{{AFX_MSG_MAP(CLightDlg)
370         ON_BN_CLICKED(IDC_BTN_TEXTURE, OnBtnTexture)
371         ON_BN_CLICKED(IDC_CHECK_EQUALRADIUS, OnCheckEqualradius)
372         ON_BN_CLICKED(IDC_CHECK_EXPLICITFALLOFF, OnCheckExplicitfalloff)
373         ON_BN_CLICKED(IDC_CHECK_POINT, OnCheckPoint)
374         ON_BN_CLICKED(IDC_CHECK_PROJECTED, OnCheckProjected)
375         ON_BN_CLICKED(IDC_RADIO_FALLOFF, OnRadioFalloff)
376         ON_BN_CLICKED(IDC_APPLY, OnApply)
377     ON_BN_CLICKED(IDC_APPLY_DIFFERENT, OnApplyDifferences)
378         ON_BN_CLICKED(IDC_BTN_COLOR, OnBtnColor)
379         ON_WM_CTLCOLOR()
380         ON_CBN_SELCHANGE(IDC_COMBO_TEXTURE, OnSelchangeComboTexture)
381         ON_BN_CLICKED(IDC_CHECK_CENTER, OnCheckCenter)
382         ON_BN_CLICKED(IDC_CHECK_PARALLEL, OnCheckParallel)
383         //}}AFX_MSG_MAP
384 END_MESSAGE_MAP()
385
386 /////////////////////////////////////////////////////////////////////////////
387 // CLightDlg message handlers
388
389 void CLightDlg::SetSpecifics() {
390         if (lightInfo.pointLight) {
391                 GetDlgItem(IDC_EDIT_RADIUSY)->EnableWindow(!lightInfo.equalRadius);
392                 GetDlgItem(IDC_EDIT_RADIUSZ)->EnableWindow(!lightInfo.equalRadius);
393                 GetDlgItem(IDC_EDIT_CENTERX)->EnableWindow(lightInfo.hasCenter);
394                 GetDlgItem(IDC_EDIT_CENTERY)->EnableWindow(lightInfo.hasCenter);
395                 GetDlgItem(IDC_EDIT_CENTERZ)->EnableWindow(lightInfo.hasCenter);
396         } else {
397                 GetDlgItem(IDC_EDIT_STARTX)->EnableWindow(lightInfo.explicitStartEnd);
398                 GetDlgItem(IDC_EDIT_STARTY)->EnableWindow(lightInfo.explicitStartEnd);
399                 GetDlgItem(IDC_EDIT_STARTZ)->EnableWindow(lightInfo.explicitStartEnd);
400                 GetDlgItem(IDC_EDIT_ENDX)->EnableWindow(lightInfo.explicitStartEnd);
401                 GetDlgItem(IDC_EDIT_ENDY)->EnableWindow(lightInfo.explicitStartEnd);
402                 GetDlgItem(IDC_EDIT_ENDZ)->EnableWindow(lightInfo.explicitStartEnd);
403         }
404 }
405
406 void CLightDlg::EnableControls() {
407         GetDlgItem(IDC_CHECK_EQUALRADIUS)->EnableWindow(lightInfo.pointLight);
408         GetDlgItem(IDC_EDIT_RADIUSX)->EnableWindow(lightInfo.pointLight);
409         GetDlgItem(IDC_EDIT_RADIUSY)->EnableWindow(lightInfo.pointLight);
410         GetDlgItem(IDC_EDIT_RADIUSZ)->EnableWindow(lightInfo.pointLight);
411         GetDlgItem(IDC_RADIO_FALLOFF)->EnableWindow(lightInfo.pointLight);
412         GetDlgItem(IDC_RADIO_FALLOFF2)->EnableWindow(lightInfo.pointLight);
413         GetDlgItem(IDC_RADIO_FALLOFF3)->EnableWindow(lightInfo.pointLight);
414         GetDlgItem(IDC_EDIT_TARGETX)->EnableWindow(!lightInfo.pointLight);
415         GetDlgItem(IDC_EDIT_TARGETY)->EnableWindow(!lightInfo.pointLight);
416         GetDlgItem(IDC_EDIT_TARGETZ)->EnableWindow(!lightInfo.pointLight);
417         GetDlgItem(IDC_EDIT_RIGHTX)->EnableWindow(!lightInfo.pointLight);
418         GetDlgItem(IDC_EDIT_RIGHTY)->EnableWindow(!lightInfo.pointLight);
419         GetDlgItem(IDC_EDIT_RIGHTZ)->EnableWindow(!lightInfo.pointLight);
420         GetDlgItem(IDC_EDIT_UPX)->EnableWindow(!lightInfo.pointLight);
421         GetDlgItem(IDC_EDIT_UPY)->EnableWindow(!lightInfo.pointLight);
422         GetDlgItem(IDC_EDIT_UPZ)->EnableWindow(!lightInfo.pointLight);
423         GetDlgItem(IDC_EDIT_STARTX)->EnableWindow(!lightInfo.pointLight);
424         GetDlgItem(IDC_EDIT_STARTY)->EnableWindow(!lightInfo.pointLight);
425         GetDlgItem(IDC_EDIT_STARTZ)->EnableWindow(!lightInfo.pointLight);
426         GetDlgItem(IDC_EDIT_ENDX)->EnableWindow(!lightInfo.pointLight);
427         GetDlgItem(IDC_EDIT_ENDY)->EnableWindow(!lightInfo.pointLight);
428         GetDlgItem(IDC_EDIT_ENDZ)->EnableWindow(!lightInfo.pointLight);
429         GetDlgItem(IDC_CHECK_EXPLICITFALLOFF)->EnableWindow(!lightInfo.pointLight);
430         GetDlgItem(IDC_CHECK_POINT)->EnableWindow(!lightInfo.pointLight);
431         GetDlgItem(IDC_CHECK_PROJECTED)->EnableWindow(lightInfo.pointLight);
432         GetDlgItem(IDC_EDIT_CENTERX)->EnableWindow(lightInfo.pointLight);
433         GetDlgItem(IDC_EDIT_CENTERY)->EnableWindow(lightInfo.pointLight);
434         GetDlgItem(IDC_EDIT_CENTERZ)->EnableWindow(lightInfo.pointLight);
435         GetDlgItem(IDC_CHECK_CENTER)->EnableWindow(lightInfo.pointLight);
436
437         reinterpret_cast<CButton*>(GetDlgItem(IDC_CHECK_PROJECTED))->SetCheck(!lightInfo.pointLight);
438         reinterpret_cast<CButton*>(GetDlgItem(IDC_CHECK_POINT))->SetCheck(lightInfo.pointLight);
439
440         SetSpecifics();
441 }
442
443 void CLightDlg::UpdateDialogFromLightInfo( void ) {
444         m_hasCenter = lightInfo.hasCenter;
445         m_bEqualRadius = lightInfo.equalRadius;
446         m_bExplicitFalloff = lightInfo.explicitStartEnd;
447         m_bPointLight = lightInfo.pointLight;
448         m_bCheckProjected = !lightInfo.pointLight;
449         m_fFallloff = lightInfo.fallOff;
450         if (lightInfo.fallOff < 0.35) {
451                 m_nFalloff = 0;
452         } else if (lightInfo.fallOff < 0.70) {
453                 m_nFalloff = 1;
454         } else {
455                 m_nFalloff = 2;
456         }
457         //m_bFog = lightInfo.fog;
458         m_bRotate = lightInfo.rotate;
459         m_bShadows = lightInfo.castShadows;
460         m_bSpecular = lightInfo.castSpecular;
461         //m_bStrobe = lightInfo.strobe;
462         //m_fStrobe = lightInfo.strobeSpeed;
463         int sel = m_wndLights.FindStringExact(-1, lightInfo.strTexture);
464         m_wndLights.SetCurSel(sel);
465         if (sel >= 0) {
466                 m_drawMaterial->setMedia(lightInfo.strTexture);
467         } else {
468                 m_drawMaterial->setMedia(lightInfo.strTexture);
469         }
470
471         m_bDiffuse = lightInfo.castDiffuse;
472         m_fEndX = lightInfo.lightEnd[0];
473         m_fEndY = lightInfo.lightEnd[1];
474         m_fEndZ = lightInfo.lightEnd[2];
475         m_fRadiusX = lightInfo.lightRadius[0];
476         m_fRadiusY = lightInfo.lightRadius[1];
477         m_fRadiusZ = lightInfo.lightRadius[2];
478         m_fRightX = lightInfo.lightRight[0];
479         m_fRightY = lightInfo.lightRight[1];
480         m_fRightZ = lightInfo.lightRight[2];
481         //m_bRotate = lightInfo.rotate;
482         //m_fRotate = lightInfo.rotateSpeed;
483         m_fStartX = lightInfo.lightStart[0];
484         m_fStartY = lightInfo.lightStart[1];
485         m_fStartZ = lightInfo.lightStart[2];
486         m_fTargetX = lightInfo.lightTarget[0];
487         m_fTargetY = lightInfo.lightTarget[1];
488         m_fTargetZ = lightInfo.lightTarget[2];
489         m_fUpX = lightInfo.lightUp[0];
490         m_fUpY = lightInfo.lightUp[1];
491         m_fUpZ = lightInfo.lightUp[2];
492         VectorCopy(lightInfo.color, color);
493         //m_fFogAlpha = lightInfo.fogDensity[3];
494         m_centerX = lightInfo.lightCenter[0];
495         m_centerY = lightInfo.lightCenter[1];
496         m_centerZ = lightInfo.lightCenter[2];
497
498     //jhefty - added parallel light updating
499     m_bIsParallel = lightInfo.isParallel;
500
501         UpdateData(FALSE);
502 }
503
504 void CLightDlg::UpdateLightInfoFromDialog( void ) {
505         UpdateData( TRUE );
506         
507         lightInfo.pointLight = ( m_bPointLight != FALSE );
508         lightInfo.equalRadius = ( m_bEqualRadius != FALSE );
509         lightInfo.explicitStartEnd = ( m_bExplicitFalloff != FALSE );
510         
511         if (lightInfo.pointLight) {
512                 if (m_nFalloff == 0) {
513                         m_fFallloff = 0.0;
514                 } else if (m_nFalloff == 1) {
515                         m_fFallloff = 0.5;
516                 } else {
517                         m_fFallloff = 1.0;
518                 }
519         }
520
521         lightInfo.fallOff = m_fFallloff;
522
523         //lightInfo.fog = m_bFog;
524         lightInfo.rotate = ( m_bRotate != FALSE );
525         lightInfo.castShadows = ( m_bShadows != FALSE );
526         lightInfo.castSpecular = ( m_bSpecular != FALSE );
527
528         VectorCopy(color, lightInfo.color);
529     lightInfo.isParallel = (m_bIsParallel == TRUE);
530
531         //lightInfo.fogDensity[3] = m_fFogAlpha;
532
533         //lightInfo.strobe = m_bStrobe;
534         //lightInfo.strobeSpeed = m_fStrobe;
535         //lightInfo.rotate = m_bRotate; 
536         //lightInfo.rotateSpeed = m_fRotate;
537
538         int sel = m_wndLights.GetCurSel();
539         CString str("");
540         if (sel >= 0) {
541                 m_wndLights.GetLBText(sel, str);
542         }
543         lightInfo.strTexture = str;
544
545         lightInfo.castDiffuse = ( m_bDiffuse != FALSE );
546         lightInfo.lightEnd[0] = m_fEndX;
547         lightInfo.lightEnd[1] = m_fEndY;
548         lightInfo.lightEnd[2] = m_fEndZ;
549         lightInfo.lightRadius[0] = m_fRadiusX;
550         lightInfo.lightRadius[1] = m_fRadiusY; 
551         lightInfo.lightRadius[2] = m_fRadiusZ; 
552         lightInfo.lightRight[0] = m_fRightX;
553         lightInfo.lightRight[1] = m_fRightY;
554         lightInfo.lightRight[2] = m_fRightZ;
555         lightInfo.lightStart[0] = m_fStartX;
556         lightInfo.lightStart[1] = m_fStartY;
557         lightInfo.lightStart[2] = m_fStartZ;
558         lightInfo.lightTarget[0] = m_fTargetX;
559         lightInfo.lightTarget[1] = m_fTargetY; 
560         lightInfo.lightTarget[2] = m_fTargetZ;
561         lightInfo.lightUp[0] = m_fUpX;
562         lightInfo.lightUp[1] = m_fUpY; 
563         lightInfo.lightUp[2] = m_fUpZ;
564
565         lightInfo.hasCenter = ( m_hasCenter != FALSE );
566         lightInfo.lightCenter[0] = m_centerX;
567         lightInfo.lightCenter[1] = m_centerY;
568         lightInfo.lightCenter[2] = m_centerZ;
569 }
570
571 void CLightDlg::SaveLightInfo( const idDict *differences ) {
572
573         if ( com_editorActive ) {
574
575                 // used from Radiant
576                 for ( brush_t *b = selected_brushes.next; b && b != &selected_brushes; b = b->next ) {
577                         if ( ( b->owner->eclass->nShowFlags & ECLASS_LIGHT ) && !b->entityModel ) {
578                                 if ( differences ) {
579                                         lightInfo.ToDictFromDifferences( &b->owner->epairs, differences );
580                                 } else {
581                                         lightInfo.ToDict( &b->owner->epairs );
582                                 }
583                                 Brush_Build( b );
584                         }
585                 }
586
587         } else {
588
589                 // used in-game
590                 idList<idEntity *> list;
591
592                 list.SetNum( 128 );
593                 int count = gameEdit->GetSelectedEntities( list.Ptr(), list.Num() );
594                 list.SetNum( count );
595
596                 for ( int i = 0; i < count; i++ ) {
597                         if ( differences ) {
598                                 gameEdit->EntityChangeSpawnArgs( list[i], differences );
599                                 gameEdit->EntityUpdateChangeableSpawnArgs( list[i], NULL );
600                         } else {
601                                 idDict newArgs;
602                                 lightInfo.ToDict( &newArgs );
603                                 gameEdit->EntityChangeSpawnArgs( list[i], &newArgs );
604                                 gameEdit->EntityUpdateChangeableSpawnArgs( list[i], NULL );
605                         }
606                         gameEdit->EntityUpdateVisuals( list[i] );
607                 }
608     }
609 }
610
611 void CLightDlg::ColorButtons() {
612         CRect r;
613
614         CClientDC dc(this);
615         
616         CButton *pBtn = (CButton *)GetDlgItem(IDC_BTN_COLOR);
617         pBtn->GetClientRect(&r);
618         colorBitmap.DeleteObject();
619         colorBitmap.CreateCompatibleBitmap(&dc, r.Width(), r.Height());
620         CDC MemDC;
621         MemDC.CreateCompatibleDC(&dc);
622         CBitmap *pOldBmp = MemDC.SelectObject(&colorBitmap);
623         {
624                 CBrush br(RGB(color[0], color[1], color[2])); 
625                 MemDC.FillRect(r,&br);
626         }
627         dc.SelectObject(pOldBmp);
628         pBtn->SetBitmap(HBITMAP(colorBitmap)); 
629 }
630
631
632 void CLightDlg::LoadLightTextures() {
633         int count = declManager->GetNumDecls( DECL_MATERIAL );
634         int i;
635         const idMaterial *mat;
636         for (i = 0; i < count; i++) {
637                 mat = declManager->MaterialByIndex(i, false);
638                 idStr str = mat->GetName();
639                 str.ToLower();
640                 if (str.Icmpn("lights/", strlen("lights/")) == 0 || str.Icmpn("fogs/", strlen("fogs/")) == 0) {
641                         m_wndLights.AddString(mat->GetName());
642                 }
643         }
644 }
645
646 BOOL CLightDlg::OnInitDialog() 
647 {
648         CDialog::OnInitDialog();
649
650         com_editors |= EDITOR_LIGHT;
651
652         UpdateDialog( true );
653
654         LoadLightTextures();
655
656         if ( com_editorActive ) {
657                 m_wndPreview.setDrawable(m_drawMaterial);
658         }
659
660         return TRUE;  // return TRUE unless you set the focus to a control
661                       // EXCEPTION: OCX Property Pages should return FALSE
662 }
663
664 void CLightDlg::OnDestroy() {
665
666         com_editors &= ~EDITOR_LIGHT;
667
668         return CDialog::OnDestroy();
669 }
670
671 void CLightDlg::OnBtnTexture() 
672 {
673         // TODO: Add your control notification handler code here
674         
675 }
676
677 void CLightDlg::OnCheckEqualradius() 
678 {
679         lightInfo.equalRadius = ( reinterpret_cast<CButton*>(GetDlgItem(IDC_CHECK_EQUALRADIUS))->GetCheck() != 0 );
680         SetSpecifics();
681 }
682
683 void CLightDlg::OnCheckExplicitfalloff() 
684 {
685         lightInfo.explicitStartEnd = ( reinterpret_cast<CButton*>(GetDlgItem(IDC_CHECK_EXPLICITFALLOFF))->GetCheck() != 0 );
686         SetSpecifics();
687 }
688
689 void CLightDlg::OnCheckPoint() 
690 {
691         lightInfo.DefaultPoint();
692         UpdateDialogFromLightInfo();
693         EnableControls();
694 }
695
696 void CLightDlg::OnCheckProjected() 
697 {
698         lightInfo.DefaultProjected();
699         UpdateDialogFromLightInfo();
700         EnableControls();
701 }
702
703 void CLightDlg::OnRadioFalloff() 
704 {
705 }
706
707 void CLightDlg::OnOK() {
708         UpdateLightInfoFromDialog();
709         SaveLightInfo( NULL );
710         Sys_UpdateWindows(W_ALL);
711         CDialog::OnOK();
712 }
713
714 entity_t *SingleLightSelected() {
715         if ( QE_SingleBrush( true, true ) ) {
716                 brush_t *b = selected_brushes.next;
717                 if ( ( b->owner->eclass->nShowFlags & ECLASS_LIGHT ) && !b->entityModel ) {
718                         return b->owner;
719                 }
720         }
721         return NULL;
722 }
723
724 void CLightDlg::UpdateDialog( bool updateChecks )
725 {       
726         CString title;
727
728         lightInfo.Defaults();
729         lightInfoOriginal.Defaults ();
730
731         if ( com_editorActive ) {
732                 // used from Radiant
733                 entity_t *e = SingleLightSelected();
734                 if ( e ) {
735                         lightInfo.FromDict(&e->epairs);
736                         lightInfoOriginal.FromDict(&e->epairs); //our original copy of the values that we compare against for apply differences
737                         title = "Light Editor";
738                 } else {   
739                         //find the last brush belonging to the last entity selected and use that as the source
740                         e = NULL;
741                         for ( brush_t *b = selected_brushes.next ; b != &selected_brushes ; b = b->next ) {
742                                 if ( ( b->owner->eclass->nShowFlags & ECLASS_LIGHT ) && !b->entityModel ) {
743                                         e = b->owner;
744                                         break;
745                                 }
746                         }
747
748                         if ( e ) {
749                                 lightInfo.FromDict( &e->epairs );
750                                 lightInfoOriginal.FromDict(&e->epairs); //our original copy of the values that we compaer against for apply differences
751                                 title = "Light Editor - (Multiple lights selected)";
752                         } else {
753                                 title = "Light Editor - (No lights selected)";
754                         }
755                 }
756         } else {
757                 // used in-game
758                 idList<idEntity *> list;
759
760                 list.SetNum( 128 );
761                 int count = gameEdit->GetSelectedEntities( list.Ptr(), list.Num() );
762                 list.SetNum( count );
763
764                 if ( count > 0 ) {
765                         lightInfo.FromDict( gameEdit->EntityGetSpawnArgs( list[count-1] ) );
766                         title = "Light Editor";
767                 } else {
768                         title = "Light Editor - (No entities selected)";
769                 }
770         }
771
772         SetWindowText( title );
773
774         UpdateDialogFromLightInfo();
775         ColorButtons();
776
777         if ( updateChecks ) {
778                 EnableControls();
779         }
780 }
781
782 void LightEditorInit( const idDict *spawnArgs ) {
783         if ( renderSystem->IsFullScreen() ) {
784                 common->Printf( "Cannot run the light editor in fullscreen mode.\n"
785                                         "Set r_fullscreen to 0 and vid_restart.\n" );
786                 return;
787         }
788
789         if ( g_LightDialog == NULL ) {
790                 InitAfx();
791                 g_LightDialog = new CLightDlg();
792         }
793
794         if ( g_LightDialog->GetSafeHwnd() == NULL ) {
795                 g_LightDialog->Create( IDD_DIALOG_LIGHT );
796                 CRect rct;
797                 LONG lSize = sizeof( rct );
798                 if ( LoadRegistryInfo( "Radiant::LightWindow", &rct, &lSize ) ) {
799                         g_LightDialog->SetWindowPos(NULL, rct.left, rct.top, 0,0, SWP_NOSIZE);
800                 }
801         }
802
803         idKeyInput::ClearStates();
804
805         g_LightDialog->ShowWindow( SW_SHOW );
806         g_LightDialog->SetFocus();
807         g_LightDialog->UpdateDialog( true );
808
809         if ( spawnArgs ) {
810                 // FIXME: select light based on spawn args
811         }
812 }
813
814 void LightEditorRun( void ) {
815 #if _MSC_VER >= 1300
816         MSG *msg = AfxGetCurrentMessage();                      // TODO Robert fix me!!
817 #else
818         MSG *msg = &m_msgCur;
819 #endif
820
821         while( ::PeekMessage(msg, NULL, NULL, NULL, PM_NOREMOVE) ) {
822                 // pump message
823                 if ( !AfxGetApp()->PumpMessage() ) {
824                 }
825         }
826 }
827
828 void LightEditorShutdown( void ) {
829         delete g_LightDialog;
830         g_LightDialog = NULL;
831 }
832
833 void UpdateLightInspector() {
834         if ( g_LightDialog && g_LightDialog->GetSafeHwnd() != NULL ) {
835                 g_LightDialog->UpdateDialog(true);   //jhefty - update ALL info about the light, including check boxes
836         }
837 }
838
839 void CLightDlg::OnApply() {
840         UpdateLightInfoFromDialog();
841         SaveLightInfo( NULL );
842         Sys_UpdateWindows( W_ALL );
843 }
844
845 void UpdateLightDialog( float r, float g, float b, float a ) {
846         UpdateRadiantColor( 0.0f, 0.0f, 0.0f, 0.0f );
847         g_LightDialog->UpdateColor( r, g, b, a );
848 }
849
850 void CLightDlg::UpdateColor( float r, float g, float b, float a ) {
851         color[0] = a * r;
852         color[1] = a * g;
853         color[2] = a * b;
854         ColorButtons();
855         UpdateLightInfoFromDialog();
856         SaveLightInfo( NULL );
857         Sys_UpdateWindows( W_CAMERA );
858 }
859
860 void CLightDlg::OnBtnColor() {
861         int r, g, b;
862         float ob;
863         r = color[0];
864         g = color[1];
865         b = color[2];
866         if ( DoNewColor( &r, &g, &b, &ob, UpdateLightDialog ) ) {
867                 color[0] = ob * r;
868                 color[1] = ob * g;
869                 color[2] = ob * b;
870                 ColorButtons();
871         }
872 }
873
874 void CLightDlg::OnCancel() {
875         CDialog::OnCancel();
876 }
877
878 HBRUSH CLightDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
879 {
880         HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
881
882         return hbr;
883 }
884
885 BOOL CLightDlg::DestroyWindow() 
886 {
887         if (GetSafeHwnd())
888         {
889                 CRect rct;
890                 GetWindowRect(rct);
891                 SaveRegistryInfo("Radiant::LightWindow", &rct, sizeof(rct));
892         }
893         return CDialog::DestroyWindow();
894 }
895
896 void CLightDlg::OnSelchangeComboTexture() 
897 {
898         UpdateData(TRUE);
899         int sel = m_wndLights.GetCurSel();
900         CString str;
901         if (sel >= 0) {
902                 m_wndLights.GetLBText(sel, str);
903                 m_drawMaterial->setMedia(str);
904                 if ( com_editorActive ) {
905                         m_wndPreview.RedrawWindow();
906                 }
907         }
908         Sys_UpdateWindows(W_ALL);
909 }
910
911 void CLightDlg::OnCheckCenter() 
912 {
913         if (reinterpret_cast<CButton*>(GetDlgItem(IDC_CHECK_CENTER))->GetCheck()) {
914                 lightInfo.hasCenter = true;
915                 lightInfo.lightCenter.x = 0;
916                 lightInfo.lightCenter.y = 0;
917                 lightInfo.lightCenter.z = 32;
918         } else {
919                 lightInfo.hasCenter = false;
920                 lightInfo.lightCenter.Zero();
921         }
922         UpdateDialogFromLightInfo();
923         SetSpecifics();
924 }
925
926 void CLightDlg::OnCheckParallel() {
927         if ( reinterpret_cast<CButton*>(GetDlgItem(IDC_CHECK_PARALLEL))->GetCheck() ) {
928                 lightInfo.hasCenter = true;
929                 lightInfo.isParallel = true;
930                 lightInfo.lightCenter.x = 0;
931                 lightInfo.lightCenter.y = 0;
932                 lightInfo.lightCenter.z = 32;
933         } else {
934                 lightInfo.isParallel = false;
935                 lightInfo.hasCenter = false;
936         }
937
938         UpdateDialogFromLightInfo();
939         SetSpecifics();
940 }
941
942 //jhefty - only apply settings that are different
943 void CLightDlg::OnApplyDifferences () {
944         idDict differences, modified, original;
945
946         UpdateLightInfoFromDialog();
947
948         lightInfo.ToDict( &modified );
949         lightInfoOriginal.ToDictWriteAllInfo( &original );
950
951         differences = modified;
952
953         // jhefty - compile a set of modified values to apply
954         for ( int i = 0; i < modified.GetNumKeyVals (); i ++ ) {
955                 const idKeyValue* valModified = modified.GetKeyVal ( i );
956                 const idKeyValue* valOriginal = original.FindKey ( valModified->GetKey() );
957
958                 //if it hasn't changed, remove it from the list of values to apply
959                 if ( !valOriginal || ( valModified->GetValue() == valOriginal->GetValue() ) ) {
960                         differences.Delete ( valModified->GetKey() );
961                 }
962         }
963
964         SaveLightInfo( &differences );
965
966         lightInfoOriginal.FromDict( &modified );
967
968         Sys_UpdateWindows( W_ALL );
969 }