Merge branch 'development' into mipwip
|
|
@ -168,11 +168,20 @@ bool AIController::getAIMove(Move* movePtr)
|
|||
{
|
||||
obj = getAIInfo()->mObj;
|
||||
}
|
||||
|
||||
Point3F start = obj->getPosition();
|
||||
Point3F end = start;
|
||||
start.z = obj->getBoxCenter().z;
|
||||
end.z -= mControllerData->mHeightTolerance;
|
||||
|
||||
obj->disableCollision();
|
||||
// Only repath if not already adjusted and on risky ground
|
||||
RayInfo info;
|
||||
if (obj->getContainer()->castRay(obj->getPosition(), obj->getPosition() - Point3F(0, 0, mControllerData->mHeightTolerance), StaticShapeObjectType, &info))
|
||||
if (obj->getContainer()->castRay(start, end, StaticShapeObjectType, &info))
|
||||
{
|
||||
getNav()->repath();
|
||||
}
|
||||
obj->enableCollision();
|
||||
getGoal()->mInRange = false;
|
||||
}
|
||||
if (getGoal()->getDist() < mControllerData->mFollowTolerance )
|
||||
|
|
@ -530,11 +539,15 @@ AIControllerData::AIControllerData()
|
|||
mAttackRadius = 2.0f;
|
||||
mMoveStuckTolerance = 0.01f;
|
||||
mMoveStuckTestDelay = 30;
|
||||
mHeightTolerance = 0.001f;
|
||||
mHeightTolerance = 0.1f;
|
||||
mFollowTolerance = 1.0f;
|
||||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
mLinkTypes = LinkData(AllFlags);
|
||||
mFilter.setIncludeFlags(mLinkTypes.getFlags());
|
||||
mFilter.setExcludeFlags(0);
|
||||
mAreaCosts.setSize(PolyAreas::NumAreas);
|
||||
mAreaCosts.fill(1.0f);
|
||||
mNavSize = AINavigation::Regular;
|
||||
mFlocking.mChance = 90;
|
||||
mFlocking.mMin = 1.0f;
|
||||
|
|
@ -560,6 +573,8 @@ AIControllerData::AIControllerData(const AIControllerData& other, bool temp_clon
|
|||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
mLinkTypes = other.mLinkTypes;
|
||||
mFilter = other.mFilter;
|
||||
mAreaCosts = other.mAreaCosts;
|
||||
mNavSize = other.mNavSize;
|
||||
mFlocking.mChance = other.mFlocking.mChance;
|
||||
mFlocking.mMin = other.mFlocking.mMin;
|
||||
|
|
@ -629,6 +644,8 @@ void AIControllerData::initPersistFields()
|
|||
addFieldV("FlockSideStep", TypeRangedF32, Offset(mFlocking.mSideStep, AIControllerData), &CommonValidators::PositiveFloat,
|
||||
"@brief Distance from destination before we stop moving out of the way.");
|
||||
|
||||
addField("areaCosts", TypeF32Vector, Offset(mAreaCosts, AIControllerData),
|
||||
"Vector of costs for each PolyArea.");
|
||||
addField("allowWalk", TypeBool, Offset(mLinkTypes.walk, AIControllerData),
|
||||
"Allow the character to walk on dry land.");
|
||||
addField("allowJump", TypeBool, Offset(mLinkTypes.jump, AIControllerData),
|
||||
|
|
@ -662,6 +679,10 @@ void AIControllerData::packData(BitStream* stream)
|
|||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
//enums
|
||||
stream->write(mAreaCosts.size());
|
||||
for (U32 i = 0; i < mAreaCosts.size(); i++) {
|
||||
stream->write(mAreaCosts[i]);
|
||||
}
|
||||
stream->write(mLinkTypes.getFlags());
|
||||
stream->write((U32)mNavSize);
|
||||
// end enums
|
||||
|
|
@ -684,10 +705,23 @@ void AIControllerData::unpackData(BitStream* stream)
|
|||
stream->read(&mFollowTolerance);
|
||||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
U32 num;
|
||||
stream->read(&num);
|
||||
mAreaCosts.setSize(num);
|
||||
for (U32 i = 0; i < num; i++)
|
||||
{
|
||||
stream->read(&mAreaCosts[i]);
|
||||
}
|
||||
//enums
|
||||
U16 linkFlags;
|
||||
stream->read(&linkFlags);
|
||||
mLinkTypes = LinkData(linkFlags);
|
||||
mFilter.setIncludeFlags(mLinkTypes.getFlags());
|
||||
mFilter.setExcludeFlags(mLinkTypes.getExcludeFlags());
|
||||
for (U32 i = 0; i < PolyAreas::NumAreas; i++)
|
||||
{
|
||||
mFilter.setAreaCost((PolyAreas)i, mAreaCosts[i]);
|
||||
}
|
||||
U32 navSize;
|
||||
stream->read(&navSize);
|
||||
mNavSize = (AINavigation::NavSize)(navSize);
|
||||
|
|
|
|||
|
|
@ -168,6 +168,8 @@ public:
|
|||
|
||||
/// Types of link we can use.
|
||||
LinkData mLinkTypes;
|
||||
dtQueryFilter mFilter;
|
||||
Vector<F32> mAreaCosts;
|
||||
AINavigation::NavSize mNavSize;
|
||||
#endif
|
||||
Delegate<void(AIController* obj, Point3F location, Move* movePtr)> resolveYawPtr;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ bool AIController::findCover(const Point3F& from, F32 radius)
|
|||
if (s.point)
|
||||
{
|
||||
// Calling setPathDestination clears cover...
|
||||
bool foundPath = getNav()->setPathDestination(s.point->getPosition());
|
||||
bool foundPath = getNav()->setPathDestination(s.point->getPosition(), true);
|
||||
setCover(s.point);
|
||||
s.point->setOccupied(true);
|
||||
return foundPath;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include "AIController.h"
|
||||
#include "T3D/shapeBase.h"
|
||||
|
||||
static U32 sAILoSMask = TerrainObjectType | StaticShapeObjectType | StaticObjectType | AIObjectType;
|
||||
static U32 sAILoSMask = TerrainObjectType | StaticShapeObjectType | StaticObjectType;
|
||||
|
||||
AINavigation::AINavigation(AIController* controller)
|
||||
{
|
||||
|
|
@ -77,6 +77,7 @@ bool AINavigation::setPathDestination(const Point3F& pos, bool replace)
|
|||
path->mAlwaysRender = true;
|
||||
path->mLinkTypes = getCtrl()->mControllerData->mLinkTypes;
|
||||
path->mXray = true;
|
||||
path->mFilter = getCtrl()->mControllerData->mFilter;
|
||||
// Paths plan automatically upon being registered.
|
||||
if (!path->registerObject())
|
||||
{
|
||||
|
|
@ -338,7 +339,11 @@ void AINavigation::repath()
|
|||
if (mPathData.path.isNull() || !mPathData.owned)
|
||||
return;
|
||||
|
||||
if (mRandI(0, 100) < getCtrl()->mControllerData->mFlocking.mChance && flock())
|
||||
if (avoidObstacles())
|
||||
{
|
||||
mPathData.path->mTo = mMoveDestination;
|
||||
}
|
||||
else if (mRandI(0, 100) < getCtrl()->mControllerData->mFlocking.mChance && flock())
|
||||
{
|
||||
mPathData.path->mTo = mMoveDestination;
|
||||
}
|
||||
|
|
@ -379,6 +384,60 @@ void AINavigation::clearPath()
|
|||
mPathData = PathData();
|
||||
}
|
||||
|
||||
bool AINavigation::avoidObstacles()
|
||||
{
|
||||
SimObjectPtr<SceneObject> obj = getCtrl()->getAIInfo()->mObj;
|
||||
obj->disableCollision();
|
||||
|
||||
Point3F pos = obj->getBoxCenter();
|
||||
VectorF forward = obj->getTransform().getForwardVector();
|
||||
forward.normalizeSafe();
|
||||
|
||||
// Generate forward-left and forward-right by rotating forward vector
|
||||
VectorF right = mCross(forward, Point3F(0, 0, 1));
|
||||
VectorF leftDir = forward + right * -0.5f; // front-left
|
||||
VectorF rightDir = forward + right * 0.5f; // front-right
|
||||
|
||||
leftDir.normalizeSafe();
|
||||
rightDir.normalizeSafe();
|
||||
|
||||
F32 rayLength = obj->getVelocity().lenSquared() * TickSec * 2 + getCtrl()->getAIInfo()->mRadius;
|
||||
Point3F directions[3] = {
|
||||
forward,
|
||||
leftDir,
|
||||
rightDir
|
||||
};
|
||||
|
||||
bool hit[3] = { false, false, false };
|
||||
RayInfo info;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
Point3F end = pos + directions[i] * rayLength;
|
||||
if (obj->getContainer()->castRay(pos, end, sAILoSMask, &info))
|
||||
{
|
||||
hit[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
Point3F avoidance = Point3F::Zero;
|
||||
if (hit[0]) avoidance += right * 1.0f;
|
||||
if (hit[1]) avoidance += right * 1.5f;
|
||||
if (hit[2]) avoidance -= right * 1.5f;
|
||||
|
||||
if (!avoidance.isZero())
|
||||
{
|
||||
avoidance.normalizeSafe();
|
||||
F32 clearance = getCtrl()->getAIInfo()->mRadius * 1.5f;
|
||||
Point3F newDest = info.point + avoidance * rayLength;
|
||||
mMoveDestination = newDest;
|
||||
obj->enableCollision();
|
||||
return true;
|
||||
}
|
||||
|
||||
obj->enableCollision();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AINavigation::flock()
|
||||
{
|
||||
AIControllerData::Flocking flockingData = getCtrl()->mControllerData->mFlocking;
|
||||
|
|
@ -386,9 +445,10 @@ bool AINavigation::flock()
|
|||
|
||||
obj->disableCollision();
|
||||
Point3F pos = obj->getBoxCenter();
|
||||
Point3F searchArea = Point3F(flockingData.mMin / 2, flockingData.mMax / 2, getCtrl()->getAIInfo()->mObj->getObjBox().maxExtents.z / 2);
|
||||
|
||||
F32 maxFlocksq = flockingData.mMax * flockingData.mMax;
|
||||
Point3F searchArea = Point3F(maxFlocksq, maxFlocksq, getCtrl()->getAIInfo()->mObj->getObjBox().maxExtents.z / 2);
|
||||
|
||||
bool flocking = false;
|
||||
U32 found = 0;
|
||||
if (getCtrl()->getGoal())
|
||||
|
|
@ -412,41 +472,35 @@ bool AINavigation::flock()
|
|||
sql.mList.remove(obj);
|
||||
|
||||
Point3F avoidanceOffset = Point3F::Zero;
|
||||
F32 avoidanceAmtSq = 0;
|
||||
|
||||
//avoid objects in the way
|
||||
RayInfo info;
|
||||
if (obj->getContainer()->castRay(pos, dest + Point3F(0, 0, obj->getObjBox().len_z() / 2), sAILoSMask, &info))
|
||||
{
|
||||
Point3F blockerOffset = (info.point - dest);
|
||||
blockerOffset.z = 0;
|
||||
avoidanceOffset += blockerOffset;
|
||||
}
|
||||
|
||||
//avoid bots that are too close
|
||||
for (U32 i = 0; i < sql.mList.size(); i++)
|
||||
{
|
||||
ShapeBase* other = dynamic_cast<ShapeBase*>(sql.mList[i]);
|
||||
Point3F objectCenter = other->getBoxCenter();
|
||||
|
||||
F32 sumRad = flockingData.mMin + other->getAIController()->mControllerData->mFlocking.mMin;
|
||||
F32 sumMinRad = flockingData.mMin + other->getAIController()->mControllerData->mFlocking.mMin;
|
||||
F32 separation = getCtrl()->getAIInfo()->mRadius + other->getAIController()->getAIInfo()->mRadius;
|
||||
sumRad += separation;
|
||||
separation += sumMinRad;
|
||||
|
||||
Point3F offset = (pos - objectCenter);
|
||||
F32 offsetLensq = offset.lenSquared(); //square roots are expensive, so use squared val compares
|
||||
if ((flockingData.mMin > 0) && (offsetLensq < (sumRad * sumRad)))
|
||||
if ((flockingData.mMin > 0) && (offsetLensq < (sumMinRad * sumMinRad)))
|
||||
{
|
||||
other->disableCollision();
|
||||
if (!obj->getContainer()->castRay(pos, other->getBoxCenter(), sAILoSMask, &info))
|
||||
if (!obj->getContainer()->castRay(pos, other->getBoxCenter(), sAILoSMask | AIObjectType, &info))
|
||||
{
|
||||
found++;
|
||||
offset.normalizeSafe();
|
||||
offset *= sumRad + separation;
|
||||
offset *= separation;
|
||||
avoidanceOffset += offset; //accumulate total group, move away from that
|
||||
avoidanceAmtSq += offsetLensq;
|
||||
}
|
||||
other->enableCollision();
|
||||
}
|
||||
}
|
||||
|
||||
//if we don't have to worry about bumping into one another (nothing found lower than minFLock), see about grouping up
|
||||
if (found == 0)
|
||||
{
|
||||
|
|
@ -455,20 +509,20 @@ bool AINavigation::flock()
|
|||
ShapeBase* other = static_cast<ShapeBase*>(sql.mList[i]);
|
||||
Point3F objectCenter = other->getBoxCenter();
|
||||
|
||||
F32 sumRad = flockingData.mMin + other->getAIController()->mControllerData->mFlocking.mMin;
|
||||
F32 sumMaxRad = flockingData.mMax + other->getAIController()->mControllerData->mFlocking.mMax;
|
||||
F32 separation = getCtrl()->getAIInfo()->mRadius + other->getAIController()->getAIInfo()->mRadius;
|
||||
sumRad += separation;
|
||||
separation += sumMaxRad;
|
||||
|
||||
Point3F offset = (pos - objectCenter);
|
||||
if ((flockingData.mMin > 0) && ((sumRad * sumRad) < (maxFlocksq)))
|
||||
F32 offsetLensq = offset.lenSquared(); //square roots are expensive, so use squared val compares
|
||||
if ((flockingData.mMax > 0) && (offsetLensq < (sumMaxRad * sumMaxRad)))
|
||||
{
|
||||
other->disableCollision();
|
||||
if (!obj->getContainer()->castRay(pos, other->getBoxCenter(), sAILoSMask, &info))
|
||||
if (!obj->getContainer()->castRay(pos, other->getBoxCenter(), sAILoSMask | AIObjectType, &info))
|
||||
{
|
||||
found++;
|
||||
offset.normalizeSafe();
|
||||
offset *= sumRad + separation;
|
||||
avoidanceOffset -= offset; // subtract total group, move toward it
|
||||
avoidanceAmtSq -= offsetLensq;
|
||||
}
|
||||
other->enableCollision();
|
||||
}
|
||||
|
|
@ -476,27 +530,36 @@ bool AINavigation::flock()
|
|||
}
|
||||
if (found > 0)
|
||||
{
|
||||
//ephasize the *side* portion of sidestep to better avoid clumps
|
||||
if (avoidanceOffset.x < avoidanceOffset.y)
|
||||
avoidanceOffset.x *= 2.0;
|
||||
else
|
||||
avoidanceOffset.y *= 2.0;
|
||||
|
||||
//add fuzz to sidestepping
|
||||
avoidanceOffset.z = 0;
|
||||
avoidanceOffset.x = (mRandF() * avoidanceOffset.x) * 0.5 + avoidanceOffset.x * 0.75;
|
||||
avoidanceOffset.y = (mRandF() * avoidanceOffset.y) * 0.5 + avoidanceOffset.y * 0.75;
|
||||
if (avoidanceOffset.lenSquared() < (maxFlocksq))
|
||||
|
||||
avoidanceOffset.normalizeSafe();
|
||||
avoidanceOffset *= avoidanceAmtSq;
|
||||
|
||||
if ((avoidanceAmtSq) > flockingData.mMin * flockingData.mMin)
|
||||
{
|
||||
dest += avoidanceOffset;
|
||||
dest = obj->getPosition()+avoidanceOffset;
|
||||
}
|
||||
|
||||
//if we're not jumping...
|
||||
if (mJump == None)
|
||||
{
|
||||
dest.z = obj->getPosition().z;
|
||||
|
||||
//make sure we don't run off a cliff
|
||||
Point3F zlen(0, 0, getCtrl()->mControllerData->mHeightTolerance);
|
||||
if (obj->getContainer()->castRay(dest + zlen, dest - zlen, TerrainObjectType | StaticShapeObjectType | StaticObjectType, &info))
|
||||
{
|
||||
if ((mMoveDestination - dest).len() > getCtrl()->mControllerData->mMoveTolerance)
|
||||
{
|
||||
mMoveDestination = dest;
|
||||
flocking = true;
|
||||
}
|
||||
mMoveDestination = dest;
|
||||
flocking = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ struct AINavigation
|
|||
|
||||
/// Move to the specified node in the current path.
|
||||
void moveToNode(S32 node);
|
||||
bool avoidObstacles();
|
||||
bool flock();
|
||||
#endif
|
||||
};
|
||||
|
|
|
|||
|
|
@ -114,6 +114,10 @@ AIPlayer::AIPlayer()
|
|||
mJump = None;
|
||||
mNavSize = Regular;
|
||||
mLinkTypes = LinkData(AllFlags);
|
||||
mFilter.setIncludeFlags(mLinkTypes.getFlags());
|
||||
mFilter.setExcludeFlags(0);
|
||||
mAreaCosts.setSize(PolyAreas::NumAreas);
|
||||
mAreaCosts.fill(1.0f);
|
||||
#endif
|
||||
|
||||
mIsAiControlled = true;
|
||||
|
|
@ -163,7 +167,8 @@ void AIPlayer::initPersistFields()
|
|||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
addGroup("Pathfinding");
|
||||
|
||||
addField("areaCosts", TypeF32Vector, Offset(mAreaCosts, AIPlayer),
|
||||
"Vector of costs for each PolyArea.");
|
||||
addField("allowWalk", TypeBool, Offset(mLinkTypes.walk, AIPlayer),
|
||||
"Allow the character to walk on dry land.");
|
||||
addField("allowJump", TypeBool, Offset(mLinkTypes.jump, AIPlayer),
|
||||
|
|
@ -785,6 +790,7 @@ void AIPlayer::moveToNode(S32 node)
|
|||
|
||||
bool AIPlayer::setPathDestination(const Point3F &pos)
|
||||
{
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
// Pathfinding only happens on the server.
|
||||
if(!isServerObject())
|
||||
return false;
|
||||
|
|
@ -799,6 +805,13 @@ bool AIPlayer::setPathDestination(const Point3F &pos)
|
|||
return false;
|
||||
}
|
||||
|
||||
mFilter.setIncludeFlags(mLinkTypes.getFlags());
|
||||
mFilter.setExcludeFlags(mLinkTypes.getExcludeFlags());
|
||||
for (U32 i = 0; i < PolyAreas::NumAreas; i++)
|
||||
{
|
||||
mFilter.setAreaCost((PolyAreas)i, mAreaCosts[i]);
|
||||
}
|
||||
|
||||
// Create a new path.
|
||||
NavPath *path = new NavPath();
|
||||
|
||||
|
|
@ -808,6 +821,7 @@ bool AIPlayer::setPathDestination(const Point3F &pos)
|
|||
path->mFromSet = path->mToSet = true;
|
||||
path->mAlwaysRender = true;
|
||||
path->mLinkTypes = mLinkTypes;
|
||||
path->mFilter = mFilter;
|
||||
path->mXray = true;
|
||||
// Paths plan automatically upon being registered.
|
||||
if(!path->registerObject())
|
||||
|
|
@ -839,6 +853,9 @@ bool AIPlayer::setPathDestination(const Point3F &pos)
|
|||
path->deleteObject();
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
setMoveDestination(pos, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
DefineEngineMethod(AIPlayer, setPathDestination, bool, (Point3F goal),,
|
||||
|
|
|
|||
|
|
@ -228,6 +228,8 @@ public:
|
|||
|
||||
/// Types of link we can use.
|
||||
LinkData mLinkTypes;
|
||||
dtQueryFilter mFilter;
|
||||
Vector<F32> mAreaCosts;
|
||||
|
||||
/// @}
|
||||
#endif // TORQUE_NAVIGATION_ENABLED
|
||||
|
|
|
|||
|
|
@ -808,6 +808,8 @@ GuiControl* GuiInspectorTypeImageAssetPtr::constructEditControl()
|
|||
if (Sim::findObject("ToolsGuiTextEditProfile", toolEditProfile))
|
||||
editTextCtrl->setControlProfile(toolEditProfile);
|
||||
|
||||
editTextCtrl->setPlaceholderText("(None)");
|
||||
|
||||
GuiControlProfile* toolDefaultProfile = nullptr;
|
||||
Sim::findObject("ToolsGuiDefaultProfile", toolDefaultProfile);
|
||||
|
||||
|
|
@ -836,21 +838,25 @@ GuiControl* GuiInspectorTypeImageAssetPtr::constructEditControl()
|
|||
|
||||
//
|
||||
// Create "Open in Editor" button
|
||||
/*mEditButton = new GuiBitmapButtonCtrl();
|
||||
mEditButton = new GuiBitmapButtonCtrl();
|
||||
|
||||
if (mInspector->getInspectObject() != nullptr)
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "%d.apply(\"\");", getId());
|
||||
else
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "%s = \"\";", mVariableName);
|
||||
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.editAsset(%d.getText());", retCtrl->getId());
|
||||
mEditButton->setField("Command", szBuffer);
|
||||
|
||||
mEditButton->setText("Edit");
|
||||
mEditButton->setSizing(horizResizeLeft, vertResizeAspectTop);
|
||||
mEditButton->setBitmap(StringTable->insert("ToolsModule:delete_n_image"));
|
||||
mEditButton->setSizing(horizResizeRight, vertResizeAspectBottom);
|
||||
|
||||
mEditButton->setDataField(StringTable->insert("Profile"), NULL, "ToolsGuiButtonProfile");
|
||||
mEditButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
|
||||
mEditButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
|
||||
mEditButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this asset in the Image Editor");
|
||||
mEditButton->setDataField(StringTable->insert("tooltip"), NULL, "Clear this ImageAsset");
|
||||
|
||||
mEditButton->registerObject();
|
||||
addObject(mEditButton);*/
|
||||
addObject(mEditButton);
|
||||
|
||||
//
|
||||
mUseHeightOverride = true;
|
||||
|
|
@ -875,9 +881,9 @@ bool GuiInspectorTypeImageAssetPtr::updateRects()
|
|||
mPreviewImage->resize(previewRect.point, previewRect.extent);
|
||||
|
||||
S32 editPos = previewRect.point.x + previewRect.extent.x + 10;
|
||||
mEdit->resize(Point2I(editPos, rowSize * 1.5), Point2I(fieldExtent.x - editPos - 5, rowSize));
|
||||
mEdit->resize(Point2I(editPos, rowSize * 1.5), Point2I(fieldExtent.x - editPos - 5 - rowSize, rowSize));
|
||||
|
||||
//mEditButton->resize(Point2I(fieldExtent.x - 105, previewRect.point.y + previewRect.extent.y - rowSize), Point2I(100, rowSize));
|
||||
mEditButton->resize(Point2I(mEdit->getPosition().x + mEdit->getExtent().x, mEdit->getPosition().y), Point2I(rowSize, rowSize));
|
||||
|
||||
mBrowseButton->setHidden(true);
|
||||
|
||||
|
|
@ -975,7 +981,7 @@ void GuiInspectorTypeImageAssetPtr::updatePreviewImage()
|
|||
//if what we're working with isn't even a valid asset, don't present like we found a good one
|
||||
if (!AssetDatabase.isDeclaredAsset(previewImage))
|
||||
{
|
||||
mPreviewImage->_setBitmap(StringTable->EmptyString());
|
||||
mPreviewImage->_setBitmap(StringTable->insert("ToolsModule:unknownImage_image"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1003,7 +1009,7 @@ void GuiInspectorTypeImageAssetPtr::setPreviewImage(StringTableEntry assetId)
|
|||
//if what we're working with isn't even a valid asset, don't present like we found a good one
|
||||
if (!AssetDatabase.isDeclaredAsset(assetId))
|
||||
{
|
||||
mPreviewImage->_setBitmap(StringTable->EmptyString());
|
||||
mPreviewImage->_setBitmap(StringTable->insert("ToolsModule:unknownImage_image"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1025,4 +1031,20 @@ void GuiInspectorTypeImageAssetPtr::setPreviewImage(StringTableEntry assetId)
|
|||
if (mPreviewImage->getBitmapAsset().isNull())
|
||||
mPreviewImage->_setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
|
||||
}
|
||||
|
||||
void GuiInspectorTypeImageAssetPtr::setCaption(StringTableEntry caption)
|
||||
{
|
||||
mCaption = caption;
|
||||
mLabel->setText(mCaption);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiInspectorTypeImageAssetPtr, setCaption, void, (String newCaption), , "() - Sets the caption of the field.")
|
||||
{
|
||||
object->setCaption(StringTable->insert(newCaption.c_str()));
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiInspectorTypeImageAssetPtr, setIsDeleteBtnVisible, void, (bool isVisible), (false), "() - Sets if the delete/clear button is visible for the field")
|
||||
{
|
||||
object->setIsDeleteBtnVisible(isVisible);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@ public:
|
|||
GuiTextCtrl* mLabel = NULL;
|
||||
GuiBitmapButtonCtrl* mPreviewBorderButton = NULL;
|
||||
GuiBitmapCtrl* mPreviewImage = NULL;
|
||||
GuiButtonCtrl* mEditButton = NULL;
|
||||
GuiBitmapButtonCtrl* mEditButton = NULL;
|
||||
|
||||
bool mIsDeleteButtonVisible;
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeImageAssetPtr);
|
||||
static void consoleInit();
|
||||
|
|
@ -29,6 +31,16 @@ public:
|
|||
|
||||
void updatePreviewImage();
|
||||
void setPreviewImage(StringTableEntry assetId);
|
||||
|
||||
/// Sets this control's caption text, usually set within setInspectorField,
|
||||
/// this is exposed in case someone wants to override the normal caption.
|
||||
void setCaption(StringTableEntry caption) override;
|
||||
|
||||
void setIsDeleteBtnVisible(const bool& isVisible)
|
||||
{
|
||||
if (mEditButton)
|
||||
mEditButton->setVisible(isVisible);
|
||||
}
|
||||
};
|
||||
|
||||
class GuiInspectorTypeImageAssetId : public GuiInspectorTypeImageAssetPtr
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@
|
|||
// GuiMaterialPreview
|
||||
GuiMaterialPreview::GuiMaterialPreview()
|
||||
: mMouseState(None),
|
||||
mModel(NULL),
|
||||
mModelInstance(NULL),
|
||||
mMountedModelInstance(NULL),
|
||||
runThread(0),
|
||||
lastRenderTime(0),
|
||||
mLastMousePoint(0, 0),
|
||||
|
|
@ -64,13 +65,13 @@ GuiMaterialPreview::GuiMaterialPreview()
|
|||
// By default don't do dynamic reflection
|
||||
// updates for this viewport.
|
||||
mReflectPriority = 0.0f;
|
||||
mMountedModel = NULL;
|
||||
|
||||
mSkinTag = 0;
|
||||
}
|
||||
|
||||
GuiMaterialPreview::~GuiMaterialPreview()
|
||||
{
|
||||
SAFE_DELETE(mModel);
|
||||
SAFE_DELETE(mModelInstance);
|
||||
SAFE_DELETE(mFakeSun);
|
||||
}
|
||||
|
||||
|
|
@ -258,30 +259,34 @@ void GuiMaterialPreview::onMiddleMouseDragged(const GuiEvent &event)
|
|||
}
|
||||
|
||||
// This is used to set the model we want to view in the control object.
|
||||
void GuiMaterialPreview::setObjectModel(const char* modelName)
|
||||
void GuiMaterialPreview::setObjectModel(StringTableEntry modelName)
|
||||
{
|
||||
deleteModel();
|
||||
|
||||
Resource<TSShape> model = ResourceManager::get().load(modelName);
|
||||
if (! bool(model))
|
||||
_setModel(modelName);
|
||||
|
||||
if (!getModel())
|
||||
{
|
||||
Con::warnf(avar("GuiMaterialPreview: Failed to load model %s. Please check your model name and load a valid model.", modelName));
|
||||
Con::warnf("GuiMaterialPreview::setObjectModel - Failed to load model '%s'", modelName);
|
||||
return;
|
||||
}
|
||||
|
||||
mModel = new TSShapeInstance(model, true);
|
||||
AssertFatal(mModel, avar("GuiMaterialPreview: Failed to load model %s. Please check your model name and load a valid model.", modelName));
|
||||
mModelInstance = new TSShapeInstance(getModel(), true);
|
||||
mModelInstance->resetMaterialList();
|
||||
mModelInstance->cloneMaterialList();
|
||||
|
||||
AssertFatal(mModelInstance, avar("GuiMaterialPreview: Failed to load model %s. Please check your model name and load a valid model.", modelName));
|
||||
|
||||
// Initialize camera values:
|
||||
mOrbitPos = mModel->getShape()->center;
|
||||
mMinOrbitDist = mModel->getShape()->mRadius;
|
||||
mOrbitPos = mModelInstance->getShape()->center;
|
||||
mMinOrbitDist = mModelInstance->getShape()->mRadius;
|
||||
|
||||
lastRenderTime = Platform::getVirtualMilliseconds();
|
||||
}
|
||||
|
||||
void GuiMaterialPreview::deleteModel()
|
||||
{
|
||||
SAFE_DELETE(mModel);
|
||||
SAFE_DELETE(mModelInstance);
|
||||
runThread = 0;
|
||||
}
|
||||
|
||||
|
|
@ -358,7 +363,7 @@ void GuiMaterialPreview::onMouseLeave(const GuiEvent & event)
|
|||
void GuiMaterialPreview::renderWorld(const RectI &updateRect)
|
||||
{
|
||||
// nothing to render, punt
|
||||
if ( !mModel && !mMountedModel )
|
||||
if ( !mModelInstance && !mMountedModelInstance )
|
||||
return;
|
||||
|
||||
S32 time = Platform::getVirtualMilliseconds();
|
||||
|
|
@ -408,10 +413,10 @@ void GuiMaterialPreview::renderWorld(const RectI &updateRect)
|
|||
LIGHTMGR->unregisterAllLights();
|
||||
LIGHTMGR->setSpecialLight( LightManager::slSunLightType, mFakeSun );
|
||||
|
||||
if ( mModel )
|
||||
mModel->render( rdata );
|
||||
if ( mModelInstance )
|
||||
mModelInstance->render( rdata );
|
||||
|
||||
if ( mMountedModel )
|
||||
if ( mMountedModelInstance )
|
||||
{
|
||||
// render a weapon
|
||||
/*
|
||||
|
|
@ -441,7 +446,7 @@ void GuiMaterialPreview::renderSunDirection() const
|
|||
{
|
||||
// Render four arrows aiming in the direction of the sun's light
|
||||
ColorI color = LinearColorF(mFakeSun->getColor()).toColorI();
|
||||
F32 length = mModel->getShape()->mBounds.len() * 0.8f;
|
||||
F32 length = mModelInstance->getShape()->mBounds.len() * 0.8f;
|
||||
|
||||
// Get the sun's vectors
|
||||
Point3F fwd = mFakeSun->getTransform().getForwardVector();
|
||||
|
|
@ -449,8 +454,8 @@ void GuiMaterialPreview::renderSunDirection() const
|
|||
Point3F right = mFakeSun->getTransform().getRightVector() * length / 8;
|
||||
|
||||
// Calculate the start and end points of the first arrow (bottom left)
|
||||
Point3F start = mModel->getShape()->center - fwd * length - up / 2 - right / 2;
|
||||
Point3F end = mModel->getShape()->center - fwd * length / 3 - up / 2 - right / 2;
|
||||
Point3F start = mModelInstance->getShape()->center - fwd * length - up / 2 - right / 2;
|
||||
Point3F end = mModelInstance->getShape()->center - fwd * length / 3 - up / 2 - right / 2;
|
||||
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setZReadWrite(true, true);
|
||||
|
|
@ -476,7 +481,7 @@ void GuiMaterialPreview::resetViewport()
|
|||
mCameraRot.set( mDegToRad(30.0f), 0, mDegToRad(-30.0f) );
|
||||
mCameraPos.set(0.0f, 1.75f, 1.25f);
|
||||
mOrbitDist = 5.0f;
|
||||
mOrbitPos = mModel->getShape()->center;
|
||||
mOrbitPos = mModelInstance->getShape()->center;
|
||||
|
||||
// Reset the viewport's lighting.
|
||||
GuiMaterialPreview::mFakeSun->setColor( LinearColorF( 1.0f, 1.0f, 1.0f ) );
|
||||
|
|
@ -498,7 +503,7 @@ DefineEngineMethod(GuiMaterialPreview, setModel, void, ( const char* shapeName )
|
|||
"Sets the model to be displayed in this control\n\n"
|
||||
"@param shapeName Name of the model to display.\n")
|
||||
{
|
||||
object->setObjectModel(shapeName);
|
||||
object->setObjectModel(StringTable->insert(shapeName));
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiMaterialPreview, deleteModel, void, (),,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#ifndef _GUIMATERIALPREVIEW_H_
|
||||
#define _GUIMATERIALPREVIEW_H_
|
||||
|
||||
#include "assets/ShapeAsset.h"
|
||||
|
||||
#include "gui/3d/guiTSControl.h"
|
||||
#include "ts/tsShapeInstance.h"
|
||||
|
||||
|
|
@ -50,8 +52,11 @@ protected:
|
|||
|
||||
MouseState mMouseState;
|
||||
|
||||
TSShapeInstance* mModel;
|
||||
TSShapeInstance* mMountedModel;
|
||||
DECLARE_SHAPEASSET_REFACTOR(GuiMaterialPreview, Model)
|
||||
DECLARE_SHAPEASSET_REFACTOR(GuiMaterialPreview, MountedModel)
|
||||
|
||||
TSShapeInstance* mModelInstance;
|
||||
TSShapeInstance* mMountedModelInstance;
|
||||
U32 mSkinTag;
|
||||
|
||||
// For Camera Panning.
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ void TurretShapeData::initPersistFields()
|
|||
"@brief Should the turret allow only z rotations.\n\n"
|
||||
"True indicates that the turret may only be rotated on its z axis, just like the Item class. "
|
||||
"This keeps the turret always upright regardless of the surface it lands on.\n");
|
||||
addFieldV("maxHeading", TypeRangedF32, Offset(maxHeading, TurretShapeData), &CommonValidators::PosDegreeRangeQuarter,
|
||||
addFieldV("maxHeading", TypeRangedF32, Offset(maxHeading, TurretShapeData), &CommonValidators::PosDegreeRangeHalf,
|
||||
"@brief Maximum number of degrees to rotate from center.\n\n"
|
||||
"A value of 180 or more degrees indicates the turret may rotate completely around.\n");
|
||||
addFieldV("minPitch", TypeRangedF32, Offset(minPitch, TurretShapeData), &CommonValidators::PosDegreeRangeQuarter,
|
||||
|
|
@ -1047,8 +1047,8 @@ void TurretShape::writePacketData(GameConnection *connection, BitStream *stream)
|
|||
// Update client regardless of status flags.
|
||||
Parent::writePacketData(connection, stream);
|
||||
|
||||
stream->writeSignedFloat(mRot.x / M_2PI_F, 7);
|
||||
stream->writeSignedFloat(mRot.z / M_2PI_F, 7);
|
||||
stream->writeSignedFloat(mRot.x / M_2PI_F, 11);
|
||||
stream->writeSignedFloat(mRot.z / M_2PI_F, 11);
|
||||
}
|
||||
|
||||
void TurretShape::readPacketData(GameConnection *connection, BitStream *stream)
|
||||
|
|
@ -1056,8 +1056,8 @@ void TurretShape::readPacketData(GameConnection *connection, BitStream *stream)
|
|||
Parent::readPacketData(connection, stream);
|
||||
|
||||
Point3F rot(0.0f, 0.0f, 0.0f);
|
||||
rot.x = stream->readSignedFloat(7) * M_2PI_F;
|
||||
rot.z = stream->readSignedFloat(7) * M_2PI_F;
|
||||
rot.x = stream->readSignedFloat(11) * M_2PI_F;
|
||||
rot.z = stream->readSignedFloat(11) * M_2PI_F;
|
||||
_setRotation(rot);
|
||||
|
||||
mTurretDelta.rot = rot;
|
||||
|
|
|
|||
|
|
@ -531,12 +531,9 @@ void WaterBlock::initPersistFields()
|
|||
docsURL;
|
||||
addGroup( "WaterBlock" );
|
||||
|
||||
addProtectedFieldV("gridSize", TypeRangedS32, Offset(mGridElementSize, WaterBlock), &setGridSizeProperty, &defaultProtectedGetFn, &CommonValidators::NaturalNumber,
|
||||
addProtectedFieldV("gridSize", TypeRangedF32, Offset(mGridElementSize, WaterBlock), &setGridSizeProperty, &defaultProtectedGetFn, &CommonValidators::PositiveFloat,
|
||||
"Spacing between vertices in the WaterBlock mesh");
|
||||
|
||||
addProtectedFieldV("gridElementSize", TypeRangedS32, Offset(mGridElementSize, WaterBlock), &setGridSizeProperty, &defaultProtectedGetFn, &CommonValidators::NaturalNumber,
|
||||
"Duplicate of gridElementSize for backwards compatility");
|
||||
|
||||
addProtectedFieldV("gridElementSize", TypeRangedF32, Offset(mGridElementSize, WaterBlock), &setGridSizeProperty, &defaultProtectedGetFn, &CommonValidators::PositiveFloat, "Duplicate of gridElementSize for backwards compatility");
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ private:
|
|||
GFXPrimitiveBufferHandle mRadialPrimBuff;
|
||||
|
||||
// misc
|
||||
U32 mGridElementSize;
|
||||
F32 mGridElementSize;
|
||||
U32 mWidth;
|
||||
U32 mHeight;
|
||||
F32 mElapsedTime;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "T3D/sfx/sfx3DWorld.h"
|
||||
#include "sfx/sfxTypes.h"
|
||||
#include "console/typeValidators.h"
|
||||
#include "gfx/gfxTransformSaver.h"
|
||||
|
||||
GFXImplementVertexFormat( GFXWaterVertex )
|
||||
{
|
||||
|
|
@ -699,6 +700,8 @@ void WaterObject::prepRenderImage( SceneRenderState *state )
|
|||
if( !state->isDiffusePass() )
|
||||
return;
|
||||
|
||||
GFXTransformSaver saver;
|
||||
|
||||
// Setup scene transforms
|
||||
mMatrixSet->setSceneView(GFX->getWorldMatrix());
|
||||
mMatrixSet->setSceneProjection(GFX->getProjectionMatrix());
|
||||
|
|
|
|||
|
|
@ -124,9 +124,7 @@ void WaterPlane::initPersistFields()
|
|||
|
||||
addProtectedFieldV( "gridSize", TypeRangedS32, Offset( mGridSize, WaterPlane ), &protectedSetGridSize, &defaultProtectedGetFn, &CommonValidators::NaturalNumber,
|
||||
"Spacing between vertices in the WaterBlock mesh" );
|
||||
|
||||
addProtectedFieldV( "gridElementSize", TypeRangedS32, Offset( mGridElementSize, WaterPlane ), &protectedSetGridElementSize, &defaultProtectedGetFn, &CommonValidators::NaturalNumber,
|
||||
"Duplicate of gridElementSize for backwards compatility");
|
||||
addProtectedFieldV("gridElementSize", TypeRangedF32, Offset(mGridElementSize, WaterPlane), &protectedSetGridElementSize, &defaultProtectedGetFn, &CommonValidators::PositiveFloat, "Duplicate of gridElementSize for backwards compatility");
|
||||
|
||||
endGroup( "WaterPlane" );
|
||||
|
||||
|
|
@ -699,6 +697,8 @@ void WaterPlane::prepRenderImage( SceneRenderState *state )
|
|||
if( !state->isDiffusePass() )
|
||||
return;
|
||||
|
||||
GFXTransformSaver saver;
|
||||
|
||||
mBasicLighting = dStricmp( LIGHTMGR->getId(), "BLM" ) == 0;
|
||||
mUnderwater = isUnderwater( state->getCameraPosition() );
|
||||
|
||||
|
|
|
|||
|
|
@ -1486,69 +1486,73 @@ void GFXDrawUtil::_drawWireCapsule( const GFXStateBlockDesc &desc, const Point3F
|
|||
|
||||
void GFXDrawUtil::drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color )
|
||||
{
|
||||
VectorF uvec = tipPnt - basePnt;
|
||||
F32 height = uvec.len();
|
||||
uvec.normalize();
|
||||
MatrixF mat( true );
|
||||
MathUtils::getMatrixFromUpVector( uvec, &mat );
|
||||
mat.setPosition(basePnt);
|
||||
VectorF dir = tipPnt - basePnt;
|
||||
F32 height = dir.len();
|
||||
dir.normalize();
|
||||
|
||||
Point3F scale( baseRadius, baseRadius, height );
|
||||
mat.scale(scale);
|
||||
MatrixF mat(true);
|
||||
MathUtils::getMatrixFromUpVector(dir, &mat);
|
||||
mat.setPosition(basePnt);
|
||||
mat.scale(Point3F(baseRadius, baseRadius, height));
|
||||
|
||||
GFXTransformSaver saver;
|
||||
|
||||
mDevice->pushWorldMatrix();
|
||||
mDevice->multWorld(mat);
|
||||
|
||||
S32 numPoints = sizeof(circlePoints)/sizeof(Point2F);
|
||||
GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, numPoints * 3 + 2, GFXBufferTypeVolatile);
|
||||
const S32 numPoints = sizeof(circlePoints) / sizeof(Point2F);
|
||||
|
||||
// Vertex index layout
|
||||
const S32 baseCenterIdx = 0;
|
||||
const S32 baseStartIdx = 1;
|
||||
const S32 tipIdx = baseStartIdx + numPoints;
|
||||
const S32 sideStartIdx = tipIdx + 1;
|
||||
|
||||
const S32 totalVerts = sideStartIdx + numPoints * 3;
|
||||
|
||||
GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, totalVerts, GFXBufferTypeVolatile);
|
||||
verts.lock();
|
||||
F32 sign = -1.f;
|
||||
S32 indexDown = 0; //counting down from numPoints
|
||||
S32 indexUp = 0; //counting up from 0
|
||||
S32 index = 0; //circlePoints index for cap
|
||||
|
||||
for (S32 i = 0; i < numPoints + 1; i++)
|
||||
// Base center vertex (at origin in local space)
|
||||
verts[baseCenterIdx].point = Point3F(0, 0, 0);
|
||||
verts[baseCenterIdx].color = color;
|
||||
|
||||
// Base circle vertices
|
||||
for (S32 i = 0; i < numPoints; i++)
|
||||
{
|
||||
//Top cap
|
||||
if (i != numPoints)
|
||||
{
|
||||
if (sign < 0)
|
||||
index = indexDown;
|
||||
else
|
||||
index = indexUp;
|
||||
verts[baseStartIdx + i].point = Point3F(circlePoints[i].x, circlePoints[i].y, 0);
|
||||
verts[baseStartIdx + i].color = color;
|
||||
}
|
||||
|
||||
verts[i].point = Point3F(circlePoints[index].x, circlePoints[index].y, 0);
|
||||
verts[i].color = color;
|
||||
// Tip vertex (pointing "up" in local Z)
|
||||
verts[tipIdx].point = Point3F(0, 0, 1);
|
||||
verts[tipIdx].color = color;
|
||||
|
||||
if (sign < 0)
|
||||
indexUp += 1;
|
||||
else
|
||||
indexDown = numPoints - indexUp;
|
||||
// Side triangles: one triangle per segment
|
||||
for (S32 i = 0; i < numPoints; i++)
|
||||
{
|
||||
S32 triBase = sideStartIdx + i * 3;
|
||||
|
||||
// invert sign
|
||||
sign *= -1.0f;
|
||||
}
|
||||
// Each triangle is (tip, base[i], base[(i+1)%numPoints])
|
||||
verts[triBase + 0].point = verts[tipIdx].point;
|
||||
verts[triBase + 1].point = verts[baseStartIdx + i].point;
|
||||
verts[triBase + 2].point = verts[baseStartIdx + ((i + 1) % numPoints)].point;
|
||||
|
||||
//cone
|
||||
S32 imod = i % numPoints;
|
||||
S32 vertindex = 2 * i + numPoints;
|
||||
verts[vertindex].point = Point3F(circlePoints[imod].x, circlePoints[imod].y, 0);
|
||||
verts[vertindex].color = color;
|
||||
verts[vertindex + 1].point = Point3F(0.0f, 0.0f, 1.0f);
|
||||
verts[vertindex + 1].color = color;
|
||||
verts[triBase + 0].color = color;
|
||||
verts[triBase + 1].color = color;
|
||||
verts[triBase + 2].color = color;
|
||||
}
|
||||
|
||||
verts.unlock();
|
||||
|
||||
mDevice->setStateBlockByDesc( desc );
|
||||
|
||||
mDevice->setVertexBuffer( verts );
|
||||
mDevice->setStateBlockByDesc(desc);
|
||||
mDevice->setVertexBuffer(verts);
|
||||
mDevice->setupGenericShaders();
|
||||
|
||||
mDevice->drawPrimitive(GFXTriangleStrip, 0, numPoints - 2);
|
||||
mDevice->drawPrimitive(GFXTriangleStrip, numPoints, numPoints * 2);
|
||||
// Draw base cap using triangle fan
|
||||
mDevice->drawPrimitive(GFXTriangleList, baseCenterIdx, numPoints - 2);
|
||||
|
||||
// Draw sides using triangle list
|
||||
mDevice->drawPrimitive(GFXTriangleList, sideStartIdx, numPoints);
|
||||
|
||||
mDevice->popWorldMatrix();
|
||||
|
||||
|
|
@ -1556,71 +1560,89 @@ void GFXDrawUtil::drawCone( const GFXStateBlockDesc &desc, const Point3F &basePn
|
|||
|
||||
void GFXDrawUtil::drawCylinder( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 radius, const ColorI &color )
|
||||
{
|
||||
VectorF uvec = tipPnt - basePnt;
|
||||
F32 height = uvec.len();
|
||||
uvec.normalize();
|
||||
MatrixF mat( true );
|
||||
MathUtils::getMatrixFromUpVector( uvec, &mat );
|
||||
VectorF dir = tipPnt - basePnt;
|
||||
F32 height = dir.len();
|
||||
dir.normalize();
|
||||
|
||||
MatrixF mat(true);
|
||||
MathUtils::getMatrixFromUpVector(dir, &mat);
|
||||
mat.setPosition(basePnt);
|
||||
mat.scale(Point3F(radius, radius, height));
|
||||
|
||||
Point3F scale( radius, radius, height * 2 );
|
||||
mat.scale(scale);
|
||||
GFXTransformSaver saver;
|
||||
|
||||
mDevice->pushWorldMatrix();
|
||||
mDevice->multWorld(mat);
|
||||
|
||||
S32 numPoints = sizeof(circlePoints) / sizeof(Point2F);
|
||||
GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, numPoints *4 + 2, GFXBufferTypeVolatile);
|
||||
const S32 numPoints = sizeof(circlePoints) / sizeof(Point2F);
|
||||
|
||||
// Vertex index layout
|
||||
const S32 baseCenterIdx = 0;
|
||||
const S32 topCenterIdx = 1;
|
||||
const S32 baseStartIdx = 2;
|
||||
const S32 topStartIdx = baseStartIdx + numPoints;
|
||||
const S32 sideStartIdx = topStartIdx + numPoints;
|
||||
|
||||
const S32 totalVerts = sideStartIdx + numPoints * 6;
|
||||
|
||||
GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, totalVerts, GFXBufferTypeVolatile);
|
||||
verts.lock();
|
||||
F32 sign = -1.f;
|
||||
S32 indexDown = 0; //counting down from numPoints
|
||||
S32 indexUp = 0; //counting up from 0
|
||||
S32 index = 0; //circlePoints index for caps
|
||||
|
||||
for (S32 i = 0; i < numPoints + 1; i++)
|
||||
// Base center
|
||||
verts[baseCenterIdx].point = Point3F(0, 0, 0);
|
||||
verts[baseCenterIdx].color = color;
|
||||
|
||||
// Top center
|
||||
verts[topCenterIdx].point = Point3F(0, 0, 1);
|
||||
verts[topCenterIdx].color = color;
|
||||
|
||||
// Base circle
|
||||
for (S32 i = 0; i < numPoints; ++i)
|
||||
{
|
||||
//Top/Bottom cap
|
||||
if (i != numPoints)
|
||||
{
|
||||
if (sign < 0)
|
||||
index = indexDown;
|
||||
else
|
||||
index = indexUp;
|
||||
verts[baseStartIdx + i].point = Point3F(circlePoints[i].x, circlePoints[i].y, 0);
|
||||
verts[baseStartIdx + i].color = color;
|
||||
}
|
||||
|
||||
verts[i].point = Point3F(circlePoints[index].x, circlePoints[index].y, 0);
|
||||
verts[i].color = color;
|
||||
verts[i + numPoints].point = Point3F(circlePoints[index].x, circlePoints[index].y, 0.5f);
|
||||
verts[i + numPoints].color = color;
|
||||
// Top circle
|
||||
for (S32 i = 0; i < numPoints; ++i)
|
||||
{
|
||||
verts[topStartIdx + i].point = Point3F(circlePoints[i].x, circlePoints[i].y, 1.0f);
|
||||
verts[topStartIdx + i].color = color;
|
||||
}
|
||||
|
||||
if (sign < 0)
|
||||
indexUp += 1;
|
||||
else
|
||||
indexDown = numPoints - indexUp;
|
||||
// Side triangles
|
||||
for (S32 i = 0; i < numPoints; ++i)
|
||||
{
|
||||
S32 next = (i + 1) % numPoints;
|
||||
S32 idx = sideStartIdx + i * 6;
|
||||
|
||||
// invert sign
|
||||
sign *= -1.0f;
|
||||
}
|
||||
// First triangle (base[i], base[next], top[i])
|
||||
verts[idx + 0].point = verts[baseStartIdx + i].point;
|
||||
verts[idx + 1].point = verts[baseStartIdx + next].point;
|
||||
verts[idx + 2].point = verts[topStartIdx + i].point;
|
||||
|
||||
//cylinder
|
||||
S32 imod = i % numPoints;
|
||||
S32 vertindex = 2 * i + (numPoints * 2);
|
||||
verts[vertindex].point = Point3F(circlePoints[imod].x, circlePoints[imod].y, 0);
|
||||
verts[vertindex].color = color;
|
||||
verts[vertindex + 1].point = Point3F(circlePoints[imod].x, circlePoints[imod].y, 0.5f);
|
||||
verts[vertindex + 1].color = color;
|
||||
// Second triangle (top[i], base[next], top[next])
|
||||
verts[idx + 3].point = verts[topStartIdx + i].point;
|
||||
verts[idx + 4].point = verts[baseStartIdx + next].point;
|
||||
verts[idx + 5].point = verts[topStartIdx + next].point;
|
||||
|
||||
for (int j = 0; j < 6; ++j)
|
||||
verts[idx + j].color = color;
|
||||
}
|
||||
|
||||
verts.unlock();
|
||||
|
||||
mDevice->setStateBlockByDesc( desc );
|
||||
|
||||
mDevice->setVertexBuffer( verts );
|
||||
mDevice->setStateBlockByDesc(desc);
|
||||
mDevice->setVertexBuffer(verts);
|
||||
mDevice->setupGenericShaders();
|
||||
|
||||
mDevice->drawPrimitive( GFXTriangleStrip, 0, numPoints-2 );
|
||||
mDevice->drawPrimitive( GFXTriangleStrip, numPoints, numPoints - 2);
|
||||
mDevice->drawPrimitive( GFXTriangleStrip, numPoints*2, numPoints * 2);
|
||||
// Draw base cap
|
||||
mDevice->drawPrimitive(GFXTriangleList, baseCenterIdx, numPoints - 2);
|
||||
|
||||
// Draw top cap
|
||||
mDevice->drawPrimitive(GFXTriangleList, topCenterIdx, numPoints - 2);
|
||||
|
||||
// Draw sides (2 triangles per segment)
|
||||
mDevice->drawPrimitive(GFXTriangleList, sideStartIdx, numPoints * 2);
|
||||
|
||||
mDevice->popWorldMatrix();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,39 +178,59 @@ public:
|
|||
U32 mSize = 0;
|
||||
}_getBufferData;
|
||||
|
||||
void lock(const U32 size, U32 offsetAlign, U32 &outOffset, void* &outPtr)
|
||||
void lock(const U32 size, U32 offsetAlign, U32& outOffset, void*& outPtr)
|
||||
{
|
||||
if( !size )
|
||||
if (!size)
|
||||
{
|
||||
AssertFatal(0, "");
|
||||
AssertFatal(0, "GLCircularVolatileBuffer::lock - size must be > 0");
|
||||
outOffset = 0;
|
||||
outPtr = NULL;
|
||||
outPtr = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
mLockManager.waitFirstRange( mBufferFreePos, (mBufferFreePos + size)-1 );
|
||||
// Align free pos first (before wraparound check)
|
||||
if (offsetAlign)
|
||||
{
|
||||
mBufferFreePos = ((mBufferFreePos + offsetAlign - 1) / offsetAlign) * offsetAlign;
|
||||
}
|
||||
|
||||
if( mBufferFreePos + size > mBufferSize )
|
||||
{
|
||||
mUsedRanges.push_back( UsedRange( mBufferFreePos, mBufferSize-1 ) );
|
||||
// If the size won't fit from current pos to end, wrap around
|
||||
if (mBufferFreePos + size > mBufferSize)
|
||||
{
|
||||
// Protect the remaining space
|
||||
if (mBufferFreePos < mBufferSize)
|
||||
mUsedRanges.push_back(UsedRange(mBufferFreePos, mBufferSize - 1));
|
||||
|
||||
// Reset free pos
|
||||
mBufferFreePos = 0;
|
||||
}
|
||||
|
||||
// force offset buffer align
|
||||
if( offsetAlign )
|
||||
mBufferFreePos = ( (mBufferFreePos/offsetAlign) + 1 ) * offsetAlign;
|
||||
// Realign after wrap
|
||||
if (offsetAlign)
|
||||
{
|
||||
mBufferFreePos = ((mBufferFreePos + offsetAlign - 1) / offsetAlign) * offsetAlign;
|
||||
}
|
||||
|
||||
// Now check for overlaps *after* wrapping
|
||||
mLockManager.waitOverlapRanges(mBufferFreePos, mBufferFreePos + size - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal range wait
|
||||
mLockManager.waitOverlapRanges(mBufferFreePos, mBufferFreePos + size - 1);
|
||||
}
|
||||
|
||||
outOffset = mBufferFreePos;
|
||||
|
||||
if( GFXGL->mCapabilities.bufferStorage )
|
||||
{
|
||||
outPtr = (U8*)(mBufferPtr) + mBufferFreePos;
|
||||
}
|
||||
else if( GFXGL->glUseMap() )
|
||||
if (GFXGL->mCapabilities.bufferStorage)
|
||||
{
|
||||
PRESERVE_BUFFER( mBinding );
|
||||
outPtr = static_cast<U8*>(mBufferPtr) + mBufferFreePos;
|
||||
}
|
||||
else if (GFXGL->glUseMap())
|
||||
{
|
||||
PRESERVE_BUFFER(mBinding);
|
||||
glBindBuffer(mBinding, mBufferName);
|
||||
|
||||
const GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
|
||||
const GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
|
||||
outPtr = glMapBufferRange(mBinding, outOffset, size, access);
|
||||
}
|
||||
else
|
||||
|
|
@ -218,14 +238,13 @@ public:
|
|||
_getBufferData.mOffset = outOffset;
|
||||
_getBufferData.mSize = size;
|
||||
|
||||
outPtr = mFrameAllocator.lock( size );
|
||||
}
|
||||
outPtr = mFrameAllocator.lock(size);
|
||||
}
|
||||
|
||||
//set new buffer pos
|
||||
mBufferFreePos = mBufferFreePos + size;
|
||||
mBufferFreePos += size;
|
||||
|
||||
//align 4bytes
|
||||
mBufferFreePos = ( (mBufferFreePos/4) + 1 ) * 4;
|
||||
mBufferFreePos = ((mBufferFreePos + 4 - 1) / 4) * 4;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,15 @@ DefineEngineMethod(GuiInspectorField, setCaption, void, (String newCaption),, "(
|
|||
object->setCaption(StringTable->insert(newCaption.c_str()));
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiInspectorField, getFieldName, const char*, (), , "() - Gets the fieldName of the field.")
|
||||
{
|
||||
constexpr U32 bufSize = 128;
|
||||
char* retBuffer = Con::getReturnBuffer(bufSize);
|
||||
dSprintf(retBuffer, bufSize, "%s", object->getFieldName());
|
||||
|
||||
return retBuffer;
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiInspectorField, setSpecialEditVariableName, void, (String newCaption), , "() - Sets the variable name for special edit fields.")
|
||||
{
|
||||
object->setSpecialEditVariableName(StringTable->insert(newCaption.c_str()));
|
||||
|
|
|
|||
|
|
@ -132,6 +132,8 @@ class GuiInspectorField : public GuiControl
|
|||
/// this is exposed in case someone wants to override the normal caption.
|
||||
virtual void setCaption( StringTableEntry caption ) { mCaption = caption; }
|
||||
|
||||
virtual StringTableEntry getCaption() { return mCaption; }
|
||||
|
||||
void setEditControl(GuiControl* editCtrl);
|
||||
|
||||
void setHeightOverride(bool useOverride, U32 heightOverride);
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ GuiInspectorField *GuiInspectorGroup::findField( const char *fieldName )
|
|||
|
||||
for( ; i != mChildren.end(); i++ )
|
||||
{
|
||||
if( (*i)->getFieldName() != NULL && dStricmp( (*i)->getFieldName(), fieldName ) == 0 )
|
||||
if( ((*i)->getFieldName() != NULL && dStricmp( (*i)->getFieldName(), fieldName ) == 0) || ((*i)->getCaption() != StringTable->EmptyString() && dStricmp((*i)->getCaption(), fieldName) == 0) )
|
||||
return (*i);
|
||||
}
|
||||
|
||||
|
|
@ -834,3 +834,26 @@ DefineEngineMethod(GuiInspectorGroup, setForcedArrayIndex, void, (S32 arrayIndex
|
|||
{
|
||||
object->setForcedArrayIndex(arrayIndex);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiInspectorGroup, findField, S32, (const char* fieldName),,
|
||||
"Finds an Inspector field in this group of a given name.\n"
|
||||
"@param fieldName The name of the field to be found.\n"
|
||||
"@return Field SimObjectId")
|
||||
{
|
||||
if (dStrEqual(fieldName, ""))
|
||||
return 0;
|
||||
|
||||
GuiInspectorField* field = object->findField(StringTable->insert(fieldName));
|
||||
if (field == nullptr)
|
||||
return 0;
|
||||
|
||||
return field->getId();
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiInspectorGroup, refresh, void, (), ,
|
||||
"Finds an Inspector field in this group of a given name.\n"
|
||||
"@param fieldName The name of the field to be found.\n"
|
||||
"@return Field SimObjectId")
|
||||
{
|
||||
object->inspectGroup();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,15 @@ ImplementEnumType(MaterialWaveType,
|
|||
{ Material::Square, "Square", "Warps the material along a wave which transitions between two oppposite states. As a Square Wave, the transition is quick and sudden." },
|
||||
EndImplementEnumType;
|
||||
|
||||
ImplementEnumType(MaterialSourceChannelType,
|
||||
"When sampling from ORM Texture maps, dictates what channel to sample from for a given AO, Roughness or Metalness texture.\n"
|
||||
"@ingroup GFX\n")
|
||||
{ Material::RedChannel, "Red", "Red Channel" },
|
||||
{ Material::GreenChannel, "Green", "Green Channel" },
|
||||
{ Material::BlueChannel, "Blue", "Blue Channel" },
|
||||
{ Material::AlphaChannel, "Alpha", "Alpha Channel" },
|
||||
EndImplementEnumType;
|
||||
|
||||
bool Material::sAllowTextureTargetAssignment = false;
|
||||
|
||||
GFXCubemap* Material::GetNormalizeCube()
|
||||
|
|
@ -254,6 +263,11 @@ void Material::initPersistFields()
|
|||
|
||||
addGroup("Light Influence Maps");
|
||||
|
||||
addFieldV("roughness", TypeRangedF32, Offset(mRoughness, Material), &CommonValidators::F32_8BitPercent, MAX_STAGES,
|
||||
"The degree of roughness when not using a ORMConfigMap.");
|
||||
addFieldV("metalness", TypeRangedF32, Offset(mMetalness, Material), &CommonValidators::F32_8BitPercent, MAX_STAGES,
|
||||
"The degree of Metalness when not using a ORMConfigMap.");
|
||||
|
||||
INITPERSISTFIELD_IMAGEASSET_ARRAY(ORMConfigMap, MAX_STAGES, Material, "AO|Roughness|metalness map");
|
||||
addField("isSRGb", TypeBool, Offset(mIsSRGb, Material), MAX_STAGES,
|
||||
"Substance Designer Workaround.");
|
||||
|
|
@ -261,21 +275,19 @@ void Material::initPersistFields()
|
|||
"Treat Roughness as Roughness");
|
||||
|
||||
INITPERSISTFIELD_IMAGEASSET_ARRAY(AOMap, MAX_STAGES, Material, "AOMap");
|
||||
INITPERSISTFIELD_IMAGEASSET_ARRAY(RoughMap, MAX_STAGES, Material, "RoughMap (also needs MetalMap)");
|
||||
INITPERSISTFIELD_IMAGEASSET_ARRAY(MetalMap, MAX_STAGES, Material, "MetalMap (also needs RoughMap)");
|
||||
INITPERSISTFIELD_IMAGEASSET_ARRAY(GlowMap, MAX_STAGES, Material, "GlowMap (needs Albedo)");
|
||||
|
||||
addFieldV("AOChan", TypeRangedS32, Offset(mAOChan, Material), &bmpChanRange, MAX_STAGES,
|
||||
addField("AOChan", TYPEID< SourceChannelType >(), Offset(mAOChan, Material), MAX_STAGES,
|
||||
"The input channel AO maps use.");
|
||||
addFieldV("roughness", TypeRangedF32, Offset(mRoughness, Material), &CommonValidators::F32_8BitPercent,MAX_STAGES,
|
||||
"The degree of roughness when not using a ORMConfigMap.");
|
||||
addFieldV("roughnessChan", TypeRangedS32, Offset(mRoughnessChan, Material), &bmpChanRange, MAX_STAGES,
|
||||
|
||||
INITPERSISTFIELD_IMAGEASSET_ARRAY(RoughMap, MAX_STAGES, Material, "RoughMap (also needs MetalMap)");
|
||||
addField("roughnessChan", TYPEID< SourceChannelType >(), Offset(mRoughnessChan, Material), MAX_STAGES,
|
||||
"The input channel roughness maps use.");
|
||||
addFieldV("metalness", TypeRangedF32, Offset(mMetalness, Material), &CommonValidators::F32_8BitPercent, MAX_STAGES,
|
||||
"The degree of Metalness when not using a ORMConfigMap.");
|
||||
addFieldV("metalChan", TypeRangedS32, Offset(mMetalChan, Material), &bmpChanRange, MAX_STAGES,
|
||||
|
||||
INITPERSISTFIELD_IMAGEASSET_ARRAY(MetalMap, MAX_STAGES, Material, "MetalMap (also needs RoughMap)");
|
||||
addField("metalChan", TYPEID< SourceChannelType >(), Offset(mMetalChan, Material), MAX_STAGES,
|
||||
"The input channel metalness maps use.");
|
||||
|
||||
INITPERSISTFIELD_IMAGEASSET_ARRAY(GlowMap, MAX_STAGES, Material, "GlowMap (needs Albedo)");
|
||||
|
||||
addFieldV("glowMul", TypeRangedF32, Offset(mGlowMul, Material),&glowMulRange, MAX_STAGES,
|
||||
"glow mask multiplier");
|
||||
endGroup("Light Influence Maps");
|
||||
|
|
|
|||
|
|
@ -129,6 +129,14 @@ public:
|
|||
Square,
|
||||
};
|
||||
|
||||
enum SourceChannelType
|
||||
{
|
||||
RedChannel = 0,
|
||||
GreenChannel,
|
||||
BlueChannel,
|
||||
AlphaChannel
|
||||
};
|
||||
|
||||
class StageData
|
||||
{
|
||||
protected:
|
||||
|
|
@ -425,9 +433,11 @@ private:
|
|||
typedef Material::AnimType MaterialAnimType;
|
||||
typedef Material::BlendOp MaterialBlendOp;
|
||||
typedef Material::WaveType MaterialWaveType;
|
||||
typedef Material::SourceChannelType MaterialSourceChannelType;
|
||||
|
||||
DefineBitfieldType(MaterialAnimType);
|
||||
DefineEnumType(MaterialBlendOp);
|
||||
DefineEnumType(MaterialWaveType);
|
||||
DefineEnumType(MaterialSourceChannelType);
|
||||
|
||||
#endif // _MATERIALDEFINITION_H_
|
||||
|
|
|
|||
315
Engine/source/navigation/ChunkyTriMesh.cpp
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include "ChunkyTriMesh.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
struct BoundsItem
|
||||
{
|
||||
float bmin[2];
|
||||
float bmax[2];
|
||||
int i;
|
||||
};
|
||||
|
||||
static int compareItemX(const void* va, const void* vb)
|
||||
{
|
||||
const BoundsItem* a = (const BoundsItem*)va;
|
||||
const BoundsItem* b = (const BoundsItem*)vb;
|
||||
if (a->bmin[0] < b->bmin[0])
|
||||
return -1;
|
||||
if (a->bmin[0] > b->bmin[0])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compareItemY(const void* va, const void* vb)
|
||||
{
|
||||
const BoundsItem* a = (const BoundsItem*)va;
|
||||
const BoundsItem* b = (const BoundsItem*)vb;
|
||||
if (a->bmin[1] < b->bmin[1])
|
||||
return -1;
|
||||
if (a->bmin[1] > b->bmin[1])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void calcExtends(const BoundsItem* items, const int /*nitems*/,
|
||||
const int imin, const int imax,
|
||||
float* bmin, float* bmax)
|
||||
{
|
||||
bmin[0] = items[imin].bmin[0];
|
||||
bmin[1] = items[imin].bmin[1];
|
||||
|
||||
bmax[0] = items[imin].bmax[0];
|
||||
bmax[1] = items[imin].bmax[1];
|
||||
|
||||
for (int i = imin+1; i < imax; ++i)
|
||||
{
|
||||
const BoundsItem& it = items[i];
|
||||
if (it.bmin[0] < bmin[0]) bmin[0] = it.bmin[0];
|
||||
if (it.bmin[1] < bmin[1]) bmin[1] = it.bmin[1];
|
||||
|
||||
if (it.bmax[0] > bmax[0]) bmax[0] = it.bmax[0];
|
||||
if (it.bmax[1] > bmax[1]) bmax[1] = it.bmax[1];
|
||||
}
|
||||
}
|
||||
|
||||
inline int longestAxis(float x, float y)
|
||||
{
|
||||
return y > x ? 1 : 0;
|
||||
}
|
||||
|
||||
static void subdivide(BoundsItem* items, int nitems, int imin, int imax, int trisPerChunk,
|
||||
int& curNode, rcChunkyTriMeshNode* nodes, const int maxNodes,
|
||||
int& curTri, int* outTris, const int* inTris)
|
||||
{
|
||||
int inum = imax - imin;
|
||||
int icur = curNode;
|
||||
|
||||
if (curNode >= maxNodes)
|
||||
return;
|
||||
|
||||
rcChunkyTriMeshNode& node = nodes[curNode++];
|
||||
|
||||
if (inum <= trisPerChunk)
|
||||
{
|
||||
// Leaf
|
||||
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
|
||||
|
||||
// Copy triangles.
|
||||
node.i = curTri;
|
||||
node.n = inum;
|
||||
|
||||
for (int i = imin; i < imax; ++i)
|
||||
{
|
||||
const int* src = &inTris[items[i].i*3];
|
||||
int* dst = &outTris[curTri*3];
|
||||
curTri++;
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Split
|
||||
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
|
||||
|
||||
int axis = longestAxis(node.bmax[0] - node.bmin[0],
|
||||
node.bmax[1] - node.bmin[1]);
|
||||
|
||||
if (axis == 0)
|
||||
{
|
||||
// Sort along x-axis
|
||||
qsort(items+imin, static_cast<size_t>(inum), sizeof(BoundsItem), compareItemX);
|
||||
}
|
||||
else if (axis == 1)
|
||||
{
|
||||
// Sort along y-axis
|
||||
qsort(items+imin, static_cast<size_t>(inum), sizeof(BoundsItem), compareItemY);
|
||||
}
|
||||
|
||||
int isplit = imin+inum/2;
|
||||
|
||||
// Left
|
||||
subdivide(items, nitems, imin, isplit, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris);
|
||||
// Right
|
||||
subdivide(items, nitems, isplit, imax, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris);
|
||||
|
||||
int iescape = curNode - icur;
|
||||
// Negative index means escape.
|
||||
node.i = -iescape;
|
||||
}
|
||||
}
|
||||
|
||||
bool rcCreateChunkyTriMesh(const float* verts, const int* tris, int ntris,
|
||||
int trisPerChunk, rcChunkyTriMesh* cm)
|
||||
{
|
||||
int nchunks = (ntris + trisPerChunk-1) / trisPerChunk;
|
||||
|
||||
cm->nodes = new rcChunkyTriMeshNode[nchunks*4];
|
||||
if (!cm->nodes)
|
||||
return false;
|
||||
|
||||
cm->tris = new int[ntris*3];
|
||||
if (!cm->tris)
|
||||
return false;
|
||||
|
||||
cm->ntris = ntris;
|
||||
|
||||
// Build tree
|
||||
BoundsItem* items = new BoundsItem[ntris];
|
||||
if (!items)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < ntris; i++)
|
||||
{
|
||||
const int* t = &tris[i*3];
|
||||
BoundsItem& it = items[i];
|
||||
it.i = i;
|
||||
// Calc triangle XZ bounds.
|
||||
it.bmin[0] = it.bmax[0] = verts[t[0]*3+0];
|
||||
it.bmin[1] = it.bmax[1] = verts[t[0]*3+2];
|
||||
for (int j = 1; j < 3; ++j)
|
||||
{
|
||||
const float* v = &verts[t[j]*3];
|
||||
if (v[0] < it.bmin[0]) it.bmin[0] = v[0];
|
||||
if (v[2] < it.bmin[1]) it.bmin[1] = v[2];
|
||||
|
||||
if (v[0] > it.bmax[0]) it.bmax[0] = v[0];
|
||||
if (v[2] > it.bmax[1]) it.bmax[1] = v[2];
|
||||
}
|
||||
}
|
||||
|
||||
int curTri = 0;
|
||||
int curNode = 0;
|
||||
subdivide(items, ntris, 0, ntris, trisPerChunk, curNode, cm->nodes, nchunks*4, curTri, cm->tris, tris);
|
||||
|
||||
delete [] items;
|
||||
|
||||
cm->nnodes = curNode;
|
||||
|
||||
// Calc max tris per node.
|
||||
cm->maxTrisPerChunk = 0;
|
||||
for (int i = 0; i < cm->nnodes; ++i)
|
||||
{
|
||||
rcChunkyTriMeshNode& node = cm->nodes[i];
|
||||
const bool isLeaf = node.i >= 0;
|
||||
if (!isLeaf) continue;
|
||||
if (node.n > cm->maxTrisPerChunk)
|
||||
cm->maxTrisPerChunk = node.n;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline bool checkOverlapRect(const float amin[2], const float amax[2],
|
||||
const float bmin[2], const float bmax[2])
|
||||
{
|
||||
bool overlap = true;
|
||||
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
||||
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
|
||||
return overlap;
|
||||
}
|
||||
|
||||
int rcGetChunksOverlappingRect(const rcChunkyTriMesh* cm,
|
||||
float bmin[2], float bmax[2],
|
||||
int* ids, const int maxIds)
|
||||
{
|
||||
// Traverse tree
|
||||
int i = 0;
|
||||
int n = 0;
|
||||
while (i < cm->nnodes)
|
||||
{
|
||||
const rcChunkyTriMeshNode* node = &cm->nodes[i];
|
||||
const bool overlap = checkOverlapRect(bmin, bmax, node->bmin, node->bmax);
|
||||
const bool isLeafNode = node->i >= 0;
|
||||
|
||||
if (isLeafNode && overlap)
|
||||
{
|
||||
if (n < maxIds)
|
||||
{
|
||||
ids[n] = i;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlap || isLeafNode)
|
||||
i++;
|
||||
else
|
||||
{
|
||||
const int escapeIndex = -node->i;
|
||||
i += escapeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool checkOverlapSegment(const float p[2], const float q[2],
|
||||
const float bmin[2], const float bmax[2])
|
||||
{
|
||||
static const float EPSILON = 1e-6f;
|
||||
|
||||
float tmin = 0;
|
||||
float tmax = 1;
|
||||
float d[2];
|
||||
d[0] = q[0] - p[0];
|
||||
d[1] = q[1] - p[1];
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (fabsf(d[i]) < EPSILON)
|
||||
{
|
||||
// Ray is parallel to slab. No hit if origin not within slab
|
||||
if (p[i] < bmin[i] || p[i] > bmax[i])
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute intersection t value of ray with near and far plane of slab
|
||||
float ood = 1.0f / d[i];
|
||||
float t1 = (bmin[i] - p[i]) * ood;
|
||||
float t2 = (bmax[i] - p[i]) * ood;
|
||||
if (t1 > t2) { float tmp = t1; t1 = t2; t2 = tmp; }
|
||||
if (t1 > tmin) tmin = t1;
|
||||
if (t2 < tmax) tmax = t2;
|
||||
if (tmin > tmax) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int rcGetChunksOverlappingSegment(const rcChunkyTriMesh* cm,
|
||||
float p[2], float q[2],
|
||||
int* ids, const int maxIds)
|
||||
{
|
||||
// Traverse tree
|
||||
int i = 0;
|
||||
int n = 0;
|
||||
while (i < cm->nnodes)
|
||||
{
|
||||
const rcChunkyTriMeshNode* node = &cm->nodes[i];
|
||||
const bool overlap = checkOverlapSegment(p, q, node->bmin, node->bmax);
|
||||
const bool isLeafNode = node->i >= 0;
|
||||
|
||||
if (isLeafNode && overlap)
|
||||
{
|
||||
if (n < maxIds)
|
||||
{
|
||||
ids[n] = i;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlap || isLeafNode)
|
||||
i++;
|
||||
else
|
||||
{
|
||||
const int escapeIndex = -node->i;
|
||||
i += escapeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
59
Engine/source/navigation/ChunkyTriMesh.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef CHUNKYTRIMESH_H
|
||||
#define CHUNKYTRIMESH_H
|
||||
|
||||
struct rcChunkyTriMeshNode
|
||||
{
|
||||
float bmin[2];
|
||||
float bmax[2];
|
||||
int i;
|
||||
int n;
|
||||
};
|
||||
|
||||
struct rcChunkyTriMesh
|
||||
{
|
||||
inline rcChunkyTriMesh() : nodes(0), nnodes(0), tris(0), ntris(0), maxTrisPerChunk(0) {}
|
||||
inline ~rcChunkyTriMesh() { delete [] nodes; delete [] tris; }
|
||||
|
||||
rcChunkyTriMeshNode* nodes;
|
||||
int nnodes;
|
||||
int* tris;
|
||||
int ntris;
|
||||
int maxTrisPerChunk;
|
||||
|
||||
private:
|
||||
// Explicitly disabled copy constructor and copy assignment operator.
|
||||
rcChunkyTriMesh(const rcChunkyTriMesh&);
|
||||
rcChunkyTriMesh& operator=(const rcChunkyTriMesh&);
|
||||
};
|
||||
|
||||
/// Creates partitioned triangle mesh (AABB tree),
|
||||
/// where each node contains at max trisPerChunk triangles.
|
||||
bool rcCreateChunkyTriMesh(const float* verts, const int* tris, int ntris,
|
||||
int trisPerChunk, rcChunkyTriMesh* cm);
|
||||
|
||||
/// Returns the chunk indices which overlap the input rectable.
|
||||
int rcGetChunksOverlappingRect(const rcChunkyTriMesh* cm, float bmin[2], float bmax[2], int* ids, const int maxIds);
|
||||
|
||||
/// Returns the chunk indices which overlap the input segment.
|
||||
int rcGetChunksOverlappingSegment(const rcChunkyTriMesh* cm, float p[2], float q[2], int* ids, const int maxIds);
|
||||
|
||||
|
||||
#endif // CHUNKYTRIMESH_H
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "renderInstance/renderPassManager.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "T3D/gameBase/gameConnection.h"
|
||||
|
||||
extern bool gEditingMission;
|
||||
|
||||
|
|
@ -285,14 +286,22 @@ void CoverPoint::prepRenderImage(SceneRenderState *state)
|
|||
|
||||
void CoverPoint::render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat)
|
||||
{
|
||||
initGFXResources();
|
||||
if (!state->isDiffusePass()) return;
|
||||
|
||||
if(overrideMat)
|
||||
GameConnection* conn = GameConnection::getConnectionToServer();
|
||||
MatrixF camTrans;
|
||||
conn->getControlCameraTransform(0, &camTrans);
|
||||
|
||||
if ((getPosition() - camTrans.getPosition()).lenSquared() > 2500) return; //50 unit clamp
|
||||
|
||||
if (overrideMat)
|
||||
return;
|
||||
|
||||
initGFXResources();
|
||||
|
||||
if(smVertexBuffer[mSize].isNull())
|
||||
return;
|
||||
|
||||
|
||||
PROFILE_SCOPE(CoverPoint_Render);
|
||||
|
||||
// Set up a GFX debug event (this helps with debugging rendering events in external tools)
|
||||
|
|
|
|||
|
|
@ -38,28 +38,64 @@
|
|||
|
||||
duDebugDrawTorque::duDebugDrawTorque()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mVertList);
|
||||
VECTOR_SET_ASSOCIATION(mDrawCache);
|
||||
mPrimType = 0;
|
||||
mQuadsMode = false;
|
||||
mVertCount = 0;
|
||||
mGroup = 0;
|
||||
mCurrColor = 0;
|
||||
mOverrideColor = 0;
|
||||
mOverride = false;
|
||||
dMemset(&mStore, 0, sizeof(mStore));
|
||||
mOverrideState = false;
|
||||
}
|
||||
|
||||
duDebugDrawTorque::~duDebugDrawTorque()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void duDebugDrawTorque::depthMask(bool state)
|
||||
{
|
||||
mDesc.setZReadWrite(state, state);
|
||||
if (mOverrideState)
|
||||
return;
|
||||
|
||||
mDesc.setZReadWrite(state);
|
||||
if (!state)
|
||||
{
|
||||
mDesc.setCullMode(GFXCullNone);
|
||||
mDesc.setBlend(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
mDesc.setCullMode(GFXCullCW);
|
||||
mDesc.setBlend(false);
|
||||
}
|
||||
}
|
||||
|
||||
void duDebugDrawTorque::depthMask(bool state, bool isOverride)
|
||||
{
|
||||
depthMask(state);
|
||||
mOverrideState = isOverride;
|
||||
}
|
||||
|
||||
void duDebugDrawTorque::blend(bool blend)
|
||||
{
|
||||
mDesc.setBlend(true);
|
||||
}
|
||||
|
||||
void duDebugDrawTorque::texture(bool state)
|
||||
{
|
||||
// need a checker texture?...... if(state is true) then set first slot to that texture.
|
||||
}
|
||||
|
||||
unsigned int duDebugDrawTorque::areaToCol(unsigned int area)
|
||||
{
|
||||
switch (area)
|
||||
{
|
||||
// Ground (1) : light blue
|
||||
case GroundArea: return duRGBA(0, 192, 255, 255);
|
||||
// Water : blue
|
||||
case WaterArea: return duRGBA(0, 0, 255, 255);
|
||||
// Road : brown
|
||||
case OffMeshArea: return duRGBA(50, 20, 12, 255);
|
||||
// Unexpected : red
|
||||
default: return duRGBA(255, 0, 0, 255);
|
||||
}
|
||||
}
|
||||
|
||||
/// Begin drawing primitives.
|
||||
|
|
@ -67,27 +103,20 @@ void duDebugDrawTorque::texture(bool state)
|
|||
/// @param size [in] size of a primitive, applies to point size and line width only.
|
||||
void duDebugDrawTorque::begin(duDebugDrawPrimitives prim, float size)
|
||||
{
|
||||
mCurrColor = -1;
|
||||
mQuadsMode = false;
|
||||
if (!mVertList.empty())
|
||||
mVertList.clear();
|
||||
|
||||
mVertCount = 0;
|
||||
mPrimType = 0;
|
||||
switch(prim)
|
||||
{
|
||||
case DU_DRAW_POINTS: mPrimType = GFXPointList; break;
|
||||
case DU_DRAW_LINES: mPrimType = GFXLineList; break;
|
||||
case DU_DRAW_TRIS: mPrimType = GFXTriangleList; break;
|
||||
case DU_DRAW_QUADS: mPrimType = GFXTriangleList;
|
||||
mQuadsMode = true; break;
|
||||
}
|
||||
mBuffers.push_back(Buffer(mPrimType));
|
||||
mBuffers.last().group = mGroup;
|
||||
mDesc.setCullMode(GFXCullNone);
|
||||
mDesc.setBlend(true);
|
||||
}
|
||||
|
||||
void duDebugDrawTorque::beginGroup(U32 group)
|
||||
{
|
||||
mGroup = group;
|
||||
switch (prim)
|
||||
{
|
||||
case DU_DRAW_POINTS: mPrimType = DU_DRAW_POINTS; break;
|
||||
case DU_DRAW_LINES: mPrimType = DU_DRAW_LINES; break;
|
||||
case DU_DRAW_TRIS: mPrimType = DU_DRAW_TRIS; break;
|
||||
case DU_DRAW_QUADS: mPrimType = DU_DRAW_QUADS; break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Submit a vertex
|
||||
|
|
@ -103,30 +132,7 @@ void duDebugDrawTorque::vertex(const float* pos, unsigned int color)
|
|||
/// @param color [in] color of the verts.
|
||||
void duDebugDrawTorque::vertex(const float x, const float y, const float z, unsigned int color)
|
||||
{
|
||||
if(mQuadsMode)
|
||||
{
|
||||
if(mVertCount == 3)
|
||||
{
|
||||
_vertex(x, -z, y, color);
|
||||
_vertex(mStore[0][0], mStore[0][1], mStore[0][2], color);
|
||||
_vertex(mStore[1][0], mStore[1][1], mStore[1][2], color);
|
||||
_vertex(mStore[1][0], mStore[1][1], mStore[1][2], color);
|
||||
_vertex(mStore[2][0], mStore[2][1], mStore[2][2], color);
|
||||
_vertex(x, -z, y, color);
|
||||
mVertCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mStore[mVertCount][0] = x;
|
||||
mStore[mVertCount][1] = -z;
|
||||
mStore[mVertCount][2] = y;
|
||||
mVertCount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_vertex(x, -z, y, color);
|
||||
}
|
||||
_vertex(x, -z, y, color);
|
||||
}
|
||||
|
||||
/// Submit a vertex
|
||||
|
|
@ -148,105 +154,325 @@ void duDebugDrawTorque::vertex(const float x, const float y, const float z, unsi
|
|||
/// Push a vertex onto the buffer.
|
||||
void duDebugDrawTorque::_vertex(const float x, const float y, const float z, unsigned int color)
|
||||
{
|
||||
// Use override color if we must.
|
||||
//if(mOverride)
|
||||
//color = mOverrideColor;
|
||||
if(mCurrColor != color || !mBuffers.last().buffer.size())
|
||||
{
|
||||
U8 r, g, b, a;
|
||||
// Convert color integer to components.
|
||||
rcCol(color, r, g, b, a);
|
||||
mBuffers.last().buffer.push_back(Instruction(r, g, b, a));
|
||||
mCurrColor = color;
|
||||
}
|
||||
// Construct vertex data.
|
||||
mBuffers.last().buffer.push_back(Instruction(x, y, z));
|
||||
GFXVertexPCT vert;
|
||||
vert.point.set(x, y, z);
|
||||
|
||||
U8 r, g, b, a;
|
||||
// Convert color integer to components.
|
||||
rcCol(color, r, g, b, a);
|
||||
|
||||
vert.color.set(r, g, b, a);
|
||||
|
||||
mVertList.push_back(vert);
|
||||
}
|
||||
|
||||
/// End drawing primitives.
|
||||
void duDebugDrawTorque::end()
|
||||
{
|
||||
}
|
||||
if (mVertList.empty())
|
||||
return;
|
||||
|
||||
void duDebugDrawTorque::overrideColor(unsigned int col)
|
||||
{
|
||||
mOverride = true;
|
||||
mOverrideColor = col;
|
||||
}
|
||||
|
||||
void duDebugDrawTorque::cancelOverride()
|
||||
{
|
||||
mOverride = false;
|
||||
}
|
||||
|
||||
void duDebugDrawTorque::renderBuffer(Buffer &b)
|
||||
{
|
||||
PrimBuild::begin(b.primType, b.buffer.size());
|
||||
Vector<Instruction> &buf = b.buffer;
|
||||
for(U32 i = 0; i < buf.size(); i++)
|
||||
const U32 maxVertsPerDraw = GFX_MAX_DYNAMIC_VERTS;
|
||||
|
||||
switch (mPrimType)
|
||||
{
|
||||
switch(buf[i].type)
|
||||
case DU_DRAW_POINTS:
|
||||
{
|
||||
const U32 totalPoints = mVertList.size();
|
||||
|
||||
for (U32 p = 0; p < totalPoints;)
|
||||
{
|
||||
case Instruction::POINT:
|
||||
PrimBuild::vertex3f(buf[i].data.point.x,
|
||||
buf[i].data.point.y,
|
||||
buf[i].data.point.z);
|
||||
break;
|
||||
const U32 pointsThisBatch = getMin(maxVertsPerDraw, totalPoints - p);
|
||||
const U32 batchVerts = pointsThisBatch;
|
||||
Box3F box;
|
||||
box.minExtents.set(F32_MAX, F32_MAX, F32_MAX);
|
||||
box.maxExtents.set(-F32_MAX, -F32_MAX, -F32_MAX);
|
||||
|
||||
case Instruction::COLOR:
|
||||
if(mOverride)
|
||||
break;
|
||||
PrimBuild::color4i(buf[i].data.color.r,
|
||||
buf[i].data.color.g,
|
||||
buf[i].data.color.b,
|
||||
buf[i].data.color.a);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
GFXVertexBufferHandle<GFXVertexPCT> buffer;
|
||||
buffer.set(GFX, batchVerts, GFXBufferTypeStatic);
|
||||
GFXVertexPCT* verts = buffer.lock();
|
||||
|
||||
for (U32 i = 0; i < pointsThisBatch; ++i)
|
||||
{
|
||||
verts[i] = mVertList[p + i];
|
||||
box.minExtents.setMin(verts[i].point);
|
||||
box.maxExtents.setMax(verts[i].point);
|
||||
}
|
||||
buffer.unlock();
|
||||
|
||||
// --- Build index buffer
|
||||
GFXPrimitiveBufferHandle pb;
|
||||
pb.set(GFX, pointsThisBatch, pointsThisBatch, GFXBufferTypeStatic);
|
||||
U16* indices = nullptr;
|
||||
pb.lock(&indices);
|
||||
|
||||
for (U32 i = 0; i < pointsThisBatch; ++i)
|
||||
{
|
||||
indices[i] = i;
|
||||
}
|
||||
|
||||
pb.unlock();
|
||||
|
||||
CachedDraw batch;
|
||||
batch.primType = GFXPointList;
|
||||
batch.buffer = buffer;
|
||||
batch.vertexCount = batchVerts;
|
||||
batch.primitiveBuffer = pb;
|
||||
batch.primitiveCount = pointsThisBatch;
|
||||
batch.state = mDesc;
|
||||
batch.bounds = box;
|
||||
|
||||
mDrawCache.push_back(batch);
|
||||
|
||||
p += pointsThisBatch;
|
||||
}
|
||||
break;
|
||||
}
|
||||
PrimBuild::end();
|
||||
|
||||
case DU_DRAW_LINES:
|
||||
{
|
||||
AssertFatal(mVertList.size() % 2 == 0, "DU_DRAW_LINES given invalid vertex count.");
|
||||
|
||||
const U32 vertsPerLine = 2;
|
||||
const U32 totalLines = mVertList.size() / vertsPerLine;
|
||||
|
||||
for (U32 l = 0; l < totalLines;)
|
||||
{
|
||||
const U32 linesThisBatch = getMin(maxVertsPerDraw / vertsPerLine, totalLines - l);
|
||||
const U32 batchVerts = linesThisBatch * vertsPerLine;
|
||||
Box3F box;
|
||||
box.minExtents.set(F32_MAX, F32_MAX, F32_MAX);
|
||||
box.maxExtents.set(-F32_MAX, -F32_MAX, -F32_MAX);
|
||||
|
||||
GFXVertexBufferHandle<GFXVertexPCT> buffer;
|
||||
buffer.set(GFX, batchVerts, GFXBufferTypeStatic);
|
||||
GFXVertexPCT* verts = buffer.lock();
|
||||
|
||||
for (U32 i = 0; i < linesThisBatch * vertsPerLine; ++i)
|
||||
{
|
||||
verts[i] = mVertList[l * vertsPerLine + i];
|
||||
box.minExtents.setMin(verts[i].point);
|
||||
box.maxExtents.setMax(verts[i].point);
|
||||
}
|
||||
buffer.unlock();
|
||||
|
||||
// --- Build index buffer
|
||||
GFXPrimitiveBufferHandle pb;
|
||||
pb.set(GFX, linesThisBatch * 2, linesThisBatch, GFXBufferTypeStatic);
|
||||
U16* indices = nullptr;
|
||||
pb.lock(&indices);
|
||||
|
||||
for (U32 i = 0; i < linesThisBatch; ++i)
|
||||
{
|
||||
indices[i * 2 + 0] = i * 2;
|
||||
indices[i * 2 + 1] = i * 2 + 1;
|
||||
}
|
||||
|
||||
pb.unlock();
|
||||
|
||||
CachedDraw batch;
|
||||
batch.primType = GFXLineList;
|
||||
batch.buffer = buffer;
|
||||
batch.vertexCount = batchVerts;
|
||||
batch.primitiveBuffer = pb;
|
||||
batch.primitiveCount = linesThisBatch;
|
||||
batch.state = mDesc;
|
||||
batch.bounds = box;
|
||||
|
||||
mDrawCache.push_back(batch);
|
||||
|
||||
l += linesThisBatch;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DU_DRAW_TRIS:
|
||||
{
|
||||
AssertFatal(mVertList.size() % 3 == 0, "DU_DRAW_TRIS given invalid vertex count.");
|
||||
|
||||
const U32 vertsPerTri = 3;
|
||||
const U32 totalTris = mVertList.size() / vertsPerTri;
|
||||
|
||||
for (U32 t = 0; t < totalTris;)
|
||||
{
|
||||
const U32 trisThisBatch = getMin(maxVertsPerDraw / vertsPerTri, totalTris - t);
|
||||
const U32 batchVerts = trisThisBatch * vertsPerTri;
|
||||
Box3F box;
|
||||
box.minExtents.set(F32_MAX, F32_MAX, F32_MAX);
|
||||
box.maxExtents.set(-F32_MAX, -F32_MAX, -F32_MAX);
|
||||
|
||||
GFXVertexBufferHandle<GFXVertexPCT> buffer;
|
||||
buffer.set(GFX, batchVerts, GFXBufferTypeStatic);
|
||||
GFXVertexPCT* verts = buffer.lock();
|
||||
|
||||
for (U32 i = 0; i < trisThisBatch * vertsPerTri; ++i)
|
||||
{
|
||||
verts[i] = mVertList[t * vertsPerTri + i];
|
||||
box.minExtents.setMin(verts[i].point);
|
||||
box.maxExtents.setMax(verts[i].point);
|
||||
}
|
||||
|
||||
buffer.unlock();
|
||||
|
||||
// --- Build index buffer
|
||||
GFXPrimitiveBufferHandle pb;
|
||||
pb.set(GFX, trisThisBatch*3, trisThisBatch, GFXBufferTypeStatic);
|
||||
U16* indices = nullptr;
|
||||
pb.lock(&indices);
|
||||
|
||||
for (U32 i = 0; i < trisThisBatch; ++i)
|
||||
{
|
||||
indices[i * 3 + 0] = i * 3 + 0;
|
||||
indices[i * 3 + 1] = i * 3 + 1;
|
||||
indices[i * 3 + 2] = i * 3 + 2;
|
||||
}
|
||||
|
||||
pb.unlock();
|
||||
|
||||
CachedDraw batch;
|
||||
batch.primType = GFXTriangleList;
|
||||
batch.buffer = buffer;
|
||||
batch.vertexCount = batchVerts;
|
||||
batch.primitiveBuffer = pb;
|
||||
batch.primitiveCount = trisThisBatch;
|
||||
batch.state = mDesc;
|
||||
batch.bounds = box;
|
||||
|
||||
mDrawCache.push_back(batch);
|
||||
|
||||
t += trisThisBatch;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DU_DRAW_QUADS:
|
||||
{
|
||||
AssertFatal(mVertList.size() % 4 == 0, "DU_DRAW_QUADS given wrong number of vertices.");
|
||||
const U32 vertsPerQuad = 4;
|
||||
const U32 totalQuads = mVertList.size() / 4;
|
||||
|
||||
for (U32 q = 0; q < totalQuads;)
|
||||
{
|
||||
const U32 quadsThisBatch = getMin(maxVertsPerDraw / vertsPerQuad, totalQuads - q);
|
||||
const U32 batchVerts = quadsThisBatch * vertsPerQuad;
|
||||
const U32 batchIndices = quadsThisBatch * 6;
|
||||
Box3F box;
|
||||
box.minExtents.set(F32_MAX, F32_MAX, F32_MAX);
|
||||
box.maxExtents.set(-F32_MAX, -F32_MAX, -F32_MAX);
|
||||
|
||||
GFXVertexBufferHandle<GFXVertexPCT> buffer;
|
||||
buffer.set(GFX, batchVerts, GFXBufferTypeStatic);
|
||||
GFXVertexPCT* verts = buffer.lock();
|
||||
|
||||
U32 outIdx = 0;
|
||||
for (U32 i = 0; i < quadsThisBatch; ++i)
|
||||
{
|
||||
const GFXVertexPCT& v0 = mVertList[(q + i) * 4 + 0];
|
||||
const GFXVertexPCT& v1 = mVertList[(q + i) * 4 + 1];
|
||||
const GFXVertexPCT& v2 = mVertList[(q + i) * 4 + 2];
|
||||
const GFXVertexPCT& v3 = mVertList[(q + i) * 4 + 3];
|
||||
|
||||
verts[outIdx++] = v0;
|
||||
verts[outIdx++] = v1;
|
||||
verts[outIdx++] = v2;
|
||||
verts[outIdx++] = v3;
|
||||
}
|
||||
|
||||
buffer.unlock();
|
||||
|
||||
GFXPrimitiveBufferHandle pb;
|
||||
pb.set(GFX, batchIndices, quadsThisBatch*2, GFXBufferTypeStatic);
|
||||
U16* indices = nullptr;
|
||||
pb.lock(&indices);
|
||||
|
||||
for (U32 i = 0; i < quadsThisBatch; ++i)
|
||||
{
|
||||
const U16 base = i * 4;
|
||||
indices[i * 6 + 0] = base + 0;
|
||||
indices[i * 6 + 1] = base + 1;
|
||||
indices[i * 6 + 2] = base + 2;
|
||||
indices[i * 6 + 3] = base + 0;
|
||||
indices[i * 6 + 4] = base + 2;
|
||||
indices[i * 6 + 5] = base + 3;
|
||||
}
|
||||
|
||||
pb.unlock();
|
||||
|
||||
CachedDraw batch;
|
||||
batch.primType = GFXTriangleList;
|
||||
batch.buffer = buffer;
|
||||
batch.vertexCount = batchVerts;
|
||||
batch.primitiveBuffer = pb;
|
||||
batch.primitiveCount = quadsThisBatch*2;
|
||||
batch.state = mDesc;
|
||||
|
||||
mDrawCache.push_back(batch);
|
||||
|
||||
q += quadsThisBatch;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mVertList.clear();
|
||||
}
|
||||
|
||||
void duDebugDrawTorque::render()
|
||||
void duDebugDrawTorque::clearCache()
|
||||
{
|
||||
GFXStateBlockRef sb = GFX->createStateBlock(mDesc);
|
||||
GFX->setStateBlock(sb);
|
||||
// Use override color for all rendering.
|
||||
if(mOverride)
|
||||
mDrawCache.clear();
|
||||
}
|
||||
|
||||
void duDebugDrawTorque::render(SceneRenderState* state)
|
||||
{
|
||||
if (!state->isDiffusePass()) return;
|
||||
|
||||
const Frustum& frustum = state->getCameraFrustum();
|
||||
|
||||
for (U32 i = 0; i < mDrawCache.size(); ++i)
|
||||
{
|
||||
U8 r, g, b, a;
|
||||
rcCol(mOverrideColor, r, g, b, a);
|
||||
PrimBuild::color4i(r, g, b, a);
|
||||
}
|
||||
for(U32 b = 0; b < mBuffers.size(); b++)
|
||||
{
|
||||
renderBuffer(mBuffers[b]);
|
||||
const CachedDraw& draw = mDrawCache[i];
|
||||
|
||||
if (!frustum.getBounds().isOverlapped(draw.bounds))
|
||||
continue;
|
||||
|
||||
GFX->setPrimitiveBuffer(draw.primitiveBuffer);
|
||||
GFX->setStateBlockByDesc(draw.state);
|
||||
GFX->setupGenericShaders(GFXDevice::GSColor);
|
||||
GFX->setVertexBuffer(draw.buffer);
|
||||
|
||||
GFX->drawIndexedPrimitive(
|
||||
draw.primType,
|
||||
0, // start vertex
|
||||
0, // min vertex index
|
||||
draw.vertexCount, // vertex count
|
||||
0, // start index
|
||||
draw.primitiveCount // primitive count
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void duDebugDrawTorque::renderGroup(U32 group)
|
||||
void duDebugDrawTorque::immediateRender()
|
||||
{
|
||||
GFXStateBlockRef sb = GFX->createStateBlock(mDesc);
|
||||
GFX->setStateBlock(sb);
|
||||
// Use override color for all rendering.
|
||||
if(mOverride)
|
||||
for (U32 i = 0; i < mDrawCache.size(); ++i)
|
||||
{
|
||||
U8 r, g, b, a;
|
||||
rcCol(mOverrideColor, r, g, b, a);
|
||||
PrimBuild::color4i(r, g, b, a);
|
||||
}
|
||||
for(U32 b = 0; b < mBuffers.size(); b++)
|
||||
{
|
||||
if(mBuffers[b].group == group)
|
||||
renderBuffer(mBuffers[b]);
|
||||
const CachedDraw& draw = mDrawCache[i];
|
||||
|
||||
GFX->setPrimitiveBuffer(draw.primitiveBuffer);
|
||||
GFX->setStateBlockByDesc(draw.state);
|
||||
GFX->setupGenericShaders(GFXDevice::GSColor);
|
||||
GFX->setVertexBuffer(draw.buffer);
|
||||
|
||||
GFX->drawIndexedPrimitive(
|
||||
draw.primType,
|
||||
0, // start vertex
|
||||
0, // min vertex index
|
||||
draw.vertexCount, // vertex count
|
||||
0, // start index
|
||||
draw.primitiveCount // primitive count
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void duDebugDrawTorque::clear()
|
||||
{
|
||||
for(U32 b = 0; b < mBuffers.size(); b++)
|
||||
mBuffers[b].buffer.clear();
|
||||
mBuffers.clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,12 +23,37 @@
|
|||
#ifndef _DU_DEBUG_DRAW_TORQUE_H_
|
||||
#define _DU_DEBUG_DRAW_TORQUE_H_
|
||||
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "core/util/tVector.h"
|
||||
#endif
|
||||
#include <DebugDraw.h>
|
||||
#include "gfx/gfxStateBlock.h"
|
||||
|
||||
/// @brief Implements the duDebugDraw interface in Torque.
|
||||
class duDebugDrawTorque: public duDebugDraw {
|
||||
#ifndef _GFXSTATEBLOCK_H_
|
||||
#include "gfx/gfxStateBlock.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GFXVERTEXTYPES_H_
|
||||
#include "gfx/gfxVertexTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GFXVERTEXBUFFER_H_
|
||||
#include "gfx/gfxVertexBuffer.h"
|
||||
#endif
|
||||
|
||||
#ifndef _SCENERENDERSTATE_H_
|
||||
#include "scene/sceneRenderState.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @class duDebugDrawTorque
|
||||
* @brief Implements the duDebugDraw interface in Torque.
|
||||
*
|
||||
* Every debug draw from recast goes through a process of begin, add vertex and then end
|
||||
* just like our primbuilder class, but we need to catch these vertices
|
||||
* and add them to a GFXVertexBuffer as recast supports GL_QUADS which is now
|
||||
* deprecated.
|
||||
*/
|
||||
class duDebugDrawTorque : public duDebugDraw {
|
||||
public:
|
||||
duDebugDrawTorque();
|
||||
~duDebugDrawTorque();
|
||||
|
|
@ -36,23 +61,20 @@ public:
|
|||
/// Enable/disable Z read.
|
||||
void depthMask(bool state) override;
|
||||
|
||||
/// Enable/disable texturing. Not used.
|
||||
void texture(bool state) override;
|
||||
/// <summary>
|
||||
/// Enable/disable Z read and overrides any setting that will come from detour.
|
||||
/// </summary>
|
||||
/// <param name="state">Z read state.</param>
|
||||
/// <param name="isOverride">Set to true to override any future changes.</param>
|
||||
void depthMask(bool state, bool isOverride);
|
||||
|
||||
/// Special colour overwrite for when I get picky about the colours Mikko chose.
|
||||
void overrideColor(unsigned int col);
|
||||
|
||||
/// Stop the colour override.
|
||||
void cancelOverride();
|
||||
void blend(bool blend);
|
||||
|
||||
/// Begin drawing primitives.
|
||||
/// @param prim [in] primitive type to draw, one of rcDebugDrawPrimitives.
|
||||
/// @param size [in] size of a primitive, applies to point size and line width only.
|
||||
void begin(duDebugDrawPrimitives prim, float size = 1.0f) override;
|
||||
|
||||
/// All new buffers go into this group.
|
||||
void beginGroup(U32 group);
|
||||
|
||||
/// Submit a vertex
|
||||
/// @param pos [in] position of the verts.
|
||||
/// @param color [in] color of the verts.
|
||||
|
|
@ -66,92 +88,57 @@ public:
|
|||
/// Submit a vertex
|
||||
/// @param pos [in] position of the verts.
|
||||
/// @param color [in] color of the verts.
|
||||
/// @param uv [in] the uv coordinates.
|
||||
void vertex(const float* pos, unsigned int color, const float* uv) override;
|
||||
|
||||
/// Submit a vertex
|
||||
/// @param x,y,z [in] position of the verts.
|
||||
/// @param color [in] color of the verts.
|
||||
/// @param u [in] the u coordinate.
|
||||
/// @param v [in] the v coordinate.
|
||||
void vertex(const float x, const float y, const float z, unsigned int color, const float u, const float v) override;
|
||||
|
||||
/// Set a texture
|
||||
/// @param state, use a texture in this draw, usually a checker texture.
|
||||
void texture(bool state) override;
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a colour to an area type.
|
||||
/// </summary>
|
||||
/// <param name="area">The area type.</param>
|
||||
/// <returns>The colour in recast format for the area.</returns>
|
||||
unsigned int areaToCol(unsigned int area) override;
|
||||
|
||||
/// End drawing primitives.
|
||||
void end() override;
|
||||
|
||||
/// Render buffered primitive.
|
||||
void render();
|
||||
void clearCache();
|
||||
void render(SceneRenderState* state);
|
||||
void immediateRender();
|
||||
|
||||
/// Render buffered primitives in a group.
|
||||
void renderGroup(U32 group);
|
||||
|
||||
/// Delete buffered primitive.
|
||||
void clear();
|
||||
|
||||
private:
|
||||
|
||||
struct CachedDraw {
|
||||
GFXPrimitiveType primType;
|
||||
GFXVertexBufferHandle<GFXVertexPCT> buffer;
|
||||
GFXPrimitiveBufferHandle primitiveBuffer;
|
||||
U32 vertexCount;
|
||||
U32 primitiveCount;
|
||||
GFXStateBlockDesc state;
|
||||
Box3F bounds;
|
||||
};
|
||||
|
||||
Vector<CachedDraw> mDrawCache;
|
||||
|
||||
GFXStateBlockDesc mDesc;
|
||||
Vector<GFXVertexPCT> mVertList; // Our vertex list for setting up vertexBuffer in the End function.
|
||||
GFXVertexBufferHandle<GFXVertexPCT> mVertexBuffer; // our vertex buffer for drawing.
|
||||
|
||||
U32 mPrimType;
|
||||
bool mQuadsMode;
|
||||
|
||||
U32 mVertCount;
|
||||
F32 mStore[3][3];
|
||||
|
||||
U32 mGroup;
|
||||
|
||||
struct Instruction {
|
||||
// Contain either a point or a color command.
|
||||
union {
|
||||
struct {
|
||||
U8 r, g, b, a;
|
||||
} color;
|
||||
struct {
|
||||
float x, y, z;
|
||||
} point;
|
||||
U32 primType;
|
||||
} data;
|
||||
// Which type of data do we store?
|
||||
enum {
|
||||
COLOR,
|
||||
POINT,
|
||||
PRIMTYPE,
|
||||
} type;
|
||||
// Construct as color instruction.
|
||||
Instruction(U8 r, U8 g, U8 b, U8 a) {
|
||||
type = COLOR;
|
||||
data.color.r = r;
|
||||
data.color.g = g;
|
||||
data.color.b = b;
|
||||
data.color.a = a;
|
||||
}
|
||||
// Construct as point.
|
||||
Instruction(float x, float y, float z) {
|
||||
type = POINT;
|
||||
data.point.x = x;
|
||||
data.point.y = y;
|
||||
data.point.z = z;
|
||||
}
|
||||
Instruction(U32 t = 0) {
|
||||
type = PRIMTYPE;
|
||||
data.primType = t;
|
||||
}
|
||||
};
|
||||
|
||||
struct Buffer {
|
||||
U32 group;
|
||||
Vector<Instruction> buffer;
|
||||
GFXPrimitiveType primType;
|
||||
Buffer(U32 type = 0) {
|
||||
primType = (GFXPrimitiveType)type;
|
||||
group = 0;
|
||||
}
|
||||
};
|
||||
Vector<Buffer> mBuffers;
|
||||
|
||||
U32 mCurrColor;
|
||||
U32 mOverrideColor;
|
||||
bool mOverride;
|
||||
bool mOverrideState;
|
||||
|
||||
void _vertex(const float x, const float y, const float z, unsigned int color);
|
||||
|
||||
void renderBuffer(Buffer &b);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "gui/worldEditor/undoActions.h"
|
||||
#include "T3D/gameBase/gameConnection.h"
|
||||
#include "T3D/AI/AIController.h"
|
||||
#include "navigation/navMeshTool.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiNavEditorCtrl);
|
||||
|
||||
|
|
@ -47,24 +48,11 @@ ConsoleDocClass(GuiNavEditorCtrl,
|
|||
"@internal"
|
||||
);
|
||||
|
||||
// Each of the mode names directly correlates with the Nav Editor's tool palette.
|
||||
const String GuiNavEditorCtrl::mSelectMode = "SelectMode";
|
||||
const String GuiNavEditorCtrl::mLinkMode = "LinkMode";
|
||||
const String GuiNavEditorCtrl::mCoverMode = "CoverMode";
|
||||
const String GuiNavEditorCtrl::mTileMode = "TileMode";
|
||||
const String GuiNavEditorCtrl::mTestMode = "TestMode";
|
||||
|
||||
GuiNavEditorCtrl::GuiNavEditorCtrl()
|
||||
{
|
||||
mMode = mSelectMode;
|
||||
mIsDirty = false;
|
||||
mStartDragMousePoint = InvalidMousePoint;
|
||||
mMesh = NULL;
|
||||
mCurTile = mTile = -1;
|
||||
mPlayer = mCurPlayer = NULL;
|
||||
mSpawnClass = mSpawnDatablock = "";
|
||||
mLinkStart = Point3F::Max;
|
||||
mLink = mCurLink = -1;
|
||||
}
|
||||
|
||||
GuiNavEditorCtrl::~GuiNavEditorCtrl()
|
||||
|
|
@ -101,25 +89,21 @@ void GuiNavEditorCtrl::initPersistFields()
|
|||
docsURL;
|
||||
addField("isDirty", TypeBool, Offset(mIsDirty, GuiNavEditorCtrl));
|
||||
|
||||
addField("spawnClass", TypeRealString, Offset(mSpawnClass, GuiNavEditorCtrl),
|
||||
"Class of object to spawn in test mode.");
|
||||
addField("spawnDatablock", TypeRealString, Offset(mSpawnDatablock, GuiNavEditorCtrl),
|
||||
"Datablock to give new objects in test mode.");
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::onSleep()
|
||||
{
|
||||
Parent::onSleep();
|
||||
|
||||
//mMode = mSelectMode;
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::selectMesh(NavMesh *mesh)
|
||||
{
|
||||
mesh->setSelected(true);
|
||||
mMesh = mesh;
|
||||
|
||||
if (mTool)
|
||||
mTool->setActiveNavMesh(mMesh);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, selectMesh, void, (S32 id),,
|
||||
|
|
@ -141,125 +125,6 @@ DefineEngineMethod(GuiNavEditorCtrl, getMesh, S32, (),,
|
|||
return object->getMeshId();
|
||||
}
|
||||
|
||||
S32 GuiNavEditorCtrl::getPlayerId()
|
||||
{
|
||||
return mPlayer.isNull() ? 0 : mPlayer->getId();
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, getPlayer, S32, (),,
|
||||
"@brief Select a NavMesh object.")
|
||||
{
|
||||
return object->getPlayerId();
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::deselect()
|
||||
{
|
||||
if(!mMesh.isNull())
|
||||
mMesh->setSelected(false);
|
||||
mMesh = NULL;
|
||||
mPlayer = mCurPlayer = NULL;
|
||||
mCurTile = mTile = -1;
|
||||
mLinkStart = Point3F::Max;
|
||||
mLink = mCurLink = -1;
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, deselect, void, (),,
|
||||
"@brief Deselect whatever is currently selected in the editor.")
|
||||
{
|
||||
object->deselect();
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::deleteLink()
|
||||
{
|
||||
if(!mMesh.isNull() && mLink != -1)
|
||||
{
|
||||
mMesh->selectLink(mLink, false);
|
||||
mMesh->deleteLink(mLink);
|
||||
mLink = -1;
|
||||
Con::executef(this, "onLinkDeselected");
|
||||
}
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, deleteLink, void, (),,
|
||||
"@brief Delete the currently selected link.")
|
||||
{
|
||||
object->deleteLink();
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::setLinkFlags(const LinkData &d)
|
||||
{
|
||||
if(mMode == mLinkMode && !mMesh.isNull() && mLink != -1)
|
||||
{
|
||||
mMesh->setLinkFlags(mLink, d);
|
||||
}
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, setLinkFlags, void, (U32 flags),,
|
||||
"@Brief Set jump and drop properties of the selected link.")
|
||||
{
|
||||
object->setLinkFlags(LinkData(flags));
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::buildTile()
|
||||
{
|
||||
if(!mMesh.isNull() && mTile != -1)
|
||||
mMesh->buildTile(mTile);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, buildTile, void, (),,
|
||||
"@brief Build the currently selected tile.")
|
||||
{
|
||||
object->buildTile();
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::spawnPlayer(const Point3F &pos)
|
||||
{
|
||||
SceneObject *obj = (SceneObject*)Sim::spawnObject(mSpawnClass, mSpawnDatablock);
|
||||
if(obj)
|
||||
{
|
||||
MatrixF mat(true);
|
||||
mat.setPosition(pos);
|
||||
obj->setTransform(mat);
|
||||
SimObject* cleanup = Sim::findObject("MissionCleanup");
|
||||
if(cleanup)
|
||||
{
|
||||
SimGroup* missionCleanup = dynamic_cast<SimGroup*>(cleanup);
|
||||
missionCleanup->addObject(obj);
|
||||
}
|
||||
mPlayer = obj;
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(obj);
|
||||
if (asAIPlayer) //try direct
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected", Con::getIntArg(asAIPlayer->mLinkTypes.getFlags()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ShapeBase* sbo = dynamic_cast<ShapeBase*>(obj);
|
||||
if (sbo->getAIController())
|
||||
{
|
||||
if (sbo->getAIController()->mControllerData)
|
||||
Con::executef(this, "onPlayerSelected", Con::getIntArg(sbo->getAIController()->mControllerData->mLinkTypes.getFlags()));
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, spawnPlayer, void, (),,
|
||||
"@brief Spawn an AIPlayer at the centre of the screen.")
|
||||
{
|
||||
Point3F c;
|
||||
if(object->get3DCentre(c))
|
||||
object->spawnPlayer(c);
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::get3DCursor(GuiCursor *&cursor,
|
||||
bool &visible,
|
||||
const Gui3DMouseEvent &event_)
|
||||
|
|
@ -315,148 +180,12 @@ void GuiNavEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
|
|||
{
|
||||
mGizmo->on3DMouseDown(event);
|
||||
|
||||
if(!isFirstResponder())
|
||||
setFirstResponder();
|
||||
if (mTool)
|
||||
mTool->on3DMouseDown(event);
|
||||
|
||||
mouseLock();
|
||||
|
||||
// Construct a LineSegment from the camera position to 1000 meters away in
|
||||
// the direction clicked.
|
||||
// If that segment hits the terrain, truncate the ray to only be that length.
|
||||
|
||||
Point3F startPnt = event.pos;
|
||||
Point3F endPnt = event.pos + event.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
|
||||
U8 keys = Input::getModifierKeys();
|
||||
bool shift = keys & SI_LSHIFT;
|
||||
bool ctrl = keys & SI_LCTRL;
|
||||
|
||||
if(mMode == mLinkMode && !mMesh.isNull())
|
||||
{
|
||||
if(gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
{
|
||||
U32 link = mMesh->getLink(ri.point);
|
||||
if(link != -1)
|
||||
{
|
||||
if(mLink != -1)
|
||||
mMesh->selectLink(mLink, false);
|
||||
mMesh->selectLink(link, true, false);
|
||||
mLink = link;
|
||||
LinkData d = mMesh->getLinkFlags(mLink);
|
||||
Con::executef(this, "onLinkSelected", Con::getIntArg(d.getFlags()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mLink != -1)
|
||||
{
|
||||
mMesh->selectLink(mLink, false);
|
||||
mLink = -1;
|
||||
Con::executef(this, "onLinkDeselected");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mLinkStart != Point3F::Max)
|
||||
{
|
||||
mMesh->addLink(mLinkStart, ri.point);
|
||||
if(!shift)
|
||||
mLinkStart = Point3F::Max;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLinkStart = ri.point;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mMesh->selectLink(mLink, false);
|
||||
mLink = -1;
|
||||
Con::executef(this, "onLinkDeselected");
|
||||
}
|
||||
}
|
||||
|
||||
if(mMode == mTileMode && !mMesh.isNull())
|
||||
{
|
||||
if(gServerContainer.castRay(startPnt, endPnt, StaticShapeObjectType, &ri))
|
||||
{
|
||||
mTile = mMesh->getTile(ri.point);
|
||||
dd.clear();
|
||||
mMesh->renderTileData(dd, mTile);
|
||||
}
|
||||
}
|
||||
|
||||
if(mMode == mTestMode)
|
||||
{
|
||||
// Spawn new character
|
||||
if(ctrl)
|
||||
{
|
||||
if(gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
spawnPlayer(ri.point);
|
||||
}
|
||||
// Deselect character
|
||||
else if(shift)
|
||||
{
|
||||
mPlayer = NULL;
|
||||
Con::executef(this, "onPlayerDeselected");
|
||||
}
|
||||
// Select/move character
|
||||
else
|
||||
{
|
||||
if(gServerContainer.castRay(startPnt, endPnt, PlayerObjectType | VehicleObjectType, &ri))
|
||||
{
|
||||
if(ri.object)
|
||||
{
|
||||
mPlayer = ri.object;
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
|
||||
if (asAIPlayer) //try direct
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected", Con::getIntArg(asAIPlayer->mLinkTypes.getFlags()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
|
||||
if (sbo->getAIController())
|
||||
{
|
||||
if (sbo->getAIController()->mControllerData)
|
||||
Con::executef(this, "onPlayerSelected", Con::getIntArg(sbo->getAIController()->mControllerData->mLinkTypes.getFlags()));
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
}
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (!mPlayer.isNull() && gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
{
|
||||
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
|
||||
if (asAIPlayer) //try direct
|
||||
{
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
asAIPlayer->setPathDestination(ri.point);
|
||||
#else
|
||||
asAIPlayer->setMoveDestination(ri.point,false);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
|
||||
if (sbo->getAIController())
|
||||
{
|
||||
if (sbo->getAIController()->mControllerData)
|
||||
sbo->getAIController()->getNav()->setPathDestination(ri.point, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::on3DMouseUp(const Gui3DMouseEvent & event)
|
||||
|
|
@ -464,64 +193,18 @@ void GuiNavEditorCtrl::on3DMouseUp(const Gui3DMouseEvent & event)
|
|||
// Keep the Gizmo up to date.
|
||||
mGizmo->on3DMouseUp(event);
|
||||
|
||||
if (mTool)
|
||||
mTool->on3DMouseUp(event);
|
||||
|
||||
mouseUnlock();
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::on3DMouseMove(const Gui3DMouseEvent & event)
|
||||
{
|
||||
//if(mSelRiver != NULL && mSelNode != -1)
|
||||
//mGizmo->on3DMouseMove(event);
|
||||
if (mTool)
|
||||
mTool->on3DMouseMove(event);
|
||||
|
||||
Point3F startPnt = event.pos;
|
||||
Point3F endPnt = event.pos + event.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
|
||||
if(mMode == mLinkMode && !mMesh.isNull())
|
||||
{
|
||||
if(gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
{
|
||||
U32 link = mMesh->getLink(ri.point);
|
||||
if(link != -1)
|
||||
{
|
||||
if(link != mLink)
|
||||
{
|
||||
if(mCurLink != -1)
|
||||
mMesh->selectLink(mCurLink, false);
|
||||
mMesh->selectLink(link, true, true);
|
||||
}
|
||||
mCurLink = link;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mCurLink != mLink)
|
||||
mMesh->selectLink(mCurLink, false);
|
||||
mCurLink = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mMesh->selectLink(mCurLink, false);
|
||||
mCurLink = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Select a tile from our current NavMesh.
|
||||
if(mMode == mTileMode && !mMesh.isNull())
|
||||
{
|
||||
if(gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
mCurTile = mMesh->getTile(ri.point);
|
||||
else
|
||||
mCurTile = -1;
|
||||
}
|
||||
|
||||
if(mMode == mTestMode)
|
||||
{
|
||||
if(gServerContainer.castRay(startPnt, endPnt, PlayerObjectType | VehicleObjectType, &ri))
|
||||
mCurPlayer = ri.object;
|
||||
else
|
||||
mCurPlayer = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::on3DMouseDragged(const Gui3DMouseEvent & event)
|
||||
|
|
@ -549,6 +232,11 @@ void GuiNavEditorCtrl::on3DMouseLeave(const Gui3DMouseEvent & event)
|
|||
|
||||
void GuiNavEditorCtrl::updateGuiInfo()
|
||||
{
|
||||
if (mTool)
|
||||
{
|
||||
if (mTool->updateGuiInfo())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||
|
|
@ -559,22 +247,6 @@ void GuiNavEditorCtrl::onRender(Point2I offset, const RectI &updateRect)
|
|||
return;
|
||||
}
|
||||
|
||||
static void renderBoxOutline(const Box3F &box, const ColorI &col)
|
||||
{
|
||||
if(box != Box3F::Invalid)
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setCullMode(GFXCullNone);
|
||||
desc.setFillModeSolid();
|
||||
desc.setZReadWrite(true, false);
|
||||
desc.setBlend(true);
|
||||
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 20));
|
||||
desc.setFillModeWireframe();
|
||||
desc.setBlend(false);
|
||||
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 255));
|
||||
}
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::renderScene(const RectI & updateRect)
|
||||
{
|
||||
GFX->setStateBlock(mZDisableSB);
|
||||
|
|
@ -592,45 +264,15 @@ void GuiNavEditorCtrl::renderScene(const RectI & updateRect)
|
|||
Point3F camPos;
|
||||
mat.getColumn(3,&camPos);
|
||||
|
||||
if(mMode == mLinkMode)
|
||||
{
|
||||
if(mLinkStart != Point3F::Max)
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setBlend(false);
|
||||
desc.setZReadWrite(true ,true);
|
||||
MatrixF linkMat(true);
|
||||
linkMat.setPosition(mLinkStart);
|
||||
Point3F scale(0.8f, 0.8f, 0.8f);
|
||||
GFX->getDrawUtil()->drawTransform(desc, linkMat, &scale);
|
||||
}
|
||||
}
|
||||
|
||||
if(mMode == mTileMode && !mMesh.isNull())
|
||||
{
|
||||
renderBoxOutline(mMesh->getTileBox(mCurTile), ColorI::BLUE);
|
||||
renderBoxOutline(mMesh->getTileBox(mTile), ColorI::GREEN);
|
||||
if(Con::getBoolVariable("$Nav::Editor::renderVoxels", false)) dd.renderGroup(0);
|
||||
if(Con::getBoolVariable("$Nav::Editor::renderInput", false))
|
||||
{
|
||||
dd.depthMask(false);
|
||||
dd.renderGroup(1);
|
||||
dd.depthMask(true);
|
||||
}
|
||||
}
|
||||
|
||||
if(mMode == mTestMode)
|
||||
{
|
||||
if(!mCurPlayer.isNull())
|
||||
renderBoxOutline(mCurPlayer->getWorldBox(), ColorI::BLUE);
|
||||
if(!mPlayer.isNull())
|
||||
renderBoxOutline(mPlayer->getWorldBox(), ColorI::GREEN);
|
||||
}
|
||||
if (mTool)
|
||||
mTool->onRender3D();
|
||||
|
||||
duDebugDrawTorque d;
|
||||
if(!mMesh.isNull())
|
||||
if (!mMesh.isNull())
|
||||
{
|
||||
mMesh->renderLinks(d);
|
||||
d.render();
|
||||
d.immediateRender();
|
||||
}
|
||||
|
||||
// Now draw all the 2d stuff!
|
||||
GFX->setClipRect(updateRect);
|
||||
|
|
@ -652,15 +294,6 @@ bool GuiNavEditorCtrl::getStaticPos(const Gui3DMouseEvent & event, Point3F &tpos
|
|||
return hit;
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::setMode(String mode, bool sourceShortcut = false)
|
||||
{
|
||||
mMode = mode;
|
||||
Con::executef(this, "onModeSet", mode);
|
||||
|
||||
if(sourceShortcut)
|
||||
Con::executef(this, "paletteSync", mode);
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::submitUndo(const UTF8 *name)
|
||||
{
|
||||
// Grab the mission editor undo manager.
|
||||
|
|
@ -691,13 +324,41 @@ void GuiNavEditorCtrl::_prepRenderImage(SceneManager* sceneGraph, const SceneRen
|
|||
}*/
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, getMode, const char*, (), , "")
|
||||
void GuiNavEditorCtrl::setActiveTool(NavMeshTool* tool)
|
||||
{
|
||||
return object->getMode();
|
||||
if (mTool)
|
||||
{
|
||||
mTool->onDeactivated();
|
||||
}
|
||||
|
||||
mTool = tool;
|
||||
|
||||
if (mTool)
|
||||
{
|
||||
mTool->setActiveEditor(this);
|
||||
mTool->setActiveNavMesh(mMesh);
|
||||
mTool->onActivated(mLastEvent);
|
||||
}
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, setMode, void, (String mode),, "setMode(String mode)")
|
||||
void GuiNavEditorCtrl::setDrawMode(S32 id)
|
||||
{
|
||||
object->setMode(mode);
|
||||
if (mMesh.isNull())
|
||||
return;
|
||||
|
||||
mMesh->setDrawMode((NavMesh::DrawMode)id);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, setDrawMode, void, (S32 id), ,
|
||||
"@brief Deselect whatever is currently selected in the editor.")
|
||||
{
|
||||
object->setDrawMode(id);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, setActiveTool, void, (const char* toolName), , "( NavMeshTool tool )")
|
||||
{
|
||||
NavMeshTool* tool = dynamic_cast<NavMeshTool*>(Sim::findObject(toolName));
|
||||
object->setActiveTool(tool);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@
|
|||
#include "gui/worldEditor/gizmo.h"
|
||||
#endif
|
||||
|
||||
//#ifndef _NAVMESH_TOOL_H_
|
||||
//#include "navigation/navMeshTool.h"
|
||||
//#endif
|
||||
|
||||
#include "navMesh.h"
|
||||
#include "T3D/aiPlayer.h"
|
||||
|
||||
|
|
@ -41,6 +45,7 @@ struct ObjectRenderInst;
|
|||
class SceneManager;
|
||||
class SceneRenderState;
|
||||
class BaseMatInstance;
|
||||
class NavMeshTool;
|
||||
|
||||
class GuiNavEditorCtrl : public EditTSCtrl
|
||||
{
|
||||
|
|
@ -51,7 +56,6 @@ public:
|
|||
static const String mSelectMode;
|
||||
static const String mLinkMode;
|
||||
static const String mCoverMode;
|
||||
static const String mTileMode;
|
||||
static const String mTestMode;
|
||||
|
||||
GuiNavEditorCtrl();
|
||||
|
|
@ -96,26 +100,14 @@ public:
|
|||
|
||||
bool getStaticPos(const Gui3DMouseEvent & event, Point3F &tpos);
|
||||
|
||||
void setMode(String mode, bool sourceShortcut);
|
||||
String getMode() { return mMode; }
|
||||
|
||||
void selectMesh(NavMesh *mesh);
|
||||
void deselect();
|
||||
|
||||
S32 getMeshId();
|
||||
S32 getPlayerId();
|
||||
|
||||
String mSpawnClass;
|
||||
String mSpawnDatablock;
|
||||
|
||||
void deleteLink();
|
||||
void setLinkFlags(const LinkData &d);
|
||||
|
||||
void buildTile();
|
||||
|
||||
void spawnPlayer(const Point3F &pos);
|
||||
|
||||
/// @}
|
||||
void setActiveTool(NavMeshTool* tool);
|
||||
|
||||
void setDrawMode(S32 id);
|
||||
|
||||
protected:
|
||||
|
||||
|
|
@ -128,38 +120,21 @@ protected:
|
|||
|
||||
bool mIsDirty;
|
||||
|
||||
String mMode;
|
||||
|
||||
/// Currently-selected NavMesh.
|
||||
SimObjectPtr<NavMesh> mMesh;
|
||||
|
||||
/// @name Link mode
|
||||
/// @{
|
||||
|
||||
Point3F mLinkStart;
|
||||
S32 mCurLink;
|
||||
S32 mLink;
|
||||
/// The active tool in used by the editor.
|
||||
SimObjectPtr<NavMeshTool> mTool;
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Tile mode
|
||||
/// @{
|
||||
|
||||
S32 mCurTile;
|
||||
S32 mTile;
|
||||
|
||||
duDebugDrawTorque dd;
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Test mode
|
||||
/// @{
|
||||
|
||||
SimObjectPtr<SceneObject> mPlayer;
|
||||
SimObjectPtr<SceneObject> mCurPlayer;
|
||||
|
||||
/// @}
|
||||
|
||||
Gui3DMouseEvent mLastMouseEvent;
|
||||
|
||||
#define InvalidMousePoint Point2I(-100,-100)
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ public:
|
|||
U32 mMergeRegionArea;
|
||||
F32 mTileSize;
|
||||
U32 mMaxPolysPerTile;
|
||||
duDebugDrawTorque mDbgDraw;
|
||||
/// @}
|
||||
|
||||
/// @name Water
|
||||
|
|
@ -112,6 +113,29 @@ public:
|
|||
Impassable
|
||||
};
|
||||
|
||||
enum DrawMode
|
||||
{
|
||||
DRAWMODE_NAVMESH,
|
||||
DRAWMODE_NAVMESH_TRANS,
|
||||
DRAWMODE_NAVMESH_BVTREE,
|
||||
DRAWMODE_NAVMESH_NODES,
|
||||
DRAWMODE_NAVMESH_PORTALS,
|
||||
DRAWMODE_NAVMESH_INVIS,
|
||||
DRAWMODE_MESH,
|
||||
DRAWMODE_VOXELS,
|
||||
DRAWMODE_VOXELS_WALKABLE,
|
||||
DRAWMODE_COMPACT,
|
||||
DRAWMODE_COMPACT_DISTANCE,
|
||||
DRAWMODE_COMPACT_REGIONS,
|
||||
DRAWMODE_REGION_CONNECTIONS,
|
||||
DRAWMODE_RAW_CONTOURS,
|
||||
DRAWMODE_BOTH_CONTOURS,
|
||||
DRAWMODE_CONTOURS,
|
||||
DRAWMODE_POLYMESH,
|
||||
DRAWMODE_POLYMESH_DETAIL,
|
||||
MAX_DRAWMODE
|
||||
};
|
||||
|
||||
WaterMethod mWaterMethod;
|
||||
/// @}
|
||||
|
||||
|
|
@ -127,7 +151,7 @@ public:
|
|||
/// @{
|
||||
|
||||
/// Add an off-mesh link.
|
||||
S32 addLink(const Point3F &from, const Point3F &to, U32 flags = 0);
|
||||
S32 addLink(const Point3F &from, const Point3F &to, bool biDir, F32 rad, U32 flags = 0);
|
||||
|
||||
/// Get the ID of the off-mesh link near the point.
|
||||
S32 getLink(const Point3F &pos);
|
||||
|
|
@ -144,15 +168,27 @@ public:
|
|||
/// Get the flags used by a link.
|
||||
LinkData getLinkFlags(U32 idx);
|
||||
|
||||
bool getLinkDir(U32 idx);
|
||||
|
||||
F32 getLinkRadius(U32 idx);
|
||||
|
||||
void setLinkDir(U32 idx, bool biDir);
|
||||
|
||||
void setLinkRadius(U32 idx, F32 rad);
|
||||
|
||||
/// Set flags used by a link.
|
||||
void setLinkFlags(U32 idx, const LinkData &d);
|
||||
|
||||
void setDrawMode(DrawMode mode) { m_drawMode = mode; setMaskBits(LoadFlag); }
|
||||
|
||||
/// Set the selected state of a link.
|
||||
void selectLink(U32 idx, bool select, bool hover = true);
|
||||
|
||||
/// Delete the selected link.
|
||||
void deleteLink(U32 idx);
|
||||
|
||||
dtNavMeshQuery* getNavMeshQuery() { return mQuery; }
|
||||
|
||||
/// @}
|
||||
|
||||
/// Should small characters use this mesh?
|
||||
|
|
@ -230,6 +266,7 @@ public:
|
|||
void prepRenderImage(SceneRenderState *state) override;
|
||||
void render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat);
|
||||
void renderLinks(duDebugDraw &dd);
|
||||
void renderSearch(duDebugDraw& dd);
|
||||
void renderTileData(duDebugDrawTorque &dd, U32 tile);
|
||||
|
||||
bool mAlwaysRender;
|
||||
|
|
@ -249,15 +286,13 @@ public:
|
|||
|
||||
void inspectPostApply() override;
|
||||
|
||||
void createNewFile();
|
||||
|
||||
protected:
|
||||
|
||||
dtNavMesh const* getNavMesh() { return nm; }
|
||||
|
||||
private:
|
||||
/// Generates a navigation mesh for the collection of objects in this
|
||||
/// mesh. Returns true if successful. Stores the created mesh in tnm.
|
||||
bool generateMesh();
|
||||
|
||||
/// Builds the next tile in the dirty list.
|
||||
void buildNextTile();
|
||||
|
||||
|
|
@ -275,56 +310,45 @@ private:
|
|||
/// Recast min and max points.
|
||||
F32 bmin[3], bmax[3];
|
||||
/// Default constructor.
|
||||
Tile() : box(Box3F::Invalid), x(0), y(0)
|
||||
Tile() : box(Box3F::Invalid), x(0), y(0), chf(0), solid(0), cset(0), pmesh(0), dmesh(0), triareas(nullptr)
|
||||
{
|
||||
bmin[0] = bmin[1] = bmin[2] = bmax[0] = bmax[1] = bmax[2] = 0.0f;
|
||||
}
|
||||
/// Value constructor.
|
||||
Tile(const Box3F &b, U32 _x, U32 _y, const F32 *min, const F32 *max)
|
||||
: box(b), x(_x), y(_y)
|
||||
: box(b), x(_x), y(_y), chf(0), solid(0), cset(0), pmesh(0), dmesh(0), triareas(nullptr)
|
||||
{
|
||||
rcVcopy(bmin, min);
|
||||
rcVcopy(bmax, max);
|
||||
}
|
||||
};
|
||||
|
||||
/// Intermediate data for tile creation.
|
||||
struct TileData {
|
||||
RecastPolyList geom;
|
||||
rcHeightfield *hf;
|
||||
rcCompactHeightfield *chf;
|
||||
rcContourSet *cs;
|
||||
rcPolyMesh *pm;
|
||||
rcPolyMeshDetail *pmd;
|
||||
TileData()
|
||||
~Tile()
|
||||
{
|
||||
hf = NULL;
|
||||
chf = NULL;
|
||||
cs = NULL;
|
||||
pm = NULL;
|
||||
pmd = NULL;
|
||||
}
|
||||
void freeAll()
|
||||
{
|
||||
geom.clear();
|
||||
rcFreeHeightField(hf);
|
||||
rcFreeCompactHeightfield(chf);
|
||||
rcFreeContourSet(cs);
|
||||
rcFreePolyMesh(pm);
|
||||
rcFreePolyMeshDetail(pmd);
|
||||
}
|
||||
~TileData()
|
||||
{
|
||||
freeAll();
|
||||
if (chf)
|
||||
delete chf;
|
||||
if (cset)
|
||||
delete cset;
|
||||
if (solid)
|
||||
delete solid;
|
||||
if (pmesh)
|
||||
delete pmesh;
|
||||
if (dmesh)
|
||||
delete dmesh;
|
||||
if (triareas)
|
||||
delete[] triareas;
|
||||
}
|
||||
|
||||
unsigned char* triareas;
|
||||
rcCompactHeightfield* chf;
|
||||
rcHeightfield* solid;
|
||||
rcContourSet* cset;
|
||||
rcPolyMesh* pmesh;
|
||||
rcPolyMeshDetail* dmesh;
|
||||
};
|
||||
|
||||
/// List of tiles.
|
||||
Vector<Tile> mTiles;
|
||||
|
||||
/// List of tile intermediate data.
|
||||
Vector<TileData> mTileData;
|
||||
|
||||
/// List of indices to the tile array which are dirty.
|
||||
Vector<U32> mDirtyTiles;
|
||||
|
||||
|
|
@ -332,7 +356,7 @@ private:
|
|||
void updateTiles(bool dirty = false);
|
||||
|
||||
/// Generates navmesh data for a single tile.
|
||||
unsigned char *buildTileData(const Tile &tile, TileData &data, U32 &dataSize);
|
||||
unsigned char *buildTileData(const Tile &tile, U32 &dataSize);
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
@ -363,19 +387,9 @@ private:
|
|||
|
||||
/// @}
|
||||
|
||||
/// @name Intermediate data
|
||||
/// @{
|
||||
|
||||
/// Config struct.
|
||||
rcConfig cfg;
|
||||
|
||||
/// Updates our config from console members.
|
||||
void updateConfig();
|
||||
|
||||
dtNavMesh *nm;
|
||||
rcContext *ctx;
|
||||
|
||||
/// @}
|
||||
dtNavMeshQuery* mQuery;
|
||||
|
||||
/// @name Cover
|
||||
/// @{
|
||||
|
|
@ -408,8 +422,6 @@ private:
|
|||
/// @name Rendering
|
||||
/// @{
|
||||
|
||||
duDebugDrawTorque mDbgDraw;
|
||||
|
||||
void renderToDrawer();
|
||||
|
||||
/// @}
|
||||
|
|
@ -419,6 +431,21 @@ private:
|
|||
|
||||
/// Use this object to manage update events.
|
||||
static SimObjectPtr<EventManager> smEventManager;
|
||||
|
||||
protected:
|
||||
RecastPolyList* m_geo;
|
||||
unsigned char* m_triareas;
|
||||
rcHeightfield* m_solid;
|
||||
rcCompactHeightfield* m_chf;
|
||||
rcContourSet* m_cset;
|
||||
rcPolyMesh* m_pmesh;
|
||||
rcPolyMeshDetail* m_dmesh;
|
||||
rcConfig m_cfg;
|
||||
DrawMode m_drawMode;
|
||||
U32 mWaterVertStart;
|
||||
U32 mWaterTriStart;
|
||||
|
||||
void cleanup();
|
||||
};
|
||||
|
||||
typedef NavMesh::WaterMethod NavMeshWaterMethod;
|
||||
|
|
|
|||
40
Engine/source/navigation/navMeshTool.cpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
#include "platform/platform.h"
|
||||
#include "navigation/navMeshTool.h"
|
||||
#ifdef TORQUE_TOOLS
|
||||
#include "util/undo.h"
|
||||
#include "math/mMath.h"
|
||||
#include "math/mathUtils.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(NavMeshTool);
|
||||
|
||||
ConsoleDocClass(NavMeshTool,
|
||||
"@brief Base class for NavMesh Editor specific tools\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void NavMeshTool::_submitUndo(UndoAction* action)
|
||||
{
|
||||
AssertFatal(action, "NavMeshTool::_submitUndo() - No undo action!");
|
||||
|
||||
// Grab the mission editor undo manager.
|
||||
UndoManager* undoMan = NULL;
|
||||
if (!Sim::findObject("EUndoManager", undoMan))
|
||||
{
|
||||
Con::errorf("NavMeshTool::_submitUndo() - EUndoManager not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
undoMan->addAction(action);
|
||||
}
|
||||
|
||||
NavMeshTool::NavMeshTool()
|
||||
: mNavMesh(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
NavMeshTool::~NavMeshTool()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
58
Engine/source/navigation/navMeshTool.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#pragma once
|
||||
#ifndef _NAVMESH_TOOL_H_
|
||||
#define _NAVMESH_TOOL_H_
|
||||
#ifdef TORQUE_TOOLS
|
||||
#ifndef _SIMBASE_H_
|
||||
#include "console/simBase.h"
|
||||
#endif
|
||||
#ifndef _GUITYPES_H_
|
||||
#include "gui/core/guiTypes.h"
|
||||
#endif
|
||||
#ifndef _NAVMESH_H_
|
||||
#include "navigation/navMesh.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GUINAVEDITORCTRL_H_
|
||||
#include "navigation/guiNavEditorCtrl.h"
|
||||
#endif
|
||||
|
||||
class UndoAction;
|
||||
|
||||
class NavMeshTool : public SimObject
|
||||
{
|
||||
typedef SimObject Parent;
|
||||
protected:
|
||||
SimObjectPtr<NavMesh> mNavMesh;
|
||||
SimObjectPtr<GuiNavEditorCtrl> mCurEditor;
|
||||
|
||||
void _submitUndo(UndoAction* action);
|
||||
|
||||
public:
|
||||
|
||||
NavMeshTool();
|
||||
virtual ~NavMeshTool();
|
||||
|
||||
DECLARE_CONOBJECT(NavMeshTool);
|
||||
|
||||
virtual void setActiveNavMesh(NavMesh* nav_mesh) { mNavMesh = nav_mesh; }
|
||||
virtual void setActiveEditor(GuiNavEditorCtrl* nav_editor) { mCurEditor = nav_editor; }
|
||||
|
||||
virtual void onActivated(const Gui3DMouseEvent& lastEvent) {}
|
||||
virtual void onDeactivated() {}
|
||||
|
||||
virtual void on3DMouseDown(const Gui3DMouseEvent& evt) {}
|
||||
virtual void on3DMouseUp(const Gui3DMouseEvent& evt) {}
|
||||
virtual void on3DMouseMove(const Gui3DMouseEvent& evt) {}
|
||||
virtual void on3DMouseDragged(const Gui3DMouseEvent& evt) {}
|
||||
virtual void on3DMouseEnter(const Gui3DMouseEvent& evt) {}
|
||||
virtual void on3DMouseLeave(const Gui3DMouseEvent& evt) {}
|
||||
virtual bool onMouseWheel(const GuiEvent& evt) { return false; }
|
||||
virtual void onRender3D() {}
|
||||
virtual void onRender2D() {}
|
||||
virtual void updateGizmo() {}
|
||||
virtual bool updateGuiInfo() { return false; }
|
||||
virtual void onUndoAction() {}
|
||||
|
||||
};
|
||||
#endif
|
||||
#endif // !_NAVMESH_TOOL_H_
|
||||
40
Engine/source/navigation/navMeshTools/coverTool.cpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#include "coverTool.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(CoverTool);
|
||||
|
||||
CoverTool::CoverTool()
|
||||
{
|
||||
}
|
||||
|
||||
void CoverTool::onActivated(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
Con::executef(this, "onActivated");
|
||||
}
|
||||
|
||||
void CoverTool::onDeactivated()
|
||||
{
|
||||
Con::executef(this, "onDeactivated");
|
||||
}
|
||||
|
||||
void CoverTool::on3DMouseDown(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
}
|
||||
|
||||
void CoverTool::on3DMouseMove(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
}
|
||||
|
||||
void CoverTool::onRender3D()
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
}
|
||||
|
||||
bool CoverTool::updateGuiInfo()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
33
Engine/source/navigation/navMeshTools/coverTool.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef _COVERTOOL_H_
|
||||
#define _COVERTOOL_H_
|
||||
|
||||
#ifndef _NAVMESH_TOOL_H_
|
||||
#include "navigation/navMeshTool.h"
|
||||
#endif
|
||||
|
||||
#ifndef _NAVPATH_H_
|
||||
#include "navigation/navPath.h"
|
||||
#endif
|
||||
|
||||
class CoverTool : public NavMeshTool
|
||||
{
|
||||
typedef NavMeshTool Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(CoverTool);
|
||||
|
||||
CoverTool();
|
||||
|
||||
virtual ~CoverTool() {}
|
||||
|
||||
void onActivated(const Gui3DMouseEvent& evt) override;
|
||||
void onDeactivated() override;
|
||||
|
||||
void on3DMouseDown(const Gui3DMouseEvent& evt) override;
|
||||
void on3DMouseMove(const Gui3DMouseEvent& evt) override;
|
||||
void onRender3D() override;
|
||||
|
||||
bool updateGuiInfo() override;
|
||||
};
|
||||
|
||||
#endif // !_COVERTOOL_H_
|
||||
|
||||
121
Engine/source/navigation/navMeshTools/navMeshSelectTool.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
#include "navMeshSelectTool.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(NavMeshSelectTool);
|
||||
|
||||
static void renderBoxOutline(const Box3F& box, const ColorI& col)
|
||||
{
|
||||
if (box != Box3F::Invalid)
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setCullMode(GFXCullNone);
|
||||
desc.setFillModeSolid();
|
||||
desc.setZReadWrite(true, false);
|
||||
desc.setBlend(true);
|
||||
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 20));
|
||||
desc.setFillModeWireframe();
|
||||
desc.setBlend(false);
|
||||
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 255));
|
||||
}
|
||||
}
|
||||
|
||||
NavMeshSelectTool::NavMeshSelectTool()
|
||||
{
|
||||
mCurMesh = NULL;
|
||||
}
|
||||
|
||||
void NavMeshSelectTool::onActivated(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
Con::executef(this, "onActivated");
|
||||
}
|
||||
|
||||
void NavMeshSelectTool::onDeactivated()
|
||||
{
|
||||
Con::executef(this, "onDeactivated");
|
||||
}
|
||||
|
||||
void NavMeshSelectTool::on3DMouseDown(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
if (mCurEditor.isNull())
|
||||
return;
|
||||
|
||||
Point3F startPnt = evt.pos;
|
||||
Point3F endPnt = evt.pos + evt.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
if (gServerContainer.collideBox(startPnt, endPnt, MarkerObjectType, &ri))
|
||||
{
|
||||
if (!ri.object)
|
||||
return;
|
||||
|
||||
NavMesh* selNavMesh = dynamic_cast<NavMesh*>(ri.object);
|
||||
if (selNavMesh)
|
||||
{
|
||||
mCurEditor->selectMesh(selNavMesh);
|
||||
mSelMesh = selNavMesh;
|
||||
Con::executef(this, "onNavMeshSelected");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NavMeshSelectTool::on3DMouseMove(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
if (mCurEditor.isNull())
|
||||
return;
|
||||
|
||||
Point3F startPnt = evt.pos;
|
||||
Point3F endPnt = evt.pos + evt.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
if (gServerContainer.collideBox(startPnt, endPnt, MarkerObjectType, &ri))
|
||||
{
|
||||
NavMesh* selNavMesh = dynamic_cast<NavMesh*>(ri.object);
|
||||
if (selNavMesh)
|
||||
{
|
||||
mCurMesh = selNavMesh;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurMesh = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurMesh = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void NavMeshSelectTool::onRender3D()
|
||||
{
|
||||
if (!mCurMesh.isNull())
|
||||
renderBoxOutline(mCurMesh->getWorldBox(), ColorI::LIGHT);
|
||||
if (!mSelMesh.isNull())
|
||||
renderBoxOutline(mSelMesh->getWorldBox(), ColorI::LIGHT);
|
||||
}
|
||||
|
||||
bool NavMeshSelectTool::updateGuiInfo()
|
||||
{
|
||||
SimObject* statusbar;
|
||||
Sim::findObject("EditorGuiStatusBar", statusbar);
|
||||
|
||||
GuiTextCtrl* selectionBar;
|
||||
Sim::findObject("EWorldEditorStatusBarSelection", selectionBar);
|
||||
|
||||
String text;
|
||||
text = "LMB To select a NavMesh.";
|
||||
|
||||
if (statusbar)
|
||||
Con::executef(statusbar, "setInfo", text.c_str());
|
||||
|
||||
text = "";
|
||||
if(mSelMesh)
|
||||
text = String::ToString("NavMesh Selected: %d", mSelMesh->getId());
|
||||
|
||||
if (selectionBar)
|
||||
selectionBar->setText(text);
|
||||
|
||||
return true;
|
||||
}
|
||||
32
Engine/source/navigation/navMeshTools/navMeshSelectTool.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef _NAVMESHSELECTTOOL_H_
|
||||
#define _NAVMESHSELECTTOOL_H_
|
||||
|
||||
|
||||
#ifndef _NAVMESH_TOOL_H_
|
||||
#include "navigation/navMeshTool.h"
|
||||
#endif
|
||||
|
||||
class NavMeshSelectTool : public NavMeshTool
|
||||
{
|
||||
typedef NavMeshTool Parent;
|
||||
protected:
|
||||
SimObjectPtr<NavMesh> mCurMesh;
|
||||
SimObjectPtr<NavMesh> mSelMesh;
|
||||
public:
|
||||
DECLARE_CONOBJECT(NavMeshSelectTool);
|
||||
|
||||
NavMeshSelectTool();
|
||||
virtual ~NavMeshSelectTool() {}
|
||||
|
||||
void setActiveNavMesh(NavMesh* nav_mesh) { mNavMesh = nav_mesh; mSelMesh = nav_mesh; }
|
||||
void onActivated(const Gui3DMouseEvent& evt) override;
|
||||
void onDeactivated() override;
|
||||
|
||||
void on3DMouseDown(const Gui3DMouseEvent& evt) override;
|
||||
void on3DMouseMove(const Gui3DMouseEvent& evt) override;
|
||||
void onRender3D() override;
|
||||
|
||||
bool updateGuiInfo() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
426
Engine/source/navigation/navMeshTools/navMeshTestTool.cpp
Normal file
|
|
@ -0,0 +1,426 @@
|
|||
#include "navMeshTestTool.h"
|
||||
#include "navigation/guiNavEditorCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "scene/sceneManager.h"
|
||||
#include "math/mathUtils.h"
|
||||
#include "T3D/gameBase/gameConnection.h"
|
||||
#include "T3D/AI/AIController.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(NavMeshTestTool);
|
||||
|
||||
//// take control
|
||||
// GameConnection* conn = GameConnection::getConnectionToServer();
|
||||
// if (conn)
|
||||
// conn->setControlObject(static_cast<GameBase*>(obj));
|
||||
//}
|
||||
|
||||
static void renderBoxOutline(const Box3F& box, const ColorI& col)
|
||||
{
|
||||
if (box != Box3F::Invalid)
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setCullMode(GFXCullNone);
|
||||
desc.setFillModeSolid();
|
||||
desc.setZReadWrite(true, false);
|
||||
desc.setBlend(true);
|
||||
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 20));
|
||||
desc.setFillModeWireframe();
|
||||
desc.setBlend(false);
|
||||
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 255));
|
||||
}
|
||||
}
|
||||
|
||||
void NavMeshTestTool::spawnPlayer(const Point3F& position)
|
||||
{
|
||||
if (mSpawnClass.isEmpty() || mSpawnDatablock.isEmpty())
|
||||
{
|
||||
Con::warnf("NavMeshTestTool::spawnPlayer - spawn class/datablock not set!");
|
||||
return;
|
||||
}
|
||||
|
||||
SimObject* spawned = Sim::spawnObject(mSpawnClass, mSpawnDatablock);
|
||||
SceneObject* obj = dynamic_cast<SceneObject*>(spawned);
|
||||
|
||||
if (!obj)
|
||||
{
|
||||
Con::warnf("NavMeshTestTool::spawnPlayer - spawn failed or not a SceneObject");
|
||||
if (spawned)
|
||||
spawned->deleteObject();
|
||||
return;
|
||||
}
|
||||
|
||||
obj->setPosition(position);
|
||||
SimObject* cleanup = Sim::findObject("MissionCleanup");
|
||||
if (cleanup)
|
||||
{
|
||||
SimGroup* missionCleanup = dynamic_cast<SimGroup*>(cleanup);
|
||||
missionCleanup->addObject(obj);
|
||||
}
|
||||
mPlayer = obj;
|
||||
Con::executef(this, "onPlayerSpawned", obj->getIdString());
|
||||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
|
||||
if (asAIPlayer)
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
}
|
||||
else
|
||||
{
|
||||
ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
|
||||
if (sbo && sbo->getAIController() && sbo->getAIController()->mControllerData)
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
}
|
||||
else
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
}
|
||||
}
|
||||
#else
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
#endif
|
||||
}
|
||||
|
||||
void NavMeshTestTool::drawAgent(duDebugDrawTorque& dd, const F32* pos, F32 r, F32 h, F32 c, const U32 col)
|
||||
{
|
||||
dd.depthMask(false);
|
||||
|
||||
// Agent dimensions.
|
||||
duDebugDrawCylinderWire(&dd, pos[0] - r, pos[1] + 0.02f, pos[2] - r, pos[0] + r, pos[1] + h, pos[2] + r, col, 2.0f);
|
||||
|
||||
duDebugDrawCircle(&dd, pos[0], pos[1] + c, pos[2], r, duRGBA(0, 0, 0, 64), 1.0f);
|
||||
|
||||
U32 colb = duRGBA(0, 0, 0, 196);
|
||||
dd.begin(DU_DRAW_LINES);
|
||||
dd.vertex(pos[0], pos[1] - c, pos[2], colb);
|
||||
dd.vertex(pos[0], pos[1] + c, pos[2], colb);
|
||||
dd.vertex(pos[0] - r / 2, pos[1] + 0.02f, pos[2], colb);
|
||||
dd.vertex(pos[0] + r / 2, pos[1] + 0.02f, pos[2], colb);
|
||||
dd.vertex(pos[0], pos[1] + 0.02f, pos[2] - r / 2, colb);
|
||||
dd.vertex(pos[0], pos[1] + 0.02f, pos[2] + r / 2, colb);
|
||||
dd.end();
|
||||
|
||||
dd.depthMask(true);
|
||||
}
|
||||
|
||||
NavMeshTestTool::NavMeshTestTool()
|
||||
{
|
||||
mSpawnClass = String::EmptyString;
|
||||
mSpawnDatablock = String::EmptyString;
|
||||
mPlayer = NULL;
|
||||
mCurPlayer = NULL;
|
||||
|
||||
mFollowObject = NULL;
|
||||
mCurFollowObject = NULL;
|
||||
|
||||
mPathStart = Point3F::Max;
|
||||
mPathEnd = Point3F::Max;
|
||||
|
||||
mTestPath = NULL;
|
||||
|
||||
mLinkTypes = LinkData(AllFlags);
|
||||
mFilter.setIncludeFlags(mLinkTypes.getFlags());
|
||||
mFilter.setExcludeFlags(0);
|
||||
mSelectFollow = false;
|
||||
}
|
||||
|
||||
void NavMeshTestTool::onActivated(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
mSelectFollow = false;
|
||||
Con::executef(this, "onActivated");
|
||||
}
|
||||
|
||||
void NavMeshTestTool::onDeactivated()
|
||||
{
|
||||
if (mTestPath != NULL) {
|
||||
mTestPath->deleteObject();
|
||||
mTestPath = NULL;
|
||||
}
|
||||
|
||||
if (mPlayer != NULL)
|
||||
{
|
||||
mPlayer = NULL;
|
||||
Con::executef(this, "onPlayerDeselected");
|
||||
}
|
||||
|
||||
mSelectFollow = false;
|
||||
|
||||
Con::executef(this, "onDeactivated");
|
||||
}
|
||||
|
||||
void NavMeshTestTool::on3DMouseDown(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
|
||||
Point3F startPnt = evt.pos;
|
||||
Point3F endPnt = evt.pos + evt.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
bool shift = evt.modifier & SI_LSHIFT;
|
||||
bool ctrl = evt.modifier & SI_LCTRL;
|
||||
|
||||
if (ctrl)
|
||||
{
|
||||
if (gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
{
|
||||
spawnPlayer(ri.point);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (shift)
|
||||
{
|
||||
mPlayer = NULL;
|
||||
Con::executef(this, "onPlayerDeselected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gServerContainer.castRay(startPnt, endPnt, PlayerObjectType | VehicleObjectType, &ri))
|
||||
{
|
||||
if (!ri.object)
|
||||
return;
|
||||
if (mSelectFollow)
|
||||
{
|
||||
mFollowObject = ri.object;
|
||||
Con::executef(this, "onFollowSelected");
|
||||
mSelectFollow = false;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
mPlayer = ri.object;
|
||||
}
|
||||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
|
||||
if (asAIPlayer)
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
}
|
||||
else
|
||||
{
|
||||
ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
|
||||
if (sbo && sbo->getAIController() && sbo->getAIController()->mControllerData)
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
}
|
||||
else
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
}
|
||||
}
|
||||
#else
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
#endif
|
||||
}
|
||||
else if (gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
{
|
||||
if (mPlayer.isNull())
|
||||
{
|
||||
if (mPathStart != Point3F::Max && mPathEnd != Point3F::Max) // start a new path.
|
||||
{
|
||||
mPathStart = Point3F::Max;
|
||||
mPathEnd = Point3F::Max;
|
||||
}
|
||||
|
||||
if (mPathStart != Point3F::Max)
|
||||
{
|
||||
mPathEnd = ri.point;
|
||||
mTestPath = new NavPath();
|
||||
|
||||
mTestPath->mMesh = mNavMesh;
|
||||
mTestPath->mFrom = mPathStart;
|
||||
mTestPath->mTo = mPathEnd;
|
||||
mTestPath->mFromSet = mTestPath->mToSet = true;
|
||||
mTestPath->mAlwaysRender = true;
|
||||
mTestPath->mLinkTypes = mLinkTypes;
|
||||
mTestPath->mFilter = mFilter;
|
||||
mTestPath->mXray = true;
|
||||
// Paths plan automatically upon being registered.
|
||||
if (!mTestPath->registerObject())
|
||||
{
|
||||
delete mTestPath;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mPathStart = ri.point;
|
||||
if (mTestPath != NULL) {
|
||||
mTestPath->deleteObject();
|
||||
mTestPath = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
|
||||
if (asAIPlayer) //try direct
|
||||
{
|
||||
asAIPlayer->setPathDestination(ri.point);
|
||||
mPathStart = mPlayer->getPosition();
|
||||
mPathEnd = ri.point;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
|
||||
if (sbo->getAIController())
|
||||
{
|
||||
if (sbo->getAIController()->mControllerData)
|
||||
{
|
||||
sbo->getAIController()->getNav()->setPathDestination(ri.point, true);
|
||||
mPathStart = mPlayer->getPosition();
|
||||
mPathEnd = ri.point;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NavMeshTestTool::on3DMouseMove(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
|
||||
Point3F startPnt = evt.pos;
|
||||
Point3F endPnt = evt.pos + evt.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
|
||||
if (gServerContainer.castRay(startPnt, endPnt, PlayerObjectType | VehicleObjectType, &ri))
|
||||
{
|
||||
if (mSelectFollow)
|
||||
mCurFollowObject = ri.object;
|
||||
else
|
||||
mCurPlayer = ri.object;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurFollowObject = NULL;
|
||||
mCurPlayer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void NavMeshTestTool::onRender3D()
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
|
||||
static const U32 startCol = duRGBA(128, 25, 0, 192);
|
||||
static const U32 endCol = duRGBA(51, 102, 0, 129);
|
||||
|
||||
const F32 agentRadius = mNavMesh->mWalkableRadius;
|
||||
const F32 agentHeight = mNavMesh->mWalkableHeight;
|
||||
const F32 agentClimb = mNavMesh->mWalkableClimb;
|
||||
|
||||
duDebugDrawTorque dd;
|
||||
dd.depthMask(false);
|
||||
if (mPathStart != Point3F::Max)
|
||||
{
|
||||
drawAgent(dd, DTStoRC(mPathStart), agentRadius, agentHeight, agentClimb, startCol);
|
||||
}
|
||||
|
||||
if (mPathEnd != Point3F::Max)
|
||||
{
|
||||
drawAgent(dd, DTStoRC(mPathEnd), agentRadius, agentHeight, agentClimb, endCol);
|
||||
}
|
||||
dd.depthMask(true);
|
||||
|
||||
mNavMesh->renderSearch(dd);
|
||||
|
||||
dd.immediateRender();
|
||||
|
||||
if (!mCurFollowObject.isNull())
|
||||
renderBoxOutline(mCurFollowObject->getWorldBox(), ColorI::LIGHT);
|
||||
if (!mCurPlayer.isNull())
|
||||
renderBoxOutline(mCurPlayer->getWorldBox(), ColorI::BLUE);
|
||||
if (!mPlayer.isNull())
|
||||
renderBoxOutline(mPlayer->getWorldBox(), ColorI::GREEN);
|
||||
if (!mFollowObject.isNull())
|
||||
renderBoxOutline(mFollowObject->getWorldBox(), ColorI::WHITE);
|
||||
|
||||
}
|
||||
|
||||
bool NavMeshTestTool::updateGuiInfo()
|
||||
{
|
||||
SimObject* statusbar;
|
||||
Sim::findObject("EditorGuiStatusBar", statusbar);
|
||||
|
||||
GuiTextCtrl* selectionBar;
|
||||
Sim::findObject("EWorldEditorStatusBarSelection", selectionBar);
|
||||
|
||||
String text;
|
||||
|
||||
if (mPlayer)
|
||||
text = "LMB To Select move Destination. LSHIFT+LMB To Deselect Current Bot.";
|
||||
if (mCurPlayer != NULL && mCurPlayer != mPlayer)
|
||||
text = "LMB To select Bot.";
|
||||
|
||||
if (mPlayer == NULL)
|
||||
{
|
||||
text = "LMB To place start/end for test path.";
|
||||
}
|
||||
|
||||
if (mSpawnClass != String::EmptyString && mSpawnDatablock != String::EmptyString)
|
||||
text += " CTRL+LMB To spawn a new Bot.";
|
||||
|
||||
if (mSelectFollow)
|
||||
text = "LMB To select Follow Target.";
|
||||
|
||||
if (statusbar)
|
||||
Con::executef(statusbar, "setInfo", text.c_str());
|
||||
|
||||
text = "";
|
||||
if (mPlayer)
|
||||
text = String::ToString("Bot Selected: %d", mPlayer->getId());
|
||||
|
||||
if (selectionBar)
|
||||
selectionBar->setText(text);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
S32 NavMeshTestTool::getPlayerId()
|
||||
{
|
||||
return mPlayer.isNull() ? 0 : mPlayer->getId();
|
||||
}
|
||||
|
||||
S32 NavMeshTestTool::getFollowObjectId()
|
||||
{
|
||||
return mFollowObject.isNull() ? 0 : mFollowObject->getId();
|
||||
}
|
||||
|
||||
|
||||
DefineEngineMethod(NavMeshTestTool, getPlayer, S32, (), ,
|
||||
"@brief Return the current player id.")
|
||||
{
|
||||
return object->getPlayerId();
|
||||
}
|
||||
|
||||
DefineEngineMethod(NavMeshTestTool, getFollowObject, S32, (), ,
|
||||
"@brief Return the current follow object id.")
|
||||
{
|
||||
return object->getFollowObjectId();
|
||||
}
|
||||
|
||||
DefineEngineMethod(NavMeshTestTool, setSpawnClass, void, (String className), , "")
|
||||
{
|
||||
object->setSpawnClass(className);
|
||||
}
|
||||
|
||||
DefineEngineMethod(NavMeshTestTool, setSpawnDatablock, void, (String dbName), , "")
|
||||
{
|
||||
object->setSpawnDatablock(dbName);
|
||||
}
|
||||
|
||||
DefineEngineMethod(NavMeshTestTool, followSelectMode, void, (), ,
|
||||
"@brief Set NavMeshTool to select a follow object.")
|
||||
{
|
||||
return object->followSelectMode();
|
||||
}
|
||||
|
||||
60
Engine/source/navigation/navMeshTools/navMeshTestTool.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef _NAVMESHTESTTOOL_H_
|
||||
#define _NAVMESHTESTTOOL_H_
|
||||
|
||||
|
||||
#ifndef _NAVMESH_TOOL_H_
|
||||
#include "navigation/navMeshTool.h"
|
||||
#endif
|
||||
|
||||
#ifndef _NAVPATH_H_
|
||||
#include "navigation/navPath.h"
|
||||
#endif
|
||||
|
||||
class NavMeshTestTool : public NavMeshTool
|
||||
{
|
||||
typedef NavMeshTool Parent;
|
||||
protected:
|
||||
String mSpawnClass;
|
||||
String mSpawnDatablock;
|
||||
SimObjectPtr<SceneObject> mPlayer;
|
||||
SimObjectPtr<SceneObject> mCurPlayer;
|
||||
SimObjectPtr<SceneObject> mFollowObject;
|
||||
SimObjectPtr<SceneObject> mCurFollowObject;
|
||||
Point3F mPathStart;
|
||||
Point3F mPathEnd;
|
||||
NavPath* mTestPath;
|
||||
LinkData mLinkTypes;
|
||||
dtQueryFilter mFilter;
|
||||
bool mSelectFollow;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(NavMeshTestTool);
|
||||
|
||||
void spawnPlayer(const Point3F& position);
|
||||
|
||||
void drawAgent(duDebugDrawTorque& dd, const F32* pos, F32 r, F32 h, F32 c, const U32 col);
|
||||
|
||||
NavMeshTestTool();
|
||||
|
||||
virtual ~NavMeshTestTool() {}
|
||||
|
||||
void onActivated(const Gui3DMouseEvent& evt) override;
|
||||
void onDeactivated() override;
|
||||
|
||||
void on3DMouseDown(const Gui3DMouseEvent& evt) override;
|
||||
void on3DMouseMove(const Gui3DMouseEvent& evt) override;
|
||||
void onRender3D() override;
|
||||
|
||||
bool updateGuiInfo() override;
|
||||
|
||||
S32 getPlayerId();
|
||||
S32 getFollowObjectId();
|
||||
|
||||
void setSpawnClass(String className) { mSpawnClass = className; }
|
||||
void setSpawnDatablock(String dbName) { mSpawnDatablock = dbName; }
|
||||
void followSelectMode() { mSelectFollow = true; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // !_NAVMESHTESTTOOL_H_
|
||||
200
Engine/source/navigation/navMeshTools/offMeshConnTool.cpp
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
#include "offMeshConnTool.h"
|
||||
#include "navigation/guiNavEditorCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "scene/sceneManager.h"
|
||||
#include "math/mathUtils.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(OffMeshConnectionTool);
|
||||
|
||||
void OffMeshConnectionTool::onActivated(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
Con::executef(this, "onActivated");
|
||||
}
|
||||
|
||||
void OffMeshConnectionTool::onDeactivated()
|
||||
{
|
||||
Con::executef(this, "onDeactivated");
|
||||
}
|
||||
|
||||
void OffMeshConnectionTool::on3DMouseDown(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
|
||||
Point3F startPnt = evt.pos;
|
||||
Point3F endPnt = evt.pos + evt.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
bool shift = evt.modifier & SI_LSHIFT;
|
||||
bool ctrl = evt.modifier & SI_LCTRL;
|
||||
|
||||
if (gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
{
|
||||
U32 link = mNavMesh->getLink(ri.point);
|
||||
if (link != -1)
|
||||
{
|
||||
if (mLink != -1)
|
||||
mNavMesh->selectLink(mLink, false);
|
||||
mNavMesh->selectLink(link, true, false);
|
||||
mLink = link;
|
||||
|
||||
if (ctrl)
|
||||
{
|
||||
mNavMesh->selectLink(mLink, false);
|
||||
mNavMesh->deleteLink(mLink);
|
||||
mLink = -1;
|
||||
Con::executef(this, "onLinkDeselected");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
LinkData d = mNavMesh->getLinkFlags(mLink);
|
||||
bool biDir = mNavMesh->getLinkDir(mLink);
|
||||
F32 linkRad = mNavMesh->getLinkRadius(mLink);
|
||||
Con::executef(this, "onLinkSelected", Con::getIntArg(d.getFlags()), Con::getBoolArg(biDir), Con::getFloatArg(linkRad));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mLink != -1)
|
||||
{
|
||||
mNavMesh->selectLink(mLink, false);
|
||||
mLink = -1;
|
||||
Con::executef(this, "onLinkDeselected");
|
||||
}
|
||||
|
||||
if (mLinkStart != Point3F::Max)
|
||||
{
|
||||
mLink = mNavMesh->addLink(mLinkStart, ri.point, mBiDir, mLinkRadius);
|
||||
mNavMesh->selectLink(mLink, true, false);
|
||||
|
||||
if (shift)
|
||||
mLinkStart = ri.point;
|
||||
else
|
||||
mLinkStart = Point3F::Max;
|
||||
|
||||
Con::executef(this, "onLinkSelected", Con::getIntArg(mLinkCache.getFlags()), Con::getBoolArg(mBiDir), Con::getFloatArg(mLinkRadius));
|
||||
}
|
||||
else
|
||||
{
|
||||
mLinkStart = ri.point;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mLink != -1)
|
||||
{
|
||||
mNavMesh->selectLink(mLink, false);
|
||||
mLink = -1;
|
||||
Con::executef(this, "onLinkDeselected");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OffMeshConnectionTool::on3DMouseMove(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
|
||||
Point3F startPnt = evt.pos;
|
||||
Point3F endPnt = evt.pos + evt.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
if (gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
{
|
||||
U32 link = mNavMesh->getLink(ri.point);
|
||||
if (link != -1)
|
||||
{
|
||||
if (link != mLink)
|
||||
{
|
||||
if (mCurLink != -1)
|
||||
mNavMesh->selectLink(mCurLink, false);
|
||||
mNavMesh->selectLink(link, true, true);
|
||||
}
|
||||
mCurLink = link;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mCurLink != mLink)
|
||||
mNavMesh->selectLink(mCurLink, false);
|
||||
mCurLink = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mNavMesh->selectLink(mCurLink, false);
|
||||
mCurLink = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void OffMeshConnectionTool::onRender3D()
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
|
||||
duDebugDrawTorque dd;
|
||||
|
||||
if (mLinkStart != Point3F::Max)
|
||||
{
|
||||
Point3F rcFrom = DTStoRC(mLinkStart);
|
||||
dd.begin(DU_DRAW_LINES);
|
||||
dd.depthMask(false);
|
||||
duAppendCircle(&dd, rcFrom.x, rcFrom.y, rcFrom.z, mLinkRadius, duRGBA(0, 255, 0, 255));
|
||||
dd.end();
|
||||
}
|
||||
|
||||
//mNavMesh->renderLinks(dd);
|
||||
|
||||
dd.immediateRender();
|
||||
}
|
||||
|
||||
bool OffMeshConnectionTool::updateGuiInfo()
|
||||
{
|
||||
SimObject* statusbar;
|
||||
Sim::findObject("EditorGuiStatusBar", statusbar);
|
||||
|
||||
GuiTextCtrl* selectionBar;
|
||||
Sim::findObject("EWorldEditorStatusBarSelection", selectionBar);
|
||||
|
||||
String text;
|
||||
text = "LMB To Select Link. CTRL+LMB To Delete Link";
|
||||
|
||||
if (mLinkStart != Point3F::Max)
|
||||
text = "LinkStarted: LMB To place End Point. Hold Left Shift to start a new Link from the end point.";
|
||||
|
||||
if (statusbar)
|
||||
Con::executef(statusbar, "setInfo", text.c_str());
|
||||
|
||||
if (mLink != -1)
|
||||
text = String::ToString("Selected Link: %d", mLink);
|
||||
else
|
||||
text = "";
|
||||
|
||||
if (selectionBar)
|
||||
selectionBar->setText(text);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OffMeshConnectionTool::setLinkProperties(const LinkData& d, bool biDir, F32 rad)
|
||||
{
|
||||
if (!mNavMesh.isNull() && mLink != -1)
|
||||
{
|
||||
mNavMesh->setLinkFlags(mLink, d);
|
||||
mNavMesh->setLinkDir(mLink, biDir);
|
||||
mNavMesh->setLinkRadius(mLink, rad);
|
||||
}
|
||||
|
||||
mLinkCache = d;
|
||||
mBiDir = biDir;
|
||||
mLinkRadius = rad;
|
||||
}
|
||||
|
||||
DefineEngineMethod(OffMeshConnectionTool, setLinkProperties, void, (U32 flags, bool biDir, F32 rad), ,
|
||||
"@Brief Set properties of the selected link.")
|
||||
{
|
||||
object->setLinkProperties(LinkData(flags), biDir, rad);
|
||||
}
|
||||
53
Engine/source/navigation/navMeshTools/offMeshConnTool.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#ifndef _OFFMESHCONNTOOL_H_
|
||||
#define _OFFMESHCONNTOOL_H_
|
||||
|
||||
|
||||
#ifndef _NAVMESH_TOOL_H_
|
||||
#include "navigation/navMeshTool.h"
|
||||
#endif
|
||||
|
||||
class OffMeshConnectionTool : public NavMeshTool
|
||||
{
|
||||
typedef NavMeshTool Parent;
|
||||
bool mStartPosSet;
|
||||
bool mBiDir;
|
||||
S32 mLink;
|
||||
S32 mCurLink;
|
||||
Point3F mLinkStart;
|
||||
LinkData mLinkCache;
|
||||
F32 mLinkRadius;
|
||||
public:
|
||||
|
||||
DECLARE_CONOBJECT(OffMeshConnectionTool);
|
||||
|
||||
OffMeshConnectionTool() {
|
||||
mStartPosSet = false;
|
||||
mBiDir = false;
|
||||
mLink = -1;
|
||||
mCurLink = -1;
|
||||
mLinkStart = Point3F::Max;
|
||||
mLinkCache = LinkData(0);
|
||||
mLinkRadius = 1.0;
|
||||
}
|
||||
virtual ~OffMeshConnectionTool() {}
|
||||
|
||||
void setActiveNavMesh(NavMesh* nav_mesh) override {
|
||||
mNavMesh = nav_mesh;
|
||||
|
||||
if (!mNavMesh.isNull())
|
||||
mLinkRadius = mNavMesh->mWalkableRadius;
|
||||
}
|
||||
|
||||
void onActivated(const Gui3DMouseEvent& evt) override;
|
||||
void onDeactivated() override;
|
||||
|
||||
void on3DMouseDown(const Gui3DMouseEvent& evt) override;
|
||||
void on3DMouseMove(const Gui3DMouseEvent& evt) override;
|
||||
void onRender3D() override;
|
||||
|
||||
bool updateGuiInfo() override;
|
||||
|
||||
void setLinkProperties(const LinkData& d, bool biDir, F32 rad);
|
||||
};
|
||||
|
||||
#endif
|
||||
115
Engine/source/navigation/navMeshTools/tileTool.cpp
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
#include "tileTool.h"
|
||||
#include "navigation/guiNavEditorCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "scene/sceneManager.h"
|
||||
#include "math/mathUtils.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(TileTool);
|
||||
|
||||
static void renderBoxOutline(const Box3F& box, const ColorI& col)
|
||||
{
|
||||
if (box != Box3F::Invalid)
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setCullMode(GFXCullNone);
|
||||
desc.setFillModeSolid();
|
||||
desc.setZReadWrite(true, false);
|
||||
desc.setBlend(true);
|
||||
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 20));
|
||||
desc.setFillModeWireframe();
|
||||
desc.setBlend(false);
|
||||
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 255));
|
||||
}
|
||||
}
|
||||
|
||||
void TileTool::onActivated(const Gui3DMouseEvent& lastEvent)
|
||||
{
|
||||
Con::executef(this, "onActivated");
|
||||
}
|
||||
|
||||
void TileTool::onDeactivated()
|
||||
{
|
||||
Con::executef(this, "onDeactivated");
|
||||
}
|
||||
|
||||
void TileTool::on3DMouseDown(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
|
||||
Point3F start = evt.pos;
|
||||
Point3F end = evt.pos + evt.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
if (gServerContainer.castRay(start, end, StaticObjectType, &ri))
|
||||
{
|
||||
mSelTile = mNavMesh->getTile(ri.point);
|
||||
}
|
||||
}
|
||||
|
||||
void TileTool::on3DMouseMove(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
|
||||
Point3F startPnt = evt.pos;
|
||||
Point3F endPnt = evt.pos + evt.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
|
||||
if (gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
mCurTile = mNavMesh->getTile(ri.point);
|
||||
else
|
||||
mCurTile = -1;
|
||||
}
|
||||
|
||||
void TileTool::onRender3D()
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
|
||||
if(mCurTile != -1)
|
||||
renderBoxOutline(mNavMesh->getTileBox(mCurTile), ColorI::BLUE);
|
||||
|
||||
if(mSelTile != -1)
|
||||
renderBoxOutline(mNavMesh->getTileBox(mSelTile), ColorI::GREEN);
|
||||
}
|
||||
|
||||
void TileTool::buildTile()
|
||||
{
|
||||
if (!mNavMesh.isNull() && mSelTile != -1)
|
||||
mNavMesh->buildTile(mSelTile);
|
||||
}
|
||||
|
||||
bool TileTool::updateGuiInfo()
|
||||
{
|
||||
SimObject* statusbar;
|
||||
Sim::findObject("EditorGuiStatusBar", statusbar);
|
||||
|
||||
GuiTextCtrl* selectionBar;
|
||||
Sim::findObject("EWorldEditorStatusBarSelection", selectionBar);
|
||||
|
||||
String text;
|
||||
|
||||
text = "LMB To select NavMesh Tile";
|
||||
|
||||
if (statusbar)
|
||||
Con::executef(statusbar, "setInfo", text.c_str());
|
||||
|
||||
if (mSelTile != -1)
|
||||
text = String::ToString("Selected Tile: %d", mSelTile);
|
||||
else
|
||||
text = "";
|
||||
|
||||
if (selectionBar)
|
||||
selectionBar->setText(text);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DefineEngineMethod(TileTool, buildTile, void, (), ,
|
||||
"@brief Build the currently selected tile.")
|
||||
{
|
||||
return object->buildTile();
|
||||
}
|
||||
31
Engine/source/navigation/navMeshTools/tileTool.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef _TILETOOL_H_
|
||||
#define _TILETOOL_H_
|
||||
|
||||
|
||||
#ifndef _NAVMESH_TOOL_H_
|
||||
#include "navigation/navMeshTool.h"
|
||||
#endif
|
||||
|
||||
class TileTool : public NavMeshTool
|
||||
{
|
||||
typedef NavMeshTool Parent;
|
||||
S32 mCurTile;
|
||||
S32 mSelTile;
|
||||
public:
|
||||
DECLARE_CONOBJECT(TileTool);
|
||||
|
||||
TileTool() { mCurTile = -1; mSelTile = -1; }
|
||||
virtual ~TileTool() {}
|
||||
|
||||
void onActivated(const Gui3DMouseEvent& evt) override;
|
||||
void onDeactivated() override;
|
||||
|
||||
void on3DMouseDown(const Gui3DMouseEvent& evt) override;
|
||||
void on3DMouseMove(const Gui3DMouseEvent& evt) override;
|
||||
void onRender3D() override;
|
||||
void buildTile();
|
||||
|
||||
bool updateGuiInfo() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -69,14 +69,11 @@ NavPath::NavPath() :
|
|||
mXray = false;
|
||||
mRenderSearch = false;
|
||||
|
||||
mQuery = NULL;
|
||||
mStatus = DT_FAILURE;
|
||||
}
|
||||
|
||||
NavPath::~NavPath()
|
||||
{
|
||||
dtFreeNavMeshQuery(mQuery);
|
||||
mQuery = NULL;
|
||||
}
|
||||
|
||||
void NavPath::checkAutoUpdate()
|
||||
|
|
@ -264,9 +261,6 @@ bool NavPath::onAdd()
|
|||
|
||||
if(isServerObject())
|
||||
{
|
||||
mQuery = dtAllocNavMeshQuery();
|
||||
if(!mQuery)
|
||||
return false;
|
||||
checkAutoUpdate();
|
||||
if(!plan())
|
||||
setProcessTick(true);
|
||||
|
|
@ -293,7 +287,8 @@ bool NavPath::init()
|
|||
return false;
|
||||
|
||||
// Initialise our query.
|
||||
if(dtStatusFailed(mQuery->init(mMesh->getNavMesh(), MaxPathLen)))
|
||||
mQuery = mMesh->getNavMeshQuery();
|
||||
if(!mQuery)
|
||||
return false;
|
||||
|
||||
mPoints.clear();
|
||||
|
|
@ -372,9 +367,6 @@ void NavPath::resize()
|
|||
bool NavPath::plan()
|
||||
{
|
||||
PROFILE_SCOPE(NavPath_plan);
|
||||
// Initialise filter.
|
||||
mFilter.setIncludeFlags(mLinkTypes.getFlags());
|
||||
|
||||
// Initialise query and visit locations.
|
||||
if(!init())
|
||||
return false;
|
||||
|
|
@ -640,9 +632,8 @@ void NavPath::renderSimple(ObjectRenderInst *ri, SceneRenderState *state, BaseMa
|
|||
if(np->mQuery && !dtStatusSucceed(np->mStatus))
|
||||
{
|
||||
duDebugDrawTorque dd;
|
||||
dd.overrideColor(duRGBA(250, 20, 20, 255));
|
||||
duDebugDrawNavMeshNodes(&dd, *np->mQuery);
|
||||
dd.render();
|
||||
dd.immediateRender();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public:
|
|||
|
||||
/// What sort of link types are we allowed to move on?
|
||||
LinkData mLinkTypes;
|
||||
|
||||
dtQueryFilter mFilter;
|
||||
/// Plan the path.
|
||||
bool plan();
|
||||
|
||||
|
|
@ -152,7 +152,6 @@ private:
|
|||
|
||||
dtNavMeshQuery *mQuery;
|
||||
dtStatus mStatus;
|
||||
dtQueryFilter mFilter;
|
||||
S32 mCurIndex;
|
||||
Vector<Point3F> mPoints;
|
||||
Vector<U16> mFlags;
|
||||
|
|
|
|||
|
|
@ -27,12 +27,16 @@
|
|||
#include "gfx/primBuilder.h"
|
||||
#include "gfx/gfxStateBlock.h"
|
||||
|
||||
RecastPolyList::RecastPolyList()
|
||||
RecastPolyList::RecastPolyList() : mChunkyMesh(0)
|
||||
{
|
||||
nverts = 0;
|
||||
verts = NULL;
|
||||
vertcap = 0;
|
||||
|
||||
nnormals = 0;
|
||||
normals = NULL;
|
||||
normalcap = 0;
|
||||
|
||||
ntris = 0;
|
||||
tris = NULL;
|
||||
tricap = 0;
|
||||
|
|
@ -44,6 +48,28 @@ RecastPolyList::~RecastPolyList()
|
|||
clear();
|
||||
}
|
||||
|
||||
rcChunkyTriMesh* RecastPolyList::getChunkyMesh()
|
||||
{
|
||||
if (!mChunkyMesh)
|
||||
{
|
||||
mChunkyMesh = new rcChunkyTriMesh;
|
||||
if (!mChunkyMesh)
|
||||
{
|
||||
Con::errorf("Build tile navigation: out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!rcCreateChunkyTriMesh(getVerts(), getTris(), getTriCount(), 256, mChunkyMesh))
|
||||
{
|
||||
Con::errorf("Build tile navigation: out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return mChunkyMesh;
|
||||
}
|
||||
|
||||
void RecastPolyList::clear()
|
||||
{
|
||||
nverts = 0;
|
||||
|
|
@ -51,6 +77,11 @@ void RecastPolyList::clear()
|
|||
verts = NULL;
|
||||
vertcap = 0;
|
||||
|
||||
nnormals = 0;
|
||||
delete[] normals;
|
||||
normals = NULL;
|
||||
normalcap = 0;
|
||||
|
||||
ntris = 0;
|
||||
delete[] tris;
|
||||
tris = NULL;
|
||||
|
|
@ -134,6 +165,39 @@ void RecastPolyList::vertex(U32 vi)
|
|||
|
||||
void RecastPolyList::end()
|
||||
{
|
||||
// Fetch current triangle indices
|
||||
const U32 i0 = tris[ntris * 3 + 0];
|
||||
const U32 i1 = tris[ntris * 3 + 1];
|
||||
const U32 i2 = tris[ntris * 3 + 2];
|
||||
|
||||
// Rebuild vertices
|
||||
Point3F v0(verts[i0 * 3 + 0], verts[i0 * 3 + 1], verts[i0 * 3 + 2]);
|
||||
Point3F v1(verts[i1 * 3 + 0], verts[i1 * 3 + 1], verts[i1 * 3 + 2]);
|
||||
Point3F v2(verts[i2 * 3 + 0], verts[i2 * 3 + 1], verts[i2 * 3 + 2]);
|
||||
|
||||
// Compute normal
|
||||
Point3F edge1 = v1 - v0;
|
||||
Point3F edge2 = v2 - v0;
|
||||
Point3F normal = mCross(edge1, edge2);
|
||||
normal.normalizeSafe();
|
||||
|
||||
// Allocate/resize normal buffer if needed
|
||||
if (nnormals == normalcap)
|
||||
{
|
||||
normalcap = (normalcap == 0) ? 16 : normalcap * 2;
|
||||
F32* newNormals = new F32[normalcap * 3];
|
||||
if (normals)
|
||||
dMemcpy(newNormals, normals, nnormals * 3 * sizeof(F32));
|
||||
delete[] normals;
|
||||
normals = newNormals;
|
||||
}
|
||||
|
||||
// Store normal
|
||||
normals[nnormals * 3 + 0] = normal.x;
|
||||
normals[nnormals * 3 + 1] = normal.y;
|
||||
normals[nnormals * 3 + 2] = normal.z;
|
||||
|
||||
nnormals++;
|
||||
ntris++;
|
||||
}
|
||||
|
||||
|
|
@ -147,6 +211,11 @@ const F32 *RecastPolyList::getVerts() const
|
|||
return verts;
|
||||
}
|
||||
|
||||
const F32* RecastPolyList::getNormals() const
|
||||
{
|
||||
return normals;
|
||||
}
|
||||
|
||||
U32 RecastPolyList::getTriCount() const
|
||||
{
|
||||
return ntris;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@
|
|||
#include "collision/abstractPolyList.h"
|
||||
#include "core/util/tVector.h"
|
||||
|
||||
#ifndef CHUNKYTRIMESH_H
|
||||
#include "ChunkyTriMesh.h"
|
||||
#endif
|
||||
|
||||
/// Represents polygons in the same manner as the .obj file format. Handy for
|
||||
/// padding data to Recast, since it expects this data format. At the moment,
|
||||
/// this class only accepts triangles.
|
||||
|
|
@ -57,6 +61,8 @@ public:
|
|||
U32 getVertCount() const;
|
||||
const F32 *getVerts() const;
|
||||
|
||||
const F32* getNormals() const;
|
||||
|
||||
U32 getTriCount() const;
|
||||
const S32 *getTris() const;
|
||||
|
||||
|
|
@ -70,6 +76,9 @@ public:
|
|||
/// Default destructor.
|
||||
~RecastPolyList();
|
||||
|
||||
rcChunkyTriMesh* getChunkyMesh();
|
||||
|
||||
|
||||
protected:
|
||||
/// Number of vertices defined.
|
||||
U32 nverts;
|
||||
|
|
@ -78,6 +87,13 @@ protected:
|
|||
/// Size of vertex array.
|
||||
U32 vertcap;
|
||||
|
||||
// Number of normals defined.
|
||||
U32 nnormals;
|
||||
// Array of normals (xyz in float array)
|
||||
F32* normals;
|
||||
// Size of normal array (matches verts)
|
||||
U32 normalcap;
|
||||
|
||||
/// Number of triangles defined.
|
||||
U32 ntris;
|
||||
/// Array of triangle vertex indices. Size ntris*3
|
||||
|
|
@ -93,6 +109,8 @@ protected:
|
|||
/// Another inherited utility function.
|
||||
const PlaneF& getIndexedPlane(const U32 index) override { return planes[index]; }
|
||||
|
||||
rcChunkyTriMesh* mChunkyMesh;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ inline void rcCol(unsigned int col, U8 &r, U8 &g, U8 &b, U8 &a)
|
|||
}
|
||||
|
||||
enum PolyAreas {
|
||||
NullArea = 0,
|
||||
GroundArea,
|
||||
WaterArea,
|
||||
OffMeshArea,
|
||||
|
|
@ -99,6 +100,10 @@ struct LinkData {
|
|||
(climb ? ClimbFlag : 0) |
|
||||
(teleport ? TeleportFlag : 0);
|
||||
}
|
||||
U16 getExcludeFlags() const
|
||||
{
|
||||
return AllFlags & ~getFlags();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4,3 +4,58 @@ datablock ItemData(PrototypeItemData)
|
|||
ShapeAsset = "Prototyping:TorusPrimitive_shape";
|
||||
cameraMaxDist = "0.75";
|
||||
};
|
||||
|
||||
datablock PlayerData( ProtoPlayer ) {
|
||||
// Third person shape
|
||||
ShapeAsset = "Prototyping:Playerbot_shape";
|
||||
controlMap = "playerKeyMap";
|
||||
AIControllerData = "aiPlayerControl";
|
||||
};
|
||||
|
||||
datablock WheeledVehicleTire(ProtoCarTire)
|
||||
{
|
||||
// Tires act as springs and generate lateral and longitudinal
|
||||
// forces to move the vehicle. These distortion/spring forces
|
||||
// are what convert wheel angular velocity into forces that
|
||||
// act on the rigid body.
|
||||
shapeAsset = "Prototyping:carwheel_shape";
|
||||
|
||||
staticFriction = 1;
|
||||
kineticFriction = 4.2;
|
||||
|
||||
// Spring that generates lateral tire forces
|
||||
lateralForce = 150000;
|
||||
lateralDamping = 30000;
|
||||
lateralRelaxation = 0.1;
|
||||
|
||||
// Spring that generates longitudinal tire forces
|
||||
longitudinalForce = 600;
|
||||
longitudinalDamping = 1600;
|
||||
longitudinalRelaxation = 0.1;
|
||||
};
|
||||
|
||||
datablock WheeledVehicleSpring(ProtoCarSpring)
|
||||
{
|
||||
// Wheel suspension properties
|
||||
length = "0.6"; // Suspension travel
|
||||
force = 3600; // Spring force
|
||||
damping = 2800; // Spring damping
|
||||
antiSwayForce = 300; // Lateral anti-sway force
|
||||
};
|
||||
|
||||
datablock WheeledVehicleData(ProtoCar)
|
||||
{
|
||||
category = "Vehicles";
|
||||
shapeAsset = "Prototyping:car_shape";
|
||||
|
||||
collisionMul = 0;
|
||||
impactMul = 0;
|
||||
controlMap = "vehicleKeyMap";
|
||||
AIControllerData = "aiCarControl";
|
||||
cameraMaxDist = "2.81993";
|
||||
ShapeFile = "data/Prototyping/shapes/Vehicles/car.dae";
|
||||
mass = "1000";
|
||||
originalAssetName = "ProtoCar";
|
||||
massCenter = "0 0.75 0";
|
||||
dragForce = "0.1";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// This file contains script methods unique to the WheeledVehicle class. All
|
||||
// other necessary methods are contained in "../server/scripts/vehicle.cs" in
|
||||
// which the "generic" Vehicle class methods that are shared by all vehicles,
|
||||
// (flying, hover, and wheeled) can be found.
|
||||
|
||||
function ProtoCar::onAdd(%this, %obj)
|
||||
{
|
||||
Parent::onAdd(%this, %obj);
|
||||
|
||||
// Setup the car with some tires & springs
|
||||
for (%i = %obj.getWheelCount() - 1; %i >= 0; %i--)
|
||||
{
|
||||
%obj.setWheelTire(%i, ProtoCarTire);
|
||||
%obj.setWheelSpring(%i, ProtoCarSpring);
|
||||
%obj.setWheelPowered(%i, false);
|
||||
}
|
||||
|
||||
// Steer with the front tires
|
||||
%obj.setWheelSteering(0, 1);
|
||||
%obj.setWheelSteering(1, 1);
|
||||
|
||||
// Only power the two rear wheels... assuming there are only 4 wheels.
|
||||
%obj.setWheelPowered(2, true);
|
||||
%obj.setWheelPowered(3, true);
|
||||
}
|
||||
|
|
@ -1,5 +1,39 @@
|
|||
AssetBrowser::registerAssetType("ImageAsset", "Images");
|
||||
|
||||
function ImageAsset::onCreateNew()
|
||||
{
|
||||
%moduleName = $CurrentAssetBrowser.newAssetSettings.moduleName;
|
||||
%modulePath = "data/" @ %moduleName;
|
||||
|
||||
%assetName = $CurrentAssetBrowser.newAssetSettings.assetName;
|
||||
|
||||
%assetPath = NewAssetTargetAddress.getText() @ "/";
|
||||
|
||||
%tamlpath = %assetPath @ %assetName @ ".asset.taml";
|
||||
%filePath = %assetPath @ %assetName @ ".png";
|
||||
|
||||
%asset = new ImageAsset()
|
||||
{
|
||||
AssetName = %assetName;
|
||||
versionId = 1;
|
||||
imageFile = %assetName @ ".png";
|
||||
};
|
||||
|
||||
TamlWrite(%asset, %tamlpath);
|
||||
|
||||
%moduleDef = ModuleDatabase.findModule(%moduleName, 1);
|
||||
AssetDatabase.addDeclaredAsset(%moduleDef, %tamlpath);
|
||||
|
||||
%file = new FileObject();
|
||||
|
||||
if(%file.openForWrite(%filePath))
|
||||
{
|
||||
%file.close();
|
||||
}
|
||||
|
||||
return %tamlpath;
|
||||
}
|
||||
|
||||
function ImageAsset::buildBrowserElement(%this, %previewData)
|
||||
{
|
||||
//%module = %this.dirHandler.getModuleFromAddress(makeRelativePath(filePath(%assetDef.getImagePath())));
|
||||
|
|
@ -96,6 +130,17 @@ function ImageAsset::generatePreviewImage(%this, %previewButton, %forceRegenerat
|
|||
function ImageAsset::onShowActionMenu(%this)
|
||||
{
|
||||
GenericAsset::onShowActionMenu(%this);
|
||||
|
||||
%assetId = %this.getAssetId();
|
||||
|
||||
EditAssetPopup.setItemPosition("Create Composite Texture" TAB "" TAB "CompositeTextureEditor.buildComposite(\"" @ %assetId @ "\");", 4);
|
||||
|
||||
EditAssetPopup.objectData = %assetId;
|
||||
EditAssetPopup.objectType = AssetDatabase.getAssetType(%assetId);
|
||||
|
||||
EditAssetPopup.reloadItems();
|
||||
|
||||
EditAssetPopup.showPopup(Canvas);
|
||||
}
|
||||
|
||||
function ImageAsset::onEditProperties(%this)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
AssetBrowser::registerAssetType("MaterialAsset", "Materials");
|
||||
|
||||
function MaterialAsset::setupCreateNew()
|
||||
{
|
||||
NewAssetPropertiesInspector.startGroup("Material");
|
||||
NewAssetPropertiesInspector.addField("InheritFrom", "Inherit From", "MaterialInheritList", "What material should this new one inherit from.", "", "", $CurrentAssetBrowser.newAssetSettings);
|
||||
|
||||
NewAssetPropertiesInspector.endGroup();
|
||||
}
|
||||
|
||||
function MaterialAsset::onCreateNew()
|
||||
{
|
||||
%assetName = $CurrentAssetBrowser.newAssetSettings.assetName;
|
||||
|
|
@ -18,6 +26,7 @@ function MaterialAsset::onCreateNew()
|
|||
materialDefinitionName = %assetName;
|
||||
|
||||
new Material(%assetName) {
|
||||
inheritFrom = $CurrentAssetBrowser.newAssetSettings.inheritFrom;
|
||||
mapTo = %assetName;
|
||||
};
|
||||
};
|
||||
|
|
@ -227,3 +236,101 @@ function GuiInspectorTypeMaterialAssetPtr::onControlDropped( %this, %payload, %p
|
|||
|
||||
EWorldEditor.isDirty = true;
|
||||
}
|
||||
|
||||
function GuiInspectorGroup::buildMaterialInheritListField(%this, %fieldName, %fieldLabel, %fieldDesc, %fieldDefaultVal, %fieldDataVals, %callbackName, %ownerObj)
|
||||
{
|
||||
%extent = 18;
|
||||
|
||||
%fieldCtrl = %this.createInspectorField();
|
||||
|
||||
%extent = %this.stack.getExtent();
|
||||
|
||||
%width = mRound(%extent/2);
|
||||
%height = 20;
|
||||
%inset = 10;
|
||||
|
||||
%editControl = new GuiPopUpMenuCtrlEx() {
|
||||
class = "materialInheritListField";
|
||||
maxPopupHeight = "200";
|
||||
sbUsesNAColor = "0";
|
||||
reverseTextList = "0";
|
||||
bitmapBounds = "16 16";
|
||||
maxLength = "1024";
|
||||
Margin = "0 0 0 0";
|
||||
Padding = "0 0 0 0";
|
||||
AnchorTop = "1";
|
||||
AnchorBottom = "0";
|
||||
AnchorLeft = "1";
|
||||
AnchorRight = "0";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiPopUpMenuProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
Position = %fieldCtrl.edit.position;
|
||||
Extent = %fieldCtrl.edit.extent;
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
tooltip = ""; //%tooltip;
|
||||
text = %fieldDefaultVal;
|
||||
hovertime = "1000";
|
||||
ownerObject = %ownerObj;
|
||||
fieldName = %fieldName;
|
||||
callbackName = %callbackName;
|
||||
allowTextSearch = true;
|
||||
};
|
||||
|
||||
//set the field value
|
||||
if(getSubStr(%this.fieldName, 0, 1) $= "$")
|
||||
{
|
||||
if(%fieldName $= "")
|
||||
%editControl.setText(%fieldName);
|
||||
}
|
||||
else if(isObject(%ownerObj))
|
||||
{
|
||||
//regular variable
|
||||
%setCommand = %editControl @ ".setText(" @ %ownerObj @ "." @ %fieldName @ ");";
|
||||
eval(%setCommand);
|
||||
}
|
||||
|
||||
%listCount = getTokenCount(%fieldDataVals, ",;");
|
||||
|
||||
for(%i=0; %i < materialSet.getCount(); %i++)
|
||||
{
|
||||
%matObj = materialSet.getObject(%i);
|
||||
%matName = %matObj.getName();
|
||||
|
||||
if(%matName !$= "")
|
||||
%editControl.add(%matName);
|
||||
}
|
||||
|
||||
%fieldCtrl.setCaption(%fieldLabel);
|
||||
%fieldCtrl.setEditControl(%editControl);
|
||||
|
||||
//echo("GuiInspectorListField - " @ %editControl.getID() @ " - " @ %fieldName);
|
||||
|
||||
%this.addInspectorField(%fieldCtrl);
|
||||
}
|
||||
|
||||
function materialInheritListField::onSelect( %this, %id, %text )
|
||||
{
|
||||
if(getSubStr(%this.fieldName, 0, 1) $= "$")
|
||||
{
|
||||
//ah, a global var, just do it straight, then
|
||||
%setCommand = %this.fieldName @ " = \"" @ %text @ "\";";
|
||||
}
|
||||
else if(isObject(%this.ownerObject))
|
||||
{
|
||||
//regular variable
|
||||
%setCommand = %this.ownerObject @ "." @ %this.fieldName @ " = \"" @ %text @ "\";";
|
||||
}
|
||||
else if(%this.callbackName !$= "")
|
||||
{
|
||||
%setCommand = %this.callbackName @ "(\"" @ %this.fieldName @ "\",\"" @ %text @"\");";
|
||||
}
|
||||
|
||||
echo("materialInheritListField::onSelect() - command: " @ %setCommand);
|
||||
|
||||
eval(%setCommand);
|
||||
}
|
||||
|
|
@ -16,6 +16,11 @@ function AssetBrowser::editAsset(%this, %assetDef)
|
|||
}
|
||||
else
|
||||
{
|
||||
if(AssetDatabase.isDeclaredAsset(%assetDef))
|
||||
{
|
||||
%assetDef = AssetDatabase.acquireAsset(%assetDef);
|
||||
}
|
||||
|
||||
if(isObject(%assetDef))
|
||||
{
|
||||
%assetType = AssetDatabase.getAssetType(%assetDef.getAssetId());
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@
|
|||
canSave="true"
|
||||
canSaveDynamicFields="true"
|
||||
AssetName="CubemapEditor"
|
||||
scriptFile="@assetFile=cubemapEditor.gui"
|
||||
scriptFile="@assetFile=cubemapEditor.tscript"
|
||||
GUIFile="@assetFile=cubemapEditor.gui"
|
||||
VersionId="1" />
|
||||
|
|
|
|||
437
Templates/BaseGame/game/tools/gui/compositeTextureEditor.gui
Normal file
|
|
@ -0,0 +1,437 @@
|
|||
//--- OBJECT WRITE BEGIN ---
|
||||
$guiContent = new GuiControl(CompositeTextureEditor) {
|
||||
extent = "1920 1080";
|
||||
horizSizing = "width";
|
||||
vertSizing = "height";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
isContainer = "1";
|
||||
canSaveDynamicFields = "1";
|
||||
enabled = "1";
|
||||
|
||||
new GuiWindowCtrl(CompositeTextureEditorWindow) {
|
||||
Text = "Composite Texture Editor";
|
||||
resizeWidth = "0";
|
||||
resizeHeight = "0";
|
||||
canMinimize = "0";
|
||||
canMaximize = "0";
|
||||
closeCommand = "Canvas.popDialog(CompositeTextureEditor);";
|
||||
position = "721 416";
|
||||
extent = "478 248";
|
||||
minExtent = "478 248";
|
||||
horizSizing = "center";
|
||||
vertSizing = "center";
|
||||
profile = "ToolsGuiWindowProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
|
||||
new GuiContainer(CompTextureEd_RedChan) {
|
||||
position = "11 39";
|
||||
extent = "107 174";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
className = "CompositeTextureSlotContainer";
|
||||
|
||||
new GuiTextCtrl() {
|
||||
Text = "Red Channel";
|
||||
position = "5 -2";
|
||||
extent = "100 15";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiTextProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiPopUpMenuCtrl() {
|
||||
position = "1 20";
|
||||
extent = "106 23";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiPopUpMenuEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "InputMode";
|
||||
className = "CompositeTextureChannelMode";
|
||||
};
|
||||
new GuiContainer() {
|
||||
position = "0 41";
|
||||
extent = "107 125";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "RawValueContainer";
|
||||
|
||||
new GuiTextEditCtrl() {
|
||||
position = "0 8";
|
||||
extent = "28 20";
|
||||
profile = "ToolsGuiTextEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "RawValueTxtEdit";
|
||||
className = "CompositeTextureRawValueEdit";
|
||||
};
|
||||
new GuiSliderCtrl() {
|
||||
position = "38 9";
|
||||
extent = "68 19";
|
||||
profile = "GuiSliderProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "RawValueSlider";
|
||||
className = "CompositeTextureRawValueSlider";
|
||||
Command = "$thisControl.onDragComplete();";
|
||||
range = 0 SPC 1;
|
||||
ticks = 0.01;
|
||||
};
|
||||
};
|
||||
new GuiContainer() {
|
||||
position = "0 41";
|
||||
extent = "107 125";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "TextureContainer";
|
||||
|
||||
new GuiBitmapCtrl() {
|
||||
BitmapAsset = "ToolsModule:unknownImage_image";
|
||||
BitmapFile = "tools/materialEditor/images/unknownImage.png";
|
||||
position = "21 9";
|
||||
horizSizing = "center";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "Bitmap";
|
||||
};
|
||||
new GuiBitmapButtonCtrl() {
|
||||
BitmapAsset = "ToolsModule:cubemapBtnBorder_n_image";
|
||||
position = "21 9";
|
||||
extent = "64 64";
|
||||
horizSizing = "center";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
command = "$CompTexSourceChannel = 0;AssetBrowser.showDialog(\"ImageAsset\", \"CompositeTextureEditor.setSourceTex\");";
|
||||
tooltipProfile = "ToolsGuiDefaultProfile";
|
||||
ToolTip = "Set the source of the texture for this channel to sample from when baking a composite.";
|
||||
};
|
||||
new GuiTextCtrl() {
|
||||
Text = "Source Channel";
|
||||
position = "5 85";
|
||||
extent = "100 10";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiTextProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiPopUpMenuCtrl() {
|
||||
position = "1 97";
|
||||
extent = "106 23";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiPopUpMenuEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "sourceChannel";
|
||||
className = "CompositeTextureTexSrcChannel";
|
||||
};
|
||||
};
|
||||
};
|
||||
new GuiContainer(CompTextureEd_GreenChan) {
|
||||
position = "129 39";
|
||||
extent = "107 174";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
className = "CompositeTextureSlotContainer";
|
||||
|
||||
new GuiTextCtrl() {
|
||||
Text = "Green Channel";
|
||||
position = "5 -2";
|
||||
extent = "100 15";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiTextProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiPopUpMenuCtrl() {
|
||||
position = "1 20";
|
||||
extent = "106 23";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiPopUpMenuEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "InputMode";
|
||||
className = "CompositeTextureChannelMode";
|
||||
};
|
||||
new GuiContainer() {
|
||||
position = "0 41";
|
||||
extent = "107 125";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "RawValueContainer";
|
||||
|
||||
new GuiTextEditCtrl() {
|
||||
position = "0 8";
|
||||
extent = "28 20";
|
||||
profile = "ToolsGuiTextEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "RawValueTxtEdit";
|
||||
className = "CompositeTextureRawValueEdit";
|
||||
};
|
||||
new GuiSliderCtrl() {
|
||||
position = "38 9";
|
||||
extent = "68 19";
|
||||
profile = "GuiSliderProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "RawValueSlider";
|
||||
className = "CompositeTextureRawValueSlider";
|
||||
Command = "$thisControl.onDragComplete();";
|
||||
range = 0 SPC 1;
|
||||
ticks = 0.01;
|
||||
};
|
||||
};
|
||||
new GuiContainer() {
|
||||
position = "0 41";
|
||||
extent = "107 125";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "TextureContainer";
|
||||
|
||||
new GuiBitmapCtrl() {
|
||||
BitmapAsset = "ToolsModule:unknownImage_image";
|
||||
BitmapFile = "tools/materialEditor/images/unknownImage.png";
|
||||
position = "21 9";
|
||||
horizSizing = "center";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "Bitmap";
|
||||
};
|
||||
new GuiBitmapButtonCtrl() {
|
||||
BitmapAsset = "ToolsModule:cubemapBtnBorder_n_image";
|
||||
position = "21 9";
|
||||
extent = "64 64";
|
||||
horizSizing = "center";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
command = "$CompTexSourceChannel = 1;AssetBrowser.showDialog(\"ImageAsset\", \"CompositeTextureEditor.setSourceTex\");";
|
||||
tooltipProfile = "ToolsGuiDefaultProfile";
|
||||
ToolTip = "Set the source of the texture for this channel to sample from when baking a composite.";
|
||||
};
|
||||
new GuiTextCtrl() {
|
||||
Text = "Source Channel";
|
||||
position = "5 85";
|
||||
extent = "100 10";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiTextProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiPopUpMenuCtrl() {
|
||||
position = "1 97";
|
||||
extent = "106 23";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiPopUpMenuEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "sourceChannel";
|
||||
className = "CompositeTextureTexSrcChannel";
|
||||
};
|
||||
};
|
||||
};
|
||||
new GuiContainer(CompTextureEd_BlueChan) {
|
||||
position = "247 39";
|
||||
extent = "107 174";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
className = "CompositeTextureSlotContainer";
|
||||
|
||||
new GuiTextCtrl() {
|
||||
Text = "Blue Channel";
|
||||
position = "5 -2";
|
||||
extent = "100 15";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiTextProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiPopUpMenuCtrl() {
|
||||
position = "1 20";
|
||||
extent = "106 23";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiPopUpMenuEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "InputMode";
|
||||
className = "CompositeTextureChannelMode";
|
||||
};
|
||||
new GuiContainer() {
|
||||
position = "0 41";
|
||||
extent = "107 125";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "RawValueContainer";
|
||||
|
||||
new GuiTextEditCtrl() {
|
||||
position = "0 8";
|
||||
extent = "28 20";
|
||||
profile = "ToolsGuiTextEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "RawValueTxtEdit";
|
||||
className = "CompositeTextureRawValueEdit";
|
||||
};
|
||||
new GuiSliderCtrl() {
|
||||
position = "38 9";
|
||||
extent = "68 19";
|
||||
profile = "GuiSliderProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "RawValueSlider";
|
||||
className = "CompositeTextureRawValueSlider";
|
||||
Command = "$thisControl.onDragComplete();";
|
||||
range = 0 SPC 1;
|
||||
ticks = 0.01;
|
||||
};
|
||||
};
|
||||
new GuiContainer() {
|
||||
position = "0 41";
|
||||
extent = "107 125";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "TextureContainer";
|
||||
|
||||
new GuiBitmapCtrl() {
|
||||
BitmapAsset = "ToolsModule:unknownImage_image";
|
||||
BitmapFile = "tools/materialEditor/images/unknownImage.png";
|
||||
position = "21 9";
|
||||
horizSizing = "center";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "Bitmap";
|
||||
};
|
||||
new GuiBitmapButtonCtrl() {
|
||||
BitmapAsset = "ToolsModule:cubemapBtnBorder_n_image";
|
||||
position = "21 9";
|
||||
extent = "64 64";
|
||||
horizSizing = "center";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
command = "$CompTexSourceChannel = 2;AssetBrowser.showDialog(\"ImageAsset\", \"CompositeTextureEditor.setSourceTex\");";
|
||||
tooltipProfile = "ToolsGuiDefaultProfile";
|
||||
ToolTip = "Set the source of the texture for this channel to sample from when baking a composite.";
|
||||
};
|
||||
new GuiTextCtrl() {
|
||||
Text = "Source Channel";
|
||||
position = "5 85";
|
||||
extent = "100 10";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiTextProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiPopUpMenuCtrl() {
|
||||
position = "1 97";
|
||||
extent = "106 23";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiPopUpMenuEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "sourceChannel";
|
||||
className = "CompositeTextureTexSrcChannel";
|
||||
};
|
||||
};
|
||||
};
|
||||
new GuiContainer(CompTextureEd_AlphaChan) {
|
||||
position = "361 39";
|
||||
extent = "107 174";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
className = "CompositeTextureSlotContainer";
|
||||
|
||||
new GuiTextCtrl() {
|
||||
Text = "Alpha Channel";
|
||||
position = "5 -2";
|
||||
extent = "100 15";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiTextProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiPopUpMenuCtrl() {
|
||||
position = "1 20";
|
||||
extent = "106 23";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiPopUpMenuEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "InputMode";
|
||||
className = "CompositeTextureChannelMode";
|
||||
};
|
||||
new GuiContainer() {
|
||||
position = "0 41";
|
||||
extent = "107 125";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "RawValueContainer";
|
||||
|
||||
new GuiTextEditCtrl() {
|
||||
position = "0 8";
|
||||
extent = "28 20";
|
||||
profile = "ToolsGuiTextEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "RawValueTxtEdit";
|
||||
className = "CompositeTextureRawValueEdit";
|
||||
};
|
||||
new GuiSliderCtrl() {
|
||||
position = "38 9";
|
||||
extent = "68 19";
|
||||
profile = "GuiSliderProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "RawValueSlider";
|
||||
className = "CompositeTextureRawValueSlider";
|
||||
Command = "$thisControl.onDragComplete();";
|
||||
range = 0 SPC 1;
|
||||
ticks = 0.01;
|
||||
};
|
||||
};
|
||||
new GuiContainer() {
|
||||
position = "0 41";
|
||||
extent = "107 125";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "TextureContainer";
|
||||
|
||||
new GuiBitmapCtrl() {
|
||||
BitmapAsset = "ToolsModule:unknownImage_image";
|
||||
BitmapFile = "tools/materialEditor/images/unknownImage.png";
|
||||
position = "21 9";
|
||||
horizSizing = "center";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "Bitmap";
|
||||
};
|
||||
new GuiBitmapButtonCtrl() {
|
||||
BitmapAsset = "ToolsModule:cubemapBtnBorder_n_image";
|
||||
position = "21 9";
|
||||
extent = "64 64";
|
||||
horizSizing = "center";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
command = "$CompTexSourceChannel = 3;AssetBrowser.showDialog(\"ImageAsset\", \"CompositeTextureEditor.setSourceTex\");";
|
||||
tooltipProfile = "ToolsGuiDefaultProfile";
|
||||
ToolTip = "Set the source of the texture for this channel to sample from when baking a composite.";
|
||||
};
|
||||
new GuiTextCtrl() {
|
||||
Text = "Source Channel";
|
||||
position = "5 85";
|
||||
extent = "100 10";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiTextProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiPopUpMenuCtrl() {
|
||||
position = "1 97";
|
||||
extent = "106 23";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiPopUpMenuEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "sourceChannel";
|
||||
className = "CompositeTextureTexSrcChannel";
|
||||
};
|
||||
};
|
||||
};
|
||||
new GuiButtonCtrl() {
|
||||
Text = "Save";
|
||||
position = "339 216";
|
||||
extent = "74 24";
|
||||
profile = "ToolsGuiButtonProfile";
|
||||
command = "CompositeTextureEditor.saveComposite();";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiButtonCtrl() {
|
||||
Text = "Cancel";
|
||||
position = "417 216";
|
||||
extent = "52 24";
|
||||
profile = "ToolsGuiButtonProfile";
|
||||
command = "Canvas.popDialog(CompositeTextureEditor);";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
};
|
||||
};
|
||||
//--- OBJECT WRITE END ---
|
||||
192
Templates/BaseGame/game/tools/gui/compositeTextureEditor.tscript
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
function CompositeTextureEditor::buildComposite(%this, %sourceTex0, %sourceTex1, %sourceTex2, %sourceTex3, %sourceChan0, %sourceChan1, %sourceChan2, %sourceChan3, %callback)
|
||||
{
|
||||
Canvas.pushDialog(%this);
|
||||
|
||||
CompTextureEd_RedChan.setChannelData(%sourceTex0, %sourceChan0);
|
||||
CompTextureEd_GreenChan.setChannelData(%sourceTex1, %sourceChan1);
|
||||
CompTextureEd_BlueChan.setChannelData(%sourceTex2, %sourceChan2);
|
||||
CompTextureEd_AlphaChan.setChannelData(%sourceTex3, %sourceChan3);
|
||||
|
||||
%this.callbackFunc = %callback;
|
||||
}
|
||||
|
||||
function CompositeTextureSlotContainer::onWake(%this)
|
||||
{
|
||||
%this-->InputMode.clear();
|
||||
%this-->InputMode.add("Raw Value");
|
||||
%this-->InputMode.add("Texture");
|
||||
%this-->InputMode.setSelected(1);
|
||||
%this-->InputMode.active = false;
|
||||
|
||||
%this-->sourceChannel.clear();
|
||||
%this-->sourceChannel.add("Red");
|
||||
%this-->sourceChannel.add("Green");
|
||||
%this-->sourceChannel.add("Blue");
|
||||
%this-->sourceChannel.add("Alpha");
|
||||
}
|
||||
|
||||
function CompositeTextureSlotContainer::setChannelData(%this, %sourceValue, %sourceChannel)
|
||||
{
|
||||
//for now, hard-force Texture mode
|
||||
%this-->InputMode.setSelected(1);
|
||||
|
||||
if(AssetDatabase.isDeclaredAsset(%sourceValue))
|
||||
{
|
||||
%this-->InputMode.setSelected(1);
|
||||
|
||||
%this-->bitmap.setBitmap(%sourceValue);
|
||||
|
||||
if(%sourceChannel $= "")
|
||||
%sourceChannel = "Red";
|
||||
|
||||
%this-->sourceChannel.setText(%sourceChannel);
|
||||
}
|
||||
/*else
|
||||
{
|
||||
%this-->InputMode.setSelected(0);
|
||||
|
||||
%value = 0;
|
||||
if(%sourceValue !$= "" && (isFloat(%sourceValue) || isFloat(%sourceValue)))
|
||||
{
|
||||
%value = %sourceValue;
|
||||
}
|
||||
|
||||
%this-->RawValueTxtEdit.setText(%value);
|
||||
%this-->RawValueSlider.setValue(%value);
|
||||
}*/
|
||||
}
|
||||
|
||||
function CompositeTextureSlotContainer::getChannelData(%this)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
function CompositeTextureChannelMode::onSelect(%this, %id, %text)
|
||||
{
|
||||
%isRawValueMode = %text $= "Raw Value";
|
||||
%this.getParent()-->RawValueContainer.setVisible(%isRawValueMode);
|
||||
%this.getParent()-->TextureContainer.setVisible(!%isRawValueMode);
|
||||
}
|
||||
|
||||
function CompositeTextureEditor::setSourceTex(%this, %assetId)
|
||||
{
|
||||
if($CompTexSourceChannel $= "")
|
||||
$CompTexSourceChannel = 0;
|
||||
|
||||
%channelContainer = CompositeTextureEditorWindow.getObject($CompTexSourceChannel);
|
||||
%channelContainer-->bitmap.setBitmap(%assetId);
|
||||
}
|
||||
|
||||
function CompositeTextureEditor::saveComposite(%this)
|
||||
{
|
||||
%cubemap = CubemapEditor.currentCubemap;
|
||||
|
||||
%aoMap = CompTextureEd_RedChan-->Bitmap.getBitmap();
|
||||
%roughMap = CompTextureEd_GreenChan-->Bitmap.getBitmap();
|
||||
%metalMap = CompTextureEd_BlueChan-->Bitmap.getBitmap();
|
||||
|
||||
if(%aoMap $= "ToolsModule:unknownImage_image")
|
||||
%aoMap = "";
|
||||
if(%roughMap $= "ToolsModule:unknownImage_image")
|
||||
%roughMap = "";
|
||||
if(%metalMap $= "ToolsModule:unknownImage_image")
|
||||
%metalMap = "";
|
||||
|
||||
if(%aoMap $= "" && %roughMap $= "" && %metalMap $= "")
|
||||
{
|
||||
toolsMessageBoxOK("Error", "Saving a composite map requires at least one channel slot to have source data!");
|
||||
return;
|
||||
}
|
||||
|
||||
AssetBrowser.setupCreateNewAsset("ImageAsset", AssetBrowser.selectedModule, "CompositeEditorDoSaveComposite");
|
||||
}
|
||||
|
||||
function CompositeEditorDoSaveComposite(%assetId)
|
||||
{
|
||||
%assetDef = AssetDatabase.acquireAsset(%assetId);
|
||||
if(!isObject(%assetDef))
|
||||
{
|
||||
toolsMessageBoxOK("Error", "We somehow failed to successfully create a new ImageAsset!");
|
||||
return;
|
||||
}
|
||||
|
||||
%targetFilePath = %assetDef.getImagePath();
|
||||
|
||||
%aoMapAsset = CompTextureEd_RedChan-->Bitmap.getBitmap();
|
||||
%roughMapAsset = CompTextureEd_GreenChan-->Bitmap.getBitmap();
|
||||
%metalMapAsset = CompTextureEd_BlueChan-->Bitmap.getBitmap();
|
||||
|
||||
|
||||
if(%aoMapAsset $= "ToolsModule:unknownImage_image")
|
||||
{
|
||||
%aoMap = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
%aoAssetDef = AssetDatabase.acquireAsset(%aoMapAsset);
|
||||
%aoMap = %aoAssetDef.getImagePath();
|
||||
}
|
||||
if(%roughMapAsset $= "ToolsModule:unknownImage_image")
|
||||
{
|
||||
%roughMap = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
%roughAssetDef = AssetDatabase.acquireAsset(%roughMapAsset);
|
||||
%roughMap = %roughAssetDef.getImagePath();
|
||||
}
|
||||
if(%metalMapAsset $= "ToolsModule:unknownImage_image")
|
||||
{
|
||||
%metalMap = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
%metalAssetDef = AssetDatabase.acquireAsset(%metalMapAsset);
|
||||
%metalMap = %roughAssetDef.getImagePath();
|
||||
}
|
||||
|
||||
if(%aoMap $= "" && %roughMap $= "" && %metalMap $= "")
|
||||
{
|
||||
toolsMessageBoxOK("Error", "Attempted to create a composite texture but all three source textures are blank or invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
%redChanSource = CompTextureEd_RedChan-->sourceChannel;
|
||||
%greenChanSource = CompTextureEd_GreenChan-->sourceChannel;
|
||||
%blueChanSource = CompTextureEd_BlueChan-->sourceChannel;
|
||||
|
||||
%aoChan = %redChanSource.findText(%redChanSource.getText());
|
||||
%aoChan = %aoChan == -1 ? 0 : %aoChan;
|
||||
|
||||
%roughChan = %greenChanSource.findText(%greenChanSource.getText());
|
||||
%roughChan = %roughChan == -1 ? 1 : %roughChan;
|
||||
|
||||
%metalChan = %blueChanSource.findText(%blueChanSource.getText());
|
||||
%metalChan = %metalChan == -1 ? 2 : %metalChan;
|
||||
|
||||
%channelKey = %aoChan SPC %roughChan SPC %metalChan SPC 3;
|
||||
error("Storing: \"" @ %aoMap @"\" \""@ %roughMap @"\" \""@ %metalMap @"\" \""@ %channelKey @"\" \""@ %targetFilePath @"\"");
|
||||
saveCompositeTexture(%aoMap, %roughMap, %metalMap, "", %channelKey, %targetFilePath);
|
||||
|
||||
%assetDef.refreshAsset();
|
||||
|
||||
%command = CompositeTextureEditor.callbackFunc @ "(\"" @ %assetId @ "\");";
|
||||
if(CompositeTextureEditor.callbackFunc !$= "")
|
||||
{
|
||||
eval(%command);
|
||||
CompositeTextureEditor.callbackFunc = "";
|
||||
}
|
||||
|
||||
Canvas.popDialog(CompositeTextureEditor);
|
||||
}
|
||||
|
||||
function CompositeTextureRawValueEdit::onReturn(%this)
|
||||
{
|
||||
%this.getParent()-->RawValueSlider.setValue(%this.getText());
|
||||
}
|
||||
|
||||
function CompositeTextureRawValueSlider::onDragComplete(%this)
|
||||
{
|
||||
%value = %this.getValue();
|
||||
%this.getParent()-->RawValueTxtEdit.setText(%value);
|
||||
}
|
||||
|
|
@ -39,7 +39,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
canMaximize = "0";
|
||||
minSize = "50 50";
|
||||
EdgeSnap = "1";
|
||||
closeCommand = "MaterialEditorGui.hideCubemapEditor(true);";
|
||||
closeCommand = "CubemapEditor.hideCubemapEditor(true);";
|
||||
text = "Cubemap Editor";
|
||||
|
||||
new GuiTextCtrl(){
|
||||
|
|
@ -69,23 +69,23 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
AnchorRight = "0";
|
||||
text = "myCubemap 1";
|
||||
maxLength = "1024";
|
||||
AltCommand = "MaterialEditorGui.editCubemapName($ThisControl.getText());";
|
||||
AltCommand = "CubemapEditor.editCubemapName($ThisControl.getText());";
|
||||
};
|
||||
new GuiButtonCtrl(){
|
||||
Profile = "ToolsGuiButtonProfile";
|
||||
position = "339 216";
|
||||
Extent = "74 24";
|
||||
text = "Select";
|
||||
command = "MaterialEditorGui.selectCubemap();"; // needs hookup use selected cubemap
|
||||
command = "CubemapEditor.selectCubemap();"; // needs hookup use selected cubemap
|
||||
};
|
||||
new GuiButtonCtrl(){
|
||||
Profile = "ToolsGuiButtonProfile";
|
||||
position = "417 216";
|
||||
Extent = "52 24";
|
||||
text = "Cancel";
|
||||
command = "MaterialEditorGui.hideCubemapEditor(true);"; // needs hookup Cancel
|
||||
command = "CubemapEditor.hideCubemapEditor(true);"; // needs hookup Cancel
|
||||
};
|
||||
new GuiScrollCtrl(matEd_cubemapEd_availableCubemapScroller) {
|
||||
new GuiScrollCtrl(cubemapEd_availableCubemapScroller) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "1";
|
||||
|
|
@ -106,7 +106,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
constantThumbHeight = "0";
|
||||
childMargin = "0 0";
|
||||
|
||||
new GuiListBoxCtrl(matEd_cubemapEd_availableCubemapList) {
|
||||
new GuiListBoxCtrl(cubemapEd_availableCubemapList) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -130,7 +130,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
text = "Cubemaps";
|
||||
};
|
||||
// ------------------------------ Right X Positive ------------------------------------
|
||||
new GuiBitmapCtrl(matEd_cubemapEd_XPos) {
|
||||
new GuiBitmapCtrl(cubemapEd_XPos) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -146,12 +146,12 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
bitmapAsset = "ToolsModule:unknownImage_image";
|
||||
wrap = "0";
|
||||
};
|
||||
new GuiTextCtrl(matEd_cubeMapEd_xPosTxt) {
|
||||
new GuiTextCtrl(cubeMapEd_xPosTxt) {
|
||||
position = "304 110";
|
||||
Extent = "57 10";
|
||||
text = "+ X Right";
|
||||
};
|
||||
new GuiBitmapButtonCtrl(matEd_cubeMapEd_updateXPOSImg) {
|
||||
new GuiBitmapButtonCtrl(cubeMapEd_updateXPOSImg) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -163,7 +163,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "MaterialEditorGui.editCubemapImage(\"0\", $ThisControl.bitmap );";
|
||||
Command = "CubemapEditor.editCubemapImage(\"0\", $ThisControl.bitmap );";
|
||||
tooltipprofile = "ToolsGuiDefaultProfile";
|
||||
ToolTip = "When using Static Cubemaps, select your CubeMap by clicking here.";
|
||||
hovertime = "1000";
|
||||
|
|
@ -173,7 +173,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
bitmapAsset = "ToolsModule:cubemapBtnBorder_n_image";
|
||||
};
|
||||
// ------------------------------ X Negitive ------------------------------------
|
||||
new GuiBitmapCtrl(matEd_cubemapEd_XNeg) {
|
||||
new GuiBitmapCtrl(cubemapEd_XNeg) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -189,12 +189,12 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
bitmapAsset = "ToolsModule:unknownImage_image";
|
||||
wrap = "0";
|
||||
};
|
||||
new GuiTextCtrl(matEd_cubeMapEd_xNegTxt) {
|
||||
new GuiTextCtrl(cubeMapEd_xNegTxt) {
|
||||
position = "171 110";
|
||||
Extent = "57 10";
|
||||
text = "- X Left";
|
||||
};
|
||||
new GuiBitmapButtonCtrl(matEd_cubeMapEd_updateXNEGImg) {
|
||||
new GuiBitmapButtonCtrl(cubeMapEd_updateXNEGImg) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -206,7 +206,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "MaterialEditorGui.editCubemapImage(\"1\", $ThisControl.bitmap );";
|
||||
Command = "CubemapEditor.editCubemapImage(\"1\", $ThisControl.bitmap );";
|
||||
tooltipprofile = "ToolsGuiDefaultProfile";
|
||||
ToolTip = "When using Static Cubemaps, select your CubeMap by clicking here.";
|
||||
hovertime = "1000";
|
||||
|
|
@ -216,7 +216,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
bitmapAsset = "ToolsModule:cubemapBtnBorder_n_image";
|
||||
};
|
||||
// ------------------------------ Y Positive ------------------------------------
|
||||
new GuiBitmapCtrl(matEd_cubemapEd_YPos) {
|
||||
new GuiBitmapCtrl(cubemapEd_YPos) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -232,12 +232,12 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
bitmapAsset = "ToolsModule:unknownImage_image";
|
||||
wrap = "0";
|
||||
};
|
||||
new GuiTextCtrl(matEd_cubeMapEd_yPosTxt) {
|
||||
new GuiTextCtrl(cubeMapEd_yPosTxt) {
|
||||
position = "237 175";
|
||||
Extent = "57 10";
|
||||
text = "+ Y Front";
|
||||
};
|
||||
new GuiBitmapButtonCtrl(matEd_cubeMapEd_updateYPOSImg) {
|
||||
new GuiBitmapButtonCtrl(cubeMapEd_updateYPOSImg) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -249,7 +249,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "MaterialEditorGui.editCubemapImage(\"3\", $ThisControl.bitmap );";
|
||||
Command = "CubemapEditor.editCubemapImage(\"3\", $ThisControl.bitmap );";
|
||||
tooltipprofile = "ToolsGuiDefaultProfile";
|
||||
ToolTip = "When using Static Cubemaps, select your CubeMap by clicking here.";
|
||||
hovertime = "1000";
|
||||
|
|
@ -259,7 +259,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
bitmapAsset = "ToolsModule:cubemapBtnBorder_n_image";
|
||||
};
|
||||
// ------------------------------ Y Negitive ------------------------------------
|
||||
new GuiBitmapCtrl(matEd_cubemapEd_YNeG) {
|
||||
new GuiBitmapCtrl(cubemapEd_YNeG) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -275,12 +275,12 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
bitmapAsset = "ToolsModule:unknownImage_image";
|
||||
wrap = "0";
|
||||
};
|
||||
new GuiTextCtrl(matEd_cubeMapEd_yNegTxt) {
|
||||
new GuiTextCtrl(cubeMapEd_yNegTxt) {
|
||||
position = "237 44";
|
||||
Extent = "57 10";
|
||||
text = "- Y Back";
|
||||
};
|
||||
new GuiBitmapButtonCtrl(matEd_cubeMapEd_updateYNegImg) {
|
||||
new GuiBitmapButtonCtrl(cubeMapEd_updateYNegImg) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -292,7 +292,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "MaterialEditorGui.editCubemapImage(\"2\", $ThisControl.bitmap );";
|
||||
Command = "CubemapEditor.editCubemapImage(\"2\", $ThisControl.bitmap );";
|
||||
tooltipprofile = "ToolsGuiDefaultProfile";
|
||||
ToolTip = "When using Static Cubemaps, select your CubeMap by clicking here.";
|
||||
hovertime = "1000";
|
||||
|
|
@ -302,7 +302,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
bitmapAsset = "ToolsModule:cubemapBtnBorder_n_image";
|
||||
};
|
||||
// ------------------------------ Z Positive ------------------------------------
|
||||
new GuiBitmapCtrl(matEd_cubemapEd_ZPos) {
|
||||
new GuiBitmapCtrl(cubemapEd_ZPos) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -318,12 +318,12 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
bitmapAsset = "ToolsModule:unknownImage_image";
|
||||
wrap = "0";
|
||||
};
|
||||
new GuiTextCtrl(matEd_cubeMapEd_zPosTxt) {
|
||||
new GuiTextCtrl(cubeMapEd_zPosTxt) {
|
||||
position = "237 110";
|
||||
Extent = "57 10";
|
||||
text = "+ Z Top";
|
||||
};
|
||||
new GuiBitmapButtonCtrl(matEd_cubeMapEd_updateZPosImg) {
|
||||
new GuiBitmapButtonCtrl(cubeMapEd_updateZPosImg) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -335,7 +335,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "MaterialEditorGui.editCubemapImage(\"4\", $ThisControl.bitmap );";
|
||||
Command = "CubemapEditor.editCubemapImage(\"4\", $ThisControl.bitmap );";
|
||||
tooltipprofile = "ToolsGuiDefaultProfile";
|
||||
ToolTip = "When using Static Cubemaps, select your CubeMap by clicking here.";
|
||||
hovertime = "1000";
|
||||
|
|
@ -345,7 +345,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
bitmapAsset = "ToolsModule:cubemapBtnBorder_n_image";
|
||||
};
|
||||
// ------------------------------ Z Negitive ------------------------------------
|
||||
new GuiBitmapCtrl(matEd_cubemapEd_ZNeg) {
|
||||
new GuiBitmapCtrl(cubemapEd_ZNeg) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -361,12 +361,12 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
bitmapAsset = "ToolsModule:unknownImage_image";
|
||||
wrap = "0";
|
||||
};
|
||||
new GuiTextCtrl(matEd_cubeMapEd_zNegTxt) {
|
||||
new GuiTextCtrl(cubeMapEd_zNegTxt) {
|
||||
position = "369 110";
|
||||
Extent = "57 10";
|
||||
text = "- Z Bottom";
|
||||
};
|
||||
new GuiBitmapButtonCtrl(matEd_cubeMapEd_updateZNegImg) {
|
||||
new GuiBitmapButtonCtrl(cubeMapEd_updateZNegImg) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
|
|
@ -378,7 +378,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "MaterialEditorGui.editCubemapImage(\"5\", $ThisControl.bitmap );";
|
||||
Command = "CubemapEditor.editCubemapImage(\"5\", $ThisControl.bitmap );";
|
||||
tooltipprofile = "ToolsGuiDefaultProfile";
|
||||
ToolTip = "When using Static Cubemaps, select your CubeMap by clicking here.";
|
||||
hovertime = "1000";
|
||||
|
|
@ -401,7 +401,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "matEd_addCubemapWindow.setVisible(1);"; // -------------- Needs Hookup Create New Cubemap
|
||||
Command = "addCubemapWindow.setVisible(1);"; // -------------- Needs Hookup Create New Cubemap
|
||||
hovertime = "1000";
|
||||
tooltip = "Create New Cubemap";
|
||||
bitmapAsset = "ToolsModule:new_n_image";
|
||||
|
|
@ -421,7 +421,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "MaterialEditorGui.showDeleteCubemapDialog();"; // -------------- Needs Hookup Delete Cubemap
|
||||
Command = "CubemapEditor.showDeleteCubemapDialog();"; // -------------- Needs Hookup Delete Cubemap
|
||||
hovertime = "1000";
|
||||
tooltip = "Delete Cubemap";
|
||||
bitmapAsset = "ToolsModule:delete_n_image";
|
||||
|
|
@ -442,7 +442,7 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "MaterialEditorGui.showSaveCubemapDialog();"; // -------------- Needs Hookup Save Cubemap
|
||||
Command = "CubemapEditor.showSaveCubemapDialog();"; // -------------- Needs Hookup Save Cubemap
|
||||
hovertime = "1000";
|
||||
tooltip = "Save Cubemap";
|
||||
bitmapAsset = "ToolsModule:save_icon_n_image";
|
||||
|
|
@ -451,4 +451,123 @@ $guiContent = new GuiControl(CubemapEditor) {
|
|||
useMouseEvents = "0";
|
||||
};
|
||||
};
|
||||
|
||||
new GuiWindowCtrl(addCubemapWindow) {
|
||||
canSaveDynamicFields = "0";
|
||||
isContainer = "1";
|
||||
Profile = "ToolsGuiWindowProfile";
|
||||
HorizSizing = "center";
|
||||
VertSizing = "center";
|
||||
position = "362 333";
|
||||
Extent = "300 99";
|
||||
MinExtent = "48 92";
|
||||
canSave = "1";
|
||||
Visible = "0";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
Margin = "0 0 0 0";
|
||||
Padding = "0 0 0 0";
|
||||
AnchorTop = "1";
|
||||
AnchorBottom = "0";
|
||||
AnchorLeft = "1";
|
||||
AnchorRight = "0";
|
||||
resizeWidth = "1";
|
||||
resizeHeight = "1";
|
||||
canMove = "1";
|
||||
canClose = "0";
|
||||
canMinimize = "0";
|
||||
canMaximize = "0";
|
||||
minSize = "50 50";
|
||||
EdgeSnap = "1";
|
||||
text = "Create Cubemap";
|
||||
|
||||
new GuiTextEditCtrl() {
|
||||
canSaveDynamicFields = "0";
|
||||
internalName = "cubemapName";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiTextEditProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
position = "96 35";
|
||||
Extent = "196 18";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
Margin = "0 0 0 0";
|
||||
Padding = "0 0 0 0";
|
||||
AnchorTop = "1";
|
||||
AnchorBottom = "0";
|
||||
AnchorLeft = "1";
|
||||
AnchorRight = "0";
|
||||
maxLength = "1024";
|
||||
historySize = "0";
|
||||
password = "0";
|
||||
tabComplete = "0";
|
||||
sinkAllKeyEvents = "0";
|
||||
AltCommand = "";
|
||||
passwordMask = "*";
|
||||
};
|
||||
new GuiTextCtrl() {
|
||||
canSaveDynamicFields = "0";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiTextProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
position = "12 36";
|
||||
Extent = "77 16";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
Margin = "0 0 0 0";
|
||||
Padding = "0 0 0 0";
|
||||
AnchorTop = "1";
|
||||
AnchorBottom = "0";
|
||||
AnchorLeft = "1";
|
||||
AnchorRight = "0";
|
||||
maxLength = "1024";
|
||||
text = "Cubemap Name";
|
||||
};
|
||||
new GuiButtonCtrl() {
|
||||
canSaveDynamicFields = "0";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiButtonProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
position = "96 68";
|
||||
Extent = "126 22";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
groupNum = "-1";
|
||||
buttonType = "PushButton";
|
||||
useMouseEvents = "0";
|
||||
text = "Create";
|
||||
Command = "CubemapEditor.addCubemap( addCubemapWindow-->cubemapName.getText() );addCubemapWindow.setVisible(0);";
|
||||
};
|
||||
new GuiButtonCtrl() {
|
||||
canSaveDynamicFields = "0";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiButtonProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
position = "228 68";
|
||||
Extent = "64 22";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
groupNum = "-1";
|
||||
buttonType = "PushButton";
|
||||
useMouseEvents = "0";
|
||||
text = "Cancel";
|
||||
Command = "addCubemapWindow.setVisible(0);";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
367
Templates/BaseGame/game/tools/gui/cubemapEditor.tscript
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
function CubemapEditor::onWake(%this)
|
||||
{
|
||||
cubemapEd_availableCubemapList.clear();
|
||||
}
|
||||
|
||||
function CubemapEditor::cancelCubemap(%this)
|
||||
{
|
||||
%cubemap = CubemapEditor.currentCubemap;
|
||||
|
||||
%idx = cubemapEd_availableCubemapList.findItemText( %cubemap.getName() );
|
||||
cubemapEd_availableCubemapList.setItemText( %idx, notDirtyCubemap.originalName );
|
||||
%cubemap.setName( notDirtyCubemap.originalName );
|
||||
|
||||
CubemapEditor.copyCubemaps( notDirtyCubemap, %cubemap );
|
||||
CubemapEditor.copyCubemaps( notDirtyCubemap, matEdCubeMapPreviewMat);
|
||||
|
||||
%cubemap.updateFaces();
|
||||
matEdCubeMapPreviewMat.updateFaces();
|
||||
}
|
||||
|
||||
function CubemapEditor::showCubemapEditor(%this)
|
||||
{
|
||||
if (cubemapEditor.isVisible())
|
||||
return;
|
||||
|
||||
CubemapEditor.currentCubemap = "";
|
||||
|
||||
cubemapEditor.setVisible(1);
|
||||
new PersistenceManager(cubemapEdPerMan);
|
||||
CubemapEditor.setCubemapNotDirty();
|
||||
|
||||
for( %i = 0; %i < RootGroup.getCount(); %i++ )
|
||||
{
|
||||
if( RootGroup.getObject(%i).getClassName()!$= "CubemapData" )
|
||||
continue;
|
||||
|
||||
for( %k = 0; %k < UnlistedCubemaps.count(); %k++ )
|
||||
{
|
||||
%unlistedFound = 0;
|
||||
if( UnlistedCubemaps.getValue(%k) $= RootGroup.getObject(%i).name )
|
||||
{
|
||||
%unlistedFound = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( %unlistedFound )
|
||||
continue;
|
||||
|
||||
cubemapEd_availableCubemapList.addItem( RootGroup.getObject(%i).name );
|
||||
}
|
||||
|
||||
singleton CubemapData(notDirtyCubemap);
|
||||
|
||||
// if there was no cubemap, pick the first, select, and bail, these are going to take
|
||||
// care of themselves in the selected function
|
||||
if( !isObject( CubemapEditor.currentMaterial.cubemap ) )
|
||||
{
|
||||
if( cubemapEd_availableCubemapList.getItemCount() > 0 )
|
||||
{
|
||||
cubemapEd_availableCubemapList.setSelected(0, true);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there are no cubemaps, then create one, select, and bail
|
||||
%cubemap = CubemapEditor.createNewCubemap();
|
||||
cubemapEd_availableCubemapList.addItem( %cubemap.name );
|
||||
cubemapEd_availableCubemapList.setSelected(0, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// do not directly change activeMat!
|
||||
CubemapEditor.currentCubemap = CubemapEditor.currentMaterial.cubemap.getId();
|
||||
%cubemap = CubemapEditor.currentCubemap;
|
||||
|
||||
notDirtyCubemap.originalName = %cubemap.getName();
|
||||
CubemapEditor.copyCubemaps( %cubemap, notDirtyCubemap);
|
||||
CubemapEditor.copyCubemaps( %cubemap, matEdCubeMapPreviewMat);
|
||||
CubemapEditor.syncCubemap( %cubemap );
|
||||
}
|
||||
|
||||
function CubemapEditor::hideCubemapEditor(%this,%cancel)
|
||||
{
|
||||
if(%cancel)
|
||||
CubemapEditor.cancelCubemap();
|
||||
|
||||
cubemapEd_availableCubemapList.clearItems();
|
||||
cubemapEdPerMan.delete();
|
||||
cubemapEditor.setVisible(0);
|
||||
}
|
||||
|
||||
// create category and update current material if there is one
|
||||
function CubemapEditor::addCubemap( %this,%cubemapName )
|
||||
{
|
||||
if( %cubemapName $= "" )
|
||||
{
|
||||
toolsMessageBoxOK( "Error", "Can not create a cubemap without a valid name.");
|
||||
return;
|
||||
}
|
||||
|
||||
for(%i = 0; %i < RootGroup.getCount(); %i++)
|
||||
{
|
||||
if( %cubemapName $= RootGroup.getObject(%i).getName() )
|
||||
{
|
||||
toolsMessageBoxOK( "Error", "There is already an object with the same name.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create and select a new cubemap
|
||||
%cubemap = CubemapEditor.createNewCubemap( %cubemapName );
|
||||
%idx = cubemapEd_availableCubemapList.addItem( %cubemap.name );
|
||||
cubemapEd_availableCubemapList.setSelected( %idx, true );
|
||||
|
||||
// material category text field to blank
|
||||
addCubemapWindow-->cubemapName.setText("");
|
||||
}
|
||||
|
||||
function CubemapEditor::createNewCubemap( %this, %cubemap )
|
||||
{
|
||||
if( %cubemap $= "" )
|
||||
{
|
||||
for(%i = 0; ; %i++)
|
||||
{
|
||||
%cubemap = "newCubemap_" @ %i;
|
||||
if( !isObject(%cubemap) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
new CubemapData(%cubemap)
|
||||
{
|
||||
cubeMapFaceAsset[0] = "ToolsModule:cube_xNeg_image";
|
||||
cubeMapFaceAsset[1] = "ToolsModule:cube_xPos_image";
|
||||
cubeMapFaceAsset[2] = "ToolsModule:cube_zNeg_image";
|
||||
cubeMapFaceAsset[3] = "ToolsModule:cube_zPos_image";
|
||||
cubeMapFaceAsset[4] = "ToolsModule:cube_yNeg_image";
|
||||
cubeMapFaceAsset[5] = "ToolsModule:cube_yPos_image";
|
||||
|
||||
parentGroup = RootGroup;
|
||||
};
|
||||
|
||||
cubemapEdPerMan.setDirty( %cubemap, "art/materials." @ $TorqueScriptFileExtension );
|
||||
cubemapEdPerMan.saveDirty();
|
||||
|
||||
return %cubemap;
|
||||
}
|
||||
|
||||
function CubemapEditor::setCubemapDirty(%this)
|
||||
{
|
||||
%propertyText = "Create Cubemap *";
|
||||
cubemapEditor.text = %propertyText;
|
||||
cubemapEditor.dirty = true;
|
||||
cubemapEditor-->saveCubemap.setActive(true);
|
||||
|
||||
%cubemap = CubemapEditor.currentCubemap;
|
||||
|
||||
// materials created in the materail selector are given that as its filename, so we run another check
|
||||
if( CubemapEditor.isMatEditorMaterial( %cubemap ) )
|
||||
cubemapEdPerMan.setDirty(%cubemap, "art/materials." @ $TorqueScriptFileExtension);
|
||||
else
|
||||
cubemapEdPerMan.setDirty(%cubemap);
|
||||
}
|
||||
|
||||
function CubemapEditor::setCubemapNotDirty(%this)
|
||||
{
|
||||
%propertyText= strreplace("Create Cubemap" , "*" , "");
|
||||
cubemapEditor.text = %propertyText;
|
||||
cubemapEditor.dirty = false;
|
||||
cubemapEditor-->saveCubemap.setActive(false);
|
||||
|
||||
%cubemap = CubemapEditor.currentCubemap;
|
||||
cubemapEdPerMan.removeDirty(%cubemap);
|
||||
}
|
||||
|
||||
function CubemapEditor::showDeleteCubemapDialog(%this)
|
||||
{
|
||||
%idx = cubemapEd_availableCubemapList.getSelectedItem();
|
||||
%cubemap = cubemapEd_availableCubemapList.getItemText( %idx );
|
||||
%cubemap = %cubemap.getId();
|
||||
|
||||
if( %cubemap == -1 || !isObject(%cubemap) )
|
||||
return;
|
||||
|
||||
if( isObject( %cubemap ) )
|
||||
{
|
||||
toolsMessageBoxYesNoCancel("Delete Cubemap?",
|
||||
"Are you sure you want to delete<br><br>" @ %cubemap.getName() @ "<br><br> Cubemap deletion won't take affect until the engine is quit.",
|
||||
"CubemapEditor.deleteCubemap( " @ %cubemap @ ", " @ %idx @ " );",
|
||||
"",
|
||||
"" );
|
||||
}
|
||||
}
|
||||
|
||||
function CubemapEditor::deleteCubemap( %this, %cubemap, %idx )
|
||||
{
|
||||
cubemapEd_availableCubemapList.deleteItem( %idx );
|
||||
|
||||
UnlistedCubemaps.add( "unlistedCubemaps", %cubemap.getName() );
|
||||
|
||||
if( !CubemapEditor.isMatEditorMaterial( %cubemap ) )
|
||||
{
|
||||
cubemapEdPerMan.removeDirty( %cubemap );
|
||||
cubemapEdPerMan.removeObjectFromFile( %cubemap );
|
||||
}
|
||||
|
||||
if( cubemapEd_availableCubemapList.getItemCount() > 0 )
|
||||
{
|
||||
cubemapEd_availableCubemapList.setSelected(0, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there are no cubemaps, then create one, select, and bail
|
||||
%cubemap = CubemapEditor.createNewCubemap();
|
||||
cubemapEd_availableCubemapList.addItem( %cubemap.getName() );
|
||||
cubemapEd_availableCubemapList.setSelected(0, true);
|
||||
}
|
||||
}
|
||||
|
||||
function cubemapEd_availableCubemapList::onSelect( %this, %id, %cubemap )
|
||||
{
|
||||
%cubemap = %cubemap.getId();
|
||||
if( CubemapEditor.currentCubemap $= %cubemap )
|
||||
return;
|
||||
|
||||
if( cubemapEditor.dirty )
|
||||
{
|
||||
%savedCubemap = CubemapEditor.currentCubemap;
|
||||
toolsMessageBoxYesNoCancel("Save Existing Cubemap?",
|
||||
"Do you want to save changes to <br><br>" @ %savedCubemap.getName(),
|
||||
"CubemapEditor.saveCubemap(" @ true @ ");",
|
||||
"CubemapEditor.saveCubemapDialogDontSave(" @ %cubemap @ ");",
|
||||
"CubemapEditor.saveCubemapDialogCancel();" );
|
||||
}
|
||||
else
|
||||
CubemapEditor.changeCubemap( %cubemap );
|
||||
}
|
||||
|
||||
function CubemapEditor::showSaveCubemapDialog( %this )
|
||||
{
|
||||
%cubemap = CubemapEditor.currentCubemap;
|
||||
if( !isObject(%cubemap) )
|
||||
return;
|
||||
|
||||
toolsMessageBoxYesNoCancel("Save Cubemap?",
|
||||
"Do you want to save changes to <br><br>" @ %cubemap.getName(),
|
||||
"CubemapEditor.saveCubemap( " @ %cubemap @ " );",
|
||||
"",
|
||||
"" );
|
||||
}
|
||||
|
||||
function CubemapEditor::saveCubemap( %this, %cubemap )
|
||||
{
|
||||
notDirtyCubemap.originalName = %cubemap.getName();
|
||||
CubemapEditor.copyCubemaps( %cubemap, notDirtyCubemap );
|
||||
CubemapEditor.copyCubemaps( %cubemap, matEdCubeMapPreviewMat);
|
||||
|
||||
cubemapEdPerMan.saveDirty();
|
||||
|
||||
CubemapEditor.setCubemapNotDirty();
|
||||
}
|
||||
|
||||
function CubemapEditor::saveCubemapDialogDontSave( %this, %newCubemap)
|
||||
{
|
||||
//deal with old cubemap first
|
||||
%oldCubemap = CubemapEditor.currentCubemap;
|
||||
|
||||
%idx = cubemapEd_availableCubemapList.findItemText( %oldCubemap.getName() );
|
||||
cubemapEd_availableCubemapList.setItemText( %idx, notDirtyCubemap.originalName );
|
||||
%oldCubemap.setName( notDirtyCubemap.originalName );
|
||||
|
||||
CubemapEditor.copyCubemaps( notDirtyCubemap, %oldCubemap);
|
||||
CubemapEditor.copyCubemaps( notDirtyCubemap, matEdCubeMapPreviewMat);
|
||||
CubemapEditor.syncCubemap( %oldCubemap );
|
||||
|
||||
CubemapEditor.changeCubemap( %newCubemap );
|
||||
}
|
||||
|
||||
function CubemapEditor::saveCubemapDialogCancel( %this )
|
||||
{
|
||||
%cubemap = CubemapEditor.currentCubemap;
|
||||
%idx = cubemapEd_availableCubemapList.findItemText( %cubemap.getName() );
|
||||
cubemapEd_availableCubemapList.clearSelection();
|
||||
cubemapEd_availableCubemapList.setSelected( %idx, true );
|
||||
}
|
||||
|
||||
function CubemapEditor::changeCubemap( %this, %cubemap )
|
||||
{
|
||||
CubemapEditor.setCubemapNotDirty();
|
||||
CubemapEditor.currentCubemap = %cubemap;
|
||||
|
||||
notDirtyCubemap.originalName = %cubemap.getName();
|
||||
CubemapEditor.copyCubemaps( %cubemap, notDirtyCubemap);
|
||||
CubemapEditor.copyCubemaps( %cubemap, matEdCubeMapPreviewMat);
|
||||
CubemapEditor.syncCubemap( %cubemap );
|
||||
}
|
||||
|
||||
function CubemapEditor::editCubemapImage( %this, %face )
|
||||
{
|
||||
CubemapEditor.setCubemapDirty();
|
||||
|
||||
%cubemap = CubemapEditor.currentCubemap;
|
||||
%bitmap = CubemapEditor.openFile("texture");
|
||||
if( %bitmap !$= "" && %bitmap !$= "tools/materialEditor/gui/cubemapBtnBorder" )
|
||||
{
|
||||
%cubemap.cubeFace[%face] = %bitmap;
|
||||
CubemapEditor.copyCubemaps( %cubemap, matEdCubeMapPreviewMat);
|
||||
CubemapEditor.syncCubemap( %cubemap );
|
||||
}
|
||||
}
|
||||
|
||||
function CubemapEditor::editCubemapName( %this, %newName )
|
||||
{
|
||||
CubemapEditor.setCubemapDirty();
|
||||
|
||||
%cubemap = CubemapEditor.currentCubemap;
|
||||
|
||||
%idx = cubemapEd_availableCubemapList.findItemText( %cubemap.getName() );
|
||||
cubemapEd_availableCubemapList.setItemText( %idx, %newName );
|
||||
%cubemap.setName(%newName);
|
||||
|
||||
CubemapEditor.syncCubemap( %cubemap );
|
||||
}
|
||||
|
||||
function CubemapEditor::syncCubemap( %this, %cubemap )
|
||||
{
|
||||
%xpos = CubemapEditor.searchForTexture(%cubemap.getName(), %cubemap.cubeFace[0]);
|
||||
if( %xpos !$= "" )
|
||||
cubemapEd_XPos.setBitmap( %xpos );
|
||||
|
||||
%xneg = CubemapEditor.searchForTexture(%cubemap.getName(), %cubemap.cubeFace[1]);
|
||||
if( %xneg !$= "" )
|
||||
cubemapEd_XNeg.setBitmap( %xneg );
|
||||
|
||||
%yneg = CubemapEditor.searchForTexture(%cubemap.getName(), %cubemap.cubeFace[2]);
|
||||
if( %yneg !$= "" )
|
||||
cubemapEd_YNeG.setBitmap( %yneg );
|
||||
|
||||
%ypos = CubemapEditor.searchForTexture(%cubemap.getName(), %cubemap.cubeFace[3]);
|
||||
if( %ypos !$= "" )
|
||||
cubemapEd_YPos.setBitmap( %ypos );
|
||||
|
||||
%zpos = CubemapEditor.searchForTexture(%cubemap.getName(), %cubemap.cubeFace[4]);
|
||||
if( %zpos !$= "" )
|
||||
cubemapEd_ZPos.setBitmap( %zpos );
|
||||
|
||||
%zneg = CubemapEditor.searchForTexture(%cubemap.getName(), %cubemap.cubeFace[5]);
|
||||
if( %zneg !$= "" )
|
||||
cubemapEd_ZNeg.setBitmap( %zneg );
|
||||
|
||||
cubemapEd_activeCubemapNameTxt.setText(%cubemap.getName());
|
||||
|
||||
%cubemap.updateFaces();
|
||||
matEdCubeMapPreviewMat.updateFaces();
|
||||
}
|
||||
|
||||
function CubemapEditor::copyCubemaps( %this, %copyFrom, %copyTo)
|
||||
{
|
||||
%copyTo.cubeFace[0] = %copyFrom.cubeFace[0];
|
||||
%copyTo.cubeFace[1] = %copyFrom.cubeFace[1];
|
||||
%copyTo.cubeFace[2] = %copyFrom.cubeFace[2];
|
||||
%copyTo.cubeFace[3] = %copyFrom.cubeFace[3];
|
||||
%copyTo.cubeFace[4] = %copyFrom.cubeFace[4];
|
||||
%copyTo.cubeFace[5] = %copyFrom.cubeFace[5];
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
<GUIAsset
|
||||
canSave="true"
|
||||
canSaveDynamicFields="true"
|
||||
AssetName="MaterialEditorGui,EditorGuiGroup"
|
||||
scriptFile="@assetFile=guiMaterialPropertiesWindow.ed.gui"
|
||||
GUIFile="@assetFile=guiMaterialPropertiesWindow.ed.gui"
|
||||
VersionId="1" />
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<GUIAsset
|
||||
AssetName="NuMaterialEditor"
|
||||
ScriptFile="@assetFile=NuMaterialEditor.tscript"
|
||||
GUIFile="@assetFile=NuMaterialEditor.gui"
|
||||
VersionId="1"/>
|
||||
|
|
@ -0,0 +1,490 @@
|
|||
//--- OBJECT WRITE BEGIN ---
|
||||
$guiContent = new GuiControl(MaterialEditorGui) {
|
||||
extent = "2560 1440";
|
||||
profile = "GuiNonModalDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
isContainer = "1";
|
||||
canSaveDynamicFields = "1";
|
||||
currentLayer = "0";
|
||||
currentMaterialAsset = "Prototyping:FloorGray";
|
||||
currentMeshMode = "EditorShape";
|
||||
currentMode = "Material";
|
||||
docked = "1";
|
||||
fileSpec = "Torque Material Files (materials.tscript)|materials.tscript|All Files (*.*)|*.*|";
|
||||
livePreview = "1";
|
||||
materialDirty = "0";
|
||||
modelFormats = "DTS Files (*.dts)|*.dts";
|
||||
originalAssetName = "MaterialEditorGui";
|
||||
originalName = "FloorGray";
|
||||
panelHidden = "0";
|
||||
preventUndo = "1";
|
||||
resizing = "0";
|
||||
textureFormats = "Image Files (*.png, *.jpg, *.dds, *.bmp, *.gif, *.jng. *.tga)|*.png;*.jpg;*.dds;*.bmp;*.gif;*.jng;*.tga|All Files (*.*)|*.*|";
|
||||
|
||||
new GuiWindowCollapseCtrl(MaterialEditorGuiWindow) {
|
||||
Text = " :: Material Editor";
|
||||
canMove = "0";
|
||||
canClose = "0";
|
||||
canMinimize = "0";
|
||||
canMaximize = "0";
|
||||
canCollapse = "0";
|
||||
margin = "5 5 5 5";
|
||||
position = "2168 39";
|
||||
extent = "392 1303";
|
||||
minExtent = "300 150";
|
||||
horizSizing = "windowRelative";
|
||||
vertSizing = "windowRelative";
|
||||
profile = "ToolsGuiWindowProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "InspectorWindow";
|
||||
|
||||
new GuiBitmapButtonCtrl(MaterialEditorGui_showBtn) {
|
||||
BitmapAsset = "ToolsModule:panel_show_n_image";
|
||||
position = "4 1";
|
||||
extent = "18 18";
|
||||
minExtent = "8 8";
|
||||
profile = "ToolsGuiButtonProfile";
|
||||
visible = "0";
|
||||
command = "MaterialEditorGui.showSidePanel();";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Show Sidepanel";
|
||||
hidden = "1";
|
||||
};
|
||||
new GuiBitmapButtonCtrl(MaterialEditorGui_UnDockBtn) {
|
||||
BitmapAsset = "ToolsModule:panel_undock_n_image";
|
||||
position = "369 0";
|
||||
extent = "18 18";
|
||||
minExtent = "8 8";
|
||||
horizSizing = "left";
|
||||
profile = "ToolsGuiButtonProfile";
|
||||
command = "MaterialEditorGui.releaseSidePanel();";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Detach Sidepanel";
|
||||
};
|
||||
new GuiBitmapButtonCtrl(MaterialEditorGui_hideBtn) {
|
||||
BitmapAsset = "ToolsModule:panel_hide_n_image";
|
||||
position = "351 0";
|
||||
extent = "18 18";
|
||||
minExtent = "8 8";
|
||||
horizSizing = "left";
|
||||
profile = "ToolsGuiButtonProfile";
|
||||
command = "MaterialEditorGui.hideSidePanel();";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Hide Sidepanel";
|
||||
};
|
||||
new GuiBitmapButtonCtrl(MaterialEditorGui_DockBtn) {
|
||||
BitmapAsset = "ToolsModule:panel_dock_n_image";
|
||||
position = "369 0";
|
||||
extent = "18 18";
|
||||
minExtent = "8 8";
|
||||
horizSizing = "left";
|
||||
profile = "ToolsGuiButtonProfile";
|
||||
visible = "0";
|
||||
command = "MaterialEditorGui.dockSidePanel();";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Dock Sidepanel";
|
||||
hidden = "1";
|
||||
};
|
||||
new GuiSplitContainer() {
|
||||
orientation = "Horizontal";
|
||||
splitPoint = "182 354";
|
||||
fixedSize = "692";
|
||||
position = "3 24";
|
||||
extent = "387 1269";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
|
||||
new GuiPanel() {
|
||||
docking = "Client";
|
||||
extent = "387 352";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "Panel1";
|
||||
|
||||
new GuiContainer(matEd_previewPanel) {
|
||||
docking = "Client";
|
||||
margin = "24 1 3 3";
|
||||
position = "3 24";
|
||||
extent = "381 327";
|
||||
horizSizing = "width";
|
||||
vertSizing = "height";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
|
||||
new GuiSwatchButtonCtrl(matEd_previewBackground) {
|
||||
color = "0 0 0 0.2";
|
||||
position = "-1 -1";
|
||||
extent = "383 329";
|
||||
horizSizing = "width";
|
||||
vertSizing = "height";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiContainer() {
|
||||
position = "-1 -1";
|
||||
extent = "383 329";
|
||||
horizSizing = "width";
|
||||
vertSizing = "height";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiMaterialPreview(matEd_previewObjectView) {
|
||||
position = "1 1";
|
||||
extent = "380 326";
|
||||
horizSizing = "width";
|
||||
vertSizing = "height";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
isContainer = "0";
|
||||
};
|
||||
};
|
||||
new GuiPopUpMenuCtrl(matEd_quickPreview_Popup) {
|
||||
Text = "Cube";
|
||||
position = "4 0";
|
||||
extent = "67 18";
|
||||
profile = "ToolsGuiPopUpMenuProfile";
|
||||
command = "MaterialEditorGui.updatePreviewObject();";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
ToolTip = "Changes the Preview Mesh";
|
||||
isContainer = "0";
|
||||
};
|
||||
new GuiSwatchButtonCtrl(matEd_lightColorPicker) {
|
||||
position = "79 4";
|
||||
extent = "14 14";
|
||||
command = "getColorF($ThisControl.color, \"MaterialEditorGui.updateLightColor\");";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Change Normal Light Color";
|
||||
};
|
||||
new GuiSwatchButtonCtrl(matEd_ambientLightColorPicker) {
|
||||
position = "97 4";
|
||||
extent = "14 14";
|
||||
command = "getColorF($ThisControl.color, \"MaterialEditorGui.updateAmbientColor\");";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Change Ambient Light Color";
|
||||
};
|
||||
new GuiSwatchButtonCtrl(MaterialPreviewBackgroundPicker) {
|
||||
color = "0 0 0 0.2";
|
||||
position = "113 0";
|
||||
extent = "20 20";
|
||||
command = "getColorF($thisControl.color, \"MaterialEditorGui.updatePreviewBackground\");";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Change Background Color (preview)";
|
||||
};
|
||||
new GuiCheckBoxCtrl() {
|
||||
Text = "Preview in World";
|
||||
position = "266 1";
|
||||
extent = "114 18";
|
||||
horizSizing = "left";
|
||||
profile = "ToolsGuiCheckBoxProfile";
|
||||
variable = "MaterialEditorGui.livePreview";
|
||||
command = "MaterialEditorGui.updateLivePreview($ThisControl.getValue());";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
};
|
||||
new GuiPanel() {
|
||||
docking = "Client";
|
||||
position = "0 356";
|
||||
extent = "387 913";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "panel2";
|
||||
|
||||
new GuiContainer() {
|
||||
extent = "388 22";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
|
||||
new GuiBitmapButtonCtrl(MatEd_phoBreadcrumb) {
|
||||
BitmapAsset = "ToolsModule:folderUp_image";
|
||||
position = "-1 0";
|
||||
extent = "20 19";
|
||||
profile = "GuiDefaultProfile";
|
||||
visible = "0";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Go back to previous editor";
|
||||
hidden = "1";
|
||||
};
|
||||
new GuiBitmapButtonCtrl() {
|
||||
BitmapAsset = "ToolsModule:delete_n_image";
|
||||
position = "368 1";
|
||||
extent = "17 17";
|
||||
horizSizing = "left";
|
||||
profile = "ToolsGuiButtonProfile";
|
||||
command = "MaterialEditorGui.deleteMaterial();";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Delete Material from File";
|
||||
};
|
||||
new GuiBitmapButtonCtrl(MatEd_editMaterial) {
|
||||
BitmapAsset = "ToolsModule:open_file_n_image";
|
||||
position = "249 1";
|
||||
extent = "16 16";
|
||||
horizSizing = "left";
|
||||
profile = "GuiDefaultProfile";
|
||||
command = "AssetBrowser.showDialog(\"MaterialAsset\", \"MaterialEditorGui.selectMaterialAsset\");";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Open Existing Material";
|
||||
};
|
||||
new GuiBitmapButtonCtrl() {
|
||||
BitmapAsset = "ToolsModule:new_n_image";
|
||||
position = "269 1";
|
||||
extent = "16 16";
|
||||
horizSizing = "left";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
command = "MaterialEditorGui.createNewMaterial();";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Create New Material";
|
||||
};
|
||||
new GuiBitmapButtonCtrl() {
|
||||
BitmapAsset = "ToolsModule:save_icon_n_image";
|
||||
position = "289 1";
|
||||
extent = "16 16";
|
||||
horizSizing = "left";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
command = "MaterialEditorGui.save();";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Save Material (ALT S)";
|
||||
};
|
||||
new GuiBitmapButtonCtrl() {
|
||||
BitmapAsset = "ToolsModule:visible_n_image";
|
||||
position = "309 1";
|
||||
extent = "16 16";
|
||||
horizSizing = "left";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
command = "MaterialEditorGui.lookupMaterialInstances();";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Lookup Material Instances";
|
||||
};
|
||||
new GuiBitmapCtrl() {
|
||||
BitmapAsset = "ToolsModule:separator_h_image";
|
||||
BitmapFile = "tools/gui/images/separator-h.png";
|
||||
position = "330 1";
|
||||
extent = "2 16";
|
||||
minExtent = "2 16";
|
||||
horizSizing = "left";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiBitmapButtonCtrl() {
|
||||
BitmapAsset = "ToolsModule:reset_icon_n_image";
|
||||
position = "334 1";
|
||||
extent = "17 17";
|
||||
horizSizing = "left";
|
||||
profile = "ToolsGuiButtonProfile";
|
||||
command = "MaterialEditorGui.refreshMaterial();";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Revert Material to Saved";
|
||||
};
|
||||
new GuiBitmapButtonCtrl() {
|
||||
BitmapAsset = "ToolsModule:clear_icon_n_image";
|
||||
position = "351 1";
|
||||
extent = "17 17";
|
||||
horizSizing = "left";
|
||||
profile = "ToolsGuiButtonProfile";
|
||||
command = "MaterialEditorGui.clearMaterial();";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Clear All Material Properties";
|
||||
};
|
||||
};
|
||||
new GuiContainer() {
|
||||
position = "0 27";
|
||||
extent = "388 88";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
|
||||
new GuiContainer(MatEdMaterialMode) {
|
||||
extent = "392 39";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
|
||||
new GuiTextCtrl() {
|
||||
Text = "Material";
|
||||
position = "10 1";
|
||||
extent = "50 16";
|
||||
profile = "ToolsGuiTextRightProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiTextEditCtrl() {
|
||||
position = "80 0";
|
||||
extent = "305 20";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiTextEditProfile";
|
||||
altCommand = "MaterialEditorGui.setMaterialDirty();MaterialEditorGui.updateActiveMaterialName($ThisControl.getText());";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "selMaterialName";
|
||||
};
|
||||
new GuiTextCtrl() {
|
||||
position = "70 20";
|
||||
extent = "317 16";
|
||||
horizSizing = "width";
|
||||
profile = "GuiTextProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
};
|
||||
new GuiContainer(MatEdTargetMode) {
|
||||
extent = "394 20";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
visible = "0";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
hidden = "1";
|
||||
|
||||
new GuiTextCtrl() {
|
||||
Text = "Material Slot";
|
||||
position = "4 1";
|
||||
extent = "74 16";
|
||||
profile = "ToolsGuiTextRightProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
ToolTip = "List of Material Slots available for selected object (If applicable)";
|
||||
};
|
||||
new GuiPopUpMenuCtrlEx(SubMaterialSelector) {
|
||||
Text = "MaterialAsset";
|
||||
position = "96 0";
|
||||
extent = "292 17";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiPopUpMenuProfile";
|
||||
active = "0";
|
||||
command = "SubMaterialSelector.onSelect();";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
ToolTip = "Target Material Slot";
|
||||
};
|
||||
};
|
||||
new GuiContainer() {
|
||||
position = "0 24";
|
||||
extent = "394 62";
|
||||
horizSizing = "width";
|
||||
profile = "GuiDefaultProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
|
||||
new GuiTextCtrl() {
|
||||
Text = "MapTo";
|
||||
position = "6 2";
|
||||
extent = "58 16";
|
||||
profile = "ToolsGuiTextRightProfile";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Name of material slot lookup to associate this material to for shapes.";
|
||||
};
|
||||
new GuiTextEditCtrl() {
|
||||
position = "80 -2";
|
||||
extent = "307 20";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiTextEditProfile";
|
||||
altCommand = "MaterialEditorGui.setMaterialDirty();MaterialEditorGui.updateActiveMaterialMapTo($ThisControl.getText());";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Name of material slot lookup to associate this material to for shapes.";
|
||||
internalName = "selMaterialMapTo";
|
||||
};
|
||||
new GuiTextCtrl() {
|
||||
Text = "Inherit From";
|
||||
position = "6 25";
|
||||
extent = "69 16";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Other material that this one should inherit fields from as its parent.";
|
||||
profile = "ToolsGuiTextRightProfile";
|
||||
};
|
||||
new GuiTextEditCtrl() {
|
||||
position = "80 21";
|
||||
extent = "285 20";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiTextEditProfile";
|
||||
altCommand = "MaterialEditorGui.setMaterialDirty();MaterialEditorGui.updateActiveMaterialInheritFrom($ThisControl.getText());";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
internalName = "selMaterialInheritFrom";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Other material that this one should inherit fields from as its parent.";
|
||||
};
|
||||
new GuiBitmapButtonCtrl() {
|
||||
BitmapAsset = "ToolsModule:material_image";
|
||||
position = "368 24";
|
||||
extent = "16 16";
|
||||
horizSizing = "left";
|
||||
profile = "GuiDefaultProfile";
|
||||
command = "AssetBrowser.showDialog(\"MaterialAsset\", \"MaterialEditorGui.updateActiveMaterialInheritFrom\");";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Select Material to set as this material to inherit from.";
|
||||
};
|
||||
new GuiTextCtrl() {
|
||||
Text = "Layer";
|
||||
position = "4 46";
|
||||
extent = "56 16";
|
||||
profile = "ToolsGuiTextRightProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiPopUpMenuCtrlEx(MaterialEditorLayerSelector) {
|
||||
Text = "Layer 0";
|
||||
position = "80 45";
|
||||
extent = "305 17";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiPopUpMenuProfile";
|
||||
command = "MaterialEditorGui.changeLayer( $ThisControl.getText() );";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
ToolTip = "Material Layer";
|
||||
};
|
||||
};
|
||||
};
|
||||
new GuiContainer() {
|
||||
docking = "None";
|
||||
margin = "0 43 0 5";
|
||||
anchorTop = "0";
|
||||
anchorLeft = "0";
|
||||
position = "0 120";
|
||||
extent = "382 793";
|
||||
minExtent = "64 64";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
isContainer = "0";
|
||||
|
||||
new GuiTextEditCtrl(MaterialEditorGuiFilter) {
|
||||
placeholderText = "Filter...";
|
||||
validate = "MaterialEditorPropInspector.setSearchText($ThisControl.getText());";
|
||||
position = "5 0";
|
||||
extent = "383 20";
|
||||
horizSizing = "width";
|
||||
profile = "ToolsGuiTextEditProfile";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
};
|
||||
new GuiBitmapButtonCtrl() {
|
||||
BitmapAsset = "ToolsModule:clear_icon_n_image";
|
||||
position = "371 1";
|
||||
extent = "17 17";
|
||||
horizSizing = "left";
|
||||
profile = "ToolsGuiDefaultProfile";
|
||||
command = "MaterialEditorGuiFilter.setText(\"\");MaterialEditorPropInspector.setSearchText(\"\");";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
};
|
||||
new GuiScrollCtrl() {
|
||||
hScrollBar = "alwaysOff";
|
||||
lockHorizScroll = "1";
|
||||
docking = "None";
|
||||
anchorTop = "0";
|
||||
anchorLeft = "0";
|
||||
position = "5 22";
|
||||
extent = "382 766";
|
||||
minExtent = "8 8";
|
||||
horizSizing = "width";
|
||||
vertSizing = "height";
|
||||
profile = "GuiEditorScrollProfile";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
|
||||
new GuiInspector(MaterialEditorPropInspector) {
|
||||
groupFilters = "-Internal -Ungrouped -Editing -Object -Persistence -Dynamic Fields";
|
||||
forcedArrayIndex = "0";
|
||||
position = "1 1";
|
||||
extent = "367 48";
|
||||
minExtent = "8 8";
|
||||
horizSizing = "width";
|
||||
profile = "GuiInspectorProfile";
|
||||
tooltipProfile = "ToolsGuiToolTipProfile";
|
||||
superClass = "EditorInspectorBase";
|
||||
collapseState = "1 1 0 0 0 0 0 0";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
//--- OBJECT WRITE END ---
|
||||
|
|
@ -1,456 +0,0 @@
|
|||
//--- OBJECT WRITE BEGIN ---
|
||||
$guiContent = new GuiControl() {
|
||||
canSaveDynamicFields = "0";
|
||||
internalName = "MatEdPreviewWindowContainer";
|
||||
Enabled = "1";
|
||||
isContainer = "1";
|
||||
Profile = "ToolsGuiDefaultProfile";
|
||||
HorizSizing = "width";
|
||||
VertSizing = "height";
|
||||
Position = "0 0";
|
||||
Extent = "800 600";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
hovertime = "1000";
|
||||
|
||||
new GuiWindowCollapseCtrl(MaterialEditorPreviewWindow) {
|
||||
canSaveDynamicFields = "0";
|
||||
internalName = "MatEdPreviewWindow";
|
||||
Enabled = "1";
|
||||
isContainer = "1";
|
||||
Profile = "ToolsGuiWindowProfile";
|
||||
HorizSizing = "windowRelative";
|
||||
VertSizing = "windowRelative";
|
||||
Position = getWord($pref::Video::mode, 0) - 360
|
||||
SPC getWord(EditorGuiToolbar.extent, 1) + 6;
|
||||
Extent = "360 300";
|
||||
MinExtent = "300 150";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
hovertime = "1000";
|
||||
Margin = "4 4 4 4";
|
||||
Padding = "0 0 0 0";
|
||||
AnchorTop = "1";
|
||||
AnchorBottom = "0";
|
||||
AnchorLeft = "1";
|
||||
AnchorRight = "0";
|
||||
resizeWidth = "1";
|
||||
resizeHeight = "1";
|
||||
canMove = "1";
|
||||
canClose = "0";
|
||||
canMinimize = "0";
|
||||
canMaximize = "0";
|
||||
closeCommand = "MaterialEditorPreviewWindow.setVisible(false);";
|
||||
minSize = "50 50";
|
||||
EdgeSnap = "1";
|
||||
text = ":: Material Editor - Preview";
|
||||
|
||||
/*new GuiContainer(MaterialEditorPreviewPane) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "1"; //1
|
||||
Profile = "ToolsGuiDefaultProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
Position = "4 23";
|
||||
Extent = "200 221";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
Docking = "Client";
|
||||
Margin = "0 0 0 0";
|
||||
Padding = "0 0 0 0";
|
||||
AnchorTop = "1";
|
||||
AnchorBottom = "0";
|
||||
AnchorLeft = "1";
|
||||
AnchorRight = "0";*/
|
||||
|
||||
new GuiContainer(matEd_previewPanel) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "1";
|
||||
Profile = "ToolsGuiDefaultProfile";
|
||||
HorizSizing = "width";
|
||||
VertSizing = "height";
|
||||
position = "4 45";
|
||||
Extent = "300 300";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
hovertime = "1000";
|
||||
Docking = "Client";
|
||||
Margin = "24 1 3 3 ";
|
||||
|
||||
|
||||
new GuiSwatchButtonCtrl(matEd_previewBackground) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
Profile = "GuiInspectorSwatchButtonProfile";
|
||||
HorizSizing = "width";
|
||||
VertSizing = "height";
|
||||
position = "-1 -1";
|
||||
Extent = "302 302";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
hovertime = "1000";
|
||||
color = "0 0 0 .8";
|
||||
//bitmap = "tools/materialEditor/gui/gridTiny2.PNG";
|
||||
//wrap = "1";
|
||||
};
|
||||
new GuiContainer(){ // this is blocking the mouse imput to the swatch imput behind it
|
||||
HorizSizing = "width";
|
||||
VertSizing = "height";
|
||||
Position = "-1 -1";
|
||||
Extent = "302 302";
|
||||
};
|
||||
new GuiMaterialPreview(matEd_previewObjectView) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiDefaultProfile";
|
||||
HorizSizing = "width";
|
||||
VertSizing = "height";
|
||||
position = "1 1";
|
||||
Extent = "299 299";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
hovertime = "1000";
|
||||
Margin = "0 0 0 0";
|
||||
Padding = "0 0 0 0";
|
||||
AnchorTop = "1";
|
||||
AnchorBottom = "0";
|
||||
AnchorLeft = "1";
|
||||
AnchorRight = "0";
|
||||
cameraZRot = "0";
|
||||
forceFOV = "0";
|
||||
};
|
||||
//};
|
||||
};
|
||||
|
||||
new GuiPopUpMenuCtrl(matEd_quickPreview_Popup) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiPopUpMenuProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
position = "4 24";
|
||||
Extent = "67 18";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "MaterialEditorGui.updatePreviewObject();";
|
||||
ToolTip = "Changes the Preview Mesh";
|
||||
hovertime = "1000";
|
||||
Margin = "0 0 0 0";
|
||||
Padding = "0 0 0 0";
|
||||
AnchorTop = "1";
|
||||
AnchorBottom = "0";
|
||||
AnchorLeft = "1";
|
||||
AnchorRight = "0";
|
||||
text = "Sphere";
|
||||
maxLength = "1024";
|
||||
maxPopupHeight = "200";
|
||||
sbUsesNAColor = "0";
|
||||
reverseTextList = "0";
|
||||
bitmapBounds = "16 16";
|
||||
};
|
||||
new GuiSwatchButtonCtrl(MaterialPreviewBackgroundPicker) { // Background Color
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
Profile = "GuiInspectorSwatchButtonProfile";
|
||||
HorizSizing = "left";
|
||||
VertSizing = "top";
|
||||
position = "330 270";
|
||||
Extent = "20 20";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "getColorF($thisControl.color, \"MaterialEditorGui.updatePreviewBackground\");";
|
||||
color = "0 0 0 .7";
|
||||
hovertime = "1000";
|
||||
groupNum = "-1";
|
||||
buttonType = "PushButton";
|
||||
useMouseEvents = "0";
|
||||
ToolTip ="Change Background Color (preview)";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
};
|
||||
|
||||
// Ambient light color picker
|
||||
new GuiSwatchButtonCtrl(matEd_ambientLightColorPicker) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
color = "1 1 1 1";
|
||||
isContainer = "0";
|
||||
Profile = "GuiInspectorSwatchButtonProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
position = "81 28";
|
||||
Extent = "14 14";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "getColorF($ThisControl.color, \"MaterialEditorGui.updateAmbientColor\");";
|
||||
hovertime = "1000";
|
||||
groupNum = "-1";
|
||||
ToolTip ="Change Ambient Light Color";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
buttonType = "PushButton";
|
||||
useMouseEvents = "0";
|
||||
};
|
||||
// Light color picker
|
||||
new GuiSwatchButtonCtrl(matEd_lightColorPicker) {
|
||||
canSaveDynamicFields = "0";
|
||||
Enabled = "1";
|
||||
color = "1 1 1 1";
|
||||
isContainer = "0";
|
||||
Profile = "GuiInspectorSwatchButtonProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
position = "75 23";
|
||||
Extent = "14 14";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "getColorF($ThisControl.color, \"MaterialEditorGui.updateLightColor\");";
|
||||
hovertime = "1000";
|
||||
groupNum = "-1";
|
||||
ToolTip ="Change Normal Light Color";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
buttonType = "PushButton";
|
||||
useMouseEvents = "0";
|
||||
};
|
||||
|
||||
new GuiCheckboxCtrl(){
|
||||
position = "245 25";
|
||||
Extent = "98 18";
|
||||
HorizSizing = "left";
|
||||
profile = "ToolsGuiCheckBoxProfile";
|
||||
Variable = "MaterialEditorGui.livePreview";
|
||||
Command = "MaterialEditorGui.updateLivePreview($ThisControl.getValue());";
|
||||
text = "Preview in World";
|
||||
};
|
||||
// window / panel buttons
|
||||
new GuiBitmapButtonCtrl(MaterialEditorGui_UnDockBtn) {
|
||||
canSaveDynamicFields = "0";
|
||||
internalName = "";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiButtonProfile";
|
||||
HorizSizing = "left";
|
||||
VertSizing = "bottom";
|
||||
Position = "330 1";
|
||||
Extent = "18 18";
|
||||
MinExtent = "8 8";
|
||||
canSave = "1";
|
||||
Visible = "0";
|
||||
Command = "MaterialEditorGui.releaseSidePanel();";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Detach Sidepanel";
|
||||
hovertime = "1000";
|
||||
bitmapAsset = "ToolsModule:panel_undock_n_image";
|
||||
text = "";
|
||||
groupNum = "-1";
|
||||
buttonType = "PushButton";
|
||||
useMouseEvents = "0";
|
||||
};
|
||||
|
||||
new GuiBitmapButtonCtrl(MaterialEditorGui_DockBtn) {
|
||||
canSaveDynamicFields = "0";
|
||||
internalName = "";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiButtonProfile";
|
||||
HorizSizing = "left";
|
||||
VertSizing = "bottom";
|
||||
Position = "330 1";
|
||||
Extent = "18 18";
|
||||
MinExtent = "8 8";
|
||||
canSave = "1";
|
||||
Visible = "0";
|
||||
Command = "MaterialEditorGui.dockSidePanel();";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Dock Sidepanel";
|
||||
hovertime = "1000";
|
||||
bitmapAsset = "ToolsModule:panel_dock_n_image";
|
||||
text = "";
|
||||
groupNum = "-1";
|
||||
buttonType = "PushButton";
|
||||
useMouseEvents = "0";
|
||||
};
|
||||
new GuiBitmapButtonCtrl(MaterialEditorGui_HideBtn) {
|
||||
canSaveDynamicFields = "0";
|
||||
internalName = "";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiButtonProfile";
|
||||
HorizSizing = "left";
|
||||
VertSizing = "bottom";
|
||||
Position = "312 1";
|
||||
Extent = "18 18";
|
||||
MinExtent = "8 8";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "MaterialEditorGui.hideSidePanel();";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Hide Sidepanel";
|
||||
hovertime = "1000";
|
||||
bitmapAsset = "ToolsModule:panel_hide_n_image";
|
||||
text = "";
|
||||
groupNum = "-1";
|
||||
buttonType = "PushButton";
|
||||
useMouseEvents = "0";
|
||||
};
|
||||
new GuiBitmapButtonCtrl(MaterialEditorGui_ShowBtn) {
|
||||
canSaveDynamicFields = "0";
|
||||
internalName = "";
|
||||
Enabled = "1";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiButtonProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
Position = "4 1";
|
||||
Extent = "18 18";
|
||||
MinExtent = "8 8";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
Command = "MaterialEditorGui.showSidePanel();";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
ToolTip = "Show Sidepanel";
|
||||
hovertime = "1000";
|
||||
bitmapAsset = "ToolsModule:panel_show_n_image";
|
||||
text = "";
|
||||
groupNum = "-1";
|
||||
buttonType = "PushButton";
|
||||
useMouseEvents = "0";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
new GuiWindowCtrl(matEd_addCubemapWindow) {
|
||||
canSaveDynamicFields = "0";
|
||||
isContainer = "1";
|
||||
Profile = "ToolsGuiWindowProfile";
|
||||
HorizSizing = "center";
|
||||
VertSizing = "center";
|
||||
position = "362 333";
|
||||
Extent = "300 99";
|
||||
MinExtent = "48 92";
|
||||
canSave = "1";
|
||||
Visible = "0";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
Margin = "0 0 0 0";
|
||||
Padding = "0 0 0 0";
|
||||
AnchorTop = "1";
|
||||
AnchorBottom = "0";
|
||||
AnchorLeft = "1";
|
||||
AnchorRight = "0";
|
||||
resizeWidth = "1";
|
||||
resizeHeight = "1";
|
||||
canMove = "1";
|
||||
canClose = "0";
|
||||
canMinimize = "0";
|
||||
canMaximize = "0";
|
||||
minSize = "50 50";
|
||||
EdgeSnap = "1";
|
||||
text = "Create Cubemap";
|
||||
|
||||
new GuiTextEditCtrl() {
|
||||
canSaveDynamicFields = "0";
|
||||
internalName = "cubemapName";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiTextEditProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
position = "96 35";
|
||||
Extent = "196 18";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
Margin = "0 0 0 0";
|
||||
Padding = "0 0 0 0";
|
||||
AnchorTop = "1";
|
||||
AnchorBottom = "0";
|
||||
AnchorLeft = "1";
|
||||
AnchorRight = "0";
|
||||
maxLength = "1024";
|
||||
historySize = "0";
|
||||
password = "0";
|
||||
tabComplete = "0";
|
||||
sinkAllKeyEvents = "0";
|
||||
AltCommand = "";
|
||||
passwordMask = "*";
|
||||
};
|
||||
new GuiTextCtrl() {
|
||||
canSaveDynamicFields = "0";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiTextProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
position = "12 36";
|
||||
Extent = "77 16";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
Margin = "0 0 0 0";
|
||||
Padding = "0 0 0 0";
|
||||
AnchorTop = "1";
|
||||
AnchorBottom = "0";
|
||||
AnchorLeft = "1";
|
||||
AnchorRight = "0";
|
||||
maxLength = "1024";
|
||||
text = "Cubemap Name";
|
||||
};
|
||||
new GuiButtonCtrl() {
|
||||
canSaveDynamicFields = "0";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiButtonProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
position = "96 68";
|
||||
Extent = "126 22";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
groupNum = "-1";
|
||||
buttonType = "PushButton";
|
||||
useMouseEvents = "0";
|
||||
text = "Create";
|
||||
Command = "MaterialEditorGui.addCubemap( matEd_addCubemapWindow-->cubemapName.getText() );matEd_addCubemapWindow.setVisible(0);";
|
||||
};
|
||||
new GuiButtonCtrl() {
|
||||
canSaveDynamicFields = "0";
|
||||
isContainer = "0";
|
||||
Profile = "ToolsGuiButtonProfile";
|
||||
HorizSizing = "right";
|
||||
VertSizing = "bottom";
|
||||
position = "228 68";
|
||||
Extent = "64 22";
|
||||
MinExtent = "8 2";
|
||||
canSave = "1";
|
||||
Visible = "1";
|
||||
tooltipprofile = "ToolsGuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
groupNum = "-1";
|
||||
buttonType = "PushButton";
|
||||
useMouseEvents = "0";
|
||||
text = "Cancel";
|
||||
Command = "matEd_addCubemapWindow.setVisible(0);";
|
||||
};
|
||||
};
|
||||
};
|
||||
//--- OBJECT WRITE END ---
|
||||
|
Before Width: | Height: | Size: 470 B After Width: | Height: | Size: 470 B |
|
Before Width: | Height: | Size: 465 B After Width: | Height: | Size: 465 B |
|
Before Width: | Height: | Size: 469 B After Width: | Height: | Size: 469 B |
|
Before Width: | Height: | Size: 306 B After Width: | Height: | Size: 306 B |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 289 B |
|
Before Width: | Height: | Size: 178 B After Width: | Height: | Size: 178 B |
|
Before Width: | Height: | Size: 189 B After Width: | Height: | Size: 189 B |
|
Before Width: | Height: | Size: 178 B After Width: | Height: | Size: 178 B |