1146 lines
28 KiB
C++
1146 lines
28 KiB
C++
/*
|
|
SGameFxSwordSlash.cpp
|
|
검광 표시 Fx
|
|
|
|
Created 2006/04, by JiYoung
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "SGameFxSwordSlash.h"
|
|
#include "KResourceDXDynamic.h"
|
|
#include "KViewPort.h"
|
|
#include "KSeqModel.h"
|
|
#include "SGameAvatarEx.h"
|
|
|
|
#include <sys/stat.h>
|
|
#include <io.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "SDebug_Util.h"
|
|
|
|
#include "SGameWorld.h"
|
|
#include "SGameSystem.h"
|
|
|
|
//====================================================
|
|
// Utilities
|
|
//====================================================
|
|
|
|
extern SGameSystem* g_pCurrentGameSystem;
|
|
|
|
namespace {
|
|
DWORD interpolateColor(DWORD colorA, DWORD colorB, float div) // A에서 B까지 [0, 1] 보간
|
|
// return = colorA*(1-div) + colorB*div
|
|
{
|
|
float a0,r0,g0,b0;
|
|
float a1,r1,g1,b1;
|
|
float invdiv=1.f-div;
|
|
|
|
a0=(float)((colorA>>24)&0xff);
|
|
r0=(float)((colorA>>16)&0xff);
|
|
g0=(float)((colorA>>8)&0xff);
|
|
b0=(float)(colorA&0xff);
|
|
|
|
a1=(float)((colorB>>24)&0xff);
|
|
r1=(float)((colorB>>16)&0xff);
|
|
g1=(float)((colorB>>8)&0xff);
|
|
b1=(float)(colorB&0xff);
|
|
|
|
DWORD a, r, g, b;
|
|
a = (DWORD)(a0*invdiv + a1*div);
|
|
r = (DWORD)(r0*invdiv + r1*div);
|
|
g = (DWORD)(g0*invdiv + g1*div);
|
|
b = (DWORD)(b0*invdiv + b1*div);
|
|
|
|
if (a>0xff) a=0xff;
|
|
if (r>0xff) r=0xff;
|
|
if (g>0xff) g=0xff;
|
|
if (b>0xff) b=0xff;
|
|
|
|
return (a<<24) | (r<<16) | (g<<8) | b;
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================
|
|
// Trail rendering용 primitive
|
|
//=============================================
|
|
|
|
const int TrailPrimitive_defaultTrailWidth=10.0f;
|
|
|
|
TrailPrimitive::TrailPrimitive(int maxTrails) : KMeshPrimitive()
|
|
{
|
|
indexBuffer=NULL;
|
|
vertexBuffer=NULL;
|
|
vertexCount=indexCount=polygonCount=0;
|
|
maxTrailCount=0;
|
|
|
|
trailWidth=TrailPrimitive_defaultTrailWidth;
|
|
|
|
// 적당한 색 & UV
|
|
color0[NODE_NEWEST_BOTTOM]=0x40ffffff;
|
|
color1[NODE_NEWEST_BOTTOM]=0x00404040;
|
|
u[NODE_NEWEST_BOTTOM]=0.0f;
|
|
v[NODE_NEWEST_BOTTOM]=0.0f;
|
|
|
|
color0[NODE_NEWEST_TOP]=0xc0ffffff;
|
|
color1[NODE_NEWEST_TOP]=0x00808080;
|
|
u[NODE_NEWEST_TOP]=0.0f;
|
|
v[NODE_NEWEST_TOP]=1.0f;
|
|
|
|
color0[NODE_OLDEST_BOTTOM]=0x00c0c0c0;
|
|
color1[NODE_OLDEST_BOTTOM]=0x00404040;
|
|
u[NODE_OLDEST_BOTTOM]=1.0f;
|
|
v[NODE_OLDEST_BOTTOM]=0.0f;
|
|
|
|
color0[NODE_OLDEST_TOP]=0x00808080;
|
|
color1[NODE_OLDEST_TOP]=0x00808080;
|
|
u[NODE_OLDEST_TOP]=1.0f;
|
|
v[NODE_OLDEST_TOP]=1.0f;
|
|
|
|
if (maxTrails>0) init(maxTrails);
|
|
|
|
rebuildPolygon=true;
|
|
m_bRight = true;
|
|
trailRunning = false;
|
|
}
|
|
|
|
|
|
TrailPrimitive::~TrailPrimitive()
|
|
{
|
|
close();
|
|
}
|
|
|
|
|
|
void TrailPrimitive::init(int maxTrails)
|
|
{
|
|
assert( (indexBuffer==NULL) && (vertexBuffer==NULL) );
|
|
|
|
if (maxTrails<=0) return;
|
|
|
|
// Get sizes
|
|
vertexCount=maxTrails*2; // each node has 2 vertexes
|
|
polygonCount=(maxTrails-1)*4; // Triangle strip : each vertex pair makes 2 triangles, and 2 sides
|
|
indexCount=3*polygonCount; // Triangle strip.. but render as triangle set
|
|
maxTrailCount=maxTrails;
|
|
if (trailCount>maxTrailCount) trailCount=maxTrailCount;
|
|
|
|
|
|
// Make index buffer and vertex buffer.
|
|
if (!createBuffers()) return;
|
|
|
|
// WORKAROUND : to prevent 'smartptr burst' on deleting m_spIB / m_spVB.
|
|
indexBuffer->AddRef();
|
|
vertexBuffer->AddRef();
|
|
|
|
// init trail nodes
|
|
setTrailNodeCount(maxTrailCount);
|
|
|
|
// Notify polygon informations to parent
|
|
SetIndexBuffer(indexBuffer); // set m_spIB
|
|
SetVertexBuffer(vertexBuffer); // set m_spVB
|
|
|
|
SetPrimitivesCount(polygonCount);
|
|
|
|
|
|
// Init parent parameters
|
|
K3DMaterial *tempMaterial=new K3DMaterial;
|
|
tempMaterial->Power=1.0f;
|
|
SetMaterial(tempMaterial);
|
|
|
|
K3DMatrix *tempMatrix=new K3DMatrix;
|
|
K3DMatrixIdentity(*tempMatrix);
|
|
SetUVTransform(tempMatrix);
|
|
|
|
// m_pTransform=new K3DMatrix;
|
|
// K3DMatrixIdentity(m_pTransform);
|
|
|
|
// Set basic rendering parameters
|
|
SetTransparent(true); // Add to Transparent primitive queue
|
|
SetBlendMode(K3DMaterial::MBM_ALPHATEX); // Set render mode
|
|
SetVisibility(1.0f); // Master alpha value
|
|
|
|
rebuildPolygon=true;
|
|
}
|
|
|
|
|
|
void TrailPrimitive::close()
|
|
{
|
|
// clear buffers
|
|
SetIndexBuffer(NULL);
|
|
SetVertexBuffer(NULL);
|
|
SetPrimitivesCount(0);
|
|
|
|
if (indexBuffer!=NULL) { // SAFE_RELEASE(indexBuffer);
|
|
indexBuffer->Release(); // Release() will delete SELF
|
|
indexBuffer=NULL;
|
|
}
|
|
|
|
if (vertexBuffer!=NULL) {
|
|
vertexBuffer->Release();
|
|
vertexBuffer=NULL;
|
|
}
|
|
|
|
vertexCount=indexCount=polygonCount=0;
|
|
maxTrailCount=0;
|
|
trailWidth=TrailPrimitive_defaultTrailWidth;
|
|
|
|
K3DMatrix *tempMatrix=GetUVTransform();
|
|
SetUVTransform(NULL);
|
|
SAFE_DELETE(tempMatrix);
|
|
|
|
K3DMaterial *tempMaterial=GetMaterial();
|
|
SetMaterial(NULL);
|
|
SAFE_DELETE(tempMaterial);
|
|
|
|
// SAFE_DELETE(m_pTransform);
|
|
|
|
trails.clear();
|
|
|
|
//
|
|
// Note : Colors and UVs are not cleared
|
|
//
|
|
|
|
rebuildPolygon=true;
|
|
}
|
|
|
|
|
|
bool TrailPrimitive::buildPolygon()
|
|
// 실제 버텍스 정보 만들기
|
|
{
|
|
if (trails.size()<2) {
|
|
vertexBuffer->setVertexCount(0);
|
|
indexBuffer->setIndexCount(0);
|
|
SetPrimitivesCount(0);
|
|
|
|
return false;
|
|
}
|
|
|
|
void *p;
|
|
int size=0;
|
|
DynamicVertex *v;
|
|
|
|
// Make vertex buffers
|
|
deque<TrailNode>::iterator it;
|
|
size_t i;
|
|
|
|
vertexBuffer->Lock(&p, size,D3DLOCK_NOSYSLOCK /*| D3DLOCK_DISCARD*/);
|
|
if (p!=NULL) {
|
|
// Build vertex parameters <- 임시! 나중에 parameterize시킬 것
|
|
v=(DynamicVertex *)p;
|
|
it=trails.begin();
|
|
for (i=0; i<trails.size(); i++) {
|
|
// bottom vertex
|
|
v->pos.x = it->base.x;
|
|
v->pos.y = it->base.y;
|
|
v->pos.z = it->base.z;
|
|
v++;
|
|
|
|
// top vertex
|
|
v->pos.x = it->top.x;
|
|
v->pos.y = it->top.y;
|
|
v->pos.z = it->top.z;
|
|
v++;
|
|
|
|
it++;
|
|
}
|
|
|
|
vertexBuffer->Unlock();
|
|
}
|
|
|
|
// Set geometry counts
|
|
size=trailCount;
|
|
if (size > (int)trails.size()) size=(int)trails.size();
|
|
|
|
vertexBuffer->setVertexCount(size*2); // 2 vertexes per a node
|
|
indexBuffer->setIndexCount((size-1)*3*4); // 3-vertexes and 4-polygons per segment
|
|
SetPrimitivesCount((size-1)*4); // 4 polygons per each segment
|
|
|
|
return true;
|
|
}
|
|
|
|
void TrailPrimitive::Render( KViewportObject *viewport, class K3DRenderDevice *dev, bool bUseAccum )
|
|
{
|
|
if (rebuildPolygon) {
|
|
// color, UV등이 바뀌면 파라미터를 다시 만든다
|
|
initPolygon();
|
|
rebuildPolygon=false;
|
|
}
|
|
|
|
if (buildPolygon()) {
|
|
// Set rendering parameters
|
|
//SetTransparent(true); // Add to Transparent primitive queue
|
|
//SetBlendMode(K3DMaterial::MBM_ALPHATEX); // Set render mode
|
|
|
|
SetVisibility(1.0f); // Master alpha value
|
|
KMeshPrimitive::Render(viewport, dev, bUseAccum);
|
|
}
|
|
}
|
|
|
|
|
|
void TrailPrimitive::runTrail(bool bOn)
|
|
{
|
|
if (bOn==true && trailRunning==false) {
|
|
// Clear possible previous trails
|
|
clearTrails();
|
|
}
|
|
trailRunning=bOn;
|
|
}
|
|
|
|
|
|
void TrailPrimitive::addTrails(int count, DWORD starttime, DWORD endtime, K3DMatrix *matrix, bool isBow, float angle)
|
|
{
|
|
if (!trailRunning || matrix==NULL) {
|
|
purgeTrails(count);
|
|
return;
|
|
}
|
|
|
|
int i;
|
|
TrailNode tn;
|
|
K3DVector vBottom, vTop;
|
|
|
|
vBottom.x=vBottom.y=vBottom.z=0.f;
|
|
|
|
if( m_bRight ) //오른손
|
|
vTop.x=-trailWidth;
|
|
else //왼손
|
|
vTop.x=+trailWidth;
|
|
|
|
vTop.y=vTop.z=0.f;
|
|
|
|
|
|
if ( isBow )
|
|
{
|
|
SGameWorld* pGameWorld = dynamicCast<SGameWorld*>(g_pCurrentGameSystem->GetGame());
|
|
float angle1 = pGameWorld->m_pGameCamera->getAngleX();
|
|
//float angle2;//atan2f(matrix->m31-vBottom.y, matrix->m30-vBottom.x );
|
|
|
|
float camera_z = pGameWorld->m_pGameCamera->getAngleZ() - sMathUtil::degree90;
|
|
if (camera_z>K3D_PI) camera_z = camera_z -K3D_PI*2;
|
|
|
|
|
|
float a1, a2;
|
|
a1 = fmod(camera_z, K3D_PI*2);
|
|
a2 = fmod(angle, K3D_PI*2);
|
|
if (fabs(a1 - a2) > fabs(a1 - a2 - K3D_PI*2))
|
|
a2 += K3D_PI*2;
|
|
else if(fabs(a1 - a2) > fabs(a1 - a2 + K3D_PI*2))
|
|
a2 -= K3D_PI*2;
|
|
|
|
float minval = min(fabs(a1 - a2), min(fabs(a1 - a2 + K3D_PI*2), fabs(a1 - a2 - K3D_PI*2))); // 0~3.14
|
|
if (minval> K3D_PI/2 ) minval = K3D_PI-minval; // 0~1.57
|
|
minval = K3D_PI/2 - minval; // 1.57 ~ 0
|
|
|
|
//if (camera_z > char_z) angle2 = camera_z - char_z;
|
|
//else angle2 = char_z - camera_z;
|
|
//if (angle2>K3D_PI/2) angle2 = K3D_PI -angle2;
|
|
//if (angle2<-(K3D_PI/2)) angle2 = angle2 + K3D_PI;
|
|
|
|
|
|
|
|
float delta = max( angle1,minval);
|
|
K3DMatrix matro;
|
|
K3DMatrixRotationZ ( matro,delta );
|
|
K3DVectorTransform(vTop, vTop, matro);
|
|
// K3DMatrixRotationZ ( *matrix, 1.57f );
|
|
// vTop.x = trailWidth * cos(pGameWorld->m_pGameCamera->getAngleX());
|
|
// vBottom.x = trailWidth * sin(pGameWorld->m_pGameCamera->getAngleX());
|
|
}
|
|
|
|
|
|
for (i=0; i<count; i++) {
|
|
tn.matrix=matrix[i];
|
|
K3DVectorTransform(tn.base, vBottom, tn.matrix);
|
|
K3DVectorTransform(tn.top, vTop, tn.matrix);
|
|
tn.time=(endtime-starttime)*i/count + starttime;
|
|
|
|
trails.push_back(tn);
|
|
if ((int)trails.size() > trailCount) trails.pop_front();
|
|
}
|
|
}
|
|
|
|
|
|
void TrailPrimitive::purgeTrails(int count)
|
|
{
|
|
while ( (trails.size()>0) && (count>0)) {
|
|
trails.pop_front();
|
|
count--;
|
|
}
|
|
}
|
|
|
|
|
|
void TrailPrimitive::clearTrails()
|
|
{
|
|
trails.clear();
|
|
}
|
|
|
|
|
|
bool TrailPrimitive::createBuffers() // called in init(); to create proper indexBuffer / vertexBuffer / triangleCount
|
|
{
|
|
try {
|
|
|
|
vertexBuffer=new KVertexBufferDX_dynamic();
|
|
if (vertexBuffer!=NULL) {
|
|
// (UINT length, DWORD usage, DWORD FVF, D3DPOOL pool)
|
|
if (!vertexBuffer->create(sizeof(DynamicVertex) * vertexCount, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, DynamicVertex::FVF, D3DPOOL_DEFAULT)) {
|
|
throw 0;
|
|
}
|
|
}
|
|
vertexBuffer->setVertexCount(vertexCount);
|
|
|
|
indexBuffer=new KIndexBufferDX_dynamic();
|
|
if (indexBuffer!=NULL) {
|
|
if (!indexBuffer->create(indexCount * sizeof(DWORD), D3DUSAGE_DYNAMIC, D3DFMT_INDEX32, D3DPOOL_DEFAULT)) {
|
|
// index buffer createion failed
|
|
throw 0;
|
|
}
|
|
}
|
|
indexBuffer->setIndexCount(indexCount);
|
|
|
|
rebuildPolygon=true;
|
|
|
|
void *p;
|
|
int size=0;
|
|
indexBuffer->Lock(&p, size);
|
|
if (p!=NULL) {
|
|
DWORD *pu=(DWORD *)p;
|
|
int i, n;
|
|
|
|
n=0;
|
|
for (i=0; i<maxTrailCount-1; i++) {
|
|
// 1st
|
|
*pu=n; pu++;
|
|
*pu=n+1; pu++;
|
|
*pu=n+2; pu++;
|
|
|
|
// 2nd
|
|
*pu=n+2; pu++;
|
|
*pu=n+1; pu++;
|
|
*pu=n+3; pu++;
|
|
|
|
// 1st, backside
|
|
*pu=n; pu++;
|
|
*pu=n+2; pu++;
|
|
*pu=n+1; pu++;
|
|
|
|
// 2nd, backside
|
|
*pu=n+2; pu++;
|
|
*pu=n+3; pu++;
|
|
*pu=n+1; pu++;
|
|
|
|
n+=2;
|
|
}
|
|
indexBuffer->Unlock();
|
|
}
|
|
|
|
} catch (int) {
|
|
close();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void TrailPrimitive::setTrailNodeCount(int count) // Display되는 trail의 node갯수 (segment갯수+1)
|
|
{
|
|
assert(count>=2 && count<=maxTrailCount);
|
|
trailCount=count;
|
|
|
|
// Set dirty flag
|
|
rebuildPolygon=true;
|
|
|
|
}
|
|
|
|
void TrailPrimitive::setTrailNodeColor(int nodeNumber // node번호. NODE_START_xxxx 나 NODE_END_xxxx
|
|
, DWORD _color0, DWORD _color1 // 화면표시색 = (텍스처 * color0) + color1
|
|
, float _u, float _v // 텍스처 좌표
|
|
)
|
|
{
|
|
assert(nodeNumber>=0 && nodeNumber<NODE_MAX);
|
|
color0[nodeNumber]=_color0;
|
|
color1[nodeNumber]=_color1;
|
|
u[nodeNumber]=_u;
|
|
v[nodeNumber]=_v;
|
|
|
|
// Set dirty flag
|
|
rebuildPolygon=true;
|
|
}
|
|
|
|
void TrailPrimitive::getTriailNodeColor(int nodeNumber
|
|
, DWORD *_color0, DWORD *_color1
|
|
, float *_u, float *_v
|
|
)
|
|
{
|
|
assert(nodeNumber>=0 && nodeNumber<NODE_MAX);
|
|
if (_color0!=NULL) *_color0=color0[nodeNumber];
|
|
if (_color1!=NULL) *_color1=color1[nodeNumber];
|
|
if (_u!=NULL) *_u=u[nodeNumber];
|
|
if (_v!=NULL) *_v=v[nodeNumber];
|
|
}
|
|
|
|
|
|
void TrailPrimitive::setTrailTexture(const char *texName)
|
|
{
|
|
TEXPACK texpack;
|
|
if (texName!=NULL) {
|
|
// Load texture
|
|
NX3LoadPack loadpack;
|
|
loadpack.Init();
|
|
if( KTextureManager::GetManager()->IsExistTexture( texName, &loadpack ) ) {
|
|
KTextureManager::GetManager()->RefreshTexture( texName, &loadpack );
|
|
texpack.spTexture = KTextureManager::GetManager()
|
|
->GetTexture( texName, &loadpack, true, KTextureManager::GetManager()->GetMipMapBiasLevel() );
|
|
}
|
|
}
|
|
this->SetTexture(&texpack);
|
|
}
|
|
|
|
|
|
void TrailPrimitive::setTrailTexture(K3DTexture *texture)
|
|
{
|
|
TEXPACK texpack;
|
|
texpack.spTexture=texture;
|
|
this->SetTexture(&texpack);
|
|
}
|
|
|
|
|
|
void TrailPrimitive::initPolygon()
|
|
{
|
|
if (vertexBuffer==NULL || indexBuffer==NULL) return;
|
|
|
|
//
|
|
// Set vertex colors and UVs
|
|
//
|
|
void *p;
|
|
int size=0;
|
|
DynamicVertex *vtx;
|
|
|
|
int i;
|
|
float f, fi;
|
|
|
|
//D3DLOCK_DISCARD 옵션은 비스타에서 문제 발생으로 제거됨
|
|
vertexBuffer->Lock(&p, size, D3DLOCK_NOSYSLOCK /*| D3DLOCK_DISCARD*/);
|
|
if (p!=NULL) {
|
|
// Build vertex parameters
|
|
vtx=(DynamicVertex *)p;
|
|
|
|
for (i=0; i<trailCount; i++) {
|
|
f=((float)i) / (float)(trailCount-1);
|
|
fi=1.0f-f;
|
|
|
|
// bottom vertex
|
|
vtx->clear();
|
|
vtx->color0 = interpolateColor(color0[NODE_OLDEST_BOTTOM], color0[NODE_NEWEST_BOTTOM], f);
|
|
vtx->color1 = interpolateColor(color1[NODE_OLDEST_BOTTOM], color1[NODE_NEWEST_BOTTOM], f);
|
|
vtx->u0 = u[NODE_OLDEST_BOTTOM]*fi + u[NODE_NEWEST_BOTTOM]*f;
|
|
vtx->v0 = v[NODE_OLDEST_BOTTOM]*fi + v[NODE_NEWEST_BOTTOM]*f;
|
|
|
|
vtx++;
|
|
|
|
// top vertex
|
|
vtx->clear();
|
|
vtx->color0 = interpolateColor(color0[NODE_OLDEST_TOP], color0[NODE_NEWEST_TOP], f);
|
|
vtx->color1 = interpolateColor(color1[NODE_OLDEST_TOP], color1[NODE_NEWEST_TOP], f);
|
|
vtx->u0 = u[NODE_OLDEST_TOP]*fi + u[NODE_NEWEST_TOP]*f;
|
|
vtx->v0 = v[NODE_OLDEST_TOP]*fi + v[NODE_NEWEST_TOP]*f;
|
|
|
|
vtx++;
|
|
}
|
|
vertexBuffer->Unlock();
|
|
}
|
|
indexBuffer->setIndexCount((trailCount-1)*3*4);
|
|
}
|
|
|
|
|
|
//========================================================
|
|
// SGameFxSwordSlash main code
|
|
//========================================================
|
|
|
|
|
|
const int SWORDSLASH_TRAILSEGMENTSIZE=1024; // buffer의 max크기 <- 디버깅용. 나중에 줄일 것
|
|
const int SWORDSLASH_DEFAULTSEGMENTSIZE=16;
|
|
|
|
SGameFxSwordSlash::SGameFxSwordSlash( bool bRight ) : KSeqModel() // KSeqForm()
|
|
{
|
|
m_bRight = bRight;
|
|
|
|
primitive=new TrailPrimitive();
|
|
primitive->init(SWORDSLASH_TRAILSEGMENTSIZE); // max length
|
|
primitive->setTrailNodeCount(SWORDSLASH_DEFAULTSEGMENTSIZE); // current length
|
|
primitive->SetUseRight( m_bRight );
|
|
|
|
K3DMatrixIdentity(m_matResult);
|
|
K3DMatrixIdentity(m_matWorld);
|
|
}
|
|
|
|
|
|
SGameFxSwordSlash::~SGameFxSwordSlash()
|
|
{
|
|
delete primitive;
|
|
}
|
|
|
|
|
|
//
|
|
// Inherits
|
|
//
|
|
void SGameFxSwordSlash::Render( KViewportObject *viewport, DWORD flag , const K3DMatrix * pAttachMat )
|
|
{
|
|
if (primitive==NULL) return;
|
|
primitive->SetTransform(&m_matResult, &m_matWorld);
|
|
viewport->Register( primitive
|
|
, 0 // default rendering mode
|
|
);
|
|
}
|
|
|
|
//
|
|
// Original
|
|
//
|
|
void SGameFxSwordSlash::addTrails(int count, DWORD starttime, DWORD endtime, K3DMatrix *matrix, bool isBow, float angle)
|
|
{
|
|
if (primitive==NULL) return;
|
|
primitive->addTrails(count, starttime, endtime, matrix, isBow, angle);
|
|
}
|
|
|
|
void SGameFxSwordSlash::purgeTrails(int count)
|
|
{
|
|
if (primitive==NULL) return;
|
|
primitive->purgeTrails(count);
|
|
}
|
|
|
|
void SGameFxSwordSlash::clearTrails()
|
|
{
|
|
if (primitive==NULL) return;
|
|
primitive->clearTrails();
|
|
}
|
|
|
|
|
|
void SGameFxSwordSlash::runTrail(bool bOn)
|
|
{
|
|
if (primitive==NULL) return;
|
|
primitive->runTrail(bOn);
|
|
}
|
|
|
|
bool SGameFxSwordSlash::IsRunTrail()
|
|
{
|
|
if (primitive==NULL) return false;
|
|
return primitive->isTrailRunning();
|
|
}
|
|
|
|
void SGameFxSwordSlash::setTrailWidth(float _width)
|
|
{
|
|
if (primitive==NULL) return;
|
|
primitive->setTrailWidth(_width);
|
|
}
|
|
|
|
void SGameFxSwordSlash::setTrailNodeCount(int count) // Trail의 node갯수 (segment갯수-1). 길이
|
|
{
|
|
if (primitive==NULL) return;
|
|
primitive->setTrailNodeCount(count);
|
|
}
|
|
|
|
void SGameFxSwordSlash::setTrailNodeColor(int nodeNumber // node번호. TrailPrimitive::NODE_START_xxxx 나 TrailPrimitive::NODE_END_xxxx
|
|
, int nIndex, DWORD color // 화면표시색 = (텍스처 * color0) + color1
|
|
)
|
|
{
|
|
if (primitive==NULL) return;
|
|
|
|
DWORD color0, color1;
|
|
float u, v;
|
|
|
|
primitive->getTriailNodeColor(nodeNumber, &color0, &color1, &u, &v);
|
|
|
|
if( nIndex == 0 )
|
|
primitive->setTrailNodeColor(nodeNumber, color, color1, u, v);
|
|
else if( nIndex == 1 )
|
|
primitive->setTrailNodeColor(nodeNumber, color0, color, u, v);
|
|
}
|
|
|
|
void SGameFxSwordSlash::getTriailNodeColor(int nodeNumber
|
|
, DWORD *_color0, DWORD *_color1
|
|
, float *_u, float *_v
|
|
)
|
|
{
|
|
if (primitive==NULL) return;
|
|
primitive->getTriailNodeColor(nodeNumber, _color0, _color1, _u, _v);
|
|
}
|
|
|
|
void SGameFxSwordSlash::setTrailTexture(const char *texName)
|
|
{
|
|
if (primitive==NULL) return;
|
|
primitive->setTrailTexture(texName);
|
|
}
|
|
|
|
bool SGameFxSwordSlash::setupTrailByConfigurationText(const char *config) // Config파일 로딩
|
|
// NOTE! : 원래 이렇게 붙이려던 계획이 아닌, 기획자용 console command의 확장으로서 대충!만든 루틴임
|
|
// 따라서 여러모로 모양이 안 좋으므로 다른데 쓸 계획이 있으면 개선할 것!
|
|
{
|
|
if (primitive==NULL) return false;
|
|
return primitive->setupTrailByConfigurationText(config);
|
|
}
|
|
|
|
|
|
|
|
//===================================================================================================
|
|
// Console용 입출력 함수군
|
|
// NOTE! : 원래 이렇게 붙이려던 계획이 아닌, 기획자용 console command의 확장으로서 대충!만든 루틴임
|
|
// 따라서 여러모로 모양이 안 좋으므로 다른데 쓸 계획이 있으면 개선할 것!
|
|
//===================================================================================================
|
|
|
|
bool TrailPrimitive::setupTrailByConfigurationText(const char *config) // Config파일 로딩
|
|
{
|
|
size_t len=strlen(config);
|
|
if (len<=0) return false;
|
|
|
|
char *tmpbuf=new char[len+1]; // twParseCommands()에서 strtok가 무슨짓을 할지 모르므로 copy
|
|
strcpy(tmpbuf, config);
|
|
|
|
bool ret=twParseCommands(tmpbuf);
|
|
|
|
delete [] tmpbuf;
|
|
return ret;
|
|
}
|
|
|
|
|
|
void TrailPrimitive::twprintNode(char *buffer, int nodeNo) {
|
|
buffer[0]=0;
|
|
if (nodeNo<0 || nodeNo>3) return;
|
|
DWORD color0, color1;
|
|
float u, v;
|
|
getTriailNodeColor(nodeNo, &color0, &color1, &u, &v);
|
|
sprintf(buffer, "color0 0x%08x, color1 0x%08x, u %f, v %f <br>"
|
|
, color0, color1, u, v
|
|
);
|
|
}
|
|
|
|
void TrailPrimitive::twprintSize(char *buffer)
|
|
{
|
|
sprintf(buffer, " width %f, length %d <br>", getTrailWidth(), getTrailNodeCount());
|
|
}
|
|
|
|
void TrailPrimitive::twprint(char *buffer) {
|
|
char tmpbuf[1024];
|
|
buffer[0]=0;
|
|
twprintNode(tmpbuf, 0);
|
|
strcat(buffer, " Node00 <br>");
|
|
strcat(buffer, tmpbuf);
|
|
|
|
twprintNode(tmpbuf, 1);
|
|
strcat(buffer, " Node01 <br>");
|
|
strcat(buffer, tmpbuf);
|
|
|
|
twprintNode(tmpbuf, 2);
|
|
strcat(buffer, " Node10 <br>");
|
|
strcat(buffer, tmpbuf);
|
|
|
|
twprintNode(tmpbuf, 3);
|
|
strcat(buffer, " Node11 <br>");
|
|
strcat(buffer, tmpbuf);
|
|
|
|
twprintSize(tmpbuf);
|
|
strcat(buffer, " <br>");
|
|
strcat(buffer, tmpbuf);
|
|
}
|
|
|
|
|
|
//
|
|
// String에서 command를 parse
|
|
//
|
|
bool TrailPrimitive::twParseCommands(char *buffer) {
|
|
// Comment를 전부 삭제
|
|
size_t len=strlen(buffer);
|
|
if (len==0) return false;
|
|
|
|
char line[512];
|
|
char *text=new char[len*2]; // len+1이면 충분. (+1 for eos)
|
|
char *p;
|
|
int n;
|
|
|
|
text[0]=0;
|
|
p=strtok(buffer, "\r\n");
|
|
while (p!=NULL) {
|
|
// Split by line
|
|
strcpy(line, p);
|
|
n=(int)strcspn(line, "!#"); // ! 이나 #으로 시작하면 커멘트 라인
|
|
line[n]=0; // 커멘트 이후 삭제
|
|
strcat(text, line);
|
|
strcat(text, "\n");
|
|
p=strtok(NULL, "\r\n");
|
|
}
|
|
|
|
const char *loadCommandList[] = {
|
|
"wttexture" , "wttex"
|
|
, "wtwidth" , "wtw"
|
|
, "wtlength" , "wtl"
|
|
|
|
, "wt00color0" , "wt00c0"
|
|
, "wt00color1" , "wt00c1"
|
|
, "wt00u"
|
|
, "wt00v"
|
|
|
|
, "wt01color0" , "wt01c0"
|
|
, "wt01color1" , "wt01c1"
|
|
, "wt01u"
|
|
, "wt01v"
|
|
|
|
, "wt10color0" , "wt10c0"
|
|
, "wt10color1" , "wt10c1"
|
|
, "wt10u"
|
|
, "wt10v"
|
|
|
|
, "wt11color0" , "wt11c0"
|
|
, "wt11color1" , "wt11c1"
|
|
, "wt11u"
|
|
, "wt11v"
|
|
, NULL // EOL
|
|
};
|
|
|
|
std::string _key;
|
|
std::string _param;
|
|
std::vector<std::string> arg;
|
|
const char **c=loadCommandList;
|
|
|
|
char lineBuf[1024];
|
|
|
|
while ((*c)!=NULL) {
|
|
// Find command
|
|
p=strstr(text, *c);
|
|
if (p!=NULL) {
|
|
p+=strlen(*c);
|
|
n=(int)strspn(p, " \t");
|
|
if (n>0) {
|
|
p+=n;
|
|
n=(int)strcspn(p, " \t\r\n");
|
|
|
|
strncpy(line, p, n);
|
|
line[n]=0;
|
|
|
|
if (n>0) {
|
|
_key=*c;
|
|
_param=line;
|
|
|
|
arg.clear();
|
|
arg.push_back(_param);
|
|
processConsoleCommand(_key, (int)arg.size(), arg, lineBuf);
|
|
}
|
|
}
|
|
}
|
|
c++;
|
|
}
|
|
|
|
arg.clear();
|
|
delete [] text;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool TrailPrimitive::twLoadCommands(const char *filename) {
|
|
int f=::_open(filename, _O_RDONLY | _O_TEXT, _S_IREAD | _S_IWRITE);
|
|
if (f==-1) return false;
|
|
|
|
long filesize=_lseek(f, 0, SEEK_END);
|
|
_lseek(f, 0, SEEK_SET);
|
|
|
|
char *text=new char[filesize*2];
|
|
int n=::_read(f, text, filesize*2);
|
|
text[n]=0;
|
|
|
|
bool b=twParseCommands(text);
|
|
|
|
delete [] text;
|
|
|
|
::_close(f);
|
|
|
|
return b;
|
|
}
|
|
|
|
//
|
|
// 현재 커맨드를 file에 write
|
|
//
|
|
void TrailPrimitive::twWriteCommands(char *buffer) {
|
|
const char *twSaveCommandList[] = {
|
|
"wttexture"
|
|
, "wtwidth"
|
|
, "wtlength"
|
|
|
|
, "wt00color0"
|
|
, "wt00color1"
|
|
, "wt00u"
|
|
, "wt00v"
|
|
|
|
, "wt01color0"
|
|
, "wt01color1"
|
|
, "wt01u"
|
|
, "wt01v"
|
|
|
|
, "wt10color0"
|
|
, "wt10color1"
|
|
, "wt10u"
|
|
, "wt10v"
|
|
|
|
, "wt11color0"
|
|
, "wt11color1"
|
|
, "wt11u"
|
|
, "wt11v"
|
|
, NULL // EOL
|
|
};
|
|
|
|
string _key;
|
|
std::vector<std::string> arg;
|
|
const char **c=twSaveCommandList;
|
|
char lineBuf[1024];
|
|
// char *p;
|
|
|
|
buffer[0]=0;
|
|
while (*c!=NULL) {
|
|
_key=*(c++);
|
|
processConsoleCommand(_key, (int)arg.size(), arg, lineBuf);
|
|
if (lineBuf[0]!=0) {
|
|
strcat(buffer, lineBuf); strcat(buffer, "\n");
|
|
}
|
|
}
|
|
|
|
arg.clear();
|
|
}
|
|
|
|
|
|
bool TrailPrimitive::twSaveCommand(const char *filename)
|
|
{
|
|
int f=::_open(filename, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_TEXT, _S_IREAD | _S_IWRITE);
|
|
if (f==-1) return false;
|
|
|
|
char buffer[2048]="";
|
|
twWriteCommands(buffer);
|
|
::_write(f, buffer, (unsigned int)strlen(buffer));
|
|
::_close(f);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
const char *TrailDefaultFileName="twParams.txt";
|
|
|
|
void TrailPrimitive::processConsoleCommand(std::string &key, int argc, std::vector<std::string> &argv, char *outputBuffer)
|
|
{
|
|
static char TrailTexName[512]="";
|
|
static char TrailFileName[512]="";
|
|
|
|
outputBuffer[0]=0;
|
|
|
|
const char *cmd=key.c_str();
|
|
|
|
// Print information
|
|
if ( (0==::_stricmp(cmd, "wtprint")) || (0==::_stricmp(cmd, "wtp"))) {
|
|
twprint(outputBuffer);
|
|
return;
|
|
}
|
|
|
|
|
|
// Save/load params
|
|
if ( (0==::_stricmp(cmd, "wtsave")) || (0==::_stricmp(cmd, "wtsa"))) {
|
|
const char *filename=TrailDefaultFileName;
|
|
if (argc>0) {
|
|
filename=argv[0].c_str();
|
|
}
|
|
if (false==twSaveCommand(filename)) {
|
|
sprintf(outputBuffer, "Save error");
|
|
return;
|
|
}
|
|
sprintf(outputBuffer, "Saved to %s", filename);
|
|
return;
|
|
}
|
|
|
|
if ( (0==::_stricmp(cmd, "wtload")) || (0==::_stricmp(cmd, "wtlo"))) {
|
|
const char *filename=TrailDefaultFileName;
|
|
if (argc>0) {
|
|
filename=argv[0].c_str();
|
|
}
|
|
if (false==twLoadCommands(filename)) {
|
|
sprintf(outputBuffer, "Load error");
|
|
return;
|
|
}
|
|
strcpy(TrailFileName, filename);
|
|
|
|
sprintf(outputBuffer, "Loaded from %s", filename);
|
|
return;
|
|
}
|
|
|
|
if ( (0==::_stricmp(cmd, "wtreload")) || (0==::_stricmp(cmd, "wtr"))) {
|
|
if (false==twLoadCommands(TrailFileName)) {
|
|
sprintf(outputBuffer, "Reload error");
|
|
}
|
|
sprintf(outputBuffer, "Reloaded from %s", TrailFileName);
|
|
return;
|
|
}
|
|
|
|
|
|
if ( (0==::_stricmp(cmd, "wttexreload")) || (0==::_stricmp(cmd, "wttexr"))) {
|
|
// Texture reload
|
|
if (TrailTexName[0]!=0) {
|
|
this->setTrailTexture(TrailTexName);
|
|
sprintf(outputBuffer, "Texture %s reloaded", TrailTexName);
|
|
return;
|
|
}
|
|
sprintf(outputBuffer, "No texture");
|
|
}
|
|
|
|
|
|
|
|
if ( (0==::_stricmp(cmd, "wttexture")) || (0==::_stricmp(cmd, "wttex")) ) {
|
|
if (argc>0) {
|
|
this->setTrailTexture(argv[0].c_str());
|
|
strcpy(TrailTexName, argv[0].c_str());
|
|
}
|
|
sprintf(outputBuffer, "wttexture %s", TrailTexName);
|
|
return;
|
|
}
|
|
|
|
if ( (0==::_stricmp(cmd, "wtwidth")) || (0==::_stricmp(cmd, "wtw")) ) {
|
|
if (argc>0) {
|
|
this->setTrailWidth(atof(argv[0].c_str()));
|
|
}
|
|
sprintf(outputBuffer, "wtwidth %f", this->getTrailWidth());
|
|
return;
|
|
}
|
|
|
|
if ( (0==::_stricmp(cmd, "wtlength")) || (0==::_stricmp(cmd, "wtl")) ){
|
|
if (argc>0) {
|
|
int n=atoi(argv[0].c_str());
|
|
if (n>SWORDSLASH_TRAILSEGMENTSIZE) n=SWORDSLASH_TRAILSEGMENTSIZE;
|
|
this->setTrailNodeCount(n);
|
|
}
|
|
sprintf(outputBuffer, "wtlength %d", this->getTrailNodeCount());
|
|
return;
|
|
}
|
|
|
|
if ( (cmd[2]=='0' || cmd[2]=='1') && (cmd[3]=='0' || cmd[3]=='1')) {
|
|
DWORD color0, color1;
|
|
float u, v;
|
|
char *p;
|
|
const char *c;
|
|
int n=0;
|
|
|
|
if (cmd[2]=='1') n+=2;
|
|
if (cmd[3]=='1') n+=1;
|
|
c=&(cmd[4]);
|
|
this->getTriailNodeColor(n, &color0, &color1, &u, &v);
|
|
|
|
if (0==::_stricmp(c, "color0") || 0==::_stricmp(c, "c0")) {
|
|
if (argc>0) {
|
|
color0=strtoul(argv[0].c_str(), &p, 16);
|
|
this->setTrailNodeColor(n, color0, color1, u, v);
|
|
}
|
|
sprintf(outputBuffer, "wt%c%ccolor0 %08x", cmd[2], cmd[3], color0);
|
|
return;
|
|
}
|
|
if (0==::_stricmp(c, "color1") || 0==::_stricmp(c, "c1")) {
|
|
if (argc>0) {
|
|
color1=strtoul(argv[0].c_str(), &p, 16);
|
|
this->setTrailNodeColor(n, color0, color1, u, v);
|
|
}
|
|
sprintf(outputBuffer, "wt%c%ccolor1 %08x", cmd[2], cmd[3], color1);
|
|
return;
|
|
}
|
|
if (0==::_stricmp(c, "u")) {
|
|
if (argc>0) {
|
|
u=atof(argv[0].c_str());
|
|
this->setTrailNodeColor(n, color0, color1, u, v);
|
|
}
|
|
sprintf(outputBuffer, "wt%c%cu %15f", cmd[2], cmd[3], u);
|
|
return;
|
|
}
|
|
if (0==::_stricmp(c, "v")) {
|
|
if (argc>0) {
|
|
v=atof(argv[0].c_str());
|
|
this->setTrailNodeColor(n, color0, color1, u, v);
|
|
}
|
|
sprintf(outputBuffer, "wt%c%cv %15f", cmd[2], cmd[3], v);
|
|
return;
|
|
}
|
|
|
|
// Invalid command
|
|
twprintNode(outputBuffer, n);
|
|
return;
|
|
}
|
|
|
|
|
|
// if (0==::_stricmp(cmd, "wthelp")) {
|
|
strcpy(outputBuffer, " - 커맨드 일람 -<br>"
|
|
"wtprint : 현재 파라미터를 프린트한다<br>"
|
|
"wtsave [파일명] : 현재 파라미터를 파일에 세이브한다 <br>"
|
|
"wtload [파일명] : 현재 파라미터를 파일에서 로드한다 <br>"
|
|
"wtreload : 현재 파라미터를 이전에 로드한 파일에서 다시 로드한다 <br>"
|
|
"wttexreload : 텍스처를 다시 로드한다 <br>"
|
|
"<br>"
|
|
"wt00color0 [ARGB]: 무기 위치 검광 손목쪽 색깔 0번 (ARGB)<br>"
|
|
"wt00color1 [ARGB]: 무기 위치 검광 손목쪽 색깔 1번 (ARGB)<br>"
|
|
"wt00u [float]: 무기 위치 검광 손목쪽 U값 (0.0 ~ 1.0)<br>"
|
|
"wt00v [float]: 무기 위치 검광 손목쪽 V값 (0.0 ~ 1.0)<br>"
|
|
"<br>"
|
|
"wt01color0 [ARGB]: 무기 위치 검광 칼끝쪽 색깔 0번 (ARGB)<br>"
|
|
"wt01color1 [ARGB]: 무기 위치 검광 칼끝쪽 색깔 1번 (ARGB)<br>"
|
|
"wt01u [float]: 무기 위치 검광 칼끝쪽 U값 (0.0 ~ 1.0)<br>"
|
|
"wt01v [float]: 무기 위치 검광 칼끝쪽 V값 (0.0 ~ 1.0)<br>"
|
|
"<br>"
|
|
"wt10color0 [ARGB]: 검광 과거위치 손목쪽 색깔 0번 (ARGB)<br>"
|
|
"wt10color1 [ARGB]: 검광 과거위치 손목쪽 색깔 1번 (ARGB)<br>"
|
|
"wt10u [float]: 검광 과거위치 손목쪽 U값 (0.0 ~ 1.0)<br>"
|
|
"wt10v [float]: 검광 과거위치 손목쪽 V값 (0.0 ~ 1.0)<br>"
|
|
"<br>"
|
|
"wt11color0 [ARGB]: 검광 과거위치 칼끝쪽 색깔 0번 (ARGB)<br>"
|
|
"wt11color1 [ARGB]: 검광 과거위치 칼끝쪽 색깔 1번 (ARGB)<br>"
|
|
"wt11u [float]: 검광 과거위치 검광 손목쪽 U값 (0.0 ~ 1.0)<br>"
|
|
"wt11v [float]: 검광 과거위치 검광 손목쪽 V값 (0.0 ~ 1.0)<br>"
|
|
"<br>"
|
|
"wttexture [파일명]: 텍스처 파일명<br>"
|
|
"wtwidth [float]: 검광 너비. 10.0이면 일반 칼 길이정도의 너비<br>"
|
|
"wtlength [float]: 검광 길이. 64정도면 보통 길이<br>"
|
|
"<br> -참고- <br>"
|
|
"wtp : wtprint의 약자<br>"
|
|
"wt00c0 : wt00color0의 약자<br>"
|
|
"wt00c1 : wt00color1의 약자<br>"
|
|
"wt01c0, wt01c1, wt10c0, wt10c1, wt11c0, wt11c1 : 위와 같음<br>"
|
|
"wtr : wtreload<br>"
|
|
"wtlo : wtload<br>"
|
|
"wtsa : wtsave<br>"
|
|
"wttexr : wttexreload<br>"
|
|
);
|
|
}
|
|
|
|
|
|
|
|
|
|
//===========================================================
|
|
// Debugging utility
|
|
// 콘솔에서 파라미터 잘 받아서 처리
|
|
// 나중에 지울것 or 막을것!!
|
|
//===========================================================
|
|
|
|
|
|
#include "SGame.h"
|
|
#include "SGameSystem.h"
|
|
extern SGameSystem * g_pCurrentGameSystem; // defined in SGameSystem.cpp // localPlayer얻어오는데 사용
|
|
|
|
char *WeaponTrailProcessConsoleCommand(std::string &key, int argc, std::vector<std::string> &argv)
|
|
{
|
|
static char TrailDbgMessage[2048]="";
|
|
|
|
SGameAvatarEx *localPlayer=g_pCurrentGameSystem->GetLocalPlayer();
|
|
if (localPlayer==NULL) return NULL;
|
|
|
|
SGameFxSwordSlash *trail=localPlayer->GetRightWeaponTrailRenderer(); // 오른손 무기에 대해 적용
|
|
if (trail==NULL) return NULL;
|
|
|
|
TrailPrimitive *prim=trail->getTrailPrimitive();
|
|
if (prim==NULL) return NULL;
|
|
|
|
prim->processConsoleCommand(key, argc, argv, TrailDbgMessage);
|
|
|
|
localPlayer->ActivateRightWeaponTrail(); // sonador 10.6.1 무기 강화 이펙트 추가 지원
|
|
|
|
return TrailDbgMessage;
|
|
}
|
|
|
|
|