mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-11 14:44:36 +00:00
Merge branch 'development' of https://github.com/TorqueGameEngines/Torque3D into TreeWork
This commit is contained in:
commit
a0a22178c3
23 changed files with 447 additions and 135 deletions
|
|
@ -180,6 +180,11 @@ bool AIController::getAIMove(Move* movePtr)
|
|||
if (obj->getContainer()->castRay(start, end, StaticShapeObjectType, &info))
|
||||
{
|
||||
getNav()->repath();
|
||||
mMovement.mInAir = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMovement.mInAir = true;
|
||||
}
|
||||
obj->enableCollision();
|
||||
getGoal()->mInRange = false;
|
||||
|
|
@ -307,6 +312,13 @@ void AIController::Movement::onStuck()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool AIController::Movement::isInWater()
|
||||
{
|
||||
ShapeBase* sbo = dynamic_cast<ShapeBase*>(getCtrl()->getAIInfo()->mObj.getPointer());
|
||||
if (!sbo) return false;
|
||||
return sbo->getWaterCoverage() > 0.0f;
|
||||
}
|
||||
|
||||
DefineEngineMethod(AIController, setMoveSpeed, void, (F32 speed), ,
|
||||
"@brief Sets the move speed for an AI object.\n\n"
|
||||
|
||||
|
|
@ -335,6 +347,23 @@ DefineEngineMethod(AIController, stop, void, (), ,
|
|||
object->mMovement.stopMove();
|
||||
}
|
||||
|
||||
DefineEngineMethod(AIController, isStopped, bool, (), ,
|
||||
"@brief is the player moving?.\n\n")
|
||||
{
|
||||
return object->mMovement.isStopped();
|
||||
}
|
||||
|
||||
DefineEngineMethod(AIController, isInAir, bool, (), ,
|
||||
"@brief is the player moving?.\n\n")
|
||||
{
|
||||
return object->mMovement.isInAir();
|
||||
}
|
||||
|
||||
DefineEngineMethod(AIController, isInWater, bool, (), ,
|
||||
"@brief is the player in water?.\n\n")
|
||||
{
|
||||
return object->mMovement.isInWater();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state of a movement trigger.
|
||||
|
|
|
|||
|
|
@ -85,10 +85,11 @@ public:
|
|||
AIController* mControllerRef;
|
||||
AIController* getCtrl() { return mControllerRef; };
|
||||
MoveState mMoveState;
|
||||
bool mInAir = false;
|
||||
F32 mMoveSpeed = 1.0;
|
||||
void setMoveSpeed(F32 speed) { mMoveSpeed = speed; };
|
||||
F32 getMoveSpeed() { return mMoveSpeed; };
|
||||
bool mMoveSlowdown; // Slowdown as we near the destination
|
||||
bool mMoveSlowdown = false; // Slowdown as we near the destination
|
||||
Point3F mLastLocation; // For stuck check
|
||||
S32 mMoveStuckTestCountdown; // The current countdown until at AI starts to check if it is stuck
|
||||
Point3F mAimLocation;
|
||||
|
|
@ -96,6 +97,9 @@ public:
|
|||
bool mMoveTriggers[MaxTriggerKeys];
|
||||
void stopMove();
|
||||
void onStuck();
|
||||
bool isStopped() { return mMoveState == ModeStop; };
|
||||
bool isInAir() { return mInAir; };
|
||||
bool isInWater();
|
||||
} mMovement;
|
||||
|
||||
struct TriggerState
|
||||
|
|
|
|||
|
|
@ -1436,15 +1436,13 @@ void ConvexShape::_updateGeometry( bool updateCollision )
|
|||
const Vector< U32 > &facePntMap = face.points;
|
||||
const Vector< ConvexShape::Triangle > &triangles = face.triangles;
|
||||
|
||||
const Point3F binormal = mCross(face.normal, face.tangent);
|
||||
|
||||
for (S32 j = 0; j < triangles.size(); j++)
|
||||
{
|
||||
for (S32 k = 0; k < 3; k++)
|
||||
{
|
||||
pVert->normal = face.normal;
|
||||
pVert->T = face.tangent;
|
||||
pVert->B = mCross(face.normal,face.tangent);
|
||||
pVert->B = mCross(face.normal, face.tangent);
|
||||
pVert->point = pointList[facePntMap[triangles[j][k]]];
|
||||
pVert->texCoord = face.texcoords[triangles[j][k]];
|
||||
pVert->texCoord2 = pVert->texCoord;
|
||||
|
|
@ -1966,10 +1964,12 @@ void ConvexShape::Geometry::generate(const Vector< PlaneF > &planes, const Vecto
|
|||
|
||||
U32 *vertMap = new U32[pntCount];
|
||||
|
||||
Point3F binormal = mCross(newFace.normal, newFace.tangent);
|
||||
|
||||
MatrixF quadMat( true );
|
||||
quadMat.setPosition( averagePnt );
|
||||
quadMat.setColumn( 0, newFace.tangent );
|
||||
quadMat.setColumn( 1, mCross( newFace.normal, newFace.tangent ) );
|
||||
quadMat.setColumn( 1, binormal);
|
||||
quadMat.setColumn( 2, newFace.normal );
|
||||
quadMat.inverse();
|
||||
|
||||
|
|
@ -2055,8 +2055,8 @@ void ConvexShape::Geometry::generate(const Vector< PlaneF > &planes, const Vecto
|
|||
|
||||
|
||||
// Calculate texture coordinates for each point in this face.
|
||||
if (newFace.normal.z < -0.9f) binormal = -binormal;
|
||||
|
||||
const Point3F binormal = mCross( newFace.normal, newFace.tangent );
|
||||
PlaneF planey( newFace.centroid - 0.5f * binormal, binormal );
|
||||
PlaneF planex( newFace.centroid - 0.5f * newFace.tangent, newFace.tangent );
|
||||
|
||||
|
|
@ -2064,7 +2064,7 @@ void ConvexShape::Geometry::generate(const Vector< PlaneF > &planes, const Vecto
|
|||
|
||||
for ( S32 j = 0; j < newFace.points.size(); j++ )
|
||||
{
|
||||
F32 x = planex.distToPlane( points[ newFace.points[ j ] ] );
|
||||
F32 x = -planex.distToPlane( points[ newFace.points[ j ] ] );
|
||||
F32 y = planey.distToPlane( points[ newFace.points[ j ] ] );
|
||||
|
||||
if (!texOffset.empty())
|
||||
|
|
@ -2086,7 +2086,7 @@ void ConvexShape::Geometry::generate(const Vector< PlaneF > &planes, const Vecto
|
|||
if (vertFlip.size() > 0 && vertFlip[i])
|
||||
y *= -1;
|
||||
|
||||
newFace.texcoords[j].set(-x, -y);
|
||||
newFace.texcoords[j].set(x, y);
|
||||
}
|
||||
|
||||
// Data verification tests.
|
||||
|
|
|
|||
|
|
@ -535,7 +535,7 @@ bool ParticleData::onAdd()
|
|||
{
|
||||
Con::warnf(ConsoleLogEntry::General,
|
||||
"ParticleData(%s) bad value(s) for animTexTiling [%d or %d <= 0], invalid datablock",
|
||||
animTexTiling.x, animTexTiling.y, getName());
|
||||
getName(), animTexTiling.x, animTexTiling.y);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ IMPLEMENT_CALLBACK( Item, onLeaveLiquid, void, ( const char* objID, const char*
|
|||
Item::Item()
|
||||
{
|
||||
mTypeMask |= ItemObjectType | DynamicShapeObjectType;
|
||||
mPathfindingIgnore = true;
|
||||
mDataBlock = 0;
|
||||
mStatic = false;
|
||||
mRotate = false;
|
||||
|
|
|
|||
|
|
@ -1552,7 +1552,7 @@ ConsoleDocClass( Player,
|
|||
Player::Player()
|
||||
{
|
||||
mTypeMask |= PlayerObjectType | DynamicShapeObjectType;
|
||||
|
||||
mPathfindingIgnore = true;
|
||||
mDelta.pos = mAnchorPoint = Point3F(0,0,100);
|
||||
mDelta.rot = mDelta.head = Point3F(0,0,0);
|
||||
mDelta.rotOffset.set(0.0f,0.0f,0.0f);
|
||||
|
|
|
|||
|
|
@ -376,7 +376,7 @@ Vehicle::Vehicle()
|
|||
{
|
||||
mDataBlock = 0;
|
||||
mTypeMask |= VehicleObjectType | DynamicShapeObjectType;
|
||||
|
||||
mPathfindingIgnore = true;
|
||||
mDelta.pos = Point3F(0,0,0);
|
||||
mDelta.posVec = Point3F(0,0,0);
|
||||
mDelta.warpTicks = mDelta.warpCount = 0;
|
||||
|
|
|
|||
|
|
@ -1529,6 +1529,7 @@ U32 FunctionDeclStmtNode::compileStmt(CodeStream& codeStream, U32 ip)
|
|||
|
||||
CodeBlock::smInFunction = false;
|
||||
|
||||
setCurrentStringTable(&getGlobalStringTable());
|
||||
// check for argument setup
|
||||
for (VarNode* walk = args; walk; walk = (VarNode*)((StmtNode*)walk)->getNext())
|
||||
{
|
||||
|
|
@ -1541,6 +1542,7 @@ U32 FunctionDeclStmtNode::compileStmt(CodeStream& codeStream, U32 ip)
|
|||
ip = walk->defaultValue->compile(codeStream, ip, walkType);
|
||||
}
|
||||
}
|
||||
setCurrentStringTable(&getFunctionStringTable());
|
||||
|
||||
codeStream.emit(OP_FUNC_DECL);
|
||||
codeStream.emitSTE(fnName);
|
||||
|
|
|
|||
|
|
@ -288,6 +288,13 @@ enum ChannelSemantic : U8
|
|||
CH_B
|
||||
};
|
||||
|
||||
struct PackedChannelDesc
|
||||
{
|
||||
ChannelSemantic semantic;
|
||||
U8 bits;
|
||||
U8 shift;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// Bitmap format descriptor
|
||||
struct GBitmapFormatDesc
|
||||
|
|
@ -299,7 +306,9 @@ struct GBitmapFormatDesc
|
|||
bool premultiplied;
|
||||
bool isFloat;
|
||||
U8 bytesPerChannel;
|
||||
|
||||
bool isPacked = false;
|
||||
U8 bytesPerPixel = 0;
|
||||
PackedChannelDesc packed[4] = {};
|
||||
bool is8() const { return !isFloat && bytesPerChannel == 1; }
|
||||
bool is16() const { return !isFloat && bytesPerChannel == 2; }
|
||||
};
|
||||
|
|
@ -316,17 +325,47 @@ GBitmapFormatDesc getFormatDesc(GFXFormat fmt)
|
|||
case GFXFormatL8:
|
||||
return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
||||
case GFXFormatA4L4:
|
||||
return { 2, {CH_L, CH_A, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
||||
return { 2, {CH_L, CH_A, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 0, true, 1,
|
||||
{
|
||||
{ CH_L, 4, 0 }, // CH_L must be declared before CH_A
|
||||
{ CH_A, 4, 4 }
|
||||
}
|
||||
};
|
||||
|
||||
// 16-bit formats
|
||||
case GFXFormatR5G6B5:
|
||||
return { 3, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
||||
return { 3, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 0, true, 2,
|
||||
{
|
||||
{ CH_R, 5, 11 },
|
||||
{ CH_G, 6, 5 },
|
||||
{ CH_B, 5, 0 }
|
||||
}
|
||||
};
|
||||
case GFXFormatR5G5B5A1:
|
||||
return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
||||
return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_UINT8, false, false, false, 0, true, 2,
|
||||
{
|
||||
{ CH_R, 5, 11 },
|
||||
{ CH_G, 5, 6 },
|
||||
{ CH_B, 5, 1 },
|
||||
{ CH_A, 1, 0 }
|
||||
}
|
||||
};
|
||||
case GFXFormatR5G5B5X1:
|
||||
return { 4, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
||||
return { 4, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 0, true, 2,
|
||||
{
|
||||
{ CH_R, 5, 11 },
|
||||
{ CH_G, 5, 6 },
|
||||
{ CH_B, 5, 1 },
|
||||
{ CH_A, 1, 0 }
|
||||
}
|
||||
};
|
||||
case GFXFormatA8L8:
|
||||
return { 2, {CH_L, CH_A, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
||||
return { 2, {CH_L, CH_A, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 0, true, 2,
|
||||
{
|
||||
{ CH_L, 8, 0 }, // CH_L must be declared before CH_A
|
||||
{ CH_A, 8, 8 }
|
||||
}
|
||||
};
|
||||
case GFXFormatL16:
|
||||
return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT16, false, false, false, 2 };
|
||||
case GFXFormatR16F:
|
||||
|
|
@ -403,10 +442,73 @@ inline float linearToSrgb(float c)
|
|||
return (c <= 0.0031308f) ? c * 12.92f : 1.055f * powf(c, 1.f / 2.4f) - 0.055f;
|
||||
}
|
||||
|
||||
static inline LinearPixel loadPackedPixel(
|
||||
const void* src,
|
||||
const GBitmapFormatDesc& fmt,
|
||||
U32 index)
|
||||
{
|
||||
LinearPixel p;
|
||||
p.r = p.g = p.b = 0.f;
|
||||
p.a = 1.f;
|
||||
|
||||
const U8* base = (const U8*)src + index * fmt.bytesPerPixel;
|
||||
|
||||
U32 raw = 0;
|
||||
dMemcpy(&raw, base, fmt.bytesPerPixel);
|
||||
|
||||
#ifdef TORQUE_BIG_ENDIAN
|
||||
if (fmt.bytesPerPixel == 2)
|
||||
raw = convertLEndianToHost((U16)raw);
|
||||
else if (fmt.bytesPerPixel == 4)
|
||||
raw = convertLEndianToHost((U32)raw);
|
||||
#endif
|
||||
|
||||
for (U32 i = 0; i < fmt.channels; ++i)
|
||||
{
|
||||
const PackedChannelDesc& ch = fmt.packed[i];
|
||||
|
||||
U32 mask = (1u << ch.bits) - 1u;
|
||||
U32 v = (raw >> ch.shift) & mask;
|
||||
|
||||
// Expand to 8-bit exactly like GBitmap getColor code
|
||||
U8 expanded8;
|
||||
if (ch.bits == 5)
|
||||
expanded8 = (v << 3) | (v >> 2);
|
||||
else if (ch.bits == 6)
|
||||
expanded8 = (v << 2) | (v >> 4);
|
||||
else if (ch.bits == 4)
|
||||
expanded8 = v * 17;
|
||||
else if (ch.bits == 1)
|
||||
expanded8 = v ? 255 : 0;
|
||||
else // 8-bit
|
||||
expanded8 = (U8)v;
|
||||
|
||||
float f = expanded8 / 255.f;
|
||||
|
||||
switch (ch.semantic)
|
||||
{
|
||||
case CH_R: p.r = f; break;
|
||||
case CH_G: p.g = f; break;
|
||||
case CH_B: p.b = f; break;
|
||||
case CH_A: p.a = f; break;
|
||||
case CH_L:
|
||||
p.r = p.g = p.b = f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// Load a pixel from src format into LinearPixel
|
||||
static inline LinearPixel loadPixel(const void* src, const GBitmapFormatDesc& fmt, U32 index)
|
||||
{
|
||||
if (fmt.isPacked)
|
||||
return loadPackedPixel(src, fmt, index);
|
||||
|
||||
LinearPixel p;
|
||||
const U8* base = (const U8*)src + index * fmt.channels * fmt.bytesPerChannel;
|
||||
|
||||
|
|
@ -441,10 +543,72 @@ static inline LinearPixel loadPixel(const void* src, const GBitmapFormatDesc& fm
|
|||
return p;
|
||||
}
|
||||
|
||||
static inline void storePackedPixel(
|
||||
void* dst,
|
||||
const GBitmapFormatDesc& fmt,
|
||||
U32 index,
|
||||
const LinearPixel& p)
|
||||
{
|
||||
U32 raw = 0;
|
||||
|
||||
for (U32 i = 0; i < fmt.channels; ++i)
|
||||
{
|
||||
const PackedChannelDesc& ch = fmt.packed[i];
|
||||
|
||||
float v = 0.f;
|
||||
switch (ch.semantic)
|
||||
{
|
||||
case CH_R: v = p.r; break;
|
||||
case CH_G: v = p.g; break;
|
||||
case CH_B: v = p.b; break;
|
||||
case CH_A: v = p.a; break;
|
||||
case CH_L: v = p.r; break; // legacy behavior
|
||||
default: continue;
|
||||
}
|
||||
|
||||
// Clamp
|
||||
v = mClamp(v, 0.f, 1.f);
|
||||
|
||||
// Canonical float → U8
|
||||
U32 expanded8 = U32(v * 255.f + 0.5f);
|
||||
|
||||
// Contract to bit depth EXACTLY like Gbitmap setColor code
|
||||
U32 maxv = (1u << ch.bits) - 1u;
|
||||
U32 iv;
|
||||
|
||||
if (ch.bits == 8)
|
||||
iv = expanded8;
|
||||
else
|
||||
iv = expanded8 * maxv / 255;
|
||||
|
||||
raw |= (iv & maxv) << ch.shift;
|
||||
}
|
||||
|
||||
#ifdef TORQUE_BIG_ENDIAN
|
||||
if (fmt.bytesPerPixel == 2)
|
||||
{
|
||||
U16 v = convertLEndianToHost((U16)raw);
|
||||
dMemcpy((U8*)dst + index * fmt.bytesPerPixel, &v, 2);
|
||||
}
|
||||
else if (fmt.bytesPerPixel == 4)
|
||||
{
|
||||
U32 v = convertLEndianToHost(raw);
|
||||
dMemcpy((U8*)dst + index * fmt.bytesPerPixel, &v, 4);
|
||||
}
|
||||
#else
|
||||
dMemcpy((U8*)dst + index * fmt.bytesPerPixel, &raw, fmt.bytesPerPixel);
|
||||
#endif
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
// Store a LinearPixel into dst format
|
||||
static inline void storePixel(void* dst, const GBitmapFormatDesc& fmt, U32 index, const LinearPixel& p)
|
||||
{
|
||||
if (fmt.isPacked)
|
||||
{
|
||||
storePackedPixel(dst, fmt, index, p);
|
||||
return;
|
||||
}
|
||||
|
||||
U8* base = (U8*)dst + index * fmt.channels * fmt.bytesPerChannel;
|
||||
for (U32 c = 0; c < fmt.channels; ++c)
|
||||
{
|
||||
|
|
@ -455,7 +619,7 @@ static inline void storePixel(void* dst, const GBitmapFormatDesc& fmt, U32 index
|
|||
case CH_G: v = p.g; break;
|
||||
case CH_B: v = p.b; break;
|
||||
case CH_A: v = p.a; break;
|
||||
case CH_L: v = (p.r + p.g + p.b) / 3.f; break;
|
||||
case CH_L: v = p.r; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,45 +61,39 @@ inline F32 convertHalfToFloat(U16 h)
|
|||
U32 exp = (h >> 10) & 0x0000001F;
|
||||
U32 mant = h & 0x000003FF;
|
||||
|
||||
U32 outSign = sign << 31;
|
||||
U32 outExp, outMant;
|
||||
U32 out;
|
||||
|
||||
if (exp == 0)
|
||||
{
|
||||
if (mant == 0)
|
||||
{
|
||||
// Zero
|
||||
outExp = 0;
|
||||
outMant = 0;
|
||||
out = sign;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Subnormal number -> normalize
|
||||
exp = 1;
|
||||
while ((mant & 0x00000400) == 0)
|
||||
exp = 127 - 14;
|
||||
while ((mant & 0x0400) == 0)
|
||||
{
|
||||
mant <<= 1;
|
||||
exp -= 1;
|
||||
exp--;
|
||||
}
|
||||
mant &= 0x000003FF;
|
||||
outExp = (exp + (127 - 15)) << 23;
|
||||
outMant = mant << 13;
|
||||
mant &= 0x03FF;
|
||||
out = sign | (exp << 23) | (mant << 13);
|
||||
}
|
||||
}
|
||||
else if (exp == 31)
|
||||
{
|
||||
// Inf or NaN
|
||||
outExp = 0xFF << 23;
|
||||
outMant = mant ? (mant << 13) : 0;
|
||||
out = sign | 0x7F800000 | (mant << 13);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normalized
|
||||
outExp = (exp + (127 - 15)) << 23;
|
||||
outMant = mant << 13;
|
||||
out = sign | ((exp + (127 - 15)) << 23) | (mant << 13);
|
||||
}
|
||||
|
||||
U32 out = outSign | outExp | outMant;
|
||||
F32 result;
|
||||
dMemcpy(&result, &out, sizeof(F32));
|
||||
return result;
|
||||
|
|
@ -110,40 +104,54 @@ inline U16 convertFloatToHalf(F32 f)
|
|||
U32 bits;
|
||||
dMemcpy(&bits, &f, sizeof(U32));
|
||||
|
||||
U32 sign = (bits >> 16) & 0x00008000;
|
||||
U32 exp = ((bits >> 23) & 0x000000FF) - (127 - 15);
|
||||
U32 sign = (bits >> 16) & 0x8000;
|
||||
U32 exp = (bits >> 23) & 0xFF;
|
||||
U32 mant = bits & 0x007FFFFF;
|
||||
|
||||
if (exp <= 0)
|
||||
{
|
||||
if (exp < -10)
|
||||
return (U16)sign; // Too small => 0
|
||||
mant = (mant | 0x00800000) >> (1 - exp);
|
||||
return (U16)(sign | (mant >> 13));
|
||||
}
|
||||
else if (exp == 0xFF - (127 - 15))
|
||||
if (exp == 255)
|
||||
{
|
||||
// Inf or NaN
|
||||
if (mant == 0)
|
||||
{
|
||||
// Inf
|
||||
return (U16)(sign | 0x7C00);
|
||||
}
|
||||
else
|
||||
{
|
||||
// NaN
|
||||
mant >>= 13;
|
||||
return (U16)(sign | 0x7C00 | mant | (mant == 0));
|
||||
}
|
||||
mant >>= 13;
|
||||
return (U16)(sign | 0x7C00 | mant | (mant == 0));
|
||||
}
|
||||
else
|
||||
|
||||
S32 newExp = (S32)exp - 127 + 15;
|
||||
|
||||
if (newExp >= 31)
|
||||
{
|
||||
if (exp > 30)
|
||||
{
|
||||
// Overflow => Inf
|
||||
return (U16)(sign | 0x7C00);
|
||||
}
|
||||
return (U16)(sign | (exp << 10) | (mant >> 13));
|
||||
// Overflow → Inf
|
||||
return (U16)(sign | 0x7C00);
|
||||
}
|
||||
else if (newExp <= 0)
|
||||
{
|
||||
// Subnormal or underflow
|
||||
if (newExp < -10)
|
||||
return (U16)sign;
|
||||
|
||||
mant |= 0x800000;
|
||||
U32 shifted = mant >> (1 - newExp);
|
||||
|
||||
// Round to nearest-even
|
||||
if (shifted & 0x00001000)
|
||||
shifted += 0x00002000;
|
||||
|
||||
return (U16)(sign | (shifted >> 13));
|
||||
}
|
||||
|
||||
// Normalized with rounding
|
||||
mant += 0x00001000;
|
||||
if (mant & 0x00800000)
|
||||
{
|
||||
mant = 0;
|
||||
newExp++;
|
||||
}
|
||||
|
||||
if (newExp >= 31)
|
||||
return (U16)(sign | 0x7C00);
|
||||
|
||||
return (U16)(sign | (newExp << 10) | (mant >> 13));
|
||||
}
|
||||
|
||||
// Convert a single 16-bit value (0..65535) to 8-bit (0..255)
|
||||
|
|
|
|||
|
|
@ -202,11 +202,10 @@ bool GuiIconButtonCtrl::resize(const Point2I &newPosition, const Point2I &newExt
|
|||
|
||||
void GuiIconButtonCtrl::setBitmap(const char *name)
|
||||
{
|
||||
_setBitmap(name);
|
||||
if(!isAwake())
|
||||
return;
|
||||
|
||||
_setBitmap(name);
|
||||
|
||||
// So that extent is recalculated if autoSize is set.
|
||||
resize( getPosition(), getExtent() );
|
||||
|
||||
|
|
|
|||
|
|
@ -3389,7 +3389,7 @@ void GuiTreeViewCtrl::onMouseDown(const GuiEvent & event)
|
|||
mPossibleRenameItem = NULL;
|
||||
mRenamingItem = NULL;
|
||||
mTempItem = NULL;
|
||||
|
||||
bool wasSelected = isSelected(item);
|
||||
//
|
||||
if( event.modifier & SI_MULTISELECT )
|
||||
{
|
||||
|
|
@ -3473,8 +3473,7 @@ void GuiTreeViewCtrl::onMouseDown(const GuiEvent & event)
|
|||
else if ( !hitFlags.test(OnImage) )
|
||||
{
|
||||
mTempItem = item;
|
||||
|
||||
bool wasSelected = isSelected( item );
|
||||
|
||||
bool multiSelect = getSelectedItemsCount() > 1;
|
||||
|
||||
if( !wasSelected || !multiSelect )
|
||||
|
|
@ -3520,7 +3519,7 @@ void GuiTreeViewCtrl::onMouseDown(const GuiEvent & event)
|
|||
return;
|
||||
|
||||
//
|
||||
if ( mFullRowSelect || hitFlags.test( OnImage ) )
|
||||
if (hitFlags.test(OnImage) || ((mFullRowSelect || hitFlags.test(OnIcon)) && wasSelected))
|
||||
{
|
||||
item->setExpanded(!item->isExpanded());
|
||||
if( !item->isInspectorData() && item->mState.test(Item::VirtualParent) )
|
||||
|
|
|
|||
|
|
@ -454,8 +454,8 @@ S32 NavMesh::getLink(const Point3F &pos)
|
|||
{
|
||||
if(mDeleteLinks[i])
|
||||
continue;
|
||||
SphereF start(getLinkStart(i), mLinkRads[i]);
|
||||
SphereF end(getLinkEnd(i), mLinkRads[i]);
|
||||
SphereF start(getLinkStart(i), mMax(mLinkRads[i],0.25f));
|
||||
SphereF end(getLinkEnd(i), mMax(mLinkRads[i], 0.25f));
|
||||
if(start.isContained(pos) || end.isContained(pos))
|
||||
return i;
|
||||
}
|
||||
|
|
@ -653,7 +653,7 @@ DefineEngineMethod(NavMesh, deleteLinks, void, (),,
|
|||
static void buildCallback(SceneObject* object, void* key)
|
||||
{
|
||||
SceneContainer::CallbackInfo* info = reinterpret_cast<SceneContainer::CallbackInfo*>(key);
|
||||
if (!object->mPathfindingIgnore)
|
||||
if (!object->mPathfindingIgnore && (object->getTypeMask() & MarkerObjectType) == 0)
|
||||
object->buildPolyList(info->context, info->polyList, info->boundingBox, info->boundingSphere);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,10 @@ MODULE_BEGIN( TSShapeInstance )
|
|||
"@brief Enables mesh instancing on non-skin meshes that have less that this count of verts.\n"
|
||||
"The default value is 2000. Higher values can degrade performance.\n"
|
||||
"@ingroup Rendering\n" );
|
||||
|
||||
Con::addVariable("$MaxSkinBones", TypeS32, &TSShape::smMaxSkinBones,
|
||||
"@brief Max number of bones allowed by a given shape for hardwar skinning. Default 70\n"
|
||||
"@ingroup Rendering\n");
|
||||
}
|
||||
|
||||
MODULE_END;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue