winamp/Src/Plugins/Visualization/vis_milk2/menu.cpp

751 lines
22 KiB
C++

/*
LICENSE
-------
Copyright 2005-2013 Nullsoft, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Nullsoft nor the names of its contributors may be used to
endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "api__vis_milk2.h"
#include "state.h" // for CBlendableFloat - fix this
#include "menu.h"
#include "plugin.h"
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include "resource.h"
extern CPlugin g_plugin; // declared in main.cpp
//----------------------------------------
CMilkMenuItem::CMilkMenuItem()
{
WASABI_API_LNGSTRINGW_BUF(IDS_UNTITLED_MENU_ITEM,m_szName,64);
m_szToolTip[0] = 0;
m_type = MENUITEMTYPE_BUNK;
m_fMin = 0.0f;
m_fMax = 0.0f;
m_var_offset = NULL;
m_pCallbackFn = NULL;
m_pNext = NULL;
m_original_value = NULL;
m_nLastCursorPos = 0;
m_bEnabled = true;
}
CMilkMenuItem::~CMilkMenuItem()
{
if (m_pNext)
{
delete m_pNext;
m_pNext = NULL;
}
}
//----------------------------------------
CMilkMenu::CMilkMenu()
{
//Reset();
}
CMilkMenu::~CMilkMenu()
{
/*
if (m_pFirstChildItem)
{
delete m_pFirstChildItem;
m_pFirstChildItem = NULL;
}
*/
}
//----------------------------------------
bool CMilkMenu::ItemIsEnabled(int j)
{
if (j < m_nChildMenus)
return m_ppChildMenu[j]->IsEnabled();
int i = m_nChildMenus;
CMilkMenuItem *pChild = m_pFirstChildItem;
while (pChild && i<j)
{
pChild = pChild->m_pNext;
i++;
}
if (pChild)
return pChild->m_bEnabled;
return false;
}
//----------------------------------------
void CMilkMenu::EnableItem(wchar_t* szName, bool bEnable)
{
//search submenus
int i = 0;
for (i=0; i<m_nChildMenus; i++) {
if (!wcscmp(m_ppChildMenu[i]->GetName(), szName))
{
m_ppChildMenu[i]->Enable(bEnable);
if (!bEnable)
{
while (m_nCurSel > 0 && !ItemIsEnabled(m_nCurSel))
m_nCurSel--;
if (m_nCurSel==0 && !ItemIsEnabled(m_nCurSel))
while (m_nCurSel < m_nChildMenus+m_nChildItems-1 && !ItemIsEnabled(m_nCurSel))
m_nCurSel++;
}
return;
}
}
//search child items
CMilkMenuItem *pChild = m_pFirstChildItem;
while (pChild)
{
if (!wcscmp(pChild->m_szName, szName))
{
pChild->m_bEnabled = bEnable;
if (!bEnable)
{
while (m_nCurSel > 0 && !ItemIsEnabled(m_nCurSel))
m_nCurSel--;
if (m_nCurSel==0 && !ItemIsEnabled(m_nCurSel))
while (m_nCurSel < m_nChildMenus+m_nChildItems-1 && !ItemIsEnabled(m_nCurSel))
m_nCurSel++;
}
return;
}
pChild = pChild->m_pNext;
i++;
}
}
//----------------------------------------
void CMilkMenu::Reset()
{
m_pParentMenu = NULL;
for (int i=0; i<MAX_CHILD_MENUS; i++)
m_ppChildMenu[i] = NULL;
m_pFirstChildItem = NULL;
WASABI_API_LNGSTRINGW_BUF(IDS_UNTITLED_MENU,m_szMenuName,64);
m_nChildMenus = 0;
m_nChildItems = 0;
m_nCurSel = 0;
m_bEditingCurSel = false;
m_bEnabled = true;
}
//----------------------------------------
void CMilkMenu::Init(wchar_t *szName)
{
Reset();
if (szName && szName[0])
wcsncpy(m_szMenuName, szName, 64);
}
void CMilkMenu::Finish()
{
if (m_pFirstChildItem)
{
delete m_pFirstChildItem;
m_pFirstChildItem = NULL;
}
}
//----------------------------------------
void CMilkMenu::AddChildMenu(CMilkMenu *pMenu)
{
if (m_nChildMenus < MAX_CHILD_MENUS)
{
m_ppChildMenu[m_nChildMenus++] = pMenu;
pMenu->SetParentPointer(this);
}
}
//----------------------------------------
void CMilkMenu::AddItem(wchar_t *szName, void *var, MENUITEMTYPE type, wchar_t *szToolTip,
float min, float max, MilkMenuCallbackFnPtr pCallback,
unsigned int wParam, unsigned int lParam)
{
CMilkMenuItem *pLastItem = NULL;
// find last item in linked list
if (!m_pFirstChildItem)
{
// first item
m_pFirstChildItem = new CMilkMenuItem;
pLastItem = m_pFirstChildItem;
}
else
{
pLastItem = m_pFirstChildItem;
while (pLastItem->m_pNext)
pLastItem = pLastItem->m_pNext;
// allocate a new CMilkMenuItem
pLastItem->m_pNext = new CMilkMenuItem;
pLastItem = pLastItem->m_pNext;
}
// set its attributes
wcsncpy(pLastItem->m_szName, szName, 64);
wcsncpy(pLastItem->m_szToolTip, szToolTip, 1024);
pLastItem->m_var_offset = (size_t)var - (size_t)(g_plugin.m_pState);
pLastItem->m_type = type;
pLastItem->m_fMin = min;
pLastItem->m_fMax = max;
pLastItem->m_wParam = wParam;
pLastItem->m_lParam = lParam;
if ((type==MENUITEMTYPE_LOGBLENDABLE || type==MENUITEMTYPE_LOGFLOAT) && min==max)
{
// special defaults
pLastItem->m_fMin = 0.01f;
pLastItem->m_fMax = 100.0f;
}
pLastItem->m_pCallbackFn = pCallback;
m_nChildItems++;
}
//----------------------------------------
void MyMenuTextOut(eFontIndex font_index, wchar_t* str, DWORD color, RECT* pRect, int bCalcRect, RECT* pCalcRect)
{
if (bCalcRect)
{
RECT t = *pRect;
pRect->top += g_plugin.m_text.DrawTextW(g_plugin.GetFont(font_index), str, -1, &t, DT_SINGLELINE | DT_END_ELLIPSIS | DT_CALCRECT, 0xFFFFFFFF, false);
pCalcRect->bottom += t.bottom - t.top;
//if (pCalcRect->bottom > pRect->bottom)
// pCalcRect->bottom = pRect->bottom;
pCalcRect->right = max(pCalcRect->right, pCalcRect->left + t.right - t.left);
}
else
{
pRect->top += g_plugin.m_text.DrawTextW(g_plugin.GetFont(font_index), str, -1, pRect, DT_SINGLELINE | DT_END_ELLIPSIS, color, false);
}
}
void CMilkMenu::DrawMenu(RECT rect, int xR, int yB, int bCalcRect, RECT* pCalcRect)
{
// 'rect' is the bounding rectangle in which we're allowed to draw the menu;
// it's .top member is incremented as we draw downward.
// if bCalcRect==1, then we return pCalcRect as the area that the menu actually
// occupies, excluding any tooltips.
if (bCalcRect!=0 && pCalcRect==NULL)
return;
if (bCalcRect)
{
pCalcRect->left = rect.left;
pCalcRect->right = rect.left;
pCalcRect->top = rect.top;
pCalcRect->bottom = rect.top;
}
if (!m_bEditingCurSel)
{
int nLines = (rect.bottom - rect.top - PLAYLIST_INNER_MARGIN*2) / g_plugin.GetFontHeight(SIMPLE_FONT) - 1; // save 1 line for the tooltip
if (nLines<1) return;
int nStart = (m_nCurSel/nLines)*nLines;
int nLinesDrawn = 0;
int i = 0;
for (i=0; i < m_nChildMenus; i++)
{
if (i >= nStart && i < nStart+nLines)
{
//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);
if (m_ppChildMenu[i]->IsEnabled()) {
MyMenuTextOut(SIMPLE_FONT, m_ppChildMenu[i]->m_szMenuName, (i == m_nCurSel) ? MENU_HILITE_COLOR : MENU_COLOR, &rect, bCalcRect, pCalcRect);
nLinesDrawn++;
}
if (g_plugin.m_bShowMenuToolTips && i == m_nCurSel && !bCalcRect)
{
// tooltip:
g_plugin.DrawTooltip(WASABI_API_LNGSTRINGW(IDS_SZ_MENU_NAV_TOOLTIP), xR, yB);
}
}
}
CMilkMenuItem *pItem = m_pFirstChildItem;
while (pItem && nLinesDrawn < nStart+nLines)
{
if (!pItem->m_bEnabled)
{
pItem = pItem->m_pNext;
i++;
continue;
}
size_t addr = pItem->m_var_offset + (size_t)g_plugin.m_pState;
if (i >= nStart)
{
wchar_t szItemText[256];
switch(pItem->m_type)
{
case MENUITEMTYPE_STRING:
lstrcpyW(szItemText, pItem->m_szName);
break;
case MENUITEMTYPE_BOOL:
swprintf(szItemText, L"%s [%s]", pItem->m_szName,
WASABI_API_LNGSTRINGW(*((bool *)(addr)) ? IDS_ON : IDS_OFF));
break;
default:
lstrcpyW(szItemText, pItem->m_szName);
break;
}
if (i == m_nCurSel)
{
MyMenuTextOut(SIMPLE_FONT, szItemText, MENU_HILITE_COLOR, &rect, bCalcRect, pCalcRect);
if (g_plugin.m_bShowMenuToolTips && !bCalcRect)
{
// tooltip:
g_plugin.DrawTooltip(pItem->m_szToolTip, xR, yB);
}
}
else
{
MyMenuTextOut(SIMPLE_FONT, szItemText, MENU_COLOR, &rect, bCalcRect, pCalcRect);
}
nLinesDrawn++;
}
pItem = pItem->m_pNext;
i++;
}
}
else
{
// editing current selection
// find the item
CMilkMenuItem *pItem = m_pFirstChildItem;
for (int i=m_nChildMenus; i < m_nCurSel; i++)
pItem = pItem->m_pNext;
size_t addr = pItem->m_var_offset + (size_t)g_plugin.m_pState;
wchar_t buf[256];
MyMenuTextOut(SIMPLE_FONT, WASABI_API_LNGSTRINGW(IDS_USE_UP_DOWN_ARROW_KEYS), MENU_COLOR, &rect, bCalcRect, pCalcRect);
swprintf(buf, WASABI_API_LNGSTRINGW(IDS_CURRENT_VALUE_OF_X), pItem->m_szName);
MyMenuTextOut(SIMPLE_FONT, buf, MENU_COLOR, &rect, bCalcRect, pCalcRect);
switch(pItem->m_type)
{
case MENUITEMTYPE_INT:
swprintf(buf, L" %d ", *((int*)(addr)) );
break;
case MENUITEMTYPE_FLOAT:
case MENUITEMTYPE_LOGFLOAT:
swprintf(buf, L" %5.3f ", *((float*)(addr)) );
break;
case MENUITEMTYPE_BLENDABLE:
case MENUITEMTYPE_LOGBLENDABLE:
swprintf(buf, L" %5.3f ", ((CBlendableFloat*)addr)->eval(-1) );
break;
default:
lstrcpyW(buf, L" ? ");
break;
}
MyMenuTextOut(SIMPLE_FONT, buf, MENU_HILITE_COLOR, &rect, bCalcRect, pCalcRect);
// tooltip:
if (g_plugin.m_bShowMenuToolTips && !bCalcRect)
{
g_plugin.DrawTooltip(pItem->m_szToolTip, xR, yB);
}
}
}
void CMilkMenu::OnWaitStringAccept(wchar_t *szNewString)
{
m_bEditingCurSel = false;
// find the item
CMilkMenuItem *pItem = m_pFirstChildItem;
for (int i=m_nChildMenus; i < m_nCurSel; i++)
pItem = pItem->m_pNext;
size_t addr = pItem->m_var_offset + (size_t)g_plugin.m_pState;
assert(pItem->m_type == MENUITEMTYPE_STRING);
// apply the edited string
lstrcpyW((wchar_t *)(addr), szNewString);
// if user gave us a callback function pointer, call it now
if (pItem->m_pCallbackFn)
{
pItem->m_pCallbackFn(0, 0);
}
// remember the last cursor position
pItem->m_nLastCursorPos = g_plugin.m_waitstring.nCursorPos;
}
//----------------------------------------
LRESULT CMilkMenu::HandleKeydown(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// all WM_KEYDOWNS that your app gets when a menu is up should be handled here,
// by the menu that is currently active.
// return value: FALSE if it handled the key; TRUE if it didn't
int nRepeat = LOWORD(lParam);
int rep;
if (!m_bEditingCurSel)
{
switch(wParam)
{
case VK_UP:
for (rep=0; rep<nRepeat; rep++)
{
if (m_nCurSel==0)
break;
do {
m_nCurSel--;
} while (m_nCurSel > 0 && !ItemIsEnabled(m_nCurSel));
}
if (m_nCurSel < 0) m_nCurSel = 0;//m_nChildMenus + m_nChildItems - 1;
while (m_nCurSel < m_nChildMenus + m_nChildItems - 1 && !ItemIsEnabled(m_nCurSel))
m_nCurSel++;
return 0; // we processed (or absorbed) the key
case VK_DOWN:
for (rep=0; rep<nRepeat; rep++)
{
if (m_nCurSel == m_nChildMenus + m_nChildItems - 1)
break;
do {
m_nCurSel++;
} while (m_nCurSel < m_nChildMenus + m_nChildItems - 1 && !ItemIsEnabled(m_nCurSel));
}
if (m_nCurSel >= m_nChildMenus + m_nChildItems) m_nCurSel = m_nChildMenus + m_nChildItems - 1;//0;
while (m_nCurSel > 0 && !ItemIsEnabled(m_nCurSel))
m_nCurSel--;
return 0; // we processed (or absorbed) the key
case VK_HOME:
m_nCurSel = 0;
return 0; // we processed (or absorbed) the key
case VK_END:
m_nCurSel = m_nChildMenus + m_nChildItems - 1;
return 0; // we processed (or absorbed) the key
case VK_ESCAPE:
g_plugin.m_UI_mode = UI_REGULAR;
return 0; // we processed (or absorbed) the key
case VK_BACK:
case VK_LEFT:
if (m_pParentMenu)
g_plugin.m_pCurMenu = m_pParentMenu;
else
g_plugin.m_UI_mode = UI_REGULAR; // exit the menu
return 0; // we processed (or absorbed) the key
case VK_RETURN:
case VK_RIGHT:
case VK_SPACE:
if (m_nCurSel < m_nChildMenus)
{
// go to sub-menu
g_plugin.m_pCurMenu = m_ppChildMenu[m_nCurSel];
}
else
{
// find the item
CMilkMenuItem *pItem = GetCurItem();
size_t addr = pItem->m_var_offset + (size_t)g_plugin.m_pState;
float fTemp;
// begin editing the item
switch(pItem->m_type)
{
case MENUITEMTYPE_UIMODE:
g_plugin.m_UI_mode = (ui_mode)pItem->m_wParam;
if (g_plugin.m_UI_mode==UI_IMPORT_WAVE ||
g_plugin.m_UI_mode==UI_EXPORT_WAVE ||
g_plugin.m_UI_mode==UI_IMPORT_SHAPE ||
g_plugin.m_UI_mode==UI_EXPORT_SHAPE)
{
g_plugin.m_bPresetLockedByCode = true;
// enter WaitString mode
g_plugin.m_waitstring.bActive = true;
g_plugin.m_waitstring.bFilterBadChars = false;
g_plugin.m_waitstring.bDisplayAsCode = false;
g_plugin.m_waitstring.nSelAnchorPos = -1;
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.
swprintf(g_plugin.m_waitstring.szText, L"%sfile.dat", g_plugin.m_szPresetDir);
if (g_plugin.m_UI_mode==UI_IMPORT_WAVE || g_plugin.m_UI_mode==UI_IMPORT_SHAPE)
WASABI_API_LNGSTRINGW_BUF(IDS_LOAD_FROM_FILE,g_plugin.m_waitstring.szPrompt,512);
else
WASABI_API_LNGSTRINGW_BUF(IDS_SAVE_TO_FILE,g_plugin.m_waitstring.szPrompt,512);
g_plugin.m_waitstring.szToolTip[0] = 0;
g_plugin.m_waitstring.nCursorPos = wcslen(g_plugin.m_waitstring.szText); // set the starting edit position
}
break;
case MENUITEMTYPE_BOOL:
*((bool *)addr) = !(*((bool *)addr));
break;
case MENUITEMTYPE_INT:
m_bEditingCurSel = true;
pItem->m_original_value = (LPARAM)(*((int*)(addr)));
break;
case MENUITEMTYPE_FLOAT:
case MENUITEMTYPE_LOGFLOAT:
m_bEditingCurSel = true;
pItem->m_original_value = (LPARAM)(*((float*)(addr))*10000L);
break;
case MENUITEMTYPE_BLENDABLE:
case MENUITEMTYPE_LOGBLENDABLE:
m_bEditingCurSel = true;
{
//CBlendableFloat *p = (CBlendableFloat*)(pItem->m_pVariable);
//*p = 0.99f;
fTemp = ((CBlendableFloat*)addr)->eval(-1);//p->eval(-1);
}
pItem->m_original_value = (LPARAM)(fTemp*10000L);
break;
case MENUITEMTYPE_STRING:
// enter waitstring mode. ***This function will cease to receive keyboard input
// while the string is being edited***
g_plugin.m_UI_mode = UI_EDIT_MENU_STRING;
g_plugin.m_waitstring.bActive = true;
g_plugin.m_waitstring.bFilterBadChars = false;
g_plugin.m_waitstring.bDisplayAsCode = true;
g_plugin.m_waitstring.nSelAnchorPos = -1;
g_plugin.m_waitstring.nMaxLen = pItem->m_wParam ? pItem->m_wParam : 8190;
g_plugin.m_waitstring.nMaxLen = min(g_plugin.m_waitstring.nMaxLen, sizeof(g_plugin.m_waitstring.szText)-16);
//lstrcpyW(g_plugin.m_waitstring.szText, (wchar_t *)addr);
lstrcpyA((char*)g_plugin.m_waitstring.szText, (char*)addr);
swprintf(g_plugin.m_waitstring.szPrompt, WASABI_API_LNGSTRINGW(IDS_ENTER_THE_NEW_STRING), pItem->m_szName);
lstrcpyW(g_plugin.m_waitstring.szToolTip, pItem->m_szToolTip);
g_plugin.m_waitstring.nCursorPos = strlen/*wcslen*/((char*)g_plugin.m_waitstring.szText);
if (pItem->m_nLastCursorPos < g_plugin.m_waitstring.nCursorPos)
g_plugin.m_waitstring.nCursorPos = pItem->m_nLastCursorPos;
break;
/*
case MENUITEMTYPE_OSC:
m_bEditingCurSel = true;
pItem->m_bEditingSubSel = false;
break;
*/
}
}
return 0; // we processed (or absorbed) the key
default:
// key wasn't handled
return TRUE;
break;
}
}
else // m_bEditingCurSel
{
float fMult = 1.0f;
bool bDec;
// find the item
CMilkMenuItem *pItem = m_pFirstChildItem;
for (int i=m_nChildMenus; i < m_nCurSel; i++)
pItem = pItem->m_pNext;
size_t addr = pItem->m_var_offset + (size_t)g_plugin.m_pState;
switch(wParam)
{
case VK_ESCAPE: // exit Edit mode & restore original value
switch(pItem->m_type)
{
case MENUITEMTYPE_INT:
m_bEditingCurSel = false;
*((int *)addr) = (int)pItem->m_original_value;
break;
case MENUITEMTYPE_FLOAT:
m_bEditingCurSel = false;
*((float *)addr) = ((float)pItem->m_original_value)*0.0001f;
break;
case MENUITEMTYPE_LOGFLOAT:
m_bEditingCurSel = false;
*((float *)addr) = ((float)pItem->m_original_value)*0.0001f;
break;
case MENUITEMTYPE_BLENDABLE:
m_bEditingCurSel = false;
*((CBlendableFloat *)(addr)) = ((float)(pItem->m_original_value))*0.0001f;
break;
case MENUITEMTYPE_LOGBLENDABLE:
m_bEditingCurSel = false;
*((CBlendableFloat *)(addr)) = ((float)(pItem->m_original_value))*0.0001f;
break;
//case MENUITEMTYPE_STRING:
// won't ever happen - see OnWaitStringCancel()
}
return 0;
case VK_RETURN:
//if (pItem->m_type == MENUITEMTYPE_STRING)
// ... won't ever happen - see OnWaitStringAccept()
m_bEditingCurSel = false;
return 0;
case VK_NEXT:
case VK_PRIOR:
fMult *= 10.0f;
// break intentionally left out here...
case VK_UP:
case VK_DOWN:
{
USHORT mask = 1 << (sizeof(USHORT)*8 - 1); // we want the highest-order bit
bool bShiftHeldDown = (GetKeyState(VK_SHIFT) & mask) != 0;
//bool bCtrlHeldDown = (GetKeyState(VK_CONTROL) & mask) != 0;
if (bShiftHeldDown && (wParam==VK_UP || wParam==VK_DOWN))
fMult *= 0.1f;
}
bDec = (wParam == VK_DOWN || wParam == VK_NEXT);
switch(pItem->m_type)
{
case MENUITEMTYPE_INT:
{
int *pInt = ((int *)addr);
if (fMult<1) fMult=1;
(*pInt) += (int)((bDec) ? -fMult : fMult);
if (*pInt < pItem->m_fMin) *pInt = (int)pItem->m_fMin;
if (*pInt > pItem->m_fMax) *pInt = (int)pItem->m_fMax;
}
break;
case MENUITEMTYPE_FLOAT:
{
float *pFloat = ((float *)addr);
float fInc = (pItem->m_fMax - pItem->m_fMin)*0.01f*fMult;
(*pFloat) += (bDec) ? -fInc : fInc;
if (*pFloat < pItem->m_fMin) *pFloat = pItem->m_fMin;
if (*pFloat > pItem->m_fMax) *pFloat = pItem->m_fMax;
}
break;
case MENUITEMTYPE_LOGFLOAT:
{
float *pFloat = ((float *)addr);
(*pFloat) *= (bDec) ? powf(1.0f/1.01f, fMult) : powf(1.01f, fMult);
if (*pFloat < pItem->m_fMin) *pFloat = pItem->m_fMin;
if (*pFloat > pItem->m_fMax) *pFloat = pItem->m_fMax;
}
break;
case MENUITEMTYPE_BLENDABLE:
{
CBlendableFloat *pBlend = ((CBlendableFloat *)addr);
float fInc = (pItem->m_fMax - pItem->m_fMin)*0.01f*fMult;
(*pBlend) += (bDec) ? -fInc : fInc;
if (pBlend->eval(-1) < pItem->m_fMin) *pBlend = pItem->m_fMin;
if (pBlend->eval(-1) > pItem->m_fMax) *pBlend = pItem->m_fMax;
}
break;
case MENUITEMTYPE_LOGBLENDABLE:
{
CBlendableFloat *pBlend = ((CBlendableFloat *)addr);
(*pBlend) *= (bDec) ? powf(1.0f/1.01f, fMult) : powf(1.01f, fMult);
if (pBlend->eval(-1) < pItem->m_fMin) *pBlend = pItem->m_fMin;
if (pBlend->eval(-1) > pItem->m_fMax) *pBlend = pItem->m_fMax;
}
break;
/*
case MENUITEMTYPE_OSC:
if (pItem->m_bEditingSubSel)
{
if (wParam == VK_UP)
{
pItem->m_nSubSel--;
if (pItem->m_nSubSel < 0) pItem->m_nSubSel = 4;
}
else if (wParam == VK_DOWN)
{
pItem->m_nSubSel++;
if (pItem->m_nSubSel > 4) pItem->m_nSubSel = 0;
}
}
else
{
switch(pItem->m_nSubSel)
{
also to do: make 'drawtext' draw it properly
case 0:
fixme - what are the bounds for each type? and are incs constant or log?
break;
case 1:
fixme
break;
case 2:
fixme
break;
case 3:
fixme
break;
case 4:
fixme
break;
}
}
break;
*/
}
return 0;
default:
// key wasn't handled
return TRUE;
break;
}
}
return TRUE;
}