diff --git a/Engine/source/T3D/components/component.cpp b/Engine/source/T3D/components/component.cpp index 181c892e5..c7f9dcc2c 100644 --- a/Engine/source/T3D/components/component.cpp +++ b/Engine/source/T3D/components/component.cpp @@ -547,8 +547,9 @@ const char * Component::getDescriptionText(const char *desc) // [tom, 1/12/2007] If it isn't a file, just do it the easy way if (!Platform::isFile(desc)) { - newDesc = new char[dStrlen(desc) + 1]; - dStrcpy(newDesc, desc); + dsize_t newDescLen = dStrlen(desc) + 1; + newDesc = new char[newDescLen]; + dStrcpy(newDesc, desc, newDescLen); return newDesc; } diff --git a/Engine/source/T3D/convexShape.cpp b/Engine/source/T3D/convexShape.cpp index f97b543f6..33e2bc65c 100644 --- a/Engine/source/T3D/convexShape.cpp +++ b/Engine/source/T3D/convexShape.cpp @@ -695,6 +695,54 @@ bool ConvexShape::buildPolyList( PolyListContext context, AbstractPolyList *plis return true; } +bool ConvexShape::buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &) +{ + if (mGeometry.points.empty()) + return false; + + //Get the collision mesh geometry + { + ColladaUtils::ExportData::colMesh* colMesh; + exportData->colMeshes.increment(); + colMesh = &exportData->colMeshes.last(); + + colMesh->mesh.setTransform(&mObjToWorld, mObjScale); + colMesh->mesh.setObject(this); + + //Just get the visible + buildPolyList(PLC_Export, &colMesh->mesh, getWorldBox(), getWorldSphere()); + + colMesh->colMeshName = String::ToString("ColMesh%d-1", exportData->colMeshes.size()); + } + + //Next, process the geometry and materials. + //Convex shapes only have the one 'level', so we'll just rely on the export post-process to back-fill + if (isServerObject() && getClientObject()) + { + ConvexShape* clientShape = dynamic_cast(getClientObject()); + + exportData->meshData.increment(); + + //Prep a meshData for this shape in particular + ColladaUtils::ExportData::meshLODData* meshData = &exportData->meshData.last(); + + //Fill out the info we'll need later to actually append our mesh data for the detail levels during the processing phase + meshData->shapeInst = nullptr; + meshData->originatingObject = this; + meshData->meshTransform = mObjToWorld; + meshData->scale = mObjScale; + + meshData->meshDetailLevels.increment(); + + ColladaUtils::ExportData::detailLevel* curDetail = &meshData->meshDetailLevels.last(); + + //Make sure we denote the size this detail level has + curDetail->size = 512; + } + + return true; +} + void ConvexShape::_export( OptimizedPolyList *plist, const Box3F &box, const SphereF &sphere ) { BaseMatInstance *matInst = mMaterialInst; diff --git a/Engine/source/T3D/convexShape.h b/Engine/source/T3D/convexShape.h index d0f30eeaa..413877a36 100644 --- a/Engine/source/T3D/convexShape.h +++ b/Engine/source/T3D/convexShape.h @@ -172,6 +172,7 @@ public: virtual void prepRenderImage( SceneRenderState *state ); virtual void buildConvex( const Box3F &box, Convex *convex ); virtual bool buildPolyList( PolyListContext context, AbstractPolyList *polyList, const Box3F &box, const SphereF &sphere ); + virtual bool buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &); virtual bool castRay( const Point3F &start, const Point3F &end, RayInfo *info ); virtual bool collideBox( const Point3F &start, const Point3F &end, RayInfo *info ); diff --git a/Engine/source/T3D/decal/decalManager.cpp b/Engine/source/T3D/decal/decalManager.cpp index 2aa3bc2e0..c11faf325 100644 --- a/Engine/source/T3D/decal/decalManager.cpp +++ b/Engine/source/T3D/decal/decalManager.cpp @@ -1495,7 +1495,7 @@ bool DecalManager::_createDataFile() // See if we know our current mission name char missionName[1024]; - dStrcpy( missionName, Con::getVariable( "$Client::MissionFile" ) ); + dStrcpy( missionName, Con::getVariable( "$Client::MissionFile" ), 1024 ); char *dot = dStrstr((const char*)missionName, ".mis"); if(dot) *dot = '\0'; diff --git a/Engine/source/T3D/fx/particle.cpp b/Engine/source/T3D/fx/particle.cpp index 823376fc7..66539ab24 100644 --- a/Engine/source/T3D/fx/particle.cpp +++ b/Engine/source/T3D/fx/particle.cpp @@ -594,8 +594,9 @@ bool ParticleData::preload(bool server, String &errorStr) animTexFrames.clear(); - char* tokCopy = new char[dStrlen(animTexFramesString) + 1]; - dStrcpy(tokCopy, animTexFramesString); + dsize_t tokLen = dStrlen(animTexFramesString) + 1; + char* tokCopy = new char[tokLen]; + dStrcpy(tokCopy, animTexFramesString, tokLen); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) diff --git a/Engine/source/T3D/fx/particleEmitter.cpp b/Engine/source/T3D/fx/particleEmitter.cpp index 4005607d7..cab153574 100644 --- a/Engine/source/T3D/fx/particleEmitter.cpp +++ b/Engine/source/T3D/fx/particleEmitter.cpp @@ -608,8 +608,9 @@ bool ParticleEmitterData::onAdd() // First we parse particleString into a list of particle name tokens Vector dataBlocks(__FILE__, __LINE__); - char* tokCopy = new char[dStrlen(particleString) + 1]; - dStrcpy(tokCopy, particleString); + dsize_t tokLen = dStrlen(particleString) + 1; + char* tokCopy = new char[tokLen]; + dStrcpy(tokCopy, particleString, tokLen); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) diff --git a/Engine/source/T3D/item.cpp b/Engine/source/T3D/item.cpp index a4fc7a339..f31e2e8e0 100644 --- a/Engine/source/T3D/item.cpp +++ b/Engine/source/T3D/item.cpp @@ -1254,7 +1254,7 @@ DefineEngineMethod( Item, getLastStickyPos, const char*, (),, object->mStickyCollisionPos.y, object->mStickyCollisionPos.z); else - dStrcpy(ret, "0 0 0"); + dStrcpy(ret, "0 0 0", bufSize); return ret; } @@ -1277,7 +1277,7 @@ DefineEngineMethod( Item, getLastStickyNormal, const char *, (),, object->mStickyCollisionNormal.y, object->mStickyCollisionNormal.z); else - dStrcpy(ret, "0 0 0"); + dStrcpy(ret, "0 0 0", bufSize); return ret; } diff --git a/Engine/source/T3D/prefab.cpp b/Engine/source/T3D/prefab.cpp index 6d357565f..a30a24217 100644 --- a/Engine/source/T3D/prefab.cpp +++ b/Engine/source/T3D/prefab.cpp @@ -538,6 +538,19 @@ bool Prefab::buildPolyList(PolyListContext context, AbstractPolyList* polyList, return true; } +bool Prefab::buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &sphere) +{ + Vector foundObjects; + mChildGroup->findObjectByType(foundObjects); + + for (S32 i = 0; i < foundObjects.size(); i++) + { + foundObjects[i]->buildExportPolyList(exportData, box, sphere); + } + + return true; +} + ExplodePrefabUndoAction::ExplodePrefabUndoAction( Prefab *prefab ) : UndoAction( "Explode Prefab" ) { diff --git a/Engine/source/T3D/prefab.h b/Engine/source/T3D/prefab.h index 48d87c232..fd1ebc2a4 100644 --- a/Engine/source/T3D/prefab.h +++ b/Engine/source/T3D/prefab.h @@ -98,6 +98,8 @@ public: bool buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F &box, const SphereF& sphere); + bool buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &); + protected: void _closeFile( bool removeFileNotify ); diff --git a/Engine/source/T3D/shapeImage.cpp b/Engine/source/T3D/shapeImage.cpp index 627e8e433..4319baa4e 100644 --- a/Engine/source/T3D/shapeImage.cpp +++ b/Engine/source/T3D/shapeImage.cpp @@ -522,7 +522,7 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr) if (stateSequence[j] && stateSequence[j][0] && stateSequenceRandomFlash[j]) { char bufferVis[128]; dStrncpy(bufferVis, stateSequence[j], 100); - dStrcat(bufferVis, "_vis"); + dStrcat(bufferVis, "_vis", 128); s.sequenceVis[i] = shape[i]->findSequence(bufferVis); } if (s.sequenceVis[i] != -1) diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 97ae395df..89c5983ac 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -1073,6 +1073,97 @@ bool TSStatic::buildPolyList(PolyListContext context, AbstractPolyList* polyList return true; } +bool TSStatic::buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &) +{ + if (!mShapeInstance) + return false; + + if (mCollisionType == Bounds) + { + ColladaUtils::ExportData::colMesh* colMesh; + exportData->colMeshes.increment(); + colMesh = &exportData->colMeshes.last(); + + colMesh->mesh.setTransform(&mObjToWorld, mObjScale); + colMesh->mesh.setObject(this); + + colMesh->mesh.addBox(mObjBox); + + colMesh->colMeshName = String::ToString("ColBox%d-1", exportData->colMeshes.size()); + } + else if (mCollisionType == VisibleMesh) + { + ColladaUtils::ExportData::colMesh* colMesh; + exportData->colMeshes.increment(); + colMesh = &exportData->colMeshes.last(); + + colMesh->mesh.setTransform(&mObjToWorld, mObjScale); + colMesh->mesh.setObject(this); + + mShapeInstance->buildPolyList(&colMesh->mesh, 0); + + colMesh->colMeshName = String::ToString("ColMesh%d-1", exportData->colMeshes.size()); + } + else if (mCollisionType == CollisionMesh) + { + // Everything else is done from the collision meshes + // which may be built from either the visual mesh or + // special collision geometry. + for (U32 i = 0; i < mCollisionDetails.size(); i++) + { + ColladaUtils::ExportData::colMesh* colMesh; + exportData->colMeshes.increment(); + colMesh = &exportData->colMeshes.last(); + + colMesh->mesh.setTransform(&mObjToWorld, mObjScale); + colMesh->mesh.setObject(this); + + mShapeInstance->buildPolyListOpcode(mCollisionDetails[i], &colMesh->mesh, box); + + colMesh->colMeshName = String::ToString("ColMesh%d-1", exportData->colMeshes.size()); + } + } + + //Next, process the LOD levels and materials. + if (isServerObject() && getClientObject()) + { + TSStatic* clientShape = dynamic_cast(getClientObject()); + U32 numDetails = clientShape->mShapeInstance->getNumDetails() - 1; + + exportData->meshData.increment(); + + //Prep a meshData for this shape in particular + ColladaUtils::ExportData::meshLODData* meshData = &exportData->meshData.last(); + + //Fill out the info we'll need later to actually append our mesh data for the detail levels during the processing phase + meshData->shapeInst = clientShape->mShapeInstance; + meshData->originatingObject = this; + meshData->meshTransform = mObjToWorld; + meshData->scale = mObjScale; + + //Iterate over all our detail levels + for (U32 i = 0; i < clientShape->mShapeInstance->getNumDetails(); i++) + { + TSShape::Detail detail = clientShape->mShapeInstance->getShape()->details[i]; + + String detailName = String::ToLower(clientShape->mShapeInstance->getShape()->getName(detail.nameIndex)); + + //Skip it if it's a collision or line of sight element + if (detailName.startsWith("col") || detailName.startsWith("los")) + continue; + + meshData->meshDetailLevels.increment(); + + ColladaUtils::ExportData::detailLevel* curDetail = &meshData->meshDetailLevels.last(); + + //Make sure we denote the size this detail level has + curDetail->size = detail.size; + } + } + + return true; +} + void TSStatic::buildConvex(const Box3F& box, Convex* convex) { if ( mCollisionType == None ) @@ -1279,6 +1370,16 @@ void TSStatic::onUnmount( SceneObject *obj, S32 node ) _updateShouldTick(); } +U32 TSStatic::getNumDetails() +{ + if (isServerObject() && getClientObject()) + { + TSStatic* clientShape = dynamic_cast(getClientObject()); + return clientShape->mShapeInstance->getNumDetails(); + } + return 0; +}; + //------------------------------------------------------------------------ //These functions are duplicated in tsStatic and shapeBase. //They each function a little differently; but achieve the same purpose of gathering diff --git a/Engine/source/T3D/tsStatic.h b/Engine/source/T3D/tsStatic.h index 224086c71..9c6918c8d 100644 --- a/Engine/source/T3D/tsStatic.h +++ b/Engine/source/T3D/tsStatic.h @@ -138,6 +138,7 @@ protected: bool castRay(const Point3F &start, const Point3F &end, RayInfo* info); bool castRayRendered(const Point3F &start, const Point3F &end, RayInfo* info); bool buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F &box, const SphereF& sphere); + bool buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &); void buildConvex(const Box3F& box, Convex* convex); bool _createShape(); @@ -237,6 +238,8 @@ public: TSShapeInstance* getShapeInstance() const { return mShapeInstance; } + U32 getNumDetails(); + const Vector& getCollisionDetails() const { return mCollisionDetails; } const Vector& getLOSDetails() const { return mLOSDetails; } diff --git a/Engine/source/afx/afxMagicMissile.cpp b/Engine/source/afx/afxMagicMissile.cpp index 1cae8526c..b0549e35d 100644 --- a/Engine/source/afx/afxMagicMissile.cpp +++ b/Engine/source/afx/afxMagicMissile.cpp @@ -446,8 +446,9 @@ bool afxMagicMissileData::onAdd() Vector dataBlocks(__FILE__, __LINE__); // make a copy of points_string - char* tokCopy = new char[dStrlen(wiggle_axis_string) + 1]; - dStrcpy(tokCopy, wiggle_axis_string); + dsize_t tokCopyLen = dStrlen(wiggle_axis_string) + 1; + char* tokCopy = new char[tokCopyLen]; + dStrcpy(tokCopy, wiggle_axis_string, tokCopyLen); // extract tokens one by one, adding them to dataBlocks char* currTok = dStrtok(tokCopy, " \t"); diff --git a/Engine/source/afx/arcaneFX.cpp b/Engine/source/afx/arcaneFX.cpp index 59da040ea..cec0c870a 100644 --- a/Engine/source/afx/arcaneFX.cpp +++ b/Engine/source/afx/arcaneFX.cpp @@ -908,7 +908,7 @@ ConsoleFunction(echoThru, const char*, 2, 0, "(string passthru, string text...)" char *ret = Con::getReturnBuffer(len + 1); ret[0] = 0; for(i = 2; i < argc; i++) - dStrcat(ret, argv[i]); + dStrcat(ret, argv[i], len + 1); Con::printf("%s -- [%s]", ret, argv[1].getStringValue()); ret[0] = 0; @@ -928,7 +928,7 @@ ConsoleFunction(warnThru, const char*, 2, 0, "(string passthru, string text...)" char *ret = Con::getReturnBuffer(len + 1); ret[0] = 0; for(i = 2; i < argc; i++) - dStrcat(ret, argv[i]); + dStrcat(ret, argv[i], len + 1); Con::warnf("%s -- [%s]", ret, argv[1].getStringValue()); ret[0] = 0; @@ -948,7 +948,7 @@ ConsoleFunction(errorThru, const char*, 2, 0, "(string passthru, string text...) char *ret = Con::getReturnBuffer(len + 1); ret[0] = 0; for(i = 2; i < argc; i++) - dStrcat(ret, argv[i]); + dStrcat(ret, argv[i], len + 1); Con::errorf("%s -- [%s]", ret, argv[1].getStringValue()); ret[0] = 0; diff --git a/Engine/source/afx/ce/afxAudioBank.cpp b/Engine/source/afx/ce/afxAudioBank.cpp index 2aa148474..82537419d 100644 --- a/Engine/source/afx/ce/afxAudioBank.cpp +++ b/Engine/source/afx/ce/afxAudioBank.cpp @@ -184,7 +184,7 @@ void afxAudioBank::packData(BitStream* stream) if(!mFilename) buffer[0] = 0; else - dStrcpy(buffer, mFilename); + dStrcpy(buffer, mFilename, 256); stream->writeString(buffer); */ diff --git a/Engine/source/afx/ce/afxParticleEmitter.cpp b/Engine/source/afx/ce/afxParticleEmitter.cpp index 3983b27ba..1d76b2475 100644 --- a/Engine/source/afx/ce/afxParticleEmitter.cpp +++ b/Engine/source/afx/ce/afxParticleEmitter.cpp @@ -141,8 +141,9 @@ bool afxParticleEmitterData::onAdd() if (tpaths_string != ST_NULLSTRING) { Vector dataBlocks(__FILE__, __LINE__); - char* tokCopy = new char[dStrlen(tpaths_string) + 1]; - dStrcpy(tokCopy, tpaths_string); + dsize_t tokCopyLen = dStrlen(tpaths_string) + 1; + char* tokCopy = new char[tokCopyLen]; + dStrcpy(tokCopy, tpaths_string, tokCopyLen); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) @@ -467,8 +468,9 @@ bool afxParticleEmitterPathData::onAdd() if (epaths_string != ST_NULLSTRING) { Vector dataBlocks(__FILE__, __LINE__); - char* tokCopy = new char[dStrlen(epaths_string) + 1]; - dStrcpy(tokCopy, epaths_string); + dsize_t tokCopyLen = dStrlen(epaths_string) + 1; + char* tokCopy = new char[tokCopyLen]; + dStrcpy(tokCopy, epaths_string, tokCopyLen); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) @@ -552,8 +554,9 @@ void afxParticleEmitterPathData::onPerformSubstitutions() if (epaths_string != ST_NULLSTRING) { Vector dataBlocks(__FILE__, __LINE__); - char* tokCopy = new char[dStrlen(epaths_string) + 1]; - dStrcpy(tokCopy, epaths_string); + dsize_t tokCopyLen = dStrlen(epaths_string) + 1; + char* tokCopy = new char[tokCopyLen]; + dStrcpy(tokCopy, epaths_string, tokCopyLen); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) diff --git a/Engine/source/afx/ea/afxEA_PhraseEffect.cpp b/Engine/source/afx/ea/afxEA_PhraseEffect.cpp index 4448e1967..e253ab1ee 100644 --- a/Engine/source/afx/ea/afxEA_PhraseEffect.cpp +++ b/Engine/source/afx/ea/afxEA_PhraseEffect.cpp @@ -272,10 +272,10 @@ void afxEA_PhraseEffect::trigger_new_phrase() if (phrase_fx_data->on_trig_cmd != ST_NULLSTRING) { char obj_str[32]; - dStrcpy(obj_str, Con::getIntArg(choreographer->getId())); + dStrcpy(obj_str, Con::getIntArg(choreographer->getId()), 32); char index_str[32]; - dStrcpy(index_str, Con::getIntArg(group_index)); + dStrcpy(index_str, Con::getIntArg(group_index), 32); char buffer[1024]; char* b = buffer; @@ -382,4 +382,4 @@ bool afxEA_PhraseEffectDesc::requiresStop(const afxEffectWrapperData* ew, const return (timing.lifetime < 0); } -//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// \ No newline at end of file +//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// diff --git a/Engine/source/afx/rpg/afxRPGMagicSpell.cpp b/Engine/source/afx/rpg/afxRPGMagicSpell.cpp index dae982fa8..3e9362435 100644 --- a/Engine/source/afx/rpg/afxRPGMagicSpell.cpp +++ b/Engine/source/afx/rpg/afxRPGMagicSpell.cpp @@ -194,7 +194,7 @@ char* afxRPGMagicSpellData::fmt_placeholder_desc(char* buffer, int len) const { char pack_str[32]; if (source_pack == ST_NULLSTRING) - dStrcpy(pack_str, "unknown"); + dStrcpy(pack_str, "unknown", 32); else dSprintf(pack_str, 32, "%s", source_pack); @@ -225,9 +225,9 @@ char* afxRPGMagicSpellData::formatDesc(char* buffer, int len) const { if (spell_target != TARGET_NOTHING) { - dStrcpy(target_str, _afxRPGMagicSpell_TargetType::_sEnumTable[i].mName); + dStrcpy(target_str, _afxRPGMagicSpell_TargetType::_sEnumTable[i].mName, 32); if (spell_target != TARGET_FREE && target_optional) - dStrcat(target_str, " (opt)"); + dStrcat(target_str, " (opt)", 32); } break; } @@ -245,13 +245,13 @@ char* afxRPGMagicSpellData::formatDesc(char* buffer, int len) const char casting_str[32]; if (casting_dur <= 0) - dStrcpy(casting_str, "instant"); + dStrcpy(casting_str, "instant", 32); else dSprintf(casting_str, 32, "%.1f sec cast", casting_dur); char pack_str[32]; if (source_pack == ST_NULLSTRING) - dStrcpy(pack_str, "unknown"); + dStrcpy(pack_str, "unknown", 32); else dSprintf(pack_str, 32, "%s", source_pack); diff --git a/Engine/source/afx/ui/afxSpellButton.cpp b/Engine/source/afx/ui/afxSpellButton.cpp index 2ca1e4473..632d2e652 100644 --- a/Engine/source/afx/ui/afxSpellButton.cpp +++ b/Engine/source/afx/ui/afxSpellButton.cpp @@ -171,10 +171,11 @@ void afxSpellButton::setBitmap(const char *name, bool placeholder) if (placeholder) { - dStrcpy(buffer, name); + dStrcpy(buffer, name, 1024); + S32 pLen = 1024 - dStrlen(buffer); p = buffer + dStrlen(buffer); - dStrcpy(p, "_i"); + dStrcpy(p, "_i", pLen); mTextureInactive.set(buffer, COOLDOWN_PROFILE); mTextureNormal = mTextureInactive; mTextureHilight = mTextureInactive; @@ -183,19 +184,20 @@ void afxSpellButton::setBitmap(const char *name, bool placeholder) } else { - dStrcpy(buffer, name); + dStrcpy(buffer, name, 1024); + S32 pLen = 1024 - dStrlen(buffer); p = buffer + dStrlen(buffer); - dStrcpy(p, "_n"); + dStrcpy(p, "_n", pLen); mTextureNormal.set(buffer, COOLDOWN_PROFILE); - dStrcpy(p, "_h"); + dStrcpy(p, "_h", pLen); mTextureHilight.set(buffer, COOLDOWN_PROFILE); if (!mTextureHilight) mTextureHilight = mTextureNormal; - dStrcpy(p, "_d"); + dStrcpy(p, "_d", pLen); mTextureDepressed.set(buffer, COOLDOWN_PROFILE); if (!mTextureDepressed) mTextureDepressed = mTextureHilight; - dStrcpy(p, "_i"); + dStrcpy(p, "_i", pLen); mTextureInactive.set(buffer, COOLDOWN_PROFILE); if (!mTextureInactive) mTextureInactive = mTextureNormal; diff --git a/Engine/source/afx/xm/afxXM_PathConform.cpp b/Engine/source/afx/xm/afxXM_PathConform.cpp index af9b7869f..07bd86d92 100644 --- a/Engine/source/afx/xm/afxXM_PathConform.cpp +++ b/Engine/source/afx/xm/afxXM_PathConform.cpp @@ -194,8 +194,9 @@ bool afxXM_PathConformData::onAdd() if (paths_string != ST_NULLSTRING) { Vector dataBlocks(__FILE__, __LINE__); - char* tokCopy = new char[dStrlen(paths_string) + 1]; - dStrcpy(tokCopy, paths_string); + dsize_t tokCopyLen = dStrlen(paths_string) + 1; + char* tokCopy = new char[tokCopyLen]; + dStrcpy(tokCopy, paths_string, tokCopyLen); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) diff --git a/Engine/source/app/badWordFilter.cpp b/Engine/source/app/badWordFilter.cpp index d0547e5ee..2983a8bb5 100644 --- a/Engine/source/app/badWordFilter.cpp +++ b/Engine/source/app/badWordFilter.cpp @@ -50,7 +50,7 @@ BadWordFilter::BadWordFilter() { VECTOR_SET_ASSOCIATION( filterTables ); - dStrcpy(defaultReplaceStr, "knqwrtlzs"); + dStrcpy(defaultReplaceStr, "knqwrtlzs", 32); filterTables.push_back(new FilterTable); curOffset = 0; } @@ -147,7 +147,7 @@ bool BadWordFilter::setDefaultReplaceStr(const char *str) U32 len = dStrlen(str); if(len < 2 || len >= sizeof(defaultReplaceStr)) return false; - dStrcpy(defaultReplaceStr, str); + dStrcpy(defaultReplaceStr, str, 32); return true; } @@ -286,8 +286,9 @@ DefineEngineFunction(filterString, const char *, (const char* baseString, const else replaceStr = gBadWordFilter->getDefaultReplaceStr(); - char *ret = Con::getReturnBuffer(dStrlen(baseString) + 1); - dStrcpy(ret, baseString); + dsize_t retLen = dStrlen(baseString) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, baseString, retLen); gBadWordFilter->filterString(ret, replaceStr); return ret; } diff --git a/Engine/source/app/banList.cpp b/Engine/source/app/banList.cpp index 952b49a05..4e7de54a2 100644 --- a/Engine/source/app/banList.cpp +++ b/Engine/source/app/banList.cpp @@ -86,7 +86,7 @@ void BanList::addBan(S32 uniqueId, const char *TA, S32 banTime) } BanInfo b; - dStrcpy(b.transportAddress, TA); + dStrcpy(b.transportAddress, TA, 128); b.uniqueId = uniqueId; b.bannedUntil = banTime; diff --git a/Engine/source/app/mainLoop.cpp b/Engine/source/app/mainLoop.cpp index 5fc4aa8c0..b08363f8a 100644 --- a/Engine/source/app/mainLoop.cpp +++ b/Engine/source/app/mainLoop.cpp @@ -495,7 +495,7 @@ bool StandardMainLoop::handleCommandLine( S32 argc, const char **argv ) S32 pathLen = dStrlen( fdd.mFile ); FrameTemp szPathCopy( pathLen + 1); - dStrcpy( szPathCopy, fdd.mFile ); + dStrcpy( szPathCopy, fdd.mFile, pathLen + 1 ); //forwardslash( szPathCopy ); const char *path = dStrrchr(szPathCopy, '/'); diff --git a/Engine/source/app/net/net.cpp b/Engine/source/app/net/net.cpp index ab08da057..c5f1be189 100644 --- a/Engine/source/app/net/net.cpp +++ b/Engine/source/app/net/net.cpp @@ -128,8 +128,8 @@ const char *rmtCommandName = dStrchr(mArgv[1], ' ') + 1; if(conn->isConnectionToServer()) { - dStrcpy(mBuf, "clientCmd"); - dStrcat(mBuf, rmtCommandName); + dStrcpy(mBuf, "clientCmd", 1024); + dStrcat(mBuf, rmtCommandName, 1024); char *temp = mArgv[1]; mArgv[1] = mBuf; @@ -139,8 +139,8 @@ } else { - dStrcpy(mBuf, "serverCmd"); - dStrcat(mBuf, rmtCommandName); + dStrcpy(mBuf, "serverCmd", 1024); + dStrcat(mBuf, rmtCommandName, 1024); char *temp = mArgv[1]; dSprintf(idBuf, sizeof(idBuf), "%d", conn->getId()); @@ -409,7 +409,7 @@ ConsoleFunction( buildTaggedString, const char*, 2, 11, "(string format, ...)" S32 strLength = dStrlen(argStr); if (strLength > strMaxLength) goto done; - dStrcpy(strBufPtr, argStr); + dStrcpy(strBufPtr, argStr, strMaxLength); strBufPtr += strLength; strMaxLength -= strLength; fmtStrPtr += 2; diff --git a/Engine/source/app/net/netExamples.cpp b/Engine/source/app/net/netExamples.cpp index 81065ce6a..1f53c6d21 100644 --- a/Engine/source/app/net/netExamples.cpp +++ b/Engine/source/app/net/netExamples.cpp @@ -110,7 +110,7 @@ public: SimpleNetObject() { mNetFlags.set(ScopeAlways | Ghostable); - dStrcpy(message, "Hello World!"); + dStrcpy(message, "Hello World!", 256); } U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream) { @@ -125,7 +125,7 @@ public: void setMessage(const char *msg) { setMaskBits(1); - dStrcpy(message, msg); + dStrcpy(message, msg, 256); } DECLARE_CONOBJECT(SimpleNetObject); diff --git a/Engine/source/app/net/serverQuery.cpp b/Engine/source/app/net/serverQuery.cpp index 1b1f5f0e0..6b555629a 100644 --- a/Engine/source/app/net/serverQuery.cpp +++ b/Engine/source/app/net/serverQuery.cpp @@ -394,12 +394,12 @@ void queryLanServers(U32 port, U8 flags, const char* gameType, const char* missi if ( !sActiveFilter.gameType || dStricmp( sActiveFilter.gameType, "Any" ) != 0 ) { sActiveFilter.gameType = (char*) dRealloc( sActiveFilter.gameType, 4 ); - dStrcpy( sActiveFilter.gameType, "Any" ); + dStrcpy( sActiveFilter.gameType, "Any", 4 ); } if ( !sActiveFilter.missionType || dStricmp( sActiveFilter.missionType, "Any" ) != 0 ) { sActiveFilter.missionType = (char*) dRealloc( sActiveFilter.missionType, 4 ); - dStrcpy( sActiveFilter.missionType, "Any" ); + dStrcpy( sActiveFilter.missionType, "Any", 4 ); } sActiveFilter.queryFlags = 0; sActiveFilter.minPlayers = minPlayers; @@ -510,14 +510,16 @@ void queryMasterServer(U8 flags, const char* gameType, const char* missionType, // Update the active filter: if ( !sActiveFilter.gameType || dStrcmp( sActiveFilter.gameType, gameType ) != 0 ) { - sActiveFilter.gameType = (char*) dRealloc( sActiveFilter.gameType, dStrlen( gameType ) + 1 ); - dStrcpy( sActiveFilter.gameType, gameType ); + dsize_t gameTypeLen = dStrlen(gameType) + 1; + sActiveFilter.gameType = (char*) dRealloc( sActiveFilter.gameType, gameTypeLen ); + dStrcpy( sActiveFilter.gameType, gameType, gameTypeLen ); } if ( !sActiveFilter.missionType || dStrcmp( sActiveFilter.missionType, missionType ) != 0 ) { - sActiveFilter.missionType = (char*) dRealloc( sActiveFilter.missionType, dStrlen( missionType ) + 1 ); - dStrcpy( sActiveFilter.missionType, missionType ); + dsize_t missionTypeLen = dStrlen(missionType) + 1; + sActiveFilter.missionType = (char*) dRealloc( sActiveFilter.missionType, missionTypeLen ); + dStrcpy( sActiveFilter.missionType, missionType, missionTypeLen ); } sActiveFilter.queryFlags = flags | ServerFilter::NewStyleResponse; @@ -969,8 +971,9 @@ static void pushServerFavorites() Net::stringToAddress( addrString, &addr ); ServerInfo* si = findOrCreateServerInfo( &addr ); AssertFatal(si, "pushServerFavorites - failed to create Server Info!" ); - si->name = (char*) dRealloc( (void*) si->name, dStrlen( serverName ) + 1 ); - dStrcpy( si->name, serverName ); + dsize_t nameLen = dStrlen(serverName) + 1; + si->name = (char*) dRealloc( (void*) si->name, nameLen ); + dStrcpy( si->name, serverName, nameLen ); si->isFavorite = true; pushPingRequest( &addr ); } @@ -1053,14 +1056,15 @@ void addFakeServers( S32 howMany ) newServer.maxPlayers = 64; char buf[256]; dSprintf( buf, 255, "Fake server #%d", sNumFakeServers ); - newServer.name = (char*) dMalloc( dStrlen( buf ) + 1 ); - dStrcpy( newServer.name, buf ); + dsize_t nameLen = dStrlen(buf) + 1; + newServer.name = (char*) dMalloc( nameLen ); + dStrcpy( newServer.name, buf, nameLen ); newServer.gameType = (char*) dMalloc( 5 ); - dStrcpy( newServer.gameType, "Fake" ); - newServer.missionType = (char*) dMalloc( 4 ); - dStrcpy( newServer.missionType, "FakeMissionType" ); + dStrcpy( newServer.gameType, "Fake", 5 ); + newServer.missionType = (char*) dMalloc( 16 ); + dStrcpy( newServer.missionType, "FakeMissionType", 16 ); newServer.missionName = (char*) dMalloc( 14 ); - dStrcpy( newServer.missionName, "FakeMapName" ); + dStrcpy( newServer.missionName, "FakeMapName", 14 ); Net::stringToAddress( "IP:198.74.33.35:28000", &newServer.address ); newServer.ping = (U32)( Platform::getRandom() * 200.0f ); newServer.cpuSpeed = 470; @@ -1353,9 +1357,9 @@ static void processPingsAndQueries( U32 session, bool schedule ) char msg[64]; U32 foundCount = gServerList.size(); if ( foundCount == 0 ) - dStrcpy( msg, "No servers found." ); + dStrcpy( msg, "No servers found.", 64 ); else if ( foundCount == 1 ) - dStrcpy( msg, "One server found." ); + dStrcpy( msg, "One server found.", 64 ); else dSprintf( msg, sizeof( msg ), "%d servers found.", foundCount ); @@ -1753,8 +1757,9 @@ static void handleGameMasterInfoRequest( const NetAddress* address, U32 key, U8 out->write( playerCount ); const char* guidList = Con::getVariable( "Server::GuidList" ); - char* buf = new char[dStrlen( guidList ) + 1]; - dStrcpy( buf, guidList ); + dsize_t bufLen = dStrlen(guidList) + 1; + char* buf = new char[bufLen]; + dStrcpy( buf, guidList, bufLen ); char* temp = dStrtok( buf, "\t" ); temp8 = 0; for ( ; temp && temp8 < playerCount; temp8++ ) @@ -1948,8 +1953,9 @@ static void handleGamePingResponse( const NetAddress* address, BitStream* stream stream->readString( buf ); if ( !si->name ) { - si->name = (char*) dMalloc( dStrlen( buf ) + 1 ); - dStrcpy( si->name, buf ); + dsize_t bufLen = dStrlen(buf) + 1; + si->name = (char*) dMalloc(bufLen); + dStrcpy( si->name, buf, bufLen ); } // Set the server up to be queried: @@ -2050,8 +2056,9 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream stream->readString( stringBuf ); if ( !si->gameType || dStricmp( si->gameType, stringBuf ) != 0 ) { - si->gameType = (char*) dRealloc( (void*) si->gameType, dStrlen( stringBuf ) + 1 ); - dStrcpy( si->gameType, stringBuf ); + dsize_t gameTypeLen = dStrlen(stringBuf) + 1; + si->gameType = (char*) dRealloc( (void*) si->gameType, gameTypeLen ); + dStrcpy( si->gameType, stringBuf, gameTypeLen ); // Test against the active filter: if ( applyFilter && dStricmp( sActiveFilter.gameType, "any" ) != 0 @@ -2067,8 +2074,9 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream stream->readString( stringBuf ); if ( !si->missionType || dStrcmp( si->missionType, stringBuf ) != 0 ) { - si->missionType = (char*) dRealloc( (void*) si->missionType, dStrlen( stringBuf ) + 1 ); - dStrcpy( si->missionType, stringBuf ); + dsize_t missionTypeLen = dStrlen(stringBuf) + 1; + si->missionType = (char*) dRealloc( (void*) si->missionType, missionTypeLen ); + dStrcpy( si->missionType, stringBuf, missionTypeLen ); // Test against the active filter: if ( applyFilter && dStricmp( sActiveFilter.missionType, "any" ) != 0 @@ -2088,8 +2096,9 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream *temp = '\0'; if ( !si->missionName || dStrcmp( si->missionName, stringBuf ) != 0 ) { - si->missionName = (char*) dRealloc( (void*) si->missionName, dStrlen( stringBuf ) + 1 ); - dStrcpy( si->missionName, stringBuf ); + dsize_t missionNameLen = dStrlen(stringBuf) + 1; + si->missionName = (char*) dRealloc( (void*) si->missionName, missionNameLen ); + dStrcpy( si->missionName, stringBuf, missionNameLen ); } // Get the server status: @@ -2157,16 +2166,18 @@ static void handleGameInfoResponse( const NetAddress* address, BitStream* stream stream->readString( stringBuf ); if ( !si->statusString || ( isUpdate && dStrcmp( si->statusString, stringBuf ) != 0 ) ) { - si->infoString = (char*) dRealloc( (void*) si->infoString, dStrlen( stringBuf ) + 1 ); - dStrcpy( si->infoString, stringBuf ); + dsize_t infoLen = dStrlen(stringBuf) + 1; + si->infoString = (char*) dRealloc( (void*) si->infoString, infoLen ); + dStrcpy( si->infoString, stringBuf, infoLen ); } // Get the content string: readLongCString( stream, stringBuf ); if ( !si->statusString || ( isUpdate && dStrcmp( si->statusString, stringBuf ) != 0 ) ) { - si->statusString = (char*) dRealloc( (void*) si->statusString, dStrlen( stringBuf ) + 1 ); - dStrcpy( si->statusString, stringBuf ); + dsize_t statusLen = dStrlen(stringBuf) + 1; + si->statusString = (char*) dRealloc( (void*) si->statusString, statusLen ); + dStrcpy( si->statusString, stringBuf, statusLen ); } // Update the server browser gui! diff --git a/Engine/source/cinterface/cinterface.cpp b/Engine/source/cinterface/cinterface.cpp index f195cd7e7..aa0fae035 100644 --- a/Engine/source/cinterface/cinterface.cpp +++ b/Engine/source/cinterface/cinterface.cpp @@ -182,8 +182,9 @@ extern "C" { void torque_setexecutablepath(const char* directory) { - gExecutablePath = new char[strlen(directory)+1]; - strcpy(gExecutablePath, directory); + dsize_t pathLen = dStrlen(directory) + 1; + gExecutablePath = new char[pathLen]; + dStrcpy(gExecutablePath, directory, pathLen); } // set Torque 3D into web deployment mode (disable fullscreen exlusive mode, etc) diff --git a/Engine/source/console/CMDscan.cpp b/Engine/source/console/CMDscan.cpp index 733460b09..c30ac7bc9 100644 --- a/Engine/source/console/CMDscan.cpp +++ b/Engine/source/console/CMDscan.cpp @@ -2340,8 +2340,9 @@ static int Sc_ScanString(int ret) if (!collapseEscape(CMDtext + 1)) return -1; - char* buffer = (char*)consoleAlloc(dStrlen(CMDtext)); - dStrcpy(buffer, CMDtext + 1); + dsize_t bufferLen = dStrlen(CMDtext); + char* buffer = (char*)consoleAlloc(bufferLen); + dStrcpy(buffer, CMDtext + 1, bufferLen); CMDlval.str = MakeToken< char* >(buffer, lineIndex); return ret; diff --git a/Engine/source/console/CMDscan.l b/Engine/source/console/CMDscan.l index d9b92b6d2..e9069fe15 100644 --- a/Engine/source/console/CMDscan.l +++ b/Engine/source/console/CMDscan.l @@ -71,7 +71,7 @@ inline int isatty(int) { return 0; } buf[n++] = (char) c; \ result = n; \ } - + // General helper stuff. static int lineIndex; @@ -411,10 +411,11 @@ static int Sc_ScanString(int ret) CMDtext[CMDleng - 1] = 0; if(!collapseEscape(CMDtext+1)) return -1; - - char* buffer = ( char* ) consoleAlloc( dStrlen( CMDtext ) ); - dStrcpy( buffer, CMDtext + 1 ); - + + dsize_t bufferLen = dStrlen( CMDtext ); + char* buffer = ( char* ) consoleAlloc( bufferLen ); + dStrcpy( buffer, CMDtext + 1, bufferLen ); + CMDlval.str = MakeToken< char* >( buffer, lineIndex ); return ret; } diff --git a/Engine/source/console/SimXMLDocument.cpp b/Engine/source/console/SimXMLDocument.cpp index b2960105b..156533503 100644 --- a/Engine/source/console/SimXMLDocument.cpp +++ b/Engine/source/console/SimXMLDocument.cpp @@ -833,7 +833,7 @@ void SimXMLDocument::setObjectAttributes(const char* objectID) continue; FrameTemp valCopy( dStrlen( val ) + 1 ); - dStrcpy( (char *)valCopy, val ); + dStrcpy( (char *)valCopy, val, valCopy.size() ); if (!pObject->writeField(itr->pFieldname, valCopy)) continue; @@ -873,7 +873,7 @@ void SimXMLDocument::setObjectAttributes(const char* objectID) // continue; // FrameTemp valCopy( dStrlen( val ) + 1 ); - // dStrcpy( (char *)valCopy, val ); + // dStrcpy( (char *)valCopy, val, valCopy.size() ); // if (!pObject->writeField(itr->pFieldname, valCopy)) // continue; diff --git a/Engine/source/console/astAlloc.cpp b/Engine/source/console/astAlloc.cpp index 75fbe151c..521b6dbcc 100644 --- a/Engine/source/console/astAlloc.cpp +++ b/Engine/source/console/astAlloc.cpp @@ -238,10 +238,11 @@ StrConstNode *StrConstNode::alloc(S32 lineNumber, char *str, bool tag, bool doc) StrConstNode *ret = (StrConstNode *)consoleAlloc(sizeof(StrConstNode)); constructInPlace(ret); ret->dbgLineNumber = lineNumber; - ret->str = (char *)consoleAlloc(dStrlen(str) + 1); + dsize_t retStrLen = dStrlen(str) + 1; + ret->str = (char *)consoleAlloc(retStrLen); ret->tag = tag; ret->doc = doc; - dStrcpy(ret->str, str); + dStrcpy(ret->str, str, retStrLen); return ret; } diff --git a/Engine/source/console/codeInterpreter.cpp b/Engine/source/console/codeInterpreter.cpp index a0e13502f..46d58476e 100644 --- a/Engine/source/console/codeInterpreter.cpp +++ b/Engine/source/console/codeInterpreter.cpp @@ -95,19 +95,17 @@ static void getFieldComponent(SimObject* object, StringTableEntry field, const c // Translate xyzw and rgba into the indexed component // of the variable or field. - // - // Review: Should we use strncpy to prevent a buffer overflow? if (subField == xyzw[0] || subField == rgba[0]) - dStrcpy(val, StringUnit::getUnit(prevVal, 0, " \t\n")); + dStrcpy(val, StringUnit::getUnit(prevVal, 0, " \t\n"), 128); else if (subField == xyzw[1] || subField == rgba[1]) - dStrcpy(val, StringUnit::getUnit(prevVal, 1, " \t\n")); + dStrcpy(val, StringUnit::getUnit(prevVal, 1, " \t\n"), 128); else if (subField == xyzw[2] || subField == rgba[2]) - dStrcpy(val, StringUnit::getUnit(prevVal, 2, " \t\n")); + dStrcpy(val, StringUnit::getUnit(prevVal, 2, " \t\n"), 128); else if (subField == xyzw[3] || subField == rgba[3]) - dStrcpy(val, StringUnit::getUnit(prevVal, 3, " \t\n")); + dStrcpy(val, StringUnit::getUnit(prevVal, 3, " \t\n"), 128); else val[0] = 0; @@ -157,19 +155,17 @@ static void setFieldComponent(SimObject* object, StringTableEntry field, const c // Insert the value into the specified // component of the string. - // - // Review: Should we use strncpy to prevent a buffer overflow? if (subField == xyzw[0] || subField == rgba[0]) - dStrcpy(val, StringUnit::setUnit(prevVal, 0, strValue, " \t\n")); + dStrcpy(val, StringUnit::setUnit(prevVal, 0, strValue, " \t\n"), 128); else if (subField == xyzw[1] || subField == rgba[1]) - dStrcpy(val, StringUnit::setUnit(prevVal, 1, strValue, " \t\n")); + dStrcpy(val, StringUnit::setUnit(prevVal, 1, strValue, " \t\n"), 128); else if (subField == xyzw[2] || subField == rgba[2]) - dStrcpy(val, StringUnit::setUnit(prevVal, 2, strValue, " \t\n")); + dStrcpy(val, StringUnit::setUnit(prevVal, 2, strValue, " \t\n"), 128); else if (subField == xyzw[3] || subField == rgba[3]) - dStrcpy(val, StringUnit::setUnit(prevVal, 3, strValue, " \t\n")); + dStrcpy(val, StringUnit::setUnit(prevVal, 3, strValue, " \t\n"), 128); if (val[0] != 0) { @@ -420,13 +416,13 @@ exitLabel: if (gEvalState.traceOn) { sTraceBuffer[0] = 0; - dStrcat(sTraceBuffer, "Leaving "); + dStrcat(sTraceBuffer, "Leaving ", 1024); if (packageName) { - dStrcat(sTraceBuffer, "["); - dStrcat(sTraceBuffer, packageName); - dStrcat(sTraceBuffer, "]"); + dStrcat(sTraceBuffer, "[", 1024); + dStrcat(sTraceBuffer, packageName, 1024); + dStrcat(sTraceBuffer, "]", 1024); } if (thisNamespace && thisNamespace->mName) { @@ -471,13 +467,13 @@ void CodeInterpreter::parseArgs(U32 &ip) if (gEvalState.traceOn) { sTraceBuffer[0] = 0; - dStrcat(sTraceBuffer, "Entering "); + dStrcat(sTraceBuffer, "Entering ", 1024); if (mExec.packageName) { - dStrcat(sTraceBuffer, "["); - dStrcat(sTraceBuffer, mExec.packageName); - dStrcat(sTraceBuffer, "]"); + dStrcat(sTraceBuffer, "[", 1024); + dStrcat(sTraceBuffer, mExec.packageName, 1024); + dStrcat(sTraceBuffer, "]", 1024); } if (mExec.thisNamespace && mExec.thisNamespace->mName) { @@ -491,11 +487,11 @@ void CodeInterpreter::parseArgs(U32 &ip) } for (S32 i = 0; i < wantedArgc; i++) { - dStrcat(sTraceBuffer, mExec.argv[i + 1]); + dStrcat(sTraceBuffer, mExec.argv[i + 1], 1024); if (i != wantedArgc - 1) - dStrcat(sTraceBuffer, ", "); + dStrcat(sTraceBuffer, ", ", 1024); } - dStrcat(sTraceBuffer, ")"); + dStrcat(sTraceBuffer, ")", 1024); Con::printf("%s", sTraceBuffer); } @@ -1729,7 +1725,7 @@ OPCodeReturn CodeInterpreter::op_setcurfield(U32 &ip) { // Save the previous field for parsing vector fields. mPrevField = mCurField; - dStrcpy(prevFieldArray, curFieldArray); + dStrcpy(prevFieldArray, curFieldArray, 256); mCurField = CodeToSTE(mCodeBlock->code, ip); curFieldArray[0] = 0; ip += 2; @@ -1738,7 +1734,7 @@ OPCodeReturn CodeInterpreter::op_setcurfield(U32 &ip) OPCodeReturn CodeInterpreter::op_setcurfield_array(U32 &ip) { - dStrcpy(curFieldArray, STR.getStringValue()); + dStrcpy(curFieldArray, STR.getStringValue(), 256); return OPCodeReturn::success; } @@ -1771,7 +1767,7 @@ OPCodeReturn CodeInterpreter::op_setcurfield_this(U32 &ip) mCurObject = mThisObject; mPrevField = mCurField; - dStrcpy(prevFieldArray, curFieldArray); + dStrcpy(prevFieldArray, curFieldArray, 256); mCurField = CodeToSTE(mCodeBlock->code, ip); curFieldArray[0] = 0; ip += 2; diff --git a/Engine/source/console/compiledEval.cpp b/Engine/source/console/compiledEval.cpp index dc6f8a5f5..73969afb2 100644 --- a/Engine/source/console/compiledEval.cpp +++ b/Engine/source/console/compiledEval.cpp @@ -70,9 +70,9 @@ namespace Con ret[0] = 0; for (walk = ns; walk; walk = walk->mParent) { - dStrcat(ret, walk->mName); + dStrcat(ret, walk->mName, size); if (walk->mParent) - dStrcat(ret, " -> "); + dStrcat(ret, " -> ", size); } return ret; } diff --git a/Engine/source/console/compiler.cpp b/Engine/source/console/compiler.cpp index 0330f4d59..716b9e377 100644 --- a/Engine/source/console/compiler.cpp +++ b/Engine/source/console/compiler.cpp @@ -164,7 +164,7 @@ U32 CompilerStringTable::add(const char *str, bool caseSens, bool tag) newStr->string = (char *)consoleAlloc(len); newStr->len = len; newStr->tag = tag; - dStrcpy(newStr->string, str); + dStrcpy(newStr->string, str, len); // Put into the hash table. hashTable[str] = newStr; @@ -195,7 +195,7 @@ char *CompilerStringTable::build() char *ret = new char[totalLen]; dMemset(ret, 0, totalLen); for (Entry *walk = list; walk; walk = walk->next) - dStrcpy(ret + walk->start, walk->string); + dStrcpy(ret + walk->start, walk->string, totalLen - walk->start); return ret; } diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index 983aa40ba..219f00c59 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -440,7 +440,7 @@ U32 tabComplete(char* inputBuffer, U32 cursorPos, U32 maxResultLength, bool forw { // If not... // Save it for checking next time. - dStrcpy(tabBuffer, inputBuffer); + dStrcpy(tabBuffer, inputBuffer, MaxCompletionBufferSize); // Scan backward from the cursor position to find the base to complete from. S32 p = cursorPos; while ((p > 0) && (inputBuffer[p - 1] != ' ') && (inputBuffer[p - 1] != '.') && (inputBuffer[p - 1] != '(')) @@ -527,7 +527,7 @@ U32 tabComplete(char* inputBuffer, U32 cursorPos, U32 maxResultLength, bool forw } // Save the modified input buffer for checking next time. - dStrcpy(tabBuffer, inputBuffer); + dStrcpy(tabBuffer, inputBuffer, MaxCompletionBufferSize); // Return the new (maybe) cursor position. return cursorPos; @@ -646,8 +646,9 @@ static void _printf(ConsoleLogEntry::Level level, ConsoleLogEntry::Type type, co entry.mLevel = level; entry.mType = type; #ifndef TORQUE_SHIPPING // this is equivalent to a memory leak, turn it off in ship build - entry.mString = (const char *)consoleLogChunker.alloc(dStrlen(pos) + 1); - dStrcpy(const_cast(entry.mString), pos); + dsize_t logStringLen = dStrlen(pos) + 1; + entry.mString = (const char *)consoleLogChunker.alloc(logStringLen); + dStrcpy(const_cast(entry.mString), pos, logStringLen); // This prevents infinite recursion if the console itself needs to // re-allocate memory to accommodate the new console log entry, and @@ -1271,7 +1272,7 @@ bool executeFile(const char* fileName, bool noCalls, bool journalScript) scriptFile = NULL; dsoModifiedTime = dsoFile->getModifiedTime(); - dStrcpy(nameBuffer, scriptFileName); + dStrcpy(nameBuffer, scriptFileName, 512); } // If we're supposed to be compiling this file, check to see if there's a DSO @@ -2097,12 +2098,12 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor if (ensureTrailingSlash) { // Yes, so ensure it. - Con::ensureTrailingSlash(pDstPath, pSrcPath); + Con::ensureTrailingSlash(pDstPath, pSrcPath, size); } else { // No, so just use the source path. - dStrcpy(pDstPath, pSrcPath); + dStrcpy(pDstPath, pSrcPath, size); } return false; @@ -2118,7 +2119,7 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor if (ensureTrailingSlash) { // Yes, so ensure it. - Con::ensureTrailingSlash(pathBuffer, pathBuffer); + Con::ensureTrailingSlash(pathBuffer, pathBuffer, size); } // Strip repeat slashes. @@ -2143,12 +2144,12 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor if (ensureTrailingSlash) { // Yes, so ensure it. - Con::ensureTrailingSlash(pDstPath, pSrcPath); + Con::ensureTrailingSlash(pDstPath, pSrcPath, size); } else { // No, so just use the source path. - dStrcpy(pDstPath, pSrcPath); + dStrcpy(pDstPath, pSrcPath, size); } return false; @@ -2183,7 +2184,7 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor if (ensureTrailingSlash) { // Yes, so ensure it. - Con::ensureTrailingSlash(pathBuffer, pathBuffer); + Con::ensureTrailingSlash(pathBuffer, pathBuffer, size); } // Strip repeat slashes. @@ -2208,7 +2209,7 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor if (ensureTrailingSlash) { // Yes, so ensure it. - Con::ensureTrailingSlash(pathBuffer, pathBuffer); + Con::ensureTrailingSlash(pathBuffer, pathBuffer, size); } // Strip repeat slashes. @@ -2300,10 +2301,10 @@ void collapsePath(char* pDstPath, U32 size, const char* pSrcPath, const char* pW } -void ensureTrailingSlash(char* pDstPath, const char* pSrcPath) +void ensureTrailingSlash(char* pDstPath, const char* pSrcPath, S32 dstSize) { // Copy to target. - dStrcpy(pDstPath, pSrcPath); + dStrcpy(pDstPath, pSrcPath, dstSize); // Find trailing character index. S32 trailIndex = dStrlen(pDstPath); @@ -2353,7 +2354,7 @@ StringTableEntry getDSOPath(const char *scriptPath) else { StringTableEntry strippedPath = Platform::stripBasePath(scriptPath); - dStrcpy(relPath, strippedPath); + dStrcpy(relPath, strippedPath, 1024); char *slash = dStrrchr(relPath, '/'); if (slash) @@ -2616,7 +2617,7 @@ const char *ConsoleValue::getStringValue() else if(newLen > bufferLen) sval = (char *) dRealloc(sval, newLen); - dStrcpy(sval, internalValue); + dStrcpy(sval, internalValue, newLen); bufferLen = newLen; return sval; diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index e1e64bea2..67138d06c 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -491,7 +491,7 @@ namespace Con bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWorkingDirectoryHint = NULL, const bool ensureTrailingSlash = false); void collapsePath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWorkingDirectoryHint = NULL); bool isBasePath(const char* SrcPath, const char* pBasePath); - void ensureTrailingSlash(char* pDstPath, const char* pSrcPath); + void ensureTrailingSlash(char* pDstPath, const char* pSrcPath, S32 dstSize); bool stripRepeatSlashes(char* pDstPath, const char* pSrcPath, S32 dstSize); StringTableEntry getDSOPath(const char *scriptPath); diff --git a/Engine/source/console/consoleDoc.cpp b/Engine/source/console/consoleDoc.cpp index 4fb6921dd..f4b74402b 100644 --- a/Engine/source/console/consoleDoc.cpp +++ b/Engine/source/console/consoleDoc.cpp @@ -90,7 +90,7 @@ void printClassHeader(const char* usage, const char * className, const char * su // Copy Usage Document S32 usageLen = dStrlen( usage ); FrameTemp usageStr( usageLen ); - dStrcpy( usageStr, usage ); + dStrcpy( usageStr, usage, usageLen ); // Print Header Con::printf( "/*!" ); @@ -117,7 +117,7 @@ void printClassHeader(const char* usage, const char * className, const char * su } // Copy line and update usagePtr - dStrcpy( lineStr, usagePtr ); + dStrcpy( lineStr, usagePtr, 2048 ); usagePtr = (newLine != NULL ) ? newLine : usagePtr; lineLen = dStrlen( lineStr ); diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index fa5ab3a2b..fc14af173 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -561,12 +561,13 @@ DefineConsoleFunction( stripChars, const char*, ( const char* str, const char* c "@endtsexample\n" "@ingroup Strings" ) { - char* ret = Con::getReturnBuffer( dStrlen( str ) + 1 ); - dStrcpy( ret, str ); + S32 len = dStrlen(str) + 1; + char* ret = Con::getReturnBuffer( len ); + dStrcpy( ret, str, len ); U32 pos = dStrcspn( ret, chars ); while ( pos < dStrlen( ret ) ) { - dStrcpy( ret + pos, ret + pos + 1 ); + dStrcpy( ret + pos, ret + pos + 1, len - pos ); pos = dStrcspn( ret, chars ); } return( ret ); @@ -584,8 +585,9 @@ DefineConsoleFunction( strlwr, const char*, ( const char* str ),, "@see strupr\n" "@ingroup Strings" ) { - char *ret = Con::getReturnBuffer(dStrlen(str) + 1); - dStrcpy(ret, str); + dsize_t retLen = dStrlen(str) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, str, retLen); return dStrlwr(ret); } @@ -601,8 +603,9 @@ DefineConsoleFunction( strupr, const char*, ( const char* str ),, "@see strlwr\n" "@ingroup Strings" ) { - char *ret = Con::getReturnBuffer(dStrlen(str) + 1); - dStrcpy(ret, str); + dsize_t retLen = dStrlen(str) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, str, retLen); return dStrupr(ret); } @@ -663,7 +666,8 @@ DefineConsoleFunction( strreplace, const char*, ( const char* source, const char count++; } } - char *ret = Con::getReturnBuffer(dStrlen(source) + 1 + (toLen - fromLen) * count); + S32 retLen = dStrlen(source) + 1 + (toLen - fromLen) * count; + char *ret = Con::getReturnBuffer(retLen); U32 scanp = 0; U32 dstp = 0; for(;;) @@ -671,13 +675,13 @@ DefineConsoleFunction( strreplace, const char*, ( const char* source, const char const char *subScan = dStrstr(source + scanp, from); if(!subScan) { - dStrcpy(ret + dstp, source + scanp); + dStrcpy(ret + dstp, source + scanp, retLen - dstp); return ret; } U32 len = subScan - (source + scanp); - dStrncpy(ret + dstp, source + scanp, len); + dStrncpy(ret + dstp, source + scanp, getMin(len, retLen - dstp)); dstp += len; - dStrcpy(ret + dstp, to); + dStrcpy(ret + dstp, to, retLen - dstp); dstp += toLen; scanp += len + fromLen; } @@ -901,8 +905,8 @@ DefineConsoleFunction( startsWith, bool, ( const char* str, const char* prefix, char* targetBuf = new char[ targetLen + 1 ]; // copy src and target into buffers - dStrcpy( srcBuf, str ); - dStrcpy( targetBuf, prefix ); + dStrcpy( srcBuf, str, srcLen + 1 ); + dStrcpy( targetBuf, prefix, targetLen + 1 ); // reassign src/target pointers to lowercase versions str = dStrlwr( srcBuf ); @@ -952,8 +956,8 @@ DefineConsoleFunction( endsWith, bool, ( const char* str, const char* suffix, bo char* targetBuf = new char[ targetLen + 1 ]; // copy src and target into buffers - dStrcpy( srcBuf, str ); - dStrcpy( targetBuf, suffix ); + dStrcpy( srcBuf, str, srcLen + 1 ); + dStrcpy( targetBuf, suffix, targetLen + 1 ); // reassign src/target pointers to lowercase versions str = dStrlwr( srcBuf ); @@ -1824,8 +1828,9 @@ DefineEngineFunction( detag, const char*, ( const char* str ),, if( word == NULL ) return ""; - char* ret = Con::getReturnBuffer( dStrlen( word + 1 ) + 1 ); - dStrcpy( ret, word + 1 ); + dsize_t retLen = dStrlen(word + 1) + 1; + char* ret = Con::getReturnBuffer(retLen); + dStrcpy( ret, word + 1, retLen ); return ret; } else @@ -1889,7 +1894,7 @@ ConsoleFunction( echo, void, 2, 0, "( string message... ) " char *ret = Con::getReturnBuffer(len + 1); ret[0] = 0; for(i = 1; i < argc; i++) - dStrcat(ret, argv[i]); + dStrcat(ret, argv[i], len + 1); Con::printf("%s", ret); ret[0] = 0; @@ -1913,7 +1918,7 @@ ConsoleFunction( warn, void, 2, 0, "( string message... ) " char *ret = Con::getReturnBuffer(len + 1); ret[0] = 0; for(i = 1; i < argc; i++) - dStrcat(ret, argv[i]); + dStrcat(ret, argv[i], len + 1); Con::warnf(ConsoleLogEntry::General, "%s", ret); ret[0] = 0; @@ -1937,7 +1942,7 @@ ConsoleFunction( error, void, 2, 0, "( string message... ) " char *ret = Con::getReturnBuffer(len + 1); ret[0] = 0; for(i = 1; i < argc; i++) - dStrcat(ret, argv[i]); + dStrcat(ret, argv[i], len + 1); Con::errorf(ConsoleLogEntry::General, "%s", ret); ret[0] = 0; diff --git a/Engine/source/console/consoleInternal.cpp b/Engine/source/console/consoleInternal.cpp index eadee5d7b..61a63ae1e 100644 --- a/Engine/source/console/consoleInternal.cpp +++ b/Engine/source/console/consoleInternal.cpp @@ -125,7 +125,7 @@ StringValue & StringValue::operator=(const char *string) { S32 len = dStrlen(string); if (len < size) - dStrcpy(val, string); + dStrcpy(val, string, size); else { size = len; @@ -569,7 +569,7 @@ void ConsoleValue::setStringValue(const char * value) type = TypeInternalString; bufferLen = newLen; - dStrcpy(sval, value); + dStrcpy(sval, value, newLen); } else Con::setData(type, dataPtr, 0, 1, &value, enumTable); @@ -702,7 +702,7 @@ Dictionary::Entry* Dictionary::addVariable(const char *name, if (name[0] != '$') { scratchBuffer[0] = '$'; - dStrcpy(scratchBuffer + 1, name); + dStrcpy(scratchBuffer + 1, name, 1023); name = scratchBuffer; } @@ -900,21 +900,21 @@ DefineEngineFunction(backtrace, void, (), , buf[0] = 0; for (U32 i = 0; i < gEvalState.getStackDepth(); i++) { - dStrcat(buf, "->"); + dStrcat(buf, "->", totalSize); if (gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage) { - dStrcat(buf, "["); - dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage); - dStrcat(buf, "]"); + dStrcat(buf, "[", totalSize); + dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage, totalSize); + dStrcat(buf, "]", totalSize); } if (gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mName) { - dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mName); - dStrcat(buf, "::"); + dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mName, totalSize); + dStrcat(buf, "::", totalSize); } if (gEvalState.stack[i]->scopeName) - dStrcat(buf, gEvalState.stack[i]->scopeName); + dStrcat(buf, gEvalState.stack[i]->scopeName, totalSize); } Con::printf("BackTrace: %s", buf); @@ -1360,9 +1360,9 @@ void Namespace::addScriptCallback(const char *funcName, const char *usage, Conso static U32 uid = 0; char buffer[1024]; char lilBuffer[32]; - dStrcpy(buffer, funcName); + dStrcpy(buffer, funcName, 1024); dSprintf(lilBuffer, 32, "_%d_cb", uid++); - dStrcat(buffer, lilBuffer); + dStrcat(buffer, lilBuffer, 1024); Entry *ent = createLocalEntry(StringTable->insert(buffer)); trashCache(); @@ -1381,9 +1381,9 @@ void Namespace::markGroup(const char* name, const char* usage) static U32 uid = 0; char buffer[1024]; char lilBuffer[32]; - dStrcpy(buffer, name); + dStrcpy(buffer, name, 1024); dSprintf(lilBuffer, 32, "_%d", uid++); - dStrcat(buffer, lilBuffer); + dStrcat(buffer, lilBuffer, 1024); Entry *ent = createLocalEntry(StringTable->insert(buffer)); trashCache(); diff --git a/Engine/source/console/consoleObject.cpp b/Engine/source/console/consoleObject.cpp index e1744c5e1..52e2d9256 100644 --- a/Engine/source/console/consoleObject.cpp +++ b/Engine/source/console/consoleObject.cpp @@ -356,7 +356,7 @@ void ConsoleObject::addGroup(const char* in_pGroupname, const char* in_pGroupDoc char* pFieldNameBuf = suppressSpaces(in_pGroupname); // Append group type to fieldname. - dStrcat(pFieldNameBuf, "_begingroup"); + dStrcat(pFieldNameBuf, "_begingroup", 1024); // Create Field. AbstractClassRep::Field f; @@ -385,7 +385,7 @@ void ConsoleObject::endGroup(const char* in_pGroupname) char* pFieldNameBuf = suppressSpaces(in_pGroupname); // Append group type to fieldname. - dStrcat(pFieldNameBuf, "_endgroup"); + dStrcat(pFieldNameBuf, "_endgroup", 1024); // Create Field. AbstractClassRep::Field f; @@ -407,7 +407,7 @@ void ConsoleObject::endGroup(const char* in_pGroupname) void ConsoleObject::addArray( const char *arrayName, S32 count ) { char *nameBuff = suppressSpaces(arrayName); - dStrcat(nameBuff, "_beginarray"); + dStrcat(nameBuff, "_beginarray", 1024); // Create Field. AbstractClassRep::Field f; @@ -430,7 +430,7 @@ void ConsoleObject::addArray( const char *arrayName, S32 count ) void ConsoleObject::endArray( const char *arrayName ) { char *nameBuff = suppressSpaces(arrayName); - dStrcat(nameBuff, "_endarray"); + dStrcat(nameBuff, "_endarray", 1024); // Create Field. AbstractClassRep::Field f; @@ -773,11 +773,11 @@ static const char* returnClassList( Vector< AbstractClassRep* >& classes, U32 bu dQsort( classes.address(), classes.size(), sizeof( AbstractClassRep* ), ACRCompare ); char* ret = Con::getReturnBuffer( bufSize ); - dStrcpy( ret, classes[ 0 ]->getClassName() ); + dStrcpy( ret, classes[ 0 ]->getClassName(), bufSize ); for( U32 i = 1; i < classes.size(); i ++ ) { - dStrcat( ret, "\t" ); - dStrcat( ret, classes[ i ]->getClassName() ); + dStrcat( ret, "\t", bufSize ); + dStrcat( ret, classes[ i ]->getClassName(), bufSize ); } return ret; @@ -888,7 +888,7 @@ DefineEngineFunction( enumerateConsoleClassesByCategory, const char*, ( String c && ( repCategory[ categoryLength ] == ' ' || repCategory[ categoryLength ] == '\0' ) ) { classes.push_back( rep ); - bufSize += dStrlen( rep->getClassName() + 1 ); + bufSize += dStrlen( rep->getClassName() ) + 1; } } diff --git a/Engine/source/console/consoleXMLExport.cpp b/Engine/source/console/consoleXMLExport.cpp index 953a016cf..79e302595 100644 --- a/Engine/source/console/consoleXMLExport.cpp +++ b/Engine/source/console/consoleXMLExport.cpp @@ -319,8 +319,8 @@ DefineConsoleFunction( consoleExportXML, const char*, (), ,"Exports console defi Con::XMLExport xmlExport; String xml; xmlExport.exportXML(xml); - char* ret = Con::getReturnBuffer(xml.length() + 1); - dStrcpy(ret, xml.c_str()); + char* ret = Con::getReturnBuffer(xml.size()); + dStrcpy(ret, xml.c_str(), xml.size()); return ret; } diff --git a/Engine/source/console/fieldBrushObject.cpp b/Engine/source/console/fieldBrushObject.cpp index 3e91f711a..486b5c40a 100644 --- a/Engine/source/console/fieldBrushObject.cpp +++ b/Engine/source/console/fieldBrushObject.cpp @@ -273,9 +273,9 @@ DefineConsoleMethod(FieldBrushObject, queryFields, const char*, (const char* sim for ( U32 groupIndex = 0; groupIndex < groupCount; ++groupIndex ) { // Copy string element. - dStrcpy( tempBuf, StringUnit::getUnit( groupList, groupIndex, " \t\n" ) ); + dStrcpy( tempBuf, StringUnit::getUnit( groupList, groupIndex, " \t\n" ), 256 ); // Append internal name. - dStrcat( tempBuf, "_begingroup" ); + dStrcat( tempBuf, "_begingroup", 256 ); // Store Group. groups.push_back( StringTable->insert( tempBuf ) ); } @@ -416,7 +416,7 @@ void FieldBrushObject::copyFields( SimObject* pSimObject, const char* fieldList for ( U32 fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex ) { // Copy string element. - dStrcpy( tempBuf, StringUnit::getUnit( fieldList, fieldIndex, " \t\n" ) ); + dStrcpy( tempBuf, StringUnit::getUnit( fieldList, fieldIndex, " \t\n" ), bufferSizes ); // Store field. fields.push_back( StringTable->insert( tempBuf ) ); diff --git a/Engine/source/console/fileSystemFunctions.cpp b/Engine/source/console/fileSystemFunctions.cpp index d8531ff7c..23ef01c24 100644 --- a/Engine/source/console/fileSystemFunctions.cpp +++ b/Engine/source/console/fileSystemFunctions.cpp @@ -495,7 +495,7 @@ DefineEngineFunction(getDirectoryList, String, ( const char* path, S32 depth ), // Copy the directory names to the buffer. for (S32 i = 0; i < directories.size(); i++) { - dStrcpy(p, directories[i]); + dStrcpy(p, directories[i], length - (p - buffer)); p += dStrlen(directories[i]); // Tab separated. p[0] = '\t'; @@ -537,7 +537,7 @@ DefineEngineFunction( fileModifiedTime, String, ( const char* fileName ),, String fileStr = Platform::localTimeToString( lt ); char *buffer = Con::getReturnBuffer( fileStr.size() ); - dStrcpy( buffer, fileStr ); + dStrcpy( buffer, fileStr, fileStr.size() ); return buffer; } @@ -560,7 +560,7 @@ DefineEngineFunction( fileCreatedTime, String, ( const char* fileName ),, String fileStr = Platform::localTimeToString( lt ); char *buffer = Con::getReturnBuffer( fileStr.size() ); - dStrcpy( buffer, fileStr ); + dStrcpy( buffer, fileStr, fileStr.size() ); return buffer; } @@ -609,7 +609,7 @@ DefineEngineFunction(fileBase, String, ( const char* fileName ),, S32 pathLen = dStrlen( fileName ); FrameTemp szPathCopy( pathLen + 1); - dStrcpy( szPathCopy, fileName ); + dStrcpy( szPathCopy, fileName, pathLen + 1 ); forwardslash( szPathCopy ); const char *path = dStrrchr(szPathCopy, '/'); @@ -617,8 +617,9 @@ DefineEngineFunction(fileBase, String, ( const char* fileName ),, path = szPathCopy; else path++; - char *ret = Con::getReturnBuffer(dStrlen(path) + 1); - dStrcpy(ret, path); + dsize_t retLen = dStrlen(path) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, path, retLen); char *ext = dStrrchr(ret, '.'); if(ext) *ext = 0; @@ -635,7 +636,7 @@ DefineEngineFunction(fileName, String, ( const char* fileName ),, S32 pathLen = dStrlen( fileName ); FrameTemp szPathCopy( pathLen + 1); - dStrcpy( szPathCopy, fileName ); + dStrcpy( szPathCopy, fileName, pathLen + 1 ); forwardslash( szPathCopy ); const char *name = dStrrchr(szPathCopy, '/'); @@ -643,8 +644,9 @@ DefineEngineFunction(fileName, String, ( const char* fileName ),, name = szPathCopy; else name++; - char *ret = Con::getReturnBuffer(dStrlen(name)); - dStrcpy(ret, name); + dsize_t retLen = dStrlen(name) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, name, retLen); return ret; } @@ -658,7 +660,7 @@ DefineEngineFunction(filePath, String, ( const char* fileName ),, S32 pathLen = dStrlen( fileName ); FrameTemp szPathCopy( pathLen + 1); - dStrcpy( szPathCopy, fileName ); + dStrcpy( szPathCopy, fileName, pathLen + 1 ); forwardslash( szPathCopy ); const char *path = dStrrchr(szPathCopy, '/'); diff --git a/Engine/source/console/persistenceManager.cpp b/Engine/source/console/persistenceManager.cpp index c4af549ed..56812cd4b 100644 --- a/Engine/source/console/persistenceManager.cpp +++ b/Engine/source/console/persistenceManager.cpp @@ -950,7 +950,7 @@ void PersistenceManager::updateToken( const U32 lineNumber, const U32 linePositi char* postString = ( char* ) dMalloc( postStringLen + 1 ); if( needQuotes ) postString[ 0 ] = '"'; - dStrcpy( &postString[ needQuotes ? 1 : 0 ], postStringSrc ); + dStrcpy( &postString[ needQuotes ? 1 : 0 ], postStringSrc, postStringLen + (needQuotes ? 0 : 1) ); postString[ postStringLen ] = 0; // Calculate the length of our new line @@ -967,10 +967,10 @@ void PersistenceManager::updateToken( const U32 lineNumber, const U32 linePositi // Build the new line with the // preString + newValue + postString - dStrcat(newLine, preString); + dStrcat(newLine, preString, newLineLen + 1); if ( newValue ) - dStrcat(newLine, newValue); - dStrcat(newLine, postString); + dStrcat(newLine, newValue, newLineLen + 1); + dStrcat(newLine, postString, newLineLen + 1); // Clear our existing line if (mLineBuffer[lineNumber]) @@ -1243,7 +1243,7 @@ PersistenceManager::ParsedObject* PersistenceManager::writeNewObject(SimObject* char* indent = getObjectIndent(parentObject); if (parentObject) - dStrcat(indent, " \0"); + dStrcat(indent, " \0", 2048); // Write out the beginning of the object declaration const char* dclToken = "new"; diff --git a/Engine/source/console/scriptFilename.cpp b/Engine/source/console/scriptFilename.cpp index 7a72756af..332f01d26 100644 --- a/Engine/source/console/scriptFilename.cpp +++ b/Engine/source/console/scriptFilename.cpp @@ -189,7 +189,7 @@ bool expandToolScriptFilename(char *filename, U32 size, const char *src) // Relative to script directory if(cbFullPath) { - dStrcpy(varBuf, cbFullPath); + dStrcpy(varBuf, cbFullPath, 1024); slash = dStrrchr(varBuf, '/'); if(slash) *slash = 0; @@ -219,7 +219,7 @@ bool expandOldScriptFilename(char *filename, U32 size, const char *src) const StringTableEntry cbName = CodeBlock::getCurrentCodeBlockName(); if (!cbName) { - dStrcpy(filename, src); + dStrcpy(filename, src, size); return true; } @@ -244,7 +244,7 @@ bool expandOldScriptFilename(char *filename, U32 size, const char *src) *filename = 0; return false; } - dStrcpy(filename, src); + dStrcpy(filename, src, size); return true; } @@ -264,7 +264,7 @@ bool expandOldScriptFilename(char *filename, U32 size, const char *src) } dStrncpy(filename, cbName, length); - dStrcpy(filename+length, src+1); + dStrcpy(filename+length, src+1, size - length); return true; } @@ -325,7 +325,7 @@ bool collapseScriptFilename(char *filename, U32 size, const char *src) *filename = 0; if(*test[i].replace) dSprintf(filename, size, "%s/", test[i].replace); - dStrcat(filename, rel); + dStrcat(filename, rel, size); return true; } diff --git a/Engine/source/console/sim.cpp b/Engine/source/console/sim.cpp index 0ea902b5c..cb01e8019 100644 --- a/Engine/source/console/sim.cpp +++ b/Engine/source/console/sim.cpp @@ -216,7 +216,7 @@ DefineConsoleFunction( getUniqueName, const char*, (const char * baseName), , return NULL; char *buffer = Con::getReturnBuffer( outName.size() ); - dStrcpy( buffer, outName ); + dStrcpy( buffer, outName, outName.size() ); return buffer; } @@ -241,7 +241,7 @@ DefineConsoleFunction( getUniqueInternalName, const char*, (const char * baseNam return NULL; char *buffer = Con::getReturnBuffer( outName.size() ); - dStrcpy( buffer, outName ); + dStrcpy( buffer, outName, outName.size() ); return buffer; } diff --git a/Engine/source/console/simDatablock.cpp b/Engine/source/console/simDatablock.cpp index 85d2ee8f8..84d11f932 100644 --- a/Engine/source/console/simDatablock.cpp +++ b/Engine/source/console/simDatablock.cpp @@ -198,10 +198,10 @@ void SimDataBlock::performSubstitutions(SimDataBlock* dblock, const SimObject* o } char obj_str[32]; - dStrcpy(obj_str, Con::getIntArg(obj->getId())); + dStrcpy(obj_str, Con::getIntArg(obj->getId()), 32); char index_str[32]; - dStrcpy(index_str, Con::getIntArg(index)); + dStrcpy(index_str, Con::getIntArg(index), 32); for (S32 i = 0; i < substitutions.size(); i++) { diff --git a/Engine/source/console/simFieldDictionary.cpp b/Engine/source/console/simFieldDictionary.cpp index 2c9f474ae..332224160 100644 --- a/Engine/source/console/simFieldDictionary.cpp +++ b/Engine/source/console/simFieldDictionary.cpp @@ -281,7 +281,7 @@ void SimFieldDictionary::writeFields(SimObject *obj, Stream &stream, U32 tabStop dSprintf(expandedBuffer, nBufferSize, "%s%s%s = \"", typeName, *typeName ? " " : "", (*itr)->slotName); if ((*itr)->value) expandEscape((char*)expandedBuffer + dStrlen(expandedBuffer), (*itr)->value); - dStrcat(expandedBuffer, "\";\r\n"); + dStrcat(expandedBuffer, "\";\r\n", nBufferSize); stream.write(dStrlen(expandedBuffer), expandedBuffer); } diff --git a/Engine/source/console/simObject.cpp b/Engine/source/console/simObject.cpp index c3044df0e..ef23f0448 100644 --- a/Engine/source/console/simObject.cpp +++ b/Engine/source/console/simObject.cpp @@ -320,7 +320,7 @@ void SimObject::writeFields(Stream &stream, U32 tabStop) U32 nBufferSize = dStrlen( val ) + 1; FrameTemp valCopy( nBufferSize ); - dStrcpy( (char *)valCopy, val ); + dStrcpy( (char *)valCopy, val, nBufferSize ); if (!writeField(f->pFieldname, valCopy)) continue; @@ -347,7 +347,7 @@ void SimObject::writeFields(Stream &stream, U32 tabStop) } expandEscape((char*)expandedBuffer + dStrlen(expandedBuffer), val); - dStrcat(expandedBuffer, "\";\r\n"); + dStrcat(expandedBuffer, "\";\r\n", expandedBufferSize); stream.writeTabs(tabStop); stream.write(dStrlen(expandedBuffer),expandedBuffer); @@ -402,12 +402,12 @@ bool SimObject::save(const char *pcFileName, bool bOnlySelected, const char *pre char docRoot[256]; char modRoot[256]; - dStrcpy(docRoot, pcFileName); + dStrcpy(docRoot, pcFileName, 256); char *p = dStrrchr(docRoot, '/'); if (p) *++p = '\0'; else docRoot[0] = '\0'; - dStrcpy(modRoot, pcFileName); + dStrcpy(modRoot, pcFileName, 256); p = dStrchr(modRoot, '/'); if (p) *++p = '\0'; else modRoot[0] = '\0'; @@ -1028,8 +1028,8 @@ void SimObject::setDataField(StringTableEntry slotName, const char *array, const else { char buf[256]; - dStrcpy(buf, slotName); - dStrcat(buf, array); + dStrcpy(buf, slotName, 256); + dStrcat(buf, array, 256); StringTableEntry permanentSlotName = StringTable->insert(buf); mFieldDictionary->setFieldValue(permanentSlotName, value); onDynamicModified( permanentSlotName, value ); @@ -1069,8 +1069,8 @@ const char *SimObject::getDataField(StringTableEntry slotName, const char *array else { static char buf[256]; - dStrcpy(buf, slotName); - dStrcat(buf, array); + dStrcpy(buf, slotName, 256); + dStrcat(buf, array, 256); if (const char* val = mFieldDictionary->getFieldValue(StringTable->insert(buf))) return val; } @@ -1310,8 +1310,8 @@ U32 SimObject::getDataFieldType( StringTableEntry slotName, const char* array ) else { static char buf[256]; - dStrcpy( buf, slotName ); - dStrcat( buf, array ); + dStrcpy( buf, slotName, 256 ); + dStrcat( buf, array, 256 ); return mFieldDictionary->getFieldType( StringTable->insert( buf ) ); } @@ -1333,8 +1333,8 @@ void SimObject::setDataFieldType(const U32 fieldTypeId, StringTableEntry slotNam else { static char buf[256]; - dStrcpy( buf, slotName ); - dStrcat( buf, array ); + dStrcpy( buf, slotName, 256 ); + dStrcat( buf, array, 256 ); mFieldDictionary->setFieldType( StringTable->insert( buf ), fieldTypeId ); onDynamicModified( slotName, mFieldDictionary->getFieldValue(slotName) ); @@ -1354,8 +1354,8 @@ void SimObject::setDataFieldType(const char *typeName, StringTableEntry slotName else { static char buf[256]; - dStrcpy( buf, slotName ); - dStrcat( buf, array ); + dStrcpy( buf, slotName, 256 ); + dStrcat( buf, array, 256 ); StringTableEntry permanentSlotName = StringTable->insert(buf); mFieldDictionary->setFieldType( permanentSlotName, typeName ); diff --git a/Engine/source/console/simObjectMemento.cpp b/Engine/source/console/simObjectMemento.cpp index ef2e8f732..949349442 100644 --- a/Engine/source/console/simObjectMemento.cpp +++ b/Engine/source/console/simObjectMemento.cpp @@ -134,10 +134,11 @@ SimObject *SimObjectMemento::restore() const return NULL; U32 numCharsToLeftParen = pLeftParen - mState; - tempBuffer = ( char* ) dMalloc( dStrlen( mState ) + uniqueNameLen + 1 ); + dsize_t tempBufferLen = dStrlen(mState) + uniqueNameLen + 1; + tempBuffer = ( char* ) dMalloc( tempBufferLen ); dMemcpy( tempBuffer, mState, numCharsToLeftParen ); dMemcpy( &tempBuffer[ numCharsToLeftParen ], uniqueName, uniqueNameLen ); - dStrcpy( &tempBuffer[ numCharsToLeftParen + uniqueNameLen ], &mState[ numCharsToLeftParen ] ); + dStrcpy( &tempBuffer[ numCharsToLeftParen + uniqueNameLen ], &mState[ numCharsToLeftParen ], tempBufferLen - numCharsToLeftParen - uniqueNameLen ); } Con::evaluate( tempBuffer ); diff --git a/Engine/source/console/stringStack.h b/Engine/source/console/stringStack.h index d76ad71ec..0550bb61e 100644 --- a/Engine/source/console/stringStack.h +++ b/Engine/source/console/stringStack.h @@ -176,7 +176,7 @@ struct StringStack mLen = dStrlen(s); validateBufferSize(mStart + mLen + 2); - dStrcpy(mBuffer + mStart, s); + dStrcpy(mBuffer + mStart, s, mBufferSize - mStart); } /// Get the top of the stack, as a StringTableEntry. diff --git a/Engine/source/console/telnetDebugger.cpp b/Engine/source/console/telnetDebugger.cpp index 7db6e9710..7cb39dc83 100644 --- a/Engine/source/console/telnetDebugger.cpp +++ b/Engine/source/console/telnetDebugger.cpp @@ -470,19 +470,19 @@ void TelnetDebugger::sendBreak() if ( ns ) { if ( ns->mParent && ns->mParent->mPackage && ns->mParent->mPackage[0] ) { - dStrcat( scope, ns->mParent->mPackage ); - dStrcat( scope, "::" ); + dStrcat( scope, ns->mParent->mPackage, MaxCommandSize ); + dStrcat( scope, "::", MaxCommandSize ); } if ( ns->mName && ns->mName[0] ) { - dStrcat( scope, ns->mName ); - dStrcat( scope, "::" ); + dStrcat( scope, ns->mName, MaxCommandSize ); + dStrcat( scope, "::", MaxCommandSize ); } } const char *function = gEvalState.stack[i]->scopeName; if ((!function) || (!function[0])) function = ""; - dStrcat( scope, function ); + dStrcat( scope, function, MaxCommandSize ); U32 line=0, inst; U32 ip = gEvalState.stack[i]->ip; diff --git a/Engine/source/core/frameAllocator.h b/Engine/source/core/frameAllocator.h index 86884085c..2e03e6fc2 100644 --- a/Engine/source/core/frameAllocator.h +++ b/Engine/source/core/frameAllocator.h @@ -185,7 +185,7 @@ public: /// the FrameAllocator. For example: /// @code /// FrameTemp tempStr(32); // NOTE! This parameter is NOT THE SIZE IN BYTES. See constructor docs. -/// dStrcat( tempStr, SomeOtherString ); +/// dStrcat( tempStr, SomeOtherString, 32 * sizeof(char) ); /// tempStr[2] = 'l'; /// Con::printf( tempStr ); /// Con::printf( "Foo: %s", ~tempStr ); diff --git a/Engine/source/core/stream/bitStream.cpp b/Engine/source/core/stream/bitStream.cpp index 2a62b4964..1a5ab3202 100644 --- a/Engine/source/core/stream/bitStream.cpp +++ b/Engine/source/core/stream/bitStream.cpp @@ -668,13 +668,13 @@ void BitStream::readString(char buf[256]) { S32 offset = readInt(8); HuffmanProcessor::g_huffProcessor.readHuffBuffer(this, stringBuffer + offset); - dStrcpy(buf, stringBuffer); + dStrcpy(buf, stringBuffer, 256); return; } } HuffmanProcessor::g_huffProcessor.readHuffBuffer(this, buf); if(stringBuffer) - dStrcpy(stringBuffer, buf); + dStrcpy(stringBuffer, buf, 256); } void BitStream::writeString(const char *string, S32 maxLen) diff --git a/Engine/source/core/stringTable.cpp b/Engine/source/core/stringTable.cpp index cbdfaec40..f88a0af2f 100644 --- a/Engine/source/core/stringTable.cpp +++ b/Engine/source/core/stringTable.cpp @@ -142,10 +142,11 @@ StringTableEntry _StringTable::insert(const char* _val, const bool caseSens) } char *ret = 0; if(!*walk) { + dsize_t valLen = dStrlen(val) + 1; *walk = (Node *) mempool.alloc(sizeof(Node)); (*walk)->next = 0; - (*walk)->val = (char *) mempool.alloc(dStrlen(val) + 1); - dStrcpy((*walk)->val, val); + (*walk)->val = (char *) mempool.alloc(valLen); + dStrcpy((*walk)->val, val, valLen); ret = (*walk)->val; itemCount ++; } diff --git a/Engine/source/core/strings/findMatch.cpp b/Engine/source/core/strings/findMatch.cpp index 1bb35128e..97829a5ca 100644 --- a/Engine/source/core/strings/findMatch.cpp +++ b/Engine/source/core/strings/findMatch.cpp @@ -71,8 +71,9 @@ void FindMatch::setExpression( const char *_expression ) { delete [] expression; - expression = new char[dStrlen(_expression) + 1]; - dStrcpy(expression, _expression); + dsize_t expressionLen = dStrlen(_expression) + 1; + expression = new char[expressionLen]; + dStrcpy(expression, _expression, expressionLen); dStrupr(expression); } @@ -82,7 +83,7 @@ bool FindMatch::findMatch( const char *str, bool caseSensitive ) return false; char nstr[512]; - dStrcpy( nstr,str ); + dStrcpy( nstr,str,512 ); dStrupr(nstr); if ( isMatch( expression, nstr, caseSensitive ) ) { @@ -143,7 +144,7 @@ bool FindMatch::isMatchMultipleExprs( const char *exps, const char *str, bool ca S32 len = dStrlen(exps); char *e = new char[len+1]; - dStrcpy(e,exps); + dStrcpy(e,exps,len+1); // [tom, 12/18/2006] This no longer supports space separated expressions as // they don't work when the paths have spaces in. diff --git a/Engine/source/core/strings/stringFunctions.cpp b/Engine/source/core/strings/stringFunctions.cpp index 3fe24c7f1..77f7214d0 100644 --- a/Engine/source/core/strings/stringFunctions.cpp +++ b/Engine/source/core/strings/stringFunctions.cpp @@ -215,8 +215,9 @@ S32 dStrnatcasecmp(const nat_char* a, const nat_char* b) { char *dStrdup_r(const char *src, const char *fileName, dsize_t lineNumber) { - char *buffer = (char *) dMalloc_r(dStrlen(src) + 1, fileName, lineNumber); - dStrcpy(buffer, src); + dsize_t bufferLen = dStrlen(src) + 1; + char *buffer = (char *) dMalloc_r(bufferLen, fileName, lineNumber); + dStrcpy(buffer, src, bufferLen); return buffer; } @@ -381,6 +382,67 @@ char* dStrlwr(char *str) #endif } +//------------------------------------------------------------------------------ + +S32 dStrlcat(char *dst, const char *src, dsize_t dstSize) +{ + //TODO: Do other platforms support strlcat in their libc +#ifdef TORQUE_OS_MAC + S32 len = strlcat(dst, src, dstSize); + + AssertWarn(len < dstSize, "Buffer too small in call to dStrlcat!"); + + return len; +#else //TORQUE_OS_MAC + S32 dstLen = dStrlen(dst); + S32 srcLen = dStrlen(src); + S32 copyLen = srcLen; + + //Check for buffer overflow and don't allow it. Warn on debug so we can fix it + AssertWarn(dstLen + copyLen < dstSize, "Buffer too small in call to dStrlcat!"); + if (dstLen + copyLen + 1 > dstSize) + { + copyLen = dstSize - dstLen - 1; + } + + //Copy src after dst and null terminate + memcpy(dst + dstLen, src, copyLen); + dst[dstLen + copyLen] = 0; + + //Return the length of the string we would have generated + return dstLen + srcLen; +#endif //TORQUE_OS_MAC +} + +S32 dStrlcpy(char *dst, const char *src, dsize_t dstSize) +{ + //TODO: Do other platforms support strlcpy in their libc +#ifdef TORQUE_OS_MAC + S32 len = strlcpy(dst, src, dstSize); + + AssertWarn(len < dstSize, "Buffer too small in call to dStrlcpy!"); + + return len; +#else //TORQUE_OS_MAC + S32 srcLen = dStrlen(src); + S32 copyLen = srcLen; + + //Check for buffer overflow and don't allow it. Warn on debug so we can fix it + AssertWarn(copyLen < dstSize, "Buffer too small in call to dStrlcpy!"); + if (srcLen + 1 > dstSize) + { + copyLen = dstSize - 1; + } + + //Copy src and null terminate + memcpy(dst, src, copyLen); + dst[copyLen] = 0; + + //Return the length of the string we would have generated + return srcLen; +#endif //TORQUE_OS_MAC +} + //------------------------------------------------------------------------------ // standard I/O functions diff --git a/Engine/source/core/strings/stringFunctions.h b/Engine/source/core/strings/stringFunctions.h index 6a3d54548..918273423 100644 --- a/Engine/source/core/strings/stringFunctions.h +++ b/Engine/source/core/strings/stringFunctions.h @@ -32,6 +32,10 @@ #include "platform/types.h" #endif +#ifndef _PLATFORMASSERT_H_ +#include "platform/platformAssert.h" +#endif + #if defined(TORQUE_OS_WIN) // These standard functions are not defined on Win32 and other Microsoft platforms... #define strcasecmp _stricmp @@ -43,18 +47,37 @@ #endif // defined(TORQUE_OS_WIN) - //------------------------------------------------------------------------------ // standard string functions [defined in platformString.cpp] +// Buffer size bounds checking "safe" versions of strcat and strcpy. Ideally you +// should use these and check if they return >= dstSize and throw an error if so. +extern S32 dStrlcat(char *dst, const char *src, dsize_t dstSize); +extern S32 dStrlcpy(char *dst, const char *src, dsize_t dstSize); + +#ifdef UNSAFE_STRING_FUNCTIONS +/// @deprecated Use dStrcat(char *, const char *, dsize_t) instead inline char *dStrcat(char *dst, const char *src) { + AssertFatal(false, "dStrcat without length is deprecated"); return strcat(dst,src); } +#endif + +/// Concatenate strings. +/// @note The third parameter is the size of the destination buffer like strlcat +/// instead of the number of characters to copy like strncat. This is done +/// under the assumption that being easier to use will make this safer. +/// If you want the original behavior use dStrncat. +inline char *dStrcat(char *dst, const char *src, dsize_t dstSize) +{ + dStrlcat(dst, src, dstSize); + return dst; +} inline char *dStrncat(char *dst, const char *src, dsize_t len) { - return strncat(dst,src,len); + return strncat(dst, src, len); } inline S32 dStrcmp(const char *str1, const char *str2) @@ -82,9 +105,19 @@ inline S32 dStrnicmp(const char *str1, const char *str2, dsize_t len) return strncasecmp( str1, str2, len ); } +#ifdef UNSAFE_STRING_FUNCTIONS +/// @deprecated Use strcpy(char *, const char *, dsize_t) instead inline char *dStrcpy(char *dst, const char *src) { + AssertFatal(false, "dStrcpy without length is deprecated"); return strcpy(dst,src); +} +#endif + +inline char *dStrcpy(char *dst, const char *src, dsize_t dstSize) +{ + dStrlcpy(dst, src, dstSize); + return dst; } inline char *dStrncpy(char *dst, const char *src, dsize_t len) diff --git a/Engine/source/core/strings/stringUnit.cpp b/Engine/source/core/strings/stringUnit.cpp index dc666f38c..0012d60e6 100644 --- a/Engine/source/core/strings/stringUnit.cpp +++ b/Engine/source/core/strings/stringUnit.cpp @@ -164,7 +164,7 @@ namespace StringUnit // replace this unit ret[sz] = '\0'; - dStrcat(ret, replace); + dStrcat(ret, replace, 2048); // copy remaining chunks sz = dStrcspn(string, set); // skip chunk we're replacing @@ -172,7 +172,7 @@ namespace StringUnit return ret; string += sz; - dStrcat(ret, string); + dStrcat(ret, string, 2048); return ret; } @@ -211,7 +211,7 @@ namespace StringUnit } string += sz + 1; // skip the extra field delimiter - dStrcat(ret, string); + dStrcat(ret, string, 2048); return ret; } } diff --git a/Engine/source/core/tokenizer.cpp b/Engine/source/core/tokenizer.cpp index a51d3d5ad..6d155d18a 100644 --- a/Engine/source/core/tokenizer.cpp +++ b/Engine/source/core/tokenizer.cpp @@ -61,7 +61,7 @@ bool Tokenizer::openFile(const char* pFileName) delete pStream; return false; } - dStrcpy(mFileName, pFileName); + dStrcpy(mFileName, pFileName, 1024); mBufferSize = pStream->getStreamSize(); mpBuffer = new char[mBufferSize]; @@ -99,7 +99,7 @@ void Tokenizer::setBuffer(const char* buffer, U32 bufferSize) mBufferSize = bufferSize; mpBuffer = new char[mBufferSize + 1]; - dStrcpy(mpBuffer, buffer); + dStrcpy(mpBuffer, buffer, mBufferSize + 1); reset(); @@ -634,4 +634,4 @@ bool Tokenizer::endOfFile() return false; else return true; -} \ No newline at end of file +} diff --git a/Engine/source/core/util/zip/centralDir.cpp b/Engine/source/core/util/zip/centralDir.cpp index e107df2e8..7646bac7a 100644 --- a/Engine/source/core/util/zip/centralDir.cpp +++ b/Engine/source/core/util/zip/centralDir.cpp @@ -177,8 +177,9 @@ bool CentralDir::write(Stream *stream) void CentralDir::setFileComment(const char *comment) { SAFE_DELETE_ARRAY(mFileComment); - mFileComment = new char [dStrlen(comment)+1]; - dStrcpy(mFileComment, comment); + dsize_t commentLen = dStrlen(comment) + 1; + mFileComment = new char [commentLen]; + dStrcpy(mFileComment, comment, commentLen); } //----------------------------------------------------------------------------- diff --git a/Engine/source/core/util/zip/test/zipTestWrite.cpp b/Engine/source/core/util/zip/test/zipTestWrite.cpp index 889cf6948..d23f9a657 100644 --- a/Engine/source/core/util/zip/test/zipTestWrite.cpp +++ b/Engine/source/core/util/zip/test/zipTestWrite.cpp @@ -95,7 +95,7 @@ private: { // Find a unique filename U32 count = 1; - dStrcpy(fileBuf, filename); + dStrcpy(fileBuf, filename, bufSize); while(zip->findFileInfo(fileBuf)) { @@ -109,7 +109,7 @@ private: } } else if(fileBuf && bufSize > 0) - dStrcpy(fileBuf, filename); + dStrcpy(fileBuf, filename, bufSize); // Try and write to the file Stream * stream = zip->openFile(fileBuf ? fileBuf : filename, ZipArchive::Write); diff --git a/Engine/source/gfx/Null/gfxNullDevice.cpp b/Engine/source/gfx/Null/gfxNullDevice.cpp index f22e3bc7a..6b2b0b659 100644 --- a/Engine/source/gfx/Null/gfxNullDevice.cpp +++ b/Engine/source/gfx/Null/gfxNullDevice.cpp @@ -309,7 +309,7 @@ void GFXNullDevice::enumerateAdapters( Vector &adapterList ) vm.resolution.set(800,600); toAdd->mAvailableModes.push_back(vm); - dStrcpy(toAdd->mName, "GFX Null Device"); + dStrcpy(toAdd->mName, "GFX Null Device", GFXAdapter::MaxAdapterNameLen); adapterList.push_back(toAdd); } @@ -342,4 +342,4 @@ public: } }; -static GFXNullRegisterDevice pNullRegisterDevice; \ No newline at end of file +static GFXNullRegisterDevice pNullRegisterDevice; diff --git a/Engine/source/gfx/gfxStructs.cpp b/Engine/source/gfx/gfxStructs.cpp index dca361af1..7f64c6ee6 100644 --- a/Engine/source/gfx/gfxStructs.cpp +++ b/Engine/source/gfx/gfxStructs.cpp @@ -39,8 +39,9 @@ void GFXVideoMode::parseFromString( const char *str ) return; // Copy the string, as dStrtok is destructive - char *tempBuf = new char[dStrlen( str ) + 1]; - dStrcpy( tempBuf, str ); + dsize_t tempBufLen = dStrlen(str) + 1; + char *tempBuf = new char[tempBufLen]; + dStrcpy( tempBuf, str, tempBufLen ); #define PARSE_ELEM(type, var, func, tokParam, sep) \ if(const char *ptr = dStrtok( tokParam, sep)) \ @@ -76,4 +77,4 @@ void GFXShaderMacro::stringize( const Vector ¯os, String *ou } (*outString) += ";"; } -} \ No newline at end of file +} diff --git a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp index 3f3245c91..79308ce1c 100644 --- a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp +++ b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp @@ -128,11 +128,11 @@ void GFXGLDevice::enumerateAdapters( Vector &adapterList ) if (renderer) { - dStrcpy(toAdd->mName, renderer); - dStrncat(toAdd->mName, " OpenGL", GFXAdapter::MaxAdapterNameLen); + dStrcpy(toAdd->mName, renderer, GFXAdapter::MaxAdapterNameLen); + dStrcat(toAdd->mName, " OpenGL", GFXAdapter::MaxAdapterNameLen); } else - dStrcpy(toAdd->mName, "OpenGL"); + dStrcpy(toAdd->mName, "OpenGL", GFXAdapter::MaxAdapterNameLen); toAdd->mType = OpenGL; toAdd->mShaderModel = 0.f; diff --git a/Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp b/Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp index eaf7d1449..cb71ca48c 100644 --- a/Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp +++ b/Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp @@ -129,11 +129,11 @@ void GFXGLDevice::enumerateAdapters( Vector &adapterList ) if (renderer) { - dStrcpy(toAdd->mName, renderer); + dStrcpy(toAdd->mName, renderer, GFXAdapter::MaxAdapterNameLen); dStrncat(toAdd->mName, " OpenGL", GFXAdapter::MaxAdapterNameLen); } else - dStrcpy(toAdd->mName, "OpenGL"); + dStrcpy(toAdd->mName, "OpenGL", GFXAdapter::MaxAdapterNameLen); toAdd->mType = OpenGL; toAdd->mShaderModel = 0.f; diff --git a/Engine/source/gfx/screenshot.cpp b/Engine/source/gfx/screenshot.cpp index f10802bf3..1ba48d75d 100644 --- a/Engine/source/gfx/screenshot.cpp +++ b/Engine/source/gfx/screenshot.cpp @@ -55,7 +55,7 @@ ScreenShot::ScreenShot() void ScreenShot::setPending( const char *filename, bool writeJPG, S32 tiles, F32 overlap ) { - dStrcpy( mFilename, filename ); + dStrcpy( mFilename, filename, 256 ); mWriteJPG = writeJPG; mTiles = getMax( tiles, 1 ); mPixelOverlap.set(getMin(overlap, 0.25f), getMin(overlap, 0.25f)); diff --git a/Engine/source/gui/containers/guiFormCtrl.cpp b/Engine/source/gui/containers/guiFormCtrl.cpp index f94e6c234..0c562d49d 100644 --- a/Engine/source/gui/containers/guiFormCtrl.cpp +++ b/Engine/source/gui/containers/guiFormCtrl.cpp @@ -218,9 +218,9 @@ bool GuiFormCtrl::resize(const Point2I &newPosition, const Point2I &newExtent) S32 strlen = dStrlen((const char*)mCaption); for(S32 i=strlen; i>=0; --i) { - dStrcpy(buf, ""); - dStrncat(buf, (const char*)mCaption, i); - dStrcat(buf, "..."); + dStrcpy(buf, "", i); + dStrcat(buf, (const char*)mCaption, i); + dStrcat(buf, "...", i); textWidth = mProfile->mFont->getStrWidth(buf); diff --git a/Engine/source/gui/controls/guiAnimBitmapCtrl.cpp b/Engine/source/gui/controls/guiAnimBitmapCtrl.cpp index eff5f1410..26ce32376 100644 --- a/Engine/source/gui/controls/guiAnimBitmapCtrl.cpp +++ b/Engine/source/gui/controls/guiAnimBitmapCtrl.cpp @@ -167,8 +167,9 @@ bool guiAnimBitmapCtrl::ptSetFrameRanges(void *object, const char *index, const pData->mCurFrameIndex = pData->mNumFrames; return true; } - char* tokCopy = new char[dStrlen(data) + 1]; - dStrcpy(tokCopy, data); + dsize_t tokLen = dStrlen(data) + 1; + char* tokCopy = new char[tokLen]; + dStrcpy(tokCopy, data, tokLen); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) @@ -291,4 +292,4 @@ void guiAnimBitmapCtrl::onRender(Point2I offset, const RectI &updateRect) } renderChildControls(offset, updateRect); -} \ No newline at end of file +} diff --git a/Engine/source/gui/controls/guiConsole.cpp b/Engine/source/gui/controls/guiConsole.cpp index 0a1e2459d..d063272bf 100644 --- a/Engine/source/gui/controls/guiConsole.cpp +++ b/Engine/source/gui/controls/guiConsole.cpp @@ -50,6 +50,12 @@ IMPLEMENT_CALLBACK( GuiConsole, onMessageSelected, void, ( ConsoleLogEntry::Leve "@param level Diagnostic level of the message.\n" "@param message Message text.\n" ); +IMPLEMENT_CALLBACK(GuiConsole, onNewMessage, void, (U32 errorCount, U32 warnCount, U32 normalCount), (errorCount, warnCount, normalCount), + "Called when a new message is logged.\n\n" + "@param errorCount The number of error messages logged.\n" + "@param warnCount The number of warning messages logged.\n" + "@param normalCount The number of normal messages logged.\n"); + //----------------------------------------------------------------------------- @@ -58,6 +64,11 @@ GuiConsole::GuiConsole() setExtent(64, 64); mCellSize.set(1, 1); mSize.set(1, 0); + + mDisplayErrors = true; + mDisplayWarnings = true; + mDisplayNormalMessages = true; + mFiltersDirty = true; } //----------------------------------------------------------------------------- @@ -81,56 +92,98 @@ S32 GuiConsole::getMaxWidth(S32 startIndex, S32 endIndex) U32 size; ConsoleLogEntry *log; - Con::getLockLog(log, size); - - if(startIndex < 0 || (U32)endIndex >= size || startIndex > endIndex) + if (startIndex < 0 || (U32)endIndex >= mFilteredLog.size() || startIndex > endIndex) return 0; S32 result = 0; for(S32 i = startIndex; i <= endIndex; i++) - result = getMax(result, (S32)(mFont->getStrWidth((const UTF8 *)log[i].mString))); - - Con::unlockLog(); + result = getMax(result, (S32)(mFont->getStrWidth((const UTF8 *)mFilteredLog[i].mString))); return(result + 6); } +void GuiConsole::refreshLogText() +{ + U32 size; + ConsoleLogEntry *log; + + Con::getLockLog(log, size); + + if (mFilteredLog.size() != size || mFiltersDirty) + { + mFilteredLog.clear(); + + U32 errorCount = 0; + U32 warnCount = 0; + U32 normalCount = 0; + + //Filter the log if needed + for (U32 i = 0; i < size; ++i) + { + ConsoleLogEntry &entry = log[i]; + + if (entry.mLevel == ConsoleLogEntry::Error) + { + errorCount++; + if (mDisplayErrors) + { + mFilteredLog.push_back(entry); + } + } + else if (entry.mLevel == ConsoleLogEntry::Warning) + { + warnCount++; + if (mDisplayWarnings) + { + mFilteredLog.push_back(entry); + } + } + else if (entry.mLevel == ConsoleLogEntry::Normal) + { + normalCount++; + if (mDisplayNormalMessages) + { + mFilteredLog.push_back(entry); + } + } + } + + onNewMessage_callback(errorCount, warnCount, normalCount); + } + + Con::unlockLog(); +} + //----------------------------------------------------------------------------- void GuiConsole::onPreRender() { //see if the size has changed U32 prevSize = getHeight() / mCellSize.y; - U32 size; - ConsoleLogEntry *log; - Con::getLockLog(log, size); - Con::unlockLog(); // we unlock immediately because we only use size here, not log. + refreshLogText(); - if(size != prevSize) - { - //first, find out if the console was scrolled up - bool scrolled = false; - GuiScrollCtrl *parent = dynamic_cast(getParent()); + //first, find out if the console was scrolled up + bool scrolled = false; + GuiScrollCtrl *parent = dynamic_cast(getParent()); - if(parent) - scrolled = parent->isScrolledToBottom(); + if(parent) + scrolled = parent->isScrolledToBottom(); - //find the max cell width for the new entries - S32 newMax = getMaxWidth(prevSize, size - 1); - if(newMax > mCellSize.x) - mCellSize.set(newMax, mFont->getHeight()); + //find the max cell width for the new entries + S32 newMax = getMaxWidth(prevSize, mFilteredLog.size() - 1); + if(newMax > mCellSize.x) + mCellSize.set(newMax, mFont->getHeight()); - //set the array size - mSize.set(1, size); + //set the array size + mSize.set(1, mFilteredLog.size()); - //resize the control - setExtent( Point2I(mCellSize.x, mCellSize.y * size)); + //resize the control + setExtent(Point2I(mCellSize.x, mCellSize.y * mFilteredLog.size())); - //if the console was not scrolled, make the last entry visible - if (scrolled) - scrollCellVisible(Point2I(0,mSize.y - 1)); - } + //if the console was not scrolled, make the last entry visible + if (scrolled) + scrollCellVisible(Point2I(0,mSize.y - 1)); } //----------------------------------------------------------------------------- @@ -139,10 +192,8 @@ void GuiConsole::onRenderCell(Point2I offset, Point2I cell, bool /*selected*/, b { U32 size; ConsoleLogEntry *log; - - Con::getLockLog(log, size); - - ConsoleLogEntry &entry = log[cell.y]; + + ConsoleLogEntry &entry = mFilteredLog[cell.y]; switch (entry.mLevel) { case ConsoleLogEntry::Normal: GFX->getDrawUtil()->setBitmapModulation(mProfile->mFontColor); break; @@ -151,8 +202,6 @@ void GuiConsole::onRenderCell(Point2I offset, Point2I cell, bool /*selected*/, b default: AssertFatal(false, "GuiConsole::onRenderCell - Unrecognized ConsoleLogEntry type, update this."); } GFX->getDrawUtil()->drawText(mFont, Point2I(offset.x + 3, offset.y), entry.mString, mProfile->mFontColors); - - Con::unlockLog(); } //----------------------------------------------------------------------------- @@ -164,10 +213,81 @@ void GuiConsole::onCellSelected( Point2I cell ) U32 size; ConsoleLogEntry* log; - Con::getLockLog(log, size); - - ConsoleLogEntry& entry = log[ cell.y ]; + ConsoleLogEntry& entry = mFilteredLog[cell.y]; onMessageSelected_callback( entry.mLevel, entry.mString ); - - Con::unlockLog(); } + +void GuiConsole::setDisplayFilters(bool errors, bool warns, bool normal) +{ + mDisplayErrors = errors; + mDisplayWarnings = warns; + mDisplayNormalMessages = normal; + mFiltersDirty = true; + + refreshLogText(); + + //find the max cell width for the new entries + S32 newMax = getMaxWidth(0, mFilteredLog.size() - 1); + mCellSize.set(newMax, mFont->getHeight()); + + //set the array size + mSize.set(1, mFilteredLog.size()); + + //resize the control + setExtent(Point2I(mCellSize.x, mCellSize.y * mFilteredLog.size())); + + scrollCellVisible(Point2I(0, mSize.y - 1)); + + mFiltersDirty = false; +} + +DefineEngineMethod(GuiConsole, setDisplayFilters, void, (bool errors, bool warns, bool normal), (true, true, true), + "Sets the current display filters for the console gui. Allows you to indicate if it should display errors, warns and/or normal messages.\n\n" + "@param errors If true, the console gui will display any error messages that were emitted.\n\n" + "@param warns If true, the console gui will display any warning messages that were emitted.\n\n" + "@param normal If true, the console gui will display any regular messages that were emitted.\n\n") +{ + object->setDisplayFilters(errors, warns, normal); +} + +DefineEngineMethod(GuiConsole, getErrorFilter, bool, (), , + "Returns if the error filter is on or not.") +{ + return object->getErrorFilter(); +} + +DefineEngineMethod(GuiConsole, getWarnFilter, bool, (), , + "Returns if the warning filter is on or not.") +{ + return object->getWarnFilter(); +} + +DefineEngineMethod(GuiConsole, getNormalFilter, bool, (), , + "Returns if the normal message filter is on or not.") +{ + return object->getNormalFilter(); +} + +DefineEngineMethod(GuiConsole, toggleErrorFilter, void, (), , + "Toggles the error filter.") +{ + object->toggleErrorFilter(); +} + +DefineEngineMethod(GuiConsole, toggleWarnFilter, void, (), , + "Toggles the warning filter.") +{ + object->toggleWarnFilter(); +} + +DefineEngineMethod(GuiConsole, toggleNormalFilter, void, (), , + "Toggles the normal messages filter.") +{ + object->toggleNormalFilter(); +} + +DefineEngineMethod(GuiConsole, refresh, void, (), , + "Refreshes the displayed messages.") +{ + object->refresh(); +} \ No newline at end of file diff --git a/Engine/source/gui/controls/guiConsole.h b/Engine/source/gui/controls/guiConsole.h index 8f67573e1..2ef9eb7c8 100644 --- a/Engine/source/gui/controls/guiConsole.h +++ b/Engine/source/gui/controls/guiConsole.h @@ -39,14 +39,22 @@ class GuiConsole : public GuiArrayCtrl Resource mFont; + bool mDisplayErrors; + bool mDisplayWarnings; + bool mDisplayNormalMessages; + bool mFiltersDirty; + S32 getMaxWidth(S32 startIndex, S32 endIndex); + Vector mFilteredLog; + protected: /// @name Callbacks /// @{ DECLARE_CALLBACK( void, onMessageSelected, ( ConsoleLogEntry::Level level, const char* message ) ); + DECLARE_CALLBACK(void, onNewMessage, (U32 errorCount, U32 warnCount, U32 normalCount)); /// @} @@ -63,6 +71,30 @@ class GuiConsole : public GuiArrayCtrl virtual bool onWake(); virtual void onPreRender(); virtual void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver); + + void setDisplayFilters(bool errors, bool warns, bool normal); + bool getErrorFilter() { return mDisplayErrors; } + bool getWarnFilter() { return mDisplayWarnings; } + bool getNormalFilter() { return mDisplayNormalMessages; } + + void toggleErrorFilter() + { + setDisplayFilters(!mDisplayErrors, mDisplayWarnings, mDisplayNormalMessages); + } + void toggleWarnFilter() + { + setDisplayFilters(mDisplayErrors, !mDisplayWarnings, mDisplayNormalMessages); + } + void toggleNormalFilter() + { + setDisplayFilters(mDisplayErrors, mDisplayWarnings, !mDisplayNormalMessages); + } + void refresh() + { + setDisplayFilters(mDisplayErrors, mDisplayWarnings, mDisplayNormalMessages); + } + + void refreshLogText(); }; #endif diff --git a/Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp b/Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp index 2752bb9dd..724c0c4e2 100644 --- a/Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp +++ b/Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp @@ -195,7 +195,7 @@ DefineEngineMethod( GuiDirectoryFileListCtrl, getSelectedFiles, const char*, (), dMemset( itemBuffer, 0, itemBufSize ); dSprintf( itemBuffer, itemBufSize, " %s", itemText ); - dStrcat( returnBuffer, itemBuffer ); + dStrcat( returnBuffer, itemBuffer, itemBufSize ); } return returnBuffer; diff --git a/Engine/source/gui/controls/guiFileTreeCtrl.cpp b/Engine/source/gui/controls/guiFileTreeCtrl.cpp index db38fbe58..b6531fbaa 100644 --- a/Engine/source/gui/controls/guiFileTreeCtrl.cpp +++ b/Engine/source/gui/controls/guiFileTreeCtrl.cpp @@ -276,7 +276,7 @@ void GuiFileTreeCtrl::recurseInsert( Item* parent, StringTableEntry path ) char szPathCopy [ 1024 ]; dMemset( szPathCopy, 0, 1024 ); - dStrcpy( szPathCopy, path ); + dStrcpy( szPathCopy, path, 1024 ); // Jump over the first character if it's a root / char *curPos = szPathCopy; diff --git a/Engine/source/gui/controls/guiListBoxCtrl.cpp b/Engine/source/gui/controls/guiListBoxCtrl.cpp index 8c0dabb11..d47914d3d 100644 --- a/Engine/source/gui/controls/guiListBoxCtrl.cpp +++ b/Engine/source/gui/controls/guiListBoxCtrl.cpp @@ -458,7 +458,7 @@ DefineEngineMethod( GuiListBoxCtrl, getSelectedItems, const char*, (),, { UTF8 retFormat[12]; dSprintf( retFormat, 12, "%d ", (*i) ); - dStrcat( retBuffer, retFormat ); + dStrcat( retBuffer, retFormat, 12 ); } return retBuffer; diff --git a/Engine/source/gui/controls/guiPopUpCtrl.cpp b/Engine/source/gui/controls/guiPopUpCtrl.cpp index 33f3c0d30..c1454f206 100644 --- a/Engine/source/gui/controls/guiPopUpCtrl.cpp +++ b/Engine/source/gui/controls/guiPopUpCtrl.cpp @@ -566,13 +566,14 @@ void GuiPopUpMenuCtrl::setBitmap( const char *name ) { char buffer[1024]; char *p; - dStrcpy(buffer, name); + dStrcpy(buffer, name, 1024); p = buffer + dStrlen(buffer); + S32 pLen = 1024 - dStrlen(buffer); - dStrcpy(p, "_n"); + dStrcpy(p, "_n", pLen); mTextureNormal = GFXTexHandle( (StringTableEntry)buffer, &GFXDefaultGUIProfile, avar("%s() - mTextureNormal (line %d)", __FUNCTION__, __LINE__) ); - dStrcpy(p, "_d"); + dStrcpy(p, "_d", pLen); mTextureDepressed = GFXTexHandle( (StringTableEntry)buffer, &GFXDefaultGUIProfile, avar("%s() - mTextureDepressed (line %d)", __FUNCTION__, __LINE__) ); if ( !mTextureDepressed ) mTextureDepressed = mTextureNormal; @@ -637,7 +638,7 @@ void GuiPopUpMenuCtrl::addEntry( const char *buf, S32 id, U32 scheme ) mIdMax = id; Entry e; - dStrcpy( e.buf, buf ); + dStrcpy( e.buf, buf, 256 ); e.id = id; e.scheme = scheme; diff --git a/Engine/source/gui/controls/guiPopUpCtrlEx.cpp b/Engine/source/gui/controls/guiPopUpCtrlEx.cpp index 02f588e1e..dbd5356b5 100644 --- a/Engine/source/gui/controls/guiPopUpCtrlEx.cpp +++ b/Engine/source/gui/controls/guiPopUpCtrlEx.cpp @@ -390,7 +390,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, addScheme, void, (S32 id, ColorI fontCol U32 r, g, b; char buf[64]; - dStrcpy( buf, argv[3] ); + dStrcpy( buf, argv[3], 64 ); char* temp = dStrtok( buf, " \0" ); r = temp ? dAtoi( temp ) : 0; temp = dStrtok( NULL, " \0" ); @@ -399,7 +399,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, addScheme, void, (S32 id, ColorI fontCol b = temp ? dAtoi( temp ) : 0; fontColor.set( r, g, b ); - dStrcpy( buf, argv[4] ); + dStrcpy( buf, argv[4], 64 ); temp = dStrtok( buf, " \0" ); r = temp ? dAtoi( temp ) : 0; temp = dStrtok( NULL, " \0" ); @@ -408,7 +408,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, addScheme, void, (S32 id, ColorI fontCol b = temp ? dAtoi( temp ) : 0; fontColorHL.set( r, g, b ); - dStrcpy( buf, argv[5] ); + dStrcpy( buf, argv[5], 64 ); temp = dStrtok( buf, " \0" ); r = temp ? dAtoi( temp ) : 0; temp = dStrtok( NULL, " \0" ); @@ -426,7 +426,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, addScheme, void, (S32 id, ColorI fontCol // U32 r, g, b; // char buf[64]; // -// dStrcpy( buf, argv[3] ); +// dStrcpy( buf, argv[3], 64 ); // char* temp = dStrtok( buf, " \0" ); // r = temp ? dAtoi( temp ) : 0; // temp = dStrtok( NULL, " \0" ); @@ -435,7 +435,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, addScheme, void, (S32 id, ColorI fontCol // b = temp ? dAtoi( temp ) : 0; // fontColor.set( r, g, b ); // -// dStrcpy( buf, argv[4] ); +// dStrcpy( buf, argv[4], 64 ); // temp = dStrtok( buf, " \0" ); // r = temp ? dAtoi( temp ) : 0; // temp = dStrtok( NULL, " \0" ); @@ -444,7 +444,7 @@ DefineEngineMethod( GuiPopUpMenuCtrlEx, addScheme, void, (S32 id, ColorI fontCol // b = temp ? dAtoi( temp ) : 0; // fontColorHL.set( r, g, b ); // -// dStrcpy( buf, argv[5] ); +// dStrcpy( buf, argv[5], 64 ); // temp = dStrtok( buf, " \0" ); // r = temp ? dAtoi( temp ) : 0; // temp = dStrtok( NULL, " \0" ); @@ -771,13 +771,14 @@ void GuiPopUpMenuCtrlEx::setBitmap(const char *name) { char buffer[1024]; char *p; - dStrcpy(buffer, name); + dStrcpy(buffer, name, 1024); p = buffer + dStrlen(buffer); + S32 pLen = 1024 - dStrlen(buffer); - dStrcpy(p, "_n"); + dStrcpy(p, "_n", pLen); mTextureNormal = GFXTexHandle( (StringTableEntry)buffer, &GFXDefaultGUIProfile, avar("%s() - mTextureNormal (line %d)", __FUNCTION__, __LINE__) ); - dStrcpy(p, "_d"); + dStrcpy(p, "_d", pLen); mTextureDepressed = GFXTexHandle( (StringTableEntry)buffer, &GFXDefaultGUIProfile, avar("%s() - mTextureDepressed (line %d)", __FUNCTION__, __LINE__) ); if ( !mTextureDepressed ) mTextureDepressed = mTextureNormal; @@ -840,7 +841,7 @@ void GuiPopUpMenuCtrlEx::addEntry(const char *buf, S32 id, U32 scheme) mIdMax = id; Entry e; - dStrcpy( e.buf, buf ); + dStrcpy( e.buf, buf, 256 ); e.id = id; e.scheme = scheme; diff --git a/Engine/source/gui/controls/guiTabPageCtrl.cpp b/Engine/source/gui/controls/guiTabPageCtrl.cpp index ada0a2712..c87363cde 100644 --- a/Engine/source/gui/controls/guiTabPageCtrl.cpp +++ b/Engine/source/gui/controls/guiTabPageCtrl.cpp @@ -50,7 +50,7 @@ GuiTabPageCtrl::GuiTabPageCtrl(void) { setExtent(Point2I(100, 200)); mFitBook = false; - dStrcpy(mText,(UTF8*)"TabPage"); + dStrcpy(mText,(UTF8*)"TabPage", MAX_STRING_LENGTH); mActive = true; mIsContainer = true; } diff --git a/Engine/source/gui/controls/guiTreeViewCtrl.cpp b/Engine/source/gui/controls/guiTreeViewCtrl.cpp index 881f76ed4..3e815b1a5 100644 --- a/Engine/source/gui/controls/guiTreeViewCtrl.cpp +++ b/Engine/source/gui/controls/guiTreeViewCtrl.cpp @@ -4750,15 +4750,15 @@ StringTableEntry GuiTreeViewCtrl::getTextToRoot( S32 itemId, const char * delimi dMemset( bufferOne, 0, sizeof(bufferOne) ); dMemset( bufferTwo, 0, sizeof(bufferTwo) ); - dStrcpy( bufferOne, item->getText() ); + dStrcpy( bufferOne, item->getText(), 1024 ); Item *prevNode = item->mParent; while ( prevNode ) { dMemset( bufferNodeText, 0, sizeof(bufferNodeText) ); - dStrcpy( bufferNodeText, prevNode->getText() ); + dStrcpy( bufferNodeText, prevNode->getText(), 128 ); dSprintf( bufferTwo, 1024, "%s%s%s",bufferNodeText, delimiter, bufferOne ); - dStrcpy( bufferOne, bufferTwo ); + dStrcpy( bufferOne, bufferTwo, 1024 ); dMemset( bufferTwo, 0, sizeof(bufferTwo) ); prevNode = prevNode->mParent; } @@ -5566,4 +5566,4 @@ DefineEngineMethod(GuiTreeViewCtrl, getItemAtPosition, S32, (Point2I position), "@return The id of the item under the position.") { return object->getItemAtPosition(position); -} \ No newline at end of file +} diff --git a/Engine/source/gui/core/guiControl.cpp b/Engine/source/gui/core/guiControl.cpp index 968fc9a16..6fded2e92 100644 --- a/Engine/source/gui/core/guiControl.cpp +++ b/Engine/source/gui/core/guiControl.cpp @@ -2570,7 +2570,7 @@ DefineEngineMethod( GuiControl, findHitControls, const char*, ( S32 x, S32 y, S3 return ""; char* buffer = Con::getReturnBuffer( s.size() ); - dStrcpy( buffer, s.c_str() ); + dStrcpy( buffer, s.c_str(), s.size() ); return buffer; } diff --git a/Engine/source/gui/editor/guiDebugger.cpp b/Engine/source/gui/editor/guiDebugger.cpp index b77a909e4..fb888538a 100644 --- a/Engine/source/gui/editor/guiDebugger.cpp +++ b/Engine/source/gui/editor/guiDebugger.cpp @@ -431,7 +431,7 @@ bool DbgFileView::findMouseOverVariable() { S32 stringPosition = pt.x - gFileXOffset; char tempBuf[256], *varNamePtr = &tempBuf[1]; - dStrcpy(tempBuf, mFileView[cell.y].text); + dStrcpy(tempBuf, mFileView[cell.y].text, 256); //find the current mouse over char S32 charNum = findMouseOverChar(mFileView[cell.y].text, stringPosition); @@ -526,7 +526,7 @@ void DbgFileView::onPreRender() { setUpdate(); char oldVar[256]; - dStrcpy(oldVar, mMouseOverVariable); + dStrcpy(oldVar, mMouseOverVariable, 256); bool found = findMouseOverVariable(); if (found && mPCCurrentLine >= 0) { @@ -685,7 +685,7 @@ void DbgFileView::onRenderCell(Point2I offset, Point2I cell, bool selected, bool { S32 startPos, endPos; char tempBuf[256]; - dStrcpy(tempBuf, mFileView[cell.y].text); + dStrcpy(tempBuf, mFileView[cell.y].text, 256); //get the end coord tempBuf[mBlockEnd] = '\0'; diff --git a/Engine/source/gui/editor/guiEditCtrl.cpp b/Engine/source/gui/editor/guiEditCtrl.cpp index f81619efe..2e6371f98 100644 --- a/Engine/source/gui/editor/guiEditCtrl.cpp +++ b/Engine/source/gui/editor/guiEditCtrl.cpp @@ -2625,8 +2625,8 @@ DefineConsoleMethod( GuiEditCtrl, getSelectionGlobalBounds, const char*, (), , " RectI bounds = object->getSelectionGlobalBounds(); String str = String::ToString( "%i %i %i %i", bounds.point.x, bounds.point.y, bounds.extent.x, bounds.extent.y ); - char* buffer = Con::getReturnBuffer( str.length() ); - dStrcpy( buffer, str.c_str() ); + char* buffer = Con::getReturnBuffer( str.size() ); + dStrcpy( buffer, str.c_str(), str.size() ); return buffer; } diff --git a/Engine/source/gui/editor/guiFilterCtrl.cpp b/Engine/source/gui/editor/guiFilterCtrl.cpp index 41dfa13a6..3ac67238a 100644 --- a/Engine/source/gui/editor/guiFilterCtrl.cpp +++ b/Engine/source/gui/editor/guiFilterCtrl.cpp @@ -70,8 +70,8 @@ DefineConsoleMethod( GuiFilterCtrl, getValue, const char*, (), , "Return a tuple for (U32 i=0; i < filter->size(); i++) { char value[32]; - dSprintf(value, 31, "%1.5f ", *(filter->begin()+i) ); - dStrcat(buffer, value); + dSprintf(value, 32, "%1.5f ", *(filter->begin()+i) ); + dStrcat(buffer, value, 32); } return buffer; @@ -239,7 +239,7 @@ void Filter::set(S32 argc, const char *argv[]) if (argc == 1) { // in the form of one string "1.0 1.0 1.0" char list[1024]; - dStrcpy(list, *argv); // strtok modifies the string so we need to copy it + dStrcpy(list, *argv, 1024); // strtok modifies the string so we need to copy it char *value = dStrtok(list, " "); while (value) { diff --git a/Engine/source/gui/utility/messageVector.cpp b/Engine/source/gui/utility/messageVector.cpp index 2ee18387f..19255e38b 100644 --- a/Engine/source/gui/utility/messageVector.cpp +++ b/Engine/source/gui/utility/messageVector.cpp @@ -500,7 +500,7 @@ void MessageVector::insertLine(const U32 position, U32 len = dStrlen(newMessage) + 1; char* copy = new char[len]; - dStrcpy(copy, newMessage); + dStrcpy(copy, newMessage, len); mMessageLines.insert(position); mMessageLines[position].message = copy; diff --git a/Engine/source/gui/worldEditor/terrainEditor.cpp b/Engine/source/gui/worldEditor/terrainEditor.cpp index 59d8adaca..8e81d84e3 100644 --- a/Engine/source/gui/worldEditor/terrainEditor.cpp +++ b/Engine/source/gui/worldEditor/terrainEditor.cpp @@ -2495,8 +2495,8 @@ DefineConsoleMethod(TerrainEditor, getTerrainBlocksMaterialList, const char *, ( ret[0] = 0; for(U32 i = 0; i < list.size(); ++i) { - dStrcat( ret, list[i] ); - dStrcat( ret, "\n" ); + dStrcat( ret, list[i], size ); + dStrcat( ret, "\n", size ); } return ret; @@ -2709,8 +2709,8 @@ DefineConsoleMethod(TerrainEditor, getMaterials, const char *, (), , "() gets th ret[0] = 0; for(U32 i = 0; i < terr->getMaterialCount(); i++) { - dStrcat( ret, terr->getMaterialName(i) ); - dStrcat( ret, "\n" ); + dStrcat( ret, terr->getMaterialName(i), 4096 ); + dStrcat( ret, "\n", 4096 ); } return ret; diff --git a/Engine/source/gui/worldEditor/worldEditor.cpp b/Engine/source/gui/worldEditor/worldEditor.cpp index 0a5b6f47b..651ef4ded 100644 --- a/Engine/source/gui/worldEditor/worldEditor.cpp +++ b/Engine/source/gui/worldEditor/worldEditor.cpp @@ -3927,15 +3927,38 @@ void WorldEditor::makeSelectionAMesh(const char *filename) OptimizedPolyList polyList; polyList.setBaseTransform(orientation); + ColladaUtils::ExportData exportData; + for (S32 i = 0; i < objectList.size(); i++) { SceneObject *pObj = objectList[i]; - if (!pObj->buildPolyList(PLC_Export, &polyList, pObj->getWorldBox(), pObj->getWorldSphere())) + if (!pObj->buildExportPolyList(&exportData, pObj->getWorldBox(), pObj->getWorldSphere())) Con::warnf("colladaExportObjectList() - object %i returned no geometry.", pObj->getId()); } + //Now that we have all of our mesh data, process it so we can correctly collapse everything. + exportData.processData(); + + //recenter generated visual mesh results + for (U32 dl = 0; dl < exportData.colMeshes.size(); dl++) + { + for (U32 pnt = 0; pnt < exportData.colMeshes[dl].mesh.mPoints.size(); pnt++) + { + exportData.colMeshes[dl].mesh.mPoints[pnt] -= centroid; + } + } + + //recenter generated collision mesh results + for (U32 dl = 0; dl < exportData.detailLevels.size(); dl++) + { + for (U32 pnt = 0; pnt < exportData.detailLevels[dl].mesh.mPoints.size(); pnt++) + { + exportData.detailLevels[dl].mesh.mPoints[pnt] -= centroid; + } + } + // Use a ColladaUtils function to do the actual export to a Collada file - ColladaUtils::exportToCollada(filename, polyList); + ColladaUtils::exportToCollada(filename, exportData); // // Allocate TSStatic object and add to level. diff --git a/Engine/source/i18n/lang.cpp b/Engine/source/i18n/lang.cpp index 24f2e2d59..7e1efe4a5 100644 --- a/Engine/source/i18n/lang.cpp +++ b/Engine/source/i18n/lang.cpp @@ -42,8 +42,9 @@ LangFile::LangFile(const UTF8 *langName /* = NULL */) if(langName) { - mLangName = new UTF8 [dStrlen(langName) + 1]; - dStrcpy(mLangName, langName); + dsize_t langNameLen = dStrlen(langName) + 1; + mLangName = new UTF8 [langNameLen]; + dStrcpy(mLangName, langName, langNameLen); } else mLangName = NULL; @@ -136,8 +137,9 @@ const UTF8 * LangFile::getString(U32 id) U32 LangFile::addString(const UTF8 *str) { - UTF8 *newstr = new UTF8 [dStrlen(str) + 1]; - dStrcpy(newstr, str); + dsize_t newstrLen = dStrlen(str) + 1; + UTF8 *newstr = new UTF8 [newstrLen]; + dStrcpy(newstr, str, newstrLen); mStringTable.push_back(newstr); return mStringTable.size() - 1; } @@ -156,8 +158,9 @@ void LangFile::setString(U32 id, const UTF8 *str) SAFE_DELETE_ARRAY(mStringTable[id]); - UTF8 *newstr = new UTF8 [dStrlen(str) + 1]; - dStrcpy(newstr, str); + dsize_t newstrLen = dStrlen(str) + 1; + UTF8 *newstr = new UTF8 [newstrLen]; + dStrcpy(newstr, str, newstrLen); mStringTable[id] = newstr; } @@ -166,8 +169,9 @@ void LangFile::setLangName(const UTF8 *newName) if(mLangName) delete [] mLangName; - mLangName = new UTF8 [dStrlen(newName) + 1]; - dStrcpy(mLangName, newName); + dsize_t langNameLen = dStrlen(newName) + 1; + mLangName = new UTF8 [langNameLen]; + dStrcpy(mLangName, newName, langNameLen); } void LangFile::setLangFile(const UTF8 *langFile) @@ -175,8 +179,9 @@ void LangFile::setLangFile(const UTF8 *langFile) if(mLangFile) delete [] mLangFile; - mLangFile = new UTF8 [dStrlen(langFile) + 1]; - dStrcpy(mLangFile, langFile); + dsize_t langFileLen = dStrlen(langFile) + 1; + mLangFile = new UTF8 [langFileLen]; + dStrcpy(mLangFile, langFile, langFileLen); } bool LangFile::activateLanguage() @@ -349,8 +354,9 @@ DefineConsoleMethod(LangTable, getString, const char *, (U32 id), , const char * str = (const char*)object->getString(id); if(str != NULL) { - char * ret = Con::getReturnBuffer(dStrlen(str) + 1); - dStrcpy(ret, str); + dsize_t retLen = dStrlen(str) + 1; + char * ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, str, retLen); return ret; } @@ -387,8 +393,9 @@ DefineConsoleMethod(LangTable, getLangName, const char *, (S32 langId), , "(int const char * str = (const char*)object->getLangName(langId); if(str != NULL) { - char * ret = Con::getReturnBuffer(dStrlen(str) + 1); - dStrcpy(ret, str); + dsize_t retLen = dStrlen(str) + 1; + char * ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, str, retLen); return ret; } @@ -414,7 +421,7 @@ UTF8 *sanitiseVarName(const UTF8 *varName, UTF8 *buffer, U32 bufsize) return NULL; } - dStrcpy(buffer, (const UTF8*)"I18N::"); + dStrcpy(buffer, (const UTF8*)"I18N::", bufsize); UTF8 *dptr = buffer + 6; const UTF8 *sptr = varName; @@ -575,4 +582,4 @@ ConsoleFunction(CompileLanguage, void, 2, 3, "(string inputFile, [bool createMap delete mapStream; } } -//end lang_ localization \ No newline at end of file +//end lang_ localization diff --git a/Engine/source/main/main.cpp b/Engine/source/main/main.cpp index f74430fc1..ad3556913 100644 --- a/Engine/source/main/main.cpp +++ b/Engine/source/main/main.cpp @@ -283,6 +283,16 @@ int main(int argc, const char **argv) #include "app/mainLoop.h" #include "T3D/gameFunctions.h" +#if defined(WIN32) || defined(_WIN32) +//tell switchable graphics supported systems that they need to use the beefier GPU +#include +extern "C" { __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; } +extern "C" { __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; } +#else +extern "C" { int NvOptimusEnablement = 1; } +extern "C" { int AmdPowerXpressRequestHighPerformance = 1; } +#endif + // Entry point for your game. // // This is build by default using the "StandardMainLoop" toolkit. Feel free diff --git a/Engine/source/materials/materialDefinition.cpp b/Engine/source/materials/materialDefinition.cpp index d4ec8ed7d..3ef1b1d01 100644 --- a/Engine/source/materials/materialDefinition.cpp +++ b/Engine/source/materials/materialDefinition.cpp @@ -654,35 +654,35 @@ DefineConsoleMethod( Material, getAnimFlags, const char*, (U32 id), , "" ) if(object->mAnimFlags[ id ] & Material::Scroll) { if(dStrcmp( animFlags, "" ) == 0) - dStrcpy( animFlags, "$Scroll" ); + dStrcpy( animFlags, "$Scroll", 512 ); } if(object->mAnimFlags[ id ] & Material::Rotate) { if(dStrcmp( animFlags, "" ) == 0) - dStrcpy( animFlags, "$Rotate" ); + dStrcpy( animFlags, "$Rotate", 512 ); else - dStrcat( animFlags, " | $Rotate"); + dStrcat( animFlags, " | $Rotate", 512); } if(object->mAnimFlags[ id ] & Material::Wave) { if(dStrcmp( animFlags, "" ) == 0) - dStrcpy( animFlags, "$Wave" ); + dStrcpy( animFlags, "$Wave", 512 ); else - dStrcat( animFlags, " | $Wave"); + dStrcat( animFlags, " | $Wave", 512); } if(object->mAnimFlags[ id ] & Material::Scale) { if(dStrcmp( animFlags, "" ) == 0) - dStrcpy( animFlags, "$Scale" ); + dStrcpy( animFlags, "$Scale", 512 ); else - dStrcat( animFlags, " | $Scale"); + dStrcat( animFlags, " | $Scale", 512); } if(object->mAnimFlags[ id ] & Material::Sequence) { if(dStrcmp( animFlags, "" ) == 0) - dStrcpy( animFlags, "$Sequence" ); + dStrcpy( animFlags, "$Sequence", 512 ); else - dStrcat( animFlags, " | $Sequence"); + dStrcat( animFlags, " | $Sequence", 512); } return animFlags; @@ -718,4 +718,4 @@ bool Material::_setAccuEnabled( void *object, const char *index, const char *dat AccumulationVolume::refreshVolumes(); } return true; -} \ No newline at end of file +} diff --git a/Engine/source/module/moduleDefinition.h b/Engine/source/module/moduleDefinition.h index 42deff44d..8652876cf 100644 --- a/Engine/source/module/moduleDefinition.h +++ b/Engine/source/module/moduleDefinition.h @@ -254,11 +254,11 @@ protected: for ( U32 dependencyIndex = 0; dependencyIndex < dependencyWordCount; ++dependencyIndex ) { // Fetch slot. - dStrcpy( slotUnit, StringUnit::getUnit( pDependencyValue, dependencyIndex, "," ) ); + dStrcpy( slotUnit, StringUnit::getUnit( pDependencyValue, dependencyIndex, "," ), 256 ); // Fetch slot name and value. - dStrcpy( slotName, StringUnit::getUnit( slotUnit, 0, "=" ) ); - dStrcpy( slotValue, StringUnit::getUnit( slotUnit, 1, "=" ) ); + dStrcpy( slotName, StringUnit::getUnit( slotUnit, 0, "=" ), 256 ); + dStrcpy( slotValue, StringUnit::getUnit( slotUnit, 1, "=" ), 256 ); // Fetch module Id. StringTableEntry moduleId = StringTable->insert( slotName ); diff --git a/Engine/source/module/moduleManager.cpp b/Engine/source/module/moduleManager.cpp index fa53728b7..ec45ad918 100644 --- a/Engine/source/module/moduleManager.cpp +++ b/Engine/source/module/moduleManager.cpp @@ -74,7 +74,7 @@ ModuleManager::ModuleManager() : mIgnoreLoadedGroups(false) { // Set module extension. - dStrcpy( mModuleExtension, MODULE_MANAGER_MODULE_DEFINITION_EXTENSION ); + dStrcpy( mModuleExtension, MODULE_MANAGER_MODULE_DEFINITION_EXTENSION, 256 ); } //----------------------------------------------------------------------------- @@ -155,7 +155,7 @@ bool ModuleManager::setModuleExtension( const char* pExtension ) } // Set module extension. - dStrcpy( mModuleExtension, pExtension ); + dStrcpy( mModuleExtension, pExtension, 256 ); return true; } diff --git a/Engine/source/persistence/taml/fsTinyXml.cpp b/Engine/source/persistence/taml/fsTinyXml.cpp index 8afe7f16c..ffc069613 100644 --- a/Engine/source/persistence/taml/fsTinyXml.cpp +++ b/Engine/source/persistence/taml/fsTinyXml.cpp @@ -33,7 +33,7 @@ bool fsTiXmlDocument::LoadFile( const char * pFilename, TiXmlEncoding encoding ) #ifdef TORQUE_OS_ANDROID if (strlen(pFilename) > strlen(filenameBuffer)) { - strcpy(filenameBuffer, pFilename); + dStrcpy(filenameBuffer, pFilename, 1024); } #endif diff --git a/Engine/source/persistence/taml/taml.cpp b/Engine/source/persistence/taml/taml.cpp index b9144e8ed..82369a7c0 100644 --- a/Engine/source/persistence/taml/taml.cpp +++ b/Engine/source/persistence/taml/taml.cpp @@ -708,7 +708,7 @@ ImplementEnumType(_TamlFormatMode, U32 nBufferSize = dStrlen(pFieldValue) + 1; FrameTemp valueCopy(nBufferSize); - dStrcpy((char *)valueCopy, pFieldValue); + dStrcpy((char *)valueCopy, pFieldValue, nBufferSize); // Skip if field should not be written. if (!pSimObject->writeField(fieldName, valueCopy)) @@ -1547,4 +1547,4 @@ ImplementEnumType(_TamlFormatMode, TiXmlElement* pAnyElement = new TiXmlElement("xs:any"); pAnyElement->SetAttribute("processContents", "skip"); pSequenceElement->LinkEndChild(pAnyElement); - } \ No newline at end of file + } diff --git a/Engine/source/persistence/taml/tamlCustom.cpp b/Engine/source/persistence/taml/tamlCustom.cpp index 83c063a61..e45984dd4 100644 --- a/Engine/source/persistence/taml/tamlCustom.cpp +++ b/Engine/source/persistence/taml/tamlCustom.cpp @@ -53,7 +53,7 @@ void TamlCustomField::set( const char* pFieldName, const char* pFieldValue ) } #endif // Copy field value. - dStrcpy( mFieldValue, pFieldValue ); + dStrcpy( mFieldValue, pFieldValue, MAX_TAML_NODE_FIELDVALUE_LENGTH ); } //----------------------------------------------------------------------------- diff --git a/Engine/source/persistence/taml/tamlCustom.h b/Engine/source/persistence/taml/tamlCustom.h index 261c77dde..2f3ba857e 100644 --- a/Engine/source/persistence/taml/tamlCustom.h +++ b/Engine/source/persistence/taml/tamlCustom.h @@ -334,7 +334,7 @@ public: // Sanity! AssertFatal( fieldNameLength < sizeof(fieldNameBuffer), "TamlCustomField: Field name is too long." ); - dStrcpy( fieldNameBuffer, mFieldName ); + dStrcpy( fieldNameBuffer, mFieldName, 1024 ); fieldNameBuffer[fieldNameLength-1] = 0; StringTableEntry fieldName = StringTable->insert( fieldNameBuffer ); @@ -782,4 +782,4 @@ private: TamlCustomNodeVector mNodes; }; -#endif // _TAML_CUSTOM_H_ \ No newline at end of file +#endif // _TAML_CUSTOM_H_ diff --git a/Engine/source/persistence/taml/tamlWriteNode.h b/Engine/source/persistence/taml/tamlWriteNode.h index 5ec722045..b406a54d8 100644 --- a/Engine/source/persistence/taml/tamlWriteNode.h +++ b/Engine/source/persistence/taml/tamlWriteNode.h @@ -53,8 +53,9 @@ public: mName = name; // Allocate and copy the value. - mpValue = new char[ dStrlen(pValue)+1 ]; - dStrcpy( (char *)mpValue, pValue ); + dsize_t valueLen = dStrlen(pValue) + 1; + mpValue = new char[ valueLen ]; + dStrcpy( (char *)mpValue, pValue, valueLen ); } @@ -113,4 +114,4 @@ public: TamlCustomNodes mCustomNodes; }; -#endif // _TAML_WRITE_NODE_H_ \ No newline at end of file +#endif // _TAML_WRITE_NODE_H_ diff --git a/Engine/source/persistence/taml/xml/tamlXmlParser.cpp b/Engine/source/persistence/taml/xml/tamlXmlParser.cpp index b479fa07e..6ba33dd98 100644 --- a/Engine/source/persistence/taml/xml/tamlXmlParser.cpp +++ b/Engine/source/persistence/taml/xml/tamlXmlParser.cpp @@ -53,7 +53,7 @@ bool TamlXmlParser::accept( const char* pFilename, TamlVisitor& visitor ) #ifdef TORQUE_OS_ANDROID if (strlen(pFilename) > strlen(filenameBuffer)) { - strcpy(filenameBuffer, pFilename); + dStrcpy(filenameBuffer, pFilename, 1024); } #endif diff --git a/Engine/source/platform/input/leapMotion/leapMotionDevice.cpp b/Engine/source/platform/input/leapMotion/leapMotionDevice.cpp index 5e4aef681..9bbb3eaaf 100644 --- a/Engine/source/platform/input/leapMotion/leapMotionDevice.cpp +++ b/Engine/source/platform/input/leapMotion/leapMotionDevice.cpp @@ -82,7 +82,7 @@ U32 LeapMotionDevice::LM_FRAME = 0; LeapMotionDevice::LeapMotionDevice() { // From IInputDevice - dStrcpy(mName, "leapmotion"); + dStrcpy(mName, "leapmotion", 30); mDeviceType = INPUTMGR->getNextDeviceType(); mController = NULL; diff --git a/Engine/source/platform/input/oculusVR/oculusVRDevice.cpp b/Engine/source/platform/input/oculusVR/oculusVRDevice.cpp index 229bc0429..e2ffb411a 100644 --- a/Engine/source/platform/input/oculusVR/oculusVRDevice.cpp +++ b/Engine/source/platform/input/oculusVR/oculusVRDevice.cpp @@ -86,7 +86,7 @@ F32 OculusVRDevice::smPositionTrackingScale = 1.0f; OculusVRDevice::OculusVRDevice() { // From IInputDevice - dStrcpy(mName, "oculusvr"); + dStrcpy(mName, "oculusvr", 30); mDeviceType = INPUTMGR->getNextDeviceType(); // diff --git a/Engine/source/platform/input/openVR/openVRProvider.cpp b/Engine/source/platform/input/openVR/openVRProvider.cpp index 9fa31e4cc..53cc228f5 100644 --- a/Engine/source/platform/input/openVR/openVRProvider.cpp +++ b/Engine/source/platform/input/openVR/openVRProvider.cpp @@ -493,7 +493,7 @@ OpenVRProvider::OpenVRProvider() : mDrawCanvas(NULL), mGameConnection(NULL) { - dStrcpy(mName, "openvr"); + dStrcpy(mName, "openvr", 30); mDeviceType = INPUTMGR->getNextDeviceType(); buildInputCodeTable(); GFXDevice::getDeviceEventSignal().notify(this, &OpenVRProvider::_handleDeviceEvent); diff --git a/Engine/source/platform/input/razerHydra/razerHydraDevice.cpp b/Engine/source/platform/input/razerHydra/razerHydraDevice.cpp index 8a36bd9d6..e2d87129d 100644 --- a/Engine/source/platform/input/razerHydra/razerHydraDevice.cpp +++ b/Engine/source/platform/input/razerHydra/razerHydraDevice.cpp @@ -91,7 +91,7 @@ U32 RazerHydraDevice::RH_FRAME = 0; RazerHydraDevice::RazerHydraDevice() { // From IInputDevice - dStrcpy(mName, "razerhydra"); + dStrcpy(mName, "razerhydra", 30); mDeviceType = INPUTMGR->getNextDeviceType(); // diff --git a/Engine/source/platform/nativeDialogs/fileDialog.cpp b/Engine/source/platform/nativeDialogs/fileDialog.cpp index ad8bdfafb..21bdfefa3 100644 --- a/Engine/source/platform/nativeDialogs/fileDialog.cpp +++ b/Engine/source/platform/nativeDialogs/fileDialog.cpp @@ -433,7 +433,7 @@ bool FileDialog::setDefaultPath(void *object, const char *index, const char *dat // Copy and Backslash the path (Windows dialogs are VERY picky about this format) static char szPathValidate[512]; - dStrcpy(szPathValidate, data); + dStrcpy(szPathValidate, data, 512); Platform::makeFullPathName(data, szPathValidate, sizeof(szPathValidate)); //backslash( szPathValidate ); diff --git a/Engine/source/platform/platformCPUCount.cpp b/Engine/source/platform/platformCPUCount.cpp index fc066f75d..a3fe99d67 100644 --- a/Engine/source/platform/platformCPUCount.cpp +++ b/Engine/source/platform/platformCPUCount.cpp @@ -523,7 +523,7 @@ next: tblPkgID[j] = apicID & PackageIDMask; sprintf(tmp," AffinityMask = %d; Initial APIC = %d; Physical ID = %d, Core ID = %d, SMT ID = %d\n", dwAffinityMask, apicID, tblPkgID[j], tblCoreID[j], tblSMTID[j]); - strcat(g_s3Levels, tmp); + dStrcat(g_s3Levels, tmp, 2048); numLPEnabled ++; // Number of available logical processors in the system. @@ -654,4 +654,4 @@ next: } // namespace CPUInfo #endif -#endif \ No newline at end of file +#endif diff --git a/Engine/source/platform/platformFileIO.cpp b/Engine/source/platform/platformFileIO.cpp index 15fd9ad6d..a9ace740b 100644 --- a/Engine/source/platform/platformFileIO.cpp +++ b/Engine/source/platform/platformFileIO.cpp @@ -534,7 +534,7 @@ StringTableEntry Platform::makeRelativePathName(const char *path, const char *to // Copy the rest if(*branch) - dStrcpy(bufPtr, branch + 1); + dStrcpy(bufPtr, branch + 1, temp.size - (bufPtr - temp.ptr)); else *--bufPtr = 0; diff --git a/Engine/source/platform/platformMemory.cpp b/Engine/source/platform/platformMemory.cpp index d295a45e4..5f7aa926d 100644 --- a/Engine/source/platform/platformMemory.cpp +++ b/Engine/source/platform/platformMemory.cpp @@ -1130,7 +1130,7 @@ static void logFree(const AllocatedHeader* hdr) void enableLogging(const char* fileName) { - dStrcpy(gLogFilename, fileName); + dStrcpy(gLogFilename, fileName, 256); if (!gEnableLogging) { gEnableLogging = true; diff --git a/Engine/source/platform/platformNet.cpp b/Engine/source/platform/platformNet.cpp index 6c6d3b234..2a22499c4 100644 --- a/Engine/source/platform/platformNet.cpp +++ b/Engine/source/platform/platformNet.cpp @@ -280,7 +280,7 @@ namespace PlatformNetState if (addressString[0] == '[') { // Must be ipv6 notation - dStrcpy(outAddress, addressString+1); + dStrcpy(outAddress, addressString+1, 256); addressString = outAddress; portString = dStrchr(outAddress, ']'); @@ -305,7 +305,7 @@ namespace PlatformNetState } else { - dStrcpy(outAddress, addressString); + dStrcpy(outAddress, addressString, 256); addressString = outAddress; // Check to see if we have multiple ":" which would indicate this is an ipv6 address @@ -546,7 +546,7 @@ static PolledSocket* addPolledSocket(NetSocket handleFd, SOCKET fd, S32 state, sock->handleFd = handleFd; sock->state = state; if (remoteAddr) - dStrcpy(sock->remoteAddr, remoteAddr); + dStrcpy(sock->remoteAddr, remoteAddr, 256); if (port != -1) sock->remotePort = port; gPolledSockets.push_back(sock); diff --git a/Engine/source/platform/platformRedBook.cpp b/Engine/source/platform/platformRedBook.cpp index d95a0eb92..82b1bae2d 100644 --- a/Engine/source/platform/platformRedBook.cpp +++ b/Engine/source/platform/platformRedBook.cpp @@ -94,7 +94,7 @@ void RedBook::setLastError(const char * error) if(!error || dStrlen(error) >= sizeof(smLastError)) setLastError("Invalid error string passed"); else - dStrcpy(smLastError, error); + dStrcpy(smLastError, error, 1024); } const char * RedBook::getLastError() diff --git a/Engine/source/platform/profiler.cpp b/Engine/source/platform/profiler.cpp index 444679284..d623443ab 100644 --- a/Engine/source/platform/profiler.cpp +++ b/Engine/source/platform/profiler.cpp @@ -328,9 +328,9 @@ const char * Profiler::constructProfilePath(ProfilerData * pd) U32 mark = FrameAllocator::getWaterMark(); char * buf = (char*)FrameAllocator::alloc(len+1); - dStrcpy(buf,pd->mParent->mPath); - dStrcat(buf,connector); - dStrcat(buf,pd->mRoot->mName); + dStrcpy(buf,pd->mParent->mPath,len+1); + dStrcat(buf,connector,len+1); + dStrcat(buf,pd->mRoot->mName,len+1); const char * ret = StringTable->insert(buf); FrameAllocator::setWaterMark(mark); @@ -433,7 +433,7 @@ void Profiler::dumpToFile(const char* fileName) AssertFatal(dStrlen(fileName) < DumpFileNameLength, "Error, dump filename too long"); mDumpToFile = true; mDumpToConsole = false; - dStrcpy(mDumpFileName, fileName); + dStrcpy(mDumpFileName, fileName, DumpFileNameLength); } void Profiler::hashPop(ProfilerRootData *expected) @@ -645,11 +645,11 @@ void Profiler::dump() AssertFatal(success, "Cannot write profile dump to specified file!"); char buffer[1024]; - dStrcpy(buffer, "Profiler Data Dump:\n"); + dStrcpy(buffer, "Profiler Data Dump:\n", 1024); fws.write(dStrlen(buffer), buffer); - dStrcpy(buffer, "Ordered by non-sub total time -\n"); + dStrcpy(buffer, "Ordered by non-sub total time -\n", 1024); fws.write(dStrlen(buffer), buffer); - dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n"); + dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n", 1024); fws.write(dStrlen(buffer), buffer); for(U32 i = 0; i < rootVector.size(); i++) @@ -665,9 +665,9 @@ void Profiler::dump() rootVector[i]->mTotalTime = 0; rootVector[i]->mSubTime = 0; } - dStrcpy(buffer, "\nOrdered by non-sub total time -\n"); + dStrcpy(buffer, "\nOrdered by non-sub total time -\n", 1024); fws.write(dStrlen(buffer), buffer); - dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n"); + dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n", 1024); fws.write(dStrlen(buffer), buffer); mCurrentProfilerData->mTotalTime = endHighResolutionTimer(mCurrentProfilerData->mStartTime); diff --git a/Engine/source/platform/types.mac.h b/Engine/source/platform/types.mac.h index e700afac0..fb31d5ea7 100644 --- a/Engine/source/platform/types.mac.h +++ b/Engine/source/platform/types.mac.h @@ -27,10 +27,11 @@ #define FN_CDECL #define STDCALL +#include // size_t is needed to overload new // size_t tends to be OS and compiler specific and may need to // be if/def'ed in the future -typedef unsigned long dsize_t; +typedef size_t dsize_t; /** Platform dependent file date-time structure. The defination of this structure diff --git a/Engine/source/platformMac/macFileIO.mm b/Engine/source/platformMac/macFileIO.mm index f11b5b052..767dbca8e 100644 --- a/Engine/source/platformMac/macFileIO.mm +++ b/Engine/source/platformMac/macFileIO.mm @@ -894,7 +894,7 @@ static bool recurseDumpDirectories(const char *basePath, const char *subPath, Ve { char child[1024]; if ( (basePath[dStrlen(basePath) - 1]) == '/') - dStrcpy (child, d->d_name); + dStrcpy (child, d->d_name, 1024); else dSprintf(child, 1024, "/%s", d->d_name); if (currentDepth < recurseDepth || recurseDepth == -1) diff --git a/Engine/source/platformMac/macString.mm b/Engine/source/platformMac/macString.mm deleted file mode 100644 index 3a255d924..000000000 --- a/Engine/source/platformMac/macString.mm +++ /dev/null @@ -1,69 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- - -#import "platform/platform.h" -#import -#import -#import -#import -#import -#import "core/strings/stringFunctions.h" - -char *dStrnew(const char *src) -{ - char *buffer = new char[dStrlen(src) + 1]; - dStrcpy(buffer, src); - return buffer; -} - -char* dStrstr(char *str1, char *str2) -{ - return strstr(str1,str2); -} - -int dSprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, ...) -{ - va_list args; - va_start(args, format); - S32 len = vsprintf(buffer, format, args); - va_end(args); - return (len); -} - - -int dVsprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, va_list arglist) -{ - S32 len = vsprintf(buffer, format, arglist); - - return (len); -} - -int dFflushStdout() -{ - return fflush(stdout); -} - -int dFflushStderr() -{ - return fflush(stderr); -} - diff --git a/Engine/source/platformPOSIX/posixVolume.cpp b/Engine/source/platformPOSIX/posixVolume.cpp index 0f39bea3c..271df1e18 100644 --- a/Engine/source/platformPOSIX/posixVolume.cpp +++ b/Engine/source/platformPOSIX/posixVolume.cpp @@ -585,7 +585,7 @@ bool Platform::FS::InstallFileSystems() { // add trailing '/' if it isn't there if (buffer[dStrlen(buffer) - 1] != '/') - dStrcat(buffer, "/"); + dStrcat(buffer, "/", PATH_MAX); Platform::FS::SetCwd(buffer); } diff --git a/Engine/source/platformWin32/minidump/winMiniDump.cpp b/Engine/source/platformWin32/minidump/winMiniDump.cpp index fbe2b96f6..267b6fc3f 100644 --- a/Engine/source/platformWin32/minidump/winMiniDump.cpp +++ b/Engine/source/platformWin32/minidump/winMiniDump.cpp @@ -144,7 +144,7 @@ INT CreateMiniDump( LPEXCEPTION_POINTERS ExceptionInfo) //copy over the pdb file char pdbName[1024]; - dStrcpy(pdbName, exeName); + dStrcpy(pdbName, exeName, 1024); dStrncat(pdbName, ".pdb", 4); dSprintf(fromFile, 2048, "%s/%s", Platform::getCurrentDirectory(), pdbName ); dSprintf(fileName, 2048, "%s/%s", crashPath, pdbName ); diff --git a/Engine/source/platformWin32/nativeDialogs/fileDialog.cpp b/Engine/source/platformWin32/nativeDialogs/fileDialog.cpp index 1d64139ee..e73bbe65b 100644 --- a/Engine/source/platformWin32/nativeDialogs/fileDialog.cpp +++ b/Engine/source/platformWin32/nativeDialogs/fileDialog.cpp @@ -142,7 +142,7 @@ static UINT_PTR CALLBACK FolderHookProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPA #ifdef UNICODE convertUTF16toUTF8(buf, filePath); #else - dStrcpy( filePath, buf ); + dStrcpy( filePath, buf, MAX_PATH ); #endif // [tom, 12/8/2006] Hack to remove files from the list because @@ -333,8 +333,8 @@ bool FileDialog::Execute() char pszFile[MAX_PATH]; char pszFilter[1024]; char pszFileTitle[MAX_PATH]; - dStrcpy( pszFile, mData.mDefaultFile ); - dStrcpy( pszFilter, mData.mFilters ); + dStrcpy( pszFile, mData.mDefaultFile, MAX_PATH ); + dStrcpy( pszFilter, mData.mFilters, 1024 ); const char* pszInitialDir = mData.mDefaultPath; const char* pszTitle = mData.mTitle; @@ -447,7 +447,7 @@ bool FileDialog::Execute() convertUTF16toUTF8DoubleNULL( (UTF16*)pszFile, (UTF8*)pszResult, sizeof(pszResult)); #else if(pszFileTitle[0] || ! ( mData.mStyle & FileDialogData::FDS_OPEN && mData.mStyle & FileDialogData::FDS_MULTIPLEFILES )) - dStrcpy(pszResult,pszFile); + dStrcpy(pszResult,pszFile,MAX_PATH); else { // [tom, 1/4/2007] pszResult is a double-NULL terminated, NULL separated list in this case so we can't just dSstrcpy() @@ -614,7 +614,7 @@ bool FileDialog::setDefaultPath( void *object, const char *index, const char *da // Copy and Backslash the path (Windows dialogs are VERY picky about this format) static char szPathValidate[512]; - dStrcpy( szPathValidate, data ); + dStrcpy( szPathValidate, data, 512 ); Platform::makeFullPathName( data,szPathValidate, sizeof(szPathValidate)); backslash( szPathValidate ); diff --git a/Engine/source/platformWin32/winDInputDevice.cpp b/Engine/source/platformWin32/winDInputDevice.cpp index a88f9ff1d..9ce308090 100644 --- a/Engine/source/platformWin32/winDInputDevice.cpp +++ b/Engine/source/platformWin32/winDInputDevice.cpp @@ -1552,31 +1552,32 @@ const char* DInputDevice::getJoystickAxesString() switch ( mObjInfo[i].mInst ) { case SI_XAXIS: - dStrcat( buf, "\tX" ); + dStrcat( buf, "\tX", 64 ); break; case SI_YAXIS: - dStrcat( buf, "\tY" ); + dStrcat( buf, "\tY", 64 ); break; case SI_ZAXIS: - dStrcat( buf, "\tZ" ); + dStrcat( buf, "\tZ", 64 ); break; case SI_RXAXIS: - dStrcat( buf, "\tR" ); + dStrcat( buf, "\tR", 64 ); break; case SI_RYAXIS: - dStrcat( buf, "\tU" ); + dStrcat( buf, "\tU", 64 ); break; case SI_RZAXIS: - dStrcat( buf, "\tV" ); + dStrcat( buf, "\tV", 64 ); break; case SI_SLIDER: - dStrcat( buf, "\tS" ); + dStrcat( buf, "\tS", 64 ); break; } } - char* returnString = Con::getReturnBuffer( dStrlen( buf ) + 1 ); - dStrcpy( returnString, buf ); + dsize_t returnLen = dStrlen(buf) + 1; + char* returnString = Con::getReturnBuffer(returnLen); + dStrcpy( returnString, buf, returnLen ); return( returnString ); } diff --git a/Engine/source/platformWin32/winFileio.cpp b/Engine/source/platformWin32/winFileio.cpp index 85f8676a3..3e1974ae4 100644 --- a/Engine/source/platformWin32/winFileio.cpp +++ b/Engine/source/platformWin32/winFileio.cpp @@ -56,7 +56,7 @@ bool dFileDelete(const char * name) #ifdef UNICODE convertUTF8toUTF16N( name, buf, buf.size ); #else - dStrcpy( buf, name ); + dStrcpy( buf, name, buf.size ); #endif backslash( buf ); @@ -88,8 +88,8 @@ bool dFileRename(const char *oldName, const char *newName) convertUTF8toUTF16N( oldName, oldf, oldf.size ); convertUTF8toUTF16N( newName, newf, newf.size ); #else - dStrcpy(oldf, oldName); - dStrcpy(newf, newName); + dStrcpy(oldf, oldName, oldf.size); + dStrcpy(newf, newName, newf.size); #endif backslash(oldf); backslash(newf); @@ -106,7 +106,7 @@ bool dFileTouch(const char * name) #ifdef UNICODE convertUTF8toUTF16N( name, buf, buf.size ); #else - dStrcpy( buf, name ); + dStrcpy( buf, name, buf.size ); #endif backslash( buf ); @@ -133,8 +133,8 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) convertUTF8toUTF16N( fromName, from, from.size ); convertUTF8toUTF16N( toName, to, to.size ); #else - dStrcpy( from, fromName ); - dStrcpy( to, toName ); + dStrcpy( from, fromName, from.size ); + dStrcpy( to, toName, to.size ); #endif backslash( from ); @@ -168,7 +168,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) char* toDir = tempBuf; Platform::makeFullPathName(fromDir + dStrlen(fromName) + (dStricmp(fromDir, fromName) ? 1 : 0), tempBuf, tempBuf.size, toName); if(*(toDir + dStrlen(toDir) - 1) != '/') - dStrcat(toDir, "/"); + dStrcat(toDir, "/", tempBuf.size); forwardslash(toDir); if (!Platform::createPath(toDir)) @@ -191,8 +191,8 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) char* toFile = tempBuf; Platform::makeFullPathName(fileInfo[i].pFullPath + dStrlen(fromName) + (dStricmp(fileInfo[i].pFullPath, fromName) ? 1 : 0), tempBuf, tempBuf.size, toName); - dStrcat(toFile, "/"); - dStrcat(toFile, fileInfo[i].pFileName); + dStrcat(toFile, "/", tempBuf.size); + dStrcat(toFile, fileInfo[i].pFileName, tempBuf.size); backslash(fromFile); backslash(toFile); @@ -269,7 +269,7 @@ File::FileStatus File::open(const char *filename, const AccessMode openMode) #ifdef UNICODE convertUTF8toUTF16N( filename, fname, fname.size ); #else - dStrcpy(fname, filename); + dStrcpy(fname, filename, fname.size); #endif backslash( fname ); @@ -678,7 +678,7 @@ bool Platform::getFileTimes(const char *filePath, FileTime *createTime, FileTime #ifdef UNICODE convertUTF8toUTF16N( filePath, fp, fp.size ); #else - dStrcpy( fp, filePath ); + dStrcpy( fp, filePath, fp.size ); #endif backslash( fp ); @@ -833,7 +833,7 @@ bool Platform::setCurrentDirectory(StringTableEntry newDir) #ifdef UNICODE convertUTF8toUTF16N( newDir, buf, buf.size - 1 ); #else - dStrcpy( buf, newDir ); + dStrcpy( buf, newDir, buf.size ); #endif backslash( buf ); @@ -948,7 +948,7 @@ bool Platform::isFile(const char *pFilePath) #ifdef UNICODE convertUTF8toUTF16N( pFilePath, buf, buf.size ); #else - dStrcpy( buf, pFilePath ); + dStrcpy( buf, pFilePath, buf.size ); #endif backslash( buf ); @@ -987,7 +987,7 @@ S32 Platform::getFileSize(const char *pFilePath) #ifdef UNICODE convertUTF8toUTF16N( pFilePath, buf, buf.size ); #else - dStrcpy( buf, pFilePath ); + dStrcpy( buf, pFilePath, buf.size ); #endif backslash( buf ); @@ -1024,7 +1024,7 @@ bool Platform::isDirectory(const char *pDirPath) #ifdef UNICODE convertUTF8toUTF16N( pDirPath, buf, buf.size ); #else - dStrcpy( buf, pDirPath ); + dStrcpy( buf, pDirPath, buf.size ); #endif backslash( buf ); @@ -1071,8 +1071,8 @@ bool Platform::isSubDirectory(const char *pParent, const char *pDir) convertUTF8toUTF16N( fileName, file, file.size ); convertUTF8toUTF16N( pDir, dir, dir.size ); #else - dStrcpy( file, fileName ); - dStrcpy( dir, pDir ); + dStrcpy( file, fileName, file.size ); + dStrcpy( dir, pDir, dir.size ); #endif backslash( file ); @@ -1256,7 +1256,7 @@ bool Platform::hasSubDirectory(const char *pPath) // Compose our search string - Format : ([path]/[subpath]/*) char trail = pPath[ dStrlen(pPath) - 1 ]; if( trail == '/' ) - dStrcpy( searchBuf, pPath ); + dStrcpy( searchBuf, pPath, 1024 ); else dSprintf(searchBuf, 1024, "%s/*", pPath ); diff --git a/Engine/source/platformWin32/winRedbook.cpp b/Engine/source/platformWin32/winRedbook.cpp index 309f7513a..beef38dd0 100644 --- a/Engine/source/platformWin32/winRedbook.cpp +++ b/Engine/source/platformWin32/winRedbook.cpp @@ -83,8 +83,9 @@ void installRedBookDevices() if(::GetDriveTypeA(str) == DRIVE_CDROM) { Win32RedBookDevice * device = new Win32RedBookDevice; - device->mDeviceName = new char[dStrlen(str) + 1]; - dStrcpy(device->mDeviceName, str); + dsize_t deviceNameLen = dStrlen(str) + 1; + device->mDeviceName = new char[deviceNameLen]; + dStrcpy(device->mDeviceName, str, deviceNameLen); RedBook::installDevice(device); } diff --git a/Engine/source/platformWin32/winWindow.cpp b/Engine/source/platformWin32/winWindow.cpp index 74738f3b5..63fb5ea54 100644 --- a/Engine/source/platformWin32/winWindow.cpp +++ b/Engine/source/platformWin32/winWindow.cpp @@ -606,7 +606,7 @@ const char* Platform::getLoginPassword() if ( RegQueryValueEx( regKey, dT("LoginPassword"), NULL, NULL, buf, &size ) == ERROR_SUCCESS ) { returnString = Con::getReturnBuffer( size + 1 ); - dStrcpy( returnString, (const char*) buf ); + dStrcpy( returnString, (const char*) buf, size + 1 ); } RegCloseKey( regKey ); diff --git a/Engine/source/platformX86UNIX/x86UNIXFileio.cpp b/Engine/source/platformX86UNIX/x86UNIXFileio.cpp index 6e51b85e1..40f5fedae 100644 --- a/Engine/source/platformX86UNIX/x86UNIXFileio.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXFileio.cpp @@ -211,7 +211,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) dStrncpy(pathEl, currChar, pathElLen); pathEl[pathElLen] = '\0'; dStrncpy(testPath, tempBuf, MaxPath); - dStrcat(testPath, pathEl); + dStrcat(testPath, pathEl, MaxPath); if (stat(testPath, &filestat) != -1) { dStrncpy(tempBuf, testPath, MaxPath); @@ -226,7 +226,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) if (dStricmp(pathEl, ent->d_name) == 0) { foundMatch = true; - dStrcat(tempBuf, ent->d_name); + dStrcat(tempBuf, ent->d_name, MaxPath); break; } } @@ -238,7 +238,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) } if (*termChar == '/') { - dStrcat(tempBuf, "/"); + dStrcat(tempBuf, "/", MaxPath); termChar++; currChar = termChar; } @@ -935,7 +935,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) TempAlloc< UTF8 > buf( dStrlen( newDir ) + 2 ); - dStrcpy( buf, newDir ); + dStrcpy( buf, newDir, buf.size ); ForwardSlash( buf ); return chdir( buf ) == 0; @@ -1267,7 +1267,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) { char child[1024]; if ( (basePath[dStrlen(basePath) - 1]) == '/') - dStrcpy (child, d->d_name); + dStrcpy (child, d->d_name, 1024); else dSprintf(child, 1024, "/%s", d->d_name); if (currentDepth < recurseDepth || recurseDepth == -1) diff --git a/Engine/source/platformX86UNIX/x86UNIXInput.client.cpp b/Engine/source/platformX86UNIX/x86UNIXInput.client.cpp index 37e3ee179..2776601a7 100644 --- a/Engine/source/platformX86UNIX/x86UNIXInput.client.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXInput.client.cpp @@ -554,7 +554,7 @@ bool XClipboard::setClipboard(const char *text) checkTDataSize(len); // copy the data into the storage buffer - dStrcpy(mTData, text); + dStrcpy(mTData, text, mTDataSize); // tell X that we own the clipboard. (we'll get events // if an app tries to paste) diff --git a/Engine/source/platformX86UNIX/x86UNIXNet.cpp b/Engine/source/platformX86UNIX/x86UNIXNet.cpp index e186b8f8a..2cfb81521 100644 --- a/Engine/source/platformX86UNIX/x86UNIXNet.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXNet.cpp @@ -97,7 +97,7 @@ static Socket* addPolledSocket(NetSocket& fd, S32 state, sock->fd = fd; sock->state = state; if (remoteAddr) - dStrcpy(sock->remoteAddr, remoteAddr); + dStrcpy(sock->remoteAddr, remoteAddr, 256); if (port != -1) sock->remotePort = port; gPolledSockets.push_back(sock); @@ -242,7 +242,7 @@ NetSocket Net::openConnectTo(const char *addressString) if(!dStrnicmp(addressString, "ip:", 3)) addressString += 3; // eat off the ip: char remoteAddr[256]; - dStrcpy(remoteAddr, addressString); + dStrcpy(remoteAddr, addressString, 256); char *portString = dStrchr(remoteAddr, ':'); @@ -814,7 +814,7 @@ bool Net::stringToAddress(const char *addressString, NetAddress *address) if(strlen(addressString) > 255) return false; - dStrcpy(remoteAddr, addressString); + dStrcpy(remoteAddr, addressString, 256); char *portString = dStrchr(remoteAddr, ':'); if(portString) diff --git a/Engine/source/platformX86UNIX/x86UNIXOGLVideo.client.cpp b/Engine/source/platformX86UNIX/x86UNIXOGLVideo.client.cpp index 16f906f69..9db3236c5 100644 --- a/Engine/source/platformX86UNIX/x86UNIXOGLVideo.client.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXOGLVideo.client.cpp @@ -40,8 +40,9 @@ bool InitOpenGL() // Get the video settings from the prefs: const char* resString = Con::getVariable( "$pref::Video::resolution" ); - char* tempBuf = new char[dStrlen( resString ) + 1]; - dStrcpy( tempBuf, resString ); + dsize_t tempBufLen = dStrlen(resString) + 1; + char* tempBuf = new char[tempBufLen]; + dStrcpy( tempBuf, resString, tempBufLen ); char* temp = dStrtok( tempBuf, " x\0" ); U32 width = ( temp ? dAtoi( temp ) : 800 ); temp = dStrtok( NULL, " x\0" ); diff --git a/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp b/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp index 65741218f..d24902230 100644 --- a/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp @@ -101,8 +101,9 @@ void UnixRedBookDevice::setDeviceInfo(S32 deviceId, const char *deviceName) { #if !defined(__FreeBSD__) mDeviceId = deviceId; - mDeviceName = new char[dStrlen(deviceName) + 1]; - dStrcpy(mDeviceName, deviceName); + dsize_t deviceNameLen = dStrlen(deviceName) + 1; + mDeviceName = new char[deviceNameLen]; + dStrcpy(mDeviceName, deviceName, deviceNameLen); #endif // !defined(__FreeBSD__) } diff --git a/Engine/source/scene/sceneObject.h b/Engine/source/scene/sceneObject.h index 549246c9e..34060acce 100644 --- a/Engine/source/scene/sceneObject.h +++ b/Engine/source/scene/sceneObject.h @@ -60,6 +60,9 @@ #include "gfx/gfxDevice.h" #endif +#ifndef _COLLADA_UTILS_H_ +#include "ts/collada/colladaUtils.h" +#endif class SceneManager; class SceneRenderState; @@ -550,6 +553,23 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce const Box3F& box, const SphereF& sphere ) { return false; } + /// Builds a list of polygons which intersect a bounding volume for exporting + /// + /// This will use either the sphere or the box, not both, the + /// SceneObject implementation ignores sphere. + /// + /// @see AbstractPolyList + /// @param context A contentual hint as to the type of polylist to build. + /// @param polyList Poly list build (out) + /// @param box Box bounding volume + /// @param sphere Sphere bounding volume + /// + virtual bool buildExportPolyList(ColladaUtils::ExportData *exportData, + const Box3F& box, + const SphereF& sphere) { + return false; + } + /// Casts a ray and obtain collision information, returns true if RayInfo is modified. /// /// @param start Start point of ray diff --git a/Engine/source/sfx/openal/sfxALProvider.cpp b/Engine/source/sfx/openal/sfxALProvider.cpp index dc6714b5a..47b2444b3 100644 --- a/Engine/source/sfx/openal/sfxALProvider.cpp +++ b/Engine/source/sfx/openal/sfxALProvider.cpp @@ -114,7 +114,7 @@ void SFXALProvider::init() dSprintf( temp, sizeof( temp ), "[EAX %d.0] %s", eax, ( mALDL->IsExtensionSupported( i, SFXALEAXRAM ) ? "EAX-RAM" : "" ) ); } else - dStrcpy( temp, "" ); + dStrcpy( temp, "", 256 ); info->driver = String::ToString( deviceFormat, major, minor, temp ); info->hasHardware = eax > 0; @@ -144,4 +144,4 @@ SFXDevice *SFXALProvider::createDevice( const String& deviceName, bool useHardwa return new SFXALDevice( this, mOpenAL, info->name, useHardware, maxBuffers ); return NULL; -} \ No newline at end of file +} diff --git a/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp b/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp index 66d746ebe..db449b49f 100644 --- a/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp @@ -142,7 +142,7 @@ void AppVertConnectorGLSL::sortVars() void AppVertConnectorGLSL::setName( char *newName ) { - dStrcpy( (char*)mName, newName ); + dStrcpy( (char*)mName, newName, 32 ); } void AppVertConnectorGLSL::reset() @@ -287,7 +287,7 @@ void VertPixelConnectorGLSL::sortVars() void VertPixelConnectorGLSL::setName( char *newName ) { - dStrcpy( (char*)mName, newName ); + dStrcpy( (char*)mName, newName, 32 ); } void VertPixelConnectorGLSL::reset() diff --git a/Engine/source/shaderGen/HLSL/shaderCompHLSL.cpp b/Engine/source/shaderGen/HLSL/shaderCompHLSL.cpp index b01419a8b..66c23d353 100644 --- a/Engine/source/shaderGen/HLSL/shaderCompHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/shaderCompHLSL.cpp @@ -232,7 +232,7 @@ void ShaderConnectorHLSL::sortVars() void ShaderConnectorHLSL::setName( char *newName ) { - dStrcpy( (char*)mName, newName ); + dStrcpy( (char*)mName, newName, 32 ); } void ShaderConnectorHLSL::reset() diff --git a/Engine/source/shaderGen/langElement.cpp b/Engine/source/shaderGen/langElement.cpp index 59e9a3bde..e4870bb14 100644 --- a/Engine/source/shaderGen/langElement.cpp +++ b/Engine/source/shaderGen/langElement.cpp @@ -87,7 +87,7 @@ U32 Var::texUnitCount = 0; Var::Var() { - dStrcpy( (char*)type, "float4" ); + dStrcpy( (char*)type, "float4", 32 ); structName[0] = '\0'; connectName[0] = '\0'; constSortPos = cspUninit; @@ -209,4 +209,4 @@ void MultiLine::print( Stream &stream ) { mStatementList[i]->print( stream ); } -} \ No newline at end of file +} diff --git a/Engine/source/shaderGen/shaderGen.cpp b/Engine/source/shaderGen/shaderGen.cpp index a182588d5..6b19ba0f5 100644 --- a/Engine/source/shaderGen/shaderGen.cpp +++ b/Engine/source/shaderGen/shaderGen.cpp @@ -153,8 +153,8 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData, dSprintf( vertShaderName, sizeof(vertShaderName), "shadergen:/%s_V.%s", cacheName, mFileEnding.c_str() ); dSprintf( pixShaderName, sizeof(pixShaderName), "shadergen:/%s_P.%s", cacheName, mFileEnding.c_str() ); - dStrcpy( vertFile, vertShaderName ); - dStrcpy( pixFile, pixShaderName ); + dStrcpy( vertFile, vertShaderName, 256 ); + dStrcpy( pixFile, pixShaderName, 256 ); // this needs to change - need to optimize down to ps v.1.1 *pixVersion = GFX->getPixelShaderVersion(); diff --git a/Engine/source/sim/actionMap.cpp b/Engine/source/sim/actionMap.cpp index 841f3e39b..ca2932e84 100644 --- a/Engine/source/sim/actionMap.cpp +++ b/Engine/source/sim/actionMap.cpp @@ -245,11 +245,11 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const else { // IMPORTANT -- do NOT change the following line, it identifies the file as an input map file - dStrcpy( lineBuffer, "// Torque Input Map File\n" ); + dStrcpy( lineBuffer, "// Torque Input Map File\n", 1024 ); iostrm->write( dStrlen( lineBuffer ), lineBuffer ); } - dSprintf(lineBuffer, 1023, "if (isObject(%s)) %s.delete();\n" + dSprintf(lineBuffer, 1024, "if (isObject(%s)) %s.delete();\n" "new ActionMap(%s);\n", getName(), getName(), getName()); iostrm->write(dStrlen(lineBuffer), lineBuffer); @@ -277,7 +277,7 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const else command = "bind"; - dSprintf(lineBuffer, 1023, "%s.%s(%s, \"%s%s\"", + dSprintf(lineBuffer, 1024, "%s.%s(%s, \"%s%s\"", getName(), command, devbuffer, @@ -298,53 +298,53 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const buff[curr++] = 'I'; buff[curr] = '\0'; - dStrcat(lineBuffer, buff); + dStrcat(lineBuffer, buff, 1024); } if (rNode.flags & Node::HasDeadZone) { char buff[64]; dSprintf(buff, 63, ", \"%g %g\"", rNode.deadZoneBegin, rNode.deadZoneEnd); - dStrcat(lineBuffer, buff); + dStrcat(lineBuffer, buff, 1024); } if (rNode.flags & Node::HasScale) { char buff[64]; dSprintf(buff, 63, ", %g", rNode.scaleFactor); - dStrcat(lineBuffer, buff); + dStrcat(lineBuffer, buff, 1024); } if (rNode.flags & Node::BindCmd) { if (rNode.makeConsoleCommand) { - dStrcat(lineBuffer, ", \""); + dStrcat(lineBuffer, ", \"", 1024); U32 pos = dStrlen(lineBuffer); expandEscape(lineBuffer + pos, rNode.makeConsoleCommand); - dStrcat(lineBuffer, "\""); + dStrcat(lineBuffer, "\"", 1024); } else { - dStrcat(lineBuffer, ", \"\""); + dStrcat(lineBuffer, ", \"\"", 1024); } if (rNode.breakConsoleCommand) { - dStrcat(lineBuffer, ", \""); + dStrcat(lineBuffer, ", \"", 1024); U32 pos = dStrlen(lineBuffer); expandEscape(lineBuffer + pos, rNode.breakConsoleCommand); - dStrcat(lineBuffer, "\""); + dStrcat(lineBuffer, "\"", 1024); } else - dStrcat(lineBuffer, ", \"\""); + dStrcat(lineBuffer, ", \"\"", 1024); } else if (rNode.flags & Node::Held) { - dStrcat(lineBuffer, ", "); - dStrcat(lineBuffer, rNode.consoleFunction); + dStrcat(lineBuffer, ", ", 1024); + dStrcat(lineBuffer, rNode.consoleFunction, 1024); - dStrcat(lineBuffer, ", "); - dStrcat(lineBuffer, rNode.contextEvent->mConsoleFunctionHeld); + dStrcat(lineBuffer, ", ", 1024); + dStrcat(lineBuffer, rNode.contextEvent->mConsoleFunctionHeld, 1024); } else { - dStrcat(lineBuffer, ", "); - dStrcat(lineBuffer, rNode.consoleFunction); + dStrcat(lineBuffer, ", ", 1024); + dStrcat(lineBuffer, rNode.consoleFunction, 1024); } - dStrcat(lineBuffer, ");\n"); + dStrcat(lineBuffer, ");\n", 1024); iostrm->write(dStrlen(lineBuffer), lineBuffer); } } @@ -377,7 +377,7 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const command = "bind"; char finalBuffer[1024]; - dSprintf(finalBuffer, 1023, "%s.%s(%s, \"%s%s\"", + dSprintf(finalBuffer, 1024, "%s.%s(%s, \"%s%s\"", getName(), command, devbuffer, @@ -398,51 +398,51 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const buff[curr++] = 'I'; buff[curr] = '\0'; - dStrcat(finalBuffer, buff); + dStrcat(finalBuffer, buff, 1024); } if (rNode.flags & Node::HasDeadZone) { char buff[64]; dSprintf(buff, 63, ", \"%g %g\"", rNode.deadZoneBegin, rNode.deadZoneEnd); - dStrcat(finalBuffer, buff); + dStrcat(finalBuffer, buff, 1024); } if (rNode.flags & Node::HasScale) { char buff[64]; dSprintf(buff, 63, ", %g", rNode.scaleFactor); - dStrcat(finalBuffer, buff); + dStrcat(finalBuffer, buff, 1024); } if (rNode.flags & Node::BindCmd) { if (rNode.makeConsoleCommand) { - dStrcat(finalBuffer, ", \""); - dStrcat(finalBuffer, rNode.makeConsoleCommand); - dStrcat(finalBuffer, "\""); + dStrcat(finalBuffer, ", \"", 1024); + dStrcat(finalBuffer, rNode.makeConsoleCommand, 1024); + dStrcat(finalBuffer, "\"", 1024); } else { - dStrcat(finalBuffer, ", \"\""); + dStrcat(finalBuffer, ", \"\"", 1024); } if (rNode.breakConsoleCommand) { - dStrcat(finalBuffer, ", \""); - dStrcat(finalBuffer, rNode.breakConsoleCommand); - dStrcat(finalBuffer, "\""); + dStrcat(finalBuffer, ", \"", 1024); + dStrcat(finalBuffer, rNode.breakConsoleCommand, 1024); + dStrcat(finalBuffer, "\"", 1024); } else - dStrcat(finalBuffer, ", \"\""); + dStrcat(finalBuffer, ", \"\"", 1024); } else if (rNode.flags & Node::Held) { - dStrcat(finalBuffer, ", "); - dStrcat(finalBuffer, rNode.consoleFunction); + dStrcat(finalBuffer, ", ", 1024); + dStrcat(finalBuffer, rNode.consoleFunction, 1024); - dStrcat(finalBuffer, ", "); - dStrcat(finalBuffer, rNode.contextEvent->mConsoleFunctionHeld); + dStrcat(finalBuffer, ", ", 1024); + dStrcat(finalBuffer, rNode.contextEvent->mConsoleFunctionHeld, 1024); } else { - dStrcat(finalBuffer, ", "); - dStrcat(finalBuffer, rNode.consoleFunction); + dStrcat(finalBuffer, ", ", 1024); + dStrcat(finalBuffer, rNode.consoleFunction, 1024); } - dStrcat(finalBuffer, ");"); + dStrcat(finalBuffer, ");", 1024); Con::printf(finalBuffer); } } @@ -453,7 +453,7 @@ void ActionMap::dumpActionMap(const char* fileName, const bool append) const bool ActionMap::createEventDescriptor(const char* pEventString, EventDescriptor* pDescriptor) { char copyBuffer[256]; - dStrcpy(copyBuffer, pEventString); + dStrcpy(copyBuffer, pEventString, 256); // Do we have modifiers? char* pSpace = dStrchr(copyBuffer, ' '); @@ -786,8 +786,8 @@ const char* ActionMap::getBinding( const char* command ) { dSprintf( buffer, sizeof( buffer ), "%s\t%s%s", deviceBuffer, modifierString, keyBuffer ); if ( returnString[0] ) - dStrcat( returnString, "\t" ); - dStrcat( returnString, buffer ); + dStrcat( returnString, "\t", 1024 ); + dStrcat( returnString, buffer, 1024 ); } } @@ -908,8 +908,9 @@ const char* ActionMap::getDeadZone( const char* device, const char* action ) { char buf[64]; dSprintf( buf, sizeof( buf ), "%g %g", mapNode->deadZoneBegin, mapNode->deadZoneEnd ); - char* returnString = Con::getReturnBuffer( dStrlen( buf ) + 1 ); - dStrcpy( returnString, buf ); + dsize_t returnLen = dStrlen(buf) + 1; + char* returnString = Con::getReturnBuffer( returnLen ); + dStrcpy( returnString, buf, returnLen ); return( returnString ); } else @@ -995,7 +996,7 @@ bool ActionMap::getDeviceName(const U32 deviceType, const U32 deviceInstance, ch { switch (deviceType) { case KeyboardDeviceType: - dStrcpy(buffer, "keyboard"); + dStrcpy(buffer, "keyboard", 16); break; case MouseDeviceType: @@ -1135,7 +1136,7 @@ bool ActionMap::getKeyString(const U32 action, char* buffer) for (U32 i = 0; gAsciiMap[i].asciiCode != 0xFFFF; i++) { if (gAsciiMap[i].asciiCode == asciiCode) { - dStrcpy(buffer, gAsciiMap[i].pDescription); + dStrcpy(buffer, gAsciiMap[i].pDescription, 16); return true; } } @@ -1159,14 +1160,14 @@ bool ActionMap::getKeyString(const U32 action, char* buffer) } //for (U32 i = 0; gVirtualMap[i].code != 0xFFFFFFFF; i++) { // if (gVirtualMap[i].code == action) { - // dStrcpy(buffer, gVirtualMap[i].pDescription); + // dStrcpy(buffer, gVirtualMap[i].pDescription, 16); // return true; // } //} const char* desc = INPUTMGR->findVirtualMapDescFromCode(action); if(desc) { - dStrcpy(buffer, desc); + dStrcpy(buffer, desc, 16); return true; } } diff --git a/Engine/source/sim/connectionStringTable.cpp b/Engine/source/sim/connectionStringTable.cpp index dddd935b2..c3fa4dff6 100644 --- a/Engine/source/sim/connectionStringTable.cpp +++ b/Engine/source/sim/connectionStringTable.cpp @@ -71,7 +71,7 @@ public: static char buffer[512]; dSprintf(buffer, sizeof(buffer), "%s - \"", getClassName()); expandEscape(buffer + dStrlen(buffer), mString.getString()); - dStrcat(buffer, "\""); + dStrcat(buffer, "\"", 512); return buffer; } #endif diff --git a/Engine/source/sim/netDownload.cpp b/Engine/source/sim/netDownload.cpp index 00fc6f0fc..b523ef0ad 100644 --- a/Engine/source/sim/netDownload.cpp +++ b/Engine/source/sim/netDownload.cpp @@ -53,7 +53,7 @@ public: for(U32 i = 0; i < nameCount; i++) { - dStrcpy(mFileNames[i], (*nameList)[i]); + dStrcpy(mFileNames[i], (*nameList)[i], 256); //Con::printf("Sending request for file %s", mFileNames[i]); } } diff --git a/Engine/source/sim/netObject.h b/Engine/source/sim/netObject.h index 1ba588944..60e8786d7 100644 --- a/Engine/source/sim/netObject.h +++ b/Engine/source/sim/netObject.h @@ -132,8 +132,8 @@ struct GhostInfo; /// // the ScopeAlways flag indicates that the object is always scoped /// // on all active connections. /// mNetFlags.set(ScopeAlways | Ghostable); -/// dStrcpy(message1, "Hello World 1!"); -/// dStrcpy(message2, "Hello World 2!"); +/// dStrcpy(message1, "Hello World 1!", bufLen); +/// dStrcpy(message2, "Hello World 2!", bufLen); /// } /// @endcode /// @@ -187,12 +187,12 @@ struct GhostInfo; /// void setMessage1(const char *msg) /// { /// setMaskBits(Message1Mask); -/// dStrcpy(message1, msg); +/// dStrcpy(message1, msg, bufLen); /// } /// void setMessage2(const char *msg) /// { /// setMaskBits(Message2Mask); -/// dStrcpy(message2, msg); +/// dStrcpy(message2, msg, bufLen); /// } /// @endcode /// diff --git a/Engine/source/sim/netStringTable.cpp b/Engine/source/sim/netStringTable.cpp index 117d0a020..83a059eff 100644 --- a/Engine/source/sim/netStringTable.cpp +++ b/Engine/source/sim/netStringTable.cpp @@ -96,8 +96,9 @@ U32 NetStringTable::addString(const char *string) size = newSize; } table[e].refCount++; - table[e].string = (char *) allocator->alloc(dStrlen(string) + 1); - dStrcpy(table[e].string, string); + dsize_t stringLen = dStrlen(string) + 1; + table[e].string = (char *) allocator->alloc(stringLen); + dStrcpy(table[e].string, string, stringLen); table[e].next = hashTable[bucket]; hashTable[bucket] = e; table[e].link = firstValid; @@ -178,8 +179,9 @@ void NetStringTable::repack() const char *prevStr = table[walk].string; - table[walk].string = (char *) newAllocator->alloc(dStrlen(prevStr) + 1); - dStrcpy(table[walk].string, prevStr); + dsize_t prevStrLen = dStrlen(prevStr) + 1; + table[walk].string = (char *) newAllocator->alloc(prevStrLen); + dStrcpy(table[walk].string, prevStr, prevStrLen); } delete allocator; allocator = newAllocator; @@ -239,7 +241,7 @@ void NetStringTable::expandString(NetStringHandle &inString, char *buf, U32 bufS } buf[bufSize - 1] = 0; } else { - dStrcat(buf, ""); + dStrcat(buf, "", bufSize); } } diff --git a/Engine/source/sqlite/SQLiteObject.cpp b/Engine/source/sqlite/SQLiteObject.cpp index 7fe06de5f..4cba76720 100644 --- a/Engine/source/sqlite/SQLiteObject.cpp +++ b/Engine/source/sqlite/SQLiteObject.cpp @@ -157,19 +157,21 @@ S32 Callback(void *pArg, S32 argc, char **argv, char **columnNames) { // DBEUG CODE // Con::printf("%s = %s\n", columnNames[i], argv[i] ? argv[i] : "NULL"); - name = new char[dStrlen(columnNames[i]) + 1]; - dStrcpy(name, columnNames[i]); + dsize_t columnNameLen = dStrlen(columnNames[i]) + 1; + name = new char[columnNameLen]; + dStrcpy(name, columnNames[i], columnNameLen); pRow->vColumnNames.push_back(name); if (argv[i]) { - value = new char[dStrlen(argv[i]) + 1]; - dStrcpy(value, argv[i]); + dsize_t valueLen = dStrlen(argv[i]) + 1; + value = new char[valueLen]; + dStrcpy(value, argv[i], valueLen); pRow->vColumnValues.push_back(value); } else { value = new char[10]; - dStrcpy(value, "NULL"); + dStrcpy(value, "NULL", 10); pRow->vColumnValues.push_back(value); } } diff --git a/Engine/source/terrain/terrData.cpp b/Engine/source/terrain/terrData.cpp index a97ec7e98..37f523356 100644 --- a/Engine/source/terrain/terrData.cpp +++ b/Engine/source/terrain/terrData.cpp @@ -1303,20 +1303,20 @@ DefineEngineMethod( TerrainBlock, save, bool, ( const char* fileName),, "@return True if file save was successful, false otherwise") { char filename[256]; - dStrcpy(filename,fileName); + dStrcpy(filename,fileName,256); char *ext = dStrrchr(filename, '.'); if (!ext || dStricmp(ext, ".ter") != 0) - dStrcat(filename, ".ter"); + dStrcat(filename, ".ter", 256); return static_cast(object)->save(filename); } //ConsoleMethod(TerrainBlock, save, bool, 3, 3, "(string fileName) - saves the terrain block's terrain file to the specified file name.") //{ // char filename[256]; -// dStrcpy(filename,argv[2]); +// dStrcpy(filename,argv[2],256); // char *ext = dStrrchr(filename, '.'); // if (!ext || dStricmp(ext, ".ter") != 0) -// dStrcat(filename, ".ter"); +// dStrcat(filename, ".ter", 256); // return static_cast(object)->save(filename); //} diff --git a/Engine/source/testing/unitTesting.cpp b/Engine/source/testing/unitTesting.cpp index 2724bf637..a86a28eb3 100644 --- a/Engine/source/testing/unitTesting.cpp +++ b/Engine/source/testing/unitTesting.cpp @@ -99,8 +99,8 @@ DefineConsoleFunction( runAllUnitTests, int, (const char* testSpecs), (""), testArgc = 2; testArgv = new char*[2]; testArgv[0] = NULL; // Program name is unused by googletest. - testArgv[1] = new char[specs.length()+1]; - dStrcpy(testArgv[1], specs); + testArgv[1] = new char[specs.size()]; + dStrcpy(testArgv[1], specs, specs.size()); } // Initialize Google Test. diff --git a/Engine/source/ts/collada/colladaUtils.cpp b/Engine/source/ts/collada/colladaUtils.cpp index 2294ff7be..a3c217bf5 100644 --- a/Engine/source/ts/collada/colladaUtils.cpp +++ b/Engine/source/ts/collada/colladaUtils.cpp @@ -26,6 +26,9 @@ #include "ts/collada/colladaUtils.h" #include "materials/matInstance.h" +//special handling for export classes +#include "T3D/convexShape.h" + using namespace ColladaUtils; #define MAX_PATH_LENGTH 256 @@ -1277,6 +1280,289 @@ void ColladaUtils::exportColladaMaterials(TiXmlElement* rootNode, const Optimize } +void ColladaUtils::exportColladaMaterials(TiXmlElement* rootNode, const ExportData& exportData, const Torque::Path& colladaFile) +{ + // First the image library + TiXmlElement* imgLibNode = new TiXmlElement("library_images"); + rootNode->LinkEndChild(imgLibNode); + + Vector matNames; + + for (U32 i = 0; i < exportData.materials.size(); i++) + { + BaseMatInstance* baseInst = exportData.materials[i]; + + matNames.push_back(String::ToString("Material%d", i)); + + Material* mat = dynamic_cast(baseInst->getMaterial()); + if (!mat) + continue; + + String diffuseMap; + + if (mat->getName() && mat->getName()[0]) + matNames.last() = mat->mMapTo; + + // Handle an auto-generated "Default Material" specially + if (mat->isAutoGenerated()) + { + Torque::Path diffusePath; + + if (mat->mDiffuseMapFilename[0].isNotEmpty()) + diffusePath = mat->mDiffuseMapFilename[0]; + else + diffusePath = String("warningMat"); + + matNames.last() = diffusePath.getFileName(); + diffuseMap += diffusePath.getFullFileName(); + } + else + { + if (mat->mDiffuseMapFilename[0].isNotEmpty()) + diffuseMap += mat->mDiffuseMapFilename[0]; + else + diffuseMap += "warningMat"; + } + + Torque::Path diffusePath = findTexture(colladaFile.getPath() + "/" + diffuseMap); + + // If we didn't get a path + if (diffusePath.getFullPath().isNotEmpty()) + diffuseMap = Torque::Path::MakeRelativePath(diffusePath, colladaFile); + + TiXmlElement* imageNode = new TiXmlElement("image"); + imgLibNode->LinkEndChild(imageNode); + imageNode->SetAttribute("id", avar("%s", matNames.last().c_str())); + imageNode->SetAttribute("name", avar("%s", matNames.last().c_str())); + + TiXmlElement* initNode = new TiXmlElement("init_from"); + imageNode->LinkEndChild(initNode); + TiXmlText* initText = new TiXmlText(avar("file://%s", diffuseMap.c_str())); // "the file://" is needed to load the texture in some old apps (ex: 3ds Max 2009) + initNode->LinkEndChild(initText); + } + + // Next the effects library + TiXmlElement* effectLibNode = new TiXmlElement("library_effects"); + rootNode->LinkEndChild(effectLibNode); + + for (U32 i = 0; i < exportData.materials.size(); i++) + { + BaseMatInstance* baseInst = exportData.materials[i]; + + Material* mat = dynamic_cast(baseInst->getMaterial()); + if (!mat) + continue; + + TiXmlElement* effectNode = new TiXmlElement("effect"); + effectLibNode->LinkEndChild(effectNode); + effectNode->SetAttribute("id", avar("%s-effect", matNames[i].c_str())); + effectNode->SetAttribute("name", avar("%s-effect", matNames[i].c_str())); + + TiXmlElement* profileNode = new TiXmlElement("profile_COMMON"); + effectNode->LinkEndChild(profileNode); + + // --------------------------- + TiXmlElement* newParamNode = new TiXmlElement("newparam"); + profileNode->LinkEndChild(newParamNode); + newParamNode->SetAttribute("sid", avar("%s-surface", matNames[i].c_str())); + + TiXmlElement* surfaceNode = new TiXmlElement("surface"); + newParamNode->LinkEndChild(surfaceNode); + surfaceNode->SetAttribute("type", "2D"); + + TiXmlElement* initNode2 = new TiXmlElement("init_from"); + surfaceNode->LinkEndChild(initNode2); + TiXmlText* init2Text = new TiXmlText(avar("%s", matNames[i].c_str())); + initNode2->LinkEndChild(init2Text); + + TiXmlElement* formatNode = new TiXmlElement("format"); + surfaceNode->LinkEndChild(formatNode); + TiXmlText* formatText = new TiXmlText("A8R8G8B8"); + formatNode->LinkEndChild(formatText); + + // --------------------------- + TiXmlElement* newParam2Node = new TiXmlElement("newparam"); + profileNode->LinkEndChild(newParam2Node); + newParam2Node->SetAttribute("sid", avar("%s-sampler", matNames[i].c_str())); + + TiXmlElement* sampler2DNode = new TiXmlElement("sampler2D"); + newParam2Node->LinkEndChild(sampler2DNode); + + TiXmlElement* sourceSampler2DNode = new TiXmlElement("source"); + sampler2DNode->LinkEndChild(sourceSampler2DNode); + TiXmlText* sourceSampler2DText = new TiXmlText(avar("%s-surface", matNames[i].c_str())); + sourceSampler2DNode->LinkEndChild(sourceSampler2DText); + + // --------------------------- + + TiXmlElement* techniqueNode = new TiXmlElement("technique"); + profileNode->LinkEndChild(techniqueNode); + techniqueNode->SetAttribute("sid", "common"); + + TiXmlElement* blinnNode = new TiXmlElement("blinn"); + techniqueNode->LinkEndChild(blinnNode); + + // --------------------------- + TiXmlElement* emissionNode = new TiXmlElement("emission"); + blinnNode->LinkEndChild(emissionNode); + + TiXmlElement* colorEmissionNode = new TiXmlElement("color"); + emissionNode->LinkEndChild(colorEmissionNode); + colorEmissionNode->SetAttribute("sid", "emission"); + + TiXmlText* colorEmissionNodeText = new TiXmlText("0.0 0.0 0.0 1.0"); + colorEmissionNode->LinkEndChild(colorEmissionNodeText); + + // --------------------------- + TiXmlElement* ambientNode = new TiXmlElement("ambient"); + blinnNode->LinkEndChild(ambientNode); + + TiXmlElement* colorAmbientNode = new TiXmlElement("color"); + ambientNode->LinkEndChild(colorAmbientNode); + colorAmbientNode->SetAttribute("sid", "ambient"); + + TiXmlText* colorAmbientNodeText = new TiXmlText("0.0 0.0 0.0 1.0"); + colorAmbientNode->LinkEndChild(colorAmbientNodeText); + + // --------------------------- + TiXmlElement* diffuseNode = new TiXmlElement("diffuse"); + blinnNode->LinkEndChild(diffuseNode); + TiXmlElement* textureDiffuseNode = new TiXmlElement("texture"); + diffuseNode->LinkEndChild(textureDiffuseNode); + textureDiffuseNode->SetAttribute("texture", avar("%s-sampler", matNames[i].c_str())); + textureDiffuseNode->SetAttribute("texcoord", "UVMap"); + + // Extra info useful for getting the texture to show up correctly in MAYA and 3DS Max + TiXmlElement* extraNode = new TiXmlElement("extra"); + textureDiffuseNode->LinkEndChild(extraNode); + + TiXmlElement* extraTechNode = new TiXmlElement("technique"); + extraNode->LinkEndChild(extraTechNode); + extraTechNode->SetAttribute("profile", "MAYA"); + + TiXmlElement* extraWrapUNode = new TiXmlElement("wrapU"); + extraTechNode->LinkEndChild(extraWrapUNode); + extraWrapUNode->SetAttribute("sid", "wrapU0"); + + TiXmlText* extraWrapUText = new TiXmlText("TRUE"); + extraWrapUNode->LinkEndChild(extraWrapUText); + + TiXmlElement* extraWrapVNode = new TiXmlElement("wrapV"); + extraTechNode->LinkEndChild(extraWrapVNode); + extraWrapVNode->SetAttribute("sid", "wrapV0"); + + TiXmlText* extraWrapVText = new TiXmlText("TRUE"); + extraWrapVNode->LinkEndChild(extraWrapVText); + + TiXmlElement* extraBlendNode = new TiXmlElement("blend_mode"); + extraTechNode->LinkEndChild(extraBlendNode); + + TiXmlText* extraBlendText = new TiXmlText("ADD"); + extraBlendNode->LinkEndChild(extraBlendText); + + // --------------------------- + TiXmlElement* specularNode = new TiXmlElement("specular"); + blinnNode->LinkEndChild(specularNode); + + TiXmlElement* colorSpecularNode = new TiXmlElement("color"); + specularNode->LinkEndChild(colorSpecularNode); + colorSpecularNode->SetAttribute("sid", "specular"); + + TiXmlText* colorSpecularNodeText = new TiXmlText("0.5 0.5 0.5 1.0"); + colorSpecularNode->LinkEndChild(colorSpecularNodeText); + + // --------------------------- + TiXmlElement* shininessNode = new TiXmlElement("shininess"); + blinnNode->LinkEndChild(shininessNode); + + TiXmlElement* colorShininessNode = new TiXmlElement("float"); + shininessNode->LinkEndChild(colorShininessNode); + colorShininessNode->SetAttribute("sid", "shininess"); + + TiXmlText* colorShininessNodeText = new TiXmlText("1.0"); + colorShininessNode->LinkEndChild(colorShininessNodeText); + + // --------------------------- + TiXmlElement* reflectiveNode = new TiXmlElement("reflective"); + blinnNode->LinkEndChild(reflectiveNode); + + TiXmlElement* colorReflectiveNode = new TiXmlElement("color"); + reflectiveNode->LinkEndChild(colorReflectiveNode); + colorReflectiveNode->SetAttribute("sid", "reflective"); + + TiXmlText* colorReflectiveNodeText = new TiXmlText("0.0 0.0 0.0 1.0"); + colorReflectiveNode->LinkEndChild(colorReflectiveNodeText); + + // --------------------------- + TiXmlElement* reflectivityNode = new TiXmlElement("reflectivity"); + blinnNode->LinkEndChild(reflectivityNode); + + TiXmlElement* floatReflectivityNode = new TiXmlElement("float"); + reflectivityNode->LinkEndChild(floatReflectivityNode); + floatReflectivityNode->SetAttribute("sid", "reflectivity"); + + TiXmlText* floatReflectivityText = new TiXmlText("0.5"); + floatReflectivityNode->LinkEndChild(floatReflectivityText); + + // --------------------------- + TiXmlElement* transparentNode = new TiXmlElement("transparent"); + blinnNode->LinkEndChild(transparentNode); + transparentNode->SetAttribute("opaque", "RGB_ZERO"); + + TiXmlElement* colorTransparentNode = new TiXmlElement("color"); + transparentNode->LinkEndChild(colorTransparentNode); + colorTransparentNode->SetAttribute("sid", "transparent"); + + TiXmlText* colorTransparentNodeText = new TiXmlText("0.0 0.0 0.0 1.0"); + colorTransparentNode->LinkEndChild(colorTransparentNodeText); + + // --------------------------- + TiXmlElement* transparencyNode = new TiXmlElement("transparency"); + blinnNode->LinkEndChild(transparencyNode); + + TiXmlElement* floatTransparencyNode = new TiXmlElement("float"); + transparencyNode->LinkEndChild(floatTransparencyNode); + floatTransparencyNode->SetAttribute("sid", "transparency"); + + TiXmlText* floatTransparencyText = new TiXmlText("0.0"); + floatTransparencyNode->LinkEndChild(floatTransparencyText); + + // --------------------------- + TiXmlElement* refractionNode = new TiXmlElement("index_of_refraction"); + blinnNode->LinkEndChild(refractionNode); + + TiXmlElement* colorRefractionNode = new TiXmlElement("float"); + refractionNode->LinkEndChild(colorRefractionNode); + colorRefractionNode->SetAttribute("sid", "index_of_refraction"); + + TiXmlText* colorRefractionNodeText = new TiXmlText("1"); + colorRefractionNode->LinkEndChild(colorRefractionNodeText); + } + + // Finally the material library + TiXmlElement* matLibNode = new TiXmlElement("library_materials"); + rootNode->LinkEndChild(matLibNode); + + for (U32 i = 0; i < exportData.materials.size(); i++) + { + BaseMatInstance* baseInst = exportData.materials[i]; + + Material* mat = dynamic_cast(baseInst->getMaterial()); + if (!mat) + continue; + + TiXmlElement* materialNode = new TiXmlElement("material"); + matLibNode->LinkEndChild(materialNode); + materialNode->SetAttribute("id", avar("%s-material", matNames[i].c_str())); + materialNode->SetAttribute("name", matNames[i].c_str()); + + TiXmlElement* instEffectNode = new TiXmlElement("instance_effect"); + materialNode->LinkEndChild(instEffectNode); + instEffectNode->SetAttribute("url", avar("#%s-effect", matNames[i].c_str())); + } + +} + void ColladaUtils::exportColladaTriangles(TiXmlElement* meshNode, const OptimizedPolyList& mesh, const String& meshName, const Vector& matNames) { // Start at -1 so we will export polygons that do not have a material. @@ -1396,6 +1682,252 @@ void ColladaUtils::exportColladaTriangles(TiXmlElement* meshNode, const Optimize } } +void ColladaUtils::exportColladaTriangles(TiXmlElement* meshNode, const ExportData& exportData, const U32 detailLevel, const String& meshName) +{ + // Calculate the number of triangles that uses this Material + U32 triangleCount = 0; + + const ExportData::detailLevel* dl = &exportData.detailLevels[detailLevel]; + + for (S32 i = 0; i < dl->materialRefList.size(); i++) + { + int matIdx; + dl->materialRefList.tryGetValue(i, matIdx); + BaseMatInstance* baseInst = exportData.materials[matIdx]; + + Material* mat = dynamic_cast(baseInst->getMaterial()); + if (!mat) + continue; + + String matName; + + if (mat->getName() && mat->getName()[0]) + matName = mat->mMapTo; + + for (U32 j = 0; j < dl->mesh.mPolyList.size(); j++) + { + const OptimizedPolyList::Poly& poly = dl->mesh.mPolyList[j]; + + if (poly.material != i) + continue; + + if (poly.vertexCount < 3) + continue; + + if (poly.type == OptimizedPolyList::TriangleList || + poly.type == OptimizedPolyList::TriangleFan || + poly.type == OptimizedPolyList::TriangleStrip) + { + triangleCount += poly.vertexCount - 2; + } + else + AssertISV(false, "ColladaUtils::exportColladaTriangles(): Unknown Poly type!"); + } + + // Make sure that we are actually using this Material + if (triangleCount == 0) + continue; + + TiXmlElement* trianglesNode = new TiXmlElement("triangles"); + meshNode->LinkEndChild(trianglesNode); + trianglesNode->SetAttribute("material", (i > -1) ? avar("%s-material", matName.c_str()) : ""); + trianglesNode->SetAttribute("count", avar("%d", triangleCount)); + + TiXmlElement* trianglesVertInputNode = new TiXmlElement("input"); + trianglesNode->LinkEndChild(trianglesVertInputNode); + trianglesVertInputNode->SetAttribute("semantic", "VERTEX"); + trianglesVertInputNode->SetAttribute("source", avar("#%s-mesh-vertices", meshName.c_str())); + trianglesVertInputNode->SetAttribute("offset", "0"); + + TiXmlElement* trianglesNormalInputNode = new TiXmlElement("input"); + trianglesNode->LinkEndChild(trianglesNormalInputNode); + trianglesNormalInputNode->SetAttribute("semantic", "NORMAL"); + trianglesNormalInputNode->SetAttribute("source", avar("#%s-mesh-normals", meshName.c_str())); + trianglesNormalInputNode->SetAttribute("offset", "1"); + + TiXmlElement* trianglesUV0InputNode = new TiXmlElement("input"); + trianglesNode->LinkEndChild(trianglesUV0InputNode); + trianglesUV0InputNode->SetAttribute("semantic", "TEXCOORD"); + trianglesUV0InputNode->SetAttribute("source", avar("#%s-mesh-map-0", meshName.c_str())); + trianglesUV0InputNode->SetAttribute("offset", "2"); + trianglesUV0InputNode->SetAttribute("set", "0"); + + TiXmlElement* polyNode = new TiXmlElement("p"); + trianglesNode->LinkEndChild(polyNode); + + Vector tempIndices; + tempIndices.reserve(4); + + for (U32 j = 0; j < dl->mesh.mPolyList.size(); j++) + { + const OptimizedPolyList::Poly& poly = dl->mesh.mPolyList[j]; + + if (poly.vertexCount < 3) + continue; + + if (poly.material != i) + continue; + + tempIndices.setSize(poly.vertexCount); + dMemset(tempIndices.address(), 0, poly.vertexCount); + + if (poly.type == OptimizedPolyList::TriangleStrip) + { + tempIndices[0] = 0; + U32 idx = 1; + + for (U32 k = 1; k < poly.vertexCount; k += 2) + tempIndices[idx++] = k; + + for (U32 k = ((poly.vertexCount - 1) & (~0x1)); k > 0; k -= 2) + tempIndices[idx++] = k; + } + else if (poly.type == OptimizedPolyList::TriangleList || + poly.type == OptimizedPolyList::TriangleFan) + { + for (U32 k = 0; k < poly.vertexCount; k++) + tempIndices[k] = k; + } + else + AssertISV(false, "ColladaUtils::exportColladaTriangles(): Unknown Poly type!"); + + const U32& firstIdx = dl->mesh.mIndexList[poly.vertexStart]; + const OptimizedPolyList::VertIndex& firstVertIdx = dl->mesh.mVertexList[firstIdx]; + + for (U32 k = 1; k < poly.vertexCount - 1; k++) + { + const U32& secondIdx = dl->mesh.mIndexList[poly.vertexStart + tempIndices[k]]; + const U32& thirdIdx = dl->mesh.mIndexList[poly.vertexStart + tempIndices[k + 1]]; + + const OptimizedPolyList::VertIndex& secondVertIdx = dl->mesh.mVertexList[secondIdx]; + const OptimizedPolyList::VertIndex& thirdVertIdx = dl->mesh.mVertexList[thirdIdx]; + + // Note the reversed winding on the triangles + const char* tri = avar("%d %d %d %d %d %d %d %d %d ", + thirdVertIdx.vertIdx, thirdVertIdx.normalIdx, thirdVertIdx.uv0Idx, + secondVertIdx.vertIdx, secondVertIdx.normalIdx, secondVertIdx.uv0Idx, + firstVertIdx.vertIdx, firstVertIdx.normalIdx, firstVertIdx.uv0Idx); + + TiXmlText* triangleText = new TiXmlText(tri); + polyNode->LinkEndChild(triangleText); + } + } + } +} + +void ColladaUtils::exportColladaCollisionTriangles(TiXmlElement* meshNode, const ExportData& exportData, const U32 collisionIdx) +{ + // Calculate the number of triangles that uses this Material + U32 triangleCount = 0; + + const ExportData::colMesh* col = &exportData.colMeshes[collisionIdx]; + + String meshName = col->colMeshName; + + for (U32 j = 0; j < col->mesh.mPolyList.size(); j++) + { + const OptimizedPolyList::Poly& poly = col->mesh.mPolyList[j]; + + if (poly.vertexCount < 3) + continue; + + if (poly.type == OptimizedPolyList::TriangleList || + poly.type == OptimizedPolyList::TriangleFan || + poly.type == OptimizedPolyList::TriangleStrip) + { + triangleCount += poly.vertexCount - 2; + } + else + AssertISV(false, "ColladaUtils::exportColladaCollisionTriangles(): Unknown Poly type!"); + } + + // Make sure that we are actually using this Material + if (triangleCount == 0) + return; + + TiXmlElement* trianglesNode = new TiXmlElement("triangles"); + meshNode->LinkEndChild(trianglesNode); + trianglesNode->SetAttribute("material", ""); + trianglesNode->SetAttribute("count", avar("%d", triangleCount)); + + TiXmlElement* trianglesVertInputNode = new TiXmlElement("input"); + trianglesNode->LinkEndChild(trianglesVertInputNode); + trianglesVertInputNode->SetAttribute("semantic", "VERTEX"); + trianglesVertInputNode->SetAttribute("source", avar("#%s-mesh-vertices", meshName.c_str())); + trianglesVertInputNode->SetAttribute("offset", "0"); + + TiXmlElement* trianglesNormalInputNode = new TiXmlElement("input"); + trianglesNode->LinkEndChild(trianglesNormalInputNode); + trianglesNormalInputNode->SetAttribute("semantic", "NORMAL"); + trianglesNormalInputNode->SetAttribute("source", avar("#%s-mesh-normals", meshName.c_str())); + trianglesNormalInputNode->SetAttribute("offset", "1"); + + TiXmlElement* trianglesUV0InputNode = new TiXmlElement("input"); + trianglesNode->LinkEndChild(trianglesUV0InputNode); + trianglesUV0InputNode->SetAttribute("semantic", "TEXCOORD"); + trianglesUV0InputNode->SetAttribute("source", avar("#%s-mesh-map-0", meshName.c_str())); + trianglesUV0InputNode->SetAttribute("offset", "2"); + trianglesUV0InputNode->SetAttribute("set", "0"); + + TiXmlElement* polyNode = new TiXmlElement("p"); + trianglesNode->LinkEndChild(polyNode); + + Vector tempIndices; + tempIndices.reserve(4); + + for (U32 j = 0; j < col->mesh.mPolyList.size(); j++) + { + const OptimizedPolyList::Poly& poly = col->mesh.mPolyList[j]; + + if (poly.vertexCount < 3) + continue; + + tempIndices.setSize(poly.vertexCount); + dMemset(tempIndices.address(), 0, poly.vertexCount); + + if (poly.type == OptimizedPolyList::TriangleStrip) + { + tempIndices[0] = 0; + U32 idx = 1; + + for (U32 k = 1; k < poly.vertexCount; k += 2) + tempIndices[idx++] = k; + + for (U32 k = ((poly.vertexCount - 1) & (~0x1)); k > 0; k -= 2) + tempIndices[idx++] = k; + } + else if (poly.type == OptimizedPolyList::TriangleList || + poly.type == OptimizedPolyList::TriangleFan) + { + for (U32 k = 0; k < poly.vertexCount; k++) + tempIndices[k] = k; + } + else + AssertISV(false, "ColladaUtils::exportColladaTriangles(): Unknown Poly type!"); + + const U32& firstIdx = col->mesh.mIndexList[poly.vertexStart]; + const OptimizedPolyList::VertIndex& firstVertIdx = col->mesh.mVertexList[firstIdx]; + + for (U32 k = 1; k < poly.vertexCount - 1; k++) + { + const U32& secondIdx = col->mesh.mIndexList[poly.vertexStart + tempIndices[k]]; + const U32& thirdIdx = col->mesh.mIndexList[poly.vertexStart + tempIndices[k + 1]]; + + const OptimizedPolyList::VertIndex& secondVertIdx = col->mesh.mVertexList[secondIdx]; + const OptimizedPolyList::VertIndex& thirdVertIdx = col->mesh.mVertexList[thirdIdx]; + + // Note the reversed winding on the triangles + const char* tri = avar("%d %d %d %d %d %d %d %d %d ", + thirdVertIdx.vertIdx, thirdVertIdx.normalIdx, thirdVertIdx.uv0Idx, + secondVertIdx.vertIdx, secondVertIdx.normalIdx, secondVertIdx.uv0Idx, + firstVertIdx.vertIdx, firstVertIdx.normalIdx, firstVertIdx.uv0Idx); + + TiXmlText* triangleText = new TiXmlText(tri); + polyNode->LinkEndChild(triangleText); + } + } +} + void ColladaUtils::exportColladaMesh(TiXmlElement* rootNode, const OptimizedPolyList& mesh, const String& meshName, const Vector& matNames) { TiXmlElement* libGeomsNode = new TiXmlElement("library_geometries"); @@ -1576,6 +2108,380 @@ void ColladaUtils::exportColladaMesh(TiXmlElement* rootNode, const OptimizedPoly } +void ColladaUtils::exportColladaMesh(TiXmlElement* rootNode, const ExportData& exportData, const String& meshName) +{ + TiXmlElement* libGeomsNode = new TiXmlElement("library_geometries"); + rootNode->LinkEndChild(libGeomsNode); + + for (U32 d = 0; d < exportData.detailLevels.size(); d++) + { + char lodMeshName[256]; + dSprintf(lodMeshName, 256, "%s%d", meshName.c_str(), exportData.detailLevels[d].size); + + char lodMeshID[256]; + dSprintf(lodMeshID, 256, "%s-mesh", lodMeshName); + + TiXmlElement* geometryNode = new TiXmlElement("geometry"); + libGeomsNode->LinkEndChild(geometryNode); + geometryNode->SetAttribute("id", lodMeshID); + geometryNode->SetAttribute("name", lodMeshName); + + TiXmlElement* meshNode = new TiXmlElement("mesh"); + geometryNode->LinkEndChild(meshNode); + + // Save out the vertices + TiXmlElement* vertsSourceNode = new TiXmlElement("source"); + meshNode->LinkEndChild(vertsSourceNode); + vertsSourceNode->SetAttribute("id", avar("%s-mesh-positions", lodMeshName)); + + TiXmlElement* vertsNode = new TiXmlElement("float_array"); + vertsSourceNode->LinkEndChild(vertsNode); + vertsNode->SetAttribute("id", avar("%s-mesh-positions-array", lodMeshName)); + vertsNode->SetAttribute("count", avar("%d", exportData.detailLevels[d].mesh.mPoints.size() * 3)); + + for (U32 i = 0; i < exportData.detailLevels[d].mesh.mPoints.size(); i++) + { + const Point3F& vert = exportData.detailLevels[d].mesh.mPoints[i]; + + TiXmlText* vertText = new TiXmlText(avar("%.4f %.4f %.4f ", vert.x, vert.y, vert.z)); + vertsNode->LinkEndChild(vertText); + } + + // Save the vertex accessor + TiXmlElement* vertsTechNode = new TiXmlElement("technique_common"); + vertsSourceNode->LinkEndChild(vertsTechNode); + + TiXmlElement* vertsAccNode = new TiXmlElement("accessor"); + vertsTechNode->LinkEndChild(vertsAccNode); + vertsAccNode->SetAttribute("source", avar("#%s-mesh-positions-array", lodMeshName)); + vertsAccNode->SetAttribute("count", avar("%d", exportData.detailLevels[d].mesh.mPoints.size())); + vertsAccNode->SetAttribute("stride", "3"); + + TiXmlElement* vertsAccXNode = new TiXmlElement("param"); + vertsAccNode->LinkEndChild(vertsAccXNode); + vertsAccXNode->SetAttribute("name", "X"); + vertsAccXNode->SetAttribute("type", "float"); + + TiXmlElement* vertsAccYNode = new TiXmlElement("param"); + vertsAccNode->LinkEndChild(vertsAccYNode); + vertsAccYNode->SetAttribute("name", "Y"); + vertsAccYNode->SetAttribute("type", "float"); + + TiXmlElement* vertsAccZNode = new TiXmlElement("param"); + vertsAccNode->LinkEndChild(vertsAccZNode); + vertsAccZNode->SetAttribute("name", "Z"); + vertsAccZNode->SetAttribute("type", "float"); + + // Save out the normals + TiXmlElement* normalsSourceNode = new TiXmlElement("source"); + meshNode->LinkEndChild(normalsSourceNode); + normalsSourceNode->SetAttribute("id", avar("%s-mesh-normals", lodMeshName)); + + TiXmlElement* normalsNode = new TiXmlElement("float_array"); + normalsSourceNode->LinkEndChild(normalsNode); + normalsNode->SetAttribute("id", avar("%s-mesh-normals-array", lodMeshName)); + normalsNode->SetAttribute("count", avar("%d", exportData.detailLevels[d].mesh.mNormals.size() * 3)); + + for (U32 i = 0; i < exportData.detailLevels[d].mesh.mNormals.size(); i++) + { + const Point3F& normal = exportData.detailLevels[d].mesh.mNormals[i]; + + TiXmlText* normalText = new TiXmlText(avar("%.4f %.4f %.4f ", normal.x, normal.y, normal.z)); + normalsNode->LinkEndChild(normalText); + } + + // Save the normals accessor + TiXmlElement* normalsTechNode = new TiXmlElement("technique_common"); + normalsSourceNode->LinkEndChild(normalsTechNode); + + TiXmlElement* normalsAccNode = new TiXmlElement("accessor"); + normalsTechNode->LinkEndChild(normalsAccNode); + normalsAccNode->SetAttribute("source", avar("#%s-mesh-normals-array", lodMeshName)); + normalsAccNode->SetAttribute("count", avar("%d", exportData.detailLevels[d].mesh.mNormals.size())); + normalsAccNode->SetAttribute("stride", "3"); + + TiXmlElement* normalsAccXNode = new TiXmlElement("param"); + normalsAccNode->LinkEndChild(normalsAccXNode); + normalsAccXNode->SetAttribute("name", "X"); + normalsAccXNode->SetAttribute("type", "float"); + + TiXmlElement* normalsAccYNode = new TiXmlElement("param"); + normalsAccNode->LinkEndChild(normalsAccYNode); + normalsAccYNode->SetAttribute("name", "Y"); + normalsAccYNode->SetAttribute("type", "float"); + + TiXmlElement* normalsAccZNode = new TiXmlElement("param"); + normalsAccNode->LinkEndChild(normalsAccZNode); + normalsAccZNode->SetAttribute("name", "Z"); + normalsAccZNode->SetAttribute("type", "float"); + + // Save out the uvs + TiXmlElement* uv0SourceNode = new TiXmlElement("source"); + meshNode->LinkEndChild(uv0SourceNode); + uv0SourceNode->SetAttribute("id", avar("%s-mesh-map-0", lodMeshName)); + + TiXmlElement* uv0Node = new TiXmlElement("float_array"); + uv0SourceNode->LinkEndChild(uv0Node); + uv0Node->SetAttribute("id", avar("%s-mesh-map-0-array", lodMeshName)); + uv0Node->SetAttribute("count", avar("%d", exportData.detailLevels[d].mesh.mUV0s.size() * 2)); + + for (U32 i = 0; i < exportData.detailLevels[d].mesh.mUV0s.size(); i++) + { + const Point2F& uv0 = exportData.detailLevels[d].mesh.mUV0s[i]; + + TiXmlText* uv0Text = new TiXmlText(avar("%.4f %.4f ", uv0.x, 1.0f - uv0.y)); // COLLADA uvs are upside down compared to Torque + uv0Node->LinkEndChild(uv0Text); + } + + // Save the uv0 accessor + TiXmlElement* uv0TechNode = new TiXmlElement("technique_common"); + uv0SourceNode->LinkEndChild(uv0TechNode); + + TiXmlElement* uv0AccNode = new TiXmlElement("accessor"); + uv0TechNode->LinkEndChild(uv0AccNode); + uv0AccNode->SetAttribute("source", avar("#%s-mesh-map-0-array", lodMeshName)); + uv0AccNode->SetAttribute("count", avar("%d", exportData.detailLevels[d].mesh.mUV0s.size())); + uv0AccNode->SetAttribute("stride", "2"); + + TiXmlElement* uv0AccSNode = new TiXmlElement("param"); + uv0AccNode->LinkEndChild(uv0AccSNode); + uv0AccSNode->SetAttribute("name", "S"); + uv0AccSNode->SetAttribute("type", "float"); + + TiXmlElement* uv0AccTNode = new TiXmlElement("param"); + uv0AccNode->LinkEndChild(uv0AccTNode); + uv0AccTNode->SetAttribute("name", "T"); + uv0AccTNode->SetAttribute("type", "float"); + + // Define the vertices position array + TiXmlElement* verticesNode = new TiXmlElement("vertices"); + meshNode->LinkEndChild(verticesNode); + verticesNode->SetAttribute("id", avar("%s-mesh-vertices", lodMeshName)); + + TiXmlElement* verticesInputNode = new TiXmlElement("input"); + verticesNode->LinkEndChild(verticesInputNode); + verticesInputNode->SetAttribute("semantic", "POSITION"); + verticesInputNode->SetAttribute("source", avar("#%s-mesh-positions", lodMeshName)); + + Vector mapNames; + + //exportColladaTriangles(meshNode, exportData.detailLevels[d].mesh, lodMeshName, mapNames); + exportColladaTriangles(meshNode, exportData, d, lodMeshName); + + // Extra info useful for COLLADAMaya importer (OpenCOLLADA) + TiXmlElement* extraGeoNode = new TiXmlElement("extra"); + libGeomsNode->LinkEndChild(extraGeoNode); + + TiXmlElement* extraGeoNodeTech = new TiXmlElement("technique"); + extraGeoNode->LinkEndChild(extraGeoNodeTech); + extraGeoNodeTech->SetAttribute("profile", "OpenCOLLADAMaya"); + + TiXmlElement* mayaNode2Id = new TiXmlElement("originalMayaNodeId"); + extraGeoNodeTech->LinkEndChild(mayaNode2Id); + mayaNode2Id->SetAttribute("sid", "originalMayaNodeId"); + TiXmlText* mayaIdMesh = new TiXmlText(avar("%s", lodMeshName)); + mayaNode2Id->LinkEndChild(mayaIdMesh); + + TiXmlElement* doubleSidedId = new TiXmlElement("double_sided"); + extraGeoNodeTech->LinkEndChild(doubleSidedId); + doubleSidedId->SetAttribute("sid", "double_sided"); + TiXmlText* doubleSideIdText = new TiXmlText("1"); + doubleSidedId->LinkEndChild(doubleSideIdText); + + TiXmlElement* paramExtraNode = new TiXmlElement("param"); + extraGeoNodeTech->LinkEndChild(paramExtraNode); + paramExtraNode->SetAttribute("sid", "colladaId"); + paramExtraNode->SetAttribute("type", "string"); + + TiXmlText* mayaParamMesh = new TiXmlText(avar("%s-mesh", lodMeshName)); + paramExtraNode->LinkEndChild(mayaParamMesh); + } + + //And now collisions + for (U32 d = 0; d < exportData.colMeshes.size(); d++) + { + const char* colMeshName = exportData.colMeshes[d].colMeshName; + + char colMeshId[256]; + dSprintf(colMeshId, 256, "%s-mesh", colMeshName); + + TiXmlElement* geometryNode = new TiXmlElement("geometry"); + libGeomsNode->LinkEndChild(geometryNode); + geometryNode->SetAttribute("id", colMeshId); + geometryNode->SetAttribute("name", colMeshName); + + TiXmlElement* meshNode = new TiXmlElement("mesh"); + geometryNode->LinkEndChild(meshNode); + + // Save out the vertices + TiXmlElement* vertsSourceNode = new TiXmlElement("source"); + meshNode->LinkEndChild(vertsSourceNode); + vertsSourceNode->SetAttribute("id", avar("%s-mesh-positions", colMeshName)); + + TiXmlElement* vertsNode = new TiXmlElement("float_array"); + vertsSourceNode->LinkEndChild(vertsNode); + vertsNode->SetAttribute("id", avar("%s-mesh-positions-array", colMeshName)); + vertsNode->SetAttribute("count", avar("%d", exportData.colMeshes[d].mesh.mPoints.size() * 3)); + + for (U32 i = 0; i < exportData.colMeshes[d].mesh.mPoints.size(); i++) + { + const Point3F& vert = exportData.colMeshes[d].mesh.mPoints[i]; + + TiXmlText* vertText = new TiXmlText(avar("%.4f %.4f %.4f ", vert.x, vert.y, vert.z)); + vertsNode->LinkEndChild(vertText); + } + + // Save the vertex accessor + TiXmlElement* vertsTechNode = new TiXmlElement("technique_common"); + vertsSourceNode->LinkEndChild(vertsTechNode); + + TiXmlElement* vertsAccNode = new TiXmlElement("accessor"); + vertsTechNode->LinkEndChild(vertsAccNode); + vertsAccNode->SetAttribute("source", avar("#%s-mesh-positions-array", colMeshName)); + vertsAccNode->SetAttribute("count", avar("%d", exportData.colMeshes[d].mesh.mPoints.size())); + vertsAccNode->SetAttribute("stride", "3"); + + TiXmlElement* vertsAccXNode = new TiXmlElement("param"); + vertsAccNode->LinkEndChild(vertsAccXNode); + vertsAccXNode->SetAttribute("name", "X"); + vertsAccXNode->SetAttribute("type", "float"); + + TiXmlElement* vertsAccYNode = new TiXmlElement("param"); + vertsAccNode->LinkEndChild(vertsAccYNode); + vertsAccYNode->SetAttribute("name", "Y"); + vertsAccYNode->SetAttribute("type", "float"); + + TiXmlElement* vertsAccZNode = new TiXmlElement("param"); + vertsAccNode->LinkEndChild(vertsAccZNode); + vertsAccZNode->SetAttribute("name", "Z"); + vertsAccZNode->SetAttribute("type", "float"); + + // Save out the normals + TiXmlElement* normalsSourceNode = new TiXmlElement("source"); + meshNode->LinkEndChild(normalsSourceNode); + normalsSourceNode->SetAttribute("id", avar("%s-mesh-normals", colMeshName)); + + TiXmlElement* normalsNode = new TiXmlElement("float_array"); + normalsSourceNode->LinkEndChild(normalsNode); + normalsNode->SetAttribute("id", avar("%s-mesh-normals-array", colMeshName)); + normalsNode->SetAttribute("count", avar("%d", exportData.colMeshes[d].mesh.mNormals.size() * 3)); + + for (U32 i = 0; i < exportData.colMeshes[d].mesh.mNormals.size(); i++) + { + const Point3F& normal = exportData.colMeshes[d].mesh.mNormals[i]; + + TiXmlText* normalText = new TiXmlText(avar("%.4f %.4f %.4f ", normal.x, normal.y, normal.z)); + normalsNode->LinkEndChild(normalText); + } + + // Save the normals accessor + TiXmlElement* normalsTechNode = new TiXmlElement("technique_common"); + normalsSourceNode->LinkEndChild(normalsTechNode); + + TiXmlElement* normalsAccNode = new TiXmlElement("accessor"); + normalsTechNode->LinkEndChild(normalsAccNode); + normalsAccNode->SetAttribute("source", avar("#%s-mesh-normals-array", colMeshName)); + normalsAccNode->SetAttribute("count", avar("%d", exportData.colMeshes[d].mesh.mNormals.size())); + normalsAccNode->SetAttribute("stride", "3"); + + TiXmlElement* normalsAccXNode = new TiXmlElement("param"); + normalsAccNode->LinkEndChild(normalsAccXNode); + normalsAccXNode->SetAttribute("name", "X"); + normalsAccXNode->SetAttribute("type", "float"); + + TiXmlElement* normalsAccYNode = new TiXmlElement("param"); + normalsAccNode->LinkEndChild(normalsAccYNode); + normalsAccYNode->SetAttribute("name", "Y"); + normalsAccYNode->SetAttribute("type", "float"); + + TiXmlElement* normalsAccZNode = new TiXmlElement("param"); + normalsAccNode->LinkEndChild(normalsAccZNode); + normalsAccZNode->SetAttribute("name", "Z"); + normalsAccZNode->SetAttribute("type", "float"); + + // Save out the uvs + TiXmlElement* uv0SourceNode = new TiXmlElement("source"); + meshNode->LinkEndChild(uv0SourceNode); + uv0SourceNode->SetAttribute("id", avar("%s-mesh-map-0", colMeshName)); + + TiXmlElement* uv0Node = new TiXmlElement("float_array"); + uv0SourceNode->LinkEndChild(uv0Node); + uv0Node->SetAttribute("id", avar("%s-mesh-map-0-array", colMeshName)); + uv0Node->SetAttribute("count", avar("%d", exportData.colMeshes[d].mesh.mUV0s.size() * 2)); + + for (U32 i = 0; i < exportData.colMeshes[d].mesh.mUV0s.size(); i++) + { + const Point2F& uv0 = exportData.colMeshes[d].mesh.mUV0s[i]; + + TiXmlText* uv0Text = new TiXmlText(avar("%.4f %.4f ", uv0.x, 1.0f - uv0.y)); // COLLADA uvs are upside down compared to Torque + uv0Node->LinkEndChild(uv0Text); + } + + // Save the uv0 accessor + TiXmlElement* uv0TechNode = new TiXmlElement("technique_common"); + uv0SourceNode->LinkEndChild(uv0TechNode); + + TiXmlElement* uv0AccNode = new TiXmlElement("accessor"); + uv0TechNode->LinkEndChild(uv0AccNode); + uv0AccNode->SetAttribute("source", avar("#%s-mesh-map-0-array", colMeshName)); + uv0AccNode->SetAttribute("count", avar("%d", exportData.colMeshes[d].mesh.mUV0s.size())); + uv0AccNode->SetAttribute("stride", "2"); + + TiXmlElement* uv0AccSNode = new TiXmlElement("param"); + uv0AccNode->LinkEndChild(uv0AccSNode); + uv0AccSNode->SetAttribute("name", "S"); + uv0AccSNode->SetAttribute("type", "float"); + + TiXmlElement* uv0AccTNode = new TiXmlElement("param"); + uv0AccNode->LinkEndChild(uv0AccTNode); + uv0AccTNode->SetAttribute("name", "T"); + uv0AccTNode->SetAttribute("type", "float"); + + // Define the vertices position array + TiXmlElement* verticesNode = new TiXmlElement("vertices"); + meshNode->LinkEndChild(verticesNode); + verticesNode->SetAttribute("id", avar("%s-mesh-vertices", colMeshName)); + + TiXmlElement* verticesInputNode = new TiXmlElement("input"); + verticesNode->LinkEndChild(verticesInputNode); + verticesInputNode->SetAttribute("semantic", "POSITION"); + verticesInputNode->SetAttribute("source", avar("#%s-mesh-positions", colMeshName)); + + Vector mapNames; + + //exportColladaTriangles(meshNode, exportData.detailLevels[d].mesh, lodMeshName, mapNames); + exportColladaCollisionTriangles(meshNode, exportData, d); + + // Extra info useful for COLLADAMaya importer (OpenCOLLADA) + TiXmlElement* extraGeoNode = new TiXmlElement("extra"); + libGeomsNode->LinkEndChild(extraGeoNode); + + TiXmlElement* extraGeoNodeTech = new TiXmlElement("technique"); + extraGeoNode->LinkEndChild(extraGeoNodeTech); + extraGeoNodeTech->SetAttribute("profile", "OpenCOLLADAMaya"); + + TiXmlElement* mayaNode2Id = new TiXmlElement("originalMayaNodeId"); + extraGeoNodeTech->LinkEndChild(mayaNode2Id); + mayaNode2Id->SetAttribute("sid", "originalMayaNodeId"); + TiXmlText* mayaIdMesh = new TiXmlText(avar("%s", colMeshName)); + mayaNode2Id->LinkEndChild(mayaIdMesh); + + TiXmlElement* doubleSidedId = new TiXmlElement("double_sided"); + extraGeoNodeTech->LinkEndChild(doubleSidedId); + doubleSidedId->SetAttribute("sid", "double_sided"); + TiXmlText* doubleSideIdText = new TiXmlText("1"); + doubleSidedId->LinkEndChild(doubleSideIdText); + + TiXmlElement* paramExtraNode = new TiXmlElement("param"); + extraGeoNodeTech->LinkEndChild(paramExtraNode); + paramExtraNode->SetAttribute("sid", "colladaId"); + paramExtraNode->SetAttribute("type", "string"); + + TiXmlText* mayaParamMesh = new TiXmlText(avar("%s-mesh", colMeshName)); + paramExtraNode->LinkEndChild(mayaParamMesh); + } +} + void ColladaUtils::exportColladaScene(TiXmlElement* rootNode, const String& meshName, const Vector& matNames) { TiXmlElement* libSceneNode = new TiXmlElement("library_visual_scenes"); @@ -1695,6 +2601,244 @@ void ColladaUtils::exportColladaScene(TiXmlElement* rootNode, const String& mesh instVisSceneNode->SetAttribute("url", "#RootNode"); } +void ColladaUtils::exportColladaScene(TiXmlElement* rootNode, const ExportData& exportData, const String& meshName) +{ + TiXmlElement* libSceneNode = new TiXmlElement("library_visual_scenes"); + rootNode->LinkEndChild(libSceneNode); + + TiXmlElement* visSceneNode = new TiXmlElement("visual_scene"); + libSceneNode->LinkEndChild(visSceneNode); + visSceneNode->SetAttribute("id", "RootNode"); + visSceneNode->SetAttribute("name", "RootNode"); + + for (U32 d = 0; d < exportData.detailLevels.size(); d++) + { + char lodMeshName[256]; + dSprintf(lodMeshName, 256, "%s%d", meshName.c_str(), exportData.detailLevels[d].size); + + TiXmlElement* nodeNode = new TiXmlElement("node"); + visSceneNode->LinkEndChild(nodeNode); + nodeNode->SetAttribute("id", lodMeshName); + nodeNode->SetAttribute("name", lodMeshName); + nodeNode->SetAttribute("type", "NODE"); + + TiXmlElement* instanceGeomNode = new TiXmlElement("instance_geometry"); + nodeNode->LinkEndChild(instanceGeomNode); + instanceGeomNode->SetAttribute("url", avar("#%s%d-mesh", meshName.c_str(), exportData.detailLevels[d].size)); + instanceGeomNode->SetAttribute("name", lodMeshName); + + TiXmlElement* bindMatNode = new TiXmlElement("bind_material"); + instanceGeomNode->LinkEndChild(bindMatNode); + + TiXmlElement* techniqueNode = new TiXmlElement("technique_common"); + bindMatNode->LinkEndChild(techniqueNode); + + // Bind the materials + for (U32 i = 0; i < exportData.detailLevels[d].materialRefList.size(); i++) + { + int matIdx; + exportData.detailLevels[d].materialRefList.tryGetValue(i, matIdx); + BaseMatInstance* baseInst = exportData.materials[matIdx]; + + Material* mat = dynamic_cast(baseInst->getMaterial()); + if (!mat) + continue; + + String matName; + + if (mat->getName() && mat->getName()[0]) + matName = mat->mMapTo; + + TiXmlElement* instMatNode = new TiXmlElement("instance_material"); + techniqueNode->LinkEndChild(instMatNode); + instMatNode->SetAttribute("symbol", avar("%s-material", matName.c_str())); + instMatNode->SetAttribute("target", avar("#%s-material", matName.c_str())); + TiXmlElement* bindVertexNode = new TiXmlElement("bind_vertex_input"); + instMatNode->LinkEndChild(bindVertexNode); + //bindVertexNode->SetAttribute("semantic", avar("%s-mesh-map-0", meshName.c_str())); + bindVertexNode->SetAttribute("semantic", "UVMap"); + bindVertexNode->SetAttribute("input_semantic", "TEXCOORD"); + bindVertexNode->SetAttribute("input_set", "0"); + } + + // Extra info useful for COLLADAMax importer (OpenCOLLADA) + TiXmlElement* extraInsGeoNode = new TiXmlElement("extra"); + nodeNode->LinkEndChild(extraInsGeoNode); + + TiXmlElement* extraInsGeoTechNode = new TiXmlElement("technique"); + extraInsGeoNode->LinkEndChild(extraInsGeoTechNode); + extraInsGeoTechNode->SetAttribute("profile", "OpenCOLLADA"); + + TiXmlElement* castShadowsNode = new TiXmlElement("cast_shadows"); + extraInsGeoTechNode->LinkEndChild(castShadowsNode); + castShadowsNode->SetAttribute("sid", "cast_shadows"); + castShadowsNode->SetAttribute("type", "bool"); + + TiXmlText* castShadowsText = new TiXmlText("1"); + castShadowsNode->LinkEndChild(castShadowsText); + + //----------------------------- + TiXmlElement* receiveShadowsNode = new TiXmlElement("receive_shadows"); + extraInsGeoTechNode->LinkEndChild(receiveShadowsNode); + receiveShadowsNode->SetAttribute("sid", "receive_shadows"); + receiveShadowsNode->SetAttribute("type", "bool"); + + TiXmlText* receiveShadowsText = new TiXmlText("1"); + receiveShadowsNode->LinkEndChild(receiveShadowsText); + + //----------------------------- + TiXmlElement* primaryVisibiltyNode = new TiXmlElement("primary_visibility"); + extraInsGeoTechNode->LinkEndChild(primaryVisibiltyNode); + primaryVisibiltyNode->SetAttribute("sid", "primary_visibility"); + primaryVisibiltyNode->SetAttribute("type", "int"); + + TiXmlText* primaryVisibiltyText = new TiXmlText("1"); + primaryVisibiltyNode->LinkEndChild(primaryVisibiltyText); + + //----------------------------- + TiXmlElement* secondaryVisibilityNode = new TiXmlElement("secondary_visibility"); + extraInsGeoTechNode->LinkEndChild(secondaryVisibilityNode); + secondaryVisibilityNode->SetAttribute("sid", "secondary_visibility"); + secondaryVisibilityNode->SetAttribute("type", "int"); + + TiXmlText* secondaryVisibilityText = new TiXmlText("1"); + secondaryVisibilityNode->LinkEndChild(secondaryVisibilityText); + + // Extra info useful for COLLADAMaya importer (OpenCOLLADA) + TiXmlElement* extra2InsGeoNode = new TiXmlElement("extra"); + nodeNode->LinkEndChild(extra2InsGeoNode); + + TiXmlElement* extra2InsGeoTechNode = new TiXmlElement("technique"); + extra2InsGeoNode->LinkEndChild(extra2InsGeoTechNode); + extra2InsGeoTechNode->SetAttribute("profile", "OpenCOLLADAMaya"); + + TiXmlElement* mayaNodeId = new TiXmlElement("originalMayaNodeId"); + extra2InsGeoTechNode->LinkEndChild(mayaNodeId); + mayaNodeId->SetAttribute("sid", "originalMayaNodeId"); + mayaNodeId->SetAttribute("type", "string"); + + TiXmlText* mayaNodeIdMesh = new TiXmlText(lodMeshName); + mayaNodeId->LinkEndChild(mayaNodeIdMesh); + + TiXmlElement* paramExtraNode = new TiXmlElement("param"); + extra2InsGeoTechNode->LinkEndChild(paramExtraNode); + paramExtraNode->SetAttribute("sid", "colladaId"); + paramExtraNode->SetAttribute("type", "string"); + + TiXmlText* mayaParamMesh = new TiXmlText(lodMeshName); + paramExtraNode->LinkEndChild(mayaParamMesh); + } + + //Collisions + for (U32 d = 0; d < exportData.colMeshes.size(); d++) + { + const char* colMeshName = exportData.colMeshes[d].colMeshName; + + TiXmlElement* nodeNode = new TiXmlElement("node"); + visSceneNode->LinkEndChild(nodeNode); + nodeNode->SetAttribute("id", colMeshName); + nodeNode->SetAttribute("name", colMeshName); + nodeNode->SetAttribute("type", "NODE"); + + TiXmlElement* instanceGeomNode = new TiXmlElement("instance_geometry"); + nodeNode->LinkEndChild(instanceGeomNode); + instanceGeomNode->SetAttribute("url", avar("#%s-mesh", colMeshName)); + instanceGeomNode->SetAttribute("name", colMeshName); + + TiXmlElement* bindMatNode = new TiXmlElement("bind_material"); + instanceGeomNode->LinkEndChild(bindMatNode); + + TiXmlElement* techniqueNode = new TiXmlElement("technique_common"); + bindMatNode->LinkEndChild(techniqueNode); + + TiXmlElement* instMatNode = new TiXmlElement("instance_material"); + techniqueNode->LinkEndChild(instMatNode); + instMatNode->SetAttribute("symbol", avar("%s-material", colMeshName)); + instMatNode->SetAttribute("target", avar("#%s-material", colMeshName)); + TiXmlElement* bindVertexNode = new TiXmlElement("bind_vertex_input"); + instMatNode->LinkEndChild(bindVertexNode); + //bindVertexNode->SetAttribute("semantic", avar("%s-mesh-map-0", meshName.c_str())); + bindVertexNode->SetAttribute("semantic", "UVMap"); + bindVertexNode->SetAttribute("input_semantic", "TEXCOORD"); + bindVertexNode->SetAttribute("input_set", "0"); + + // Extra info useful for COLLADAMax importer (OpenCOLLADA) + TiXmlElement* extraInsGeoNode = new TiXmlElement("extra"); + nodeNode->LinkEndChild(extraInsGeoNode); + + TiXmlElement* extraInsGeoTechNode = new TiXmlElement("technique"); + extraInsGeoNode->LinkEndChild(extraInsGeoTechNode); + extraInsGeoTechNode->SetAttribute("profile", "OpenCOLLADA"); + + TiXmlElement* castShadowsNode = new TiXmlElement("cast_shadows"); + extraInsGeoTechNode->LinkEndChild(castShadowsNode); + castShadowsNode->SetAttribute("sid", "cast_shadows"); + castShadowsNode->SetAttribute("type", "bool"); + + TiXmlText* castShadowsText = new TiXmlText("1"); + castShadowsNode->LinkEndChild(castShadowsText); + + //----------------------------- + TiXmlElement* receiveShadowsNode = new TiXmlElement("receive_shadows"); + extraInsGeoTechNode->LinkEndChild(receiveShadowsNode); + receiveShadowsNode->SetAttribute("sid", "receive_shadows"); + receiveShadowsNode->SetAttribute("type", "bool"); + + TiXmlText* receiveShadowsText = new TiXmlText("1"); + receiveShadowsNode->LinkEndChild(receiveShadowsText); + + //----------------------------- + TiXmlElement* primaryVisibiltyNode = new TiXmlElement("primary_visibility"); + extraInsGeoTechNode->LinkEndChild(primaryVisibiltyNode); + primaryVisibiltyNode->SetAttribute("sid", "primary_visibility"); + primaryVisibiltyNode->SetAttribute("type", "int"); + + TiXmlText* primaryVisibiltyText = new TiXmlText("1"); + primaryVisibiltyNode->LinkEndChild(primaryVisibiltyText); + + //----------------------------- + TiXmlElement* secondaryVisibilityNode = new TiXmlElement("secondary_visibility"); + extraInsGeoTechNode->LinkEndChild(secondaryVisibilityNode); + secondaryVisibilityNode->SetAttribute("sid", "secondary_visibility"); + secondaryVisibilityNode->SetAttribute("type", "int"); + + TiXmlText* secondaryVisibilityText = new TiXmlText("1"); + secondaryVisibilityNode->LinkEndChild(secondaryVisibilityText); + + // Extra info useful for COLLADAMaya importer (OpenCOLLADA) + TiXmlElement* extra2InsGeoNode = new TiXmlElement("extra"); + nodeNode->LinkEndChild(extra2InsGeoNode); + + TiXmlElement* extra2InsGeoTechNode = new TiXmlElement("technique"); + extra2InsGeoNode->LinkEndChild(extra2InsGeoTechNode); + extra2InsGeoTechNode->SetAttribute("profile", "OpenCOLLADAMaya"); + + TiXmlElement* mayaNodeId = new TiXmlElement("originalMayaNodeId"); + extra2InsGeoTechNode->LinkEndChild(mayaNodeId); + mayaNodeId->SetAttribute("sid", "originalMayaNodeId"); + mayaNodeId->SetAttribute("type", "string"); + + TiXmlText* mayaNodeIdMesh = new TiXmlText(colMeshName); + mayaNodeId->LinkEndChild(mayaNodeIdMesh); + + TiXmlElement* paramExtraNode = new TiXmlElement("param"); + extra2InsGeoTechNode->LinkEndChild(paramExtraNode); + paramExtraNode->SetAttribute("sid", "colladaId"); + paramExtraNode->SetAttribute("type", "string"); + + TiXmlText* mayaParamMesh = new TiXmlText(colMeshName); + paramExtraNode->LinkEndChild(mayaParamMesh); + } + //----------------------------- + + TiXmlElement* sceneNode = new TiXmlElement("scene"); + rootNode->LinkEndChild(sceneNode); + + TiXmlElement* instVisSceneNode = new TiXmlElement("instance_visual_scene"); + sceneNode->LinkEndChild(instVisSceneNode); + instVisSceneNode->SetAttribute("url", "#RootNode"); +} + void ColladaUtils::exportToCollada(const Torque::Path& colladaFile, const OptimizedPolyList& mesh, const String& meshName) { // Get the mesh name @@ -1728,11 +2872,14 @@ void ColladaUtils::exportToCollada(const Torque::Path& colladaFile, const Optimi exportColladaMaterials(rootNode, mesh, mapNames, colladaFile); + S32 suffix; + String baseMeshName = String::GetTrailingNumber(outMeshName, suffix); + // Save out our geometry - exportColladaMesh(rootNode, mesh, outMeshName, mapNames); + exportColladaMesh(rootNode, mesh, baseMeshName, mapNames); // Save out our scene nodes - exportColladaScene(rootNode, outMeshName, mapNames); + exportColladaScene(rootNode, baseMeshName, mapNames); // Write out the actual Collada file char fullPath[MAX_PATH_LENGTH]; @@ -1740,4 +2887,156 @@ void ColladaUtils::exportToCollada(const Torque::Path& colladaFile, const Optimi if (!doc.SaveFile(fullPath)) Con::errorf("ColladaUtils::exportToCollada(): Unable to export to %s", fullPath); +} + +void ColladaUtils::exportToCollada(const Torque::Path& colladaFile, const ExportData& exportData) +{ + // Get the mesh name + String outMeshName = colladaFile.getFileName(); + + // The XML document that will hold all of our data + TiXmlDocument doc; + + // Add a standard XML declaration to the top + TiXmlDeclaration* xmlDecl = new TiXmlDeclaration("1.0", "utf-8", ""); + doc.LinkEndChild(xmlDecl); + + // Create our Collada root node and populate a couple standard attributes + TiXmlElement* rootNode = new TiXmlElement("COLLADA"); + rootNode->SetAttribute("xmlns", "http://www.collada.org/2005/11/COLLADASchema"); + rootNode->SetAttribute("version", "1.4.1"); + //rootNode->SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); //T3D Collada loader complaint about this. + + + // Add the root node to the document + doc.LinkEndChild(rootNode); + + // Save out our header info + exportColladaHeader(rootNode); + + // Save out the materials + Vector mapNames; + + exportColladaMaterials(rootNode, exportData, colladaFile); + + S32 suffix; + String baseMeshName = String::GetTrailingNumber(outMeshName, suffix); + + // Save out our geometry + exportColladaMesh(rootNode, exportData, baseMeshName); + + // Save out our scene nodes + exportColladaScene(rootNode, exportData, baseMeshName); + + // Write out the actual Collada file + char fullPath[MAX_PATH_LENGTH]; + Platform::makeFullPathName(colladaFile.getFullPath(), fullPath, MAX_PATH_LENGTH); + + if (!doc.SaveFile(fullPath)) + Con::errorf("ColladaUtils::exportToCollada(): Unable to export to %s", fullPath); +} + +void ColladaUtils::ExportData::processData() +{ + //This pref dictates if we 'backfill' lower LODs with higher ones if any given mesh being exported lacks that level. + //For example, if there are 2 meshes, and one has 500, 200, 100 and the other has 500 and 200 - if this setting is on, the second mesh + //will backfill the 200 to the 100 so it has all levels filled. If it's off, the second mesh will not render at the 100 level + bool fillLowDetailLevels = dAtob(Con::getVariable("$exportMesh::fillLowDetailLevels", "1")); + + S32 numDetailLevels = numberOfDetailLevels(); + + detailLevels.clear(); + detailLevels.setSize(numDetailLevels); + + for (U32 m = 0; m < meshData.size(); ++m) + { + for (U32 i = 0; i < numDetailLevels; ++i) + { + //Get our target size + S32 targetDetailLevelSize = getDetailLevelSize(i); + + //alright, step through each meshdata and propagate the polyList info 'up' to fill + detailLevel* curDetail = &detailLevels[i]; + + curDetail->size = targetDetailLevelSize; + + //Do we have a detail level for this? + S32 detailLevelIdx = -1; + + for (S32 mdl = i; mdl >= 0; mdl--) + { + //walk backwards as needed to find our first valid detail level for this mesh. if we find none, just move on + S32 testDetailLevelSize = getDetailLevelSize(mdl); + detailLevelIdx = meshData[m].hasDetailLevel(testDetailLevelSize); + + if (detailLevelIdx != -1) + break; + } + + if (detailLevelIdx == -1) + { + //found nothing backwards, so lets check if we're configured to back-fill the first detail levels + if (fillLowDetailLevels) + { + //if so, search forward, find the first valid detail and fill it in + for (S32 mdl = 0; mdl < numDetailLevels; mdl++) + { + //walk backwards as needed to find our first valid detail level for this mesh. if we find none, just move on + S32 testDetailLevelSize = getDetailLevelSize(mdl); + detailLevelIdx = meshData[m].hasDetailLevel(testDetailLevelSize); + + if (detailLevelIdx != -1) + break; + } + } + } + + //If we found the detail level index, go ahead and build out the data for it + if (detailLevelIdx != -1) + { + curDetail->mesh.setTransform(&meshData[m].meshTransform, meshData[m].scale); + curDetail->mesh.setObject(meshData[m].originatingObject); + + if (meshData[m].shapeInst != nullptr) + { + + if (!meshData[m].shapeInst->buildPolyList(&curDetail->mesh, detailLevelIdx)) + { + Con::errorf("TSStatic::buildExportPolyList - failed to build polylist for LOD %i", i); + continue; + } + } + else + { + //special handling classes + ConvexShape* convexShp = dynamic_cast(meshData[m].originatingObject); + if (convexShp != nullptr) + { + if (!convexShp->buildPolyList(PLC_Export, &curDetail->mesh, meshData[m].originatingObject->getWorldBox(), meshData[m].originatingObject->getWorldSphere())) + { + Con::errorf("TSStatic::buildExportPolyList - failed to build ConvexShape polylist for LOD %i", i); + continue; + } + } + } + + //lastly, get material + for (U32 m = 0; m < curDetail->mesh.mMaterialList.size(); m++) + { + S32 matIdx = hasMaterialInstance(curDetail->mesh.mMaterialList[m]); + + if (matIdx == -1) + { + //cool, haven't already got this material, so lets store it out + materials.push_back(curDetail->mesh.mMaterialList[m]); + curDetail->materialRefList.insert(m, materials.size() - 1); + } + else + { + curDetail->materialRefList.insert(m, matIdx); + } + } + } + } + } } \ No newline at end of file diff --git a/Engine/source/ts/collada/colladaUtils.h b/Engine/source/ts/collada/colladaUtils.h index 04592126e..144a62c7b 100644 --- a/Engine/source/ts/collada/colladaUtils.h +++ b/Engine/source/ts/collada/colladaUtils.h @@ -50,6 +50,10 @@ #include "console/console.h" #endif +#ifndef _TSSHAPEINSTANCE_H_ +#include "ts/tsShapeInstance.h" +#endif + #include "platform/tmm_off.h" #include "dae.h" @@ -63,6 +67,7 @@ #include "dom/domCOLLADA.h" #include "platform/tmm_on.h" +#include "core/strings/findMatch.h" namespace ColladaUtils { @@ -100,7 +105,7 @@ namespace ColladaUtils { upAxis = UPAXISTYPE_COUNT; unit = -1.0f; - lodType = DetectDTS; + lodType = TrailingNumber; singleDetailSize = 2; matNamePrefix = ""; alwaysImport = ""; @@ -117,6 +122,126 @@ namespace ColladaUtils ImportOptions& getOptions(); + struct ExportData + { + struct detailLevel + { + OptimizedPolyList mesh; + S32 size; + Map materialRefList; + }; + + struct meshLODData + { + Vector meshDetailLevels; + TSShapeInstance* shapeInst; + MatrixF meshTransform; + SceneObject* originatingObject; + + Point3F scale; + + S32 hasDetailLevel(S32 size) + { + for (U32 i = 0; i < meshDetailLevels.size(); ++i) + { + U32 mdlSize = meshDetailLevels[i].size; + + if (mdlSize == size) + return i; + } + + return -1; + } + + meshLODData() : shapeInst(nullptr), meshTransform(true), originatingObject(nullptr), scale(0) + {} + }; + + struct colMesh + { + OptimizedPolyList mesh; + String colMeshName; + }; + + Vector detailLevels; + Vector meshData; + Vector colMeshes; + Vector materials; + + void processData(); + + S32 hasDetailLevel(U32 dl) + { + for (U32 i = 0; i < detailLevels.size(); i++) + { + if (detailLevels[i].size == dl) + return i; + } + + return -1; + } + + S32 hasMaterialInstance(BaseMatInstance* matInst) + { + for (U32 i = 0; i < materials.size(); i++) + { + if (materials[i] == matInst) + return i; + } + + return -1; + } + + S32 numberOfDetailLevels() + { + Vector detailLevelIdxs; + + for (U32 i = 0; i < meshData.size(); ++i) + { + for (U32 d = 0; d < meshData[i].meshDetailLevels.size(); ++d) + { + detailLevelIdxs.push_back_unique(meshData[i].meshDetailLevels[d].size); + } + } + + return detailLevelIdxs.size(); + } + + static S32 _Sort(const S32 *p1, const S32 *p2) + { + S32 e1 = (*p1); + S32 e2 = (*p2); + + if (e1 > e2) + return 1; + else if (e1 < e2) + return -1; + + return 0; + } + + S32 getDetailLevelSize(U32 detailIdx) + { + Vector detailLevelIdxs; + + for (U32 i = 0; i < meshData.size(); ++i) + { + for (U32 d = 0; d < meshData[i].meshDetailLevels.size(); ++d) + { + S32 mdlSize = meshData[i].meshDetailLevels[d].size; + detailLevelIdxs.push_back_unique(mdlSize); + } + } + + if (detailIdx >= detailLevelIdxs.size()) + return -1; + + detailLevelIdxs.sort(&_Sort); + + return detailLevelIdxs[detailIdx]; + } + }; + void convertTransform(MatrixF& m); void collapsePath(std::string& path); @@ -139,8 +264,15 @@ namespace ColladaUtils void exportColladaMesh(TiXmlElement* rootNode, const OptimizedPolyList& mesh, const String& meshName, const Vector& matNames); void exportColladaScene(TiXmlElement* rootNode, const String& meshName, const Vector& matNames); + void exportColladaMaterials(TiXmlElement* rootNode, const ExportData& exportData, const Torque::Path& colladaFile); + void exportColladaMesh(TiXmlElement* rootNode, const ExportData& exportData, const String& meshName); + void exportColladaCollisionTriangles(TiXmlElement* meshNode, const ExportData& exportData, const U32 collisionIdx); + void exportColladaTriangles(TiXmlElement* meshNode, const ExportData& exportData, const U32 detailLevel, const String& meshName); + void exportColladaScene(TiXmlElement* rootNode, const ExportData& exportData, const String& meshName); + // Export an OptimizedPolyList to a simple Collada file void exportToCollada(const Torque::Path& colladaFile, const OptimizedPolyList& mesh, const String& meshName = String::EmptyString); + void exportToCollada(const Torque::Path& colladaFile, const ExportData& exportData); }; //----------------------------------------------------------------------------- @@ -535,7 +667,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTrian continue; domUint* pSrcData = &(P->getValue()[0]); - S32 numTriangles = (P->getValue().getCount() / stride) - 2; + size_t numTriangles = (P->getValue().getCount() / stride) - 2; // Convert the strip back to a triangle list domUint* v0 = pSrcData; @@ -576,7 +708,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTriangl continue; domUint* pSrcData = &(P->getValue()[0]); - S32 numTriangles = (P->getValue().getCount() / stride) - 2; + size_t numTriangles = (P->getValue().getCount() / stride) - 2; // Convert the fan back to a triangle list domUint* v0 = pSrcData + stride; @@ -608,7 +740,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTriang continue; domUint* pSrcData = &(P->getValue()[0]); - S32 numPoints = P->getValue().getCount() / stride; + size_t numPoints = P->getValue().getCount() / stride; // Use a simple tri-fan (centered at the first point) method of // converting the polygon to triangles. diff --git a/Engine/source/ts/tsShapeConstruct.cpp b/Engine/source/ts/tsShapeConstruct.cpp index 24fb85726..c77802895 100644 --- a/Engine/source/ts/tsShapeConstruct.cpp +++ b/Engine/source/ts/tsShapeConstruct.cpp @@ -135,6 +135,20 @@ IMPLEMENT_CONOBJECT(TSShapeConstructor); TSShapeConstructor::TSShapeConstructor() : mShapePath(""), mLoadingShape(false) { + mOptions.upAxis = UPAXISTYPE_COUNT; + mOptions.unit = -1.0f; + mOptions.lodType = ColladaUtils::ImportOptions::TrailingNumber; + mOptions.singleDetailSize = 2; + mOptions.matNamePrefix = ""; + mOptions.alwaysImport = ""; + mOptions.neverImport = String(Con::getVariable("$TSShapeConstructor::neverImport")); + mOptions.alwaysImportMesh = ""; + mOptions.neverImportMesh = String(Con::getVariable("$TSShapeConstructor::neverImportMesh")); + mOptions.ignoreNodeScale = false; + mOptions.adjustCenter = false; + mOptions.adjustFloor = false; + mOptions.forceUpdateMaterials = false; + mOptions.useDiffuseNames = false; mShape = NULL; } diff --git a/Engine/source/util/messaging/eventManager.cpp b/Engine/source/util/messaging/eventManager.cpp index f39bf13b0..0edfa98fc 100644 --- a/Engine/source/util/messaging/eventManager.cpp +++ b/Engine/source/util/messaging/eventManager.cpp @@ -288,8 +288,9 @@ bool EventManager::subscribe(SimObject *callbackObj, const char* event, const ch } else { - cb = new char[dStrlen(callback) + 1]; - dStrcpy(cb, callback); + dsize_t cbLen = dStrlen(callback) + 1; + cb = new char[cbLen]; + dStrcpy(cb, callback, cbLen); } // Create the subscriber object. diff --git a/Engine/source/util/undo.cpp b/Engine/source/util/undo.cpp index fd23033fa..7ea0acc8c 100644 --- a/Engine/source/util/undo.cpp +++ b/Engine/source/util/undo.cpp @@ -545,8 +545,9 @@ DefineConsoleMethod(UndoManager, getNextUndoName, const char *, (),, "UndoManage const char *name = object->getNextUndoName(); if(!name) return NULL; - char *ret = Con::getReturnBuffer(dStrlen(name) + 1); - dStrcpy(ret, name); + dsize_t retLen = dStrlen(name) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, name, retLen); return ret; } @@ -556,8 +557,9 @@ DefineConsoleMethod(UndoManager, getNextRedoName, const char *, (),, "UndoManage const char *name = object->getNextRedoName(); if(!name) return NULL; - char *ret = Con::getReturnBuffer(dStrlen(name) + 1); - dStrcpy(ret, name); + dsize_t retLen = dStrlen(name) + 1; + char *ret = Con::getReturnBuffer(retLen); + dStrcpy(ret, name, retLen); return ret; } diff --git a/Templates/BaseGame/game/core/console/console.gui b/Templates/BaseGame/game/core/console/console.gui index 8c6c7f63a..c2f21eba9 100644 --- a/Templates/BaseGame/game/core/console/console.gui +++ b/Templates/BaseGame/game/core/console/console.gui @@ -1,51 +1,191 @@ -new GuiControl(ConsoleDlg) { - profile = "GuiDefaultProfile"; +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(ConsoleDlg) { + position = "0 0"; + extent = "1024 768"; + minExtent = "8 8"; horizSizing = "right"; vertSizing = "bottom"; - position = "0 0"; - extent = "640 480"; - minExtent = "8 8"; + profile = "GuiDefaultProfile"; visible = "1"; - helpTag = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + helpTag = "0"; new GuiConsoleEditCtrl(ConsoleEntry) { - profile = "ConsoleTextEditProfile"; - horizSizing = "width"; - vertSizing = "top"; - position = "0 462"; - extent = "640 18"; - minExtent = "8 8"; - visible = "1"; - altCommand = "ConsoleEntry::eval();"; - helpTag = "0"; - maxLength = "255"; + useSiblingScroller = "1"; historySize = "40"; - password = "0"; tabComplete = "0"; sinkAllKeyEvents = "1"; - useSiblingScroller = "1"; + password = "0"; + passwordMask = "*"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 750"; + extent = "1024 18"; + minExtent = "8 8"; + horizSizing = "width"; + vertSizing = "top"; + profile = "ConsoleTextEditProfile"; + visible = "1"; + active = "1"; + altCommand = "ConsoleEntry::eval();"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiContainer() { + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "1 728"; + extent = "1024 22"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "top"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiBitmapCtrl() { + bitmap = "data/ui/art/hudfill.png"; + color = "255 255 255 255"; + wrap = "0"; + position = "0 0"; + extent = "1024 22"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl(ConsoleDlgErrorFilterBtn) { + text = "Errors"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "2 2"; + extent = "113 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl(ConsoleDlgWarnFilterBtn) { + text = "Warnings"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "119 2"; + extent = "113 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl(ConsoleDlgNormalFilterBtn) { + text = "Normal Messages"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "236 2"; + extent = "113 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; new GuiScrollCtrl() { - internalName = "Scroll"; - profile = "ConsoleScrollProfile"; - horizSizing = "width"; - vertSizing = "height"; - position = "0 0"; - extent = "640 462"; - minExtent = "8 8"; - visible = "1"; - helpTag = "0"; willFirstRespond = "1"; hScrollBar = "alwaysOn"; vScrollBar = "alwaysOn"; - lockHorizScroll = "false"; - lockVertScroll = "false"; + lockHorizScroll = "0"; + lockVertScroll = "0"; constantThumbHeight = "0"; childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 0"; + extent = "1024 730"; + minExtent = "8 8"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ConsoleScrollProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "Scroll"; + canSave = "1"; + canSaveDynamicFields = "0"; - new GuiConsole( ConsoleMessageLogView ) { - profile = "GuiConsoleProfile"; - position = "0 0"; - }; + new GuiConsole(ConsoleMessageLogView) { + position = "1 1"; + extent = "622 324"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiConsoleProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; }; + }; }; +//--- OBJECT WRITE END --- \ No newline at end of file diff --git a/Templates/BaseGame/game/core/console/main.cs b/Templates/BaseGame/game/core/console/main.cs index b36dafd24..3d89234b8 100644 --- a/Templates/BaseGame/game/core/console/main.cs +++ b/Templates/BaseGame/game/core/console/main.cs @@ -99,6 +99,15 @@ function ConsoleDlg::showWindow(%this) %this-->Scroll.setVisible(true); } +function ConsoleDlg::onWake(%this) +{ + ConsoleDlgErrorFilterBtn.setStateOn(ConsoleMessageLogView.getErrorFilter()); + ConsoleDlgWarnFilterBtn.setStateOn(ConsoleMessageLogView.getWarnFilter()); + ConsoleDlgNormalFilterBtn.setStateOn(ConsoleMessageLogView.getNormalFilter()); + + ConsoleMessageLogView.refresh(); +} + function ConsoleDlg::setAlpha( %this, %alpha) { if (%alpha $= "") @@ -106,3 +115,26 @@ function ConsoleDlg::setAlpha( %this, %alpha) else ConsoleScrollProfile.fillColor = getWords($ConsoleDefaultFillColor, 0, 2) SPC %alpha * 255.0; } + +function ConsoleDlgErrorFilterBtn::onClick(%this) +{ + ConsoleMessageLogView.toggleErrorFilter(); +} + +function ConsoleDlgWarnFilterBtn::onClick(%this) +{ + + ConsoleMessageLogView.toggleWarnFilter(); +} + +function ConsoleDlgNormalFilterBtn::onClick(%this) +{ + ConsoleMessageLogView.toggleNormalFilter(); +} + +function ConsoleMessageLogView::onNewMessage(%this, %errorCount, %warnCount, %normalCount) +{ + ConsoleDlgErrorFilterBtn.setText("(" @ %errorCount @ ") Errors"); + ConsoleDlgWarnFilterBtn.setText("(" @ %warnCount @ ") Warnings"); + ConsoleDlgNormalFilterBtn.setText("(" @ %normalCount @ ") Messages"); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/shaders/postFX/fxaa/fxaaV.hlsl b/Templates/BaseGame/game/core/shaders/postFX/fxaa/fxaaV.hlsl index 3bef0a4d3..f2974c587 100644 --- a/Templates/BaseGame/game/core/shaders/postFX/fxaa/fxaaV.hlsl +++ b/Templates/BaseGame/game/core/shaders/postFX/fxaa/fxaaV.hlsl @@ -21,7 +21,7 @@ //----------------------------------------------------------------------------- #include "./../../torque.hlsl" -#include "./../postFX.hlsl" +#include "./../postFx.hlsl" struct VertToPix { diff --git a/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_Blur_P.hlsl b/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_Blur_P.hlsl index a47261397..5bdf9a77d 100644 --- a/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_Blur_P.hlsl +++ b/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_Blur_P.hlsl @@ -20,7 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "../../ShaderModelAutoGen.hlsl" +#include "../../shaderModelAutoGen.hlsl" #include "./../postFx.hlsl" TORQUE_UNIFORM_SAMPLER2D(occludeMap, 0); diff --git a/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_P.hlsl b/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_P.hlsl index 67365e846..ff31a4b8b 100644 --- a/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_P.hlsl +++ b/Templates/BaseGame/game/core/shaders/postFX/ssao/SSAO_P.hlsl @@ -20,7 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "../../ShaderModelAutoGen.hlsl" +#include "../../shaderModelAutoGen.hlsl" #include "./../postFx.hlsl" #define DOSMALL diff --git a/Templates/Full/game/art/shapes/weapons/Grenade/materials.cs b/Templates/Full/game/art/shapes/weapons/Grenade/materials.cs index 569f28ed0..ba26267da 100644 --- a/Templates/Full/game/art/shapes/weapons/Grenade/materials.cs +++ b/Templates/Full/game/art/shapes/weapons/Grenade/materials.cs @@ -49,11 +49,11 @@ singleton Material(debri_debris) { mapTo = "debris"; diffuseColor[0] = "0.7 0.7 0.7 1"; - diffuseMap[0] = "rock_diffuse.dds"; - normalMap[0] = "rock_normals.dds"; + diffuseMap[0] = "rock_d"; + normalMap[0] = "rock_n"; + specularMap[0] = "rock_s"; specular[0] = "1 1 1 0"; - specularPower[0] = "50"; - specularMap[0] = "rock_specular.dds"; + specularPower[0] = "50"; castShadows = "0"; translucentBlendOp = "None"; materialTag0 = "Weapon"; diff --git a/Templates/Full/game/art/shapes/weapons/Grenade/rock_diffuse.DDS b/Templates/Full/game/art/shapes/weapons/Grenade/rock_d.dds similarity index 100% rename from Templates/Full/game/art/shapes/weapons/Grenade/rock_diffuse.DDS rename to Templates/Full/game/art/shapes/weapons/Grenade/rock_d.dds diff --git a/Templates/Full/game/art/shapes/weapons/Grenade/rock_normals.DDS b/Templates/Full/game/art/shapes/weapons/Grenade/rock_n.dds similarity index 100% rename from Templates/Full/game/art/shapes/weapons/Grenade/rock_normals.DDS rename to Templates/Full/game/art/shapes/weapons/Grenade/rock_n.dds diff --git a/Templates/Full/game/art/shapes/weapons/Grenade/rock_specular.DDS b/Templates/Full/game/art/shapes/weapons/Grenade/rock_s.dds similarity index 100% rename from Templates/Full/game/art/shapes/weapons/Grenade/rock_specular.DDS rename to Templates/Full/game/art/shapes/weapons/Grenade/rock_s.dds diff --git a/Templates/Full/game/core/art/gui/console.gui b/Templates/Full/game/core/art/gui/console.gui index 70e5fb61b..fd3a2c0e5 100644 --- a/Templates/Full/game/core/art/gui/console.gui +++ b/Templates/Full/game/core/art/gui/console.gui @@ -1,54 +1,192 @@ //--- OBJECT WRITE BEGIN --- %guiContent = new GuiControl(ConsoleDlg) { - profile = "GuiDefaultProfile"; + position = "0 0"; + extent = "1024 768"; + minExtent = "8 8"; horizSizing = "right"; vertSizing = "bottom"; - position = "0 0"; - extent = "640 480"; - minExtent = "8 8"; + profile = "GuiDefaultProfile"; visible = "1"; - helpTag = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + helpTag = "0"; new GuiConsoleEditCtrl(ConsoleEntry) { - profile = "ConsoleTextEditProfile"; - horizSizing = "width"; - vertSizing = "top"; - position = "0 462"; - extent = "640 18"; - minExtent = "8 8"; - visible = "1"; - altCommand = "ConsoleEntry::eval();"; - helpTag = "0"; - maxLength = "255"; + useSiblingScroller = "1"; historySize = "40"; - password = "0"; tabComplete = "0"; sinkAllKeyEvents = "1"; - useSiblingScroller = "1"; + password = "0"; + passwordMask = "*"; + maxLength = "255"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 750"; + extent = "1024 18"; + minExtent = "8 8"; + horizSizing = "width"; + vertSizing = "top"; + profile = "ConsoleTextEditProfile"; + visible = "1"; + active = "1"; + altCommand = "ConsoleEntry::eval();"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiContainer() { + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "1 728"; + extent = "1024 22"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "top"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiBitmapCtrl() { + bitmap = "data/ui/art/hudfill.png"; + color = "255 255 255 255"; + wrap = "0"; + position = "0 0"; + extent = "1024 22"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl(ConsoleDlgErrorFilterBtn) { + text = "Errors"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "2 2"; + extent = "113 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl(ConsoleDlgWarnFilterBtn) { + text = "Warnings"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "119 2"; + extent = "113 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiCheckBoxCtrl(ConsoleDlgNormalFilterBtn) { + text = "Normal Messages"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "236 2"; + extent = "113 20"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; new GuiScrollCtrl() { - internalName = "Scroll"; - profile = "ConsoleScrollProfile"; - horizSizing = "width"; - vertSizing = "height"; - position = "0 0"; - extent = "640 462"; - minExtent = "8 8"; - visible = "1"; - helpTag = "0"; willFirstRespond = "1"; hScrollBar = "alwaysOn"; vScrollBar = "alwaysOn"; - lockHorizScroll = "false"; - lockVertScroll = "false"; + lockHorizScroll = "0"; + lockVertScroll = "0"; constantThumbHeight = "0"; childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 0"; + extent = "1024 730"; + minExtent = "8 8"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ConsoleScrollProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "Scroll"; + canSave = "1"; + canSaveDynamicFields = "0"; - new GuiConsole( ConsoleMessageLogView ) { - profile = "GuiConsoleProfile"; - position = "0 0"; - }; + new GuiConsole(ConsoleMessageLogView) { + position = "1 1"; + extent = "622 324"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiConsoleProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; }; + }; }; //--- OBJECT WRITE END --- @@ -173,3 +311,35 @@ function ConsoleMessageLogView::onMessageSelected( %this, %level, %message ) EditorOpenFileInTorsion( %fileName, %lineNumber ); } + +function ConsoleDlg::onWake(%this) +{ + ConsoleDlgErrorFilterBtn.setStateOn(ConsoleMessageLogView.getErrorFilter()); + ConsoleDlgWarnFilterBtn.setStateOn(ConsoleMessageLogView.getWarnFilter()); + ConsoleDlgNormalFilterBtn.setStateOn(ConsoleMessageLogView.getNormalFilter()); + + ConsoleMessageLogView.refresh(); +} + +function ConsoleDlgErrorFilterBtn::onClick(%this) +{ + ConsoleMessageLogView.toggleErrorFilter(); +} + +function ConsoleDlgWarnFilterBtn::onClick(%this) +{ + + ConsoleMessageLogView.toggleWarnFilter(); +} + +function ConsoleDlgNormalFilterBtn::onClick(%this) +{ + ConsoleMessageLogView.toggleNormalFilter(); +} + +function ConsoleMessageLogView::onNewMessage(%this, %errorCount, %warnCount, %normalCount) +{ + ConsoleDlgErrorFilterBtn.setText("(" @ %errorCount @ ") Errors"); + ConsoleDlgWarnFilterBtn.setText("(" @ %warnCount @ ") Warnings"); + ConsoleDlgNormalFilterBtn.setText("(" @ %normalCount @ ") Messages"); +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/postFx/fxaa/fxaaV.hlsl b/Templates/Full/game/shaders/common/postFx/fxaa/fxaaV.hlsl index 3bef0a4d3..f2974c587 100644 --- a/Templates/Full/game/shaders/common/postFx/fxaa/fxaaV.hlsl +++ b/Templates/Full/game/shaders/common/postFx/fxaa/fxaaV.hlsl @@ -21,7 +21,7 @@ //----------------------------------------------------------------------------- #include "./../../torque.hlsl" -#include "./../postFX.hlsl" +#include "./../postFx.hlsl" struct VertToPix { diff --git a/Templates/Full/game/shaders/common/postFx/ssao/SSAO_Blur_P.hlsl b/Templates/Full/game/shaders/common/postFx/ssao/SSAO_Blur_P.hlsl index a47261397..5bdf9a77d 100644 --- a/Templates/Full/game/shaders/common/postFx/ssao/SSAO_Blur_P.hlsl +++ b/Templates/Full/game/shaders/common/postFx/ssao/SSAO_Blur_P.hlsl @@ -20,7 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "../../ShaderModelAutoGen.hlsl" +#include "../../shaderModelAutoGen.hlsl" #include "./../postFx.hlsl" TORQUE_UNIFORM_SAMPLER2D(occludeMap, 0); diff --git a/Templates/Full/game/shaders/common/postFx/ssao/SSAO_P.hlsl b/Templates/Full/game/shaders/common/postFx/ssao/SSAO_P.hlsl index 67365e846..ff31a4b8b 100644 --- a/Templates/Full/game/shaders/common/postFx/ssao/SSAO_P.hlsl +++ b/Templates/Full/game/shaders/common/postFx/ssao/SSAO_P.hlsl @@ -20,7 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "../../ShaderModelAutoGen.hlsl" +#include "../../shaderModelAutoGen.hlsl" #include "./../postFx.hlsl" #define DOSMALL