📄 terraineditor.cc
字号:
found = true;
}
}
if(!found)
return("");
return terrBlock->mMaterialFileName[group];
}
void TerrainEditor::markEmptySquares()
{
if(!checkTerrainBlock(this, "markEmptySquares"))
return;
// build a list of all the marked interiors
Vector<InteriorInstance*> interiors;
U32 mask = InteriorObjectType;
gServerContainer.findObjects(mask, findObjectsCallback, &interiors);
// walk the terrain and empty any grid which clips to an interior
for(U32 x = 0; x < TerrainBlock::BlockSize; x++)
for(U32 y = 0; y < TerrainBlock::BlockSize; y++)
{
TerrainBlock::Material * material = mTerrainBlock->getMaterial(x,y);
material->flags |= ~(TerrainBlock::Material::Empty);
Point3F a, b;
gridToWorld(Point2I(x,y), a);
gridToWorld(Point2I(x+1,y+1), b);
Box3F box;
box.min = a;
box.max = b;
box.min.setMin(b);
box.max.setMax(a);
const MatrixF & terrOMat = mTerrainBlock->getTransform();
const MatrixF & terrWMat = mTerrainBlock->getWorldTransform();
terrWMat.mulP(box.min);
terrWMat.mulP(box.max);
for(U32 i = 0; i < interiors.size(); i++)
{
MatrixF mat = interiors[i]->getWorldTransform();
mat.scale(interiors[i]->getScale());
mat.mul(terrOMat);
U32 waterMark = FrameAllocator::getWaterMark();
U16* zoneVector = (U16*)FrameAllocator::alloc(interiors[i]->getDetailLevel(0)->getNumZones());
U32 numZones = 0;
interiors[i]->getDetailLevel(0)->scanZones(box, mat,
zoneVector, &numZones);
if (numZones != 0)
{
Con::printf("%d %d", x, y);
material->flags |= TerrainBlock::Material::Empty;
FrameAllocator::setWaterMark(waterMark);
break;
}
FrameAllocator::setWaterMark(waterMark);
}
}
// rebuild stuff..
mTerrainBlock->buildGridMap();
mTerrainBlock->rebuildEmptyFlags();
mTerrainBlock->packEmptySquares();
}
void TerrainEditor::clearModifiedFlags()
{
if(!checkTerrainBlock(this, "clearModifiedFlags"))
return;
//
for(U32 i = 0; i < (TerrainBlock::BlockSize * TerrainBlock::BlockSize); i++)
mTerrainBlock->materialMap[i].flags &= ~TerrainBlock::Material::Modified;
}
void TerrainEditor::mirrorTerrain(S32 mirrorIndex)
{
if(!checkTerrainBlock(this, "mirrorTerrain"))
return;
TerrainBlock * terrain = mTerrainBlock;
setDirty();
//
enum {
top = BIT(0),
bottom = BIT(1),
left = BIT(2),
right = BIT(3)
};
U32 sides[8] =
{
bottom,
bottom | left,
left,
left | top,
top,
top | right,
right,
bottom | right
};
U32 n = TerrainBlock::BlockSize;
U32 side = sides[mirrorIndex % 8];
bool diag = mirrorIndex & 0x01;
Point2I src((side & right) ? (n - 1) : 0, (side & bottom) ? (n - 1) : 0);
Point2I dest((side & left) ? (n - 1) : 0, (side & top) ? (n - 1) : 0);
Point2I origSrc(src);
Point2I origDest(dest);
// determine the run length
U32 minStride = ((side & top) || (side & bottom)) ? n : n / 2;
U32 majStride = ((side & left) || (side & right)) ? n : n / 2;
Point2I srcStep((side & right) ? -1 : 1, (side & bottom) ? -1 : 1);
Point2I destStep((side & left) ? -1 : 1, (side & top) ? -1 : 1);
//
U16 * heights = terrain->getHeightAddress(0,0);
U8 * baseMaterials = terrain->getBaseMaterialAddress(0,0);
TerrainBlock::Material * materials = terrain->getMaterial(0,0);
// create an undo selection
Selection * undo = new Selection;
// walk through all the positions
for(U32 i = 0; i < majStride; i++)
{
for(U32 j = 0; j < minStride; j++)
{
// skip the same position
if(src != dest)
{
U32 si = src.x + (src.y << TerrainBlock::BlockShift);
U32 di = dest.x + (dest.y << TerrainBlock::BlockShift);
// add to undo selection
GridInfo info;
getGridInfo(dest, info);
undo->add(info);
//... copy info... (height, basematerial, material)
heights[di] = heights[si];
baseMaterials[di] = baseMaterials[si];
materials[di] = materials[si];
}
// get to the new position
src.x += srcStep.x;
diag ? (dest.y += destStep.y) : (dest.x += destStep.x);
}
// get the next position for a run
src.y += srcStep.y;
diag ? (dest.x += destStep.x) : (dest.y += destStep.y);
// reset the minor run
src.x = origSrc.x;
diag ? (dest.y = origDest.y) : (dest.x = origDest.x);
// shorten the run length for diag runs
if(diag)
minStride--;
}
// rebuild stuff..
terrain->buildGridMap();
terrain->rebuildEmptyFlags();
terrain->packEmptySquares();
// add undo selection to undo list and clear redo
addUndo(mUndoList, undo);
clearUndo(mRedoList);
}
void TerrainEditor::popBaseMaterialInfo()
{
if(!checkTerrainBlock(this, "popMaterialInfo"))
return;
if(!mBaseMaterialInfos.size())
return;
TerrainBlock * terrain = mTerrainBlock;
BaseMaterialInfo * info = mBaseMaterialInfos.front();
// names
for(U32 i = 0; i < TerrainBlock::MaterialGroups; i++)
terrain->mMaterialFileName[i] = info->mMaterialNames[i];
// base materials
dMemcpy(terrain->mBaseMaterialMap, info->mBaseMaterials,
TerrainBlock::BlockSize * TerrainBlock::BlockSize);
// kill it..
delete info;
mBaseMaterialInfos.pop_front();
// rebuild
terrain->refreshMaterialLists();
terrain->buildGridMap();
}
void TerrainEditor::pushBaseMaterialInfo()
{
if(!checkTerrainBlock(this, "pushMaterialInfo"))
return;
TerrainBlock * terrain = mTerrainBlock;
BaseMaterialInfo * info = new BaseMaterialInfo;
// copy the material list names
for(U32 i = 0; i < TerrainBlock::MaterialGroups; i++)
info->mMaterialNames[i] = terrain->mMaterialFileName[i];
// copy the base materials
dMemcpy(info->mBaseMaterials, terrain->mBaseMaterialMap,
TerrainBlock::BlockSize * TerrainBlock::BlockSize);
mBaseMaterialInfos.push_front(info);
}
void TerrainEditor::setLoneBaseMaterial(const char* materialListBaseName)
{
if(!checkTerrainBlock(this, "setLoneBaseMaterial"))
return;
TerrainBlock * terrain = mTerrainBlock;
// force the material group
terrain->mMaterialFileName[0] = StringTable->insert(materialListBaseName);
dMemset(terrain->getBaseMaterialAddress(0,0),
TerrainBlock::BlockSize * TerrainBlock::BlockSize, 0);
terrain->refreshMaterialLists();
terrain->buildGridMap();
}
//------------------------------------------------------------------------------
ConsoleMethod( TerrainEditor, attachTerrain, void, 2, 3, "(TerrainBlock terrain)")
{
TerrainBlock * terrBlock = 0;
SimSet * missionGroup = dynamic_cast<SimSet*>(Sim::findObject("MissionGroup"));
if(!missionGroup)
{
Con::errorf(ConsoleLogEntry::Script, "TerrainEditor::attach: no mission group found");
return;
}
// attach to first found terrainBlock
if(argc == 2)
{
for(SimSetIterator itr(missionGroup); *itr; ++itr)
{
terrBlock = dynamic_cast<TerrainBlock*>(*itr);
if(terrBlock)
break;
}
if(!terrBlock)
Con::errorf(ConsoleLogEntry::Script, "TerrainEditor::attach: no TerrainBlock objects found!");
}
else // attach to named object
{
terrBlock = dynamic_cast<TerrainBlock*>(Sim::findObject(argv[2]));
if(!terrBlock)
Con::errorf(ConsoleLogEntry::Script, "TerrainEditor::attach: failed to attach to object '%s'", argv[2]);
}
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsServerObject
if(terrBlock && !terrBlock->isServerObject())
{
Con::errorf(ConsoleLogEntry::Script, "TerrainEditor::attach: cannot attach to client TerrainBlock");
terrBlock = 0;
}
#endif
object->attachTerrain(terrBlock);
}
ConsoleMethod( TerrainEditor, setBrushType, void, 3, 3, "(string type)"
"One of box, ellipse, selection.")
{
object->setBrushType(argv[2]);
}
ConsoleMethod( TerrainEditor, setBrushSize, void, 4, 4, "(int w, int h)")
{
S32 w = dAtoi(argv[2]);
S32 h = dAtoi(argv[3]);
//
if(w < 1 || w > Brush::MaxBrushDim || h < 1 || h > Brush::MaxBrushDim)
{
Con::errorf(ConsoleLogEntry::General, "TerrainEditor::cSetBrushSize: invalid brush dimension. [1-%d].", Brush::MaxBrushDim);
return;
}
object->setBrushSize(w, h);
}
ConsoleMethod( TerrainEditor, getBrushPos, const char*, 2, 2, "Returns a Point2I.")
{
return object->getBrushPos();
}
ConsoleMethod( TerrainEditor, setBrushPos, void, 3, 4, "(int x, int y)")
{
//
Point2I pos;
if(argc == 3)
dSscanf(argv[2], "%d %d", &pos.x, &pos.y);
else
{
pos.x = dAtoi(argv[2]);
pos.y = dAtoi(argv[3]);
}
object->setBrushPos(pos);
}
ConsoleMethod( TerrainEditor, setAction, void, 3, 3, "(string action_name)")
{
object->setAction(argv[2]);
}
ConsoleMethod( TerrainEditor, getActionName, const char*, 3, 3, "(int num)")
{
return (object->getActionName(dAtoi(argv[2])));
}
ConsoleMethod( TerrainEditor, getNumActions, S32, 2, 2, "")
{
return(object->getNumActions());
}
ConsoleMethod( TerrainEditor, getCurrentAction, const char*, 2, 2, "")
{
return object->getCurrentAction();
}
ConsoleMethod( TerrainEditor, resetSelWeights, void, 3, 3, "(bool clear)")
{
object->resetSelWeights(dAtob(argv[2]));
}
ConsoleMethod( TerrainEditor, undo, void, 2, 2, "")
{
object->undo();
}
ConsoleMethod( TerrainEditor, redo, void, 2, 2, "")
{
object->redo();
}
ConsoleMethod( TerrainEditor, clearSelection, void, 2, 2, "")
{
object->clearSelection();
}
ConsoleMethod( TerrainEditor, processAction, void, 2, 3, "(string action=NULL)")
{
if(argc == 3)
object->processAction(argv[2]);
else object->processAction("");
}
ConsoleMethod( TerrainEditor, buildMaterialMap, void, 2, 2, "")
{
object->buildMaterialMap();
}
ConsoleMethod( TerrainEditor, getNumTextures, S32, 2, 2, "")
{
return object->getNumTextures();
}
ConsoleMethod( TerrainEditor, getTextureName, const char*, 3, 3, "(int index)")
{
return object->getTextureName(dAtoi(argv[2]));
}
ConsoleMethod( TerrainEditor, markEmptySquares, void, 2, 2, "")
{
object->markEmptySquares();
}
ConsoleMethod( TerrainEditor, clearModifiedFlags, void, 2, 2, "")
{
object->clearModifiedFlags();
}
ConsoleMethod( TerrainEditor, mirrorTerrain, void, 3, 3, "")
{
object->mirrorTerrain(dAtoi(argv[2]));
}
ConsoleMethod(TerrainEditor, pushBaseMaterialInfo, void, 2, 2, "")
{
object->pushBaseMaterialInfo();
}
ConsoleMethod( TerrainEditor, popBaseMaterialInfo, void, 2, 2, "")
{
object->popBaseMaterialInfo();
}
ConsoleMethod( TerrainEditor, setLoneBaseMaterial, void, 3, 3, "(string materialListBaseName)")
{
object->setLoneBaseMaterial(argv[2]);
}
ConsoleMethod(TerrainEditor, setTerraformOverlay, void, 3, 3, "(bool overlayEnable) - sets the terraformer current heightmap to draw as an overlay over the current terrain.")
{
// XA: This one needs to be implemented :)
}
ConsoleMethod(TerrainEditor, setTerrainMaterials, void, 3, 3, "(string matList) sets the list of current terrain materials.")
{
TerrainEditor *tEditor = (TerrainEditor *) object;
TerrainBlock *terr = tEditor->getTerrainBlock();
if(!terr)
return;
Resource<TerrainFile> file = terr->getFile();
const char *fileList = argv[2];
for(U32 i = 0; i < TerrainBlock::MaterialGroups; i++)
{
U32 len;
const char *spos = dStrchr(fileList, '\n');
if(!spos)
len = dStrlen(fileList);
else
len = spos - fileList;
if(len)
file->mMaterialFileName[i] = StringTable->insertn(fileList, len, true);
else
file->mMaterialFileName[i] = 0;
fileList += len;
if(*fileList)
fileList++;
}
tEditor->getClientTerrain()->buildMaterialMap();
}
ConsoleMethod(TerrainEditor, getTerrainMaterials, const char *, 2, 2, "() gets the list of current terrain materials.")
{
char *ret = Con::getReturnBuffer(4096);
TerrainEditor *tEditor = (TerrainEditor *) object;
TerrainBlock *terr = tEditor->getTerrainBlock();
if(!terr)
return "";
ret[0] = 0;
Resource<TerrainFile> file = terr->getFile();
for(U32 i = 0; i < TerrainBlock::MaterialGroups; i++)
{
if(file->mMaterialFileName[i])
dStrcat(ret, file->mMaterialFileName[i]);
dStrcat(ret, "\n");
}
return ret;
}
//------------------------------------------------------------------------------
void TerrainEditor::initPersistFields()
{
Parent::initPersistFields();
addGroup("Misc");
addField("isDirty", TypeBool, Offset(mIsDirty, TerrainEditor));
addField("isMissionDirty", TypeBool, Offset(mIsMissionDirty, TerrainEditor));
addField("renderBorder", TypeBool, Offset(mRenderBorder, TerrainEditor));
addField("borderHeight", TypeF32, Offset(mBorderHeight, TerrainEditor));
addField("borderFillColor", TypeColorI, Offset(mBorderFillColor, TerrainEditor));
addField("borderFrameColor", TypeColorI, Offset(mBorderFrameColor, TerrainEditor));
addField("borderLineMode", TypeBool, Offset(mBorderLineMode, TerrainEditor));
addField("selectionHidden", TypeBool, Offset(mSelectionHidden, TerrainEditor));
addField("enableSoftBrushes", TypeBool, Offset(mEnableSoftBrushes, TerrainEditor));
addField("renderVertexSelection", TypeBool, Offset(mRenderVertexSelection, TerrainEditor));
addField("processUsesBrush", TypeBool, Offset(mProcessUsesBrush, TerrainEditor));
// action values...
addField("adjustHeightVal", TypeF32, Offset(mAdjustHeightVal, TerrainEditor));
addField("setHeightVal", TypeF32, Offset(mSetHeightVal, TerrainEditor));
addField("scaleVal", TypeF32, Offset(mScaleVal, TerrainEditor));
addField("smoothFactor", TypeF32, Offset(mSmoothFactor, TerrainEditor));
addField("materialGroup", TypeS32, Offset(mMaterialGroup, TerrainEditor));
addField("softSelectRadius", TypeF32, Offset(mSoftSelectRadius, TerrainEditor));
addField("softSelectFilter", TypeString, Offset(mSoftSelectFilter, TerrainEditor));
addField("softSelectDefaultFilter", TypeString, Offset(mSoftSelectDefaultFilter, TerrainEditor));
addField("adjustHeightMouseScale", TypeF32, Offset(mAdjustHeightMouseScale, TerrainEditor));
addField("paintMaterial", TypeCaseString, Offset(mPaintMaterial, TerrainEditor));
addField("setHeightVal", TypeF32, Offset(mSetHeightVal, TerrainEditor));
#ifdef TGE_RPG /// TGE_TerrainScene
addField("sceneFlag", TypeF32, Offset(m_uSceneFlag, TerrainEditor));
#endif
endGroup("Misc");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -