DlgPgPolygon.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. // DlgPgPolygon.cpp : implementation file
  13. //
  14. #include "stdafx.h"
  15. #include "DlgPgPolygon.h"
  16. #ifdef _DEBUG
  17. #undef new
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CDlgPgPolygon property page
  24. IMPLEMENT_DYNCREATE(CDlgPgPolygon, CPropertyPage)
  25. CDlgPgPolygon::CDlgPgPolygon() : CPropertyPage(CDlgPgPolygon::IDD)
  26. {
  27. //{{AFX_DATA_INIT(CDlgPgPolygon)
  28. //}}AFX_DATA_INIT
  29. }
  30. CDlgPgPolygon::~CDlgPgPolygon()
  31. {
  32. }
  33. void CDlgPgPolygon::DoDataExchange(CDataExchange* pDX)
  34. {
  35. if( theApp.m_bDisableDataExchange) return;
  36. CPropertyPage::DoDataExchange(pDX);
  37. // mark that property page has been modified
  38. SetModified( TRUE);
  39. // obtain document
  40. CWorldEditorDoc* pDoc = theApp.GetDocument();
  41. if( pDoc == NULL) return;
  42. // polygon mode must be on
  43. if( pDoc->GetEditingMode() != POLYGON_MODE) return;
  44. // get flags of control activity
  45. BOOL bSelectionExists = pDoc->m_selPolygonSelection.Count() != 0;
  46. // if dialog is recieving data and control window is valid
  47. if( (pDX->m_bSaveAndValidate == FALSE) && IsWindow( m_IsPortal.m_hWnd) )
  48. {
  49. // initialize combo boxes
  50. InitComboBoxes();
  51. // polygon controls exist if polygon selection exists
  52. m_IsPortal.EnableWindow( bSelectionExists);
  53. m_IsOldPortal.EnableWindow( bSelectionExists);
  54. m_IsOccluder.EnableWindow( bSelectionExists);
  55. m_IsPassable.EnableWindow( bSelectionExists);
  56. m_bStairs.EnableWindow( bSelectionExists);
  57. m_bShootThru.EnableWindow( bSelectionExists);
  58. m_IsInvisible.EnableWindow( bSelectionExists);
  59. m_IsDoubleSided.EnableWindow( bSelectionExists);
  60. m_bIsDetail.EnableWindow( bSelectionExists);
  61. m_IsTranslucent.EnableWindow( bSelectionExists);
  62. m_IsTransparent.EnableWindow( bSelectionExists);
  63. m_ComboMirror.EnableWindow( bSelectionExists);
  64. m_ComboFriction.EnableWindow( bSelectionExists);
  65. GetDlgItem( IDC_STATIC_MIRROR)->EnableWindow( bSelectionExists);
  66. GetDlgItem( IDC_STATIC_FRICTION)->EnableWindow( bSelectionExists);
  67. GetDlgItem( IDC_PRETENDER_DISTANCE)->EnableWindow( bSelectionExists);
  68. GetDlgItem( IDC_STATIC_PRETENDER_DISTANCE)->EnableWindow( bSelectionExists);
  69. // if selection exists, calculate tri-state value of attribute intersection
  70. if( bSelectionExists)
  71. {
  72. // get friction, illumination, mirror and effect properties from first polygon
  73. UBYTE ubFirstFriction;
  74. UBYTE ubFirstMirror;
  75. BOOL bSameFriction = TRUE;
  76. BOOL bSameMirror = TRUE;
  77. UWORD uwFirstPretenderDistance;
  78. m_bPretenderDistance = TRUE;
  79. ULONG ulFlagsOn = MAX_ULONG;
  80. ULONG ulFlagsOff = MAX_ULONG;
  81. INDEX iPolygon = 0;
  82. // for each of the selected polygons
  83. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  84. {
  85. ulFlagsOn &= itbpo->bpo_ulFlags;
  86. ulFlagsOff &= ~itbpo->bpo_ulFlags;
  87. if( iPolygon == 0)
  88. {
  89. ubFirstFriction = itbpo->bpo_bppProperties.bpp_ubSurfaceType;
  90. ubFirstMirror = itbpo->bpo_bppProperties.bpp_ubMirrorType;
  91. uwFirstPretenderDistance = itbpo->bpo_bppProperties.bpp_uwPretenderDistance;
  92. }
  93. else
  94. {
  95. if( itbpo->bpo_bppProperties.bpp_ubSurfaceType != ubFirstFriction) bSameFriction = FALSE;
  96. if( itbpo->bpo_bppProperties.bpp_ubMirrorType != ubFirstMirror) bSameMirror = FALSE;
  97. if( itbpo->bpo_bppProperties.bpp_uwPretenderDistance != uwFirstPretenderDistance) m_bPretenderDistance = FALSE;
  98. }
  99. iPolygon++;
  100. }
  101. // apply flags to controls
  102. #define SET_TRI_STATE_TO_CTRL( ctrl, flag)\
  103. if((ulFlagsOn & flag) && !(ulFlagsOff & flag)) ctrl.SetCheck( 1);\
  104. else if(!(ulFlagsOn & flag) && (ulFlagsOff & flag)) ctrl.SetCheck( 0);\
  105. else ctrl.SetCheck( 2);
  106. SET_TRI_STATE_TO_CTRL( m_IsPortal, BPOF_PORTAL);
  107. SET_TRI_STATE_TO_CTRL( m_IsOldPortal, OPOF_PORTAL);
  108. SET_TRI_STATE_TO_CTRL( m_IsOccluder, BPOF_OCCLUDER);
  109. SET_TRI_STATE_TO_CTRL( m_IsPassable, BPOF_PASSABLE);
  110. SET_TRI_STATE_TO_CTRL( m_bStairs, BPOF_STAIRS);
  111. SET_TRI_STATE_TO_CTRL( m_bShootThru, BPOF_SHOOTTHRU);
  112. SET_TRI_STATE_TO_CTRL( m_IsInvisible, BPOF_INVISIBLE);
  113. SET_TRI_STATE_TO_CTRL( m_IsDoubleSided, BPOF_DOUBLESIDED);
  114. SET_TRI_STATE_TO_CTRL( m_bIsDetail, BPOF_DETAILPOLYGON);
  115. SET_TRI_STATE_TO_CTRL( m_IsTranslucent, BPOF_TRANSLUCENT);
  116. SET_TRI_STATE_TO_CTRL( m_IsTransparent, BPOF_TRANSPARENT);
  117. if( bSameFriction) m_ComboFriction.SetCurSel( ubFirstFriction);
  118. else m_ComboFriction.SetCurSel(-1);
  119. if( bSameMirror) m_ComboMirror.SetCurSel( ubFirstMirror);
  120. else m_ComboMirror.SetCurSel(-1);
  121. if( m_bPretenderDistance) m_fPretenderDistance = uwFirstPretenderDistance;
  122. }
  123. // mark that page is updated
  124. m_udPolygonSelection.MarkUpdated();
  125. }
  126. //{{AFX_DATA_MAP(CDlgPgPolygon)
  127. DDX_Control(pDX, IDC_DOUBLESIDED, m_IsDoubleSided);
  128. DDX_Control(pDX, IDC_SHOOTTROUGH, m_bShootThru);
  129. DDX_Control(pDX, IDC_IS_TRANSPARENT, m_IsTransparent);
  130. DDX_Control(pDX, IDC_STAIRS, m_bStairs);
  131. DDX_Control(pDX, IDC_IS_OCCLUDER, m_IsOccluder);
  132. DDX_Control(pDX, IDC_MIRROR_COMBO, m_ComboMirror);
  133. DDX_Control(pDX, IDC_IS_OLD_PORTAL, m_IsOldPortal);
  134. DDX_Control(pDX, IDC_IS_DETAIL, m_bIsDetail);
  135. DDX_Control(pDX, IDC_INVISIBLE, m_IsInvisible);
  136. DDX_Control(pDX, IDC_IS_TRANSLUSCENT, m_IsTranslucent);
  137. DDX_Control(pDX, IDC_IS_PASSABLE, m_IsPassable);
  138. DDX_Control(pDX, IDC_IS_PORTAL, m_IsPortal);
  139. DDX_Control(pDX, IDC_FRICTION_COMBO, m_ComboFriction);
  140. //}}AFX_DATA_MAP
  141. DDX_SkyFloat(pDX, IDC_PRETENDER_DISTANCE, m_fPretenderDistance, m_bPretenderDistance);
  142. // if dialog is giving data
  143. if( pDX->m_bSaveAndValidate != FALSE)
  144. {
  145. BOOL bFindShadowLayers = FALSE;
  146. // calculate bounding box for all polygons
  147. FLOATaabbox3D boxBoundingBoxPolygonSelection;
  148. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  149. {
  150. boxBoundingBoxPolygonSelection |= itbpo->bpo_boxBoundingBox;
  151. if( m_ComboFriction.GetCurSel()!=-1) itbpo->bpo_bppProperties.bpp_ubSurfaceType = m_ComboFriction.GetCurSel();
  152. INDEX iItemMirror = m_ComboMirror.GetCurSel();
  153. if( iItemMirror!=CB_ERR)
  154. {
  155. if( itbpo->bpo_bppProperties.bpp_ubMirrorType != iItemMirror)
  156. {
  157. itbpo->bpo_bppProperties.bpp_ubMirrorType = (UBYTE) iItemMirror;
  158. }
  159. }
  160. // if all polygons have same pretender distance
  161. if( m_bPretenderDistance)
  162. {
  163. itbpo->bpo_bppProperties.bpp_uwPretenderDistance = UWORD (m_fPretenderDistance);
  164. }
  165. // set polygon's flags acording witg given tri-state ctrl
  166. #define TRI_STATE_CTRL_TO_FLAGS( ctrl, flag, bDiscardShd, bFindShdLayers)\
  167. if( (ctrl.GetCheck() == 1) && !(itbpo->bpo_ulFlags & flag) ) {\
  168. itbpo->bpo_ulFlags |= flag;\
  169. if( bDiscardShd) itbpo->DiscardShadows();\
  170. if( bFindShdLayers) bFindShadowLayers = TRUE;\
  171. } else if( (ctrl.GetCheck() == 0) && (itbpo->bpo_ulFlags & flag) ) {\
  172. itbpo->bpo_ulFlags &= ~flag;\
  173. if( bDiscardShd) itbpo->DiscardShadows();\
  174. if( bFindShdLayers) bFindShadowLayers = TRUE;\
  175. }
  176. ULONG ulFlagsBefore = itbpo->bpo_ulFlags;
  177. TRI_STATE_CTRL_TO_FLAGS( m_IsPortal, BPOF_PORTAL, TRUE, TRUE);
  178. TRI_STATE_CTRL_TO_FLAGS( m_IsOccluder, BPOF_OCCLUDER, FALSE, FALSE);
  179. TRI_STATE_CTRL_TO_FLAGS( m_IsOldPortal, OPOF_PORTAL, TRUE, TRUE);
  180. TRI_STATE_CTRL_TO_FLAGS( m_IsPassable, BPOF_PASSABLE, FALSE, FALSE);
  181. TRI_STATE_CTRL_TO_FLAGS( m_bStairs, BPOF_STAIRS, FALSE, FALSE);
  182. TRI_STATE_CTRL_TO_FLAGS( m_bShootThru, BPOF_SHOOTTHRU, FALSE, FALSE);
  183. TRI_STATE_CTRL_TO_FLAGS( m_IsInvisible, BPOF_INVISIBLE, FALSE, FALSE);
  184. TRI_STATE_CTRL_TO_FLAGS( m_IsDoubleSided, BPOF_DOUBLESIDED, FALSE, FALSE);
  185. TRI_STATE_CTRL_TO_FLAGS( m_bIsDetail, BPOF_DETAILPOLYGON, FALSE, FALSE);
  186. TRI_STATE_CTRL_TO_FLAGS( m_IsTranslucent, BPOF_TRANSLUCENT, FALSE, FALSE);
  187. TRI_STATE_CTRL_TO_FLAGS( m_IsTransparent, BPOF_TRANSPARENT, FALSE, FALSE);
  188. ULONG ulFlagsAfter = itbpo->bpo_ulFlags;
  189. // occluder and detail flags can't be on at the same time
  190. BOOL bOccluderSet = ((ulFlagsBefore&BPOF_OCCLUDER)!=(ulFlagsAfter&BPOF_OCCLUDER))&&(ulFlagsAfter&BPOF_OCCLUDER);
  191. BOOL bDetailSet = ((ulFlagsBefore&BPOF_DETAILPOLYGON)!=(ulFlagsAfter&BPOF_DETAILPOLYGON))&&(ulFlagsAfter&BPOF_DETAILPOLYGON);
  192. BOOL bDoubleSidedSet = ((ulFlagsBefore&BPOF_DOUBLESIDED)!=(ulFlagsAfter&BPOF_DOUBLESIDED))&&(ulFlagsAfter&BPOF_DOUBLESIDED);
  193. // if occluder set
  194. if( bOccluderSet)
  195. {
  196. // turn off detail
  197. itbpo->bpo_ulFlags &= ~BPOF_DETAILPOLYGON;
  198. itbpo->bpo_ulFlags |= BPOF_DOESNOTCASTSHADOW;
  199. }
  200. // if doublesided set
  201. if(bDoubleSidedSet)
  202. {
  203. // turn on transparent and detail
  204. itbpo->bpo_ulFlags |= BPOF_TRANSPARENT;
  205. itbpo->bpo_ulFlags |= BPOF_DETAILPOLYGON;
  206. }
  207. // if detail set
  208. if( bDetailSet)
  209. {
  210. // turn off occluder
  211. itbpo->bpo_ulFlags &= ~BPOF_OCCLUDER;
  212. }
  213. }
  214. // if we should find shadow layers
  215. if( bFindShadowLayers)
  216. {
  217. pDoc->m_woWorld.FindShadowLayers( boxBoundingBoxPolygonSelection);
  218. }
  219. // mark that document is changed
  220. theApp.GetDocument()->SetModifiedFlag( TRUE);
  221. // redraw to show changes
  222. pDoc->UpdateAllViews( NULL);
  223. }
  224. }
  225. BEGIN_MESSAGE_MAP(CDlgPgPolygon, CPropertyPage)
  226. //{{AFX_MSG_MAP(CDlgPgPolygon)
  227. ON_CBN_SELCHANGE(IDC_FRICTION_COMBO, OnSelchangeFrictionCombo)
  228. ON_CBN_DROPDOWN(IDC_FRICTION_COMBO, OnDropdownFrictionCombo)
  229. ON_CBN_SELCHANGE(IDC_MIRROR_COMBO, OnSelchangeMirrorCombo)
  230. ON_CBN_DROPDOWN(IDC_MIRROR_COMBO, OnDropdownMirrorCombo)
  231. ON_WM_CONTEXTMENU()
  232. //}}AFX_MSG_MAP
  233. END_MESSAGE_MAP()
  234. /////////////////////////////////////////////////////////////////////////////
  235. // CDlgPgPolygon message handlers
  236. void CDlgPgPolygon::InitComboBoxes(void)
  237. {
  238. CWorldEditorDoc* pDoc = theApp.GetDocument();
  239. CTString strFrictionName;
  240. CTString strMirrorName;
  241. m_ComboFriction.ResetContent();
  242. m_ComboMirror.ResetContent();
  243. // add all available frictions
  244. for(INDEX iFriction=0; iFriction<MAX_UBYTE; iFriction++)
  245. {
  246. strFrictionName = pDoc->m_woWorld.wo_astSurfaceTypes[iFriction].st_strName;
  247. if( strFrictionName == "") break;
  248. INDEX iAddedAs = m_ComboFriction.AddString( CString(strFrictionName));
  249. }
  250. // none must exist
  251. m_ComboMirror.AddString( L"None");
  252. // if there is polygon selection
  253. if( pDoc->m_selPolygonSelection.Count() != 0)
  254. {
  255. // obtain first polygon's brush
  256. CBrush3D *pbrBrush = NULL;
  257. pDoc->m_selPolygonSelection.Lock();
  258. if( !pDoc->m_selPolygonSelection.IsMember( pDoc->m_pbpoLastCentered))
  259. {
  260. pbrBrush = pDoc->m_selPolygonSelection[0].bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush;
  261. }
  262. pDoc->m_selPolygonSelection.Unlock();
  263. BOOL bEnableMirror = TRUE;
  264. // for each of the selected polygons
  265. FOREACHINDYNAMICCONTAINER(pDoc->m_selPolygonSelection, CBrushPolygon, itbpo)
  266. {
  267. // disable mirror combo box if all polygons are not from same brush
  268. if( pbrBrush != itbpo->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush)
  269. {
  270. bEnableMirror = FALSE;
  271. break;
  272. }
  273. }
  274. // if mirror combo is enabled
  275. if( bEnableMirror)
  276. {
  277. // add mirrors
  278. for(INDEX iMirror=1; iMirror<MAX_UBYTE; iMirror++)
  279. {
  280. CTString strMirrorName = pbrBrush->br_penEntity->GetMirrorName( iMirror);
  281. if( strMirrorName == "") break;
  282. m_ComboMirror.AddString( CString(strMirrorName));
  283. }
  284. }
  285. }
  286. }
  287. BOOL CDlgPgPolygon::OnIdle(LONG lCount)
  288. {
  289. CWorldEditorDoc* pDoc = theApp.GetDocument();
  290. if( (pDoc == NULL) || !IsWindow(m_hWnd) )
  291. {
  292. return TRUE;
  293. }
  294. // if selections have been changed (they are not up to date)
  295. if( !pDoc->m_chSelections.IsUpToDate( m_udPolygonSelection) )
  296. {
  297. // update dialog data
  298. UpdateData( FALSE);
  299. }
  300. return TRUE;
  301. }
  302. BOOL CDlgPgPolygon::PreTranslateMessage(MSG* pMsg)
  303. {
  304. if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN)
  305. {
  306. // move data from page to polygon
  307. UpdateData( TRUE);
  308. // the message is handled
  309. return TRUE;
  310. }
  311. return CPropertyPage::PreTranslateMessage(pMsg);
  312. }
  313. BOOL CDlgPgPolygon::OnInitDialog()
  314. {
  315. CPropertyPage::OnInitDialog();
  316. if( IsWindow( m_ComboFriction.m_hWnd))
  317. {
  318. InitComboBoxes();
  319. }
  320. m_bIsDetail.SetDialogPtr( this);
  321. m_IsInvisible.SetDialogPtr( this);
  322. m_IsDoubleSided.SetDialogPtr( this);
  323. m_IsTranslucent.SetDialogPtr( this);
  324. m_IsTransparent.SetDialogPtr( this);
  325. m_IsPassable.SetDialogPtr( this);
  326. m_bStairs.SetDialogPtr( this);
  327. m_bShootThru.SetDialogPtr( this);
  328. m_IsPortal.SetDialogPtr( this);
  329. m_IsOldPortal.SetDialogPtr( this);
  330. m_IsOccluder.SetDialogPtr( this);
  331. return TRUE;
  332. }
  333. void CDlgPgPolygon::OnSelchangeFrictionCombo()
  334. {
  335. UpdateData( TRUE);
  336. }
  337. void CDlgPgPolygon::OnDropdownFrictionCombo()
  338. {
  339. m_ComboFriction.SetDroppedWidth( 256);
  340. }
  341. void CDlgPgPolygon::OnSelchangeMirrorCombo()
  342. {
  343. UpdateData( TRUE);
  344. }
  345. void CDlgPgPolygon::OnDropdownMirrorCombo()
  346. {
  347. m_ComboMirror.SetDroppedWidth( 256);
  348. }
  349. void CDlgPgPolygon::OnContextMenu(CWnd* pWnd, CPoint point)
  350. {
  351. CWorldEditorDoc* pDoc = theApp.GetActiveDocument();
  352. CMenu menu;
  353. if( pDoc->GetEditingMode() == POLYGON_MODE)
  354. {
  355. if( menu.LoadMenu(IDR_INFO_POLYGON_POPUP))
  356. {
  357. CMenu* pPopup = menu.GetSubMenu(0);
  358. if( pDoc->m_selPolygonSelection.Count() != 1)
  359. {
  360. menu.EnableMenuItem(ID_SET_AS_DEFAULT, MF_DISABLED|MF_GRAYED);
  361. }
  362. pPopup->TrackPopupMenu(TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_LEFTALIGN,
  363. point.x, point.y, this);
  364. }
  365. }
  366. }