📄 terraineditor.cc
字号:
}
void TerrainEditor::setCursor(GuiCursor * cursor)
{
mCurrentCursor = cursor ? cursor : mDefaultCursor;
}
S32 TerrainEditor::getPaintMaterial()
{
if(!mPaintMaterial)
return -1;
return getClientTerrain()->getMaterialAlphaIndex(mPaintMaterial);
}
//------------------------------------------------------------------------------
TerrainBlock * TerrainEditor::getClientTerrain()
{
#ifdef TGE_RPGCLIENT2 /// TGE_RPGGhost
return mTerrainBlock;
#else
// do the client..
NetConnection * toServer = NetConnection::getConnectionToServer();
NetConnection * toClient = NetConnection::getLocalClientConnection();
S32 index = toClient->getGhostIndex(mTerrainBlock);
return(dynamic_cast<TerrainBlock*>(toServer->resolveGhost(index)));
#endif
}
//------------------------------------------------------------------------------
bool TerrainEditor::gridToWorld(const Point2I & gPos, Point3F & wPos)
{
const MatrixF & mat = mTerrainBlock->getTransform();
Point3F origin;
mat.getColumn(3, &origin);
#ifdef TGE_RPG /// TGE_TerrainScene
if(mCurrentAction->isGridByBlock())
{
wPos.x = gPos.x * (float)mTerrainBlock->getSquareSize() + origin.x;
wPos.y = gPos.y * (float)mTerrainBlock->getSquareSize() + origin.y;
}
else
{
wPos.x = mFloor(gPos.x) + origin.x;
wPos.y = mFloor(gPos.y) + origin.y;
}
#else
wPos.x = gPos.x * (float)mTerrainBlock->getSquareSize() + origin.x;
wPos.y = gPos.y * (float)mTerrainBlock->getSquareSize() + origin.y;
#endif
wPos.z = getGridHeight(gPos);
return(!(gPos.x >> TerrainBlock::BlockShift || gPos.y >> TerrainBlock::BlockShift));
}
bool TerrainEditor::worldToGrid(const Point3F & wPos, Point2I & gPos)
{
const MatrixF & mat = mTerrainBlock->getTransform();
Point3F origin;
mat.getColumn(3, &origin);
#ifdef TGE_RPG /// TGE_TerrainScene
if(mCurrentAction->isGridByBlock())
{
F32 squareSize = (F32) mTerrainBlock->getSquareSize();
F32 halfSquareSize = squareSize / 2;
gPos.x = (S32)mFloor((wPos.x - origin.x + halfSquareSize) / squareSize);
gPos.y = (S32)mFloor((wPos.y - origin.y + halfSquareSize) / squareSize);
}
else
{
gPos.x = (S32)mFloor(wPos.x - origin.x);
gPos.y = (S32)mFloor(wPos.y - origin.y);
}
#else
F32 squareSize = (F32) mTerrainBlock->getSquareSize();
F32 halfSquareSize = squareSize / 2;
float x = (wPos.x - origin.x + halfSquareSize) / squareSize;
float y = (wPos.y - origin.y + halfSquareSize) / squareSize;
gPos.x = (S32)mFloor(x);
gPos.y = (S32)mFloor(y);
#endif
return(!(gPos.x >> TerrainBlock::BlockShift || gPos.y >> TerrainBlock::BlockShift));
}
bool TerrainEditor::gridToCenter(const Point2I & gPos, Point2I & cPos)
{
#ifdef TGE_RPG /// TGE_TerrainScene
if(mCurrentAction->isGridByBlock())
{
cPos.x = gPos.x & TerrainBlock::BlockMask;
cPos.y = gPos.y & TerrainBlock::BlockMask;
}
else
{
F32 fMod = (F32) mTerrainBlock->getSquareSize() * TerrainBlock::BlockSize;
cPos.x = mFmod(gPos.x,fMod);
cPos.y = mFmod(gPos.y,fMod);
}
#else
cPos.x = gPos.x & TerrainBlock::BlockMask;
cPos.y = gPos.y & TerrainBlock::BlockMask;
#endif
return(!(gPos.x >> TerrainBlock::BlockShift || gPos.y >> TerrainBlock::BlockShift));
}
//------------------------------------------------------------------------------
bool TerrainEditor::getGridInfo(const Point3F & wPos, GridInfo & info)
{
Point2I gPos;
worldToGrid(wPos, gPos);
return getGridInfo(gPos, info);
}
bool TerrainEditor::getGridInfo(const Point2I & gPos, GridInfo & info)
{
//
info.mGridPos = gPos;
info.mMaterial = getGridMaterial(gPos);
info.mHeight = getGridHeight(gPos);
info.mWeight = 1.f;
info.mPrimarySelect = true;
info.mMaterialChanged = false;
Point2I cPos;
gridToCenter(gPos, cPos);
info.mMaterialGroup = mTerrainBlock->getBaseMaterial(cPos.x, cPos.y);
mTerrainBlock->getMaterialAlpha(gPos, info.mMaterialAlpha);
return(!(gPos.x >> TerrainBlock::BlockShift || gPos.y >> TerrainBlock::BlockShift));
}
void TerrainEditor::setGridInfo(const GridInfo & info)
{
#ifdef TGE_RPG /// TGE_TerrainScene
setGridBlock(info.mGridPos, info.m_uSceneFlags);
#endif
setGridHeight(info.mGridPos, info.mHeight);
setGridMaterial(info.mGridPos, info.mMaterial);
setGridMaterialGroup(info.mGridPos, info.mMaterialGroup);
if(info.mMaterialChanged)
mTerrainBlock->setMaterialAlpha(info.mGridPos, info.mMaterialAlpha);
}
//------------------------------------------------------------------------------
void TerrainEditor::gridUpdateComplete()
{
if(mGridUpdateMin.x <= mGridUpdateMax.x)
mTerrainBlock->updateGrid(mGridUpdateMin, mGridUpdateMax);
mGridUpdateMin.set(256,256);
mGridUpdateMax.set(0,0);
}
void TerrainEditor::materialUpdateComplete()
{
if(mGridUpdateMin.x <= mGridUpdateMax.x)
{
TerrainBlock * clientTerrain = getClientTerrain();
clientTerrain->updateGridMaterials(mGridUpdateMin, mGridUpdateMax);
mTerrainBlock->updateGrid(mGridUpdateMin, mGridUpdateMax);
}
mGridUpdateMin.set(256,256);
mGridUpdateMax.set(0,0);
}
void TerrainEditor::setGridHeight(const Point2I & gPos, const F32 height)
{
Point2I cPos;
gridToCenter(gPos, cPos);
if(cPos.x < mGridUpdateMin.x)
mGridUpdateMin.x = cPos.x;
if(cPos.y < mGridUpdateMin.y)
mGridUpdateMin.y = cPos.y;
if(cPos.x > mGridUpdateMax.x)
mGridUpdateMax.x = cPos.x;
if(cPos.y > mGridUpdateMax.y)
mGridUpdateMax.y = cPos.y;
mTerrainBlock->setHeight(cPos, height);
}
F32 TerrainEditor::getGridHeight(const Point2I & gPos)
{
Point2I cPos;
gridToCenter(gPos, cPos);
return(fixedToFloat(mTerrainBlock->getHeight(cPos.x, cPos.y)));
}
#ifdef TGE_RPG /// TGE_TerrainScene
U32 TerrainEditor::getGridBlock(const Point2I & gPos)
{
Point2I cPos;
gridToCenter(gPos, cPos);
return mTerrainBlock->getBlockAt(cPos.x, cPos.y);
}
void TerrainEditor::setGridBlock(const Point2I & gPos, const U32 uFlags)
{
Point2I cPos;
gridToCenter(gPos, cPos);
if(cPos.x < mGridUpdateMin.x)
mGridUpdateMin.x = cPos.x;
if(cPos.y < mGridUpdateMin.y)
mGridUpdateMin.y = cPos.y;
if(cPos.x > mGridUpdateMax.x)
mGridUpdateMax.x = cPos.x;
if(cPos.y > mGridUpdateMax.y)
mGridUpdateMax.y = cPos.y;
Point3F ptPos;
gridToWorld(cPos,ptPos);
mTerrainBlock->setBlockAt(ptPos.x,ptPos.y,uFlags);
//mTerrainBlock->setBlockAt(cPos.x,cPos.y,uFlags);
}
#endif
TerrainBlock::Material TerrainEditor::getGridMaterial(const Point2I & gPos)
{
Point2I cPos;
gridToCenter(gPos, cPos);
return(*mTerrainBlock->getMaterial(cPos.x, cPos.y));
}
void TerrainEditor::setGridMaterial(const Point2I & gPos, const TerrainBlock::Material & material)
{
Point2I cPos;
gridToCenter(gPos, cPos);
// check if empty has been altered...
TerrainBlock::Material * mat = mTerrainBlock->getMaterial(cPos.x, cPos.y);
if((mat->flags & TerrainBlock::Material::Empty) ^ (material.flags & TerrainBlock::Material::Empty))
mRebuildEmpty = true;
*mat = material;
}
U8 TerrainEditor::getGridMaterialGroup(const Point2I & gPos)
{
Point2I cPos;
gridToCenter(gPos, cPos);
return(mTerrainBlock->getBaseMaterial(cPos.x, cPos.y));
}
// basematerials are shared through a resource... so work on client object
// so wont need to load textures....
void TerrainEditor::setGridMaterialGroup(const Point2I & gPos, const U8 group)
{
Point2I cPos;
gridToCenter(gPos, cPos);
TerrainBlock * clientTerrain = getClientTerrain();
clientTerrain->setBaseMaterial(cPos.x, cPos.y, group);
}
//------------------------------------------------------------------------------
bool TerrainEditor::collide(const Gui3DMouseEvent & event, Point3F & pos)
{
if(!mTerrainBlock)
return(false);
// call the terrain block's ray collision routine directly
Point3F startPnt = event.pos;
Point3F endPnt = event.pos + event.vec * 1000;
Point3F tStartPnt, tEndPnt;
mTerrainBlock->getTransform().mulP(startPnt, &tStartPnt);
mTerrainBlock->getTransform().mulP(endPnt, &tEndPnt);
RayInfo ri;
if(mTerrainBlock->castRayI(tStartPnt, tEndPnt, &ri, true))
{
ri.point.interpolate(startPnt, endPnt, ri.t);
pos = ri.point;
return(true);
}
return(false);
}
//------------------------------------------------------------------------------
void TerrainEditor::updateGuiInfo()
{
char buf[128];
// mouse num grids
// mouse avg height
// selection num grids
// selection avg height
dSprintf(buf, sizeof(buf), "%d %g %d %g",
mMouseBrush->size(), mMouseBrush->getAvgHeight(),
mDefaultSel.size(), mDefaultSel.getAvgHeight());
Con::executef(this, 2, "onGuiUpdate", buf);
}
//------------------------------------------------------------------------------
void TerrainEditor::renderScene(const RectI &)
{
if(!mTerrainBlock)
return;
if(!mSelectionHidden)
renderSelection(mDefaultSel, ColorF(1,0,0), ColorF(0,1,0), ColorF(0,0,1), ColorF(0,0,1), true, false);
if(mRenderBrush && mMouseBrush->size())
renderSelection(*mMouseBrush, ColorF(1,0,0), ColorF(0,1,0), ColorF(0,0,1), ColorF(0,0,1), false, true);
if(mRenderBorder)
renderBorder();
}
//------------------------------------------------------------------------------
struct TerrVertex
{
Point3F point;
ColorI color;
};
void TerrainEditor::renderSelection( const Selection & sel, const ColorF & inColorFull, const ColorF & inColorNone, const ColorF & outColorFull, const ColorF & outColorNone, bool renderFill, bool renderFrame )
{
Vector<TerrVertex> vertexBuffer;
ColorF color;
ColorI iColor;
vertexBuffer.setSize(sel.size() * 4);
if(mRenderVertexSelection)
{
for(U32 i = 0; i < sel.size(); i++)
{
Point3F wPos;
bool center = gridToWorld(sel[i].mGridPos, wPos);
if(center)
{
if(sel[i].mWeight < 0.f || sel[i].mWeight > 1.f)
color = inColorFull;
else
color.interpolate(inColorNone, inColorFull, sel[i].mWeight);
}
else
{
if(sel[i].mWeight < 0.f || sel[i].mWeight > 1.f)
color = outColorFull;
else
color.interpolate(outColorFull, outColorNone, sel[i].mWeight);
}
//
iColor = color;
TerrVertex *verts = &(vertexBuffer[i * 4]);
#ifdef TGE_RPG /// TGE_TerrainScene
if(mCurrentAction->isGridByBlock())
{
verts[0].point = wPos + Point3F(-1, -1, 0);
verts[0].color = iColor;
verts[1].point = wPos + Point3F( 1, -1, 0);
verts[1].color = iColor;
verts[2].point = wPos + Point3F( 1, 1, 0);
verts[2].color = iColor;
verts[3].point = wPos + Point3F(-1, 1, 0);
verts[3].color = iColor;
}
else
{
verts[0].point = wPos;
verts[0].color = iColor;
verts[1].point = wPos + Point3F(1, 0, 0);
verts[1].color = iColor;
verts[2].point = wPos + Point3F(1, 1, 0);
verts[2].color = iColor;
verts[3].point = wPos + Point3F(0, 1, 0);
verts[3].color = iColor;
}
#else
verts[0].point = wPos + Point3F(-1, -1, 0);
verts[0].color = iColor;
verts[1].point = wPos + Point3F( 1, -1, 0);
verts[1].color = iColor;
verts[2].point = wPos + Point3F( 1, 1, 0);
verts[2].color = iColor;
verts[3].point = wPos + Point3F(-1, 1, 0);
verts[3].color = iColor;
#endif
}
}
else
{
// walk the points in the selection
for(U32 i = 0; i < sel.size(); i++)
{
Point2I gPos = sel[i].mGridPos;
TerrVertex *verts = &(vertexBuffer[i * 4]);
bool center = gridToWorld(gPos, verts[0].point);
gridToWorld(Point2I(gPos.x + 1, gPos.y), verts[1].point);
gridToWorld(Point2I(gPos.x + 1, gPos.y + 1), verts[2].point);
gridToWorld(Point2I(gPos.x, gPos.y + 1), verts[3].point);
if(center)
{
if(sel[i].mWeight < 0.f || sel[i].mWeight > 1.f)
color = inColorFull;
else
color.interpolate(inColorNone, inColorFull, sel[i].mWeight);
}
else
{
if(sel[i].mWeight < 0.f || sel[i].mWeight > 1.f)
color = outColorFull;
else
color.interpolate(outColorFull, outColorNone, sel[i].mWeight);
}
iColor = color;
verts[0].color = iColor;
verts[1].color = iColor;
verts[2].color = iColor;
verts[3].color = iColor;
}
}
//
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(TerrVertex), &(vertexBuffer[0]));
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(TerrVertex), &(vertexBuffer[0].color));
#ifndef TORQUE_OS_MAC // line drawing crashes on mac under CVAs... !!!!TBD
if (dglDoesSupportCompiledVertexArray())
glLockArraysEXT(0, vertexBuffer.size());
#endif
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
if(renderFill)
glDrawArrays(GL_QUADS, 0, vertexBuffer.size());
glDisable(GL_BLEND);
if(renderFrame)
for(U32 i = 0; i < sel.size(); i++)
glDrawArrays(GL_LINE_LOOP, i * 4, 4);
#ifndef TORQUE_OS_MAC // line drawing crashes on mac under CVAs...
if (dglDoesSupportCompiledVertexArray())
glUnlockArraysEXT();
#endif
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
//------------------------------------------------------------------------------
void TerrainEditor::renderBorder()
{
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Point2I pos(0,0);
Point2I dir[4] = {
Point2I(1,0),
Point2I(0,1),
Point2I(-1,0),
Point2I(0,-1)
};
//
if(mBorderLineMode)
{
glColor4ub(mBorderFrameColor.red, mBorderFrameColor.green, mBorderFrameColor.blue, mBorderFrameColor.alpha);
glBegin(GL_LINE_STRIP);
for(U32 i = 0; i < 4; i++)
{
for(U32 j = 0; j < TerrainBlock::BlockSize; j++)
{
Point3F wPos;
gridToWorld(pos, wPos);
glVertex3f(wPos.x, wPos.y, wPos.z);
pos += dir[i];
}
}
Point3F wPos;
gridToWorld(Point2I(0,0), wPos);
glVertex3f(wPos.x, wPos.y, wPos.z);
glEnd();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -