mirror of
https://github.com/tribes2/engine.git
synced 2026-03-09 23:40:32 +00:00
t2 engine svn checkout
This commit is contained in:
commit
ff569bd2ae
988 changed files with 394180 additions and 0 deletions
537
editor/compTest.cc
Normal file
537
editor/compTest.cc
Normal file
|
|
@ -0,0 +1,537 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "GUI/guiControl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "Core/fileStream.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "GUI/guiScrollCtrl.h"
|
||||
#include "terrain/terrData.h"
|
||||
#include <math.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class CompTest : public GuiScrollContentCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
S32 mHeights[65536];
|
||||
S32 mHeightMin;
|
||||
S32 mHeightMax;
|
||||
void calcMinMax();
|
||||
|
||||
U16 mTerrainHeights[65536];
|
||||
U32 mCurrentIndex;
|
||||
Point2I mHilbertPos;
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
UP,
|
||||
LEFT,
|
||||
DOWN,
|
||||
RIGHT
|
||||
};
|
||||
|
||||
DECLARE_CONOBJECT(CompTest);
|
||||
|
||||
static S32 smShift;
|
||||
static S32 smHisto;
|
||||
static S32 smSaveHiLo;
|
||||
|
||||
static void consoleInit();
|
||||
void onRender(Point2I offset, const RectI & updateRect, GuiControl * firstResponder);
|
||||
void openFile(StringTableEntry fileName);
|
||||
void saveFile(StringTableEntry fileName);
|
||||
void buildRep(StringTableEntry type);
|
||||
void windowCompress();
|
||||
|
||||
TerrainBlock * getTerrainObj();
|
||||
|
||||
// hilbert curve stuff
|
||||
void hilbertFill(S32 level, S32 direction = UP);
|
||||
void move(S32 direction);
|
||||
};
|
||||
|
||||
S32 CompTest::smShift;
|
||||
S32 CompTest::smHisto;
|
||||
S32 CompTest::smSaveHiLo;
|
||||
|
||||
IMPLEMENT_CONOBJECT(CompTest);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void cCompTestOpenFile(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
static_cast<CompTest*>(obj)->openFile(argv[2]);
|
||||
}
|
||||
|
||||
static void cCompTestSaveFile(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
static_cast<CompTest*>(obj)->saveFile(argv[2]);
|
||||
}
|
||||
|
||||
static void cCompTestBuildRep(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
static_cast<CompTest*>(obj)->buildRep(argv[2]);
|
||||
}
|
||||
|
||||
void CompTest::consoleInit()
|
||||
{
|
||||
Con::addCommand("CompTest", "buildRep", cCompTestBuildRep, "compTest.buildRep(type)", 3, 3);
|
||||
Con::addCommand("CompTest", "openFile", cCompTestOpenFile, "compTest.openFile(filename)", 3, 3);
|
||||
Con::addCommand("CompTest", "saveFile", cCompTestSaveFile, "compTest.saveFile(filename)", 3, 3);
|
||||
|
||||
Con::addVariable("CompTestShift", TypeS32, &smShift);
|
||||
Con::addVariable("CompTestHisto", TypeS32, &smHisto);
|
||||
Con::addVariable("CompTestSaveHiLo", TypeS32, &smSaveHiLo);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// BEGIN Hilbert curve stuff
|
||||
void CompTest::move(S32 direction)
|
||||
{
|
||||
switch(direction)
|
||||
{
|
||||
case LEFT:
|
||||
mHilbertPos.x--;
|
||||
break;
|
||||
case RIGHT:
|
||||
mHilbertPos.x++;
|
||||
break;
|
||||
case UP:
|
||||
mHilbertPos.y--;
|
||||
break;
|
||||
case DOWN:
|
||||
mHilbertPos.y++;
|
||||
break;
|
||||
}
|
||||
|
||||
AssertFatal(mCurrentIndex < 256 * 256, "Doh!");
|
||||
AssertFatal(mHilbertPos.x + 256 * mHilbertPos.y < 256 * 256, "Blah!");
|
||||
|
||||
// copy at the hilbert position
|
||||
mHeights[mCurrentIndex++] = mTerrainHeights[mHilbertPos.x + 256 * mHilbertPos.y];
|
||||
}
|
||||
|
||||
void CompTest::hilbertFill(S32 level, S32 direction)
|
||||
{
|
||||
if (level==1) {
|
||||
switch (direction) {
|
||||
case LEFT:
|
||||
move(RIGHT); /* move() could draw a line in... */
|
||||
move(DOWN); /* ...the indicated direction */
|
||||
move(LEFT);
|
||||
break;
|
||||
case RIGHT:
|
||||
move(LEFT);
|
||||
move(UP);
|
||||
move(RIGHT);
|
||||
break;
|
||||
case UP:
|
||||
move(DOWN);
|
||||
move(RIGHT);
|
||||
move(UP);
|
||||
break;
|
||||
case DOWN:
|
||||
move(UP);
|
||||
move(LEFT);
|
||||
move(DOWN);
|
||||
break;
|
||||
} /* switch */
|
||||
} else {
|
||||
switch (direction) {
|
||||
case LEFT:
|
||||
hilbertFill(level-1,UP);
|
||||
move(RIGHT);
|
||||
hilbertFill(level-1,LEFT);
|
||||
move(DOWN);
|
||||
hilbertFill(level-1,LEFT);
|
||||
move(LEFT);
|
||||
hilbertFill(level-1,DOWN);
|
||||
break;
|
||||
case RIGHT:
|
||||
hilbertFill(level-1,DOWN);
|
||||
move(LEFT);
|
||||
hilbertFill(level-1,RIGHT);
|
||||
move(UP);
|
||||
hilbertFill(level-1,RIGHT);
|
||||
move(RIGHT);
|
||||
hilbertFill(level-1,UP);
|
||||
break;
|
||||
case UP:
|
||||
hilbertFill(level-1,LEFT);
|
||||
move(DOWN);
|
||||
hilbertFill(level-1,UP);
|
||||
move(RIGHT);
|
||||
hilbertFill(level-1,UP);
|
||||
move(UP);
|
||||
hilbertFill(level-1,RIGHT);
|
||||
break;
|
||||
case DOWN:
|
||||
hilbertFill(level-1,RIGHT);
|
||||
move(UP);
|
||||
hilbertFill(level-1,DOWN);
|
||||
move(LEFT);
|
||||
hilbertFill(level-1,DOWN);
|
||||
move(DOWN);
|
||||
hilbertFill(level-1,LEFT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// END Hilbert curve stuff
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static S32 QSORT_CALLBACK sortHisto(const void * a, const void * b)
|
||||
{
|
||||
S16 intA = *((S16*)a);
|
||||
S16 intB = *((S16*)b);
|
||||
return(intA == intB ? 0 : intA > intB ? -1 : 1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
TerrainBlock * CompTest::getTerrainObj()
|
||||
{
|
||||
// get the terrain obj
|
||||
SimObject* obj = Sim::findObject("Terrain");
|
||||
if(!obj)
|
||||
return(0);
|
||||
TerrainBlock * terrain = static_cast<TerrainBlock *>(obj);
|
||||
return(terrain);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CompTest::windowCompress()
|
||||
{
|
||||
U16 window[32];
|
||||
S32 size = 32 * 16;
|
||||
S32 windowCount = 0;
|
||||
S32 i;
|
||||
for(i = 0; i < 65536 && windowCount < 32; i++)
|
||||
{
|
||||
U16 h = mHeights[i];
|
||||
S32 j;
|
||||
for(j = 0; j < windowCount;j++)
|
||||
if(window[j] == h)
|
||||
break;
|
||||
if(j == windowCount)
|
||||
window[windowCount++] = h;
|
||||
}
|
||||
S32 runStart = 0;
|
||||
S32 runCount = 0;
|
||||
S32 winPos = 0;
|
||||
for(i = 0; i < 65536; i++)
|
||||
{
|
||||
U16 h = mHeights[i];
|
||||
S32 j;
|
||||
for(j = 0; j < windowCount; j++)
|
||||
if(h == window[j])
|
||||
break;
|
||||
if(j == windowCount)
|
||||
{
|
||||
size += runCount * 5 + 32;
|
||||
window[winPos++] = h;
|
||||
if(winPos == windowCount)
|
||||
winPos = 0;
|
||||
runStart = i+1;
|
||||
runCount = 0;
|
||||
}
|
||||
else
|
||||
runCount++;
|
||||
}
|
||||
Con::printf("Compressed size: %d", size >> 3);
|
||||
}
|
||||
|
||||
void CompTest::buildRep(StringTableEntry type)
|
||||
{
|
||||
TerrainBlock * terrain = getTerrainObj();
|
||||
if(!terrain)
|
||||
return;
|
||||
|
||||
U16 *htcpy = terrain->heightMap;
|
||||
|
||||
for(S32 y = 0; y < 256; y++)
|
||||
for(S32 x = 0; x < 256; x++)
|
||||
mTerrainHeights[y * 256 + x] = htcpy[y * 257 + x];
|
||||
|
||||
// check for shift
|
||||
if(smShift)
|
||||
for(U32 i = 0; i < 256<<8; i++)
|
||||
mTerrainHeights[i] >>= smShift;
|
||||
|
||||
// just copy
|
||||
if(!dStricmp(type, "baseline"))
|
||||
{
|
||||
for(U32 i = 0; i < 256 * 256; i++)
|
||||
mHeights[i] = mTerrainHeights[i];
|
||||
}
|
||||
// hilbert curve
|
||||
else if(!dStricmp(type, "hilbert"))
|
||||
{
|
||||
mHilbertPos.x = mHilbertPos.y = 0;
|
||||
mHeights[0] = mTerrainHeights[0];
|
||||
mCurrentIndex = 1;
|
||||
hilbertFill(8,UP);
|
||||
}
|
||||
// MarkF delta type
|
||||
else if(!dStricmp(type, "delta"))
|
||||
{
|
||||
for(U32 y = 0; y < 256; y++)
|
||||
for(U32 x = 0; x < 256; x++)
|
||||
{
|
||||
U16 h1 = mTerrainHeights[x + (y<<8)];
|
||||
U16 h2 = mTerrainHeights[((x+1) % 256) + (y << 8)];
|
||||
U16 h3 = mTerrainHeights[x + (((y+1) % 256) << 8)];
|
||||
U16 h4 = mTerrainHeights[((x+1) % 256) + (((y+1) % 256) << 8)];
|
||||
mHeights[x + (y<<8)] = h4 - h1 + (h2 - h1) + (h3 - h1);
|
||||
}
|
||||
}
|
||||
else if(!dStricmp(type, "delta2"))
|
||||
{
|
||||
U16 prevHeight = 0;
|
||||
for(U32 i = 0; i < 65536; i++)
|
||||
{
|
||||
mHeights[i] = mTerrainHeights[i] - prevHeight;
|
||||
prevHeight = mTerrainHeights[i];
|
||||
}
|
||||
}
|
||||
else if(!dStricmp(type, "delta3"))
|
||||
{
|
||||
mHeights[0] = mTerrainHeights[0];
|
||||
S32 delta = mTerrainHeights[0] / 2;
|
||||
S32 deltaPrev = mTerrainHeights[0] - delta;
|
||||
for(U32 i = 0; i < 65536; i++)
|
||||
{
|
||||
S32 ph = mTerrainHeights[i-1];
|
||||
S32 h = mTerrainHeights[i];
|
||||
|
||||
mHeights[i] = h - ph - ((delta + deltaPrev) >> 1);
|
||||
deltaPrev = delta;
|
||||
delta = h - ph;
|
||||
}
|
||||
/*for(U32 y = 0; y < 256; y++)
|
||||
{
|
||||
U32 prevy = (y - 1) & 0xFF;
|
||||
|
||||
U16 *prevRow = mTerrainHeights + prevy * 256;
|
||||
U16 *curRow = mTerrainHeights + y * 256;
|
||||
S16 *dest = mHeights + y *256;
|
||||
for(U32 x = 0; x < 256; x++)
|
||||
dest[x] = curRow[x] - prevRow[x];
|
||||
}*/
|
||||
/* U16 prevDelta = 0;
|
||||
U16 prevHeight = 0;
|
||||
for(U32 i = 0; i < 65536; i++)
|
||||
{
|
||||
U16 h = mTerrainHeights[i];
|
||||
mHeights[i] = h - (prevHeight + prevDelta);
|
||||
prevHeight = h;
|
||||
prevDelta = mHeights[i];
|
||||
}
|
||||
prevHeight = 0;
|
||||
prevDelta = 0;
|
||||
for(U32 i = 0; i < 65536; i++)
|
||||
{
|
||||
U16 newDelta = mHeights[i];
|
||||
mHeights[i] = prevHeight + prevDelta + newDelta;
|
||||
prevDelta = newDelta;
|
||||
prevHeight = mHeights[i];
|
||||
}*/
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
// check for histo display
|
||||
windowCompress();
|
||||
if(smHisto)
|
||||
{
|
||||
S16 *hist = new S16[256*256];
|
||||
U32 i;
|
||||
for(i = 0; i < 256*256; i++)
|
||||
hist[i] = 0;
|
||||
for(i = 0; i < 256*256; i++)
|
||||
hist[U16(mHeights[i])]++;
|
||||
|
||||
dQsort(hist, 256*256, 2, sortHisto);
|
||||
for(i = 0; i < 256*256; i++)
|
||||
mHeights[i] = hist[i];
|
||||
|
||||
U32 used = 0;
|
||||
for(i = 0; i < 256*256; i++)
|
||||
if(mHeights[i])
|
||||
used++;
|
||||
delete [] hist;
|
||||
|
||||
Con::printf("compTest => number of unique histogram entries: %d", used);
|
||||
F32 sum = 0;
|
||||
for(i = 0; i < 65536; i++)
|
||||
{
|
||||
if(hist[i] == 0)
|
||||
continue;
|
||||
F32 p = hist[i] / 65536.0f;
|
||||
sum += p * log(p) / log(2.0);
|
||||
}
|
||||
Con::printf("Compressability sum: %f", -sum);
|
||||
}
|
||||
calcMinMax();
|
||||
|
||||
Con::printf("compTest => min/max terrain height: %f / %f",
|
||||
F32(mHeightMin) * 0.03125, F32(mHeightMax) * 0.03125);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CompTest::calcMinMax()
|
||||
{
|
||||
mHeightMin = 32000;
|
||||
mHeightMax = -32000;
|
||||
|
||||
for(U32 i = 0; i < (256*256); i++)
|
||||
{
|
||||
if(mHeights[i] < mHeightMin)
|
||||
mHeightMin = mHeights[i];
|
||||
if(mHeights[i] > mHeightMax)
|
||||
mHeightMax = mHeights[i];
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CompTest::openFile(StringTableEntry fileName)
|
||||
{
|
||||
if(!fileName || !dStrlen(fileName))
|
||||
return;
|
||||
|
||||
FileStream file;
|
||||
if(!file.open(fileName, FileStream::Read))
|
||||
return;
|
||||
|
||||
for(U32 i = 0; i < (256*256); i++)
|
||||
{
|
||||
if(!file.read(&mHeights[i]))
|
||||
return;
|
||||
}
|
||||
calcMinMax();
|
||||
}
|
||||
|
||||
void CompTest::saveFile(StringTableEntry fileName)
|
||||
{
|
||||
if(!fileName || !dStrlen(fileName) || !mHeights)
|
||||
return;
|
||||
|
||||
FileStream file;
|
||||
file.open(fileName, FileStream::ReadWrite);
|
||||
U32 i;
|
||||
for(i = 0; i < (256*256); i++)
|
||||
file.write(mHeights[i]);
|
||||
file.close();
|
||||
|
||||
if(smSaveHiLo)
|
||||
{
|
||||
// save lo data
|
||||
file.open("lo_byte.out", FileStream::ReadWrite);
|
||||
for(i = 0; i < (256*256); i++)
|
||||
{
|
||||
U8 out = mHeights[i];
|
||||
file.write(out);
|
||||
}
|
||||
// save high data
|
||||
file.open("hi_byte.out", FileStream::ReadWrite);
|
||||
for(i = 0; i < (256*256); i++)
|
||||
{
|
||||
U8 out = mHeights[i] >> 8;
|
||||
file.write(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CompTest::onRender(Point2I offset, const RectI & updateRect, GuiControl * firstResponder)
|
||||
{
|
||||
firstResponder;
|
||||
if(!mHeights)
|
||||
return;
|
||||
|
||||
dglSetViewport(updateRect);
|
||||
|
||||
GuiControl * parent = getParent();
|
||||
if(!parent)
|
||||
return;
|
||||
|
||||
Point2I parentOff = parent->localToGlobalCoord(Point2I(0,0));
|
||||
offset -= parentOff;
|
||||
|
||||
// clear the background only
|
||||
// glClear(GL_COLOR_BUFFER_BIT);
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(0.2, 0.2, 0.2);
|
||||
glVertex2f(updateRect.point.x, updateRect.point.y);
|
||||
glVertex2f(updateRect.point.x + updateRect.extent.x, updateRect.point.y);
|
||||
glVertex2f(updateRect.point.x + updateRect.extent.x, updateRect.point.y + updateRect.extent.y);
|
||||
glVertex2f(updateRect.point.x, updateRect.point.y + updateRect.extent.y);
|
||||
glEnd();
|
||||
|
||||
// draw forest, draw!
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(0.8,0,0);
|
||||
|
||||
// check for neg vals
|
||||
if(mHeightMin < 0)
|
||||
{
|
||||
U16 range = mHeightMax > -mHeightMin ? mHeightMax : -mHeightMin;
|
||||
|
||||
for(U32 i = 0; i < updateRect.extent.x; i++)
|
||||
{
|
||||
U32 index = i + -offset.x;
|
||||
if(i >= 256 * 256)
|
||||
break;
|
||||
|
||||
S16 curHeight = mHeights[index];
|
||||
|
||||
F32 bottom = updateRect.point.y + updateRect.extent.y / 2;
|
||||
glVertex2f(i, bottom);
|
||||
|
||||
F32 scale = F32(curHeight) / F32(range);
|
||||
|
||||
F32 top = bottom - F32(updateRect.extent.y / 2) * scale;
|
||||
glVertex2f(i, top);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
U16 range = mHeightMax - mHeightMin;
|
||||
|
||||
F32 maxScale = 0.f;
|
||||
|
||||
for(U32 i = 0; i < updateRect.extent.x; i++)
|
||||
{
|
||||
U32 index = i + -offset.x;
|
||||
if(index >= 256 * 256)
|
||||
break;
|
||||
|
||||
U16 curHeight = mHeights[index];
|
||||
|
||||
F32 bottom = updateRect.point.y + updateRect.extent.y;
|
||||
glVertex2f(updateRect.point.x + i, bottom);
|
||||
|
||||
F32 scale = (F32(curHeight) - F32(mHeightMin)) / F32(range);
|
||||
|
||||
if(scale > maxScale)
|
||||
maxScale = scale;
|
||||
|
||||
F32 top = bottom - F32(updateRect.extent.y) * scale;
|
||||
glVertex2f(updateRect.point.x + i, top);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
465
editor/creator.cc
Normal file
465
editor/creator.cc
Normal file
|
|
@ -0,0 +1,465 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Editor/creator.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(CreatorTree);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Class CreatorTree::Node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
CreatorTree::Node::Node() :
|
||||
mFlags(0),
|
||||
mParent(0),
|
||||
mName(0),
|
||||
mValue(0),
|
||||
mId(0),
|
||||
mTab(0)
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mChildren);
|
||||
}
|
||||
|
||||
CreatorTree::Node::~Node()
|
||||
{
|
||||
for(U32 i = 0; i < mChildren.size(); i++)
|
||||
delete mChildren[i];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CreatorTree::Node::expand(bool exp)
|
||||
{
|
||||
if(exp)
|
||||
{
|
||||
if(mParent)
|
||||
mParent->expand(exp);
|
||||
mFlags.set(Node::Expanded);
|
||||
}
|
||||
else if(!isRoot())
|
||||
{
|
||||
if(isGroup())
|
||||
for(U32 i = 0; i < mChildren.size(); i++)
|
||||
mChildren[i]->expand(exp);
|
||||
|
||||
mFlags.clear(Selected);
|
||||
mFlags.clear(Expanded);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
CreatorTree::Node * CreatorTree::Node::find(S32 id)
|
||||
{
|
||||
if(mId == id)
|
||||
return(this);
|
||||
|
||||
if(!isGroup())
|
||||
return(0);
|
||||
|
||||
for(U32 i = 0; i < mChildren.size(); i++)
|
||||
{
|
||||
Node * node = mChildren[i]->find(id);
|
||||
if(node)
|
||||
return(node);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool CreatorTree::Node::isFirst()
|
||||
{
|
||||
AssertFatal(!isRoot(), "CreatorTree::Node::isFirst - cannot call on root node");
|
||||
return(this == mParent->mChildren[0]);
|
||||
}
|
||||
|
||||
bool CreatorTree::Node::isLast()
|
||||
{
|
||||
AssertFatal(!isRoot(), "CreatorTree::Node::isLast - cannot call on root node");
|
||||
return(this == mParent->mChildren[mParent->mChildren.size()-1]);
|
||||
}
|
||||
|
||||
bool CreatorTree::Node::hasChildItem()
|
||||
{
|
||||
for(U32 i = 0; i < mChildren.size(); i++)
|
||||
{
|
||||
if(mChildren[i]->isGroup() && mChildren[i]->hasChildItem())
|
||||
return(true);
|
||||
|
||||
if(!mChildren[i]->isGroup())
|
||||
return(true);
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
S32 CreatorTree::Node::getSelected()
|
||||
{
|
||||
for(U32 i = 0; i < mChildren.size(); i++)
|
||||
{
|
||||
if(mChildren[i]->isSelected())
|
||||
return(mChildren[i]->mId);
|
||||
else if(mChildren[i]->isGroup())
|
||||
{
|
||||
S32 ret = mChildren[i]->getSelected();
|
||||
if(ret != -1)
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Class CreatorTree
|
||||
//------------------------------------------------------------------------------
|
||||
CreatorTree::CreatorTree() :
|
||||
mCurId(0),
|
||||
mTxtOffset(5),
|
||||
mRoot(0)
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mNodeList);
|
||||
clear();
|
||||
}
|
||||
|
||||
CreatorTree::~CreatorTree()
|
||||
{
|
||||
delete mRoot;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
CreatorTree::Node * CreatorTree::createNode(const char * name, const char * value, bool group, Node * parent)
|
||||
{
|
||||
Node * node = new Node();
|
||||
node->mId = mCurId++;
|
||||
node->mName = name ? StringTable->insert(name) : 0;
|
||||
node->mValue = value ? StringTable->insert(value) : 0;
|
||||
node->mFlags.set(Node::Group, group);
|
||||
|
||||
// add to the parent group
|
||||
if(parent)
|
||||
{
|
||||
node->mParent = parent;
|
||||
if(!addNode(parent, node))
|
||||
{
|
||||
delete node;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CreatorTree::clear()
|
||||
{
|
||||
delete mRoot;
|
||||
mCurId = 0;
|
||||
mRoot = createNode(0, 0, true);
|
||||
mRoot->mFlags.set(Node::Root | Node::Expanded);
|
||||
mSize = Point2I(1,0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool CreatorTree::addNode(Node * parent, Node * node)
|
||||
{
|
||||
if(!parent->isGroup())
|
||||
return(false);
|
||||
|
||||
//
|
||||
parent->mChildren.push_back(node);
|
||||
return(true);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
CreatorTree::Node * CreatorTree::findNode(S32 id)
|
||||
{
|
||||
return(mRoot->find(id));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CreatorTree::sort()
|
||||
{
|
||||
// groups then items by alpha
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static S32 cAddGroup(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
CreatorTree * tree = dynamic_cast<CreatorTree*>(obj);
|
||||
CreatorTree::Node * grp = tree->findNode(dAtoi(argv[2]));
|
||||
|
||||
if(!grp || !grp->isGroup())
|
||||
return(-1);
|
||||
|
||||
// return same named group if found...
|
||||
for(U32 i = 0; i < grp->mChildren.size(); i++)
|
||||
if(!dStricmp(argv[3], grp->mChildren[i]->mName))
|
||||
return(grp->mChildren[i]->mId);
|
||||
|
||||
CreatorTree::Node * node = tree->createNode(argv[3], 0, true, grp);
|
||||
tree->build();
|
||||
return(node ? node->getId() : -1);
|
||||
}
|
||||
|
||||
static S32 cAddItem(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
CreatorTree * tree = dynamic_cast<CreatorTree*>(obj);
|
||||
CreatorTree::Node * grp = tree->findNode(dAtoi(argv[2]));
|
||||
|
||||
if(!grp || !grp->isGroup())
|
||||
return -1;
|
||||
|
||||
CreatorTree::Node * node = tree->createNode(argv[3], argv[4], false, grp);
|
||||
tree->build();
|
||||
return(node ? node->getId() : -1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static bool cFileNameMatch(SimObject *, S32, const char ** argv)
|
||||
{
|
||||
// argv[2] - world short
|
||||
// argv[3] - type short
|
||||
// argv[4] - filename
|
||||
|
||||
// interior filenames
|
||||
// 0 - world short ('b', 'x', ...)
|
||||
// 1-> - type short ('towr', 'bunk', ...)
|
||||
U32 typeLen = dStrlen(argv[3]);
|
||||
if(dStrlen(argv[4]) < (typeLen + 1))
|
||||
return(false);
|
||||
|
||||
// world
|
||||
if(dToupper(argv[4][0]) != dToupper(argv[2][0]))
|
||||
return(false);
|
||||
|
||||
return(!dStrnicmp(argv[4]+1, argv[3], typeLen));
|
||||
}
|
||||
|
||||
static S32 cGetSelected(SimObject * obj, S32, const char **)
|
||||
{
|
||||
CreatorTree * tree = dynamic_cast<CreatorTree*>(obj);
|
||||
return(tree->getSelected());
|
||||
}
|
||||
|
||||
static bool cIsGroup(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
CreatorTree * tree = dynamic_cast<CreatorTree*>(obj);
|
||||
CreatorTree::Node * node = tree->findNode(dAtoi(argv[2]));
|
||||
if(node && node->isGroup())
|
||||
return(true);
|
||||
return(false);
|
||||
}
|
||||
|
||||
static const char * cGetName(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
CreatorTree * tree = dynamic_cast<CreatorTree*>(obj);
|
||||
CreatorTree::Node * node = tree->findNode(dAtoi(argv[2]));
|
||||
return(node ? node->mName : 0);
|
||||
}
|
||||
|
||||
static const char * cGetValue(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
CreatorTree * tree = dynamic_cast<CreatorTree*>(obj);
|
||||
CreatorTree::Node * node = tree->findNode(dAtoi(argv[2]));
|
||||
return(node ? node->mValue : 0);
|
||||
}
|
||||
|
||||
static void cClear(SimObject * obj, S32, const char **)
|
||||
{
|
||||
CreatorTree * tree = dynamic_cast<CreatorTree*>(obj);
|
||||
tree->clear();
|
||||
}
|
||||
|
||||
static S32 cGetParent(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
CreatorTree * tree = dynamic_cast<CreatorTree*>(obj);
|
||||
CreatorTree::Node * node = tree->findNode(dAtoi(argv[2]));
|
||||
if(node && node->mParent)
|
||||
return(node->mParent->getId());
|
||||
else
|
||||
return(-1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CreatorTree::consoleInit()
|
||||
{
|
||||
Con::addCommand("CreatorTree", "fileNameMatch", cFileNameMatch, "creator.fileNameMatch(world, type, filename);", 5, 5);
|
||||
Con::addCommand("CreatorTree", "addGroup", cAddGroup, "creator.addGroup(parent, group);", 4, 4);
|
||||
Con::addCommand("CreatorTree", "addItem", cAddItem, "creator.addItem(group, name, value);", 5, 5);
|
||||
Con::addCommand("CreatorTree", "getSelected", cGetSelected, "creator.getSelected();", 2, 2);
|
||||
Con::addCommand("CreatorTree", "isGroup", cIsGroup, "creator.isGroup(id);", 3, 3);
|
||||
Con::addCommand("CreatorTree", "getName", cGetName, "creator.getName(id);", 3, 3);
|
||||
Con::addCommand("CreatorTree", "getValue", cGetValue, "creator.getValue(id);", 3, 3);
|
||||
Con::addCommand("CreatorTree", "clear", cClear, "creator.clear();", 2, 2);
|
||||
Con::addCommand("CreatorTree", "getParent", cGetParent, "creator.getParent(id);", 3, 3);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CreatorTree::buildNode(Node * node, U32 tab)
|
||||
{
|
||||
if(node->isExpanded())
|
||||
for(U32 i = 0; i < node->mChildren.size(); i++)
|
||||
{
|
||||
Node * child = node->mChildren[i];
|
||||
child->mTab = tab;
|
||||
child->select(false);
|
||||
mNodeList.push_back(child);
|
||||
|
||||
// grab width
|
||||
if(bool(mProfile->mFont) && child->mName)
|
||||
{
|
||||
S32 width = (tab + 1) * mTabSize + mProfile->mFont->getStrWidth(child->mName) + mTxtOffset;
|
||||
if(width > mMaxWidth)
|
||||
mMaxWidth = width;
|
||||
}
|
||||
|
||||
if(node->mChildren[i]->isGroup())
|
||||
buildNode(node->mChildren[i], tab+1);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CreatorTree::build()
|
||||
{
|
||||
mMaxWidth = 0;
|
||||
mNodeList.clear();
|
||||
buildNode(mRoot, 0);
|
||||
mCellSize.set(mMaxWidth+1, mBitmapBounds[BmpParentContinue].extent.y);
|
||||
setSize(Point2I(1, mNodeList.size()));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool CreatorTree::onWake()
|
||||
{
|
||||
if(!Parent::onWake())
|
||||
return(false);
|
||||
|
||||
if(!mProfile->mTextureHandle.getBitmap())
|
||||
return(false);
|
||||
|
||||
if(!createBitmapArray(mProfile->mTextureHandle.getBitmap(), mBitmapBounds, 1, BmpCount))
|
||||
return(false);
|
||||
|
||||
mTabSize = mBitmapBounds[BmpParentContinue].extent.x;
|
||||
|
||||
//
|
||||
build();
|
||||
mCellSize.set(mMaxWidth + 1, mBitmapBounds[BmpParentContinue].extent.y);
|
||||
setSize(Point2I(1, mNodeList.size()));
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CreatorTree::onMouseDown(const GuiEvent & event)
|
||||
{
|
||||
if(!mActive)
|
||||
{
|
||||
Parent::onMouseDown(event);
|
||||
return;
|
||||
}
|
||||
|
||||
Point2I pos = globalToLocalCoord(event.mousePoint);
|
||||
|
||||
bool dblClick = event.mouseClickCount > 1;
|
||||
|
||||
// determine cell
|
||||
Point2I cell(pos.x < 0 ? -1 : pos.x / mCellSize.x, pos.y < 0 ? -1 : pos.y / mCellSize.y);
|
||||
if(cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
|
||||
{
|
||||
Node * node = mNodeList[cell.y];
|
||||
S32 offset = mTabSize * node->mTab;
|
||||
if(node->isGroup() && node->mChildren.size() && pos.x >= offset && pos.x <= (offset + mTabSize))
|
||||
{
|
||||
node->expand(!node->isExpanded());
|
||||
build();
|
||||
dblClick = false;
|
||||
}
|
||||
|
||||
if(pos.x >= offset)
|
||||
{
|
||||
if(dblClick)
|
||||
node->expand(!node->isExpanded());
|
||||
build();
|
||||
node->select(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CreatorTree::onMouseDragged(const GuiEvent & event)
|
||||
{
|
||||
event;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CreatorTree::onRenderCell(Point2I offset, Point2I cell, bool, bool)
|
||||
{
|
||||
Node * node = mNodeList[cell.y];
|
||||
|
||||
// get the bitmap index...
|
||||
S32 bmpIndex = BmpNone;
|
||||
if(node->isGroup())
|
||||
{
|
||||
if(node->isExpanded() || !node->mChildren.size())
|
||||
bmpIndex = BmpParentOpen;
|
||||
else bmpIndex = BmpParentClosed;
|
||||
}
|
||||
|
||||
//
|
||||
if(!node->isFirst())
|
||||
bmpIndex += 2;
|
||||
if(!node->isLast())
|
||||
bmpIndex += 1;
|
||||
|
||||
//
|
||||
if(bmpIndex != BmpNone)
|
||||
{
|
||||
Point2I pos(offset.x + mTabSize * (mNodeList[cell.y]->mTab), offset.y);
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mProfile->mTextureHandle, pos, mBitmapBounds[bmpIndex]);
|
||||
}
|
||||
|
||||
// draw the vertical line thingies
|
||||
Node * parent = node->mParent;
|
||||
while(!parent->isRoot())
|
||||
{
|
||||
if(!parent->isLast())
|
||||
{
|
||||
Point2I pos(offset.x + mTabSize * parent->mTab, offset.y);
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mProfile->mTextureHandle, pos, mBitmapBounds[BmpParentContinue]);
|
||||
}
|
||||
parent = parent->mParent;
|
||||
}
|
||||
|
||||
// set the color
|
||||
ColorI fontColor = mProfile->mFontColor;
|
||||
if(node->isSelected())
|
||||
fontColor = mProfile->mFontColorHL;
|
||||
else if(node->isGroup() && node->hasChildItem())
|
||||
fontColor.set(128, 0, 0);
|
||||
else if(!node->isGroup())
|
||||
fontColor.set(0, 0, 128);
|
||||
|
||||
dglSetBitmapModulation(fontColor); //node->isSelected() ? mProfile->mFontColorHL : mProfile->mFontColor);
|
||||
dglDrawText(mProfile->mFont, Point2I(offset.x + mTxtOffset + mTabSize * (mNodeList[cell.y]->mTab + 1), offset.y), mNodeList[cell.y]->mName);
|
||||
}
|
||||
131
editor/creator.h
Normal file
131
editor/creator.h
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _CREATOR_H_
|
||||
#define _CREATOR_H_
|
||||
|
||||
#ifndef _SIMBASE_H_
|
||||
#include "console/simBase.h"
|
||||
#endif
|
||||
#ifndef _GUIARRAYCTRL_H_
|
||||
#include "GUI/guiArrayCtrl.h"
|
||||
#endif
|
||||
|
||||
class CreatorTree : public GuiArrayCtrl
|
||||
{
|
||||
typedef GuiArrayCtrl Parent;
|
||||
public:
|
||||
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
Node();
|
||||
~Node();
|
||||
|
||||
enum {
|
||||
Group = BIT(0),
|
||||
Expanded = BIT(1),
|
||||
Selected = BIT(2),
|
||||
Root = BIT(3)
|
||||
};
|
||||
|
||||
BitSet32 mFlags;
|
||||
S32 mId;
|
||||
U32 mTab;
|
||||
Node * mParent;
|
||||
Vector<Node*> mChildren;
|
||||
StringTableEntry mName;
|
||||
StringTableEntry mValue;
|
||||
|
||||
void expand(bool exp);
|
||||
void select(bool sel){mFlags.set(Selected, sel);}
|
||||
|
||||
Node * find(S32 id);
|
||||
|
||||
//
|
||||
bool isGroup(){return(mFlags.test(Group));}
|
||||
bool isExpanded(){return(mFlags.test(Expanded));}
|
||||
bool isSelected(){return(mFlags.test(Selected));}
|
||||
bool isRoot(){return(mFlags.test(Root));}
|
||||
S32 getId(){return(mId);}
|
||||
bool hasChildItem();
|
||||
S32 getSelected();
|
||||
|
||||
//
|
||||
bool isFirst();
|
||||
bool isLast();
|
||||
};
|
||||
|
||||
CreatorTree();
|
||||
~CreatorTree();
|
||||
|
||||
//
|
||||
S32 mCurId;
|
||||
Node * mRoot;
|
||||
Vector<Node*> mNodeList;
|
||||
|
||||
//
|
||||
void buildNode(Node * node, U32 tab);
|
||||
void build();
|
||||
|
||||
//
|
||||
bool addNode(Node * parent, Node * node);
|
||||
Node * createNode(const char * name, const char * value, bool group = false, Node * parent = 0);
|
||||
Node * findNode(S32 id);
|
||||
S32 getSelected(){return(mRoot->getSelected());}
|
||||
|
||||
//
|
||||
void expandNode(Node * node, bool expand);
|
||||
void selectNode(Node * node, bool select);
|
||||
|
||||
//
|
||||
void sort();
|
||||
void clear();
|
||||
|
||||
// bitmap stuff taken from guiinspector..
|
||||
enum BitmapIndices
|
||||
{
|
||||
BmpNone = -1,
|
||||
BmpChildAbove,
|
||||
BmpChildBelow,
|
||||
BmpChildBetween,
|
||||
|
||||
BmpParentOpen,
|
||||
BmpParentOpenAbove,
|
||||
BmpParentOpenBelow,
|
||||
BmpParentOpenBetween,
|
||||
|
||||
BmpParentClosed,
|
||||
BmpParentClosedAbove,
|
||||
BmpParentClosedBelow,
|
||||
BmpParentClosedBetween,
|
||||
|
||||
BmpParentContinue,
|
||||
|
||||
BmpCount
|
||||
};
|
||||
|
||||
RectI mBitmapBounds[BmpCount];
|
||||
S32 mTabSize;
|
||||
S32 mMaxWidth;
|
||||
S32 mTxtOffset;
|
||||
|
||||
// SimObject
|
||||
static void consoleInit();
|
||||
|
||||
// GuiControl
|
||||
void onMouseDown(const GuiEvent & event);
|
||||
void onMouseDragged(const GuiEvent & event);
|
||||
bool onWake();
|
||||
|
||||
// GuiArrayCtrl
|
||||
void onRenderCell(Point2I offset, Point2I cell, bool, bool);
|
||||
|
||||
DECLARE_CONOBJECT(CreatorTree);
|
||||
};
|
||||
|
||||
#endif
|
||||
583
editor/editTSCtrl.cc
Normal file
583
editor/editTSCtrl.cc
Normal file
|
|
@ -0,0 +1,583 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "core/dnet.h"
|
||||
#include "editor/editTSCtrl.h"
|
||||
#include "sceneGraph/sceneGraph.h"
|
||||
#include "editor/editor.h"
|
||||
#include "game/gameConnection.h"
|
||||
#include "game/gameBase.h"
|
||||
#include "game/missionArea.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "terrain/terrData.h"
|
||||
#include "game/game.h"
|
||||
#include "game/sphere.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(EditTSCtrl);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Point3F EditTSCtrl::smCamPos;
|
||||
EulerF EditTSCtrl::smCamRot;
|
||||
MatrixF EditTSCtrl::smCamMatrix;
|
||||
F32 EditTSCtrl::smVisibleDistance = 2100.f;
|
||||
|
||||
EditTSCtrl::EditTSCtrl() :
|
||||
mEditManager(0)
|
||||
{
|
||||
mRenderMissionArea = true;
|
||||
mMissionAreaFillColor.set(255,0,0,20);
|
||||
mMissionAreaFrameColor.set(255,0,0,128);
|
||||
|
||||
mConsoleFrameColor.set(255,0,0,255);
|
||||
mConsoleFillColor.set(255,0,0,120);
|
||||
mConsoleSphereLevel = 1;
|
||||
mConsoleCircleSegments = 32;
|
||||
mConsoleLineWidth = 1;
|
||||
|
||||
mConsoleRendering = false;
|
||||
}
|
||||
|
||||
EditTSCtrl::~EditTSCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool EditTSCtrl::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return(false);
|
||||
|
||||
// give all derived access to the fields
|
||||
setModStaticFields(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditTSCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
updateGuiInfo();
|
||||
Parent::onRender(offset, updateRect, firstResponder);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void EditTSCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("renderMissionArea", TypeBool, Offset(mRenderMissionArea, EditTSCtrl));
|
||||
addField("missionAreaFillColor", TypeColorI, Offset(mMissionAreaFillColor, EditTSCtrl));
|
||||
addField("missionAreaFrameColor", TypeColorI, Offset(mMissionAreaFrameColor, EditTSCtrl));
|
||||
|
||||
addField("consoleFrameColor", TypeColorI, Offset(mConsoleFrameColor, EditTSCtrl));
|
||||
addField("consoleFillColor", TypeColorI, Offset(mConsoleFillColor, EditTSCtrl));
|
||||
addField("consoleSphereLevel", TypeS32, Offset(mConsoleSphereLevel, EditTSCtrl));
|
||||
addField("consoleCircleSegments", TypeS32, Offset(mConsoleCircleSegments, EditTSCtrl));
|
||||
addField("consoleLineWidth", TypeS32, Offset(mConsoleLineWidth, EditTSCtrl));
|
||||
|
||||
Con::addVariable("pref::Editor::visibleDistance", TypeF32, &EditTSCtrl::smVisibleDistance);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void EditTSCtrl::make3DMouseEvent(Gui3DMouseEvent & gui3DMouseEvent, const GuiEvent & event)
|
||||
{
|
||||
(GuiEvent&)(gui3DMouseEvent) = event;
|
||||
|
||||
// get the eye pos and the mouse vec from that...
|
||||
Point3F sp(event.mousePoint.x, event.mousePoint.y, 1);
|
||||
|
||||
Point3F wp;
|
||||
unproject(sp, &wp);
|
||||
|
||||
gui3DMouseEvent.pos = smCamPos;
|
||||
gui3DMouseEvent.vec = wp - smCamPos;
|
||||
gui3DMouseEvent.vec.normalize();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void EditTSCtrl::onMouseUp(const GuiEvent & event)
|
||||
{
|
||||
Gui3DMouseEvent gui3DMouseEvent;
|
||||
make3DMouseEvent(gui3DMouseEvent, event);
|
||||
on3DMouseUp(gui3DMouseEvent);
|
||||
}
|
||||
|
||||
void EditTSCtrl::onMouseDown(const GuiEvent & event)
|
||||
{
|
||||
Gui3DMouseEvent gui3DMouseEvent;
|
||||
make3DMouseEvent(gui3DMouseEvent, event);
|
||||
on3DMouseDown(gui3DMouseEvent);
|
||||
}
|
||||
|
||||
void EditTSCtrl::onMouseMove(const GuiEvent & event)
|
||||
{
|
||||
Gui3DMouseEvent gui3DMouseEvent;
|
||||
make3DMouseEvent(gui3DMouseEvent, event);
|
||||
on3DMouseMove(gui3DMouseEvent);
|
||||
}
|
||||
|
||||
void EditTSCtrl::onMouseDragged(const GuiEvent & event)
|
||||
{
|
||||
Gui3DMouseEvent gui3DMouseEvent;
|
||||
make3DMouseEvent(gui3DMouseEvent, event);
|
||||
on3DMouseDragged(gui3DMouseEvent);
|
||||
|
||||
}
|
||||
|
||||
void EditTSCtrl::onMouseEnter(const GuiEvent & event)
|
||||
{
|
||||
Gui3DMouseEvent gui3DMouseEvent;
|
||||
make3DMouseEvent(gui3DMouseEvent, event);
|
||||
on3DMouseEnter(gui3DMouseEvent);
|
||||
}
|
||||
|
||||
void EditTSCtrl::onMouseLeave(const GuiEvent & event)
|
||||
{
|
||||
Gui3DMouseEvent gui3DMouseEvent;
|
||||
make3DMouseEvent(gui3DMouseEvent, event);
|
||||
on3DMouseLeave(gui3DMouseEvent);
|
||||
}
|
||||
|
||||
void EditTSCtrl::onRightMouseDown(const GuiEvent & event)
|
||||
{
|
||||
Gui3DMouseEvent gui3DMouseEvent;
|
||||
make3DMouseEvent(gui3DMouseEvent, event);
|
||||
on3DRightMouseDown(gui3DMouseEvent);
|
||||
}
|
||||
|
||||
void EditTSCtrl::onRightMouseUp(const GuiEvent & event)
|
||||
{
|
||||
Gui3DMouseEvent gui3DMouseEvent;
|
||||
make3DMouseEvent(gui3DMouseEvent, event);
|
||||
on3DRightMouseUp(gui3DMouseEvent);
|
||||
}
|
||||
|
||||
void EditTSCtrl::onRightMouseDragged(const GuiEvent & event)
|
||||
{
|
||||
Gui3DMouseEvent gui3DMouseEvent;
|
||||
make3DMouseEvent(gui3DMouseEvent, event);
|
||||
on3DRightMouseDragged(gui3DMouseEvent);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void EditTSCtrl::renderWorld(const RectI & updateRect)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
dglSetCanonicalState();
|
||||
gClientSceneGraph->renderScene();
|
||||
|
||||
// render the mission area...
|
||||
if(mRenderMissionArea)
|
||||
renderMissionArea();
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
// render through console callbacks
|
||||
SimSet * missionGroup = static_cast<SimSet*>(Sim::findObject("MissionGroup"));
|
||||
if(missionGroup)
|
||||
{
|
||||
mConsoleRendering = true;
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
for(SimSetIterator itr(missionGroup); *itr; ++itr)
|
||||
{
|
||||
char buf[2][16];
|
||||
dSprintf(buf[0], 16, (*itr)->isSelected() ? "true" : "false");
|
||||
dSprintf(buf[1], 16, (*itr)->isExpanded() ? "true" : "false");
|
||||
Con::executef(*itr, 4, "onEditorRender", getIdString(), buf[0], buf[1]);
|
||||
}
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
mConsoleRendering = false;
|
||||
}
|
||||
|
||||
// render the editor stuff
|
||||
renderScene(updateRect);
|
||||
|
||||
dglSetClipRect(updateRect);
|
||||
}
|
||||
|
||||
void EditTSCtrl::renderMissionArea()
|
||||
{
|
||||
MissionArea * obj = dynamic_cast<MissionArea*>(Sim::findObject("MissionArea"));
|
||||
TerrainBlock * terrain = dynamic_cast<TerrainBlock*>(Sim::findObject("Terrain"));
|
||||
if(!terrain)
|
||||
return;
|
||||
|
||||
GridSquare * gs = terrain->findSquare(TerrainBlock::BlockShift, Point2I(0,0));
|
||||
F32 height = F32(gs->maxHeight) * 0.03125f + 10.f;
|
||||
|
||||
//
|
||||
const RectI &area = obj->getArea();
|
||||
Point2F min(area.point.x, area.point.y);
|
||||
Point2F max(area.point.x + area.extent.x, area.point.y + area.extent.y);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
ColorI & a = mMissionAreaFillColor;
|
||||
ColorI & b = mMissionAreaFrameColor;
|
||||
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_BLEND);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool EditTSCtrl::processCameraQuery(CameraQuery * query)
|
||||
{
|
||||
GameConnection* connection = dynamic_cast<GameConnection *>(NetConnection::getServerConnection());
|
||||
if (connection)
|
||||
{
|
||||
if (connection->getControlCameraTransform(0.032,&query->cameraMatrix)) {
|
||||
query->nearPlane = 0.1;
|
||||
query->farPlane = getMax(smVisibleDistance, 50.f);
|
||||
query->fov = 3.1415 / 2;
|
||||
|
||||
smCamMatrix = query->cameraMatrix;
|
||||
smCamMatrix.getColumn(3,&smCamPos);
|
||||
smCamRot.set(0,0,0);
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// sort the surfaces: not correct when camera is inside sphere but not
|
||||
// inside tesselated representation of sphere....
|
||||
struct SortInfo {
|
||||
U32 idx;
|
||||
F32 dot;
|
||||
};
|
||||
|
||||
static int QSORT_CALLBACK alphaSort(const void* p1, const void* p2)
|
||||
{
|
||||
const SortInfo* ip1 = (const SortInfo*)p1;
|
||||
const SortInfo* ip2 = (const SortInfo*)p2;
|
||||
|
||||
if(ip1->dot > ip2->dot)
|
||||
return(1);
|
||||
if(ip1->dot == ip2->dot)
|
||||
return(0);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void cRenderSphere(SimObject * obj, S32 argc, const char ** argv)
|
||||
{
|
||||
EditTSCtrl * ctrl = static_cast<EditTSCtrl*>(obj);
|
||||
if(!ctrl->mConsoleRendering)
|
||||
return;
|
||||
|
||||
static Sphere sphere(Sphere::Icosahedron);
|
||||
|
||||
if(!ctrl->mConsoleFrameColor.alpha && !ctrl->mConsoleFillColor.alpha)
|
||||
return;
|
||||
|
||||
S32 sphereLevel = ctrl->mConsoleSphereLevel;
|
||||
if(argc == 5)
|
||||
sphereLevel = dAtoi(argv[4]);
|
||||
|
||||
const Sphere::TriangleMesh * mesh = sphere.getMesh(sphereLevel);
|
||||
|
||||
Point3F pos;
|
||||
dSscanf(argv[2], "%f %f %f", &pos.x, &pos.y, &pos.z);
|
||||
|
||||
F32 radius = dAtoi(argv[3]);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// sort the surfaces back->front
|
||||
Vector<SortInfo> sortInfos;
|
||||
|
||||
Point3F camNormal = ctrl->smCamPos - pos;
|
||||
camNormal.normalize();
|
||||
|
||||
sortInfos.setSize(mesh->numPoly);
|
||||
for(U32 i = 0; i < mesh->numPoly; i++)
|
||||
{
|
||||
sortInfos[i].idx = i;
|
||||
sortInfos[i].dot = mDot(camNormal, mesh->poly[i].normal);
|
||||
}
|
||||
dQsort(sortInfos.address(), sortInfos.size(), sizeof(SortInfo), alphaSort);
|
||||
|
||||
// frame
|
||||
if(ctrl->mConsoleFrameColor.alpha)
|
||||
{
|
||||
glColor4ub(ctrl->mConsoleFrameColor.red,
|
||||
ctrl->mConsoleFrameColor.green,
|
||||
ctrl->mConsoleFrameColor.blue,
|
||||
ctrl->mConsoleFrameColor.alpha);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
glLineWidth(ctrl->mConsoleLineWidth);
|
||||
glBegin(GL_TRIANGLES);
|
||||
for(U32 i = 0; i < mesh->numPoly; i++)
|
||||
{
|
||||
Sphere::Triangle & tri = mesh->poly[sortInfos[i].idx];
|
||||
for(S32 j = 2; j >= 0; j--)
|
||||
glVertex3f(tri.pnt[j].x * radius + pos.x,
|
||||
tri.pnt[j].y * radius + pos.y,
|
||||
tri.pnt[j].z * radius + pos.z);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glLineWidth(1);
|
||||
}
|
||||
|
||||
// fill
|
||||
if(ctrl->mConsoleFillColor.alpha)
|
||||
{
|
||||
glColor4ub(ctrl->mConsoleFillColor.red,
|
||||
ctrl->mConsoleFillColor.green,
|
||||
ctrl->mConsoleFillColor.blue,
|
||||
ctrl->mConsoleFillColor.alpha);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for(U32 i = 0; i < mesh->numPoly; i++)
|
||||
{
|
||||
Sphere::Triangle & tri = mesh->poly[sortInfos[i].idx];
|
||||
for(S32 j = 2; j >= 0; j--)
|
||||
glVertex3f(tri.pnt[j].x * radius + pos.x,
|
||||
tri.pnt[j].y * radius + pos.y,
|
||||
tri.pnt[j].z * radius + pos.z);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
static void cRenderCircle(SimObject * obj, S32 argc, const char ** argv)
|
||||
{
|
||||
EditTSCtrl * ctrl = static_cast<EditTSCtrl*>(obj);
|
||||
if(!ctrl->mConsoleRendering)
|
||||
return;
|
||||
|
||||
if(!ctrl->mConsoleFrameColor.alpha && !ctrl->mConsoleFillColor.alpha)
|
||||
return;
|
||||
|
||||
Point3F pos, normal;
|
||||
dSscanf(argv[2], "%f %f %f", &pos.x, &pos.y, &pos.z);
|
||||
dSscanf(argv[3], "%f %f %f", &normal.x, &normal.y, &normal.z);
|
||||
|
||||
F32 radius = dAtoi(argv[4]);
|
||||
|
||||
S32 segments = ctrl->mConsoleCircleSegments;
|
||||
if(argc == 6)
|
||||
segments = dAtoi(argv[5]);
|
||||
|
||||
normal.normalize();
|
||||
|
||||
AngAxisF aa;
|
||||
mCross(normal, Point3F(0,0,1), &aa.axis);
|
||||
aa.angle = mAcos(mClampF(mDot(normal, Point3F(0,0,1)), -1.f, 1.f));
|
||||
|
||||
if(aa.angle == 0.f)
|
||||
aa.axis.set(0,0,1);
|
||||
|
||||
MatrixF mat;
|
||||
aa.setMatrix(&mat);
|
||||
|
||||
F32 step = M_2PI / segments;
|
||||
F32 angle = 0.f;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
Vector<Point3F> points;
|
||||
segments--;
|
||||
for(U32 i = 0; i < segments; i++)
|
||||
{
|
||||
Point3F pnt(mCos(angle), mSin(angle), 0.f);
|
||||
|
||||
mat.mulP(pnt);
|
||||
pnt *= radius;
|
||||
pnt += pos;
|
||||
|
||||
points.push_back(pnt);
|
||||
angle += step;
|
||||
}
|
||||
|
||||
// framed
|
||||
if(ctrl->mConsoleFrameColor.alpha)
|
||||
{
|
||||
glColor4ub(ctrl->mConsoleFrameColor.red,
|
||||
ctrl->mConsoleFrameColor.green,
|
||||
ctrl->mConsoleFrameColor.blue,
|
||||
ctrl->mConsoleFrameColor.alpha);
|
||||
glLineWidth(ctrl->mConsoleLineWidth);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
for(U32 i = 0; i < points.size(); i++)
|
||||
glVertex3f(points[i].x, points[i].y, points[i].z);
|
||||
glEnd();
|
||||
glLineWidth(1);
|
||||
}
|
||||
|
||||
// filled
|
||||
if(ctrl->mConsoleFillColor.alpha)
|
||||
{
|
||||
glColor4ub(ctrl->mConsoleFillColor.red,
|
||||
ctrl->mConsoleFillColor.green,
|
||||
ctrl->mConsoleFillColor.blue,
|
||||
ctrl->mConsoleFillColor.alpha);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
|
||||
for(S32 i = 0; i < points.size(); i++)
|
||||
{
|
||||
S32 j = (i + 1) % points.size();
|
||||
glVertex3f(points[i].x, points[i].y, points[i].z);
|
||||
glVertex3f(points[j].x, points[j].y, points[j].z);
|
||||
glVertex3f(pos.x, pos.y, pos.z);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
static void cRenderTriangle(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
EditTSCtrl * ctrl = static_cast<EditTSCtrl*>(obj);
|
||||
if(!ctrl->mConsoleRendering)
|
||||
return;
|
||||
|
||||
if(!ctrl->mConsoleFrameColor.alpha && !ctrl->mConsoleFillColor.alpha)
|
||||
return;
|
||||
|
||||
Point3F pnts[3];
|
||||
for(U32 i = 0; i < 3; i++)
|
||||
dSscanf(argv[i+2], "%f %f %f", &pnts[i].x, &pnts[i].y, &pnts[i].z);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// frame
|
||||
if(ctrl->mConsoleFrameColor.alpha)
|
||||
{
|
||||
glColor4ub(ctrl->mConsoleFrameColor.red,
|
||||
ctrl->mConsoleFrameColor.green,
|
||||
ctrl->mConsoleFrameColor.blue,
|
||||
ctrl->mConsoleFrameColor.alpha);
|
||||
glLineWidth(ctrl->mConsoleLineWidth);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
for(U32 i = 0; i < 3; i++)
|
||||
glVertex3f(pnts[i].x, pnts[i].y, pnts[i].z);
|
||||
glEnd();
|
||||
glLineWidth(1);
|
||||
}
|
||||
|
||||
// fill
|
||||
if(ctrl->mConsoleFillColor.alpha)
|
||||
{
|
||||
glColor4ub(ctrl->mConsoleFillColor.red,
|
||||
ctrl->mConsoleFillColor.green,
|
||||
ctrl->mConsoleFillColor.blue,
|
||||
ctrl->mConsoleFillColor.alpha);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for(U32 i = 0; i < 3; i++)
|
||||
glVertex3f(pnts[i].x, pnts[i].y, pnts[i].z);
|
||||
glEnd();
|
||||
}
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
static void cRenderLine(SimObject * obj, S32 argc, const char ** argv)
|
||||
{
|
||||
EditTSCtrl * ctrl = static_cast<EditTSCtrl*>(obj);
|
||||
if(!ctrl->mConsoleRendering)
|
||||
return;
|
||||
|
||||
if(!ctrl->mConsoleFrameColor.alpha)
|
||||
return;
|
||||
|
||||
Point3F start, end;
|
||||
dSscanf(argv[2], "%f %f %f", &start.x, &start.y, &start.z);
|
||||
dSscanf(argv[3], "%f %f %f", &end.x, &end.y, &end.z);
|
||||
|
||||
S32 width = ctrl->mConsoleLineWidth;
|
||||
if(argc == 5)
|
||||
width = dAtoi(argv[4]);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glColor4ub(ctrl->mConsoleFrameColor.red,
|
||||
ctrl->mConsoleFrameColor.green,
|
||||
ctrl->mConsoleFrameColor.blue,
|
||||
ctrl->mConsoleFrameColor.alpha);
|
||||
|
||||
glLineWidth(width);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(start.x, start.y, start.z);
|
||||
glVertex3f(end.x, end.y, end.z);
|
||||
glEnd();
|
||||
|
||||
glLineWidth(1);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void EditTSCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand("EditTSCtrl", "renderSphere", cRenderSphere, "EditTSCtrl.renderSphere(pos, radius, <subdivisions>", 4, 5);
|
||||
Con::addCommand("EditTSCtrl", "renderCircle", cRenderCircle, "EditTSCtrl.renderCircle(pos, normal, radius, <segments>", 5, 6);
|
||||
Con::addCommand("EditTSCtrl", "renderTriangle", cRenderTriangle, "EditTSCtrl.renderTriangle(pnt, pnt, pnt)", 5, 5);
|
||||
Con::addCommand("EditTSCtrl", "renderLine", cRenderLine, "EditTSCtrl.renderLine(start, end, <width>", 4, 5);
|
||||
}
|
||||
|
||||
100
editor/editTSCtrl.h
Normal file
100
editor/editTSCtrl.h
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _EDITTSCTRL_H_
|
||||
#define _EDITTSCTRL_H_
|
||||
|
||||
#ifndef _GUITSCONTROL_H_
|
||||
#include "GUI/guiTSControl.h"
|
||||
#endif
|
||||
|
||||
struct Gui3DMouseEvent : public GuiEvent
|
||||
{
|
||||
Point3F vec;
|
||||
Point3F pos;
|
||||
};
|
||||
|
||||
class EditManager;
|
||||
|
||||
class EditTSCtrl : public GuiTSCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTSCtrl Parent;
|
||||
|
||||
// EditTSCtrl
|
||||
void make3DMouseEvent(Gui3DMouseEvent & gui3Devent, const GuiEvent & event);
|
||||
void onMouseUp(const GuiEvent & event);
|
||||
void onMouseDown(const GuiEvent & event);
|
||||
void onMouseMove(const GuiEvent & event);
|
||||
void onMouseDragged(const GuiEvent & event);
|
||||
void onMouseEnter(const GuiEvent & event);
|
||||
void onMouseLeave(const GuiEvent & event);
|
||||
void onRightMouseDown(const GuiEvent & event);
|
||||
void onRightMouseUp(const GuiEvent & event);
|
||||
void onRightMouseDragged(const GuiEvent & event);
|
||||
|
||||
virtual void updateGuiInfo() {};
|
||||
virtual void renderScene(const RectI &){};
|
||||
void renderMissionArea();
|
||||
|
||||
// GuiTSCtrl
|
||||
void renderWorld(const RectI & updateRect);
|
||||
|
||||
protected:
|
||||
EditManager * mEditManager;
|
||||
|
||||
public:
|
||||
|
||||
EditTSCtrl();
|
||||
~EditTSCtrl();
|
||||
|
||||
// SimObject
|
||||
bool onAdd();
|
||||
|
||||
//
|
||||
bool mRenderMissionArea;
|
||||
ColorI mMissionAreaFillColor;
|
||||
ColorI mMissionAreaFrameColor;
|
||||
|
||||
//
|
||||
ColorI mConsoleFrameColor;
|
||||
ColorI mConsoleFillColor;
|
||||
S32 mConsoleSphereLevel;
|
||||
S32 mConsoleCircleSegments;
|
||||
S32 mConsoleLineWidth;
|
||||
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
//
|
||||
bool mConsoleRendering;
|
||||
|
||||
// all editors will share a camera
|
||||
static Point3F smCamPos;
|
||||
static EulerF smCamRot;
|
||||
static MatrixF smCamMatrix;
|
||||
static F32 smVisibleDistance;
|
||||
|
||||
// GuiTSCtrl
|
||||
bool processCameraQuery(CameraQuery * query);
|
||||
|
||||
// guiControl
|
||||
virtual void onRender(Point2I, const RectI &, GuiControl *);
|
||||
virtual void on3DMouseUp(const Gui3DMouseEvent &){};
|
||||
virtual void on3DMouseDown(const Gui3DMouseEvent &){};
|
||||
virtual void on3DMouseMove(const Gui3DMouseEvent &){};
|
||||
virtual void on3DMouseDragged(const Gui3DMouseEvent &){};
|
||||
virtual void on3DMouseEnter(const Gui3DMouseEvent &){};
|
||||
virtual void on3DMouseLeave(const Gui3DMouseEvent &){};
|
||||
virtual void on3DRightMouseDown(const Gui3DMouseEvent &){};
|
||||
virtual void on3DRightMouseUp(const Gui3DMouseEvent &){};
|
||||
virtual void on3DRightMouseDragged(const Gui3DMouseEvent &){};
|
||||
|
||||
DECLARE_CONOBJECT(EditTSCtrl);
|
||||
};
|
||||
|
||||
#endif
|
||||
116
editor/editor.cc
Normal file
116
editor/editor.cc
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "editor/editor.h"
|
||||
#include "console/console.h"
|
||||
#include "console/consoleInternal.h"
|
||||
#include "gui/guiTextListCtrl.h"
|
||||
#include "platform/event.h"
|
||||
#include "game/shapeBase.h"
|
||||
#include "game/gameConnection.h"
|
||||
|
||||
bool gEditingMission = false;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Class EditManager
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(EditManager);
|
||||
|
||||
EditManager::EditManager()
|
||||
{
|
||||
for(U32 i = 0; i < 10; i++)
|
||||
mBookmarks[i] = MatrixF(true);
|
||||
}
|
||||
|
||||
EditManager::~EditManager()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool EditManager::onWake()
|
||||
{
|
||||
if(!Parent::onWake())
|
||||
return(false);
|
||||
|
||||
for(SimSetIterator itr(Sim::getRootGroup()); *itr; ++itr)
|
||||
(*itr)->onEditorEnable();
|
||||
|
||||
gEditingMission = true;
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
void EditManager::onSleep()
|
||||
{
|
||||
for(SimSetIterator itr(Sim::getRootGroup()); *itr; ++itr)
|
||||
(*itr)->onEditorDisable();
|
||||
|
||||
gEditingMission = false;
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool EditManager::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return(false);
|
||||
|
||||
// hook the namespace
|
||||
const char * name = getName();
|
||||
if(name && name[0] && getClassRep())
|
||||
{
|
||||
Namespace * parent = getClassRep()->getNameSpace();
|
||||
Con::linkNamespaces(parent->mName, name);
|
||||
mNameSpace = Con::lookupNamespace(name);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static GameBase * getControlObj()
|
||||
{
|
||||
GameConnection * connection = GameConnection::getLocalClientConnection();
|
||||
ShapeBase* control = 0;
|
||||
if(connection)
|
||||
control = connection->getControlObject();
|
||||
return(control);
|
||||
}
|
||||
|
||||
static void cSetBookmark(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
S32 val = dAtoi(argv[2]);
|
||||
if(val < 0 || val > 9)
|
||||
return;
|
||||
|
||||
EditManager * editor = static_cast<EditManager*>(obj);
|
||||
GameBase * control = getControlObj();
|
||||
if(control)
|
||||
editor->mBookmarks[val] = control->getTransform();
|
||||
}
|
||||
|
||||
static void cGotoBookmark(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
S32 val = dAtoi(argv[2]);
|
||||
if(val < 0 || val > 9)
|
||||
return;
|
||||
|
||||
EditManager * editor = static_cast<EditManager*>(obj);
|
||||
GameBase * control = getControlObj();
|
||||
if(control)
|
||||
control->setTransform(editor->mBookmarks[val]);
|
||||
}
|
||||
|
||||
void EditManager::consoleInit()
|
||||
{
|
||||
Con::addCommand("EditManager", "setBookmark", cSetBookmark, "editor.setBookmark(<1-0>);", 3, 3);
|
||||
Con::addCommand("EditManager", "gotoBookmark", cGotoBookmark, "editor.gotoBookmark(<1-0>);", 3, 3);
|
||||
}
|
||||
46
editor/editor.h
Normal file
46
editor/editor.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _EDITOR_H_
|
||||
#define _EDITOR_H_
|
||||
|
||||
#ifndef _MMATRIX_H_
|
||||
#include "Math/mMatrix.h"
|
||||
#endif
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
|
||||
class GameBase;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class EditManager : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
public:
|
||||
EditManager();
|
||||
~EditManager();
|
||||
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
// SimObject
|
||||
bool onAdd();
|
||||
static void consoleInit();
|
||||
|
||||
MatrixF mBookmarks[10];
|
||||
DECLARE_CONOBJECT(EditManager);
|
||||
};
|
||||
|
||||
extern bool gEditingMission;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
119
editor/editorButtonCtrl.cc
Normal file
119
editor/editorButtonCtrl.cc
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Editor/editorButtonCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(EditorButtonCtrl);
|
||||
|
||||
EditorButtonCtrl::EditorButtonCtrl()
|
||||
{
|
||||
mBitmapName = StringTable->insert("");
|
||||
mTextureHandle = 0;
|
||||
mMouseOverColor.set(200,0,0);
|
||||
mDepressedAlpha = 0.2;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void EditorButtonCtrl::onRender(Point2I offset, const RectI & updateRect,
|
||||
GuiControl * firstResponder)
|
||||
{
|
||||
GuiCanvas * root = getRoot();
|
||||
bool stateOver = cursorInControl();
|
||||
bool stateDepressed = (stateOver && root && root->mouseButtonDown());
|
||||
|
||||
if(mTextureHandle)
|
||||
{
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapStretch(mTextureHandle, updateRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
glColor4f(0, 0, 0, 1);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2i(updateRect.point.x, updateRect.point.y);
|
||||
glVertex2i(updateRect.point.x+updateRect.extent.x-1, updateRect.point.y);
|
||||
glVertex2i(updateRect.point.x+updateRect.extent.x-1, updateRect.point.y+updateRect.extent.y-1);
|
||||
glVertex2i(updateRect.point.x, updateRect.point.y+updateRect.extent.y-1);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
//
|
||||
if(stateOver)
|
||||
dglDrawRect(updateRect, mMouseOverColor);
|
||||
|
||||
//
|
||||
if(stateDepressed)
|
||||
{
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
|
||||
glBegin(GL_QUADS);
|
||||
glColor4f(1,1,1,mDepressedAlpha);
|
||||
glVertex2i(updateRect.point.x, updateRect.point.y);
|
||||
glVertex2i(updateRect.point.x+updateRect.extent.x-1, updateRect.point.y);
|
||||
glVertex2i(updateRect.point.x+updateRect.extent.x-1, updateRect.point.y+updateRect.extent.y-1);
|
||||
glVertex2i(updateRect.point.x, updateRect.point.y+updateRect.extent.y-1);
|
||||
glEnd();
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void EditorButtonCtrl::setBitmap(const char * name)
|
||||
{
|
||||
mBitmapName = StringTable->insert(name);
|
||||
if(mBitmapName[0])
|
||||
mTextureHandle = TextureHandle(mBitmapName, BitmapTexture);
|
||||
else
|
||||
mTextureHandle = 0;
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool EditorButtonCtrl::onWake()
|
||||
{
|
||||
if(!Parent::onWake())
|
||||
return false;
|
||||
setActive(true);
|
||||
setBitmap(mBitmapName);
|
||||
return(true);
|
||||
}
|
||||
|
||||
void EditorButtonCtrl::onSleep()
|
||||
{
|
||||
mTextureHandle = 0;
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void EditorButtonCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("bitmap", TypeString, Offset(mBitmapName, EditorButtonCtrl));
|
||||
addField("mouseOverColor", TypeColorI, Offset(mMouseOverColor, EditorButtonCtrl));
|
||||
addField("depressedAlpha", TypeF32, Offset(mDepressedAlpha, EditorButtonCtrl));
|
||||
}
|
||||
|
||||
static void cSetBitmap(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
EditorButtonCtrl * ctrl = static_cast<EditorButtonCtrl*>(obj);
|
||||
ctrl->setBitmap(argv[2]);
|
||||
}
|
||||
|
||||
void EditorButtonCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand("EditorButtonCtrl", "setBitmap", cSetBitmap, "editorButtonCtrl.setBitmap(name);", 3, 3);
|
||||
}
|
||||
|
||||
45
editor/editorButtonCtrl.h
Normal file
45
editor/editorButtonCtrl.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _EDITORBUTTONCTRL_H_
|
||||
#define _EDITORBUTTONCTRL_H_
|
||||
|
||||
#ifndef _GUIBUTTONCTRL_H_
|
||||
#include "GUI/guiButtonCtrl.h"
|
||||
#endif
|
||||
|
||||
// JFF - move into gui once finished
|
||||
|
||||
class EditorButtonCtrl : public GuiButtonCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiButtonCtrl Parent;
|
||||
|
||||
protected:
|
||||
TextureHandle mTextureHandle;
|
||||
StringTableEntry mBitmapName;
|
||||
ColorI mMouseOverColor;
|
||||
F32 mDepressedAlpha;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(EditorButtonCtrl);
|
||||
|
||||
EditorButtonCtrl();
|
||||
|
||||
// SimObject
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
// GuiControl
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
void setBitmap(const char *name);
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
};
|
||||
|
||||
#endif
|
||||
118
editor/editorCheckboxCtrl.cc
Normal file
118
editor/editorCheckboxCtrl.cc
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Editor/editorCheckboxCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(EditorCheckBoxCtrl);
|
||||
|
||||
EditorCheckBoxCtrl::EditorCheckBoxCtrl()
|
||||
{
|
||||
mBitmapName = StringTable->insert("");
|
||||
mTextureHandle = 0;
|
||||
mMouseOverColor.set(200,0,0);
|
||||
mDepressedAlpha = 0.2;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void EditorCheckBoxCtrl::onRender(Point2I offset, const RectI & updateRect,
|
||||
GuiControl * firstResponder)
|
||||
{
|
||||
GuiCanvas * root = getRoot();
|
||||
bool stateOver = cursorInControl();
|
||||
bool stateDepressed = (stateOver && root && root->mouseButtonDown());
|
||||
|
||||
if(mTextureHandle)
|
||||
{
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapStretch(mTextureHandle, updateRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
glColor4f(0, 0, 0, 1);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2i(updateRect.point.x, updateRect.point.y);
|
||||
glVertex2i(updateRect.point.x+updateRect.extent.x-1, updateRect.point.y);
|
||||
glVertex2i(updateRect.point.x+updateRect.extent.x-1, updateRect.point.y+updateRect.extent.y-1);
|
||||
glVertex2i(updateRect.point.x, updateRect.point.y+updateRect.extent.y-1);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
//
|
||||
if(stateOver)
|
||||
Parent::drawBorder(updateRect, mMouseOverColor);
|
||||
|
||||
//
|
||||
if(!mStateOn)
|
||||
{
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
|
||||
glBegin(GL_QUADS);
|
||||
glColor4f(1,1,1,mDepressedAlpha);
|
||||
glVertex2i(updateRect.point.x, updateRect.point.y);
|
||||
glVertex2i(updateRect.point.x+updateRect.extent.x-1, updateRect.point.y);
|
||||
glVertex2i(updateRect.point.x+updateRect.extent.x-1, updateRect.point.y+updateRect.extent.y-1);
|
||||
glVertex2i(updateRect.point.x, updateRect.point.y+updateRect.extent.y-1);
|
||||
glEnd();
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void EditorCheckBoxCtrl::setBitmap(const char * name)
|
||||
{
|
||||
mBitmapName = StringTable->insert(name);
|
||||
if(mBitmapName[0])
|
||||
mTextureHandle = TextureHandle(mBitmapName, BitmapTexture);
|
||||
else
|
||||
mTextureHandle = 0;
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool EditorCheckBoxCtrl::onWake()
|
||||
{
|
||||
if(!Parent::onWake())
|
||||
return false;
|
||||
setActive(true);
|
||||
setBitmap(mBitmapName);
|
||||
return(true);
|
||||
}
|
||||
|
||||
void EditorCheckBoxCtrl::onSleep()
|
||||
{
|
||||
mTextureHandle = 0;
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void EditorCheckBoxCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("bitmap", TypeString, Offset(mBitmapName, EditorCheckBoxCtrl));
|
||||
addField("mouseOverColor", TypeColorI, Offset(mMouseOverColor, EditorCheckBoxCtrl));
|
||||
addField("depressedAlpha", TypeF32, Offset(mDepressedAlpha, EditorCheckBoxCtrl));
|
||||
}
|
||||
|
||||
static void cSetBitmap(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
EditorCheckBoxCtrl * ctrl = static_cast<EditorCheckBoxCtrl*>(obj);
|
||||
ctrl->setBitmap(argv[2]);
|
||||
}
|
||||
|
||||
void EditorCheckBoxCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand("EditorCheckBoxCtrl", "setBitmap", cSetBitmap, "editorButtonCtrl.setBitmap(name);", 3, 3);
|
||||
}
|
||||
44
editor/editorCheckboxCtrl.h
Normal file
44
editor/editorCheckboxCtrl.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _EDITORCHECKBOXCTRL_H_
|
||||
#define _EDITORCHECKBOXCTRL_H_
|
||||
|
||||
#ifndef _GUICHECKBOXCTRL_H_
|
||||
#include "GUI/guiCheckBoxCtrl.h"
|
||||
#endif
|
||||
|
||||
// JFF - move into gui once finished
|
||||
|
||||
class EditorCheckBoxCtrl : public GuiCheckBoxCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiCheckBoxCtrl Parent;
|
||||
|
||||
protected:
|
||||
TextureHandle mTextureHandle;
|
||||
StringTableEntry mBitmapName;
|
||||
ColorI mMouseOverColor;
|
||||
F32 mDepressedAlpha;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(EditorCheckBoxCtrl);
|
||||
|
||||
EditorCheckBoxCtrl();
|
||||
|
||||
// SimObject
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
// GuiControl
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
void setBitmap(const char *name);
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
};
|
||||
#endif
|
||||
324
editor/guiTerrPreviewCtrl.cc
Normal file
324
editor/guiTerrPreviewCtrl.cc
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "platformWin32/platformGL.h"
|
||||
#include "game/game.h"
|
||||
#include "terrain/terrData.h"
|
||||
#include "editor/guiTerrPreviewCtrl.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiTerrPreviewCtrl);
|
||||
|
||||
GuiTerrPreviewCtrl::GuiTerrPreviewCtrl(void)
|
||||
{
|
||||
mTerrainSize = 2048.0f;
|
||||
mRoot.set( 0, 0 );
|
||||
mOrigin.set( 0, 0 );
|
||||
mWorldScreenCenter.set( mTerrainSize*0.5f, mTerrainSize*0.5f );
|
||||
}
|
||||
|
||||
void GuiTerrPreviewCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
|
||||
static void cTerrPreview_Reset(SimObject *obj, S32, const char **)
|
||||
{
|
||||
static_cast<GuiTerrPreviewCtrl*>(obj)->reset();
|
||||
}
|
||||
|
||||
static void cTerrPreview_SetRoot(SimObject *obj, S32, const char **)
|
||||
{
|
||||
static_cast<GuiTerrPreviewCtrl*>(obj)->setRoot();
|
||||
}
|
||||
|
||||
static const char* cTerrPreview_GetRoot(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiTerrPreviewCtrl *ctrl = static_cast<GuiTerrPreviewCtrl*>(obj);
|
||||
Point2F p = ctrl->getRoot();
|
||||
|
||||
static char buf[32];
|
||||
dSprintf(buf,sizeof(buf),"%f %f", p.x, -p.y);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void cTerrPreview_SetOrigin(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiTerrPreviewCtrl *ctrl = static_cast<GuiTerrPreviewCtrl*>(obj);
|
||||
ctrl->setOrigin( Point2F( dAtof(argv[2]), -dAtof(argv[3]) ) );
|
||||
}
|
||||
|
||||
static const char* cTerrPreview_GetOrigin(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiTerrPreviewCtrl *ctrl = static_cast<GuiTerrPreviewCtrl*>(obj);
|
||||
Point2F p = ctrl->getOrigin();
|
||||
|
||||
static char buf[32];
|
||||
dSprintf(buf,sizeof(buf),"%f %f", p.x, -p.y);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char* cTerrPreview_GetValue(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiTerrPreviewCtrl *ctrl = static_cast<GuiTerrPreviewCtrl*>(obj);
|
||||
Point2F r = ctrl->getRoot();
|
||||
Point2F o = ctrl->getOrigin();
|
||||
|
||||
static char buf[64];
|
||||
dSprintf(buf,sizeof(buf),"%f %f %f %f", r.x, -r.y, o.x, -o.y);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void cTerrPreview_SetValue(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
Point2F r,o;
|
||||
GuiTerrPreviewCtrl *ctrl = static_cast<GuiTerrPreviewCtrl*>(obj);
|
||||
dSscanf(argv[1],"%f %f %f %f", &r.x, &r.y, &o.x, &o.y);
|
||||
r.y = -r.y;
|
||||
o.y = -o.y;
|
||||
ctrl->reset();
|
||||
ctrl->setRoot(r);
|
||||
ctrl->setOrigin(o);
|
||||
}
|
||||
|
||||
|
||||
void GuiTerrPreviewCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand("GuiTerrPreviewCtrl", "reset", cTerrPreview_Reset, "guiTerrPreviewCtrl.reset()", 2, 2);
|
||||
Con::addCommand("GuiTerrPreviewCtrl", "setRoot", cTerrPreview_SetRoot, "guiTerrPreviewCtrl.setRoot()", 2, 2);
|
||||
Con::addCommand("GuiTerrPreviewCtrl", "getRoot", cTerrPreview_GetRoot, "guiTerrPreviewCtrl.getRoot()", 2, 2);
|
||||
Con::addCommand("GuiTerrPreviewCtrl", "setOrigin", cTerrPreview_SetOrigin, "guiTerrPreviewCtrl.setOrigin(x,y)", 4, 4);
|
||||
Con::addCommand("GuiTerrPreviewCtrl", "getOrigin", cTerrPreview_GetOrigin, "guiTerrPreviewCtrl.getOrigin()", 2, 2);
|
||||
Con::addCommand("GuiTerrPreviewCtrl", "getValue", cTerrPreview_GetValue, "guiTerrPreviewCtrl.getValue()", 2, 2);
|
||||
Con::addCommand("GuiTerrPreviewCtrl", "setValue", cTerrPreview_SetValue, "guiTerrPreviewCtrl.getValue(t)", 3, 3);
|
||||
}
|
||||
|
||||
|
||||
bool GuiTerrPreviewCtrl::onWake()
|
||||
{
|
||||
if (! Parent::onWake())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiTerrPreviewCtrl::onSleep()
|
||||
{
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
|
||||
void GuiTerrPreviewCtrl::setBitmap(const TextureHandle &handle)
|
||||
{
|
||||
mTextureHandle = handle;
|
||||
}
|
||||
|
||||
void GuiTerrPreviewCtrl::reset()
|
||||
{
|
||||
mRoot.set(0,0);
|
||||
mOrigin.set(0,0);
|
||||
}
|
||||
|
||||
void GuiTerrPreviewCtrl::setRoot()
|
||||
{
|
||||
mRoot += mOrigin;
|
||||
mOrigin.set(0,0);
|
||||
}
|
||||
|
||||
void GuiTerrPreviewCtrl::setRoot(const Point2F &p)
|
||||
{
|
||||
mRoot = p;
|
||||
}
|
||||
|
||||
void GuiTerrPreviewCtrl::setOrigin(const Point2F &p)
|
||||
{
|
||||
mOrigin = p;
|
||||
}
|
||||
|
||||
|
||||
Point2F& GuiTerrPreviewCtrl::wrap(const Point2F &p)
|
||||
{
|
||||
static Point2F result;
|
||||
result = p;
|
||||
|
||||
while (result.x < 0.0f)
|
||||
result.x += mTerrainSize;
|
||||
while (result.x > mTerrainSize)
|
||||
result.x -= mTerrainSize;
|
||||
while (result.y < 0.0f)
|
||||
result.y += mTerrainSize;
|
||||
while (result.y > mTerrainSize)
|
||||
result.y -= mTerrainSize;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Point2F& GuiTerrPreviewCtrl::worldToTexture(const Point2F &p)
|
||||
{
|
||||
static Point2F result;
|
||||
result = wrap( p + mRoot ) / mTerrainSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Point2F& GuiTerrPreviewCtrl::worldToCtrl(const Point2F &p)
|
||||
{
|
||||
static Point2F result;
|
||||
result = wrap( p - mCamera + mOrigin - mWorldScreenCenter );
|
||||
result *= mBounds.extent.x / mTerrainSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void GuiTerrPreviewCtrl::onPreRender()
|
||||
{
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
void GuiTerrPreviewCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
struct CameraQuery query;
|
||||
GameProcessCameraQuery(&query);
|
||||
Point3F cameraRot;
|
||||
|
||||
MatrixF matrix = query.cameraMatrix;
|
||||
matrix.getColumn(3,&cameraRot); // get Camera translation
|
||||
mCamera.set(cameraRot.x, -cameraRot.y);
|
||||
matrix.getRow(1,&cameraRot); // get camera rotation
|
||||
|
||||
mTerrainSize = 8*256;
|
||||
TerrainBlock *terrBlock = dynamic_cast<TerrainBlock*>(Sim::findObject("Terrain"));
|
||||
if (terrBlock)
|
||||
mTerrainSize = terrBlock->getSquareSize()*TerrainBlock::BlockSize;
|
||||
|
||||
|
||||
//----------------------------------------- RENDER the Terrain Bitmap
|
||||
if (mTextureHandle)
|
||||
{
|
||||
TextureObject *texture = (TextureObject*)mTextureHandle;
|
||||
if (texture)
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture->texGLName);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
Point2F screenP1(offset.x - 0.5f, offset.y + 0.5f);
|
||||
Point2F screenP2(offset.x + mBounds.extent.x - 0.5f, offset.y + mBounds.extent.x + 0.5f);
|
||||
Point2F textureP1( worldToTexture( mCamera ) );
|
||||
Point2F textureP2(textureP1 + Point2F(1.0f, 1.0f));
|
||||
|
||||
// the texture if flipped horz to reflect how the terrain is really drawn
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glTexCoord2f(textureP1.x, textureP2.y);
|
||||
glVertex2f(screenP1.x, screenP2.y); // left bottom
|
||||
|
||||
glTexCoord2f(textureP2.x, textureP2.y);
|
||||
glVertex2f(screenP2.x, screenP2.y); // right bottom
|
||||
|
||||
glTexCoord2f(textureP2.x, textureP1.y);
|
||||
glVertex2f(screenP2.x, screenP1.y); // right top
|
||||
|
||||
glTexCoord2f(textureP1.x, textureP1.y);
|
||||
glVertex2f(screenP1.x, screenP1.y); // left top
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RectI rect(offset.x, offset.y, mBounds.extent.x, mBounds.extent.y);
|
||||
dglDrawRectFill(rect, ColorI(0,0,0));
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
//----------------------------------------- RENDER the '+' at the center of the Block
|
||||
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.7f);
|
||||
Point2F center( worldToCtrl(Point2F(0,0)) );
|
||||
S32 y;
|
||||
for (y=-1; y<=1; y++)
|
||||
{
|
||||
F32 yoffset = offset.y + y*256.0f;
|
||||
for (S32 x=-1; x<=1; x++)
|
||||
{
|
||||
F32 xoffset = offset.x + x*256.0f;
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(xoffset + center.x, yoffset + center.y-5);
|
||||
glVertex2f(xoffset + center.x, yoffset + center.y+6);
|
||||
glVertex2f(xoffset + center.x-5, yoffset + center.y);
|
||||
glVertex2f(xoffset + center.x+6, yoffset + center.y);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------- RENDER the Block Corners
|
||||
Point2F corner( worldToCtrl(Point2F(-mTerrainSize/2.0f, -mTerrainSize/2.0f)) );
|
||||
for (y=-1; y<=1; y++)
|
||||
{
|
||||
S32 yoffset = offset.y + y*256;
|
||||
for (S32 x=-1; x<=1; x++)
|
||||
{
|
||||
S32 xoffset = offset.x + x*256;
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
|
||||
glVertex2i(xoffset + corner.x, yoffset + corner.y-128);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.7f);
|
||||
glVertex2i(xoffset + corner.x, yoffset + corner.y);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
|
||||
glVertex2i(xoffset + corner.x+128, yoffset + corner.y);
|
||||
glEnd();
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
|
||||
glVertex2i(xoffset + corner.x, yoffset + corner.y+128);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.7f);
|
||||
glVertex2i(xoffset + corner.x, yoffset + corner.y);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
|
||||
glVertex2i(xoffset + corner.x-128, yoffset + corner.y);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------- RENDER the Viewcone
|
||||
Point2F pointA(cameraRot.x * -40, cameraRot.y * -40);
|
||||
Point2F pointB(-pointA.y, pointA.x);
|
||||
|
||||
F32 tann = mTan(0.5f);
|
||||
Point2F point1( pointA + pointB * tann );
|
||||
Point2F point2( pointA - pointB * tann );
|
||||
|
||||
center.set(offset.x + mBounds.extent.x / 2, offset.y + mBounds.extent.y / 2 );
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 0.7f);
|
||||
glVertex2i(center.x + point1.x, center.y + point1.y);
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
glVertex2i(center.x, center.y);
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 0.7f);
|
||||
glVertex2i(center.x + point2.x, center.y + point2.y);
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
/* debuging stuff
|
||||
Point2I loc(offset.x +5, offset.y+10);
|
||||
dglSetBitmapModulation(mProfile->mFontColor);
|
||||
dglDrawText(mProfile->mFont, loc, avar("mCamera(%3.2f, %3.2f)", mCamera.x, mCamera.y)); loc.y += 10;
|
||||
dglDrawText(mProfile->mFont, loc, avar("mRoot(%3.2f, %3.2f)", mRoot.x, mRoot.y)); loc.y += 10;
|
||||
dglDrawText(mProfile->mFont, loc, avar("mOrigin(%3.2f, %3.2f)", mOrigin.x, mOrigin.y)); loc.y += 10;
|
||||
*/
|
||||
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
|
||||
|
||||
61
editor/guiTerrPreviewCtrl.h
Normal file
61
editor/guiTerrPreviewCtrl.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUITERRPREVIEWCTRL_H_
|
||||
#define _GUITERRPREVIEWCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
#ifndef _GUITSCONTROL_H_
|
||||
#include "GUI/guiTSControl.h"
|
||||
#endif
|
||||
|
||||
class GuiTerrPreviewCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
TextureHandle mTextureHandle;
|
||||
Point2F mRoot;
|
||||
Point2F mOrigin;
|
||||
Point2F mWorldScreenCenter;
|
||||
Point2F mCamera;
|
||||
F32 mTerrainSize;
|
||||
|
||||
Point2F& wrap(const Point2F &p);
|
||||
Point2F& worldToTexture(const Point2F &p);
|
||||
Point2F& worldToCtrl(const Point2F &p);
|
||||
|
||||
|
||||
public:
|
||||
//creation methods
|
||||
DECLARE_CONOBJECT(GuiTerrPreviewCtrl);
|
||||
GuiTerrPreviewCtrl();
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
//Parental methods
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
void setBitmap(const TextureHandle &handle);
|
||||
|
||||
void reset();
|
||||
void setRoot();
|
||||
void setRoot(const Point2F &root);
|
||||
void setOrigin(const Point2F &origin);
|
||||
const Point2F& getRoot() { return mRoot; }
|
||||
const Point2F& getOrigin() { return mOrigin; }
|
||||
|
||||
//void setValue(const Point2F *center, const Point2F *camera);
|
||||
//const char *getScriptValue();
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
1103
editor/missionAreaEditor.cc
Normal file
1103
editor/missionAreaEditor.cc
Normal file
File diff suppressed because it is too large
Load diff
148
editor/missionAreaEditor.h
Normal file
148
editor/missionAreaEditor.h
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _MISSIONAREAEDITOR_H_
|
||||
#define _MISSIONAREAEDITOR_H_
|
||||
|
||||
#ifndef _GUIBITMAPCTRL_H_
|
||||
#include "gui/guiBitmapCtrl.h"
|
||||
#endif
|
||||
#ifndef _GUITYPES_H_
|
||||
#include "gui/guiTypes.h"
|
||||
#endif
|
||||
#ifndef _MISSIONAREA_H_
|
||||
#include "game/missionArea.h"
|
||||
#endif
|
||||
|
||||
class GBitmap;
|
||||
class TerrainBlock;
|
||||
|
||||
class MissionAreaEditor : public GuiBitmapCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiBitmapCtrl Parent;
|
||||
|
||||
SimObjectPtr<MissionArea> mMissionArea;
|
||||
SimObjectPtr<TerrainBlock> mTerrainBlock;
|
||||
|
||||
GBitmap * createTerrainBitmap();
|
||||
void onUpdate();
|
||||
|
||||
void setControlObjPos(const Point2F & pos);
|
||||
bool clampArea(RectI & area);
|
||||
|
||||
// --------------------------------------------------
|
||||
// conversion
|
||||
VectorF mScale;
|
||||
Point2F mCenterPos;
|
||||
|
||||
Point2F worldToScreen(const Point2F &);
|
||||
Point2F screenToWorld(const Point2F &);
|
||||
|
||||
void getScreenMissionArea(RectI & rect);
|
||||
void getScreenMissionArea(RectF & rect);
|
||||
|
||||
void setupScreenTransform(const Point2I & offset);
|
||||
|
||||
// --------------------------------------------------
|
||||
// mouse
|
||||
enum {
|
||||
DefaultCursor = 0,
|
||||
HandCursor,
|
||||
GrabCursor,
|
||||
VertResizeCursor,
|
||||
HorizResizeCursor,
|
||||
DiagRightResizeCursor,
|
||||
DiagLeftResizeCursor,
|
||||
NumCursors
|
||||
};
|
||||
|
||||
bool grabCursors();
|
||||
GuiCursor * mCurrentCursor;
|
||||
GuiCursor * mCursors[NumCursors];
|
||||
GuiCursor * getCursor();
|
||||
void setCursor(U32 cursor);
|
||||
|
||||
S32 mLastHitMode;
|
||||
Point2I mLastMousePoint;
|
||||
|
||||
// --------------------------------------------------
|
||||
// mission area
|
||||
enum {
|
||||
NUT_SIZE = 3
|
||||
};
|
||||
|
||||
enum {
|
||||
nothing = 0,
|
||||
sizingLeft = BIT(0),
|
||||
sizingRight = BIT(1),
|
||||
sizingTop = BIT(2),
|
||||
sizingBottom = BIT(3),
|
||||
moving = BIT(4)
|
||||
};
|
||||
|
||||
void updateCursor(S32 hit);
|
||||
bool inNut(const Point2I & pt, S32 x, S32 y);
|
||||
S32 getSizingHitKnobs(const Point2I & pt, const RectI & box);
|
||||
void drawNut(const Point2I & nut);
|
||||
void drawNuts(RectI & box);
|
||||
|
||||
public:
|
||||
|
||||
MissionAreaEditor();
|
||||
|
||||
//
|
||||
bool missionAreaObjValid() { return(bool(mMissionArea)); }
|
||||
bool terrainObjValid() { return( mTerrainBlock.operator bool () ); }
|
||||
|
||||
TerrainBlock * getTerrainObj();
|
||||
|
||||
const RectI & getArea();
|
||||
void setArea(const RectI & area);
|
||||
|
||||
void updateTerrainBitmap();
|
||||
|
||||
// GuiControl
|
||||
void parentResized(const Point2I &, const Point2I &);
|
||||
void onRender(Point2I offset, const RectI & updateRect, GuiControl * firstResponder);
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
void onMouseUp(const GuiEvent & event);
|
||||
void onMouseDown(const GuiEvent & event);
|
||||
void onMouseMove(const GuiEvent & event);
|
||||
void onMouseDragged(const GuiEvent & event);
|
||||
void onMouseEnter(const GuiEvent & event);
|
||||
void onMouseLeave(const GuiEvent & event);
|
||||
|
||||
// SimObject
|
||||
bool onAdd();
|
||||
|
||||
// field data..
|
||||
bool mSquareBitmap;
|
||||
bool mEnableEditing;
|
||||
bool mRenderCamera;
|
||||
|
||||
ColorI mHandleFrameColor;
|
||||
ColorI mHandleFillColor;
|
||||
ColorI mDefaultObjectColor;
|
||||
ColorI mWaterObjectColor;
|
||||
ColorI mMissionBoundsColor;
|
||||
ColorI mCameraColor;
|
||||
|
||||
bool mEnableMirroring;
|
||||
S32 mMirrorIndex;
|
||||
ColorI mMirrorLineColor;
|
||||
ColorI mMirrorArrowColor;
|
||||
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
DECLARE_CONOBJECT(MissionAreaEditor);
|
||||
};
|
||||
|
||||
#endif
|
||||
1371
editor/terraformer.cc
Normal file
1371
editor/terraformer.cc
Normal file
File diff suppressed because it is too large
Load diff
232
editor/terraformer.h
Normal file
232
editor/terraformer.h
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _TERRAFORMER_H_
|
||||
#define _TERRAFORMER_H_
|
||||
|
||||
#ifndef _CONSOLE_H_
|
||||
#include "console/console.h"
|
||||
#endif
|
||||
#ifndef _SIMBASE_H_
|
||||
#include "console/simBase.h"
|
||||
#endif
|
||||
#ifndef _TERRDATA_H_
|
||||
#include "terrain/terrData.h"
|
||||
#endif
|
||||
#ifndef _GBITMAP_H_
|
||||
#include "dgl/gBitmap.h"
|
||||
#endif
|
||||
#ifndef _MRANDOM_H_
|
||||
#include "Math/mRandom.h"
|
||||
#endif
|
||||
#ifndef _TERRAFORMER_NOISE_H_
|
||||
#include "Editor/terraformer_noise.h"
|
||||
#endif
|
||||
#ifndef _GUIFILTERCTRL_H_
|
||||
#include "GUI/guiFilterCtrl.h"
|
||||
#endif
|
||||
|
||||
|
||||
struct Heightfield
|
||||
{
|
||||
static S32 *zoneOffset;
|
||||
static U32 instance;
|
||||
|
||||
U32 registerNumber;
|
||||
U32 mask;
|
||||
U32 shift;
|
||||
union
|
||||
{
|
||||
F32 *data;
|
||||
S32 *dataS32;
|
||||
};
|
||||
Heightfield(U32 r, U32 sz);
|
||||
~Heightfield();
|
||||
|
||||
Heightfield& operator=(const Heightfield &src);
|
||||
S32 offset(S32 x, S32 y);
|
||||
F32& val(S32 x, S32 y);
|
||||
F32& val(S32 index);
|
||||
void block(S32 x, S32 y, F32 *a );
|
||||
|
||||
S32& valS32(S32 x, S32 y);
|
||||
S32& valS32(S32 index);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Terraformer: public SimObject
|
||||
{
|
||||
public:
|
||||
enum BlendOperation
|
||||
{
|
||||
OperationAdd,
|
||||
OperationSubtract,
|
||||
OperationMax,
|
||||
OperationMin,
|
||||
OperationMultiply,
|
||||
};
|
||||
|
||||
private:
|
||||
VectorPtr<Heightfield*> registerList;
|
||||
VectorPtr<Heightfield*> scratchList;
|
||||
MRandomR250 random;
|
||||
|
||||
Noise2D noise;
|
||||
|
||||
// used by wrap, val inlines
|
||||
U32 blockMask;
|
||||
U32 blockSize;
|
||||
F32 worldTileSize;
|
||||
F32 worldBaseHeight;
|
||||
F32 worldHeight;
|
||||
F32 worldWater;
|
||||
Point2F mShift;
|
||||
|
||||
S32 wrap(S32 p);
|
||||
|
||||
Heightfield* getRegister(U32 r);
|
||||
Heightfield* getScratch(U32 r);
|
||||
void getMinMax(U32 r, F32 *fmin, F32 *fmax);
|
||||
|
||||
public:
|
||||
Terraformer();
|
||||
~Terraformer();
|
||||
static void consoleInit();
|
||||
DECLARE_CONOBJECT(Terraformer);
|
||||
|
||||
void setSize(U32 n);
|
||||
void setTerrainInfo(U32 blockSize, F32 tileSize, F32 minHeight, F32 heightRange, F32 worldWater);
|
||||
void setShift( const Point2F &shift );
|
||||
void clearRegister(U32 r);
|
||||
|
||||
// I/O operations
|
||||
GBitmap* getScaledGreyscale(U32 r);
|
||||
GBitmap* getGreyscale(U32 r);
|
||||
bool saveGreyscale(U32 r, const char *filename);
|
||||
bool loadGreyscale(U32 r, const char *filename);
|
||||
bool saveHeightField(U32 r, const char *filename);
|
||||
bool setTerrain(U32 r);
|
||||
void setCameraPosition(const Point3F & pos);
|
||||
Point3F getCameraPosition();
|
||||
|
||||
|
||||
// Mathmatical operations
|
||||
bool scale(U32 r_src, U32 r_dst, F32 fmin, F32 fmax);
|
||||
bool smooth(U32 r_src, U32 r_dst, F32 factor, U32 iterations);
|
||||
bool smoothWater(U32 r_src, U32 r_dst, F32 factor, U32 iterations);
|
||||
bool smoothRidges(U32 r_src, U32 r_dst, F32 factor, U32 iterations, F32 threshold);
|
||||
bool blend(U32 r_srcA, U32 r_srcB, U32 r_dst, F32 factor, BlendOperation operation);
|
||||
bool filter(U32 r_src, U32 r_dst, const Filter &filter);
|
||||
bool turbulence(U32 r_src, U32 r_dst, F32 v, F32 r);
|
||||
bool shift(U32 r_src);
|
||||
|
||||
// Generation operations
|
||||
bool setHeight(U32 r, F32 height);
|
||||
bool terrainData(U32 r);
|
||||
bool terrainFile(U32 r, const char * terrFile);
|
||||
bool fBm(U32 r, U32 interval, F32 roughness, F32 detail, U32 seed);
|
||||
bool rigidMultiFractal(U32 r, U32 interval, F32 roughness, F32 detail, U32 seed);
|
||||
bool canyonFractal(U32 r, U32 f, F32 v, U32 seed);
|
||||
bool sinus(U32 r, const Filter &filter, U32 seed);
|
||||
|
||||
// effects
|
||||
bool erodeHydraulic(U32 r_src, U32 r_dst, U32 iterations, const Filter &filter);
|
||||
bool erodeThermal(U32 r_src, U32 r_dst, F32 slope, F32 materialLoss, U32 iterations);
|
||||
|
||||
// Texturing operations
|
||||
bool maskFBm(U32 r_dst, U32 interval, F32 roughness, U32 seed, const Filter &filter, bool distort, U32 r_distort);
|
||||
bool maskHeight(U32 r_src, U32 r_dst, const Filter &filter, bool distort, U32 r_distort);
|
||||
bool maskSlope(U32 r_src, U32 r_dst, const Filter &filter, bool distort, U32 r_distort);
|
||||
bool maskWater(U32 r_src, U32 r_dst, bool distort, U32 r_distort);
|
||||
|
||||
bool mergeMasks(const char *r_src, U32 r_dst);
|
||||
bool setMaterials(const char *r_src, const char *materials);
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
inline S32 Heightfield::offset(S32 x, S32 y)
|
||||
{
|
||||
return (y<<shift) + x;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
inline F32& Heightfield::val(S32 i)
|
||||
{
|
||||
return (data[i]);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
inline F32& Heightfield::val(S32 x, S32 y)
|
||||
{
|
||||
return data[ (y<<shift) + x ];
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
inline S32& Heightfield::valS32(S32 i)
|
||||
{
|
||||
return (dataS32[i]);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
inline S32& Heightfield::valS32(S32 x, S32 y)
|
||||
{
|
||||
return dataS32[ (y<<shift) + x ];
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
inline S32 Terraformer::wrap(S32 p)
|
||||
{ // simply wrap the coordinate
|
||||
return (p & blockMask);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
inline void Heightfield::block(S32 x, S32 y, F32 *a )
|
||||
{
|
||||
// zone = 0-8
|
||||
//
|
||||
// 0 1 2
|
||||
// 3 4 5
|
||||
// 5 6 8
|
||||
//
|
||||
|
||||
U32 zone = 0;
|
||||
if (x > 0)
|
||||
{
|
||||
zone++;
|
||||
if (x >= mask)
|
||||
zone++;
|
||||
}
|
||||
if (y > 0)
|
||||
{
|
||||
zone += 3;
|
||||
if (y >= mask)
|
||||
zone += 3;
|
||||
}
|
||||
|
||||
F32 *d = &data[ (y<<shift) + x ];
|
||||
S32 *p = &zoneOffset[ zone*9 ];
|
||||
|
||||
a[0] = d[ p[0] ];
|
||||
a[1] = d[ p[1] ];
|
||||
a[2] = d[ p[2] ];
|
||||
|
||||
a[3] = d[ p[3] ];
|
||||
a[4] = d[ p[4] ];
|
||||
a[5] = d[ p[5] ];
|
||||
|
||||
a[6] = d[ p[6] ];
|
||||
a[7] = d[ p[7] ];
|
||||
a[8] = d[ p[8] ];
|
||||
}
|
||||
|
||||
|
||||
#endif //_H_TERRAFORMER_
|
||||
325
editor/terraformerNoise.cc
Normal file
325
editor/terraformerNoise.cc
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Editor/terraformer_noise.h"
|
||||
#include "Editor/terraformer.h"
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
Noise2D::Noise2D()
|
||||
{
|
||||
mSeed = 0;
|
||||
}
|
||||
|
||||
Noise2D::~Noise2D()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
void Noise2D::normalize(F32 v[2])
|
||||
{
|
||||
F32 s;
|
||||
|
||||
s = mSqrt(v[0] * v[0] + v[1] * v[1]);
|
||||
v[0] = v[0] / s;
|
||||
v[1] = v[1] / s;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
void Noise2D::setSeed(U32 seed)
|
||||
{
|
||||
if (mSeed == seed)
|
||||
return;
|
||||
mSeed = seed;
|
||||
mRandom.setSeed(mSeed);
|
||||
|
||||
S32 i, j, k;
|
||||
|
||||
for (i = 0 ; i < SIZE ; i++) {
|
||||
mPermutation[i] = i;
|
||||
|
||||
for (j = 0 ; j < 2 ; j++)
|
||||
mGradient[i][j] = mRandom.randF( -1.0f, 1.0f );
|
||||
normalize(mGradient[i]);
|
||||
}
|
||||
|
||||
while (--i) {
|
||||
k = mPermutation[i];
|
||||
j = mRandom.randI(0, SIZE-1);
|
||||
mPermutation[i] = mPermutation[j];
|
||||
mPermutation[j] = k;
|
||||
}
|
||||
|
||||
// extend the size of the arrays x2 to get rid of a bunch of MODs
|
||||
// we'd have to do later in the code
|
||||
for (i = 0 ; i < SIZE + 2 ; i++) {
|
||||
mPermutation[SIZE + i] = mPermutation[i];
|
||||
for (j = 0 ; j < 2 ; j++)
|
||||
mGradient[SIZE + i][j] = mGradient[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
U32 Noise2D::getSeed()
|
||||
{
|
||||
return mSeed;
|
||||
}
|
||||
|
||||
|
||||
inline F32 Noise2D::lerp(F32 t, F32 a, F32 b)
|
||||
{
|
||||
return a + t * (b - a);
|
||||
}
|
||||
|
||||
|
||||
inline F32 Noise2D::curve(F32 t)
|
||||
{
|
||||
return t * t * (3.0f - 2.0f * t);
|
||||
}
|
||||
|
||||
|
||||
inline F32 clamp(F32 f, F32 m)
|
||||
{
|
||||
while (f > m)
|
||||
f -= m;
|
||||
while (f < 0.0f)
|
||||
f += m;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
void Noise2D::fBm(Heightfield *dst, U32 size, U32 interval, F32 h, F32 octaves)
|
||||
{
|
||||
interval = getMin(U32(128), getMax(U32(1), interval));
|
||||
F32 H = getMin(1.0f, getMax(0.0f, h));
|
||||
octaves = getMin(5.0f, getMax(1.0f, octaves));
|
||||
F32 lacunarity = 2.0f;
|
||||
|
||||
F32 exponent_array[32];
|
||||
|
||||
// precompute and store spectral weights
|
||||
// seize required memory for exponent_array
|
||||
F32 frequency = 1.0;
|
||||
for (U32 i=0; i<=octaves; i++)
|
||||
{
|
||||
// compute weight for each frequency
|
||||
exponent_array[i] = mPow( frequency, -H );
|
||||
frequency *= lacunarity;
|
||||
}
|
||||
|
||||
// initialize dst
|
||||
for (S32 k=0; k < (size*size); k++)
|
||||
dst->val(k) = 0.0f;
|
||||
|
||||
F32 scale = 1.0f / (F32)size * interval;
|
||||
for (S32 o=0; o<octaves; o++)
|
||||
{
|
||||
F32 exp = exponent_array[o];
|
||||
for (S32 y=0; y<size; y++)
|
||||
{
|
||||
F32 fy = (F32)y * scale;
|
||||
for (S32 x=0; x<size; x++)
|
||||
{
|
||||
F32 fx = (F32)x * scale;
|
||||
F32 noise = getValue(fx, fy, interval);
|
||||
dst->val(x, y) += noise * exp;
|
||||
}
|
||||
}
|
||||
scale *= lacunarity;
|
||||
interval = (U32)(interval * lacunarity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
void Noise2D::rigidMultiFractal(Heightfield *dst, Heightfield *sig, U32 size, U32 interval, F32 h, F32 octaves)
|
||||
{
|
||||
interval = getMin(U32(128), getMax(U32(1), interval));
|
||||
F32 H = getMin(1.0f, getMax(0.0f, h));
|
||||
octaves = getMin(5.0f, getMax(1.0f, octaves));
|
||||
F32 lacunarity = 2.0f;
|
||||
F32 offset = 1.0f;
|
||||
F32 gain = 2.0f;
|
||||
|
||||
F32 exponent_array[32];
|
||||
|
||||
// precompute and store spectral weights
|
||||
// seize required memory for exponent_array
|
||||
F32 frequency = 1.0;
|
||||
for (U32 i=0; i<=octaves; i++)
|
||||
{
|
||||
// compute weight for each frequency
|
||||
exponent_array[i] = mPow( frequency, -H );
|
||||
frequency *= lacunarity;
|
||||
}
|
||||
|
||||
F32 scale = 1.0f / (F32)size * interval;
|
||||
|
||||
//--------------------------------------
|
||||
// compute first octave
|
||||
for (S32 y=0; y<size; y++)
|
||||
{
|
||||
F32 fy = (F32)y * scale;
|
||||
for (S32 x=0; x<size; x++)
|
||||
{
|
||||
F32 fx = (F32)x * scale;
|
||||
|
||||
F32 signal = mFabs(getValue(fx,fy,interval)); // get absolute value of signal (this creates the ridges)
|
||||
//signal = mSqrt(signal);
|
||||
signal = offset - signal; // invert and translate (note that "offset" should be ~= 1.0)
|
||||
signal *= signal + 0.1; // square the signal, to increase "sharpness" of ridges
|
||||
|
||||
// assign initial values
|
||||
dst->val(x, y) = signal;
|
||||
sig->val(x, y) = signal;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// compute remaining octaves
|
||||
for (S32 o=1; o<octaves; o++)
|
||||
{
|
||||
// increase the frequency
|
||||
scale *= lacunarity;
|
||||
interval = (U32)(interval * lacunarity);
|
||||
F32 exp = exponent_array[o];
|
||||
|
||||
for (S32 y=0; y<size; y++)
|
||||
{
|
||||
F32 fy = (F32)y * scale;
|
||||
for (S32 x=0; x<size; x++)
|
||||
{
|
||||
F32 fx = (F32)x * scale;
|
||||
U32 index = dst->offset(x,y);
|
||||
F32 result = dst->val(index);
|
||||
F32 signal = sig->val(index);
|
||||
|
||||
// weight successive contributions by previous signal
|
||||
F32 weight = mClampF(signal * gain, 0.0f, 1.0f);
|
||||
|
||||
signal = mFabs(getValue( fx, fy, interval ));
|
||||
|
||||
signal = offset - signal;
|
||||
signal *= signal + 0.2;
|
||||
// weight the contribution
|
||||
signal *= weight;
|
||||
result += signal * exp;
|
||||
|
||||
dst->val(index) = result;
|
||||
sig->val(index) = signal;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (S32 k=0; k < (size*size); k++)
|
||||
dst->val(k) = (dst->val(k)-1.0f)/2.0f;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
F32 Noise2D::turbulence(F32 x, F32 y, F32 freq)
|
||||
{
|
||||
F32 t, x2, y2;
|
||||
|
||||
for ( t = 0.0f ; freq >= 3.0f ; freq /= 2.0f)
|
||||
{
|
||||
x2 = freq * x;
|
||||
y2 = freq * y;
|
||||
t += mFabs(getValue(x2, y2, freq)) / freq;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
inline void Noise2D::setup(F32 t, S32 &b0, S32 &b1, F32 &r0, F32 &r1)
|
||||
{
|
||||
// find the bounding integers of u
|
||||
b0 = S32(t) & SIZE_MASK;
|
||||
b1 = (b0+1) & SIZE_MASK;
|
||||
|
||||
// seperate the fractional components
|
||||
r0 = t - (S32)t;
|
||||
r1 = r0 - 1.0f;
|
||||
}
|
||||
|
||||
inline F32 Noise2D::dot(const F32 *q, F32 rx, F32 ry)
|
||||
{
|
||||
return (rx * q[0] + ry * q[1] );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
F32 Noise2D::getValue(F32 x, F32 y, S32 interval)
|
||||
{
|
||||
S32 bx0, bx1, by0, by1;
|
||||
F32 rx0, rx1, ry0, ry1;
|
||||
|
||||
// Imagine having a square of the type
|
||||
// p0---p1 Where p0 = (bx0, by0) +----> U
|
||||
// |(u,v)| p1 = (bx1, by0) |
|
||||
// | | p2 = (bx0, by1) | Coordinate System
|
||||
// p2---p3 p3 = (bx1, by1) V
|
||||
// The u, v point in 2D texture space is bounded by this rectangle.
|
||||
|
||||
// Goal, determine the scalar at the points p0, p1, p2, p3.
|
||||
// Then the scalar of the point (u, v) will be found by linear interpolation.
|
||||
|
||||
// First step: Get the 2D coordinates of the points p0, p1, p2, p3.
|
||||
// We also need vectors pointing from each point in the square above and
|
||||
// ending at the (u,v) coordinate located inside the square.
|
||||
// The vector (rx0, ry0) goes from P0 to the (u,v) coordinate.
|
||||
// The vector (rx1, ry0) goes from P1 to the (u,v) coordinate.
|
||||
// The vector (rx0, ry1) goes from P2 to the (u,v) coordinate.
|
||||
// The vector (rx1, ry1) goes from P3 to the (u,v) coordinate.
|
||||
|
||||
setup(x, bx0, bx1, rx0, rx1);
|
||||
setup(y, by0, by1, ry0, ry1);
|
||||
|
||||
// Make sure the box corners fall within the interval
|
||||
// so that the final output will wrap on itself
|
||||
bx0 = bx0 % interval;
|
||||
bx1 = bx1 % interval;
|
||||
by0 = by0 % interval;
|
||||
by1 = by1 % interval;
|
||||
|
||||
S32 i = mPermutation[ bx0 ];
|
||||
S32 j = mPermutation[ bx1 ];
|
||||
|
||||
S32 b00 = mPermutation[ i + by0 ];
|
||||
S32 b10 = mPermutation[ j + by0 ];
|
||||
S32 b01 = mPermutation[ i + by1 ];
|
||||
S32 b11 = mPermutation[ j + by1 ];
|
||||
|
||||
// Next, calculate the dropoff component about the point p0.
|
||||
F32 sx = curve(rx0);
|
||||
F32 sy = curve(ry0);
|
||||
|
||||
// Now, for each point in the square shown above, calculate the dot
|
||||
// product of the gradiant vector and the vector going from each square
|
||||
// corner point to the (u,v) point inside the square.
|
||||
F32 u = dot(mGradient[ b00 ], rx0,ry0);
|
||||
F32 v = dot(mGradient[ b10 ], rx1,ry0);
|
||||
|
||||
// Interpolation along the X axis.
|
||||
F32 a = lerp(sx, u, v);
|
||||
|
||||
u = dot(mGradient[ b01 ], rx0,ry1);
|
||||
v = dot(mGradient[ b11 ], rx1,ry1);
|
||||
|
||||
// Interpolation along the Y axis.
|
||||
F32 b = lerp(sx, u, v);
|
||||
|
||||
// Final Interpolation
|
||||
return lerp(sy, a, b);
|
||||
}
|
||||
|
||||
|
||||
60
editor/terraformerNoise.h
Normal file
60
editor/terraformerNoise.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _TERRAFORMER_NOISE_H_
|
||||
#define _TERRAFORMER_NOISE_H_
|
||||
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _MMATH_H_
|
||||
#include "Math/mMath.h"
|
||||
#endif
|
||||
#ifndef _MRANDOM_H_
|
||||
#include "Math/mRandom.h"
|
||||
#endif
|
||||
|
||||
struct Heightfield;
|
||||
|
||||
class Noise2D
|
||||
{
|
||||
private:
|
||||
enum Constants {
|
||||
SIZE = 0x100,
|
||||
SIZE_MASK = 0x0ff
|
||||
};
|
||||
S32 mPermutation[SIZE + SIZE + 2];
|
||||
F32 mGradient[SIZE + SIZE + 2][2];
|
||||
|
||||
U32 mSeed;
|
||||
|
||||
MRandom mRandom;
|
||||
|
||||
F32 lerp(F32 t, F32 a, F32 b);
|
||||
F32 curve(F32 t);
|
||||
void setup(F32 t, S32 &b0, S32 &b1, F32 &r0, F32 &r1);
|
||||
F32 dot(const F32 *q, F32 rx, F32 ry);
|
||||
void normalize(F32 v[2]);
|
||||
|
||||
|
||||
public:
|
||||
Noise2D();
|
||||
~Noise2D();
|
||||
|
||||
void setSeed(U32 seed);
|
||||
U32 getSeed();
|
||||
|
||||
F32 getValue(F32 u, F32 v, S32 interval);
|
||||
void fBm(Heightfield *dst, U32 size, U32 interval, F32 h, F32 octave=5.0f);
|
||||
void rigidMultiFractal(Heightfield *dst, Heightfield *signal, U32 size, U32 interval, F32 h, F32 octave=5.0f);
|
||||
F32 turbulence(F32 x, F32 y, F32 freq);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // _H_TERRAFORMER_NOISE_
|
||||
415
editor/terraformerTexture.cc
Normal file
415
editor/terraformerTexture.cc
Normal file
|
|
@ -0,0 +1,415 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "terrain/terrData.h"
|
||||
#include "editor/terraformer.h"
|
||||
#include "gui/guiFilterCtrl.h"
|
||||
#include "editor/editor.h"
|
||||
#include "platform/event.h"
|
||||
#include "game/gameConnection.h"
|
||||
|
||||
#include "core/fileStream.h"
|
||||
|
||||
|
||||
|
||||
inline F32 lerp(F32 t, F32 a, F32 b)
|
||||
{
|
||||
return a + t * (b - a);
|
||||
}
|
||||
|
||||
|
||||
inline F32 curve(F32 t)
|
||||
{
|
||||
return t * t * (3.0f - 2.0f * t);
|
||||
}
|
||||
|
||||
|
||||
F32 getAlpha(U32 x, U32 y, Heightfield *alpha)
|
||||
{
|
||||
F32 xFactor = F32(x & 7) * (1.0f/8.0f);
|
||||
F32 yFactor = F32(y & 7) * (1.0f/8.0f);
|
||||
U32 xi = x >> 3;
|
||||
U32 yi = y >> 3;
|
||||
|
||||
F32 a0 = alpha->val(xi, yi);
|
||||
F32 a1 = alpha->val(xi+1, yi);
|
||||
F32 a2 = alpha->val(xi+1, yi+1);
|
||||
F32 a3 = alpha->val(xi, yi+1);
|
||||
|
||||
// F32 ah0 = (a0 * (1.0f-xFactor)) + (a1 * xFactor);
|
||||
// F32 ah1 = (a3 * (1.0f-xFactor)) + (a2 * xFactor);
|
||||
//
|
||||
// F32 a = (ah0 * (1.0f-yFactor)) + (ah1 * yFactor);
|
||||
|
||||
//xFactor = curve(xFactor);
|
||||
//yFactor = curve(yFactor);
|
||||
|
||||
F32 ah0 = lerp(xFactor, a0, a1);
|
||||
F32 ah1 = lerp(xFactor, a3, a2);
|
||||
F32 a = lerp(yFactor, ah0, ah1);
|
||||
|
||||
return (a*a);
|
||||
}
|
||||
|
||||
|
||||
GBitmap* merge(VectorPtr<Heightfield*> &alpha, VectorPtr<GBitmap*> &material)
|
||||
{
|
||||
// due to memory constraints we build the the output bitmap one scan-line at a time.
|
||||
F32 sum[2048];
|
||||
GBitmap *bitmap = new GBitmap(2048, 2048, false, GBitmap::RGB);
|
||||
VectorPtr<Heightfield*>::iterator itrA;
|
||||
VectorPtr<GBitmap*>::iterator itrM;
|
||||
|
||||
for (S32 y = 0; y<2048; y++)
|
||||
{
|
||||
// first compute the sum of the alphas at each pixel
|
||||
S32 x;
|
||||
for (x = 0; x<2048; x++)
|
||||
{
|
||||
sum[x] = 0.0f;
|
||||
for (itrA = alpha.begin(); itrA != alpha.end(); itrA++)
|
||||
sum[x] += getAlpha(x,y,*itrA);
|
||||
}
|
||||
|
||||
// blend the pixels
|
||||
for (x = 0; x<2048; x++)
|
||||
{
|
||||
ColorI blend(0,0,0,0);
|
||||
if (sum[x] > 0.0f)
|
||||
{
|
||||
F32 fsum = sum[x];
|
||||
F32 scaleFactor = (1.0f/fsum);
|
||||
for (itrA = alpha.begin(), itrM = material.begin(); itrM != material.end(); itrM++, itrA++)
|
||||
{
|
||||
ColorI color;
|
||||
GBitmap *bmp = *itrM;
|
||||
bmp->getColor(x % bmp->getWidth(), y % bmp->getHeight(), color);
|
||||
color *= getAlpha(x,y,*itrA) * scaleFactor;
|
||||
blend.red += color.red;
|
||||
blend.green += color.green;
|
||||
blend.blue += color.blue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GBitmap *mat = *material.begin();
|
||||
mat->getColor(x % mat->getWidth(), y % mat->getHeight(), blend);
|
||||
}
|
||||
bitmap->setColor(x,y,blend);
|
||||
}
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool Terraformer::setMaterials(const char *r_src, const char *materials )
|
||||
{
|
||||
TerrainBlock *serverTerrBlock = dynamic_cast<TerrainBlock*>(Sim::findObject("Terrain"));
|
||||
if (!serverTerrBlock)
|
||||
return false;
|
||||
|
||||
NetConnection* toServer = NetConnection::getServerConnection();
|
||||
NetConnection* toClient = NetConnection::getLocalClientConnection();
|
||||
|
||||
S32 index = toClient->getGhostIndex(serverTerrBlock);
|
||||
|
||||
TerrainBlock *clientTerrBlock = dynamic_cast<TerrainBlock*>(toServer->resolveGhost(index));
|
||||
if (!clientTerrBlock)
|
||||
return false;
|
||||
|
||||
VectorPtr<Heightfield*> src;
|
||||
VectorPtr<char*> dml;
|
||||
Vector<S32> dmlIndex;
|
||||
|
||||
//--------------------------------------
|
||||
// extract the source registers
|
||||
char buffer[1024];
|
||||
dStrcpy(buffer, r_src);
|
||||
char *str = dStrtok(buffer, " \0");
|
||||
while (str)
|
||||
{
|
||||
src.push_back( getRegister(dAtof(str)) );
|
||||
str = dStrtok(NULL, " \0");
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// extract the materials
|
||||
dStrcpy(buffer, materials);
|
||||
str = dStrtok(buffer, " \0");
|
||||
while (str)
|
||||
{
|
||||
S32 i;
|
||||
for (i=0; i<dml.size(); i++)
|
||||
if (dStricmp(str, dml[i]) == 0)
|
||||
break;
|
||||
|
||||
// a unique material list ?
|
||||
if (i == dml.size())
|
||||
dml.push_back(str);
|
||||
|
||||
// map register to dml
|
||||
dmlIndex.push_back(i);
|
||||
|
||||
str = dStrtok(NULL, " \0");
|
||||
}
|
||||
|
||||
if (dml.size() > TerrainBlock::MaterialGroups)
|
||||
{
|
||||
Con::printf("maximum number of DML Material Exceeded");
|
||||
return false;
|
||||
}
|
||||
|
||||
// install the new DMLs
|
||||
clientTerrBlock->setBaseMaterials(dml.size(), (const char**)dml.address());
|
||||
|
||||
//--------------------------------------
|
||||
// build alpha masks for each material type
|
||||
|
||||
for (S32 y=0; y<blockSize; y++)
|
||||
{
|
||||
for (S32 x=0; x<blockSize; x++)
|
||||
{
|
||||
// skip? (cannot skip if index is out of range...)
|
||||
F32 total = 0;
|
||||
F32 matVals[TerrainBlock::MaterialGroups];
|
||||
S32 i;
|
||||
|
||||
for(i = 0; i < TerrainBlock::MaterialGroups; i++)
|
||||
matVals[i] = 0;
|
||||
|
||||
for(i = 0; i < src.size(); i++)
|
||||
{
|
||||
matVals[dmlIndex[i]] += src[i]->val(x,y);
|
||||
total += src[i]->val(x,y);
|
||||
}
|
||||
|
||||
if(total == 0)
|
||||
{
|
||||
matVals[0] = 1;
|
||||
total = 1;
|
||||
}
|
||||
|
||||
// axe out any amount that is less than the threshold
|
||||
F32 threshold = 0.15 * total;
|
||||
for(i = 0; i < TerrainBlock::MaterialGroups; i++)
|
||||
if(matVals[i] < threshold)
|
||||
matVals[i] = 0;
|
||||
|
||||
total = 0;
|
||||
for(i = 0; i < TerrainBlock::MaterialGroups; i++)
|
||||
total += matVals[i];
|
||||
|
||||
for(i = 0; i < TerrainBlock::MaterialGroups; i++)
|
||||
{
|
||||
U8 *map = clientTerrBlock->getMaterialAlphaMap(i);
|
||||
map[x + (y << TerrainBlock::BlockShift)] = (U8)(255 * matVals[i] / total);
|
||||
}
|
||||
|
||||
S32 material = 0;
|
||||
F32 best = 0.0f;
|
||||
for (i=0; i<src.size(); i++)
|
||||
{
|
||||
F32 value = src[i]->val(x,y);
|
||||
if ( value > best)
|
||||
{
|
||||
material = dmlIndex[i];
|
||||
best = value;
|
||||
}
|
||||
}
|
||||
// place the material
|
||||
*clientTerrBlock->getBaseMaterialAddress(x, y) = material;
|
||||
}
|
||||
}
|
||||
|
||||
// make it so!
|
||||
clientTerrBlock->buildGridMap();
|
||||
clientTerrBlock->buildMaterialMap();
|
||||
|
||||
// reload the material lists?
|
||||
if(gEditingMission)
|
||||
clientTerrBlock->refreshMaterialLists();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// for mow steal the first bitmap out of each dml
|
||||
|
||||
if (Con::getBoolVariable("$terrainTestBmp", false) == true)
|
||||
{
|
||||
VectorPtr<GBitmap*> mats;
|
||||
for (S32 i=0; i<dmlIndex.size(); i++)
|
||||
{
|
||||
char buf[128];
|
||||
dSprintf(buf, sizeof(buf), "textures/%s.dml", dml[dmlIndex[i]]);
|
||||
Resource<MaterialList> mlist = ResourceManager->load(buf);
|
||||
mlist->load();
|
||||
GBitmap *bmp = mlist->getMaterial(0).getBitmap();
|
||||
mats.push_back(bmp);
|
||||
}
|
||||
GBitmap *texture = merge(src,mats);
|
||||
|
||||
FileStream stream;
|
||||
stream.open("terrain.png", FileStream::Write);
|
||||
texture->writePNG(stream);
|
||||
stream.close();
|
||||
delete texture;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool Terraformer::mergeMasks(const char *r_src, U32 r_dst)
|
||||
{
|
||||
Heightfield *dst = getRegister(r_dst);
|
||||
VectorPtr<Heightfield*> src;
|
||||
|
||||
// extract the source registers
|
||||
char buffer[1024];
|
||||
dStrcpy(buffer, r_src);
|
||||
char *reg = dStrtok(buffer, " \0");
|
||||
while (reg)
|
||||
{
|
||||
src.push_back( getRegister(dAtoi(reg)) );
|
||||
reg = dStrtok(NULL, " \0");
|
||||
}
|
||||
|
||||
// if no masks set the destination to Zero
|
||||
if (src.size() == 0)
|
||||
{
|
||||
for (S32 i=0; i < (blockSize*blockSize); i++)
|
||||
dst->val(i) = 0.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (src.size() == 1)
|
||||
{
|
||||
for (S32 i=0; i < (blockSize*blockSize); i++)
|
||||
dst->val(i) = src[0]->val(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
// store the MAX of the masks into dst
|
||||
for (S32 i=0; i < (blockSize*blockSize); i++)
|
||||
{
|
||||
F32 value = src[0]->val(i);
|
||||
for (S32 j=1; j<src.size(); j++)
|
||||
value *= src[j]->val(i);
|
||||
dst->val(i) = value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool Terraformer::maskFBm(U32 r_dst, U32 interval, F32 roughness, U32 seed, const Filter &filter, bool distort, U32 r_distort)
|
||||
{
|
||||
Heightfield *dst = getRegister(r_dst);
|
||||
noise.setSeed(seed);
|
||||
noise.fBm(dst, blockSize, interval, 1.0-roughness, 3.0f);
|
||||
|
||||
scale(r_dst, r_dst, 0.0f, 1.0f);
|
||||
|
||||
for (S32 i=0; i < (blockSize*blockSize); i++)
|
||||
dst->val(i) = filter.getValue( dst->val(i) );
|
||||
|
||||
if (distort)
|
||||
{
|
||||
Heightfield *d = getRegister(r_distort);
|
||||
for (S32 i=0; i < (blockSize*blockSize); i++)
|
||||
dst->val(i) *= d->val(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool Terraformer::maskHeight(U32 r_src, U32 r_dst, const Filter &filter, bool distort, U32 r_distort)
|
||||
{
|
||||
Heightfield *src = getRegister(r_src);
|
||||
Heightfield *dst = getRegister(r_dst);
|
||||
|
||||
scale(r_src, r_dst, 0.0f, 1.0f);
|
||||
|
||||
for (S32 i=0; i < (blockSize*blockSize); i++)
|
||||
dst->val(i) = filter.getValue(dst->val(i));
|
||||
|
||||
if (distort)
|
||||
{
|
||||
Heightfield *d = getRegister(r_distort);
|
||||
for (S32 i=0; i < (blockSize*blockSize); i++)
|
||||
dst->val(i) *= d->val(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool Terraformer::maskSlope(U32 r_src, U32 r_dst, const Filter &filter, bool distort, U32 r_distort)
|
||||
{
|
||||
Heightfield *src = getRegister(r_src);
|
||||
Heightfield *dst = getRegister(r_dst);
|
||||
|
||||
F32 fmin, fmax;
|
||||
getMinMax(r_src, &fmin, &fmax);
|
||||
F32 scale = worldHeight / (fmax-fmin);
|
||||
|
||||
for (S32 y=0; y<blockSize; y++)
|
||||
{
|
||||
for (S32 x=0; x<blockSize; x++)
|
||||
{
|
||||
// for each height look at the immediate surrounding heights and find max slope
|
||||
F32 array[9];
|
||||
F32 maxDelta = 0;
|
||||
src->block(x,y,array);
|
||||
F32 height = array[4];
|
||||
|
||||
for (S32 i=0; i<9; i++)
|
||||
{
|
||||
F32 delta = mFabs(array[i] - height);
|
||||
if ( (i&1) == 0)
|
||||
delta *= 0.70711f; // compensate for diagonals
|
||||
|
||||
if (delta > maxDelta)
|
||||
maxDelta = delta;
|
||||
}
|
||||
F32 slopeVal = mAtan( maxDelta * scale, worldTileSize ) * (2.0f/M_PI);
|
||||
dst->val(x, y) = filter.getValue( mPow(slopeVal, 1.5f) );
|
||||
}
|
||||
}
|
||||
|
||||
if (distort)
|
||||
{
|
||||
Heightfield *d = getRegister(r_distort);
|
||||
for (S32 i=0; i < (blockSize*blockSize); i++)
|
||||
dst->val(i) *= d->val(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool Terraformer::maskWater(U32 r_src, U32 r_dst, bool distort, U32 r_distort)
|
||||
{
|
||||
Heightfield *src = getRegister(r_src);
|
||||
Heightfield *dst = getRegister(r_dst);
|
||||
|
||||
scale(r_src, r_dst, 0.0f, 1.0f);
|
||||
|
||||
for (S32 i=0; i < (blockSize*blockSize); i++)
|
||||
dst->val(i) = (dst->val(i) > worldWater) ? 0.0f : 1.0f;
|
||||
|
||||
if (distort)
|
||||
{
|
||||
Heightfield *d = getRegister(r_distort);
|
||||
for (S32 i=0; i < (blockSize*blockSize); i++)
|
||||
dst->val(i) *= d->val(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
454
editor/terrainActions.cc
Normal file
454
editor/terrainActions.cc
Normal file
|
|
@ -0,0 +1,454 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Editor/terrainActions.h"
|
||||
#include "Platform/event.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void SelectAction::process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type)
|
||||
{
|
||||
if(sel == mTerrainEditor->getCurrentSel())
|
||||
return;
|
||||
|
||||
if(type == Process)
|
||||
return;
|
||||
|
||||
if(selChanged)
|
||||
{
|
||||
if(event.modifier & SI_CTRL)
|
||||
{
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
mTerrainEditor->getCurrentSel()->remove((*sel)[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
GridInfo gInfo;
|
||||
if(mTerrainEditor->getCurrentSel()->getInfo((*sel)[i].mGridPos, gInfo))
|
||||
{
|
||||
if(!gInfo.mPrimarySelect)
|
||||
gInfo.mPrimarySelect = (*sel)[i].mPrimarySelect;
|
||||
|
||||
if(gInfo.mWeight < (*sel)[i].mWeight)
|
||||
gInfo.mWeight = (*sel)[i].mWeight;
|
||||
|
||||
mTerrainEditor->getCurrentSel()->setInfo(gInfo);
|
||||
}
|
||||
else
|
||||
mTerrainEditor->getCurrentSel()->add((*sel)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void SoftSelectAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type type)
|
||||
{
|
||||
// allow process of current selection
|
||||
Selection tmpSel;
|
||||
if(sel == mTerrainEditor->getCurrentSel())
|
||||
{
|
||||
tmpSel = *sel;
|
||||
sel = &tmpSel;
|
||||
}
|
||||
|
||||
if(type == Begin || type == Process)
|
||||
mFilter.set(1, &mTerrainEditor->mSoftSelectFilter);
|
||||
|
||||
//
|
||||
if(selChanged)
|
||||
{
|
||||
F32 radius = mTerrainEditor->mSoftSelectRadius;
|
||||
if(radius == 0.f)
|
||||
return;
|
||||
|
||||
S32 squareSize = mTerrainEditor->getTerrainBlock()->getSquareSize();
|
||||
U32 offset = U32(radius / F32(squareSize)) + 1;
|
||||
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
GridInfo & info = (*sel)[i];
|
||||
|
||||
info.mPrimarySelect = true;
|
||||
info.mWeight = mFilter.getValue(0);
|
||||
|
||||
if(!mTerrainEditor->getCurrentSel()->add(info))
|
||||
mTerrainEditor->getCurrentSel()->setInfo(info);
|
||||
|
||||
Point2F infoPos(info.mGridPos.x, info.mGridPos.y);
|
||||
|
||||
//
|
||||
for(S32 x = info.mGridPos.x - offset; x < info.mGridPos.x + (offset << 1); x++)
|
||||
for(S32 y = info.mGridPos.y - offset; y < info.mGridPos.y + (offset << 1); y++)
|
||||
{
|
||||
//
|
||||
Point2F pos(x, y);
|
||||
|
||||
F32 dist = Point2F(pos - infoPos).len() * F32(squareSize);
|
||||
|
||||
if(dist > radius)
|
||||
continue;
|
||||
|
||||
F32 weight = mFilter.getValue(dist / radius);
|
||||
|
||||
//
|
||||
GridInfo gInfo;
|
||||
if(mTerrainEditor->getCurrentSel()->getInfo(Point2I(x, y), gInfo))
|
||||
{
|
||||
if(gInfo.mPrimarySelect)
|
||||
continue;
|
||||
|
||||
if(gInfo.mWeight < weight)
|
||||
{
|
||||
gInfo.mWeight = weight;
|
||||
mTerrainEditor->getCurrentSel()->setInfo(gInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mTerrainEditor->getGridInfo(Point2I(x, y), gInfo);
|
||||
gInfo.mWeight = weight;
|
||||
gInfo.mPrimarySelect = false;
|
||||
mTerrainEditor->getCurrentSel()->add(gInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void OutlineSelectAction::process(Selection * sel, const Gui3DMouseEvent & event, bool, Type type)
|
||||
{
|
||||
sel;event;type;
|
||||
switch(type)
|
||||
{
|
||||
case Begin:
|
||||
if(event.modifier & SI_SHIFT)
|
||||
break;
|
||||
|
||||
mTerrainEditor->getCurrentSel()->reset();
|
||||
break;
|
||||
|
||||
case End:
|
||||
case Update:
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
mLastEvent = event;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void RaiseHeightAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
|
||||
{
|
||||
if(selChanged)
|
||||
for(U32 i = 0; i < (*sel).size(); i++)
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
(*sel)[i].mHeight += mTerrainEditor->mAdjustHeightVal * (*sel)[i].mWeight;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void LowerHeightAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
|
||||
{
|
||||
if(selChanged)
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
(*sel)[i].mHeight -= mTerrainEditor->mAdjustHeightVal * (*sel)[i].mWeight;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void SetHeightAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
|
||||
{
|
||||
if(selChanged)
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
(*sel)[i].mHeight = mTerrainEditor->mSetHeightVal;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void SetEmptyAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
|
||||
{
|
||||
if(selChanged)
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
(*sel)[i].mMaterial.flags |= TerrainBlock::Material::Empty;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ClearEmptyAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
|
||||
{
|
||||
if(selChanged)
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
(*sel)[i].mMaterial.flags &= ~TerrainBlock::Material::Empty;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void SetModifiedAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
|
||||
{
|
||||
if(selChanged)
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
(*sel)[i].mMaterial.flags |= TerrainBlock::Material::Modified;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ClearModifiedAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
|
||||
{
|
||||
if(selChanged)
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
(*sel)[i].mMaterial.flags &= ~TerrainBlock::Material::Modified;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ScaleHeightAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
|
||||
{
|
||||
if(selChanged)
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
(*sel)[i].mHeight *= mTerrainEditor->mScaleVal;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void BrushAdjustHeightAction::process(Selection * sel, const Gui3DMouseEvent & event, bool, Type type)
|
||||
{
|
||||
if(type == Process)
|
||||
return;
|
||||
|
||||
//
|
||||
if(type == Begin)
|
||||
{
|
||||
mTerrainEditor->lockSelection(true);
|
||||
|
||||
mFirstPos = mLastPos = event.mousePoint;
|
||||
Canvas->mouseLock(mTerrainEditor);
|
||||
|
||||
// add to undo
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
}
|
||||
else if(type == Update)
|
||||
{
|
||||
//
|
||||
F32 diff = (event.mousePoint.x - mLastPos.x) * mTerrainEditor->mAdjustHeightMouseScale;
|
||||
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
(*sel)[i].mHeight += diff * (*sel)[i].mWeight;
|
||||
|
||||
// clamp it
|
||||
if((*sel)[i].mHeight < 0.f)
|
||||
(*sel)[i].mHeight = 0.f;
|
||||
if((*sel)[i].mHeight > 2047.f)
|
||||
(*sel)[i].mHeight = 2047.f;
|
||||
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
|
||||
mLastPos = event.mousePoint;
|
||||
}
|
||||
else if(type == End)
|
||||
{
|
||||
Canvas->mouseUnlock(mTerrainEditor);
|
||||
Canvas->setCursorPos(mFirstPos);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
AdjustHeightAction::AdjustHeightAction(TerrainEditor * editor) :
|
||||
TerrainAction(editor)
|
||||
{
|
||||
mCursor = 0;
|
||||
}
|
||||
|
||||
void AdjustHeightAction::process(Selection *, const Gui3DMouseEvent & event, bool, Type type)
|
||||
{
|
||||
if(type == Process)
|
||||
return;
|
||||
|
||||
Selection * curSel = mTerrainEditor->getCurrentSel();
|
||||
|
||||
//
|
||||
if(type == Begin)
|
||||
{
|
||||
mTerrainEditor->lockSelection(true);
|
||||
|
||||
if(!mTerrainEditor->collide(event, mHitPos))
|
||||
return;
|
||||
|
||||
if(!bool(mCursor))
|
||||
mCursor = dynamic_cast<GuiCursor*>(Sim::findObject("Editor_HandCursor"));
|
||||
|
||||
if(bool(mCursor))
|
||||
mTerrainEditor->setCursor(mCursor);
|
||||
|
||||
mLastPos = mHitPos;
|
||||
|
||||
// add to undo
|
||||
for(U32 i = 0; i < curSel->size(); i++)
|
||||
mTerrainEditor->getUndoSel()->add((*curSel)[i]);
|
||||
}
|
||||
else if(type == Update)
|
||||
{
|
||||
// do a projection onto the z axis
|
||||
F64 dist = mSqrt((event.pos.x - mHitPos.x) * (event.pos.x - mHitPos.x) +
|
||||
(event.pos.y - mHitPos.y) * (event.pos.y - mHitPos.y));
|
||||
|
||||
Point3F vec(mHitPos.x - event.pos.x, mHitPos.y - event.pos.y, 0.f);
|
||||
vec.normalize();
|
||||
|
||||
F64 projDist = mDot(event.vec, vec);
|
||||
if(projDist == 0.f)
|
||||
return;
|
||||
|
||||
F64 scale = dist / projDist;
|
||||
vec = event.pos + (event.vec * scale);
|
||||
|
||||
for(U32 i = 0; i < curSel->size(); i++)
|
||||
{
|
||||
F32 diff = (vec.z - mLastPos.z) * (*curSel)[i].mWeight;
|
||||
(*curSel)[i].mHeight += diff;
|
||||
|
||||
// clamp it
|
||||
if((*curSel)[i].mHeight < 0.f)
|
||||
(*curSel)[i].mHeight = 0.f;
|
||||
if((*curSel)[i].mHeight > 2047.f)
|
||||
(*curSel)[i].mHeight = 2047.f;
|
||||
|
||||
mTerrainEditor->setGridInfo((*curSel)[i]);
|
||||
}
|
||||
|
||||
mLastPos = vec;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// flatten the primary selection then blend in the rest...
|
||||
|
||||
void FlattenHeightAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
|
||||
{
|
||||
if(!sel->size())
|
||||
return;
|
||||
|
||||
if(selChanged)
|
||||
{
|
||||
F32 average = 0.f;
|
||||
|
||||
// get the average height
|
||||
U32 cPrimary = 0;
|
||||
for(U32 k = 0; k < sel->size(); k++)
|
||||
if((*sel)[k].mPrimarySelect)
|
||||
{
|
||||
cPrimary++;
|
||||
average += (*sel)[k].mHeight;
|
||||
}
|
||||
|
||||
average /= cPrimary;
|
||||
|
||||
// set it
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
|
||||
//
|
||||
if((*sel)[i].mPrimarySelect)
|
||||
(*sel)[i].mHeight = average;
|
||||
else
|
||||
{
|
||||
F32 h = average - (*sel)[i].mHeight;
|
||||
(*sel)[i].mHeight += (h * (*sel)[i].mWeight);
|
||||
}
|
||||
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void SmoothHeightAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
|
||||
{
|
||||
if(!sel->size())
|
||||
return;
|
||||
|
||||
if(selChanged)
|
||||
{
|
||||
F32 avgHeight = 0.f;
|
||||
for(U32 k = 0; k < sel->size(); k++)
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[k]);
|
||||
avgHeight += (*sel)[k].mHeight;
|
||||
}
|
||||
|
||||
avgHeight /= sel->size();
|
||||
|
||||
// clamp the terrain smooth factor...
|
||||
if(mTerrainEditor->mSmoothFactor < 0.f)
|
||||
mTerrainEditor->mSmoothFactor = 0.f;
|
||||
if(mTerrainEditor->mSmoothFactor > 1.f)
|
||||
mTerrainEditor->mSmoothFactor = 1.f;
|
||||
|
||||
// linear
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
(*sel)[i].mHeight += (avgHeight - (*sel)[i].mHeight) * mTerrainEditor->mSmoothFactor * (*sel)[i].mWeight;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetMaterialGroupAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
|
||||
{
|
||||
if(selChanged)
|
||||
for(U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
|
||||
(*sel)[i].mMaterial.flags |= TerrainBlock::Material::Modified;
|
||||
(*sel)[i].mMaterialGroup = mTerrainEditor->mMaterialGroup;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
233
editor/terrainActions.h
Normal file
233
editor/terrainActions.h
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _TERRAINACTIONS_H_
|
||||
#define _TERRAINACTIONS_H_
|
||||
|
||||
#ifndef _TERRAINEDITOR_H_
|
||||
#include "Editor/terrainEditor.h"
|
||||
#endif
|
||||
#ifndef _GUIFILTERCTRL_H_
|
||||
#include "GUI/guiFilterCtrl.h"
|
||||
#endif
|
||||
|
||||
class TerrainAction
|
||||
{
|
||||
protected:
|
||||
TerrainEditor * mTerrainEditor;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~TerrainAction(){};
|
||||
TerrainAction(TerrainEditor * editor) : mTerrainEditor(editor){}
|
||||
|
||||
virtual StringTableEntry getName() = 0;
|
||||
|
||||
enum Type {
|
||||
Begin = 0,
|
||||
Update,
|
||||
End,
|
||||
Process
|
||||
};
|
||||
|
||||
//
|
||||
virtual void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type) = 0;
|
||||
virtual bool useMouseBrush() { return(true); }
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class SelectAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
SelectAction(TerrainEditor * editor) : TerrainAction(editor){};
|
||||
StringTableEntry getName(){return("select");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
class SoftSelectAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
SoftSelectAction(TerrainEditor * editor) : TerrainAction(editor){};
|
||||
StringTableEntry getName(){return("softSelect");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
|
||||
Filter mFilter;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class OutlineSelectAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
OutlineSelectAction(TerrainEditor * editor) : TerrainAction(editor){};
|
||||
StringTableEntry getName(){return("outlineSelect");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
bool useMouseBrush() { return(false); }
|
||||
|
||||
private:
|
||||
|
||||
Gui3DMouseEvent mLastEvent;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class RaiseHeightAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
RaiseHeightAction(TerrainEditor * editor) : TerrainAction(editor){}
|
||||
StringTableEntry getName(){return("raiseHeight");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class LowerHeightAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
LowerHeightAction(TerrainEditor * editor) : TerrainAction(editor){}
|
||||
StringTableEntry getName(){return("lowerHeight");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class SetHeightAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
SetHeightAction(TerrainEditor * editor) : TerrainAction(editor){}
|
||||
StringTableEntry getName(){return("setHeight");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class SetEmptyAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
SetEmptyAction(TerrainEditor * editor) : TerrainAction(editor){}
|
||||
StringTableEntry getName(){return("setEmpty");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class ClearEmptyAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
ClearEmptyAction(TerrainEditor * editor) : TerrainAction(editor){}
|
||||
StringTableEntry getName(){return("clearEmpty");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class SetModifiedAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
SetModifiedAction(TerrainEditor * editor) : TerrainAction(editor){}
|
||||
StringTableEntry getName(){return("setModified");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class ClearModifiedAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
ClearModifiedAction(TerrainEditor * editor) : TerrainAction(editor){}
|
||||
StringTableEntry getName(){return("clearModified");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class ScaleHeightAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
ScaleHeightAction(TerrainEditor * editor) : TerrainAction(editor){}
|
||||
StringTableEntry getName(){return("scaleHeight");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class BrushAdjustHeightAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
BrushAdjustHeightAction(TerrainEditor * editor) : TerrainAction(editor){}
|
||||
StringTableEntry getName(){return("brushAdjustHeight");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
|
||||
private:
|
||||
Point2I mFirstPos;
|
||||
Point2I mLastPos;
|
||||
|
||||
// private:
|
||||
// //
|
||||
// Point3F mHitPos;
|
||||
// Point3F mLastPos;
|
||||
};
|
||||
|
||||
class AdjustHeightAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
AdjustHeightAction(TerrainEditor * editor);
|
||||
StringTableEntry getName(){return("adjustHeight");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
bool useMouseBrush() { return(false); }
|
||||
|
||||
private:
|
||||
//
|
||||
Point3F mHitPos;
|
||||
Point3F mLastPos;
|
||||
SimObjectPtr<GuiCursor> mCursor;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class FlattenHeightAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
FlattenHeightAction(TerrainEditor * editor) : TerrainAction(editor){}
|
||||
StringTableEntry getName(){return("flattenHeight");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
class SmoothHeightAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
SmoothHeightAction(TerrainEditor * editor) : TerrainAction(editor){}
|
||||
StringTableEntry getName(){return("smoothHeight");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
class SetMaterialGroupAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
SetMaterialGroupAction(TerrainEditor * editor) : TerrainAction(editor){}
|
||||
StringTableEntry getName(){return("setMaterialGroup");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
#endif
|
||||
1703
editor/terrainEditor.cc
Normal file
1703
editor/terrainEditor.cc
Normal file
File diff suppressed because it is too large
Load diff
313
editor/terrainEditor.h
Normal file
313
editor/terrainEditor.h
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _TERRAINEDITOR_H_
|
||||
#define _TERRAINEDITOR_H_
|
||||
|
||||
#ifndef _EDITTSCTRL_H_
|
||||
#include "Editor/editTSCtrl.h"
|
||||
#endif
|
||||
#ifndef _TERRDATA_H_
|
||||
#include "terrain/terrData.h"
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class GridInfo
|
||||
{
|
||||
public:
|
||||
Point2I mGridPos;
|
||||
TerrainBlock::Material mMaterial;
|
||||
F32 mHeight;
|
||||
U8 mMaterialGroup;
|
||||
F32 mWeight;
|
||||
|
||||
bool mPrimarySelect;
|
||||
|
||||
// hash table
|
||||
S32 mNext;
|
||||
S32 mPrev;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class Selection : public Vector<GridInfo>
|
||||
{
|
||||
private:
|
||||
|
||||
StringTableEntry mName;
|
||||
BitSet32 mUndoFlags;
|
||||
|
||||
// hash table
|
||||
S32 lookup(const Point2I & pos);
|
||||
void insert(GridInfo & info);
|
||||
U32 getHashIndex(const Point2I & pos);
|
||||
|
||||
Vector<S32> mHashLists;
|
||||
U32 mHashListSize;
|
||||
|
||||
public:
|
||||
|
||||
Selection();
|
||||
|
||||
void reset();
|
||||
bool add(GridInfo & info);
|
||||
bool getInfo(Point2I pos, GridInfo & info);
|
||||
bool setInfo(GridInfo & info);
|
||||
bool remove(const GridInfo & info);
|
||||
void setName(StringTableEntry name);
|
||||
StringTableEntry getName(){return(mName);}
|
||||
F32 getAvgHeight();
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class TerrainEditor;
|
||||
class Brush : public Selection
|
||||
{
|
||||
protected:
|
||||
TerrainEditor * mTerrainEditor;
|
||||
Point2I mSize;
|
||||
Point2I mGridPos;
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
MaxBrushDim = 40
|
||||
};
|
||||
|
||||
Brush(TerrainEditor * editor);
|
||||
virtual ~Brush(){};
|
||||
|
||||
//
|
||||
void setPosition(const Point3F & pos);
|
||||
void setPosition(const Point2I & pos);
|
||||
const Point2I & getPosition();
|
||||
|
||||
void update();
|
||||
virtual void rebuild() = 0;
|
||||
|
||||
Point2I getSize(){return(mSize);}
|
||||
virtual void setSize(const Point2I & size){mSize = size;}
|
||||
};
|
||||
|
||||
class BoxBrush : public Brush
|
||||
{
|
||||
public:
|
||||
BoxBrush(TerrainEditor * editor) : Brush(editor){}
|
||||
void rebuild();
|
||||
};
|
||||
|
||||
class EllipseBrush : public Brush
|
||||
{
|
||||
public:
|
||||
EllipseBrush(TerrainEditor * editor) : Brush(editor){}
|
||||
void rebuild();
|
||||
};
|
||||
|
||||
class SelectionBrush : public Brush
|
||||
{
|
||||
public:
|
||||
SelectionBrush(TerrainEditor * editor);
|
||||
void rebuild();
|
||||
void setSize(const Point2I &){}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// must declare the console functions before making them a friend of TerrainEditor
|
||||
static void cAttachTerrain(SimObject *, S32, const char **);
|
||||
static void cSetBrushType(SimObject *, S32, const char **);
|
||||
static void cSetBrushSize(SimObject *, S32, const char **);
|
||||
static const char * cGetBrushPos(SimObject *, S32, const char **);
|
||||
static void cSetBrushPos(SimObject *, S32, const char **);
|
||||
static void cSetAction(SimObject *, S32, const char **);
|
||||
static S32 cGetNumActions(SimObject *, S32, const char **);
|
||||
static const char * cGetActionName(SimObject *, S32, const char **);
|
||||
static const char * cGetCurrentAction(SimObject *, S32, const char **);
|
||||
static void cResetSelWeights(SimObject *, S32, const char **);
|
||||
static void cUndoAction(SimObject *, S32, const char **);
|
||||
static void cRedoAction(SimObject *, S32, const char **);
|
||||
static void cClearSelection(SimObject *, S32, const char **);
|
||||
static void cProcessAction(SimObject *, S32, const char **);
|
||||
static void cBuildMaterialMap(SimObject * obj, S32, const char **);
|
||||
static S32 cGetNumTextures(SimObject * obj, S32, const char **);
|
||||
static const char * cGetTextureName(SimObject * obj, S32, const char ** argv);
|
||||
static void cMarkEmptySquares(SimObject * obj, S32, const char **);
|
||||
static void cClearModifiedFlags(SimObject * obj, S32, const char **);
|
||||
static void cMirrorTerrain(SimObject * obj, S32, const char **);
|
||||
static void cPushBaseMaterialInfo(SimObject * obj, S32, const char **);
|
||||
static void cPopBaseMaterialInfo(SimObject * obj, S32, const char **);
|
||||
static void cSetLoneBaseMaterial(SimObject * obj, S32, const char ** argv);
|
||||
|
||||
struct BaseMaterialInfo {
|
||||
StringTableEntry mMaterialNames[TerrainBlock::MaterialGroups];
|
||||
U8 mBaseMaterials[TerrainBlock::BlockSize * TerrainBlock::BlockSize];
|
||||
};
|
||||
|
||||
class TerrainAction;
|
||||
class TerrainEditor : public EditTSCtrl
|
||||
{
|
||||
private:
|
||||
|
||||
// give console functions full access
|
||||
friend void cAttachTerrain(SimObject *, S32, const char **);
|
||||
friend void cSetBrushType(SimObject *, S32, const char **);
|
||||
friend void cSetBrushSize(SimObject *, S32, const char **);
|
||||
friend const char * cGetBrushPos(SimObject *, S32, const char **);
|
||||
friend void cSetBrushPos(SimObject *, S32, const char **);
|
||||
friend void cSetAction(SimObject *, S32, const char **);
|
||||
friend S32 cGetNumActions(SimObject *, S32, const char **);
|
||||
friend const char * cGetActionName(SimObject *, S32, const char **);
|
||||
friend const char * cGetCurrentAction(SimObject *, S32, const char **);
|
||||
friend void cResetSelWeights(SimObject *, S32, const char **);
|
||||
friend void cUndoAction(SimObject *, S32, const char **);
|
||||
friend void cRedoAction(SimObject *, S32, const char **);
|
||||
friend void cClearSelection(SimObject *, S32, const char**);
|
||||
friend void cProcessAction(SimObject *, S32, const char **);
|
||||
friend void cBuildMaterialMap(SimObject * obj, S32, const char **);
|
||||
friend S32 cGetNumTextures(SimObject * obj, S32, const char **);
|
||||
friend const char * cGetTextureName(SimObject * obj, S32, const char ** argv);
|
||||
friend void cMarkEmptySquares(SimObject * obj, S32, const char **);
|
||||
friend void cClearModifiedFlags(SimObject * obj, S32, const char **);
|
||||
friend void cMirrorTerrain(SimObject * obj, S32, const char **);
|
||||
friend void cPushBaseMaterialInfo(SimObject * obj, S32, const char **);
|
||||
friend void cPopBaseMaterialInfo(SimObject * obj, S32, const char **);
|
||||
friend void cSetLoneBaseMaterial(SimObject * obj, S32, const char ** argv);
|
||||
|
||||
typedef EditTSCtrl Parent;
|
||||
TerrainBlock * mTerrainBlock;
|
||||
|
||||
Point3F mMousePos;
|
||||
Brush * mMouseBrush;
|
||||
bool mRenderBrush;
|
||||
Point2I mBrushSize;
|
||||
Vector<TerrainAction *> mActions;
|
||||
TerrainAction * mCurrentAction;
|
||||
bool mInAction;
|
||||
Selection mDefaultSel;
|
||||
bool mSelectionLocked;
|
||||
GuiCursor * mDefaultCursor;
|
||||
Selection * mCurrentSel;
|
||||
|
||||
//
|
||||
bool mRebuildEmpty;
|
||||
bool mRebuildTextures;
|
||||
void rebuild();
|
||||
|
||||
void addUndo(Vector<Selection *> & list, Selection * sel);
|
||||
bool processUndo(Vector<Selection *> & src, Vector<Selection *> & dest);
|
||||
void clearUndo(Vector<Selection *> & list);
|
||||
|
||||
U32 mUndoLimit;
|
||||
Selection * mUndoSel;
|
||||
|
||||
Vector<Selection*> mUndoList;
|
||||
Vector<Selection*> mRedoList;
|
||||
|
||||
Vector<BaseMaterialInfo*> mBaseMaterialInfos;
|
||||
public:
|
||||
|
||||
TerrainEditor();
|
||||
~TerrainEditor();
|
||||
|
||||
// conversion functions
|
||||
bool gridToWorld(const Point2I & gPos, Point3F & wPos);
|
||||
bool worldToGrid(const Point3F & wPos, Point2I & gPos);
|
||||
bool gridToCenter(const Point2I & gPos, Point2I & cPos);
|
||||
|
||||
bool getGridInfo(const Point3F & wPos, GridInfo & info);
|
||||
bool getGridInfo(const Point2I & gPos, GridInfo & info);
|
||||
void setGridInfo(const GridInfo & info);
|
||||
|
||||
bool collide(const Gui3DMouseEvent & event, Point3F & pos);
|
||||
void lockSelection(bool lock) { mSelectionLocked = lock; };
|
||||
|
||||
Selection * getUndoSel(){return(mUndoSel);}
|
||||
Selection * getCurrentSel(){return(mCurrentSel);}
|
||||
void setCurrentSel(Selection * sel) { mCurrentSel = sel; }
|
||||
void resetCurrentSel() {mCurrentSel = &mDefaultSel; }
|
||||
|
||||
Point2I getBrushSize() { return(mBrushSize); }
|
||||
TerrainBlock * getTerrainBlock() { AssertFatal(mTerrainBlock, "No terrain block"); return(mTerrainBlock); }
|
||||
bool terrainBlockValid() { return(mTerrainBlock ? true : false); }
|
||||
void setCursor(GuiCursor * cursor);
|
||||
|
||||
TerrainAction * lookupAction(const char * name);
|
||||
|
||||
private:
|
||||
|
||||
TerrainBlock * getClientTerrain();
|
||||
|
||||
// terrain interface functions
|
||||
F32 getGridHeight(const Point2I & gPos);
|
||||
void setGridHeight(const Point2I & gPos, const F32 height);
|
||||
|
||||
TerrainBlock::Material getGridMaterial(const Point2I & gPos);
|
||||
void setGridMaterial(const Point2I & gPos, const TerrainBlock::Material & material);
|
||||
|
||||
U8 getGridMaterialGroup(const Point2I & gPos);
|
||||
void setGridMaterialGroup(const Point2I & gPos, U8 group);
|
||||
|
||||
//
|
||||
void updateBrush(Brush & brush, const Point2I & gPos);
|
||||
|
||||
//
|
||||
Point3F getMousePos(){return(mMousePos);};
|
||||
|
||||
//
|
||||
void renderSelection(const Selection & sel, const ColorF & inColorFull, const ColorF & inColorNone, const ColorF & outColorFull, const ColorF & outColorNone, bool renderFill, bool renderFrame);
|
||||
void renderBorder();
|
||||
|
||||
public:
|
||||
|
||||
// persist field data - these are dynamic
|
||||
bool mRenderBorder;
|
||||
F32 mBorderHeight;
|
||||
ColorI mBorderFillColor;
|
||||
ColorI mBorderFrameColor;
|
||||
bool mBorderLineMode;
|
||||
bool mSelectionHidden;
|
||||
bool mEnableSoftBrushes;
|
||||
bool mRenderVertexSelection;
|
||||
bool mProcessUsesBrush;
|
||||
|
||||
//
|
||||
F32 mAdjustHeightVal;
|
||||
F32 mSetHeightVal;
|
||||
F32 mScaleVal;
|
||||
F32 mSmoothFactor;
|
||||
S32 mMaterialGroup;
|
||||
F32 mSoftSelectRadius;
|
||||
StringTableEntry mSoftSelectFilter;
|
||||
StringTableEntry mSoftSelectDefaultFilter;
|
||||
F32 mAdjustHeightMouseScale;
|
||||
|
||||
public:
|
||||
|
||||
// SimObject
|
||||
bool onAdd();
|
||||
void onDeleteNotify(SimObject * object);
|
||||
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
// EditTSCtrl
|
||||
void on3DMouseUp(const Gui3DMouseEvent & event);
|
||||
void on3DMouseDown(const Gui3DMouseEvent & event);
|
||||
void on3DMouseMove(const Gui3DMouseEvent & event);
|
||||
void on3DMouseDragged(const Gui3DMouseEvent & event);
|
||||
void on3DMouseEnter(const Gui3DMouseEvent & event);
|
||||
void on3DMouseLeave(const Gui3DMouseEvent & event);
|
||||
void updateGuiInfo();
|
||||
void renderScene(const RectI & updateRect);
|
||||
|
||||
DECLARE_CONOBJECT(TerrainEditor);
|
||||
};
|
||||
|
||||
#endif
|
||||
2479
editor/worldEditor.cc
Normal file
2479
editor/worldEditor.cc
Normal file
File diff suppressed because it is too large
Load diff
375
editor/worldEditor.h
Normal file
375
editor/worldEditor.h
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _WORLDEDITOR_H_
|
||||
#define _WORLDEDITOR_H_
|
||||
|
||||
#ifndef _EDITTSCTRL_H_
|
||||
#include "Editor/editTSCtrl.h"
|
||||
#endif
|
||||
#ifndef _CONSOLETYPES_H_
|
||||
#include "console/consoleTypes.h"
|
||||
#endif
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#include "dgl/gTexManager.h"
|
||||
#endif
|
||||
|
||||
|
||||
// declare the console functions and then make them friends of the class -
|
||||
// hopefully this will reduce the number of functions needed in this class
|
||||
static void cIgnoreObjClass(SimObject *, S32, const char **);
|
||||
static void cClearIgnoreList(SimObject *, S32, const char**);
|
||||
static void cUndoAction(SimObject *, S32, const char **);
|
||||
static void cRedoAction(SimObject *, S32, const char **);
|
||||
static void cClearSelection(SimObject *, S32, const char **);
|
||||
static void cSelectObject(SimObject *, S32, const char **);
|
||||
static void cUnselectObject(SimObject *, S32, const char **);
|
||||
static S32 cGetSelectionSize(SimObject *, S32, const char **);
|
||||
static S32 cGetSelectedObject(SimObject *, S32, const char **);
|
||||
static const char * cGetSelectionCentroid(SimObject *, S32, const char **);
|
||||
static void cDropSelection(SimObject *, S32, const char **);
|
||||
static void cDeleteSelection(SimObject *, S32, const char **);
|
||||
static void cCopySelection(SimObject *, S32, const char **);
|
||||
static void cPasteSelection(SimObject *, S32, const char **);
|
||||
static bool cCanPasteSelection(SimObject *, S32, const char **);
|
||||
static void cHideSelection(SimObject *, S32, const char **);
|
||||
static void cLockSelection(SimObject *, S32, const char **);
|
||||
static const char * cGetMode(SimObject *, S32, const char **);
|
||||
static void cSetMode(SimObject *, S32, const char **);
|
||||
static void cAddUndoState(SimObject *, S32, const char **);
|
||||
static void cRedirectConsole(SimObject * obj, S32, const char ** argv);
|
||||
|
||||
class SceneObject;
|
||||
class WorldEditor : public EditTSCtrl
|
||||
{
|
||||
//...
|
||||
friend void cIgnoreObjClass(SimObject *, S32, const char **);
|
||||
friend void cClearIgnoreList(SimObject *, S32, const char **);
|
||||
friend void cUndoAction(SimObject *, S32, const char **);
|
||||
friend void cRedoAction(SimObject *, S32, const char **);
|
||||
friend void cClearSelection(SimObject *, S32, const char **);
|
||||
friend void cSelectObject(SimObject *, S32, const char **);
|
||||
friend void cUnselectObject(SimObject *, S32, const char **);
|
||||
friend S32 cGetSelectionSize(SimObject *, S32, const char **);
|
||||
friend S32 cGetSelectedObject(SimObject *, S32, const char **);
|
||||
friend const char * cGetSelectionCentroid(SimObject *, S32, const char **);
|
||||
friend void cDropSelection(SimObject *, S32, const char **);
|
||||
friend void cDeleteSelection(SimObject *, S32, const char **);
|
||||
friend void cCopySelection(SimObject *, S32, const char **);
|
||||
friend void cPasteSelection(SimObject *, S32, const char **);
|
||||
friend bool cCanPasteSelection(SimObject *, S32, const char **);
|
||||
friend void cHideSelection(SimObject *, S32, const char **);
|
||||
friend void cLockSelection(SimObject *, S32, const char **);
|
||||
friend const char * cGetMode(SimObject *, S32, const char **);
|
||||
friend void cSetMode(SimObject *, S32, const char **);
|
||||
friend void cAddUndoState(SimObject *, S32, const char **);
|
||||
friend void cRedirectConsole(SimObject * obj, S32, const char ** argv);
|
||||
|
||||
public:
|
||||
|
||||
struct CollisionInfo
|
||||
{
|
||||
SceneObject * obj;
|
||||
Point3F pos;
|
||||
VectorF normal;
|
||||
};
|
||||
|
||||
class Selection : public SimObject
|
||||
{
|
||||
typedef SimObject Parent;
|
||||
|
||||
private:
|
||||
|
||||
Point3F mCentroid;
|
||||
Point3F mBoxCentroid;
|
||||
bool mCentroidValid;
|
||||
SimObjectList mObjectList;
|
||||
bool mAutoSelect;
|
||||
|
||||
void updateCentroid();
|
||||
|
||||
public:
|
||||
|
||||
Selection();
|
||||
~Selection();
|
||||
|
||||
//
|
||||
U32 size() { return(mObjectList.size()); }
|
||||
SceneObject * operator[] (S32 index) { return((SceneObject*)mObjectList[index]); }
|
||||
|
||||
bool objInSet(SceneObject *);
|
||||
|
||||
bool addObject(SceneObject *);
|
||||
bool removeObject(SceneObject *);
|
||||
void clear();
|
||||
|
||||
void onDeleteNotify(SimObject *);
|
||||
|
||||
const Point3F & getCentroid();
|
||||
const Point3F & getBoxCentroid();
|
||||
|
||||
void enableCollision();
|
||||
void disableCollision();
|
||||
|
||||
//
|
||||
void autoSelect(bool b) { mAutoSelect = b; }
|
||||
void invalidateCentroid() { mCentroidValid = false; }
|
||||
|
||||
//
|
||||
void offset(const Point3F &);
|
||||
void rotate(const EulerF &, const Point3F &);
|
||||
void scale(const VectorF &);
|
||||
};
|
||||
|
||||
//
|
||||
static SceneObject * getClientObj(SceneObject *);
|
||||
static void setClientObjInfo(SceneObject *, const MatrixF &, const VectorF &);
|
||||
static void updateClientTransforms(Selection &);
|
||||
|
||||
// VERY basic undo stuff - only concerned with transform/scale/...
|
||||
private:
|
||||
|
||||
struct SelectionState
|
||||
{
|
||||
struct Entry
|
||||
{
|
||||
MatrixF mMatrix;
|
||||
VectorF mScale;
|
||||
|
||||
// validation
|
||||
U32 mObjId;
|
||||
U32 mObjNumber;
|
||||
};
|
||||
|
||||
Vector<Entry> mEntries;
|
||||
|
||||
SelectionState() {
|
||||
VECTOR_SET_ASSOCIATION(mEntries);
|
||||
}
|
||||
};
|
||||
|
||||
SelectionState * createUndo(Selection &);
|
||||
void addUndo(Vector<SelectionState *> & list, SelectionState * sel);
|
||||
bool processUndo(Vector<SelectionState *> & src, Vector<SelectionState *> & dest);
|
||||
void clearUndo(Vector<SelectionState *> & list);
|
||||
|
||||
Vector<SelectionState*> mUndoList;
|
||||
Vector<SelectionState*> mRedoList;
|
||||
|
||||
// someday get around to creating a growing memory stream...
|
||||
Vector<U8[2048]> mStreamBufs;
|
||||
|
||||
bool deleteSelection(Selection & sel);
|
||||
bool copySelection(Selection & sel);
|
||||
bool pasteSelection();
|
||||
void dropSelection(Selection & sel);
|
||||
|
||||
// work off of mSelected
|
||||
void hideSelection(bool hide);
|
||||
void lockSelection(bool lock);
|
||||
|
||||
private:
|
||||
typedef EditTSCtrl Parent;
|
||||
|
||||
SceneObject * getControlObject();
|
||||
bool collide(const Gui3DMouseEvent & event, CollisionInfo & info);
|
||||
|
||||
// gfx stuff
|
||||
void renderObjectBox(SceneObject * obj, const ColorI & col);
|
||||
void renderObjectFace(SceneObject * obj, const VectorF & normal, const ColorI & col);
|
||||
void renderSelectionWorldBox(Selection & sel);
|
||||
|
||||
void renderPlane(const Point3F & origin);
|
||||
void renderMousePopupInfo();
|
||||
void renderScreenObj(SceneObject * obj, Point2I sPos);
|
||||
|
||||
// axis gizmo stuff...
|
||||
void calcAxisInfo();
|
||||
bool collideAxisGizmo(const Gui3DMouseEvent & event);
|
||||
void renderAxisGizmo();
|
||||
void renderAxisGizmoText();
|
||||
|
||||
// axis gizmo stuff...
|
||||
Point3F mAxisGizmoCenter;
|
||||
VectorF mAxisGizmoVector[3];
|
||||
F32 mAxisGizmoProjLen;
|
||||
S32 mAxisGizmoSelAxis;
|
||||
bool mUsingAxisGizmo;
|
||||
|
||||
//
|
||||
Point3F snapPoint(const Point3F & pnt);
|
||||
|
||||
//
|
||||
bool mMouseDown;
|
||||
Selection mSelected;
|
||||
bool mUseVertMove;
|
||||
|
||||
Selection mDragSelected;
|
||||
bool mDragSelect;
|
||||
RectI mDragRect;
|
||||
Point2I mDragStart;
|
||||
|
||||
// modes for when dragging a selection
|
||||
enum {
|
||||
Move = 0,
|
||||
Rotate,
|
||||
Scale
|
||||
};
|
||||
|
||||
//
|
||||
U32 mCurrentMode;
|
||||
U32 mDefaultMode;
|
||||
|
||||
S32 mRedirectID;
|
||||
|
||||
CollisionInfo mHitInfo;
|
||||
Point3F mHitOffset;
|
||||
SimObjectPtr<SceneObject> mHitObject;
|
||||
Point2I mHitMousePos;
|
||||
Point3F mHitCentroid;
|
||||
EulerF mHitRotation;
|
||||
bool mMouseDragged;
|
||||
Gui3DMouseEvent mLastMouseEvent;
|
||||
F32 mLastRotation;
|
||||
|
||||
//
|
||||
class ClassInfo
|
||||
{
|
||||
public:
|
||||
~ClassInfo();
|
||||
|
||||
struct Entry
|
||||
{
|
||||
StringTableEntry mName;
|
||||
bool mIgnoreCollision;
|
||||
TextureHandle mDefaultHandle;
|
||||
TextureHandle mSelectHandle;
|
||||
TextureHandle mLockedHandle;
|
||||
};
|
||||
|
||||
Vector<Entry*> mEntries;
|
||||
};
|
||||
|
||||
|
||||
ClassInfo mClassInfo;
|
||||
ClassInfo::Entry mDefaultClassEntry;
|
||||
|
||||
bool objClassIgnored(const SceneObject * obj);
|
||||
ClassInfo::Entry * getClassEntry(StringTableEntry name);
|
||||
ClassInfo::Entry * getClassEntry(const SceneObject * obj);
|
||||
bool addClassEntry(ClassInfo::Entry * entry);
|
||||
|
||||
// persist field data
|
||||
public:
|
||||
|
||||
enum {
|
||||
DropAtOrigin = 0,
|
||||
DropAtCamera,
|
||||
DropAtCameraWithRot,
|
||||
DropBelowCamera,
|
||||
DropAtScreenCenter,
|
||||
DropAtCentroid,
|
||||
DropToGround
|
||||
};
|
||||
|
||||
bool mPlanarMovement;
|
||||
S32 mUndoLimit;
|
||||
S32 mDropType;
|
||||
F32 mProjectDistance;
|
||||
bool mBoundingBoxCollision;
|
||||
bool mRenderPlane;
|
||||
bool mRenderPlaneHashes;
|
||||
ColorI mGridColor;
|
||||
F32 mPlaneDim;
|
||||
Point3F mGridSize;
|
||||
bool mRenderPopupBackground;
|
||||
ColorI mPopupBackgroundColor;
|
||||
ColorI mPopupTextColor;
|
||||
StringTableEntry mSelectHandle;
|
||||
StringTableEntry mDefaultHandle;
|
||||
StringTableEntry mLockedHandle;
|
||||
ColorI mObjectTextColor;
|
||||
bool mObjectsUseBoxCenter;
|
||||
S32 mAxisGizmoMaxScreenLen;
|
||||
bool mAxisGizmoActive;
|
||||
F32 mMouseMoveScale;
|
||||
F32 mMouseRotateScale;
|
||||
F32 mMouseScaleScale;
|
||||
F32 mMinScaleFactor;
|
||||
F32 mMaxScaleFactor;
|
||||
ColorI mObjSelectColor;
|
||||
ColorI mObjMouseOverSelectColor;
|
||||
ColorI mObjMouseOverColor;
|
||||
bool mShowMousePopupInfo;
|
||||
ColorI mDragRectColor;
|
||||
bool mRenderObjText;
|
||||
bool mRenderObjHandle;
|
||||
StringTableEntry mObjTextFormat;
|
||||
ColorI mFaceSelectColor;
|
||||
bool mRenderSelectionBox;
|
||||
ColorI mSelectionBoxColor;
|
||||
bool mSelectionLocked;
|
||||
bool mSnapToGrid;
|
||||
bool mSnapRotations;
|
||||
F32 mRotationSnap;
|
||||
bool mToggleIgnoreList;
|
||||
bool mRenderNav;
|
||||
|
||||
private:
|
||||
// cursor stuff
|
||||
enum {
|
||||
HandCursor = 0,
|
||||
RotateCursor,
|
||||
ScaleCursor,
|
||||
MoveCursor,
|
||||
ArrowCursor,
|
||||
DefaultCursor,
|
||||
|
||||
//
|
||||
NumCursors
|
||||
};
|
||||
|
||||
GuiCursor * mCursors[NumCursors];
|
||||
GuiCursor * mCurrentCursor;
|
||||
bool grabCursors();
|
||||
void setCursor(U32 cursor);
|
||||
GuiCursor * getCursor();
|
||||
|
||||
public:
|
||||
|
||||
WorldEditor();
|
||||
~WorldEditor();
|
||||
|
||||
// SimObject
|
||||
bool onAdd();
|
||||
void onEditorEnable();
|
||||
|
||||
// EditTSCtrl
|
||||
void on3DMouseMove(const Gui3DMouseEvent & event);
|
||||
void on3DMouseDown(const Gui3DMouseEvent & event);
|
||||
void on3DMouseUp(const Gui3DMouseEvent & event);
|
||||
void on3DMouseDragged(const Gui3DMouseEvent & event);
|
||||
void on3DMouseEnter(const Gui3DMouseEvent & event);
|
||||
void on3DMouseLeave(const Gui3DMouseEvent & event);
|
||||
void on3DRightMouseDown(const Gui3DMouseEvent & event);
|
||||
void on3DRightMouseUp(const Gui3DMouseEvent & event);
|
||||
|
||||
void updateGuiInfo();
|
||||
|
||||
//
|
||||
void renderScene(const RectI & updateRect);
|
||||
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
DECLARE_CONOBJECT(WorldEditor);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue