00001
00002
00003
00004 #include "stdafx.h"
00005 #include "mplayerc.h"
00006 #include "PixelShaderCompiler.h"
00007 #include "ShaderEditorDlg.h"
00008
00009 #undef SubclassWindow
00010
00011
00012
00013
00014 BEGIN_MESSAGE_MAP(CShaderLabelComboBox, CComboBox)
00015 ON_WM_CTLCOLOR()
00016 ON_WM_DESTROY()
00017 END_MESSAGE_MAP()
00018
00019 HBRUSH CShaderLabelComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
00020 {
00021 if(nCtlColor == CTLCOLOR_EDIT)
00022 {
00023 if(m_edit.GetSafeHwnd() == NULL)
00024 m_edit.SubclassWindow(pWnd->GetSafeHwnd());
00025 }
00026
00027 return __super::OnCtlColor(pDC, pWnd, nCtlColor);
00028 }
00029
00030 void CShaderLabelComboBox::OnDestroy()
00031 {
00032 if(m_edit.GetSafeHwnd() != NULL)
00033 m_edit.UnsubclassWindow();
00034
00035 __super::OnDestroy();
00036 }
00037
00038
00039
00040 CShaderEdit::CShaderEdit()
00041 {
00042 m_acdlg.Create(CShaderAutoCompleteDlg::IDD, NULL);
00043
00044 m_nEndChar = -1;
00045 m_nIDEvent = -1;
00046 }
00047
00048 CShaderEdit::~CShaderEdit()
00049 {
00050 m_acdlg.DestroyWindow();
00051 }
00052
00053 BOOL CShaderEdit::PreTranslateMessage(MSG* pMsg)
00054 {
00055 if(m_acdlg.IsWindowVisible()
00056 && pMsg->message == WM_KEYDOWN
00057 && (pMsg->wParam == VK_UP || pMsg->wParam == VK_DOWN
00058 || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT
00059 || pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE))
00060 {
00061 int i = m_acdlg.m_list.GetCurSel();
00062
00063 if(pMsg->wParam == VK_RETURN && i >= 0)
00064 {
00065 CString str;
00066 m_acdlg.m_list.GetText(i, str);
00067 i = str.Find('(')+1;
00068 if(i > 0) str = str.Left(i);
00069
00070 int nStartChar = 0, nEndChar = -1;
00071 GetSel(nStartChar, nEndChar);
00072
00073 CString text;
00074 GetWindowText(text);
00075 while(nStartChar > 0 && _istalnum(text.GetAt(nStartChar-1)))
00076 nStartChar--;
00077
00078 SetSel(nStartChar, nEndChar);
00079 ReplaceSel(str, TRUE);
00080 }
00081 else if(pMsg->wParam == VK_ESCAPE)
00082 {
00083 m_acdlg.ShowWindow(SW_HIDE);
00084 }
00085 else
00086 {
00087 m_acdlg.m_list.SendMessage(pMsg->message, pMsg->wParam, pMsg->lParam);
00088 }
00089
00090 return TRUE;
00091 }
00092
00093 return __super::PreTranslateMessage(pMsg);
00094 }
00095
00096 BEGIN_MESSAGE_MAP(CShaderEdit, CLineNumberEdit)
00097 ON_CONTROL_REFLECT(EN_UPDATE, OnUpdate)
00098 ON_WM_KILLFOCUS()
00099 ON_WM_TIMER()
00100 END_MESSAGE_MAP()
00101
00102 void CShaderEdit::OnUpdate()
00103 {
00104 if(m_nIDEvent == -1)
00105 {
00106 m_nIDEvent = SetTimer(1, 100, NULL);
00107 }
00108
00109 CString text;
00110 int nStartChar = 0, nEndChar = -1;
00111 GetSel(nStartChar, nEndChar);
00112
00113 if(nStartChar == nEndChar)
00114 {
00115 GetWindowText(text);
00116 while(nStartChar > 0 && _istalnum(text.GetAt(nStartChar-1)))
00117 nStartChar--;
00118 }
00119
00120 if(nStartChar < nEndChar)
00121 {
00122 text = text.Mid(nStartChar, nEndChar - nStartChar);
00123 text.TrimRight('(');
00124 text.MakeLower();
00125
00126 m_acdlg.m_list.ResetContent();
00127
00128 CString key, value;
00129 POSITION pos = m_acdlg.m_inst.GetStartPosition();
00130 while(pos)
00131 {
00132 POSITION cur = pos;
00133 m_acdlg.m_inst.GetNextAssoc(pos, key, value);
00134
00135 if(key.Find(text) == 0)
00136 {
00137 CList<CString> sl;
00138 Explode(value, sl, '|', 2);
00139 if(sl.GetCount() != 2) continue;
00140 CString name = sl.RemoveHead();
00141 CString description = sl.RemoveHead();
00142 int i = m_acdlg.m_list.AddString(name);
00143 m_acdlg.m_list.SetItemDataPtr(i, cur);
00144 }
00145 }
00146
00147 if(m_acdlg.m_list.GetCount() > 0)
00148 {
00149 int lineheight = GetLineHeight();
00150
00151 CPoint p = PosFromChar(nStartChar);
00152 p.y += lineheight;
00153 ClientToScreen(&p);
00154 CRect r(p, CSize(100, 100));
00155
00156 m_acdlg.MoveWindow(r);
00157 m_acdlg.SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
00158 m_acdlg.ShowWindow(SW_SHOWNOACTIVATE);
00159
00160 m_nEndChar = nEndChar;
00161
00162 return;
00163 }
00164 }
00165
00166 m_acdlg.ShowWindow(SW_HIDE);
00167 }
00168
00169 void CShaderEdit::OnKillFocus(CWnd* pNewWnd)
00170 {
00171 CString text;
00172 GetWindowText(text);
00173 __super::OnKillFocus(pNewWnd);
00174 GetWindowText(text);
00175
00176 m_acdlg.ShowWindow(SW_HIDE);
00177 }
00178
00179 void CShaderEdit::OnTimer(UINT nIDEvent)
00180 {
00181 if(m_nIDEvent == nIDEvent)
00182 {
00183 int nStartChar = 0, nEndChar = -1;
00184 GetSel(nStartChar, nEndChar);
00185 if(nStartChar != nEndChar || m_nEndChar != nEndChar)
00186 m_acdlg.ShowWindow(SW_HIDE);
00187 }
00188
00189 __super::OnTimer(nIDEvent);
00190 }
00191
00192
00193
00194 CShaderEditorDlg::CShaderEditorDlg(CString label, ISubPicAllocatorPresenter* pCAP, CWnd* pParent )
00195 : CResizableDialog(CShaderEditorDlg::IDD, pParent)
00196 , m_label(label)
00197 , m_pCAP(pCAP)
00198 , m_fSplitterGrabbed(false)
00199 {
00200 m_pPSC = new CPixelShaderCompiler(NULL);
00201 }
00202
00203 CShaderEditorDlg::~CShaderEditorDlg()
00204 {
00205 delete m_pPSC;
00206 }
00207
00208 void CShaderEditorDlg::DoDataExchange(CDataExchange* pDX)
00209 {
00210 __super::DoDataExchange(pDX);
00211 DDX_Control(pDX, IDC_COMBO1, m_labels);
00212 DDX_Control(pDX, IDC_COMBO2, m_targets);
00213 DDX_Control(pDX, IDC_EDIT1, m_srcdata);
00214 DDX_Control(pDX, IDC_EDIT2, m_output);
00215 }
00216
00217 bool CShaderEditorDlg::HitTestSplitter(CPoint p)
00218 {
00219 CRect r, rs, ro;
00220 m_srcdata.GetWindowRect(&rs);
00221 m_output.GetWindowRect(&ro);
00222 ScreenToClient(&rs);
00223 ScreenToClient(&ro);
00224 GetClientRect(&r);
00225 r.left = ro.left;
00226 r.right = ro.right;
00227 r.top = rs.bottom;
00228 r.bottom = ro.top;
00229 return !!r.PtInRect(p);
00230 }
00231
00232 BEGIN_MESSAGE_MAP(CShaderEditorDlg, CResizableDialog)
00233 ON_CBN_SELCHANGE(IDC_COMBO1, OnCbnSelchangeCombo1)
00234 ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
00235 ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2)
00236 ON_WM_TIMER()
00237 ON_WM_CLOSE()
00238 ON_WM_LBUTTONDOWN()
00239 ON_WM_LBUTTONUP()
00240 ON_WM_MOUSEMOVE()
00241 ON_WM_SETCURSOR()
00242 END_MESSAGE_MAP()
00243
00244
00245
00246
00247 BOOL CShaderEditorDlg::OnInitDialog()
00248 {
00249 __super::OnInitDialog();
00250
00251 AddAnchor(IDC_COMBO1, TOP_LEFT, TOP_RIGHT);
00252 AddAnchor(IDC_COMBO2, TOP_RIGHT);
00253 AddAnchor(IDC_BUTTON1, TOP_RIGHT);
00254 AddAnchor(IDC_BUTTON2, TOP_RIGHT);
00255 AddAnchor(IDC_EDIT1, TOP_LEFT, BOTTOM_RIGHT);
00256 AddAnchor(IDC_EDIT2, BOTTOM_LEFT, BOTTOM_RIGHT);
00257
00258 m_srcdata.SetTabStops(16);
00259
00260 CRect r;
00261 GetWindowRect(r);
00262 CSize s = r.Size();
00263 s.cx = 400;
00264 s.cy = 150;
00265 SetMinTrackSize(s);
00266
00267 CMap<CString, LPCTSTR, bool, bool> targetmap;
00268 targetmap[_T("ps_1_1")] = true;
00269 targetmap[_T("ps_1_2")] = true;
00270 targetmap[_T("ps_1_3")] = true;
00271 targetmap[_T("ps_1_4")] = true;
00272 targetmap[_T("ps_2_0")] = true;
00273 targetmap[_T("ps_2_a")] = true;
00274 targetmap[_T("ps_2_sw")] = true;
00275 targetmap[_T("ps_3_0")] = true;
00276 targetmap[_T("ps_3_sw")] = true;
00277
00278 int nSelIndex = -1;
00279
00280 for(int i = 0; ; i++)
00281 {
00282 CString str;
00283 str.Format(_T("%d"), i);
00284 str = AfxGetApp()->GetProfileString(_T("Shaders"), str);
00285
00286 CList<CString> sl;
00287 Explode(str, sl, '|', 3);
00288 if(sl.GetCount() != 3) break;
00289
00290 CString label = sl.RemoveHead();
00291 CString target = sl.RemoveHead();
00292 CString srcdata = sl.RemoveHead();
00293 srcdata.Replace(_T("\\n"), _T("\r\n"));
00294 srcdata.Replace(_T("\\t"), _T("\t"));
00295
00296 targetmap[target] = false;
00297
00298 shader_t s = {target, srcdata};
00299 m_shaders[label] = s;
00300
00301 int nIndex = m_labels.AddString(label);
00302
00303 if(m_label == label)
00304 nSelIndex = nIndex;
00305 }
00306
00307 m_labels.SetCurSel(nSelIndex);
00308
00309 POSITION pos = targetmap.GetStartPosition();
00310 while(pos)
00311 {
00312 CString target;
00313 bool b;
00314 targetmap.GetNextAssoc(pos, target, b);
00315 m_targets.AddString(target);
00316 }
00317
00318 OnCbnSelchangeCombo1();
00319
00320 m_nIDEventShader = SetTimer(1, 1000, NULL);
00321
00322 return TRUE;
00323
00324 }
00325
00326 BOOL CShaderEditorDlg::PreTranslateMessage(MSG* pMsg)
00327 {
00328 if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN
00329 && pMsg->hwnd == m_labels.m_edit.GetSafeHwnd())
00330 {
00331 CString label;
00332 m_labels.GetWindowText(label);
00333
00334 shader_t s;
00335 m_labels.SetCurSel(!m_shaders.Lookup(label, s)
00336 ? m_labels.AddString(label)
00337 : m_labels.FindStringExact(0, label));
00338
00339 OnCbnSelchangeCombo1();
00340
00341 return TRUE;
00342 }
00343 else if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB
00344 && pMsg->hwnd == m_srcdata.GetSafeHwnd())
00345 {
00346 int nStartChar, nEndChar;
00347 m_srcdata.GetSel(nStartChar, nEndChar);
00348
00349 if(nStartChar == nEndChar)
00350 m_srcdata.ReplaceSel(_T("\t"));
00351
00352 return TRUE;
00353 }
00354 else if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE)
00355 {
00356 return TRUE;
00357 }
00358
00359 return __super::PreTranslateMessage(pMsg);
00360 }
00361
00362 void CShaderEditorDlg::OnCbnSelchangeCombo1()
00363 {
00364 int i = m_labels.GetCurSel();
00365 if(i < 0) return;
00366 CString label;
00367 m_labels.GetLBText(i, label);
00368 if(label.IsEmpty()) return;
00369
00370 shader_t s;
00371
00372 if(!m_shaders.Lookup(label, s))
00373 {
00374 s.target = _T("ps_2_0");
00375 s.srcdata =
00376 "sampler s0 : register(s0);\r\n"
00377 "float4 p0 : register(c0);\r\n"
00378 "\r\n"
00379 "#define width (p0[0])\r\n"
00380 "#define height (p0[1])\r\n"
00381 "#define counter (p0[2])\r\n"
00382 "#define clock (p0[3])\r\n"
00383 "\r\n"
00384 "float4 main(float2 tex : TEXCOORD0) : COLOR\r\n"
00385 "{\r\n"
00386 "\tfloat4 c0 = tex2D(s0, tex);\r\n"
00387 "\t// TODO\r\n"
00388 "\treturn c0;\r\n"
00389 "}\r\n";
00390 m_shaders[label] = s;
00391 }
00392
00393 if(m_shaders.Lookup(label, s))
00394 {
00395 m_targets.SetWindowText(s.target);
00396 m_srcdata.SetWindowText(s.srcdata);
00397 }
00398 }
00399
00400 void CShaderEditorDlg::OnBnClickedButton1()
00401 {
00402 CString label;
00403 m_labels.GetWindowText(label);
00404 int nIndex = m_labels.FindStringExact(0, label);
00405 if(nIndex >= 0) m_labels.DeleteString(nIndex);
00406 m_labels.SetWindowText(_T(""));
00407 m_targets.SetWindowText(_T(""));
00408 m_srcdata.SetWindowText(_T(""));
00409 m_shaders.RemoveKey(label);
00410 }
00411
00412 void CShaderEditorDlg::OnBnClickedButton2()
00413 {
00414 CString label;
00415 m_labels.GetWindowText(label);
00416 m_targets.GetWindowText(m_shaders[label].target);
00417 m_srcdata.GetWindowText(m_shaders[label].srcdata);
00418 if(m_labels.FindStringExact(0, label) < 0)
00419 m_labels.SetCurSel(m_labels.AddString(label));
00420 }
00421
00422 void CShaderEditorDlg::OnTimer(UINT nIDEvent)
00423 {
00424 if(nIDEvent == m_nIDEventShader)
00425 {
00426 static CString s_srcdata, s_target;
00427
00428 CString srcdata;
00429 m_srcdata.GetWindowText(srcdata);
00430 srcdata.Trim();
00431
00432 CString target;
00433 m_targets.GetWindowText(target);
00434 target.Trim();
00435
00436 if(!srcdata.IsEmpty() && !target.IsEmpty() && (s_srcdata != srcdata || s_target != target))
00437 {
00438 CString disasm, errmsg(_T("Unknown Error"));
00439
00440 HRESULT hr = m_pPSC->CompileShader(CStringA(srcdata), "main", CStringA(target), D3DXSHADER_DEBUG, NULL, &disasm, &errmsg);
00441
00442 if(SUCCEEDED(hr))
00443 {
00444 errmsg = _T("D3DXCompileShader succeeded\n");
00445 if(m_pCAP && FAILED(m_pCAP->SetPixelShader(CStringA(srcdata), CStringA(target))))
00446 errmsg += _T("SetPixelShader failed\n");
00447 errmsg += _T("\n");
00448 errmsg += disasm;
00449 }
00450
00451 errmsg.Replace(_T("\n"), _T("\r\n"));
00452
00453 m_output.SetWindowText(errmsg);
00454 }
00455
00456 s_srcdata = srcdata;
00457 s_target = target;
00458 }
00459
00460 __super::OnTimer(nIDEvent);
00461 }
00462
00463 void CShaderEditorDlg::OnClose()
00464 {
00465 if(IDYES == AfxMessageBox(_T("Save changes?"), MB_YESNO))
00466 {
00467 OnBnClickedButton2();
00468
00469 CWinApp* pApp = AfxGetApp();
00470
00471 pApp->WriteProfileString(_T("Shaders"), NULL, NULL);
00472 pApp->WriteProfileInt(_T("Shaders"), _T("Initialized"), 1);
00473
00474 for(int i = 0, id = 0; i < m_labels.GetCount(); i++)
00475 {
00476 CString label;
00477 m_labels.GetLBText(i, label);
00478
00479 shader_t s;
00480 if(!label.IsEmpty() && m_shaders.Lookup(label, s))
00481 {
00482 CString str;
00483 str.Format(_T("%d"), id++);
00484 s.srcdata.Replace(_T("\r"), _T(""));
00485 s.srcdata.Replace(_T("\n"), _T("\\n"));
00486 s.srcdata.Replace(_T("\t"), _T("\\t"));
00487 AfxGetApp()->WriteProfileString(_T("Shaders"), str, label + _T("|") + s.target + _T("|") + s.srcdata);
00488 }
00489 }
00490 }
00491
00492 __super::OnClose();
00493 }
00494
00495 void CShaderEditorDlg::OnLButtonDown(UINT nFlags, CPoint point)
00496 {
00497 if(HitTestSplitter(point))
00498 {
00499 m_fSplitterGrabbed = true;
00500 SetCapture();
00501 }
00502
00503 __super::OnLButtonDown(nFlags, point);
00504 }
00505
00506 void CShaderEditorDlg::OnLButtonUp(UINT nFlags, CPoint point)
00507 {
00508 if(m_fSplitterGrabbed)
00509 {
00510 ReleaseCapture();
00511 m_fSplitterGrabbed = false;
00512 }
00513
00514 __super::OnLButtonUp(nFlags, point);
00515 }
00516
00517 void CShaderEditorDlg::OnMouseMove(UINT nFlags, CPoint point)
00518 {
00519 if(m_fSplitterGrabbed)
00520 {
00521 CRect r, rs, ro;
00522 GetClientRect(&r);
00523 m_srcdata.GetWindowRect(&rs);
00524 m_output.GetWindowRect(&ro);
00525 ScreenToClient(&rs);
00526 ScreenToClient(&ro);
00527
00528 int dist = ro.top - rs.bottom;
00529 int avgdist = dist / 2;
00530
00531 rs.bottom = min(max(point.y, rs.top + 40), ro.bottom - 40) - avgdist;
00532 ro.top = rs.bottom + dist;
00533 m_srcdata.MoveWindow(&rs);
00534 m_output.MoveWindow(&ro);
00535
00536 int div = 100 * ((rs.bottom + ro.top) / 2) / (ro.bottom - rs.top);
00537
00538 RemoveAnchor(IDC_EDIT1);
00539 RemoveAnchor(IDC_EDIT2);
00540 AddAnchor(IDC_EDIT1, TOP_LEFT, CSize(100, div));
00541 AddAnchor(IDC_EDIT2, CSize(0, div), BOTTOM_RIGHT);
00542 }
00543
00544 __super::OnMouseMove(nFlags, point);
00545 }
00546
00547 BOOL CShaderEditorDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
00548 {
00549 CPoint p;
00550 GetCursorPos(&p);
00551 ScreenToClient(&p);
00552 if(HitTestSplitter(p))
00553 {
00554 ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
00555 return TRUE;
00556 }
00557
00558 return __super::OnSetCursor(pWnd, nHitTest, message);
00559 }
00560