XnStatus PlayerNode::UndoRecord(PlayerNode::RecordUndoInfo& undoInfo, XnUInt32 nDestPos, XnBool& bUndone) { XnStatus nRetVal = XN_STATUS_OK; XnUInt32 nOriginalPos = TellStream(); bUndone = FALSE; Record record(m_pRecordBuffer, RECORD_MAX_SIZE); while ((undoInfo.nRecordPos > nDestPos) && (undoInfo.nUndoRecordPos != 0)) { nRetVal = SeekStream(XN_OS_SEEK_SET, undoInfo.nUndoRecordPos); XN_IS_STATUS_OK(nRetVal); nRetVal = ReadRecordHeader(record); XN_IS_STATUS_OK(nRetVal); undoInfo.nRecordPos = undoInfo.nUndoRecordPos; undoInfo.nUndoRecordPos = record.GetUndoRecordPos(); } if (undoInfo.nRecordPos <= nDestPos) { /*We found a record that can undo the record originally pointed to by undoInfo.nDestRecordPos, so now we handle it. */ nRetVal = ReadRecordFields(record); XN_IS_STATUS_OK(nRetVal); nRetVal = HandleRecord(record, FALSE); XN_IS_STATUS_OK(nRetVal); bUndone = TRUE; } else { nRetVal = SeekStream(XN_OS_SEEK_SET, nOriginalPos); XN_IS_STATUS_OK(nRetVal); } return XN_STATUS_OK; }
XnStatus PlayerNode::ReadRecord(Record &record) { XnStatus nRetVal = ReadRecordHeader(record); XN_IS_STATUS_OK(nRetVal); nRetVal = ReadRecordFields(record); XN_IS_STATUS_OK(nRetVal); return XN_STATUS_OK; }
RecordTypeIR JsonIRReader::RecordTypeJsonToIR(const JsonObjectRef &record_type) { RecordTypeIR record_type_ir; ReadTypeInfo(record_type, &record_type_ir); ReadTemplateInfo(record_type, &record_type_ir); record_type_ir.SetAccess(GetAccess(record_type)); ReadVTableLayout(record_type, &record_type_ir); ReadRecordFields(record_type, &record_type_ir); ReadBaseSpecifiers(record_type, &record_type_ir); record_type_ir.SetRecordKind(GetRecordKind(record_type)); record_type_ir.SetAnonymity(record_type.GetBool("is_anonymous")); ReadTagTypeInfo(record_type, &record_type_ir); return record_type_ir; }
XnStatus PlayerNode::SeekToFrameAbsolute(XnUInt32 nNodeID, XnUInt32 nDestFrame) { XN_ASSERT((nNodeID != INVALID_NODE_ID) && (nNodeID < m_nMaxNodes)); PlayerNodeInfo* pPlayerNodeInfo = &m_pNodeInfoMap[nNodeID]; XN_ASSERT((nDestFrame > 0) && (nDestFrame <= pPlayerNodeInfo->nFrames)); XN_VALIDATE_INPUT_PTR(m_pNodeNotifications); XnUInt32 nStartPos = TellStream(); XnUInt32 nNextFrame = pPlayerNodeInfo->nCurFrame + 1; XnUInt32 nFrames = pPlayerNodeInfo->nFrames; XnStatus nRetVal = XN_STATUS_OK; if (nDestFrame == pPlayerNodeInfo->nCurFrame) { //Just go back to position of current frame nRetVal = SeekStream(XN_OS_SEEK_SET, pPlayerNodeInfo->nLastDataPos); XN_IS_STATUS_OK(nRetVal); } else if (nDestFrame < nNextFrame) { //Seek backwards XnUInt32 nDestRecordPos = pPlayerNodeInfo->newDataUndoInfo.nRecordPos; XnUInt32 nUndoRecordPos = pPlayerNodeInfo->newDataUndoInfo.nUndoRecordPos; NewDataRecordHeader record(m_pRecordBuffer, RECORD_MAX_SIZE); /*Scan back through the frames' undo positions until we get to a frame number that is smaller or equal to nDestFrame. We put the position of the frame we find in nDestRecordPos. */ do { if (nUndoRecordPos == 0) { /* The last frame we encountered doesn't have an undo frame. But this data frame can't be the first, so the file is corrupt */ XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Undo frame not found for frame in position %u", nDestRecordPos); } nRetVal = SeekStream(XN_OS_SEEK_SET, nUndoRecordPos); XN_IS_STATUS_OK(nRetVal); nDestRecordPos = nUndoRecordPos; record.ResetRead(); nRetVal = ReadRecordHeader(record); XN_IS_STATUS_OK(nRetVal); if (record.GetType() != RECORD_NEW_DATA) { XN_ASSERT(FALSE); XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Unexpected record type: %u", record.GetType()); } if (record.GetNodeID() != nNodeID) { XN_ASSERT(FALSE); XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Unexpected node id: %u", record.GetNodeID()); } nRetVal = ReadRecordFields(record); XN_IS_STATUS_OK(nRetVal); nRetVal = record.Decode(); XN_IS_STATUS_OK(nRetVal); nUndoRecordPos = record.GetUndoRecordPos(); } while (record.GetFrameNumber() > nDestFrame); //Now handle the frame nRetVal = HandleNewDataRecord(record, FALSE); XnBool bUndone = FALSE; for (XnUInt32 i = 0; i < m_nMaxNodes; i++) { //Rollback all properties to match the state the stream was in at position nDestRecordPos PlayerNodeInfo &pni = m_pNodeInfoMap[i]; for (RecordUndoInfoMap::Iterator it = pni.recordUndoInfoMap.begin(); it != pni.recordUndoInfoMap.end(); it++) { if ((it.Value().nRecordPos > nDestRecordPos) && (it.Value().nRecordPos < nStartPos)) { //This property was set between nDestRecordPos and our start position, so we need to undo it. nRetVal = UndoRecord(it.Value(), nDestRecordPos, bUndone); XN_IS_STATUS_OK(nRetVal); } } if ((i != nNodeID) && pni.bIsGenerator) { //Undo all other generator nodes' data RecordUndoInfo &undoInfo = pni.newDataUndoInfo; if ((undoInfo.nRecordPos > nDestRecordPos) && (undoInfo.nRecordPos < nStartPos)) { nRetVal = UndoRecord(undoInfo, nDestRecordPos, bUndone); XN_IS_STATUS_OK(nRetVal); if (!bUndone) { //We couldn't find a record that can undo this data record pni.nLastDataPos = 0; pni.newDataUndoInfo.Reset(); } } } } /*Now, for each node, go to the position of the last encountered data record, and process that record (including its payload).*/ /*TODO: Optimization: remember each node's last data pos, and later, see if it changes. Only process data frames of nodes whose last data pos actually changed.*/ nRetVal = ProcessEachNodeLastData(nNodeID); XN_IS_STATUS_OK(nRetVal); } else //(nDestFrame >= nNextFrame) { //Skip all frames until we get to our frame number, but handle any properties we run into. while (pPlayerNodeInfo->nCurFrame < nDestFrame) { nRetVal = ProcessRecord(FALSE); XN_IS_STATUS_OK(nRetVal); } /*Now, for each node, go to the position of the last encountered data record, and process that record (including its payload).*/ /*TODO: Optimization: remember each node's last data pos, and later, see if it changes. Only process data frames of nodes whose last data pos actually changed.*/ nRetVal = ProcessEachNodeLastData(nNodeID); XN_IS_STATUS_OK(nRetVal); } return XN_STATUS_OK; }