📄 terraineditor.cc
字号:
}
else
{
glEnable(GL_DEPTH_TEST);
GridSquare * gs = mTerrainBlock->findSquare(TerrainBlock::BlockShift, Point2I(0,0));
F32 height = F32(gs->maxHeight) * 0.03125f + mBorderHeight;
const MatrixF & mat = mTerrainBlock->getTransform();
Point3F pos;
mat.getColumn(3, &pos);
Point2F min(pos.x, pos.y);
Point2F max(pos.x + TerrainBlock::BlockSize * mTerrainBlock->getSquareSize(),
pos.y + TerrainBlock::BlockSize * mTerrainBlock->getSquareSize());
ColorI & a = mBorderFillColor;
ColorI & b = mBorderFrameColor;
for(U32 i = 0; i < 2; i++)
{
//
if(i){glColor4ub(a.red,a.green,a.blue,a.alpha);glBegin(GL_QUADS);} else {glColor4f(b.red,b.green,b.blue,b.alpha); glBegin(GL_LINE_LOOP);}
glVertex3f(min.x, min.y, 0);
glVertex3f(max.x, min.y, 0);
glVertex3f(max.x, min.y, height);
glVertex3f(min.x, min.y, height);
glEnd();
//
if(i){glColor4ub(a.red,a.green,a.blue,a.alpha);glBegin(GL_QUADS);} else {glColor4f(b.red,b.green,b.blue,b.alpha); glBegin(GL_LINE_LOOP);}
glVertex3f(min.x, max.y, 0);
glVertex3f(max.x, max.y, 0);
glVertex3f(max.x, max.y, height);
glVertex3f(min.x, max.y, height);
glEnd();
//
if(i){glColor4ub(a.red,a.green,a.blue,a.alpha);glBegin(GL_QUADS);} else {glColor4f(b.red,b.green,b.blue,b.alpha); glBegin(GL_LINE_LOOP);}
glVertex3f(min.x, min.y, 0);
glVertex3f(min.x, max.y, 0);
glVertex3f(min.x, max.y, height);
glVertex3f(min.x, min.y, height);
glEnd();
//
if(i){glColor4ub(a.red,a.green,a.blue,a.alpha);glBegin(GL_QUADS);} else {glColor4f(b.red,b.green,b.blue,b.alpha); glBegin(GL_LINE_LOOP);}
glVertex3f(max.x, min.y, 0);
glVertex3f(max.x, max.y, 0);
glVertex3f(max.x, max.y, height);
glVertex3f(max.x, min.y, height);
glEnd();
}
glDisable(GL_DEPTH_TEST);
}
glDisable(GL_BLEND);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void TerrainEditor::addUndo(Vector<Selection *> & list, Selection * sel)
{
AssertFatal(sel!=NULL, "TerrainEditor::addUndo - invalid selection");
list.push_front(sel);
if(list.size() == mUndoLimit)
{
Selection * undo = list[list.size()-1];
delete undo;
list.pop_back();
}
setDirty();
}
void TerrainEditor::clearUndo(Vector<Selection *> & list)
{
for(U32 i = 0; i < list.size(); i++)
delete list[i];
list.clear();
}
bool TerrainEditor::processUndo(Vector<Selection *> & src, Vector<Selection *> & dest)
{
if(!src.size())
return(false);
Selection * task = src.front();
src.pop_front();
Selection * save = new Selection;
for(U32 i = 0; i < task->size(); i++)
{
GridInfo info;
getGridInfo((*task)[i].mGridPos, info);
save->add(info);
setGridInfo((*task)[i]);
}
gridUpdateComplete();
delete task;
addUndo(dest, save);
rebuild();
return(true);
}
//------------------------------------------------------------------------------
//
void TerrainEditor::rebuild()
{
// empty
if(mRebuildEmpty)
{
mTerrainBlock->rebuildEmptyFlags();
mTerrainBlock->packEmptySquares();
mRebuildEmpty = false;
}
}
//------------------------------------------------------------------------------
void TerrainEditor::on3DMouseUp(const Gui3DMouseEvent & event)
{
if(!mTerrainBlock)
return;
if(isMouseLocked())
{
mouseUnlock();
mMouseDownSeq++;
mCurrentAction->process(mMouseBrush, event, false, TerrainAction::End);
setCursor(0);
if(mUndoSel->size())
{
addUndo(mUndoList, mUndoSel);
clearUndo(mRedoList);
}
else
delete mUndoSel;
mUndoSel = 0;
mInAction = false;
rebuild();
}
}
class TerrainProcessActionEvent : public SimEvent
{
U32 mSequence;
public:
TerrainProcessActionEvent(U32 seq)
{
mSequence = seq;
}
void process(SimObject *object)
{
((TerrainEditor *) object)->processActionTick(mSequence);
}
};
void TerrainEditor::processActionTick(U32 sequence)
{
if(mMouseDownSeq == sequence)
{
Sim::postEvent(this, new TerrainProcessActionEvent(mMouseDownSeq), Sim::getCurrentTime() + 30);
mCurrentAction->process(mMouseBrush, mLastEvent, false, TerrainAction::Update);
}
}
void TerrainEditor::on3DMouseDown(const Gui3DMouseEvent & event)
{
if(!mTerrainBlock)
return;
mSelectionLocked = false;
mouseLock();
mMouseDownSeq++;
mUndoSel = new Selection;
mCurrentAction->process(mMouseBrush, event, true, TerrainAction::Begin);
// process on ticks - every 30th of a second.
Sim::postEvent(this, new TerrainProcessActionEvent(mMouseDownSeq), Sim::getCurrentTime() + 30);
}
void TerrainEditor::on3DMouseMove(const Gui3DMouseEvent & event)
{
if(!mTerrainBlock)
return;
Point3F pos;
if(!collide(event, pos))
{
mMouseBrush->reset();
mCursorVisible = true;
}
else
{
//
if(mRenderBrush)
mCursorVisible = false;
mMousePos = pos;
mMouseBrush->setPosition(mMousePos);
}
}
void TerrainEditor::on3DMouseDragged(const Gui3DMouseEvent & event)
{
if(!mTerrainBlock)
return;
if(!isMouseLocked())
return;
Point3F pos;
if(!mSelectionLocked)
{
if(!collide(event, pos))
{
mMouseBrush->reset();
return;
}
}
// check if the mouse has actually moved in grid space
bool selChanged = false;
if(!mSelectionLocked)
{
Point2I gMouse;
Point2I gLastMouse;
worldToGrid(pos, gMouse);
worldToGrid(mMousePos, gLastMouse);
//
mMousePos = pos;
mMouseBrush->setPosition(mMousePos);
selChanged = gMouse != gLastMouse;
}
if(selChanged)
mCurrentAction->process(mMouseBrush, event, true, TerrainAction::Update);
}
void TerrainEditor::getCursor(GuiCursor *&cursor, bool &visible, const GuiEvent &event)
{
event;
cursor = mCurrentCursor;
visible = mCursorVisible;
}
//------------------------------------------------------------------------------
// any console function which depends on a terrainBlock attached to the editor
// should call this
bool checkTerrainBlock(TerrainEditor * object, const char * funcName)
{
if(!object->terrainBlockValid())
{
Con::errorf(ConsoleLogEntry::Script, "TerrainEditor::%s: not attached to a terrain block!", funcName);
return(false);
}
return(true);
}
//------------------------------------------------------------------------------
static void findObjectsCallback(SceneObject* obj, void *val)
{
Vector<SceneObject*> * list = (Vector<SceneObject*>*)val;
list->push_back(obj);
}
// XA: Methods added for interfacing with the consoleMethods.
void TerrainEditor::attachTerrain(TerrainBlock *terrBlock)
{
mTerrainBlock = terrBlock;
}
void TerrainEditor::setBrushType(const char* type)
{
if(!dStricmp(type, "box"))
{
delete mMouseBrush;
mMouseBrush = new BoxBrush(this);
}
#ifdef TGE_RPG///TGE_TerrainScene
else if(!dStricmp(type, "hline"))
{
delete mMouseBrush;
mMouseBrush = new HLineBrush(this);
}
else if(!dStricmp(type, "vline"))
{
delete mMouseBrush;
mMouseBrush = new VLineBrush(this);
}
#endif
else if(!dStricmp(type, "ellipse"))
{
delete mMouseBrush;
mMouseBrush = new EllipseBrush(this);
}
else if(!dStricmp(type, "selection"))
{
delete mMouseBrush;
mMouseBrush = new SelectionBrush(this);
}
else {}
}
void TerrainEditor::setBrushSize(S32 w, S32 h)
{
mBrushSize.set(w, h);
mMouseBrush->setSize(mBrushSize);
}
const char* TerrainEditor::getBrushPos()
{
AssertFatal(mMouseBrush!=NULL, "TerrainEditor::getBrushPos: no mouse brush!");
Point2I pos = mMouseBrush->getPosition();
char * ret = Con::getReturnBuffer(32);
dSprintf(ret, sizeof(ret), "%d %d", pos.x, pos.y);
return(ret);
}
void TerrainEditor::setBrushPos(Point2I pos)
{
AssertFatal(mMouseBrush!=NULL, "TerrainEditor::setBrushPos: no mouse brush!");
mMouseBrush->setPosition(pos);
}
void TerrainEditor::setAction(const char* action)
{
for(U32 i = 0; i < mActions.size(); i++)
{
if(!dStricmp(mActions[i]->getName(), action))
{
mCurrentAction = mActions[i];
//
mRenderBrush = mCurrentAction->useMouseBrush();
return;
}
}
}
const char* TerrainEditor::getActionName(U32 index)
{
if(index >= mActions.size())
return("");
return(mActions[index]->getName());
}
const char* TerrainEditor::getCurrentAction()
{
return(mCurrentAction->getName());
}
S32 TerrainEditor::getNumActions()
{
return(mActions.size());
}
void TerrainEditor::resetSelWeights(bool clear)
{
//
if(!clear)
{
for(U32 i = 0; i < mDefaultSel.size(); i++)
{
mDefaultSel[i].mPrimarySelect = false;
mDefaultSel[i].mWeight = 1.f;
}
return;
}
Selection sel;
U32 i;
for(i = 0; i < mDefaultSel.size(); i++)
{
if(mDefaultSel[i].mPrimarySelect)
{
mDefaultSel[i].mWeight = 1.f;
sel.add(mDefaultSel[i]);
}
}
mDefaultSel.reset();
for(i = 0; i < sel.size(); i++)
mDefaultSel.add(sel[i]);
}
void TerrainEditor::undo()
{
if(!checkTerrainBlock(this, "undoAction"))
return;
processUndo(mUndoList, mRedoList);
}
void TerrainEditor::redo()
{
if(!checkTerrainBlock(this, "redoAction"))
return;
processUndo(mRedoList, mUndoList);
}
void TerrainEditor::clearSelection()
{
mDefaultSel.reset();
}
void TerrainEditor::processAction(const char* sAction)
{
if(!checkTerrainBlock(this, "processAction"))
return;
TerrainAction * action = mCurrentAction;
if(sAction != "")
{
action = lookupAction(sAction);
if(!action)
{
Con::errorf(ConsoleLogEntry::General, "TerrainEditor::cProcessAction: invalid action name '%s'.", sAction);
return;
}
}
if(!getCurrentSel()->size() && !mProcessUsesBrush)
return;
mUndoSel = new Selection;
Gui3DMouseEvent event;
if(mProcessUsesBrush)
action->process(mMouseBrush, event, true, TerrainAction::Process);
else
action->process(getCurrentSel(), event, true, TerrainAction::Process);
rebuild();
// check if should delete the undo
if(mUndoSel->size())
{
addUndo(mUndoList, mUndoSel);
clearUndo(mRedoList);
}
else
delete mUndoSel;
mUndoSel = 0;
}
void TerrainEditor::buildMaterialMap()
{
if(!checkTerrainBlock(this, "buildMaterialMap"))
return;
mTerrainBlock->buildMaterialMap();
}
S32 TerrainEditor::getNumTextures()
{
if(!checkTerrainBlock(this, "getNumTextures"))
return(0);
// walk all the possible material lists and count them..
U32 count = 0;
for(U32 i = 0; i < TerrainBlock::MaterialGroups; i++)
if(mTerrainBlock->mMaterialFileName[i] &&
*mTerrainBlock->mMaterialFileName[i])
count++;
return count;
}
const char* TerrainEditor::getTextureName(S32 group)
{
if(!checkTerrainBlock(this, "getTextureName"))
return("");
#ifdef TGE_RPGCLIENT2 /// TGE_RPGGhost
TerrainBlock * terrBlock = mTerrainBlock;
#else
// textures only exist on the client..
NetConnection * toServer = NetConnection::getConnectionToServer();
NetConnection * toClient = NetConnection::getLocalClientConnection();
S32 index = toClient->getGhostIndex(mTerrainBlock);
TerrainBlock * terrBlock = dynamic_cast<TerrainBlock*>(toServer->resolveGhost(index));
#endif
if(!terrBlock)
return("");
// possibly in range?
if(group < 0 || group >= TerrainBlock::MaterialGroups)
return("");
// now find the i-th group
U32 count = 0;
bool found = false;
for(U32 i = 0; !found && (i < TerrainBlock::MaterialGroups); i++)
{
// count it
if(terrBlock->mMaterialFileName[i] &&
*terrBlock->mMaterialFileName[i])
count++;
if((group + 1) == count)
{
group = i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -