LightDlg.cpp 27 KB

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