1
0

menu.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. /*
  2. LICENSE
  3. -------
  4. Copyright 2005-2013 Nullsoft, Inc.
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without modification,
  7. are permitted provided that the following conditions are met:
  8. * Redistributions of source code must retain the above copyright notice,
  9. this list of conditions and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above copyright notice,
  11. this list of conditions and the following disclaimer in the documentation
  12. and/or other materials provided with the distribution.
  13. * Neither the name of Nullsoft nor the names of its contributors may be used to
  14. endorse or promote products derived from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  16. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  21. IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  22. OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "api__vis_milk2.h"
  25. #include "state.h" // for CBlendableFloat - fix this
  26. #include "menu.h"
  27. #include "plugin.h"
  28. #include <stdio.h>
  29. #include <math.h>
  30. #include <assert.h>
  31. #include "resource.h"
  32. extern CPlugin g_plugin; // declared in main.cpp
  33. //----------------------------------------
  34. CMilkMenuItem::CMilkMenuItem()
  35. {
  36. WASABI_API_LNGSTRINGW_BUF(IDS_UNTITLED_MENU_ITEM,m_szName,64);
  37. m_szToolTip[0] = 0;
  38. m_type = MENUITEMTYPE_BUNK;
  39. m_fMin = 0.0f;
  40. m_fMax = 0.0f;
  41. m_var_offset = NULL;
  42. m_pCallbackFn = NULL;
  43. m_pNext = NULL;
  44. m_original_value = NULL;
  45. m_nLastCursorPos = 0;
  46. m_bEnabled = true;
  47. }
  48. CMilkMenuItem::~CMilkMenuItem()
  49. {
  50. if (m_pNext)
  51. {
  52. delete m_pNext;
  53. m_pNext = NULL;
  54. }
  55. }
  56. //----------------------------------------
  57. CMilkMenu::CMilkMenu()
  58. {
  59. //Reset();
  60. }
  61. CMilkMenu::~CMilkMenu()
  62. {
  63. /*
  64. if (m_pFirstChildItem)
  65. {
  66. delete m_pFirstChildItem;
  67. m_pFirstChildItem = NULL;
  68. }
  69. */
  70. }
  71. //----------------------------------------
  72. bool CMilkMenu::ItemIsEnabled(int j)
  73. {
  74. if (j < m_nChildMenus)
  75. return m_ppChildMenu[j]->IsEnabled();
  76. int i = m_nChildMenus;
  77. CMilkMenuItem *pChild = m_pFirstChildItem;
  78. while (pChild && i<j)
  79. {
  80. pChild = pChild->m_pNext;
  81. i++;
  82. }
  83. if (pChild)
  84. return pChild->m_bEnabled;
  85. return false;
  86. }
  87. //----------------------------------------
  88. void CMilkMenu::EnableItem(wchar_t* szName, bool bEnable)
  89. {
  90. //search submenus
  91. int i = 0;
  92. for (i=0; i<m_nChildMenus; i++) {
  93. if (!wcscmp(m_ppChildMenu[i]->GetName(), szName))
  94. {
  95. m_ppChildMenu[i]->Enable(bEnable);
  96. if (!bEnable)
  97. {
  98. while (m_nCurSel > 0 && !ItemIsEnabled(m_nCurSel))
  99. m_nCurSel--;
  100. if (m_nCurSel==0 && !ItemIsEnabled(m_nCurSel))
  101. while (m_nCurSel < m_nChildMenus+m_nChildItems-1 && !ItemIsEnabled(m_nCurSel))
  102. m_nCurSel++;
  103. }
  104. return;
  105. }
  106. }
  107. //search child items
  108. CMilkMenuItem *pChild = m_pFirstChildItem;
  109. while (pChild)
  110. {
  111. if (!wcscmp(pChild->m_szName, szName))
  112. {
  113. pChild->m_bEnabled = bEnable;
  114. if (!bEnable)
  115. {
  116. while (m_nCurSel > 0 && !ItemIsEnabled(m_nCurSel))
  117. m_nCurSel--;
  118. if (m_nCurSel==0 && !ItemIsEnabled(m_nCurSel))
  119. while (m_nCurSel < m_nChildMenus+m_nChildItems-1 && !ItemIsEnabled(m_nCurSel))
  120. m_nCurSel++;
  121. }
  122. return;
  123. }
  124. pChild = pChild->m_pNext;
  125. i++;
  126. }
  127. }
  128. //----------------------------------------
  129. void CMilkMenu::Reset()
  130. {
  131. m_pParentMenu = NULL;
  132. for (int i=0; i<MAX_CHILD_MENUS; i++)
  133. m_ppChildMenu[i] = NULL;
  134. m_pFirstChildItem = NULL;
  135. WASABI_API_LNGSTRINGW_BUF(IDS_UNTITLED_MENU,m_szMenuName,64);
  136. m_nChildMenus = 0;
  137. m_nChildItems = 0;
  138. m_nCurSel = 0;
  139. m_bEditingCurSel = false;
  140. m_bEnabled = true;
  141. }
  142. //----------------------------------------
  143. void CMilkMenu::Init(wchar_t *szName)
  144. {
  145. Reset();
  146. if (szName && szName[0])
  147. wcsncpy(m_szMenuName, szName, 64);
  148. }
  149. void CMilkMenu::Finish()
  150. {
  151. if (m_pFirstChildItem)
  152. {
  153. delete m_pFirstChildItem;
  154. m_pFirstChildItem = NULL;
  155. }
  156. }
  157. //----------------------------------------
  158. void CMilkMenu::AddChildMenu(CMilkMenu *pMenu)
  159. {
  160. if (m_nChildMenus < MAX_CHILD_MENUS)
  161. {
  162. m_ppChildMenu[m_nChildMenus++] = pMenu;
  163. pMenu->SetParentPointer(this);
  164. }
  165. }
  166. //----------------------------------------
  167. void CMilkMenu::AddItem(wchar_t *szName, void *var, MENUITEMTYPE type, wchar_t *szToolTip,
  168. float min, float max, MilkMenuCallbackFnPtr pCallback,
  169. unsigned int wParam, unsigned int lParam)
  170. {
  171. CMilkMenuItem *pLastItem = NULL;
  172. // find last item in linked list
  173. if (!m_pFirstChildItem)
  174. {
  175. // first item
  176. m_pFirstChildItem = new CMilkMenuItem;
  177. pLastItem = m_pFirstChildItem;
  178. }
  179. else
  180. {
  181. pLastItem = m_pFirstChildItem;
  182. while (pLastItem->m_pNext)
  183. pLastItem = pLastItem->m_pNext;
  184. // allocate a new CMilkMenuItem
  185. pLastItem->m_pNext = new CMilkMenuItem;
  186. pLastItem = pLastItem->m_pNext;
  187. }
  188. // set its attributes
  189. wcsncpy(pLastItem->m_szName, szName, 64);
  190. wcsncpy(pLastItem->m_szToolTip, szToolTip, 1024);
  191. pLastItem->m_var_offset = (size_t)var - (size_t)(g_plugin.m_pState);
  192. pLastItem->m_type = type;
  193. pLastItem->m_fMin = min;
  194. pLastItem->m_fMax = max;
  195. pLastItem->m_wParam = wParam;
  196. pLastItem->m_lParam = lParam;
  197. if ((type==MENUITEMTYPE_LOGBLENDABLE || type==MENUITEMTYPE_LOGFLOAT) && min==max)
  198. {
  199. // special defaults
  200. pLastItem->m_fMin = 0.01f;
  201. pLastItem->m_fMax = 100.0f;
  202. }
  203. pLastItem->m_pCallbackFn = pCallback;
  204. m_nChildItems++;
  205. }
  206. //----------------------------------------
  207. void MyMenuTextOut(eFontIndex font_index, wchar_t* str, DWORD color, RECT* pRect, int bCalcRect, RECT* pCalcRect)
  208. {
  209. if (bCalcRect)
  210. {
  211. RECT t = *pRect;
  212. pRect->top += g_plugin.m_text.DrawTextW(g_plugin.GetFont(font_index), str, -1, &t, DT_SINGLELINE | DT_END_ELLIPSIS | DT_CALCRECT, 0xFFFFFFFF, false);
  213. pCalcRect->bottom += t.bottom - t.top;
  214. //if (pCalcRect->bottom > pRect->bottom)
  215. // pCalcRect->bottom = pRect->bottom;
  216. pCalcRect->right = max(pCalcRect->right, pCalcRect->left + t.right - t.left);
  217. }
  218. else
  219. {
  220. pRect->top += g_plugin.m_text.DrawTextW(g_plugin.GetFont(font_index), str, -1, pRect, DT_SINGLELINE | DT_END_ELLIPSIS, color, false);
  221. }
  222. }
  223. void CMilkMenu::DrawMenu(RECT rect, int xR, int yB, int bCalcRect, RECT* pCalcRect)
  224. {
  225. // 'rect' is the bounding rectangle in which we're allowed to draw the menu;
  226. // it's .top member is incremented as we draw downward.
  227. // if bCalcRect==1, then we return pCalcRect as the area that the menu actually
  228. // occupies, excluding any tooltips.
  229. if (bCalcRect!=0 && pCalcRect==NULL)
  230. return;
  231. if (bCalcRect)
  232. {
  233. pCalcRect->left = rect.left;
  234. pCalcRect->right = rect.left;
  235. pCalcRect->top = rect.top;
  236. pCalcRect->bottom = rect.top;
  237. }
  238. if (!m_bEditingCurSel)
  239. {
  240. int nLines = (rect.bottom - rect.top - PLAYLIST_INNER_MARGIN*2) / g_plugin.GetFontHeight(SIMPLE_FONT) - 1; // save 1 line for the tooltip
  241. if (nLines<1) return;
  242. int nStart = (m_nCurSel/nLines)*nLines;
  243. int nLinesDrawn = 0;
  244. int i = 0;
  245. for (i=0; i < m_nChildMenus; i++)
  246. {
  247. if (i >= nStart && i < nStart+nLines)
  248. {
  249. //rect.top += g_plugin.GetFont(SIMPLE_FONT)->DrawText(m_ppChildMenu[i]->m_szMenuName, -1, pRect, DT_SINGLELINE | DT_END_ELLIPSIS, (i == m_nCurSel) ? MENU_HILITE_COLOR : MENU_COLOR);
  250. if (m_ppChildMenu[i]->IsEnabled()) {
  251. MyMenuTextOut(SIMPLE_FONT, m_ppChildMenu[i]->m_szMenuName, (i == m_nCurSel) ? MENU_HILITE_COLOR : MENU_COLOR, &rect, bCalcRect, pCalcRect);
  252. nLinesDrawn++;
  253. }
  254. if (g_plugin.m_bShowMenuToolTips && i == m_nCurSel && !bCalcRect)
  255. {
  256. // tooltip:
  257. g_plugin.DrawTooltip(WASABI_API_LNGSTRINGW(IDS_SZ_MENU_NAV_TOOLTIP), xR, yB);
  258. }
  259. }
  260. }
  261. CMilkMenuItem *pItem = m_pFirstChildItem;
  262. while (pItem && nLinesDrawn < nStart+nLines)
  263. {
  264. if (!pItem->m_bEnabled)
  265. {
  266. pItem = pItem->m_pNext;
  267. i++;
  268. continue;
  269. }
  270. size_t addr = pItem->m_var_offset + (size_t)g_plugin.m_pState;
  271. if (i >= nStart)
  272. {
  273. wchar_t szItemText[256];
  274. switch(pItem->m_type)
  275. {
  276. case MENUITEMTYPE_STRING:
  277. lstrcpyW(szItemText, pItem->m_szName);
  278. break;
  279. case MENUITEMTYPE_BOOL:
  280. swprintf(szItemText, L"%s [%s]", pItem->m_szName,
  281. WASABI_API_LNGSTRINGW(*((bool *)(addr)) ? IDS_ON : IDS_OFF));
  282. break;
  283. default:
  284. lstrcpyW(szItemText, pItem->m_szName);
  285. break;
  286. }
  287. if (i == m_nCurSel)
  288. {
  289. MyMenuTextOut(SIMPLE_FONT, szItemText, MENU_HILITE_COLOR, &rect, bCalcRect, pCalcRect);
  290. if (g_plugin.m_bShowMenuToolTips && !bCalcRect)
  291. {
  292. // tooltip:
  293. g_plugin.DrawTooltip(pItem->m_szToolTip, xR, yB);
  294. }
  295. }
  296. else
  297. {
  298. MyMenuTextOut(SIMPLE_FONT, szItemText, MENU_COLOR, &rect, bCalcRect, pCalcRect);
  299. }
  300. nLinesDrawn++;
  301. }
  302. pItem = pItem->m_pNext;
  303. i++;
  304. }
  305. }
  306. else
  307. {
  308. // editing current selection
  309. // find the item
  310. CMilkMenuItem *pItem = m_pFirstChildItem;
  311. for (int i=m_nChildMenus; i < m_nCurSel; i++)
  312. pItem = pItem->m_pNext;
  313. size_t addr = pItem->m_var_offset + (size_t)g_plugin.m_pState;
  314. wchar_t buf[256];
  315. MyMenuTextOut(SIMPLE_FONT, WASABI_API_LNGSTRINGW(IDS_USE_UP_DOWN_ARROW_KEYS), MENU_COLOR, &rect, bCalcRect, pCalcRect);
  316. swprintf(buf, WASABI_API_LNGSTRINGW(IDS_CURRENT_VALUE_OF_X), pItem->m_szName);
  317. MyMenuTextOut(SIMPLE_FONT, buf, MENU_COLOR, &rect, bCalcRect, pCalcRect);
  318. switch(pItem->m_type)
  319. {
  320. case MENUITEMTYPE_INT:
  321. swprintf(buf, L" %d ", *((int*)(addr)) );
  322. break;
  323. case MENUITEMTYPE_FLOAT:
  324. case MENUITEMTYPE_LOGFLOAT:
  325. swprintf(buf, L" %5.3f ", *((float*)(addr)) );
  326. break;
  327. case MENUITEMTYPE_BLENDABLE:
  328. case MENUITEMTYPE_LOGBLENDABLE:
  329. swprintf(buf, L" %5.3f ", ((CBlendableFloat*)addr)->eval(-1) );
  330. break;
  331. default:
  332. lstrcpyW(buf, L" ? ");
  333. break;
  334. }
  335. MyMenuTextOut(SIMPLE_FONT, buf, MENU_HILITE_COLOR, &rect, bCalcRect, pCalcRect);
  336. // tooltip:
  337. if (g_plugin.m_bShowMenuToolTips && !bCalcRect)
  338. {
  339. g_plugin.DrawTooltip(pItem->m_szToolTip, xR, yB);
  340. }
  341. }
  342. }
  343. void CMilkMenu::OnWaitStringAccept(wchar_t *szNewString)
  344. {
  345. m_bEditingCurSel = false;
  346. // find the item
  347. CMilkMenuItem *pItem = m_pFirstChildItem;
  348. for (int i=m_nChildMenus; i < m_nCurSel; i++)
  349. pItem = pItem->m_pNext;
  350. size_t addr = pItem->m_var_offset + (size_t)g_plugin.m_pState;
  351. assert(pItem->m_type == MENUITEMTYPE_STRING);
  352. // apply the edited string
  353. lstrcpyW((wchar_t *)(addr), szNewString);
  354. // if user gave us a callback function pointer, call it now
  355. if (pItem->m_pCallbackFn)
  356. {
  357. pItem->m_pCallbackFn(0, 0);
  358. }
  359. // remember the last cursor position
  360. pItem->m_nLastCursorPos = g_plugin.m_waitstring.nCursorPos;
  361. }
  362. //----------------------------------------
  363. LRESULT CMilkMenu::HandleKeydown(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  364. {
  365. // all WM_KEYDOWNS that your app gets when a menu is up should be handled here,
  366. // by the menu that is currently active.
  367. // return value: FALSE if it handled the key; TRUE if it didn't
  368. int nRepeat = LOWORD(lParam);
  369. int rep;
  370. if (!m_bEditingCurSel)
  371. {
  372. switch(wParam)
  373. {
  374. case VK_UP:
  375. for (rep=0; rep<nRepeat; rep++)
  376. {
  377. if (m_nCurSel==0)
  378. break;
  379. do {
  380. m_nCurSel--;
  381. } while (m_nCurSel > 0 && !ItemIsEnabled(m_nCurSel));
  382. }
  383. if (m_nCurSel < 0) m_nCurSel = 0;//m_nChildMenus + m_nChildItems - 1;
  384. while (m_nCurSel < m_nChildMenus + m_nChildItems - 1 && !ItemIsEnabled(m_nCurSel))
  385. m_nCurSel++;
  386. return 0; // we processed (or absorbed) the key
  387. case VK_DOWN:
  388. for (rep=0; rep<nRepeat; rep++)
  389. {
  390. if (m_nCurSel == m_nChildMenus + m_nChildItems - 1)
  391. break;
  392. do {
  393. m_nCurSel++;
  394. } while (m_nCurSel < m_nChildMenus + m_nChildItems - 1 && !ItemIsEnabled(m_nCurSel));
  395. }
  396. if (m_nCurSel >= m_nChildMenus + m_nChildItems) m_nCurSel = m_nChildMenus + m_nChildItems - 1;//0;
  397. while (m_nCurSel > 0 && !ItemIsEnabled(m_nCurSel))
  398. m_nCurSel--;
  399. return 0; // we processed (or absorbed) the key
  400. case VK_HOME:
  401. m_nCurSel = 0;
  402. return 0; // we processed (or absorbed) the key
  403. case VK_END:
  404. m_nCurSel = m_nChildMenus + m_nChildItems - 1;
  405. return 0; // we processed (or absorbed) the key
  406. case VK_ESCAPE:
  407. g_plugin.m_UI_mode = UI_REGULAR;
  408. return 0; // we processed (or absorbed) the key
  409. case VK_BACK:
  410. case VK_LEFT:
  411. if (m_pParentMenu)
  412. g_plugin.m_pCurMenu = m_pParentMenu;
  413. else
  414. g_plugin.m_UI_mode = UI_REGULAR; // exit the menu
  415. return 0; // we processed (or absorbed) the key
  416. case VK_RETURN:
  417. case VK_RIGHT:
  418. case VK_SPACE:
  419. if (m_nCurSel < m_nChildMenus)
  420. {
  421. // go to sub-menu
  422. g_plugin.m_pCurMenu = m_ppChildMenu[m_nCurSel];
  423. }
  424. else
  425. {
  426. // find the item
  427. CMilkMenuItem *pItem = GetCurItem();
  428. size_t addr = pItem->m_var_offset + (size_t)g_plugin.m_pState;
  429. float fTemp;
  430. // begin editing the item
  431. switch(pItem->m_type)
  432. {
  433. case MENUITEMTYPE_UIMODE:
  434. g_plugin.m_UI_mode = (ui_mode)pItem->m_wParam;
  435. if (g_plugin.m_UI_mode==UI_IMPORT_WAVE ||
  436. g_plugin.m_UI_mode==UI_EXPORT_WAVE ||
  437. g_plugin.m_UI_mode==UI_IMPORT_SHAPE ||
  438. g_plugin.m_UI_mode==UI_EXPORT_SHAPE)
  439. {
  440. g_plugin.m_bPresetLockedByCode = true;
  441. // enter WaitString mode
  442. g_plugin.m_waitstring.bActive = true;
  443. g_plugin.m_waitstring.bFilterBadChars = false;
  444. g_plugin.m_waitstring.bDisplayAsCode = false;
  445. g_plugin.m_waitstring.nSelAnchorPos = -1;
  446. g_plugin.m_waitstring.nMaxLen = min(sizeof(g_plugin.m_waitstring.szText)-1, MAX_PATH - wcslen(g_plugin.GetPresetDir()) - 6); // 6 for the extension + null char. We set this because win32 LoadFile, MoveFile, etc. barf if the path+filename+ext are > MAX_PATH chars.
  447. swprintf(g_plugin.m_waitstring.szText, L"%sfile.dat", g_plugin.m_szPresetDir);
  448. if (g_plugin.m_UI_mode==UI_IMPORT_WAVE || g_plugin.m_UI_mode==UI_IMPORT_SHAPE)
  449. WASABI_API_LNGSTRINGW_BUF(IDS_LOAD_FROM_FILE,g_plugin.m_waitstring.szPrompt,512);
  450. else
  451. WASABI_API_LNGSTRINGW_BUF(IDS_SAVE_TO_FILE,g_plugin.m_waitstring.szPrompt,512);
  452. g_plugin.m_waitstring.szToolTip[0] = 0;
  453. g_plugin.m_waitstring.nCursorPos = wcslen(g_plugin.m_waitstring.szText); // set the starting edit position
  454. }
  455. break;
  456. case MENUITEMTYPE_BOOL:
  457. *((bool *)addr) = !(*((bool *)addr));
  458. break;
  459. case MENUITEMTYPE_INT:
  460. m_bEditingCurSel = true;
  461. pItem->m_original_value = (LPARAM)(*((int*)(addr)));
  462. break;
  463. case MENUITEMTYPE_FLOAT:
  464. case MENUITEMTYPE_LOGFLOAT:
  465. m_bEditingCurSel = true;
  466. pItem->m_original_value = (LPARAM)(*((float*)(addr))*10000L);
  467. break;
  468. case MENUITEMTYPE_BLENDABLE:
  469. case MENUITEMTYPE_LOGBLENDABLE:
  470. m_bEditingCurSel = true;
  471. {
  472. //CBlendableFloat *p = (CBlendableFloat*)(pItem->m_pVariable);
  473. //*p = 0.99f;
  474. fTemp = ((CBlendableFloat*)addr)->eval(-1);//p->eval(-1);
  475. }
  476. pItem->m_original_value = (LPARAM)(fTemp*10000L);
  477. break;
  478. case MENUITEMTYPE_STRING:
  479. // enter waitstring mode. ***This function will cease to receive keyboard input
  480. // while the string is being edited***
  481. g_plugin.m_UI_mode = UI_EDIT_MENU_STRING;
  482. g_plugin.m_waitstring.bActive = true;
  483. g_plugin.m_waitstring.bFilterBadChars = false;
  484. g_plugin.m_waitstring.bDisplayAsCode = true;
  485. g_plugin.m_waitstring.nSelAnchorPos = -1;
  486. g_plugin.m_waitstring.nMaxLen = pItem->m_wParam ? pItem->m_wParam : 8190;
  487. g_plugin.m_waitstring.nMaxLen = min(g_plugin.m_waitstring.nMaxLen, sizeof(g_plugin.m_waitstring.szText)-16);
  488. //lstrcpyW(g_plugin.m_waitstring.szText, (wchar_t *)addr);
  489. lstrcpyA((char*)g_plugin.m_waitstring.szText, (char*)addr);
  490. swprintf(g_plugin.m_waitstring.szPrompt, WASABI_API_LNGSTRINGW(IDS_ENTER_THE_NEW_STRING), pItem->m_szName);
  491. lstrcpyW(g_plugin.m_waitstring.szToolTip, pItem->m_szToolTip);
  492. g_plugin.m_waitstring.nCursorPos = strlen/*wcslen*/((char*)g_plugin.m_waitstring.szText);
  493. if (pItem->m_nLastCursorPos < g_plugin.m_waitstring.nCursorPos)
  494. g_plugin.m_waitstring.nCursorPos = pItem->m_nLastCursorPos;
  495. break;
  496. /*
  497. case MENUITEMTYPE_OSC:
  498. m_bEditingCurSel = true;
  499. pItem->m_bEditingSubSel = false;
  500. break;
  501. */
  502. }
  503. }
  504. return 0; // we processed (or absorbed) the key
  505. default:
  506. // key wasn't handled
  507. return TRUE;
  508. break;
  509. }
  510. }
  511. else // m_bEditingCurSel
  512. {
  513. float fMult = 1.0f;
  514. bool bDec;
  515. // find the item
  516. CMilkMenuItem *pItem = m_pFirstChildItem;
  517. for (int i=m_nChildMenus; i < m_nCurSel; i++)
  518. pItem = pItem->m_pNext;
  519. size_t addr = pItem->m_var_offset + (size_t)g_plugin.m_pState;
  520. switch(wParam)
  521. {
  522. case VK_ESCAPE: // exit Edit mode & restore original value
  523. switch(pItem->m_type)
  524. {
  525. case MENUITEMTYPE_INT:
  526. m_bEditingCurSel = false;
  527. *((int *)addr) = (int)pItem->m_original_value;
  528. break;
  529. case MENUITEMTYPE_FLOAT:
  530. m_bEditingCurSel = false;
  531. *((float *)addr) = ((float)pItem->m_original_value)*0.0001f;
  532. break;
  533. case MENUITEMTYPE_LOGFLOAT:
  534. m_bEditingCurSel = false;
  535. *((float *)addr) = ((float)pItem->m_original_value)*0.0001f;
  536. break;
  537. case MENUITEMTYPE_BLENDABLE:
  538. m_bEditingCurSel = false;
  539. *((CBlendableFloat *)(addr)) = ((float)(pItem->m_original_value))*0.0001f;
  540. break;
  541. case MENUITEMTYPE_LOGBLENDABLE:
  542. m_bEditingCurSel = false;
  543. *((CBlendableFloat *)(addr)) = ((float)(pItem->m_original_value))*0.0001f;
  544. break;
  545. //case MENUITEMTYPE_STRING:
  546. // won't ever happen - see OnWaitStringCancel()
  547. }
  548. return 0;
  549. case VK_RETURN:
  550. //if (pItem->m_type == MENUITEMTYPE_STRING)
  551. // ... won't ever happen - see OnWaitStringAccept()
  552. m_bEditingCurSel = false;
  553. return 0;
  554. case VK_NEXT:
  555. case VK_PRIOR:
  556. fMult *= 10.0f;
  557. // break intentionally left out here...
  558. case VK_UP:
  559. case VK_DOWN:
  560. {
  561. USHORT mask = 1 << (sizeof(USHORT)*8 - 1); // we want the highest-order bit
  562. bool bShiftHeldDown = (GetKeyState(VK_SHIFT) & mask) != 0;
  563. //bool bCtrlHeldDown = (GetKeyState(VK_CONTROL) & mask) != 0;
  564. if (bShiftHeldDown && (wParam==VK_UP || wParam==VK_DOWN))
  565. fMult *= 0.1f;
  566. }
  567. bDec = (wParam == VK_DOWN || wParam == VK_NEXT);
  568. switch(pItem->m_type)
  569. {
  570. case MENUITEMTYPE_INT:
  571. {
  572. int *pInt = ((int *)addr);
  573. if (fMult<1) fMult=1;
  574. (*pInt) += (int)((bDec) ? -fMult : fMult);
  575. if (*pInt < pItem->m_fMin) *pInt = (int)pItem->m_fMin;
  576. if (*pInt > pItem->m_fMax) *pInt = (int)pItem->m_fMax;
  577. }
  578. break;
  579. case MENUITEMTYPE_FLOAT:
  580. {
  581. float *pFloat = ((float *)addr);
  582. float fInc = (pItem->m_fMax - pItem->m_fMin)*0.01f*fMult;
  583. (*pFloat) += (bDec) ? -fInc : fInc;
  584. if (*pFloat < pItem->m_fMin) *pFloat = pItem->m_fMin;
  585. if (*pFloat > pItem->m_fMax) *pFloat = pItem->m_fMax;
  586. }
  587. break;
  588. case MENUITEMTYPE_LOGFLOAT:
  589. {
  590. float *pFloat = ((float *)addr);
  591. (*pFloat) *= (bDec) ? powf(1.0f/1.01f, fMult) : powf(1.01f, fMult);
  592. if (*pFloat < pItem->m_fMin) *pFloat = pItem->m_fMin;
  593. if (*pFloat > pItem->m_fMax) *pFloat = pItem->m_fMax;
  594. }
  595. break;
  596. case MENUITEMTYPE_BLENDABLE:
  597. {
  598. CBlendableFloat *pBlend = ((CBlendableFloat *)addr);
  599. float fInc = (pItem->m_fMax - pItem->m_fMin)*0.01f*fMult;
  600. (*pBlend) += (bDec) ? -fInc : fInc;
  601. if (pBlend->eval(-1) < pItem->m_fMin) *pBlend = pItem->m_fMin;
  602. if (pBlend->eval(-1) > pItem->m_fMax) *pBlend = pItem->m_fMax;
  603. }
  604. break;
  605. case MENUITEMTYPE_LOGBLENDABLE:
  606. {
  607. CBlendableFloat *pBlend = ((CBlendableFloat *)addr);
  608. (*pBlend) *= (bDec) ? powf(1.0f/1.01f, fMult) : powf(1.01f, fMult);
  609. if (pBlend->eval(-1) < pItem->m_fMin) *pBlend = pItem->m_fMin;
  610. if (pBlend->eval(-1) > pItem->m_fMax) *pBlend = pItem->m_fMax;
  611. }
  612. break;
  613. /*
  614. case MENUITEMTYPE_OSC:
  615. if (pItem->m_bEditingSubSel)
  616. {
  617. if (wParam == VK_UP)
  618. {
  619. pItem->m_nSubSel--;
  620. if (pItem->m_nSubSel < 0) pItem->m_nSubSel = 4;
  621. }
  622. else if (wParam == VK_DOWN)
  623. {
  624. pItem->m_nSubSel++;
  625. if (pItem->m_nSubSel > 4) pItem->m_nSubSel = 0;
  626. }
  627. }
  628. else
  629. {
  630. switch(pItem->m_nSubSel)
  631. {
  632. also to do: make 'drawtext' draw it properly
  633. case 0:
  634. fixme - what are the bounds for each type? and are incs constant or log?
  635. break;
  636. case 1:
  637. fixme
  638. break;
  639. case 2:
  640. fixme
  641. break;
  642. case 3:
  643. fixme
  644. break;
  645. case 4:
  646. fixme
  647. break;
  648. }
  649. }
  650. break;
  651. */
  652. }
  653. return 0;
  654. default:
  655. // key wasn't handled
  656. return TRUE;
  657. break;
  658. }
  659. }
  660. return TRUE;
  661. }