bool setupSearch(const Game *g, const int *needList, Search &search, SearchMap &searchData) { for (const int *entry = needList; *entry != -1; ++entry) { ExtractEntryList providers = getProvidersForId(*entry); if (providers.empty()) { fprintf(stderr, "ERROR: No provider for id %d/%s\n", *entry, getIdString(*entry)); return false; } else { for (ExtractEntryList::const_iterator i = providers.begin(); i != providers.end(); ++i) { // Only add generic or partly matching providers here. #ifndef DEBUG_EXTRACTION_TABLES if ((i->lang == UNK_LANG || i->lang == g->lang[0] || i->lang == g->lang[1] || i->lang == g->lang[2]) && (i->platform == kPlatformUnknown || (i->platform == g->platform))) { #endif search.addData(i->hint); searchData.insert(SearchMapEntry(*entry, *i)); #ifndef DEBUG_EXTRACTION_TABLES } #endif } } } return true; }
void GuiInspectorField::onRightMouseUp( const GuiEvent &event ) { if ( mCaptionRect.pointInRect( globalToLocalCoord( event.mousePoint ) ) ) Con::executef( mInspector, "onFieldRightClick", getIdString() ); else Parent::onMouseDown( event ); }
MatchList::const_iterator filterOutBestMatch(const MatchList &input) { MatchList::const_iterator result = input.begin(); if (input.size() > 1) warning("Multiple entries found for id %d/%s", (*result)->first, getIdString((*result)->first)); for (MatchList::const_iterator i = input.begin(); i != input.end(); ++i) { // Reduce all entries to one single entry. // // We use the following rules for this (in this order): // - Prefer the entry with the higest size // - Prefer the entry, which starts at the smallest offest // // TODO: These rules might not be safe for all games, but hopefully // they will work fine. If there are any problems it should be rather // easy to identify them, since we print out a warning for multiple // entries found. if ((*result)->second.desc.hint.size <= (*i)->second.desc.hint.size) { if ((*result)->second.offset >= (*i)->second.offset) result = i; } } return result; }
void GuiInspectorField::onRightMouseUp( const GuiEvent &event ) { if ( mCaptionRect.pointInRect( globalToLocalCoord( event.mousePoint ) ) ) { mInspector->onFieldRightClick_callback( getIdString() ); } else { Parent::onMouseDown( event ); } }
void OrthotropicThermalConductivityProperty::writeXML(QXmlStreamWriter& stream) { stream.writeStartElement("PropertyDetails"); stream.writeAttribute("id", getIdString()); stream.writeEmptyElement("Unitless"); stream.writeTextElement("Name", "Thermal Conductivity"); stream.writeEndElement(); }
void IsotropicElasticityProperty::writeXML(QXmlStreamWriter& stream) { stream.writeStartElement("PropertyDetails"); stream.writeAttribute("id", getIdString()); stream.writeEmptyElement("Unitless"); stream.writeTextElement("Name", "Elasticity"); stream.writeEndElement(); }
bool NavPath::visitNext() { U32 s = mVisitPoints.size(); if(s < 2) return false; // Current leg of journey. Point3F &start = mVisitPoints[s-1]; Point3F &end = mVisitPoints[s-2]; // Drop to height of statics. RayInfo info; if(getContainer()->castRay(start, start - Point3F(0, 0, mMesh->mWalkableHeight * 2.0f), StaticObjectType, &info)) start = info.point; if(getContainer()->castRay(end + Point3F(0, 0, 0.1f), end - Point3F(0, 0, mMesh->mWalkableHeight * 2.0f), StaticObjectType, &info)) end = info.point; // Convert to Detour-friendly coordinates and data structures. F32 from[] = {start.x, start.z, -start.y}; F32 to[] = {end.x, end.z, -end.y}; F32 extx = mMesh->mWalkableRadius * 4.0f; F32 extz = mMesh->mWalkableHeight; F32 extents[] = {extx, extz, extx}; dtPolyRef startRef, endRef; if(dtStatusFailed(mQuery->findNearestPoly(from, extents, &mFilter, &startRef, NULL)) || !startRef) { Con::errorf("No NavMesh polygon near visit point (%g, %g, %g) of NavPath %s", start.x, start.y, start.z, getIdString()); return false; } if(dtStatusFailed(mQuery->findNearestPoly(to, extents, &mFilter, &endRef, NULL)) || !endRef) { Con::errorf("No NavMesh polygon near visit point (%g, %g, %g) of NavPath %s", end.x, end.y, end.z, getIdString()); return false; } // Init sliced pathfind. mStatus = mQuery->initSlicedFindPath(startRef, endRef, from, to, &mFilter); if(dtStatusFailed(mStatus)) return false; return true; }
void OrthotropicSecantCoefficientOfThermalExpansion::writeXML(QXmlStreamWriter& stream) { stream.writeStartElement("PropertyDetails"); stream.writeAttribute("id", getIdString()); stream.writeEmptyElement("Unitless"); stream.writeTextElement("Name", "Coefficient of Thermal Expansion"); stream.writeEndElement(); }
void TextLayer::destroyResources(VidgfxContext *gfx) { appLog(LOG_CAT) << "Destroying hardware resources for layer " << getIdString(); vidgfx_texdecalbuf_destroy_vert_buf(m_vertBuf); vidgfx_texdecalbuf_set_context(m_vertBuf, NULL); vidgfx_context_destroy_tex(gfx, m_texture); m_texture = NULL; }
void PathCamera::onNode(S32 node) { if (!isGhost()) onNode_callback(Con::getIntArg(node)); //.logicking >> we need to call onNode on datablock PathCameraData class, not on PathCamera if (!isGhost()) Con::executef(mDataBlock, "onNode", getIdString(), Con::getIntArg(node)); //.logicking << }
void TextLayer::initializeResources(VidgfxContext *gfx) { appLog(LOG_CAT) << "Creating hardware resources for layer " << getIdString(); vidgfx_texdecalbuf_set_context(m_vertBuf, gfx); vidgfx_texdecalbuf_set_rect(m_vertBuf, QRectF()); vidgfx_texdecalbuf_set_tex_uv(m_vertBuf, QRectF()); m_isTexDirty = true; updateResources(gfx); }
bool NavMesh::createNavMesh(dtNavMeshCreateParams ¶ms) { unsigned char *tileData = NULL; S32 tileDataSize = 0; if(!dtCreateNavMeshData(¶ms, &tileData, &tileDataSize)) { Con::errorf("Could not construct NavMeshData for NavMesh %s", getIdString()); return false; } tnm = dtAllocNavMesh(); if(!tnm) { Con::errorf("Out of memory allocating dtNavMesh for NavMesh %s", getIdString()); return false; } dtStatus s = tnm->init(tileData, tileDataSize, DT_TILE_FREE_DATA); if(dtStatusFailed(s)) { Con::errorf("Could not initialise dtNavMesh for NavMesh %s", getIdString()); return false; } // Initialise all flags to something helpful. for(U32 i = 0; i < tnm->getMaxTiles(); ++i) { const dtMeshTile* tile = ((const dtNavMesh*)tnm)->getTile(i); if(!tile->header) continue; const dtPolyRef base = tnm->getPolyRefBase(tile); for(U32 j = 0; j < tile->header->polyCount; ++j) { const dtPolyRef ref = base | j; unsigned short f = 0; tnm->getPolyFlags(ref, &f); tnm->setPolyFlags(ref, f | 1); } } return true; }
void Scene::setName(const QString &name) { QString str = name; if(str.isEmpty()) str = tr("Unnamed"); if(m_name == str) return; QString oldName = m_name; m_name = str; m_profile->sceneChanged(this); // Remote emit if(!m_isInitializing) appLog(LOG_CAT) << "Renamed scene " << getIdString(); }
void eapsUta12Port::answerGetMaxValues( unsigned char* msgValues ) { _maxVoltageOut = msgValues[4]*256 + msgValues[5]; _maxCurrentOut = msgValues[6]*256 + msgValues[7]; _maxVoltageIn = msgValues[8]*256 + msgValues[9]; _maxCurrentIn = msgValues[10]*256 + msgValues[11]; _initValueCounter++; LOG(INFO) << "eaps uta 12 answer: get max values:" << " maxVoltageOut: " << _maxVoltageOut << " maxCurrentOut: " << _maxCurrentOut << " maxVoltageIn: " << _maxVoltageIn << " maxCurrentIn: " << _maxCurrentIn; getIdString(); }
void HitboxTarget::deactivateEvent() { if(m_isInitializing) return; if(m_videoEnc == NULL) return; // Never activated appLog(LOG_CAT) << "Deactivating Hitbox target " << getIdString() << "..."; // Immediately deactivate RTMP rtmpDeactivate(); if(m_pane != NULL) m_pane->setPaneState(TargetPane::OfflineState); appLog(LOG_CAT) << "Hitbox target deactivated"; }
bool SFXSource::_setStatus( SFXStatus status ) { if ( mStatus == status ) return false; mStatus = status; // Do the callback if we have it. const char* statusString = SFXStatusToString( mStatus ); if ( mStatusCallback && mStatusCallback[0] ) Con::executef( mStatusCallback, getIdString(), statusString ); else if ( getNamespace() ) Con::executef( this, "onStatusChange", statusString ); return true; }
void PxSingleActor::_onContact( NxActor *ourActor, NxActor *hitActor, SceneObject *hitObject, const Point3F &hitPoint, const Point3F &impactForce ) { if ( isGhost() ) return; String strHitPos = String::ToString( "%g %g %g", hitPoint.x, hitPoint.y, hitPoint.z ); String strImpactVec = String::ToString( "%g %g %g", impactForce.x, impactForce.y, impactForce.z ); String strImpactForce = String::ToString( "%g", impactForce.len() ); Con::executef( mDataBlock, "onCollision", getIdString(), hitObject ? hitObject->scriptThis() : "", strHitPos.c_str(), strImpactVec.c_str(), strImpactForce.c_str() ); }
void EditTSCtrl::_renderScene( ObjectRenderInst*, SceneRenderState *state, BaseMatInstance* ) { GFXTransformSaver saver; // render through console callbacks SimSet * missionGroup = static_cast<SimSet*>(Sim::findObject("MissionGroup")); if(missionGroup) { mConsoleRendering = true; // [ rene, 27-Jan-10 ] This calls onEditorRender on the server objects instead // of on the client objects which seems a bit questionable to me. for(SimSetIterator itr(missionGroup); *itr; ++itr) { SceneObject* object = dynamic_cast< SceneObject* >( *itr ); if( object && object->isRenderEnabled() && !object->isHidden() ) { char buf[2][16]; dSprintf(buf[0], 16, object->isSelected() ? "true" : "false"); dSprintf(buf[1], 16, object->isExpanded() ? "true" : "false"); object->onEditorRender_callback( getIdString(), buf[0], buf[1] ); } } mConsoleRendering = false; } // render the mission area... renderMissionArea(); // Draw the grid if ( mRenderGridPlane ) renderGrid(); // render the editor stuff renderScene(mSaveViewport); // Draw the camera axis GFX->setClipRect(mSaveViewport); GFX->setStateBlock(mDefaultGuiSB); renderCameraAxis(); }
bool UstreamTarget::activateEvent() { if(m_isInitializing) return false; if(m_videoEnc == NULL) return false; appLog(LOG_CAT) << "Activating Ustream target " << getIdString() << " with target URL \"" << m_remoteInfo.asUrl() << "\"..."; // Immediately initialize RTMP as we know the URL if(!rtmpActivate(m_remoteInfo)) return false; if(m_pane != NULL) setPaneStateHelper(m_pane); appLog(LOG_CAT) << "Ustream target activated"; return true; }
void SimGroup::_addObject( SimObject* obj, bool forcePushBack ) { // Make sure we aren't adding ourself. This isn't the most robust check // but it should be good enough to prevent some self-foot-shooting. if( obj == this ) { Con::errorf( "SimGroup::addObject - (%d) can't add self!", getIdString() ); return; } if( obj->getGroup() == this ) return; lock(); obj->incRefCount(); if( obj->getGroup() ) obj->getGroup()->removeObject( obj ); if( forcePushBack ? objectList.pushBack( obj ) : objectList.pushBackForce( obj ) ) { mNameDictionary.insert( obj ); obj->mGroup = this; obj->onGroupAdd(); getSetModificationSignal().trigger( SetObjectAdded, this, obj ); if( obj->isProperlyAdded() ) onObjectAdded_callback( obj ); } else obj->decRefCount(); unlock(); // SimObjects will automatically remove them from their group // when deleted so we don't hook up a delete notification. }
bool HitboxTarget::activateEvent() { if(m_isInitializing) return false; if(m_videoEnc == NULL) return false; appLog(LOG_CAT) << "Activating Hitbox target " << getIdString() << " with target URL \"" << m_remoteInfo.asUrl() << "\"..."; // Immediately initialize RTMP as we know the URL if(!rtmpActivate(m_remoteInfo)) return false; // Don't query Hitbox immediately and reset any previous results m_prevStreamQueryTime = App->getUsecSinceExec(); m_numViewers = 0; if(m_pane != NULL) setPaneStateHelper(m_pane); appLog(LOG_CAT) << "Hitbox target activated"; return true; }
void GuiOffscreenCanvas::renderFrame(bool preRenderOnly, bool bufferSwap /* = true */) { if (!mTargetDirty) return; #ifdef TORQUE_ENABLE_GFXDEBUGEVENTS char buf[256]; dSprintf(buf, sizeof(buf), "OffsceenCanvas %s", getName() ? getName() : getIdString()); GFXDEBUGEVENT_SCOPE_EX(GuiOffscreenCanvas_renderFrame, ColorI::GREEN, buf); #endif PROFILE_START(OffscreenCanvasPreRender); #ifdef TORQUE_GFX_STATE_DEBUG GFX->getDebugStateManager()->startFrame(); #endif if (mTarget->getSize() != mTargetSize) { _setupTargets(); mNamedTarget.setViewport( RectI( Point2I::Zero, mTargetSize ) ); } // Make sure the root control is the size of the canvas. Point2I size = mTarget->getSize(); if(size.x == 0 || size.y == 0) { PROFILE_END(); return; } RectI screenRect(0, 0, size.x, size.y); maintainSizing(); //preRender (recursive) all controls preRender(); PROFILE_END(); // Are we just doing pre-render? if(preRenderOnly) { return; } resetUpdateRegions(); PROFILE_START(OffscreenCanvasRenderControls); GuiCursor *mouseCursor = NULL; bool cursorVisible = true; Point2I cursorPos((S32)mCursorPt.x, (S32)mCursorPt.y); mouseCursor = mDefaultCursor; mLastCursorEnabled = cursorVisible; mLastCursor = mouseCursor; mLastCursorPt = cursorPos; // Set active target GFX->pushActiveRenderTarget(); GFX->setActiveRenderTarget(mTarget); // Clear the current viewport area GFX->setViewport( screenRect ); GFX->clear( GFXClearTarget, ColorF(0,0,0,0), 1.0f, 0 ); resetUpdateRegions(); // Make sure we have a clean matrix state // before we start rendering anything! GFX->setWorldMatrix( MatrixF::Identity ); GFX->setViewMatrix( MatrixF::Identity ); GFX->setProjectionMatrix( MatrixF::Identity ); RectI contentRect(Point2I(0,0), mTargetSize); { // Render active GUI Dialogs for(iterator i = begin(); i != end(); i++) { // Get the control GuiControl *contentCtrl = static_cast<GuiControl*>(*i); GFX->setClipRect( contentRect ); GFX->setStateBlock(mDefaultGuiSB); contentCtrl->onRender(contentCtrl->getPosition(), contentRect); } // Fill Blue if no Dialogs if(this->size() == 0) GFX->clear( GFXClearTarget, ColorF(0,0,0,1), 1.0f, 0 ); GFX->setClipRect( contentRect ); // Draw cursor // if (mCursorEnabled && mouseCursor && mShowCursor) { Point2I pos((S32)mCursorPt.x, (S32)mCursorPt.y); Point2I spot = mouseCursor->getHotSpot(); pos -= spot; mouseCursor->render(pos); } GFX->getDrawUtil()->clearBitmapModulation(); } mTarget->resolve(); GFX->popActiveRenderTarget(); PROFILE_END(); // Keep track of the last time we rendered. mLastRenderMs = Platform::getRealMilliseconds(); mTargetDirty = mDynamicTarget; onFrameRendered(); }
void AITurretShape::_scriptCallback(const char* function) { Con::executef( mDataBlock, function, getIdString() ); }
/** * Utility function to throw callbacks. Callbacks always occure * on the datablock class. * * @param name Name of script function to call */ void AIPlayer::throwCallback( const char *name ) { Con::executef(getDataBlock(), name, getIdString()); }
bool NavMesh::createPolyMesh(rcConfig &cfg, NavModelData &data, rcContext *ctx) { // Create a heightfield to voxelise our input geometry hf = rcAllocHeightfield(); if(!hf || !rcCreateHeightfield(ctx, *hf, cfg.width, cfg.height, cfg.bmin, cfg.bmax, cfg.cs, cfg.ch)) { Con::errorf("Could not generate rcHeightField for NavMesh %s", getIdString()); return false; } unsigned char *areas = new unsigned char[data.getTriCount()]; if (!areas) { Con::errorf("Out of memory (area flags) for NavMesh %s", getIdString()); return false; } memset(areas, 0, data.getTriCount()*sizeof(unsigned char)); // Subtract 1 from all indices! for(U32 i = 0; i < data.getTriCount(); i++) { data.tris[i*3]--; data.tris[i*3+1]--; data.tris[i*3+2]--; } // Filter triangles by angle and rasterize rcMarkWalkableTriangles(ctx, cfg.walkableSlopeAngle, data.getVerts(), data.getVertCount(), data.getTris(), data.getTriCount(), areas); rcRasterizeTriangles(ctx, data.getVerts(), data.getVertCount(), data.getTris(), areas, data.getTriCount(), *hf, cfg.walkableClimb); delete [] areas; // Filter out areas with low ceilings and other stuff rcFilterLowHangingWalkableObstacles(ctx, cfg.walkableClimb, *hf); rcFilterLedgeSpans(ctx, cfg.walkableHeight, cfg.walkableClimb, *hf); rcFilterWalkableLowHeightSpans(ctx, cfg.walkableHeight, *hf); chf = rcAllocCompactHeightfield(); if(!chf || !rcBuildCompactHeightfield(ctx, cfg.walkableHeight, cfg.walkableClimb, *hf, *chf)) { Con::errorf("Could not generate rcCompactHeightField for NavMesh %s", getIdString()); return false; } if(!rcErodeWalkableArea(ctx, cfg.walkableRadius, *chf)) { Con::errorf("Could not erode walkable area for NavMesh %s", getIdString()); return false; } if(false) { if(!rcBuildRegionsMonotone(ctx, *chf, cfg.borderSize, cfg.minRegionArea, cfg.mergeRegionArea)) { Con::errorf("Could not build regions for NavMesh %s", getIdString()); return false; } } else { if(!rcBuildDistanceField(ctx, *chf)) return false; if(!rcBuildRegions(ctx, *chf, cfg.borderSize, cfg.minRegionArea, cfg.mergeRegionArea)) return false; } cs = rcAllocContourSet(); if(!cs || !rcBuildContours(ctx, *chf, cfg.maxSimplificationError, cfg.maxEdgeLen, *cs)) { Con::errorf("Could not construct rcContourSet for NavMesh %s", getIdString()); return false; } pm = rcAllocPolyMesh(); if(!pm || !rcBuildPolyMesh(ctx, *cs, cfg.maxVertsPerPoly, *pm)) { Con::errorf("Could not construct rcPolyMesh for NavMesh %s", getIdString()); return false; } pmd = rcAllocPolyMeshDetail(); if(!pmd || !rcBuildPolyMeshDetail(ctx, *pm, *chf, cfg.detailSampleDist, cfg.detailSampleMaxError, *pmd)) { Con::errorf("Could not construct rcPolyMeshDetail for NavMesh %s", getIdString()); return false; } return true; }
void mql4j::java::JavaMethodDesc::addArray(Jid id) { argc++; sign += "["; sign += getIdString(id); }
void mql4j::java::JavaMethodDesc::setReturn(Jid id) { sign += ")"; sign += getIdString(id); }
bool getExtractionData(const Game *g, Search &search, ExtractMap &map) { SearchMap searchMap; const int *needList = getNeedList(g); if (!needList) { fprintf(stderr, "ERROR: No entry need list available\n"); return false; } if (!setupSearch(g, needList, search, searchMap)) return false; // Process the data search Search::ResultList results; search.search(results); if (results.empty()) { fprintf(stderr, "ERROR: Couldn't find any required data\n"); return false; } ExtractMap temporaryExtractMap; for (const int *entry = needList; *entry != -1; ++entry) { typedef std::pair<SearchMap::const_iterator, SearchMap::const_iterator> KeyRange; KeyRange idRange = searchMap.equal_range(*entry); for (Search::ResultList::const_iterator i = results.begin(); i != results.end(); ++i) { for (SearchMap::const_iterator j = idRange.first; j != idRange.second; ++j) { if (j->second.hint == i->data) temporaryExtractMap.insert(ExtractMapEntry(*entry, ExtractData(j->second, i->offset))); } } } // Free up some memory results.clear(); searchMap.clear(); bool result = true; for (const int *entry = needList; *entry != -1; ++entry) { MatchList possibleMatches = filterPlatformMatches(g, temporaryExtractMap.equal_range(*entry)); if (possibleMatches.empty()) { fprintf(stderr, "ERROR: No entry found for id %d/%s\n", *entry, getIdString(*entry)); result = false; continue; } if (isLangSpecific(*entry)) { for (int i = 0; i < 3; ++i) { if (g->lang[i] == -1) continue; MatchList langMatches = filterLanguageMatches(g->lang[i], possibleMatches); MatchList::const_iterator bestMatch = filterOutBestMatch(langMatches); if (bestMatch == langMatches.end()) { // TODO: Add nice language name to output message. fprintf(stderr, "ERROR: No entry found for id %d/%s for language %d\n", *entry, getIdString(*entry), g->lang[i]); result = false; continue; } #ifdef DEBUG_EXTRACTION_TABLES if (((*bestMatch)->second.desc.platform != kPlatformUnknown && (*bestMatch)->second.desc.platform != g->platform)) printf("%s: %.8X %.8X %d %d\n", getIdString(*entry), (*bestMatch)->second.desc.hint.size, (*bestMatch)->second.desc.hint.byteSum, (*bestMatch)->second.desc.lang, (*bestMatch)->second.desc.platform); #endif map.insert(**bestMatch); } } else { MatchList::const_iterator bestMatch = filterOutBestMatch(possibleMatches); if (bestMatch == possibleMatches.end()) { fprintf(stderr, "ERROR: No entry found for id %d/%s\n", *entry, getIdString(*entry)); result = false; continue; } #ifdef DEBUG_EXTRACTION_TABLES if (((*bestMatch)->second.desc.platform != kPlatformUnknown && (*bestMatch)->second.desc.platform != g->platform)) printf("%s: %.8X %.8X %d %d\n", getIdString(*entry), (*bestMatch)->second.desc.hint.size, (*bestMatch)->second.desc.hint.byteSum, (*bestMatch)->second.desc.lang, (*bestMatch)->second.desc.platform); #endif map.insert(**bestMatch); } } return result; }
bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) { char filename[128]; Search search(data, size); ExtractMap ids; if (!getExtractionData(g, search, ids)) return false; const int *needList = getNeedList(g); if (!needList) { fprintf(stderr, "ERROR: No entry need list available\n"); return false; } ExtractInformation extractInfo; extractInfo.game = g->game; extractInfo.platform = g->platform; extractInfo.special = g->special; for (ExtractMap::const_iterator i = ids.begin(); i != ids.end(); ++i) { const int id = i->first; extractInfo.lang = i->second.desc.lang; const ExtractFilename *fDesc = getFilenameDesc(id); if (!fDesc) { fprintf(stderr, "ERROR: couldn't find file description for id %d/%s\n", id, getIdString(id)); return false; } filename[0] = 0; if (!getFilename(filename, &extractInfo, id)) { fprintf(stderr, "ERROR: couldn't get filename for id %d/%s\n", id, getIdString(id)); return false; } const ExtractType *tDesc = findExtractType(fDesc->type); if (!tDesc) { fprintf(stderr, "ERROR: couldn't find type description for id %d/%s (%d)\n", id, getIdString(id), fDesc->type); return false; } PAKFile::cFileList *list = out.getFileList(); if (list && list->findEntry(filename) != 0) continue; if (!tDesc->extract(out, &extractInfo, data + i->second.offset, i->second.desc.hint.size, filename, id)) { fprintf(stderr, "ERROR: couldn't extract id %d/%s\n", id, getIdString(id)); return false; } } for (int i = 0; i < 3; ++i) { if (g->lang[i] == -1) continue; extractInfo.lang = g->lang[i]; if (!createIDMap(out, &extractInfo, needList)) return false; if (!updateIndex(out, &extractInfo)) { error("couldn't update INDEX file, stop processing of all files"); return false; } } return true; }
void Item::updatePos(const U32 /*mask*/, const F32 dt) { // Try and move Point3F pos; mObjToWorld.getColumn(3,&pos); delta.posVec = pos; bool contact = false; bool nonStatic = false; bool stickyNotify = false; CollisionList collisionList; F32 time = dt; static Polyhedron sBoxPolyhedron; static ExtrudedPolyList sExtrudedPolyList; static EarlyOutPolyList sEarlyOutPolyList; MatrixF collisionMatrix(true); Point3F end = pos + mVelocity * time; U32 mask = isServerObject() ? sServerCollisionMask : sClientCollisionMask; // Part of our speed problem here is that we don't track contact surfaces, like we do // with the player. In order to handle the most common and performance impacting // instance of this problem, we'll use a ray cast to detect any contact surfaces below // us. This won't be perfect, but it only needs to catch a few of these to make a // big difference. We'll cast from the top center of the bounding box at the tick's // beginning to the bottom center of the box at the end. Point3F startCast((mObjBox.minExtents.x + mObjBox.maxExtents.x) * 0.5, (mObjBox.minExtents.y + mObjBox.maxExtents.y) * 0.5, mObjBox.maxExtents.z); Point3F endCast((mObjBox.minExtents.x + mObjBox.maxExtents.x) * 0.5, (mObjBox.minExtents.y + mObjBox.maxExtents.y) * 0.5, mObjBox.minExtents.z); collisionMatrix.setColumn(3, pos); collisionMatrix.mulP(startCast); collisionMatrix.setColumn(3, end); collisionMatrix.mulP(endCast); RayInfo rinfo; bool doToughCollision = true; disableCollision(); if (mCollisionObject) mCollisionObject->disableCollision(); if (getContainer()->castRay(startCast, endCast, mask, &rinfo)) { F32 bd = -mDot(mVelocity, rinfo.normal); if (bd >= 0.0) { // Contact! if (mDataBlock->sticky && rinfo.object->getTypeMask() & (STATIC_COLLISION_TYPEMASK)) { mVelocity.set(0, 0, 0); mAtRest = true; mAtRestCounter = 0; stickyNotify = true; mStickyCollisionPos = rinfo.point; mStickyCollisionNormal = rinfo.normal; doToughCollision = false;; } else { // Subtract out velocity into surface and friction VectorF fv = mVelocity + rinfo.normal * bd; F32 fvl = fv.len(); if (fvl) { F32 ff = bd * mDataBlock->friction; if (ff < fvl) { fv *= ff / fvl; fvl = ff; } } bd *= 1 + mDataBlock->elasticity; VectorF dv = rinfo.normal * (bd + 0.002); mVelocity += dv; mVelocity -= fv; // Keep track of what we hit contact = true; U32 typeMask = rinfo.object->getTypeMask(); if (!(typeMask & StaticObjectType)) nonStatic = true; if (isServerObject() && (typeMask & ShapeBaseObjectType)) { ShapeBase* col = static_cast<ShapeBase*>(rinfo.object); queueCollision(col,mVelocity - col->getVelocity()); } } } } enableCollision(); if (mCollisionObject) mCollisionObject->enableCollision(); if (doToughCollision) { U32 count; for (count = 0; count < 3; count++) { // Build list from convex states here... end = pos + mVelocity * time; collisionMatrix.setColumn(3, end); Box3F wBox = getObjBox(); collisionMatrix.mul(wBox); Box3F testBox = wBox; Point3F oldMin = testBox.minExtents; Point3F oldMax = testBox.maxExtents; testBox.minExtents.setMin(oldMin + (mVelocity * time)); testBox.maxExtents.setMin(oldMax + (mVelocity * time)); sEarlyOutPolyList.clear(); sEarlyOutPolyList.mNormal.set(0,0,0); sEarlyOutPolyList.mPlaneList.setSize(6); sEarlyOutPolyList.mPlaneList[0].set(wBox.minExtents,VectorF(-1,0,0)); sEarlyOutPolyList.mPlaneList[1].set(wBox.maxExtents,VectorF(0,1,0)); sEarlyOutPolyList.mPlaneList[2].set(wBox.maxExtents,VectorF(1,0,0)); sEarlyOutPolyList.mPlaneList[3].set(wBox.minExtents,VectorF(0,-1,0)); sEarlyOutPolyList.mPlaneList[4].set(wBox.minExtents,VectorF(0,0,-1)); sEarlyOutPolyList.mPlaneList[5].set(wBox.maxExtents,VectorF(0,0,1)); CollisionWorkingList& eorList = mConvex.getWorkingList(); CollisionWorkingList* eopList = eorList.wLink.mNext; while (eopList != &eorList) { if ((eopList->mConvex->getObject()->getTypeMask() & mask) != 0) { Box3F convexBox = eopList->mConvex->getBoundingBox(); if (testBox.isOverlapped(convexBox)) { eopList->mConvex->getPolyList(&sEarlyOutPolyList); if (sEarlyOutPolyList.isEmpty() == false) break; } } eopList = eopList->wLink.mNext; } if (sEarlyOutPolyList.isEmpty()) { pos = end; break; } collisionMatrix.setColumn(3, pos); sBoxPolyhedron.buildBox(collisionMatrix, mObjBox, true); // Build extruded polyList... VectorF vector = end - pos; sExtrudedPolyList.extrude(sBoxPolyhedron, vector); sExtrudedPolyList.setVelocity(mVelocity); sExtrudedPolyList.setCollisionList(&collisionList); CollisionWorkingList& rList = mConvex.getWorkingList(); CollisionWorkingList* pList = rList.wLink.mNext; while (pList != &rList) { if ((pList->mConvex->getObject()->getTypeMask() & mask) != 0) { Box3F convexBox = pList->mConvex->getBoundingBox(); if (testBox.isOverlapped(convexBox)) { pList->mConvex->getPolyList(&sExtrudedPolyList); } } pList = pList->wLink.mNext; } if (collisionList.getTime() < 1.0) { // Set to collision point F32 dt = time * collisionList.getTime(); pos += mVelocity * dt; time -= dt; // Pick the most resistant surface F32 bd = 0; const Collision* collision = 0; for (int c = 0; c < collisionList.getCount(); c++) { const Collision &cp = collisionList[c]; F32 dot = -mDot(mVelocity,cp.normal); if (dot > bd) { bd = dot; collision = &cp; } } if (collision && mDataBlock->sticky && collision->object->getTypeMask() & (STATIC_COLLISION_TYPEMASK)) { mVelocity.set(0, 0, 0); mAtRest = true; mAtRestCounter = 0; stickyNotify = true; mStickyCollisionPos = collision->point; mStickyCollisionNormal = collision->normal; break; } else { // Subtract out velocity into surface and friction if (collision) { VectorF fv = mVelocity + collision->normal * bd; F32 fvl = fv.len(); if (fvl) { F32 ff = bd * mDataBlock->friction; if (ff < fvl) { fv *= ff / fvl; fvl = ff; } } bd *= 1 + mDataBlock->elasticity; VectorF dv = collision->normal * (bd + 0.002); mVelocity += dv; mVelocity -= fv; // Keep track of what we hit contact = true; U32 typeMask = collision->object->getTypeMask(); if (!(typeMask & StaticObjectType)) nonStatic = true; if (isServerObject() && (typeMask & ShapeBaseObjectType)) { ShapeBase* col = static_cast<ShapeBase*>(collision->object); queueCollision(col,mVelocity - col->getVelocity()); } } } } else { pos = end; break; } } if (count == 3) { // Couldn't move... mVelocity.set(0, 0, 0); } } // If on the client, calculate delta for backstepping if (isGhost()) { delta.pos = pos; delta.posVec -= pos; delta.dt = 1; } // Update transform MatrixF mat = mObjToWorld; mat.setColumn(3,pos); Parent::setTransform(mat); enableCollision(); if (mCollisionObject) mCollisionObject->enableCollision(); updateContainer(); if ( mPhysicsRep ) mPhysicsRep->setTransform( mat ); // if (contact) { // Check for rest condition if (!nonStatic && mVelocity.len() < sAtRestVelocity) { mVelocity.x = mVelocity.y = mVelocity.z = 0; mAtRest = true; mAtRestCounter = 0; } // Only update the client if we hit a non-static shape or // if this is our final rest pos. if (nonStatic || mAtRest) setMaskBits(PositionMask); } // Collision callbacks. These need to be processed whether we hit // anything or not. if (!isGhost()) { SimObjectPtr<Item> safePtr(this); if (stickyNotify) { notifyCollision(); if(bool(safePtr)) onStickyCollision_callback( getIdString() ); } else notifyCollision(); // water if(bool(safePtr)) { if(!mInLiquid && mWaterCoverage != 0.0f) { mInLiquid = true; if ( !isGhost() ) mDataBlock->onEnterLiquid_callback( this, mWaterCoverage, mLiquidType.c_str() ); } else if(mInLiquid && mWaterCoverage == 0.0f) { mInLiquid = false; if ( !isGhost() ) mDataBlock->onLeaveLiquid_callback( this, mLiquidType.c_str() ); } } } }