/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include
#include "HeadSpin.h"
#include "max.h"
#include "resource.h"
#include "hsTemplates.h"
#include "hsResMgr.h"
#include "plQuality.h"
#include "pnMessage/plRefMsg.h"
#include "plSurface/hsGMaterial.h"
#include "MaxMain/plMaxNode.h"
#include "MaxConvert/hsMaterialConverter.h"
#include "plComponent.h"
#include "plComponentReg.h"
#include "plGrassComponent.h"
#include "plSurface/plGrassShaderMod.h"
#include "pnKeyedObject/plUoid.h"
#include "pnMessage/plObjRefMsg.h"
#include "MaxMain/plPluginResManager.h"
void DummyCodeIncludeFuncGrassShader()
{
}
class GrassCompDlgProc : public ParamMap2UserDlgProc
{
public:
GrassCompDlgProc() {}
~GrassCompDlgProc() {}
protected:
void ISetToWave(int wave, HWND hWnd, IParamBlock2 *pb, IParamMap2 *map)
{
HWND cbox = GetDlgItem(hWnd, IDC_GRASS_WAVE);
SendMessage(cbox, CB_SETCURSEL, wave, 0);
pb->SetValue(ParamID(plGrassComponent::kWave), 0, wave);
pb->SetValue(ParamID(plGrassComponent::kDistX), 0, pb->GetFloat(ParamID(plGrassComponent::kDistXTab), 0, wave));
pb->SetValue(ParamID(plGrassComponent::kDistY), 0, pb->GetFloat(ParamID(plGrassComponent::kDistYTab), 0, wave));
pb->SetValue(ParamID(plGrassComponent::kDistZ), 0, pb->GetFloat(ParamID(plGrassComponent::kDistZTab), 0, wave));
pb->SetValue(ParamID(plGrassComponent::kDirX), 0, pb->GetFloat(ParamID(plGrassComponent::kDirXTab), 0, wave));
pb->SetValue(ParamID(plGrassComponent::kDirY), 0, pb->GetFloat(ParamID(plGrassComponent::kDirYTab), 0, wave));
pb->SetValue(ParamID(plGrassComponent::kSpeed), 0, pb->GetFloat(ParamID(plGrassComponent::kSpeedTab), 0, wave));
map->Invalidate();
}
public:
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
int id = LOWORD(wParam);
int code = HIWORD(wParam);
IParamBlock2 *pb = map->GetParamBlock();
HWND cbox = NULL;
int selection;
switch (msg)
{
case WM_INITDIALOG:
cbox = GetDlgItem(hWnd, IDC_GRASS_WAVE);
SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)"1");
SendMessage(cbox, CB_ADDSTRING, 1, (LPARAM)"2");
SendMessage(cbox, CB_ADDSTRING, 2, (LPARAM)"3");
SendMessage(cbox, CB_ADDSTRING, 3, (LPARAM)"4");
selection = pb->GetInt(plGrassComponent::kWave);
ISetToWave(selection, hWnd, pb, map);
return TRUE;
case WM_COMMAND:
case CC_SPINNER_CHANGE:
int wave = SendMessage(GetDlgItem(hWnd, IDC_GRASS_WAVE), CB_GETCURSEL, 0, 0);
if (id == IDC_GRASS_WAVE)
{
if (wave != pb->GetInt(ParamID(plGrassComponent::kWave)))
ISetToWave(wave, hWnd, pb, map);
}
else if (id == IDC_GRASS_DIST_X || id == IDC_GRASS_DIST_X_SPIN)
pb->SetValue(plGrassComponent::kDistXTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDistX)), wave);
else if (id == IDC_GRASS_DIST_Y || id == IDC_GRASS_DIST_Y_SPIN)
pb->SetValue(plGrassComponent::kDistYTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDistY)), wave);
else if (id == IDC_GRASS_DIST_Z || id == IDC_GRASS_DIST_Z_SPIN)
pb->SetValue(plGrassComponent::kDistZTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDistZ)), wave);
else if (id == IDC_GRASS_DIR_X || id == IDC_GRASS_DIR_X_SPIN)
pb->SetValue(plGrassComponent::kDirXTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDirX)), wave);
else if (id == IDC_GRASS_DIR_Y || id == IDC_GRASS_DIR_Y_SPIN)
pb->SetValue(plGrassComponent::kDirYTab, 0, pb->GetFloat(ParamID(plGrassComponent::kDirY)), wave);
else if (id == IDC_GRASS_SPEED || id == IDC_GRASS_SPEED_SPIN)
pb->SetValue(plGrassComponent::kSpeedTab, 0, pb->GetFloat(ParamID(plGrassComponent::kSpeed)), wave);
return TRUE;
}
return FALSE;
}
void DeleteThis() {}
};
static GrassCompDlgProc gGrassCompDlgProc;
CLASS_DESC(plGrassComponent, gGrassDesc, "Grass", "Grass", COMP_TYPE_SHADERS, GRASS_COMPONENT_CLASS_ID)
ParamBlockDesc2 gGrassBk
(
plComponent::kBlkComp, _T("Grass"), 0, &gGrassDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
//Roll out
IDD_COMP_GRASS, IDS_COMP_GRASS_ROLL, 0, 0, &gGrassCompDlgProc,
plGrassComponent::kWave, _T("Wave"), TYPE_INT, 0, 0,
p_default, 0,
end,
plGrassComponent::kDistX, _T("DistX"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_GRASS_DIST_X, IDC_GRASS_DIST_X_SPIN, 0.1,
end,
plGrassComponent::kDistY, _T("DistY"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_GRASS_DIST_Y, IDC_GRASS_DIST_Y_SPIN, 0.1,
end,
plGrassComponent::kDistZ, _T("DistZ"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_GRASS_DIST_Z, IDC_GRASS_DIST_Z_SPIN, 0.1,
end,
plGrassComponent::kDirX, _T("DirX"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_GRASS_DIR_X, IDC_GRASS_DIR_X_SPIN, 0.1,
end,
plGrassComponent::kDirY, _T("DirY"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_GRASS_DIR_Y, IDC_GRASS_DIR_Y_SPIN, 0.1,
end,
plGrassComponent::kSpeed, _T("Speed"), TYPE_FLOAT, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT,
IDC_GRASS_SPEED, IDC_GRASS_SPEED_SPIN, 0.1,
end,
plGrassComponent::kDistXTab, _T("DistXTab"), TYPE_FLOAT_TAB, plGrassShaderMod::kNumWaves, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
end,
plGrassComponent::kDistYTab, _T("DistYTab"), TYPE_FLOAT_TAB, plGrassShaderMod::kNumWaves, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
end,
plGrassComponent::kDistZTab, _T("DistZTab"), TYPE_FLOAT_TAB, plGrassShaderMod::kNumWaves, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
end,
plGrassComponent::kDirXTab, _T("DirXTab"), TYPE_FLOAT_TAB, plGrassShaderMod::kNumWaves, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
end,
plGrassComponent::kDirYTab, _T("DirYTab"), TYPE_FLOAT_TAB, plGrassShaderMod::kNumWaves, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
end,
plGrassComponent::kSpeedTab, _T("SpeedTab"), TYPE_FLOAT_TAB, plGrassShaderMod::kNumWaves, 0, 0,
p_default, 0.0,
p_range, -10.0, 10.0,
end,
end
);
plGrassComponent::plGrassComponent() : fShader(nil)
{
fClassDesc = &gGrassDesc;
fClassDesc->MakeAutoParamBlocks(this);
}
hsBool plGrassComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
{
fShader = TRACKED_NEW plGrassShaderMod();
plLoadMask loadMask;
int qual = 1;
int cap = plQuality::kPS_1_1;
plLoadMask::ComputeRepMasks(1, &qual, &cap, &loadMask);
plKey modKey = hsgResMgr::ResMgr()->NewKey(IGetUniqueName(node), fShader, node->GetLocation(), loadMask);
int i;
for (i = 0; i < plGrassShaderMod::kNumWaves; i++)
{
fShader->fWaves[i].fDistX = fCompPB->GetFloat(ParamID(kDistXTab), 0, i);
fShader->fWaves[i].fDistY = fCompPB->GetFloat(ParamID(kDistYTab), 0, i);
fShader->fWaves[i].fDistZ = fCompPB->GetFloat(ParamID(kDistZTab), 0, i);
fShader->fWaves[i].fDirX = fCompPB->GetFloat(ParamID(kDirXTab), 0, i);
fShader->fWaves[i].fDirY = fCompPB->GetFloat(ParamID(kDirYTab), 0, i);
fShader->fWaves[i].fSpeed = fCompPB->GetFloat(ParamID(kSpeedTab), 0, i);
}
// Add a ref to the shader.
fShader->GetKey()->RefObject();
return true;
}
hsBool plGrassComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
plObjRefMsg* refMsg = TRACKED_NEW plObjRefMsg(node->GetKey(), plRefMsg::kOnRequest, -1, plObjRefMsg::kModifier);
hsgResMgr::ResMgr()->AddViaNotify(fShader->GetKey(), refMsg, plRefFlags::kActiveRef);
hsTArray mats;
hsMaterialConverter::Instance().CollectConvertedMaterials(hsMaterialConverter::Instance().GetBaseMtl(node), mats);
hsgResMgr::ResMgr()->SendRef(mats[0]->GetKey(), TRACKED_NEW plGenRefMsg(fShader->GetKey(), plRefMsg::kOnRequest, 0, plGrassShaderMod::kRefMaterial), plRefFlags::kActiveRef);
return TRUE;
}
hsBool plGrassComponent::DeInit(plMaxNode* node, plErrorMsg* pErrMsg)
{
if( fShader )
fShader->GetKey()->UnRefObject();
fShader = nil;
return true;
}
plGrassShaderMod* plGrassComponent::GetShader(INode* node)
{
if( !node )
return nil;
plComponentBase *comp = ((plMaxNodeBase*)node)->ConvertToComponent();
if( !comp )
return nil;
if( comp->ClassID() != GRASS_COMPONENT_CLASS_ID )
return nil;
plGrassComponent *shader = (plGrassComponent*)comp;
return shader->fShader;
}
plGrassShaderMod* plGrassComponent::GetShaderNode(plMaxNode* node)
{
if( !node )
return nil;
int n = node->NumAttachedComponents();
int i;
for( i = 0; i < n; i++ )
{
plComponentBase* comp = node->GetAttachedComponent(i);
if( comp && (comp->ClassID() == GRASS_COMPONENT_CLASS_ID) )
{
plGrassComponent* shader = (plGrassComponent*)comp;
return shader->fShader;
}
}
return nil;
}