ShaderEditorDlg.cpp
上传用户:tangyu_668
上传日期:2014-02-27
资源大小:678k
文件大小:10k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. // ShaderEditorDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "mplayerc.h"
  5. #include "PixelShaderCompiler.h"
  6. #include "ShaderEditorDlg.h"
  7. #include "MainFrm.h"
  8. #undef SubclassWindow
  9. // CShaderLabelComboBox
  10. BEGIN_MESSAGE_MAP(CShaderLabelComboBox, CComboBox)
  11. ON_WM_CTLCOLOR()
  12. ON_WM_DESTROY()
  13. END_MESSAGE_MAP()
  14. HBRUSH CShaderLabelComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
  15. {
  16. if(nCtlColor == CTLCOLOR_EDIT)
  17. {
  18. if(m_edit.GetSafeHwnd() == NULL)
  19.             m_edit.SubclassWindow(pWnd->GetSafeHwnd());
  20. }
  21. return __super::OnCtlColor(pDC, pWnd, nCtlColor);
  22. }
  23. void CShaderLabelComboBox::OnDestroy()
  24. {
  25. if(m_edit.GetSafeHwnd() != NULL)
  26. m_edit.UnsubclassWindow();
  27. __super::OnDestroy();
  28. }
  29. // CShaderEdit
  30. CShaderEdit::CShaderEdit()
  31. {
  32. m_acdlg.Create(CShaderAutoCompleteDlg::IDD, NULL);
  33. m_nEndChar = -1;
  34. m_nIDEvent = -1;
  35. }
  36. CShaderEdit::~CShaderEdit()
  37. {
  38. m_acdlg.DestroyWindow();
  39. }
  40. BOOL CShaderEdit::PreTranslateMessage(MSG* pMsg)
  41. {
  42. if(m_acdlg.IsWindowVisible() 
  43. && pMsg->message == WM_KEYDOWN 
  44. && (pMsg->wParam == VK_UP || pMsg->wParam == VK_DOWN
  45. || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT
  46. || pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE))
  47. {
  48. int i = m_acdlg.m_list.GetCurSel();
  49. if(pMsg->wParam == VK_RETURN && i >= 0)
  50. {
  51. CString str;
  52. m_acdlg.m_list.GetText(i, str);
  53. i = str.Find('(')+1;
  54. if(i > 0) str = str.Left(i);
  55. int nStartChar = 0, nEndChar = -1;
  56. GetSel(nStartChar, nEndChar);
  57. CString text;
  58. GetWindowText(text);
  59. while(nStartChar > 0 && _istalnum(text.GetAt(nStartChar-1)))
  60. nStartChar--;
  61. SetSel(nStartChar, nEndChar);
  62. ReplaceSel(str, TRUE);
  63. }
  64. else if(pMsg->wParam == VK_ESCAPE)
  65. {
  66. m_acdlg.ShowWindow(SW_HIDE);
  67. }
  68. else
  69. {
  70. m_acdlg.m_list.SendMessage(pMsg->message, pMsg->wParam, pMsg->lParam);
  71. }
  72. return TRUE;
  73. }
  74. return __super::PreTranslateMessage(pMsg);
  75. }
  76. BEGIN_MESSAGE_MAP(CShaderEdit, CLineNumberEdit)
  77. ON_CONTROL_REFLECT(EN_UPDATE, OnUpdate)
  78. ON_WM_KILLFOCUS()
  79. ON_WM_TIMER()
  80. END_MESSAGE_MAP()
  81. void CShaderEdit::OnUpdate()
  82. {
  83. if(m_nIDEvent == -1)
  84. {
  85. m_nIDEvent = SetTimer(1, 100, NULL); 
  86. }
  87. CString text;
  88. int nStartChar = 0, nEndChar = -1;
  89. GetSel(nStartChar, nEndChar);
  90. if(nStartChar == nEndChar)
  91. {
  92. GetWindowText(text);
  93. while(nStartChar > 0 && _istalnum(text.GetAt(nStartChar-1)))
  94. nStartChar--;
  95. }
  96. if(nStartChar < nEndChar)
  97. {
  98. text = text.Mid(nStartChar, nEndChar - nStartChar);
  99. text.TrimRight('(');
  100. text.MakeLower();
  101. m_acdlg.m_list.ResetContent();
  102. CString key, value;
  103. POSITION pos = m_acdlg.m_inst.GetStartPosition();
  104. while(pos)
  105. {
  106. POSITION cur = pos;
  107. m_acdlg.m_inst.GetNextAssoc(pos, key, value);
  108. if(key.Find(text) == 0)
  109. {
  110. CAtlList<CString> sl;
  111. Explode(value, sl, '|', 2);
  112. if(sl.GetCount() != 2) continue;
  113. CString name = sl.RemoveHead();
  114. CString description = sl.RemoveHead();
  115. int i = m_acdlg.m_list.AddString(name);
  116. m_acdlg.m_list.SetItemDataPtr(i, cur);
  117. }
  118. }
  119. if(m_acdlg.m_list.GetCount() > 0)
  120. {
  121. int lineheight = GetLineHeight();
  122. CPoint p = PosFromChar(nStartChar);
  123. p.y += lineheight;
  124. ClientToScreen(&p);
  125. CRect r(p, CSize(100, 100));
  126. m_acdlg.MoveWindow(r);
  127. m_acdlg.SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
  128. m_acdlg.ShowWindow(SW_SHOWNOACTIVATE);
  129. m_nEndChar = nEndChar;
  130. return;
  131. }
  132. }
  133. m_acdlg.ShowWindow(SW_HIDE);
  134. }
  135. void CShaderEdit::OnKillFocus(CWnd* pNewWnd)
  136. {
  137. CString text;
  138. GetWindowText(text);
  139. __super::OnKillFocus(pNewWnd);
  140. GetWindowText(text);
  141. m_acdlg.ShowWindow(SW_HIDE);
  142. }
  143. void CShaderEdit::OnTimer(UINT nIDEvent)
  144. {
  145. if(m_nIDEvent == nIDEvent)
  146. {
  147. int nStartChar = 0, nEndChar = -1;
  148. GetSel(nStartChar, nEndChar);
  149. if(nStartChar != nEndChar || m_nEndChar != nEndChar)
  150. m_acdlg.ShowWindow(SW_HIDE);
  151. }
  152. __super::OnTimer(nIDEvent);
  153. }
  154. // CShaderEditorDlg dialog
  155. CShaderEditorDlg::CShaderEditorDlg()
  156. : CResizableDialog(CShaderEditorDlg::IDD, NULL)
  157. , m_fSplitterGrabbed(false)
  158. , m_pPSC(NULL)
  159. , m_pShader(NULL)
  160. {
  161. }
  162. CShaderEditorDlg::~CShaderEditorDlg()
  163. {
  164. delete m_pPSC;
  165. }
  166. BOOL CShaderEditorDlg::Create(CWnd* pParent)
  167. {
  168. if(!__super::Create(IDD, pParent))
  169. return FALSE;
  170. AddAnchor(IDC_COMBO1, TOP_LEFT, TOP_RIGHT);
  171. AddAnchor(IDC_COMBO2, TOP_RIGHT);
  172. AddAnchor(IDC_EDIT1, TOP_LEFT, BOTTOM_RIGHT);
  173. AddAnchor(IDC_EDIT2, BOTTOM_LEFT, BOTTOM_RIGHT);
  174. AddAnchor(IDC_BUTTON1, TOP_RIGHT);
  175. m_srcdata.SetTabStops(16);
  176. SetMinTrackSize(CSize(250, 40));
  177. m_targets.AddString(_T("ps_1_1"));
  178. m_targets.AddString(_T("ps_1_2"));
  179. m_targets.AddString(_T("ps_1_3"));
  180. m_targets.AddString(_T("ps_1_4"));
  181. m_targets.AddString(_T("ps_2_0"));
  182. m_targets.AddString(_T("ps_2_a"));
  183. m_targets.AddString(_T("ps_2_sw"));
  184. m_targets.AddString(_T("ps_3_0"));
  185. m_targets.AddString(_T("ps_3_sw"));
  186. POSITION pos = AfxGetAppSettings().m_shaders.GetHeadPosition();
  187. while(pos)
  188. {
  189. const AppSettings::Shader& s = AfxGetAppSettings().m_shaders.GetNext(pos);
  190. m_labels.SetItemDataPtr(m_labels.AddString(s.label), (void*)&s);
  191. }
  192. m_nIDEventShader = SetTimer(1, 1000, NULL);
  193. return TRUE;
  194. }
  195. void CShaderEditorDlg::DoDataExchange(CDataExchange* pDX)
  196. {
  197. __super::DoDataExchange(pDX);
  198. DDX_Control(pDX, IDC_COMBO1, m_labels);
  199. DDX_Control(pDX, IDC_COMBO2, m_targets);
  200. DDX_Control(pDX, IDC_EDIT1, m_srcdata);
  201. DDX_Control(pDX, IDC_EDIT2, m_output);
  202. }
  203. bool CShaderEditorDlg::HitTestSplitter(CPoint p)
  204. {
  205. CRect r, rs, ro;
  206. m_srcdata.GetWindowRect(&rs);
  207. m_output.GetWindowRect(&ro);
  208. ScreenToClient(&rs);
  209. ScreenToClient(&ro);
  210. GetClientRect(&r);
  211. r.left = ro.left;
  212. r.right = ro.right;
  213. r.top = rs.bottom;
  214. r.bottom = ro.top;
  215. return !!r.PtInRect(p);
  216. }
  217. BEGIN_MESSAGE_MAP(CShaderEditorDlg, CResizableDialog)
  218. ON_CBN_SELCHANGE(IDC_COMBO1, OnCbnSelchangeCombo1)
  219. ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton2)
  220. ON_WM_TIMER()
  221. ON_WM_LBUTTONDOWN()
  222. ON_WM_LBUTTONUP()
  223. ON_WM_MOUSEMOVE()
  224. ON_WM_SETCURSOR()
  225. END_MESSAGE_MAP()
  226. // CShaderEditorDlg message handlers
  227. BOOL CShaderEditorDlg::PreTranslateMessage(MSG* pMsg)
  228. {
  229. if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN
  230. && pMsg->hwnd == m_labels.m_edit.GetSafeHwnd())
  231. {
  232. OnCbnSelchangeCombo1();
  233.         
  234. return TRUE;
  235. }
  236. else if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB
  237. && pMsg->hwnd == m_srcdata.GetSafeHwnd())
  238. {
  239. int nStartChar, nEndChar;
  240. m_srcdata.GetSel(nStartChar, nEndChar);
  241. if(nStartChar == nEndChar) m_srcdata.ReplaceSel(_T("t"));
  242. return TRUE;
  243. }
  244. else if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE)
  245. {
  246. return TRUE;
  247. }
  248. return __super::PreTranslateMessage(pMsg);
  249. }
  250. void CShaderEditorDlg::OnCbnSelchangeCombo1()
  251. {
  252. int i = m_labels.GetCurSel();
  253. if(i < 0)
  254. {
  255. CString label;
  256. m_labels.GetWindowText(label);
  257. label.Trim();
  258. if(label.IsEmpty()) return;
  259. CStringA srcdata;
  260. LoadResource(IDF_SHADER_EMPTY, srcdata, _T("FILE"));
  261. AppSettings::Shader s;
  262. s.label = label;
  263. s.target = _T("ps_2_0");
  264. s.srcdata = CString(srcdata);
  265. POSITION pos = AfxGetAppSettings().m_shaders.AddTail(s);
  266. i = m_labels.AddString(s.label);
  267. m_labels.SetCurSel(i);
  268. m_labels.SetItemDataPtr(i, (void*)&AfxGetAppSettings().m_shaders.GetAt(pos));
  269. }
  270. m_pShader = (AppSettings::Shader*)m_labels.GetItemDataPtr(i);
  271. m_targets.SetWindowText(m_pShader->target);
  272. CString srcdata = m_pShader->srcdata;
  273. srcdata.Replace(_T("n"), _T("rn"));
  274. m_srcdata.SetWindowText(srcdata);
  275. ((CMainFrame*)AfxGetMainWnd())->UpdateShaders(m_pShader->label);
  276. }
  277. void CShaderEditorDlg::OnBnClickedButton2()
  278. {
  279. if(!m_pShader) return;
  280. if(IDYES != AfxMessageBox(_T("Are you sure you want to delete this shader?"), MB_YESNO))
  281. return;
  282. AppSettings& s = AfxGetAppSettings();
  283. for(POSITION pos = s.m_shaders.GetHeadPosition(); pos; s.m_shaders.GetNext(pos))
  284. {
  285. if(m_pShader == &s.m_shaders.GetAt(pos))
  286. {
  287. m_pShader = NULL;
  288. s.m_shaders.RemoveAt(pos);
  289. int i = m_labels.GetCurSel();
  290. if(i >= 0) m_labels.DeleteString(i);
  291. m_labels.SetWindowText(_T(""));
  292. m_targets.SetWindowText(_T(""));
  293. m_srcdata.SetWindowText(_T(""));
  294. m_output.SetWindowText(_T(""));
  295. ((CMainFrame*)AfxGetMainWnd())->UpdateShaders(_T(""));
  296. break;
  297. }
  298. }
  299. }
  300. void CShaderEditorDlg::OnTimer(UINT nIDEvent)
  301. {
  302. if(nIDEvent == m_nIDEventShader && IsWindowVisible() && m_pShader)
  303. {
  304. CString srcdata;
  305. m_srcdata.GetWindowText(srcdata);
  306. srcdata.Replace(_T("r"), _T(""));
  307. srcdata.Trim();
  308. CString target;
  309. m_targets.GetWindowText(target);
  310. target.Trim();
  311. if(!srcdata.IsEmpty() && !target.IsEmpty() && (m_pShader->srcdata != srcdata || m_pShader->target != target))
  312. {
  313. KillTimer(m_nIDEventShader);
  314. m_pShader->srcdata = srcdata;
  315. m_pShader->target = target;
  316. if(!m_pPSC) m_pPSC = new CPixelShaderCompiler(NULL);
  317. CString disasm, errmsg;
  318. HRESULT hr = m_pPSC->CompileShader(CStringA(srcdata), "main", CStringA(target), D3DXSHADER_DEBUG, NULL, &disasm, &errmsg); 
  319. if(SUCCEEDED(hr))
  320. {
  321. errmsg = _T("D3DXCompileShader succeededn");
  322. errmsg += _T("n");
  323. errmsg += disasm;
  324. ((CMainFrame*)AfxGetMainWnd())->UpdateShaders(m_pShader->label);
  325. }
  326. errmsg.Replace(_T("n"), _T("rn"));
  327. m_output.SetWindowText(errmsg);
  328. // TODO: autosave
  329. m_nIDEventShader = SetTimer(1, 1000, NULL);
  330. }
  331. }
  332. __super::OnTimer(nIDEvent);
  333. }
  334. void CShaderEditorDlg::OnLButtonDown(UINT nFlags, CPoint point)
  335. {
  336. if(HitTestSplitter(point))
  337. {
  338. m_fSplitterGrabbed = true;
  339. SetCapture();
  340. }
  341. __super::OnLButtonDown(nFlags, point);
  342. }
  343. void CShaderEditorDlg::OnLButtonUp(UINT nFlags, CPoint point)
  344. {
  345. if(m_fSplitterGrabbed)
  346. {
  347. ReleaseCapture();
  348. m_fSplitterGrabbed = false;
  349. }
  350. __super::OnLButtonUp(nFlags, point);
  351. }
  352. void CShaderEditorDlg::OnMouseMove(UINT nFlags, CPoint point)
  353. {
  354. if(m_fSplitterGrabbed)
  355. {
  356. CRect r, rs, ro;
  357. GetClientRect(&r);
  358. m_srcdata.GetWindowRect(&rs);
  359. m_output.GetWindowRect(&ro);
  360. ScreenToClient(&rs);
  361. ScreenToClient(&ro);
  362. int dist = ro.top - rs.bottom;
  363. int avgdist = dist / 2;
  364. rs.bottom = min(max(point.y, rs.top + 40), ro.bottom - 40) - avgdist;
  365. ro.top = rs.bottom + dist;
  366. m_srcdata.MoveWindow(&rs);
  367. m_output.MoveWindow(&ro);
  368. int div = 100 * ((rs.bottom + ro.top) / 2) / (ro.bottom - rs.top);
  369. RemoveAnchor(IDC_EDIT1);
  370. RemoveAnchor(IDC_EDIT2);
  371. AddAnchor(IDC_EDIT1, TOP_LEFT, CSize(100, div)/*BOTTOM_RIGHT*/);
  372. AddAnchor(IDC_EDIT2, CSize(0, div)/*BOTTOM_LEFT*/, BOTTOM_RIGHT);
  373. }
  374. __super::OnMouseMove(nFlags, point);
  375. }
  376. BOOL CShaderEditorDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  377. {
  378. CPoint p;
  379. GetCursorPos(&p);
  380. ScreenToClient(&p);
  381. if(HitTestSplitter(p))
  382. {
  383. ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
  384. return TRUE;
  385. }
  386. return __super::OnSetCursor(pWnd, nHitTest, message);
  387. }