const char *ParseAnimationSet(const char *pText) { const char *pName = GetNextToken(pText, &pText); if(MFString_Compare(pName, "{")) SkipToken(pText, "{"); const char *pTok = GetNextToken(pText, &pText); while(MFString_Compare(pTok, "}")) { if(!MFString_Compare(pTok, "Animation")) { pText = ParseAnimation(pText); } else { MFDebug_Warn(4, MFStr("Unexpected token '%s'\n", pTok)); SkipSection(pText); } pTok = GetNextToken(pText, &pText); } return pText; }
MF_API void MFMaterial_RemoveDefinitions(const char *pName) { MFCALLSTACK; MaterialDefinition *pDef = pDefinitionRegistry; if(!pDef) return; if(!MFString_Compare(pDef->pName, pName)) { pDefinitionRegistry = pDef->pNextDefinition; MFMaterial_DestroyDefinition(pDef); return; } while(pDef->pNextDefinition) { if(!MFString_Compare(pDef->pNextDefinition->pName, pName)) { MaterialDefinition *pDestroy = pDef->pNextDefinition; pDef->pNextDefinition = pDef->pNextDefinition->pNextDefinition; MFMaterial_DestroyDefinition(pDestroy); return; } pDef = pDef->pNextDefinition; } }
const char *GetValue(const char *pText, const char **ppTokenEnd = NULL) { char temp[1024]; const char *pVal = GetNextToken(pText, &pText); const char *pSemi = GetNextToken(pText, ppTokenEnd, temp); MFDebug_Assert(!MFString_Compare(pSemi, ";") || !MFString_Compare(pSemi, ","), "Value is not terminated with a semicolon.\n"); return pVal; }
static int MFFileSystem_GetNumEntries(const char *pFindPattern, bool recursive, bool flatten, size_t *pStringLengths) { MFFindData findData; MFFind *hFind; int numFiles = 0; hFind = MFFileSystem_FindFirst(MFString::Format("%s*", pFindPattern).CStr(), &findData); if(hFind) { *pStringLengths += MFString_Length(findData.pSystemPath) + 1; } while(hFind) { if(MFString_Compare(findData.pFilename, ".") && MFString_Compare(findData.pFilename, "..") && MFString_Compare(findData.pFilename, ".svn")) { if(findData.info.attributes & MFFA_Directory) { if(recursive) { if(flatten) { MFString newPath = MFString::Format("%s%s/", pFindPattern, findData.pFilename); numFiles += MFFileSystem_GetNumEntries(newPath.CStr(), recursive, flatten, pStringLengths); } else { *pStringLengths += MFString_Length(findData.pFilename) + 1; ++numFiles; } } } else { *pStringLengths += MFString_Length(findData.pFilename) + 1; ++numFiles; } } if(!MFFileSystem_FindNext(hFind, &findData)) { MFFileSystem_FindClose(hFind); hFind = NULL; } } return numFiles; }
void SkipSection(const char *&pText) { while(MFString_Compare(GetNextToken(pText, &pText), "{")) { } int depth = 1; while(depth) { const char *pTok = GetNextToken(pText, &pText); if(!MFString_Compare(pTok, "{")) ++depth; if(!MFString_Compare(pTok, "}")) --depth; } }
MF_API int MFString_Enumerate(const char *pString, const char **ppKeys, size_t numKeys, bool bCaseSensitive) { for(size_t i=0; i<numKeys && ppKeys[i]; ++i) { if(bCaseSensitive ? !MFString_Compare(pString, ppKeys[i]) : !MFString_CaseCmp(pString, ppKeys[i])) return (int)i; } return -1; }
MF_API int MFModule_GetModuleID(const char *pName) { for(int a=0; a<gNumModules; ++a) { if(!MFString_Compare(pName, gModules[a].pModuleName)) return a; } return -1; }
dBActionScript *dBThemeScreen::GetAction(const char *pName) { for(size_t a=0; a<actions.size(); ++a) { if(!MFString_Compare(actions[a].pName, pName)) return actions[a].pScript; } return NULL; }
MF_API uint64 MFModule_GetModuleMask(const char **ppModuleNames) { uint64 mask = 0; for(int b=0; ppModuleNames[b]; ++b) { if(!MFString_Compare(ppModuleNames[b], "MFCore")) { mask |= gCoreModules; } else { for(int a=0; a<gNumModules; ++a) { if(!MFString_Compare(ppModuleNames[b], gModules[a].pModuleName)) mask |= 1ULL << a; } } } return mask; }
void GetFloatArray(const char *pText, float *pOutput, int arrayLength, const char **ppTokenEnd = NULL) { char temp[1024]; for(int a=0; a<arrayLength; a++) { const char *pVal = GetNextToken(pText, &pText); if(a < arrayLength-1) { const char *pComa = GetNextToken(pText, &pText, temp); MFDebug_Assert(!MFString_Compare(pComa, ","), "Array values are separated with a coma.\n"); } pOutput[a] = (float)atof(pVal); } const char *pSemi = GetNextToken(pText, ppTokenEnd); MFDebug_Assert(!MFString_Compare(pSemi, ";"), "Value is not terminated with a semicolon.\n"); }
const char *FindSectionInScope(const char *pText, const char *pSection) { const char *pT; int depth = 1; while(depth) { const char *pTok = GetNextToken(pText, &pT); if(depth == 1) if(!MFString_Compare(pTok, pSection)) return pText; pText = pT; if(!MFString_Compare(pTok, "{")) ++depth; if(!MFString_Compare(pTok, "}")) --depth; } return NULL; }
dBActionMetric *dBThemeScreen::GetMetric(const char *pName) { for(size_t a=0; a<metrics.size(); ++a) { if(!MFString_Compare(metrics[a].pName, pName)) return metrics[a].pMetric; } // search the theme for global metrics //... return NULL; }
bool MFFileNative_FindNext(MFFind *pFind, MFFindData *pFindData) { dirent *pFD = readdir((DIR*)pFind->pFilesystemData); while(pFD && (!MFString_Compare(pFD->d_name, ".") || !MFString_Compare(pFD->d_name, ".."))) pFD = readdir((DIR*)pFind->pFilesystemData); if(!pFD) return false; const char *pFilePath = MFStr("%s%s", pFindData->pSystemPath, pFD->d_name); struct stat statbuf; if(stat(pFilePath, &statbuf) < 0) return false; pFindData->attributes = (S_ISDIR(statbuf.st_mode) ? MFFA_Directory : 0) | (S_ISLNK(statbuf.st_mode) ? MFFA_SymLink : 0) | (pFD->d_name[0] == '.' ? MFFA_Hidden : 0); pFindData->fileSize = statbuf.st_size; MFString_Copy((char*)pFindData->pFilename, pFD->d_name); return true; }
MF_API int MFModel_GetBoneIndex(MFModel *pModel, const char *pName) { MFModelDataChunk *pChunk = MFModel_GetDataChunk(pModel->pTemplate, MFChunkType_Bones); if(pChunk) { MFModelBone *pBones = (MFModelBone*)pChunk->pData; for(int a=0; a<pChunk->count; ++a) { if(!MFString_Compare(pBones->pBoneName, pName)) return a; } } return -1; }
MF_API int MFModel_GetSubObjectIndex(MFModel *pModel, const char *pSubobjectName) { MFModelDataChunk *pChunk = MFModel_GetDataChunk(pModel->pTemplate, MFChunkType_SubObjects); if(pChunk) { MFModelSubObject *pSubobjects = (MFModelSubObject*)pChunk->pData; for(int a=0; a<pChunk->count; ++a) { if(!MFString_Compare(pSubobjects->pSubObjectName, pSubobjectName)) return a; } } return -1; }
MFTOCEntry* MFFileSystem_BuildToc(const char *pFindPattern, MFTOCEntry *pToc, MFTOCEntry *pParent, char* &pStringCache, bool recursive, bool flatten) { MFFindData findData; MFFind *hFind; hFind = MFFileSystem_FindFirst(MFString::Format("%s*", pFindPattern).CStr(), &findData); char *pCurrentDir = pStringCache; if(hFind) { MFString_Copy(pCurrentDir, findData.pSystemPath); pStringCache += MFString_Length(findData.pSystemPath) + 1; } while(hFind) { if(MFString_Compare(findData.pFilename, ".") && MFString_Compare(findData.pFilename, "..") && MFString_Compare(findData.pFilename, ".svn")) { if(findData.info.attributes & MFFA_Directory) { if(recursive) { MFString newPath = MFString::Format("%s%s/", pFindPattern, findData.pFilename); if(flatten) { pToc = MFFileSystem_BuildToc(newPath.CStr(), pToc, pParent, pStringCache, recursive, flatten); } else { size_t stringCacheSize = 0; pToc->numChildren = MFFileSystem_GetNumEntries(newPath.CStr(), recursive, flatten, &stringCacheSize); MFString_Copy(pStringCache, findData.pFilename); pToc->pName = pStringCache; pStringCache += MFString_Length(findData.pFilename)+1; pToc->info = findData.info; pToc->pFilesysData = pCurrentDir; pToc->pParent = pParent; if (pToc->numChildren) { size_t sizeOfToc = sizeof(MFTOCEntry)*pToc->numChildren; pToc->pChildren = (MFTOCEntry*)MFHeap_Alloc(sizeOfToc + stringCacheSize); char *pNewStringCache = (char*)pToc->pChildren + sizeOfToc; MFFileSystem_BuildToc(newPath.CStr(), pToc->pChildren, pToc, pNewStringCache, recursive, flatten); } else pToc->pChildren = NULL; ++pToc; } } } else { MFString_Copy(pStringCache, findData.pFilename); pToc->pName = pStringCache; pStringCache += MFString_Length(findData.pFilename)+1; pToc->pFilesysData = pCurrentDir; pToc->pParent = pParent; pToc->pChildren = NULL; pToc->numChildren = 0; pToc->info = findData.info; ++pToc; } } if(!MFFileSystem_FindNext(hFind, &findData)) { MFFileSystem_FindClose(hFind); hFind = NULL; } } return pToc; }
void MFSound_InitModulePlatformSpecific(int *pSoundDataSize, int *pVoiceDataSize) { MFCALLSTACK; gDevices.Init(sizeof(AudioDevice), 8, 8); ALCint minor, major; alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &major); alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &minor); gAPIVersion = major*100 + minor; bool bCanEnumerate, bHasCapture; if(gAPIVersion >= 101) { bCanEnumerate = true; bHasCapture = true; } else { bCanEnumerate = alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") == AL_TRUE; bHasCapture = alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE") == AL_TRUE; } if(bCanEnumerate) { const char *pDevices = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); const char *pDefault = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); while(pDevices && *pDevices) { bool bIsDefault = !MFString_Compare(pDevices, pDefault); MFDebug_Log(2, MFStr("OpenAL: found output device '%s'%s", pDevices, bIsDefault ? " (default)" : "")); MFDevice *pDevice = MFDevice_AllocDevice(MFDT_AudioRender, &DestroyDevice); pDevice->pInternal = gDevices.AllocAndZero(); pDevice->state = MFDevState_Ready; AudioDevice &device = *(AudioDevice*)pDevice->pInternal; MFString_CopyN(pDevice->strings[MFDS_ID], pDevices, sizeof(pDevice->strings[MFDS_ID])-1); pDevice->strings[MFDS_ID][sizeof(pDevice->strings[MFDS_ID])-1] = 0; device.pDevice = NULL; if(bIsDefault) MFDevice_SetDefaultDevice(MFDT_AudioRender, MFDDT_All, pDevice); pDevices += MFString_Length(pDevices) + 1; } if(!MFDevice_GetDefaultDevice(MFDT_AudioRender, MFDDT_Default)) { MFDebug_Warn(2, "OpenAL: No default output device?"); // HACK: set it to the first one... MFDevice *pDevice = MFDevice_GetDeviceByIndex(MFDT_AudioRender, 0); MFDevice_SetDefaultDevice(MFDT_AudioRender, MFDDT_All, pDevice); } if(bHasCapture) { pDevices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); pDefault = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); while(pDevices && *pDevices) { bool bIsDefault = !MFString_Compare(pDevices, pDefault); MFDebug_Log(2, MFStr("OpenAL: found capture device '%s'%s", pDevices, bIsDefault ? " (default)" : "")); MFDevice *pDevice = MFDevice_AllocDevice(MFDT_AudioCapture, &DestroyDevice); pDevice->pInternal = gDevices.AllocAndZero(); pDevice->state = MFDevState_Ready; AudioDevice &device = *(AudioDevice*)pDevice->pInternal; MFString_CopyN(pDevice->strings[MFDS_ID], pDevices, sizeof(pDevice->strings[MFDS_ID])-1); pDevice->strings[MFDS_ID][sizeof(pDevice->strings[MFDS_ID])-1] = 0; device.pDevice = NULL; if(bIsDefault) MFDevice_SetDefaultDevice(MFDT_AudioCapture, MFDDT_All, pDevice); pDevices += MFString_Length(pDevices) + 1; } if(!MFDevice_GetDefaultDevice(MFDT_AudioCapture, MFDDT_Default)) MFDebug_Warn(2, "OpenAL: No default capture device?"); } } // create a context Context *pContext = CreateContext(MFDevice_GetDefaultDevice(MFDT_AudioRender, MFDDT_Default)); MakeCurrent(pContext); // we need to return the size of the internal structures so the platform independant // code can make the correct allocations.. *pSoundDataSize = sizeof(MFSoundDataInternal); *pVoiceDataSize = sizeof(MFVoiceDataInternal); }
MFTOCEntry* MFFileSystem_BuildToc(const char *pFindPattern, MFTOCEntry *pToc, MFTOCEntry *pParent, char* &pStringCache, bool recursive, bool flatten) { MFFindData findData; MFFind *hFind; hFind = MFFileSystem_FindFirst(MFString::Format("%s*", pFindPattern).CStr(), &findData); char *pCurrentDir = pStringCache; if(hFind) { MFString_Copy(pCurrentDir, findData.pSystemPath); pStringCache += MFString_Length(findData.pSystemPath) + 1; } while(hFind) { if(MFString_Compare(findData.pFilename, ".") && MFString_Compare(findData.pFilename, "..") && MFString_Compare(findData.pFilename, ".svn")) { if(findData.attributes & MFFA_Directory) { if(recursive) { MFString newPath = MFString::Format("%s%s/", pFindPattern, findData.pFilename); if(flatten) { pToc = MFFileSystem_BuildToc(newPath.CStr(), pToc, pParent, pStringCache, recursive, flatten); } else { size_t stringCacheSize = 0; pToc->size = MFFileSystem_GetNumEntries(newPath.CStr(), recursive, flatten, &stringCacheSize); if(pToc->size) { MFString_Copy(pStringCache, findData.pFilename); pToc->pName = pStringCache; pStringCache += MFString_Length(findData.pFilename)+1; pToc->flags = MFTF_Directory; pToc->pFilesysData = pCurrentDir; pToc->pParent = pParent; pToc->size = 0; size_t sizeOfToc = sizeof(MFTOCEntry)*pToc->size; pToc->pChild = (MFTOCEntry*)MFHeap_Alloc(sizeof(MFTOCEntry)*sizeOfToc + stringCacheSize); char *pNewStringCache = ((char*)pToc->pChild)+sizeOfToc; MFFileSystem_BuildToc(newPath.CStr(), pToc->pChild, pToc, pNewStringCache, recursive, flatten); ++pToc; } } } } else { MFString_Copy(pStringCache, findData.pFilename); pToc->pName = pStringCache; pStringCache += MFString_Length(findData.pFilename)+1; pToc->pFilesysData = pCurrentDir; pToc->pParent = pParent; pToc->pChild = NULL; MFDebug_Assert(findData.fileSize < 0x100000000LL, "Files larger than 4gb not yet supported..."); pToc->size = (uint32)findData.fileSize; pToc->flags = 0; ++pToc; } } if(!MFFileSystem_FindNext(hFind, &findData)) { MFFileSystem_FindClose(hFind); hFind = NULL; } } return pToc; }
int* ParseMaterialList(const char *pText, F3DSubObject &sub, int numFaces) { int *pMatFaces = NULL; const char *pMatList = FindSectionInScope(pText, "MeshMaterialList"); if(pMatList) { SkipToken(pMatList, "MeshMaterialList"); SkipToken(pMatList, "{"); int numMats = GetInt(pMatList, &pMatList); MFDebug_Assert(numMats < 16, "Exceeded maximum 16 materials per subobject..."); int numMatFaces = GetInt(pMatList, &pMatList); MFDebug_Assert(numMatFaces == numFaces, "Number of material faces does not match number of mesh faces"); pMatFaces = (int*)MFHeap_Alloc(sizeof(int)*numMatFaces); GetIntArray(pMatList, pMatFaces, numMatFaces, &pMatList); // process materials... const char *pToken = GetNextToken(pMatList, &pMatList); // MFDebug_Assert(!MFString_Compare(pToken, ";"), "Value is not terminated with a semicolon.\n"); if(!MFString_Compare(pToken, ";")) pToken = GetNextToken(pMatList, &pMatList); while(MFString_Compare(pToken, "}")) { if(!MFString_Compare(pToken, "Material")) { const char *pMatName = GetNextToken(pMatList, &pToken); if(MFString_Compare(pMatName, "{")) pMatList = pToken; else pMatName = "Unknown Material"; int matID = pModel->GetMaterialChunk()->GetMaterialIndexByName(pMatName); F3DMaterialSubobject &matSub = sub.matSubobjects.push(); if(matID != -1) { matSub.materialIndex = matID; SkipSection(pMatList); } else { matSub.materialIndex = pModel->GetMaterialChunk()->materials.size(); F3DMaterial &mat = pModel->GetMaterialChunk()->materials.push(); MFString_CopyN(mat.name, pMatName, 64); SkipToken(pMatList, "{"); mat.diffuse.x = GetFloat(pMatList, &pMatList); mat.diffuse.y = GetFloat(pMatList, &pMatList); mat.diffuse.z = GetFloat(pMatList, &pMatList); mat.diffuse.w = GetFloat(pMatList, &pMatList); SkipToken(pMatList, ";"); mat.specularLevel = GetFloat(pMatList, &pMatList); mat.specular.x = GetFloat(pMatList, &pMatList); mat.specular.y = GetFloat(pMatList, &pMatList); mat.specular.z = GetFloat(pMatList, &pMatList); mat.diffuse.w = 0.0f; SkipToken(pMatList, ";"); mat.emissive.x = GetFloat(pMatList, &pMatList); mat.emissive.y = GetFloat(pMatList, &pMatList); mat.emissive.z = GetFloat(pMatList, &pMatList); mat.emissive.w = 0.0f; SkipToken(pMatList, ";"); // any textures... pToken = GetNextToken(pMatList, &pMatList); while(MFString_Compare(pToken, "}")) { if(!MFString_Compare(pToken, "TextureFilename")) { SkipToken(pMatList, "{"); MFString_Copy(mat.maps[0], GetString(pMatList, &pMatList)); SkipToken(pMatList, "}"); } else { MFDebug_Warn(4, MFStr("Unknown token '%s'\n", pToken)); } pToken = GetNextToken(pMatList, &pMatList); } } } else if(!MFString_Compare(pToken, "{")) { // read material name const char *pMatName = GetNextToken(pMatList, &pMatList); int matID = pModel->GetMaterialChunk()->GetMaterialIndexByName(pMatName); F3DMaterialSubobject &matSub = sub.matSubobjects.push(); if(matID != -1) { matSub.materialIndex = matID; } else { matSub.materialIndex = pModel->GetMaterialChunk()->materials.size(); F3DMaterial &mat = pModel->GetMaterialChunk()->materials.push(); MFString_CopyN(mat.name, pMatName, 64); } pToken = GetNextToken(pMatList, &pMatList); MFDebug_Assert(!MFString_Compare(pToken, "}"), "Scope not closed.\n"); } else { MFDebug_Warn(4, MFStr("Unknown token '%s'\n", pToken)); } pToken = GetNextToken(pMatList, &pMatList); } } return pMatFaces; }
void SkipToken(const char *&pText, const char *pToken) { const char *pTok = GetNextToken(pText, &pText); MFDebug_Assert(!MFString_Compare(pTok, pToken), MFStr("Expected '%s'\n", pToken)); }
const char *ParseMesh(const char *pText, const MFMatrix &mat, const char *pFrameName) { // read name char meshName[64]; const char *pMeshName = GetNextToken(pText, &pText, meshName); if(!MFString_Compare(pMeshName, "{")) pMeshName = pFrameName; else SkipToken(pText, "{"); if(MFString_CaseCmpN(pMeshName, "m_", 2)) { // not a mesh! SkipSection(pText); return pText; } F3DMeshChunk *pMesh = pModel->GetMeshChunk(); F3DSubObject &sub = pMesh->subObjects.push(); MFString_Copy(sub.name, pMeshName); // get num positions int numPositions = GetInt(pText, &pText); sub.positions.resize(numPositions); // read positions for(int a=0; a<numPositions; a++) { sub.positions[a].x = GetFloat(pText, &pText); sub.positions[a].y = GetFloat(pText, &pText); sub.positions[a].z = GetFloat(pText, &pText); sub.positions[a] = ApplyMatrixH(sub.positions[a], mat); if(a < numPositions-1) SkipToken(pText, ","); } SkipToken(pText, ";"); // get num faces int numFaces = GetInt(pText, &pText); // see if we have a material face mapping int *pMatFaces = ParseMaterialList(pText, sub, numFaces); // read faces int face[16], numVerts[16], numTris[16]; MFZeroMemory(numVerts, sizeof(numVerts)); MFZeroMemory(numTris, sizeof(numTris)); for(int a=0; a<numFaces; a++) { int matSub = pMatFaces ? pMatFaces[a] : 0; F3DMaterialSubobject &matsub = sub.matSubobjects[matSub]; int numPoints = GetInt(pText, &pText); MFDebug_Assert(numPoints < 16, "Exceeded maximum 16 points per face..."); GetIntArray(pText, face, numPoints, &pText); int firstVert = numVerts[matSub]; numVerts[matSub] += numPoints; if(matsub.vertices.size() < numVerts[matSub]) matsub.vertices.resize(numVerts[matSub]); int firstTri = numTris[matSub]; numTris[matSub] += numPoints-2; if(matsub.triangles.size() < numTris[matSub]) matsub.triangles.resize(numTris[matSub]); for(int b=0; b<numPoints; b++) matsub.vertices[firstVert+b].position = face[b]; for(int b=0; b<numPoints-2; b++) { matsub.triangles[firstTri+b].v[0] = firstVert+0; matsub.triangles[firstTri+b].v[1] = firstVert+b+1; matsub.triangles[firstTri+b].v[2] = firstVert+b+2; } if(a < numFaces-1) SkipToken(pText, ","); } SkipToken(pText, ";"); const char *pTok = GetNextToken(pText, &pText); while(MFString_Compare(pTok, "}")) { if(!MFString_Compare(pTok, "MeshMaterialList")) { SkipSection(pText); } else if(!MFString_Compare(pTok, "MeshNormals")) { pText = ParseNormals(pText, sub, mat, numFaces, pMatFaces); } else if(!MFString_Compare(pTok, "MeshTextureCoords")) { pText = ParseTexCoords(pText, sub, numPositions); } else if(!MFString_Compare(pTok, "MeshVertexColors")) { pText = ParseColours(pText, sub, numPositions); } else if(!MFString_Compare(pTok, "XSkinMeshHeader")) { SkipToken(pText, "{"); // get num positions int nMaxSkinWeightsPerVertex = GetInt(pText, &pText); int nMaxSkinWeightsPerFace = GetInt(pText, &pText); int nBones = GetInt(pText, &pText); // not yet sure how this helps... /* for(int m=0; m<sub.matSubobjects.size(); m++) { sub.matSubobjects[m].numBones = nBones; } */ SkipToken(pText, "}"); } else if(!MFString_Compare(pTok, "SkinWeights")) { pText = ParseSkinWeights(pText, sub, numPositions); } else if(!MFString_Compare(pTok, "DeclData")) { SkipSection(pText); } else { MFDebug_Warn(4, MFStr("Unknown token '%s'\n", pTok)); SkipSection(pText); } pTok = GetNextToken(pText, &pText); } // we should order the bone weights into the most to least weighting. return pText; }
void MFInputLinux_InitGamepad(int fd, LinuxGamepad *pGamepad) { #if !defined(__CYGWIN__) MFCALLSTACK; pGamepad->joyFD = fd; // get the pad details ioctl(fd, JSIOCGNAME(80), pGamepad->identifier); ioctl(fd, JSIOCGAXES, &pGamepad->numAxiis); ioctl(fd, JSIOCGBUTTONS, &pGamepad->numButtons); MFGamepadInfo *pGI = pGamepadMappingRegistry; // we need to find a better way to get the VID/PID from the gamepad... if(!MFString_CompareN(pGamepad->identifier, "HID", 3)) { // the device was unnamed, but it is a HID device, so we'll try and match the VID/PID char *pBase = pGamepad->identifier + 3, *pEnd; // get the VID string while(*pBase && !MFIsHex(*pBase)) ++pBase; pEnd = pBase + 1; while(MFIsHex(*pEnd)) ++pEnd; uint32 vid = MFHexToInt(MFStrN(pBase, pEnd - pBase)); // get the PID string pBase = pEnd; while(*pBase && !MFIsHex(*pBase)) ++pBase; pEnd = pBase + 1; while(MFIsHex(*pEnd)) ++pEnd; uint32 pid = MFHexToInt(MFStrN(pBase, pEnd - pBase)); // find a matching descriptor for(; pGI; pGI = pGI->pNext) { if(pGI->vendorID == vid && pGI->productID == pid) break; } } else { // the device is named, so we'll compare the name against our list and hope its the same as windows.. // since we dont have the VID/PID though, we cant verify its not a device with an aliased name. pGI = pGI->pNext; // skip the first one for(; pGI; pGI = pGI->pNext) { // since linux appends the manufacturer name, we'll just check for a match on the end of the string int len1 = MFString_Length(pGamepad->identifier); int len2 = MFString_Length(pGI->pIdentifier); if(!MFString_Compare(pGamepad->identifier + (len1 - len2), pGI->pIdentifier)) break; } } if(!pGI) { // use default descriptor pGamepad->pGamepadInfo = pGamepadMappingRegistry; MFDebug_Warn(1, MFStr("Found an unknown gamepad '%s', using default mappings.", pGamepad->identifier)); // offer to send email detailing controller info.. // MessageBox(NULL, "An unknown gamepad has been detected.\r\nWe strive to support every gamepad natively, please report your gamepad to Manu at [email protected].\r\nI will contact you and request a few details about the gamepad so it can be added to the registry for the next release.", "Unknown gamepad detected...", MB_OK); } else { // use applicable descriptor pGamepad->pGamepadInfo = pGI; MFDebug_Log(2, MFStr("Found gamepad: %s '%s'.", pGI->pName, pGI->pIdentifier)); } /* // fix up the linux mapping table const int *pButtonMap = pGamepad->pGamepadInfo->pButtonMap; int numAxiis = 0; for(int a=0; a<60; a++) { for(int b=0; b<GamepadType_Max; ++b) { if((pButtonMap[b] & AID_Analog) && MFGETAXIS(pButtonMap[b]) == a) { pGamepad->axisMap[a] = numAxiis; printf("%d = %d\n", a, numAxiis); ++numAxiis; } } } */ #endif }
MF_API void MFWindow_Update(MFWindow *_pWindow, const MFWindowParams *pParams) { MFWindow_PC *pWindow = (MFWindow_PC*)_pWindow; if(MFString_Compare(pWindow->params.pWindowTitle, pParams->pWindowTitle) != 0) SetWindowText(pWindow->hWnd, pParams->pWindowTitle); RECT rect; rect.left = 0; rect.right = (long)pParams->width; rect.top = 0; rect.bottom = (long)pParams->height; DWORD dwStyle = WS_POPUP; DWORD dwExStyle = WS_EX_APPWINDOW; if(!pParams->bFullscreen) { if(pParams->flags & MFWF_WindowFrame) { dwExStyle |= WS_EX_WINDOWEDGE; dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; if(pParams->flags & MFWF_CanResize) dwStyle |= WS_THICKFRAME; } if(pParams->flags & MFWF_AlwaysOnTop) dwExStyle |= WS_EX_TOPMOST; AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle); rect.right += -rect.left + (long)pParams->x; rect.left = (long)pParams->x; rect.bottom += -rect.top + (long)pParams->y; rect.top = (long)pParams->y; } bool bFullscreenChanged = pWindow->params.bFullscreen != pParams->bFullscreen; bool bFrameChanged = pWindow->params.flags != pParams->flags || bFullscreenChanged; bool bNoMove = !bFullscreenChanged && pWindow->params.x == rect.left && pWindow->params.y == rect.top; bool bNoResize = !bFrameChanged && pWindow->params.width == pParams->width && pWindow->params.height == pParams->height; pWindow->params = *pParams; UINT flags = SWP_NOZORDER | SWP_NOOWNERZORDER; flags |= bNoMove ? SWP_NOMOVE : 0; flags |= bNoResize ? SWP_NOSIZE : 0; if(bFrameChanged) { SetWindowLong(pWindow->hWnd, GWL_STYLE, dwStyle); SetWindowLong(pWindow->hWnd, GWL_EXSTYLE, dwExStyle); flags |= SWP_FRAMECHANGED; int showState = !pParams->bFullscreen && pWindow->state == MFWinState_Maximised ? SW_MAXIMIZE : SW_SHOW; SetWindowPos(pWindow->hWnd, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, flags); ShowWindow(pWindow->hWnd, showState); SetForegroundWindow(pWindow->hWnd); SetFocus(pWindow->hWnd); } else if(!(bNoMove && bNoResize)) { SetWindowPos(pWindow->hWnd, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, flags); } }
const char *ParseAnimation(const char *pText) { const char *pAnimName = GetNextToken(pText, &pText); if(MFString_Compare(pAnimName, "{")) SkipToken(pText, "{"); char bone[64]; int numFrames = 0; float *pFrameTimes = NULL; MFQuaternion *pQuats = NULL; MFVector *pScale = NULL; MFVector *pTrans = NULL; MFMatrix *pMats = NULL; MFVector tQuat; const char *pTok = GetNextToken(pText, &pText); while(MFString_Compare(pTok, "}")) { if(!MFString_Compare(pTok, "AnimationKey")) { SkipToken(pText, "{"); int type = GetInt(pText, &pText); numFrames = GetInt(pText, &pText); pFrameTimes = (float*)MFHeap_Alloc(sizeof(float)*numFrames); switch(type) { case KT_Quat: pQuats = (MFQuaternion*)MFHeap_Alloc(sizeof(MFQuaternion)*numFrames); break; case KT_Scale: pScale = (MFVector*)MFHeap_Alloc(sizeof(MFVector)*numFrames); break; case KT_Translation: pTrans = (MFVector*)MFHeap_Alloc(sizeof(MFVector)*numFrames); break; case KT_Matrix: pMats = (MFMatrix*)MFHeap_Alloc(sizeof(MFMatrix)*numFrames); break; } // read data for(int a=0; a<numFrames; a++) { int frame = GetInt(pText, &pText); pFrameTimes[a] = (float)frame; int numComponents = GetInt(pText, &pText); switch(type) { case KT_Quat: MFDebug_Assert(numComponents == 4, "Required 4 components for a quaternion."); GetFloatArray(pText, tQuat, numComponents, &pText); ((MFVector&)pQuats[a]).Swizzle(tQuat, SW_Y|SW_NEG, SW_Z|SW_NEG, SW_W|SW_NEG, SW_X|SW_NEG); break; case KT_Scale: MFDebug_Assert(numComponents == 3, "Required 3 components for a scale."); GetFloatArray(pText, (float*)&pScale[a], numComponents, &pText); break; case KT_Translation: MFDebug_Assert(numComponents == 3, "Required 3 components for a translation."); GetFloatArray(pText, (float*)&pTrans[a], numComponents, &pText); break; case KT_Matrix: MFDebug_Assert(numComponents == 16, "Required 16 components for a matrix."); GetFloatArray(pText, (float*)&pMats[a], numComponents, &pText); break; } SkipToken(pText, ";"); if(a < numFrames-1) SkipToken(pText, ","); } SkipToken(pText, ";"); SkipToken(pText, "}"); } else if(!MFString_Compare(pTok, "{")) { GetNextToken(pText, &pText, bone); SkipToken(pText, "}"); } else { MFDebug_Warn(4, MFStr("Unexpected token '%s'\n", pTok)); SkipSection(pText); } pTok = GetNextToken(pText, &pText); } if(!MFString_CaseCmpN(bone, "bn_", 3) || !MFString_CaseCmpN(bone, "z_", 2)) { // copy data to bone F3DAnimation &anim = pModel->GetAnimationChunk()->anims.push(); anim.boneID = pModel->GetSkeletonChunk()->FindBone(bone); if(anim.boneID == -1) { MFDebug_Warn(4, MFStr("Bone '%s' not found..\n", bone)); return pText; } anim.minTime = pFrameTimes[0]; anim.maxTime = pFrameTimes[numFrames-1]; for(int a=0; a<numFrames; a++) { anim.keyframes[a].time = pFrameTimes[a]; if(pMats) { anim.keyframes[a].key = pMats[a]; // anim.keyframes[a].scale = MakeVector(pMats[a].GetXAxis().Magnitude3(), pMats[a].GetYAxis().Magnitude3(), pMats[a].GetZAxis().Magnitude3(), 1.0f); // pMats[a].Normalise(); // anim.keyframes[a].rotation = pMats[a].GetRotationQ(); // anim.keyframes[a].translation = pMats[a].GetTrans(); } else { anim.keyframes[a].key.SetRotationQ(pQuats ? pQuats[a] : MFQuaternion::identity); if(pScale) anim.keyframes[a].key.Scale(pScale[a]); anim.keyframes[a].key.SetTrans3(pTrans ? pTrans[a] : MFVector::identity); // anim.keyframes[a].rotation = pQuats ? pQuats[a] : MFQuaternion::identity; // anim.keyframes[a].scale = pScale ? pScale[a] : MFVector::one; // anim.keyframes[a].translation = pTrans ? pTrans[a] : MFVector::identity; } } } return pText; }
const char *ParseFrame(const char *pText, const MFMatrix &mat, int parentID) { char frameName[64]; const char *pName = GetNextToken(pText, &pText, frameName); MFMatrix worldMatrix = mat; F3DBone *pBone = NULL; if(!MFString_CaseCmpN(pName, "bn_", 3) || !MFString_CaseCmpN(pName, "z_", 2)) { int boneID = pModel->GetSkeletonChunk()->bones.size(); pBone = &pModel->GetSkeletonChunk()->bones[boneID]; F3DBone *pParent = parentID == -1 ? NULL : &pModel->GetSkeletonChunk()->bones[parentID]; parentID = boneID; MFString_Copy(pBone->name, pName); MFString_Copy(pBone->parentName, pParent ? pParent->name : ""); pBone->worldMatrix = mat; } if(MFString_Compare(pName, "{")) SkipToken(pText, "{"); const char *pTok = GetNextToken(pText, &pText); while(MFString_Compare(pTok, "}")) { if(!MFString_Compare(pTok, "Frame")) { pText = ParseFrame(pText, worldMatrix, parentID); } else if(!MFString_Compare(pTok, "FrameTransformMatrix")) { SkipToken(pText, "{"); MFMatrix localMatrix; GetFloatArray(pText, (float*)&localMatrix, 16, &pText); worldMatrix.Multiply(localMatrix, worldMatrix); if(pBone) { pBone->boneMatrix = localMatrix; pBone->worldMatrix = worldMatrix; } SkipToken(pText, ";"); SkipToken(pText, "}"); } else if(!MFString_Compare(pTok, "Mesh")) { gMeshChunks.push(XMeshChunk::Create(worldMatrix, pText, pName)); SkipSection(pText); } else { MFDebug_Warn(4, MFStr("Unexpected token '%s'\n", pTok)); SkipSection(pText); } pTok = GetNextToken(pText, &pText); } return pText; }
void LoadTextXFile(const char *pText) { const char *pTok = GetNextToken(pText, &pText); while(pTok) { if(!MFString_Compare(pTok, "Header")) { SkipToken(pText, "{"); int maj = GetInt(pText, &pText); int min = GetInt(pText, &pText); int flag = GetInt(pText, &pText); // printf("XFile V%d.%d, 0x%X\n", maj, min, flag); pTok = GetNextToken(pText, &pText); while(MFString_Compare(pTok, "}")) { pTok = GetNextToken(pText, &pText); } } else if(!MFString_Compare(pTok, "Frame")) { pText = ParseFrame(pText, MFMatrix::identity, -1); } else if(!MFString_Compare(pTok, "Mesh")) { gMeshChunks.push(XMeshChunk::Create(MFMatrix::identity, pText, "")); SkipSection(pText); } else if(!MFString_Compare(pTok, "AnimationSet")) { gAnimSets.push(pText); SkipSection(pText); } else if(!MFString_Compare(pTok, "template")) { // const char *pName = GetNextToken(pText, &pText); SkipSection(pText); } else { MFDebug_Warn(4, MFStr("Unknown token '%s'\n", pTok)); SkipSection(pText); } pTok = GetNextToken(pText, &pText); } int a; for(a=0; a<gMeshChunks.size(); a++) { ParseMesh(gMeshChunks[a].pMesh, gMeshChunks[a].mat, gMeshChunks[a].frameName); } for(a=0; a<gAnimSets.size(); a++) { ParseAnimationSet(gAnimSets[a]); } gMeshChunks.clear(); }