Files
AC_Pro/ListViewPattern.cpp
2026-06-13 00:05:19 +08:00

443 lines
13 KiB
C++

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "ListViewPattern.h"
#include "GlobalUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
#define LP_ITEM_OVER RGB(67, 73, 80)
#define LP_ITEM_SELECTED RGB(0, 0, 0)
#define LP_ITEM_DEF RGB(39, 42, 47)
#define CELL_HEIGHT 18
#define LINE_COLOR RGB(123, 123, 123)
#define FontClolor TColor(0xBDAA9C)
const BYTE u_arrChordPreset[2][4][4] = { //预设和弦
{{0,37,9,30},{0,37,20,28},{0,9,20,28},{0,17,37,30}},
{{37,9,28,16},{37,17,20,28},{37,0,9,17},{37,28,20,16}} };
TPngImage *pngCol = NULL;
TPngImage *pngUnCol = NULL;
TPngImage *pngCharge = NULL;
void LoadImg()
{
if( !pngCol ) pngCol = new TPngImage();
if( !pngUnCol ) pngUnCol = new TPngImage();
if( !pngCharge ) pngCharge = new TPngImage();
pngCol->LoadFromResourceName(int(HInstance), L"imgCollect");
pngUnCol->LoadFromResourceName(int(HInstance), L"imgUnCollect");
pngCharge->LoadFromResourceName(int(HInstance), L"imgStyleCharge");
}
void ReleaseImg()
{
SAFE_DELETE(pngCol);
SAFE_DELETE(pngUnCol);
SAFE_DELETE(pngCharge);
}
//---------------------------------------------------------------------------
__fastcall TListViewPattern::TListViewPattern(TComponent* Owner, bool bChan9,
TStageList* lstStages, int iPlayBar)
: TListViewBase( Owner )
{
m_nPlayIndex = -1;
m_iFont = -1;
m_iProg = -1;
m_pPtInfo = NULL;
m_bChan9 = bChan9;
m_iPlayBar = iPlayBar;
m_lstStages = lstStages;
FOnTextureChanged = NULL;
ShowHint = true;
m_btnHint = NULL;
LoadImg();
}
//---------------------------------------------------------------------------
__fastcall TListViewPattern::~TListViewPattern()
{
ReleaseImg();
}
//---------------------------------------------------------------------------
int __fastcall TListViewPattern::DoCellHgt(TTableView *Sender, int iCellIndex)
{
return CELL_HEIGHT;
}
//---------------------------------------------------------------------------
int __fastcall TListViewPattern::DoMDNum(TTableView *Sender)
{
NULL_RETURN0(m_LstParttern)
return m_LstParttern->size();
}
//---------------------------------------------------------------------------
int __fastcall TListViewPattern::DoCellData(TStateBtn *sender)
{
NULL_RETURN0(m_LstParttern)
sender->SetData((void *)((*m_LstParttern)[sender->Index]));
}
//---------------------------------------------------------------------------
void __fastcall TListViewPattern::DoCellDraw(TStateBtn *sender, int BsTmp, TRect rtTmp, TCanvas *pCanvas)
{
TStateBtn *pBtn = (TStateBtn *)sender;
TTextureInfo *pPtInfo = (TTextureInfo*)pBtn->m_Data;
if( Bs_NORMAL==BsTmp ) {
pCanvas->Brush->Color = LP_ITEM_DEF;
}else if( Bs_ENTER==BsTmp ){
pCanvas->Brush->Color = LP_ITEM_OVER;
}else if( Bs_DOWN==BsTmp ){
pCanvas->Brush->Color = LP_ITEM_SELECTED;
}
if( BsTmp==Bs_NORMAL || BsTmp==Bs_ENTER || BsTmp==Bs_DOWN ) {
pCanvas->FillRect(rtTmp);
int iLeft, iTop;
TSize sizeFont;
String strText;
pCanvas->Brush->Style = bsClear;
pCanvas->Font->Color = GetSegmentColor( pPtInfo->segType, 0, false );
//绘制乐器
if( !m_bChan9 ) strText = GM_INSTRUMENT[pPtInfo->prog];
else strText = L"GM鼓";
sizeFont = pCanvas->TextExtent( strText );
iLeft = LEFT_CAPTION+(WIDTH_PROG(Width)-sizeFont.Width)/2;
iTop = rtTmp.Top+(rtTmp.Height()-sizeFont.Height)/2;
pCanvas->TextOutW(iLeft, iTop, strText);
pCanvas->Pen->Color = LINE_COLOR;
pCanvas->MoveTo( LEFT_CAPTION+WIDTH_PROG(Width)+WIDTH_LINE/2 , rtTmp.Top);
pCanvas->LineTo( LEFT_CAPTION+WIDTH_PROG(Width)+WIDTH_LINE/2, rtTmp.Bottom);
String oriFontName = pCanvas->Font->Name;
pCanvas->Font->Name = "Times New Roman";
//绘制风格id号
char styleID[256];
if( pPtInfo->idLoc==0 )
sprintf(styleID, "[%d]", pPtInfo->idStyle);
else if( pPtInfo->idLoc==1 )
sprintf(styleID, "[S%d]", pPtInfo->idStyle);
else if( pPtInfo->idLoc!=(UINT)-1 )
sprintf( styleID, "[L%d] ", LOWORD(pPtInfo->idStyle) );
iLeft = LEFT_STYLE(Width);
strText = styleID;
sizeFont = pCanvas->TextExtent( strText );
iLeft = LEFT_STYLE(Width)+(WIDTH_STYLE(Width)-sizeFont.Width)/2;
iTop = rtTmp.Top+(rtTmp.Height()-sizeFont.Height)/2;
pCanvas->TextOutW(iLeft, iTop, strText);
pCanvas->Pen->Color = LINE_COLOR;
pCanvas->MoveTo( LEFT_STYLE(Width)+WIDTH_STYLE(Width)+WIDTH_LINE/2 , rtTmp.Top);
pCanvas->LineTo( LEFT_STYLE(Width)+WIDTH_STYLE(Width)+WIDTH_LINE/2 , rtTmp.Bottom);
//绘制伴奏类型
char segName[256];
sprintf(segName, "[%s-%d]", NAME_SEG[pPtInfo->segType], pPtInfo->segNo+1);
strText = segName;
sizeFont = pCanvas->TextExtent( strText );
iLeft = LEFT_SEG(Width)+(WIDTH_SEG(Width)-sizeFont.Width)/2;
iTop = rtTmp.Top+(rtTmp.Height()-sizeFont.Height)/2;
pCanvas->TextOutW(iLeft, iTop, strText);
pCanvas->Pen->Color = LINE_COLOR;
pCanvas->MoveTo( LEFT_SEG(Width)+WIDTH_SEG(Width)+WIDTH_LINE/2 , rtTmp.Top);
pCanvas->LineTo( LEFT_SEG(Width)+WIDTH_SEG(Width)+WIDTH_LINE/2 , rtTmp.Bottom);
pCanvas->Font->Name = oriFontName;
}
}
//---------------------------------------------------------------------------
void __fastcall TListViewPattern::DoIconDraw(TStateBtn *sender, int BsTmp, TRect rtTmp, TCanvas *pCanvas)
{
TStateBtn *pBtn = (TStateBtn *)sender;
TStateBtn *pCell = pBtn->m_PAR;
TTextureInfo *info = (TTextureInfo*)pCell->m_Data;
TPngImage *pIMG = NULL;
String sHint;
if(sender->Index==0) {
pIMG = info->bCollected?pngCol:pngUnCol;
if(BsTmp==Bs_ENTER ) {
sHint = info->bCollected ? "点击取消收藏" : "点击收藏";
}
}
else if(sender->Index==1) {
TPROSTYLE* styleInfo = GetStyleInfo( info->idLoc, info->idStyle );
if( styleInfo && styleInfo->idLoc==0 && styleInfo->pOrigin->cost>0 ) {
pIMG = pngCharge;
if(BsTmp==Bs_ENTER ) {
sHint = "收费:";
sHint += IntToStr( styleInfo->pOrigin->cost );
sHint += "唱作音符";
}
}
}
if( pIMG ) {
int iWidth = pIMG->Width/3;
int nTrans = BsTmp==Bs_NORMAL ? 0
: BsTmp==Bs_ENTER ? (-iWidth)
: BsTmp==Bs_DOWN ? (-2*iWidth)
: (-3*iWidth);
if( Bs_NORMAL==BsTmp || Bs_ENTER==BsTmp || Bs_DOWN==BsTmp ) {
HRGN rgnClip = CreateRectRgn( rtTmp.Left, rtTmp.Top,
rtTmp.Left+rtTmp.Width(), rtTmp.Top+rtTmp.Height() );
SelectClipRgn( pCanvas->Handle, rgnClip );
pCanvas->Draw(rtTmp.Left+nTrans, rtTmp.Top, pIMG);
SelectClipRgn( pCanvas->Handle, NULL );
DeleteObject(rgnClip);
}
}
if( sHint.Length() ){
m_btnHint = sender;
Hint = sHint;
}
else if(m_btnHint==sender ){
m_btnHint = NULL;
Hint = "";
Application->CancelHint();
}
}
//---------------------------------------------------------------------------
int __fastcall TListViewPattern::DoIconsNum(TStateBtn *parent)
{
return 2;
}
//---------------------------------------------------------------------------
int __fastcall TListViewPattern::DoIconsBounds(TStateBtn *sender, TRect &rtBounds)
{
int iLeft, iTop, iWidth, iHeight;
if(sender->Index==0) {
iLeft = Width - WIDTH_SB - WIDTH_IMG_COL;
iTop = (CELL_HEIGHT - 15) / 2;
iWidth = 21;
iHeight = 15;
}
else if(sender->Index==1) {
iLeft = LEFT_SEG(Width) - WIDTH_IMG_CHARGE - 1;
iTop = (CELL_HEIGHT - pngCharge->Height)/2;
iWidth = pngCharge->Width/3;
iHeight = pngCharge->Height;
}
rtBounds = TRect(iLeft, iTop, iLeft+iWidth, iTop+iHeight);
}
//---------------------------------------------------------------------------
void __fastcall TListViewPattern::DoCellLClick(TStateBtn *sender)
{
TStateBtn *pBtn = (TStateBtn *)sender;
if( m_pPtInfo!=(TTextureInfo*)pBtn->m_Data ){
if( m_nPlayIndex!=this->IndSel )
f_MM_Stop();
m_pPtInfo = (TTextureInfo *)pBtn->m_Data;
if( FOnTextureChanged )
FOnTextureChanged((TObject*)m_pPtInfo);
}
}
//---------------------------------------------------------------------------
void __fastcall TListViewPattern::DoCellDBClick(TStateBtn *sender)
{
TTextureInfo *pPtInfo = NULL;
if( sender ) {
TStateBtn *pBtn = (TStateBtn *)sender;
pPtInfo = (TTextureInfo*)pBtn->m_Data;
m_nPlayIndex = pBtn->Index;
}
else {
pPtInfo = m_pPtInfo;
}
if( pPtInfo ){
TPROSTYLE* info = GetStyleInfo( pPtInfo->idLoc, pPtInfo->idStyle );
if( !info )
return;
int stype = pPtInfo->segType,
sno = pPtInfo->segNo,
iChno = -1,
nStageNum = m_lstStages ? m_lstStages->size() : 1,
nBarCount = 0,
iPlayBar = m_iPlayBar,
iFBar = -1;
TStage* aStages = new TStage[nStageNum];
for( int i=0; i<nStageNum; i++ ){
TStage* pStage = &aStages[i];
if( m_lstStages ){
TStage* pTemp = (*m_lstStages)[i];
memcpy( pStage, pTemp, sizeof(TStage) );
if( pTemp->aChords ){
pStage->aChords = new TBarChords[pTemp->nBarNum];
memcpy( pStage->aChords, pTemp->aChords, sizeof(TBarChords)*pTemp->nBarNum );
}
}
else{
int seed = time(NULL);
int barNum = 4;
if( stype>=SEGTYPE_INTRO ){
if( info->idLoc==0 ) {
if( stype==SEGTYPE_INTRO )
barNum = info->pOrigin->detail.aIntroBars[sno];
else
barNum = info->pOrigin->detail.aEndingBars[sno];
}
else if( info->idLoc==1 )
barNum = info->pShare->aIEBars[stype][sno];
else
barNum = info->pLocal->aIEBars[stype][sno];
}
pStage->nBarNum = barNum;
int key = g_iMelodyKey;
if( key<0 || key>11 )
key = seed % 12;
pStage->iSegKey = key;
pStage->iSegType = stype;
char cType = (seed>>1) % 2;
int iPreset = (seed>>2) % 4;
aStages->aChords = new TBarChords[barNum];
for( int j=0; j<barNum; j++ ){
char chordType = u_arrChordPreset[cType][iPreset][j] % 4;
char chordKey = u_arrChordPreset[cType][iPreset][j] / 4;
aStages->aChords[j].iKey[0]
= aStages->aChords[j].iKey[1]
= aStages->aChords[j].iKey[2]
= aStages->aChords[j].iKey[3] = chordKey;
aStages->aChords[j].iType[0]
= aStages->aChords[j].iType[1]
= aStages->aChords[j].iType[2]
= aStages->aChords[j].iType[3] = chordType;
}
}
if( pStage->iSegType==stype ){
pStage->nTrkNum = 1;
pStage->aTracks = new TComposeTrack;
TComposeTrack* pTrack = pStage->aTracks;
pTrack->iProg = pPtInfo->prog;
pTrack->nVol = pPtInfo->vol;
if( info->idLoc==0 ){
pTrack->iStyleLoc = 0;
pTrack->iStyleId = info->idStyle;
pTrack->iSegNo = sno;
iChno = pTrack->iChanSpec = pTrack->iChanNo
= info->pOrigin->detail.tracks[stype][sno][pPtInfo->chNo].no;
}
else if( info->idLoc==1 ){
TSTYLESHARE* pShare = info->pShare;
TSHARETRACKREF& rRef = pShare->trkRef[stype][sno][pPtInfo->chNo];
pTrack->iStyleLoc = 0;
pTrack->iStyleId = rRef.idStyle;
pTrack->iSegNo = rRef.segNo;
iChno = pTrack->iChanSpec = pTrack->iChanNo = rRef.chan;
}
else{
TSTYLELOCAL* pLocal = info->pLocal;
TTRACKREF& rRef = pLocal->trkRef[stype][sno][pPtInfo->chNo];
pTrack->iStyleLoc = rRef.idLoc;
pTrack->iStyleId = rRef.idStyle;
pTrack->iSegNo = rRef.segNo;
iChno = pTrack->iChanSpec = pTrack->iChanNo = rRef.chan;
}
if( iFBar<0 )
iFBar = nBarCount;
}
nBarCount += pStage->nBarNum;
}
if( iPlayBar>=0 && iFBar>iPlayBar )
iPlayBar = iFBar;
int len = 1000000;
BYTE* data = new BYTE[len];
HRESULT ret = f_CM_Compose( &len, data, g_iMelodyTimeSignature, g_nMelodyTempo,
nStageNum, aStages, false, NULL, NULL );
if( ret==0 ){
f_MM_LoadDemo( data, len );
char* strFile = m_iFont==0xFF ? NULL : m_iFont<0x80 ? g_lstFonts[m_iFont]->strFileName
: g_lstVSTi[m_iFont-0x80]->strFileName;
f_MM_PlayDemo( NULL, iPlayBar, -1, m_iProg, m_iFont, strFile );
}
else
DebugPrint( "Compose error: %d", ret );
delete[] data;
SAFE_DELETE_ARRAY(aStages);
}
}
//---------------------------------------------------------------------------
void __fastcall TListViewPattern::DoIconLClick(TStateBtn *sender)
{
if(sender->Index==0) {
TStateBtn *pBtn = (TStateBtn *)sender;
TStateBtn *pCell = pBtn->m_PAR;
TTextureInfo *pPtInfo = (TTextureInfo *)pCell->m_Data;
pPtInfo->bCollected = !pPtInfo->bCollected;
TPROSTYLE* info = GetStyleInfo( pPtInfo->idLoc, pPtInfo->idStyle );
char chan = info->idLoc==0 ?
info->pOrigin->detail.tracks[pPtInfo->segType][pPtInfo->segNo][pPtInfo->chNo].no
: info->idLoc==1 ?
info->pShare->trkRef[pPtInfo->segType][pPtInfo->segNo][pPtInfo->chNo].chan
: info->pLocal->trkRef[pPtInfo->segType][pPtInfo->segNo][pPtInfo->chNo].chan;
SetFavorTexture( pPtInfo->idLoc, pPtInfo->idStyle, pPtInfo->segType, pPtInfo->segNo,
chan, pPtInfo->bCollected );
// InsColSet( pInsRefTmp, pPtInfo->bCollected );
pBtn->Paint();
}
}
//---------------------------------------------------------------------------
int __fastcall TListViewPattern::DoMouseWheel(TObject *Sender)
{
TListViewBase::DoMouseWheel(Sender);
// m_Hint->ReleaseHandle();
}
//---------------------------------------------------------------------------
//void __fastcall TListViewPattern::HintTimerProc(System::TObject* Sender)
//{
// if( m_HintTimer )
// m_HintTimer->Enabled = false;
// if( m_Hint && HintStr.Length()>0 ){
// m_Hint->ShowHintWindow( ClientToScreen(m_ptMove), HintStr );
// }
//}
//// ---------------------------------------------------------------------------