当前位置: 首页>>代码示例>>C++>>正文


C++ GFXVertexBufferHandle::lock方法代码示例

本文整理汇总了C++中GFXVertexBufferHandle::lock方法的典型用法代码示例。如果您正苦于以下问题:C++ GFXVertexBufferHandle::lock方法的具体用法?C++ GFXVertexBufferHandle::lock怎么用?C++ GFXVertexBufferHandle::lock使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在GFXVertexBufferHandle的用法示例。


在下文中一共展示了GFXVertexBufferHandle::lock方法的9个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: drawRect

void GFXDrawUtil::drawRect( const Point2F &upperLeft, const Point2F &lowerRight, const ColorI &color )
{
   //
   // Convert Box   a----------x
   //               |          |
   //               x----------b
   //
   // Into Triangle-Strip Outline
   //               v0-----------v2
   //               | a         x |
   //               |  v1-----v3  |
   //               |   |     |   |
   //               |  v7-----v5  |
   //               | x         b |
   //               v6-----------v4
   //

   // NorthWest and NorthEast facing offset vectors
   // These adjust the thickness of the line, it'd be neat if one day
   // they were passed in as arguments.
   Point2F nw(-0.5f,-0.5f); /*  \  */
   Point2F ne(0.5f,-0.5f); /*  /  */

   GFXVertexBufferHandle<GFXVertexPC> verts (mDevice, 10, GFXBufferTypeVolatile );
   verts.lock();

   F32 ulOffset = 0.5f - mDevice->getFillConventionOffset();

   verts[0].point.set( upperLeft.x + ulOffset + nw.x, upperLeft.y + ulOffset + nw.y, 0.0f );
   verts[1].point.set( upperLeft.x + ulOffset - nw.x, upperLeft.y + ulOffset - nw.y, 0.0f );
   verts[2].point.set( lowerRight.x + ne.x, upperLeft.y + ulOffset + ne.y, 0.0f );
   verts[3].point.set( lowerRight.x - ne.x, upperLeft.y + ulOffset - ne.y, 0.0f );
   verts[4].point.set( lowerRight.x - nw.x, lowerRight.y - nw.y, 0.0f );
   verts[5].point.set( lowerRight.x + nw.x, lowerRight.y + nw.y, 0.0f );
   verts[6].point.set( upperLeft.x + ulOffset - ne.x, lowerRight.y - ne.y, 0.0f );
   verts[7].point.set( upperLeft.x + ulOffset + ne.x, lowerRight.y + ne.y, 0.0f );
   verts[8].point.set( upperLeft.x + ulOffset + nw.x, upperLeft.y + ulOffset + nw.y, 0.0f ); // same as 0
   verts[9].point.set( upperLeft.x + ulOffset - nw.x, upperLeft.y + ulOffset - nw.y, 0.0f ); // same as 1

   for (S32 i=0; i<10; i++)
      verts[i].color = color;

   verts.unlock();
   mDevice->setVertexBuffer( verts );

   mDevice->setStateBlock(mRectFillSB);
   mDevice->setupGenericShaders();
   mDevice->drawPrimitive( GFXTriangleStrip, 0, 8 );
}
开发者ID:mray,项目名称:terminal-overload,代码行数:49,代码来源:gfxDrawUtil.cpp

示例2: endToBuffer

//-----------------------------------------------------------------------------
// end
//-----------------------------------------------------------------------------
GFXVertexBuffer * endToBuffer( U32 &numPrims )
{
   mVertBuff.set(GFX, mTempVertBuff.size(), GFXBufferTypeVolatile);
   GFXVertexPCT *verts = mVertBuff.lock();
   dMemcpy( verts, mTempVertBuff.address(), mTempVertBuff.size() * sizeof(GFXVertexPCT) );
   mVertBuff.unlock();

   VERTEX_SIZE_CHECK();

   switch( mType )
   {
      case GFXPointList:
      {
         numPrims = mCurVertIndex;
         break;
      }

      case GFXLineList:
      {
         numPrims = mCurVertIndex / 2;
         break;
      }

      case GFXLineStrip:
      {
         numPrims = mCurVertIndex - 1;
         break;
      }

      case GFXTriangleList:
      {
         numPrims = mCurVertIndex / 3;
         break;
      }

      case GFXTriangleStrip:
      case GFXTriangleFan:
      {
         numPrims = mCurVertIndex - 2;
         break;
      }
      case GFXPT_COUNT:
         // handle warning
         break;
   }

   return mVertBuff;
}
开发者ID:Adhdcrazzy,项目名称:Torque3D,代码行数:51,代码来源:primBuilder.cpp

示例3: renderTimeMap

void CameraSpline::renderTimeMap()
{
   buildTimeMap();

   gBuilding = true;

   // Build vertex buffer
   GFXVertexBufferHandle<GFXVertexPCT> vb;
   vb.set(GFX, mTimeMap.size(), GFXBufferTypeVolatile);
   void *ptr = vb.lock();
   if(!ptr) return;

   MRandomLCG random(1376312589 * (uintptr_t)this);
   S32 index = 0;
   for(Vector<TimeMap>::iterator itr=mTimeMap.begin(); itr != mTimeMap.end(); itr++)
   {
      Knot a;
      value(itr->mTime, &a, true);

      S32 cr = random.randI(0,255);
      S32 cg = random.randI(0,255);
      S32 cb = random.randI(0,255);
      vb[index].color.set(cr, cg, cb);
      vb[index].point.set(a.mPosition.x, a.mPosition.y, a.mPosition.z);
      index++;
   }

   gBuilding = false;

   vb.unlock();

   // Render the buffer
   GFX->pushWorldMatrix();
   GFX->setupGenericShaders();
   GFX->setVertexBuffer(vb);
   GFX->drawPrimitive(GFXLineStrip,0,index);
   GFX->popWorldMatrix();
}
开发者ID:03050903,项目名称:Torque3D,代码行数:38,代码来源:cameraSpline.cpp

示例4: _renderMoon

void ScatterSky::_renderMoon( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
{
   if ( !mMoonMatInst )
      return;

   Point3F moonlightPosition = state->getCameraPosition() - /*mLight->getDirection()*/ mMoonLightDir * state->getFarPlane() * 0.9f;
   F32 dist = (moonlightPosition - state->getCameraPosition()).len();

   // worldRadius = screenRadius * dist / worldToScreen
   // screenRadius = worldRadius / dist * worldToScreen

   //
   F32 screenRadius = GFX->getViewport().extent.y * mMoonScale * 0.5f;
   F32 worldRadius = screenRadius * dist / state->getWorldToScreenScale().y;

   // Calculate Billboard Radius (in world units) to be constant, independent of distance.
   // Takes into account distance, viewport size, and specified size in editor

   F32 BBRadius = worldRadius;


   mMatrixSet->restoreSceneViewProjection();

   if ( state->isReflectPass() )
      mMatrixSet->setProjection( state->getSceneManager()->getNonClipProjection() );

   mMatrixSet->setWorld( MatrixF::Identity );

   // Initialize points with basic info
   Point3F points[4];
   points[0] = Point3F(-BBRadius, 0.0, -BBRadius);
   points[1] = Point3F( -BBRadius, 0.0, BBRadius);
   points[2] = Point3F( BBRadius, 0.0,  BBRadius);
   points[3] = Point3F( BBRadius, 0.0,  -BBRadius);

   static const Point2F sCoords[4] =
   {
      Point2F( 0.0f, 0.0f ),
      Point2F( 0.0f, 1.0f ),
      Point2F( 1.0f, 1.0f ),
      Point2F( 1.0f, 0.0f )
   };

   // Get info we need to adjust points
   const MatrixF &camView = state->getCameraTransform();

   // Finalize points
   for(int i = 0; i < 4; i++)
   {
      // align with camera
      camView.mulV(points[i]);
      // offset
      points[i] += moonlightPosition;
   }

   // Vertex color.
   ColorF moonVertColor( 1.0f, 1.0f, 1.0f, mNightInterpolant );

   // Copy points to buffer.

   GFXVertexBufferHandle< GFXVertexPCT > vb;
   vb.set( GFX, 4, GFXBufferTypeVolatile );
   GFXVertexPCT *pVert = vb.lock();

   for ( S32 i = 0; i < 4; i++ )
   {
      pVert->color.set( moonVertColor );
      pVert->point.set( points[i] );
      pVert->texCoord.set( sCoords[i].x, sCoords[i].y );
      pVert++;
   }

   vb.unlock();

   // Setup SceneData struct.

   SceneData sgData;
   sgData.wireframe = GFXDevice::getWireframe();
   sgData.visibility = 1.0f;

   // Draw it

   while ( mMoonMatInst->setupPass( state, sgData ) )
   {
      mMoonMatInst->setTransforms( *mMatrixSet, state );
      mMoonMatInst->setSceneInfo( state, sgData );

      GFX->setVertexBuffer( vb );
      GFX->drawPrimitive( GFXTriangleFan, 0, 2 );
   }
}
开发者ID:AkiraofAstra,项目名称:Torque3D,代码行数:91,代码来源:scatterSky.cpp

示例5: _updateBaseTexture

void TerrainBlock::_updateBaseTexture(bool writeToCache)
{
   if ( !mBaseShader && !_initBaseShader() )
      return;

   // This can sometimes occur outside a begin/end scene.
   const bool sceneBegun = GFX->canCurrentlyRender();
   if ( !sceneBegun )
      GFX->beginScene();

   GFXDEBUGEVENT_SCOPE( TerrainBlock_UpdateBaseTexture, ColorI::GREEN );

   PROFILE_SCOPE( TerrainBlock_UpdateBaseTexture );

   GFXTransformSaver saver;

   const U32 maxTextureSize = GFX->getCardProfiler()->queryProfile( "maxTextureSize", 1024 );

   U32 baseTexSize = getNextPow2( mBaseTexSize );
   baseTexSize = getMin( maxTextureSize, baseTexSize );
   Point2I destSize( baseTexSize, baseTexSize );

   // Setup geometry
   GFXVertexBufferHandle<GFXVertexPT> vb;
   {
      F32 copyOffsetX = 2.0f * GFX->getFillConventionOffset() / (F32)destSize.x;
      F32 copyOffsetY = 2.0f * GFX->getFillConventionOffset() / (F32)destSize.y;

      GFXVertexPT points[4];
      points[0].point = Point3F(1.0 - copyOffsetX, -1.0 + copyOffsetY, 0.0);
      points[0].texCoord = Point2F(1.0, 1.0f);
      points[1].point = Point3F(1.0 - copyOffsetX, 1.0 + copyOffsetY, 0.0);
      points[1].texCoord = Point2F(1.0, 0.0f);
      points[2].point = Point3F(-1.0 - copyOffsetX, -1.0 + copyOffsetY, 0.0);
      points[2].texCoord = Point2F(0.0, 1.0f);
      points[3].point = Point3F(-1.0 - copyOffsetX, 1.0 + copyOffsetY, 0.0);
      points[3].texCoord = Point2F(0.0, 0.0f);

      vb.set( GFX, 4, GFXBufferTypeVolatile );
      GFXVertexPT *ptr = vb.lock();
      if(ptr)
      {
         dMemcpy( ptr, points, sizeof(GFXVertexPT) * 4 );
         vb.unlock();
      }
   }

   GFXTexHandle blendTex;

   // If the base texture is already a valid render target then 
   // use it to render to else we create one.
   if (  mBaseTex.isValid() && 
         mBaseTex->isRenderTarget() &&
         mBaseTex->getFormat() == GFXFormatR8G8B8A8 &&
         mBaseTex->getWidth() == destSize.x &&
         mBaseTex->getHeight() == destSize.y )
      blendTex = mBaseTex;
   else
      blendTex.set( destSize.x, destSize.y, GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, "" );

   GFX->pushActiveRenderTarget();   

   // Set our shader stuff
   GFX->setShader( mBaseShader );
   GFX->setShaderConstBuffer( mBaseShaderConsts );
   GFX->setStateBlock( mBaseShaderSB );
   GFX->setVertexBuffer( vb );

   mBaseTarget->attachTexture( GFXTextureTarget::Color0, blendTex );
   GFX->setActiveRenderTarget( mBaseTarget );

   GFX->clear( GFXClearTarget, ColorI(0,0,0,255), 1.0f, 0 );

   GFX->setTexture( 0, mLayerTex );
   mBaseShaderConsts->setSafe( mBaseLayerSizeConst, (F32)mLayerTex->getWidth() );      

   for ( U32 i=0; i < mBaseTextures.size(); i++ )
   {
      GFXTextureObject *tex = mBaseTextures[i];
      if ( !tex )
         continue;

      GFX->setTexture( 1, tex );

      F32 baseSize = mFile->mMaterials[i]->getDiffuseSize();
      F32 scale = 1.0f;
      if ( !mIsZero( baseSize ) )
         scale = getWorldBlockSize() / baseSize;
      
      // A mistake early in development means that texture
      // coords are not flipped correctly.  To compensate
      // we flip the y scale here.
      mBaseShaderConsts->setSafe( mBaseTexScaleConst, Point2F( scale, -scale ) );
      mBaseShaderConsts->setSafe( mBaseTexIdConst, (F32)i );

      GFX->drawPrimitive( GFXTriangleStrip, 0, 2 );
   }

   mBaseTarget->resolve();
   
//.........这里部分代码省略.........
开发者ID:03050903,项目名称:Torque3D,代码行数:101,代码来源:terrRender.cpp

示例6: prepRenderImage

bool DecalManager::prepRenderImage(SceneState* state, const U32 stateKey,
                                   const U32 /*startZone*/, const bool /*modifyBaseState*/)
{
   PROFILE_SCOPE( DecalManager_RenderDecals );

   if ( !smDecalsOn || !mData ) 
      return false;

   if (isLastState(state, stateKey))
      return false;
   setLastState(state, stateKey);

   if ( !state->isDiffusePass() && !state->isReflectPass() )
      return false;

   PROFILE_START( DecalManager_RenderDecals_SphereTreeCull );

   // Grab this before anything here changes it.
   mCuller = state->getFrustum();

   // Populate vector of decal instances to be rendered with all
   // decals from visible decal spheres.

   mDecalQueue.clear();

   const Vector<DecalSphere*> &grid = mData->getGrid();
   
   for ( U32 i = 0; i < grid.size(); i++ )
   {
      const DecalSphere *decalSphere = grid[i];
      const SphereF &worldSphere = decalSphere->mWorldSphere;
      if ( !mCuller.sphereInFrustum( worldSphere.center, worldSphere.radius ) )
         continue;

      // TODO: If each sphere stored its largest decal instance we
      // could do an LOD step on it here and skip adding any of the
      // decals in the sphere.

      mDecalQueue.merge( decalSphere->mItems );
   }

   PROFILE_END();

   PROFILE_START( DecalManager_RenderDecals_Update );

   const U32 &curSimTime = Sim::getCurrentTime();
   const Point2I &viewportExtent = state->getViewportExtent();
   Point3F cameraOffset; 
   F32   decalSize, 
         pixelRadius;
   U32 delta, diff;
   DecalInstance *dinst;

   // Loop through DecalQueue once for preRendering work.
   // 1. Update DecalInstance fade (over time)
   // 2. Clip geometry if flagged to do so.
   // 3. Calculate lod - if decal is far enough away it will not render.
   for ( U32 i = 0; i < mDecalQueue.size(); i++ )
   {
      dinst = mDecalQueue[i];

      // LOD calculation.
      // See TSShapeInstance::setDetailFromDistance for more
      // information on these calculations.
      decalSize = getMax( dinst->mSize, 0.001f );
      pixelRadius = dinst->calcPixelRadius( state );

      // Need to clamp here.
      if ( pixelRadius < dinst->calcEndPixRadius( viewportExtent ) )
      {
         mDecalQueue.erase_fast( i );
         i--;
         continue;
      }

      // We're gonna try to render this decal... so do any 
      // final adjustments to it before rendering.

      // Update fade and delete expired.
      if ( !( dinst->mFlags & PermanentDecal || dinst->mFlags & CustomDecal ) )
      {         
         delta = ( curSimTime - dinst->mCreateTime );
         if ( delta > dinst->mDataBlock->lifeSpan )         
         {            
            diff = delta - dinst->mDataBlock->lifeSpan;
            dinst->mVisibility = 1.0f - (F32)diff / (F32)dinst->mDataBlock->fadeTime;

            if ( dinst->mVisibility <= 0.0f )
            {
               mDecalQueue.erase_fast( i );
               removeDecal( dinst );               
               i--;
               continue;
            }
         }
      }

      // Build clipped geometry for this decal if needed.
      if ( dinst->mFlags & ClipDecal/* && !( dinst->mFlags & CustomDecal ) */)
      {  
//.........这里部分代码省略.........
开发者ID:adhistac,项目名称:ee-client-2-0,代码行数:101,代码来源:decalManager.cpp

示例7: generateGrid

void GroundPlane::generateGrid( U32 width, U32 height, F32 squareSize,
                                const Point2F& min, const Point2F& max,
                                GFXVertexBufferHandle< VertexType >& outVertices,
                                GFXPrimitiveBufferHandle& outPrimitives )
{
   // Generate the vertices.

   VertexType* vertices = outVertices.lock();
   for( F32 y = min.y; y <= max.y; y += squareSize )
      for( F32 x = min.x; x <= max.x; x += squareSize )
      {
         vertices->point.x = x;
         vertices->point.y = y;
         vertices->point.z = 0.0;

         vertices->texCoord.x = ( x / squareSize ) * mScaleU;
         vertices->texCoord.y = ( y / squareSize ) * -mScaleV;

         vertices->normal.x = 0.0f;
         vertices->normal.y = 0.0f;
         vertices->normal.z = 1.0f;

         vertices->tangent.x = 1.0f;
         vertices->tangent.y = 0.0f;
         vertices->tangent.z = 0.0f;

         vertices->binormal.x = 0.0f;
         vertices->binormal.y = 1.0f;
         vertices->binormal.z = 0.0f;

         vertices++;
      }
   outVertices.unlock();

   // Generate the indices.

   U16* indices;
   outPrimitives.lock( &indices );
   
   U16 corner1 = 0;
   U16 corner2 = 1;
   U16 corner3 = width + 1;
   U16 corner4 = width + 2;
   
   for( U32 y = 0; y < height; ++ y )
   {
      for( U32 x = 0; x < width; ++ x )
      {
         indices[ 0 ] = corner3;
         indices[ 1 ] = corner2;
         indices[ 2 ] = corner1;

         indices += 3;

         indices[ 0 ] = corner3;
         indices[ 1 ] = corner4;
         indices[ 2 ] = corner2;

         indices += 3;

         corner1 ++;
         corner2 ++;
         corner3 ++;
         corner4 ++;
      }

      corner1 ++;
      corner2 ++;
      corner3 ++;
      corner4 ++;
   }

   outPrimitives.unlock();
}
开发者ID:Dwarf-King,项目名称:OmniEngine.Net,代码行数:74,代码来源:groundPlane.cpp

示例8: _renderCorona

void Sun::_renderCorona( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
{   
   // Calculate Billboard Radius (in world units) to be constant, independent of distance.
   // Takes into account distance, viewport size, and specified size in editor
   F32 BBRadius = mCoronaWorldRadius;

   mMatrixSet->restoreSceneViewProjection();   
   
   if ( state->isReflectPass() )
      mMatrixSet->setProjection( state->getSceneManager()->getNonClipProjection() );

   //mMatrixSet->setWorld( MatrixF::Identity );

   // Initialize points with basic info
   Point3F points[4];
   points[0] = Point3F(-BBRadius, 0.0, -BBRadius);
   points[1] = Point3F( -BBRadius, 0.0, BBRadius);
   points[2] = Point3F( BBRadius, 0.0,  BBRadius);
   points[3] = Point3F( BBRadius, 0.0,  -BBRadius);

   static const Point2F sCoords[4] = 
   {
      Point2F( 0.0f, 0.0f ),
      Point2F( 0.0f, 1.0f ),      
      Point2F( 1.0f, 1.0f ),
      Point2F( 1.0f, 0.0f )
   };

   // Get info we need to adjust points
   const MatrixF &camView = state->getCameraTransform();

   // Finalize points
   for(S32 i = 0; i < 4; i++)
   {
      // align with camera
      camView.mulV(points[i]);
      // offset
      points[i] += mLightWorldPos;
   }

   ColorF vertColor;
   if ( mCoronaUseLightColor )
      vertColor = mLightColor;
   else
      vertColor = mCoronaTint;

   GFXVertexBufferHandle< GFXVertexPCT > vb;
   vb.set( GFX, 4, GFXBufferTypeVolatile );
   GFXVertexPCT *pVert = vb.lock();
   if(!pVert) return;

   for ( S32 i = 0; i < 4; i++ )
   {
      pVert->color.set( vertColor );
      pVert->point.set( points[i] );
      pVert->texCoord.set( sCoords[i].x, sCoords[i].y );
      pVert++;
   }

   vb.unlock();

   // Setup SceneData struct.

   SceneData sgData;
   sgData.wireframe = GFXDevice::getWireframe();
   sgData.visibility = 1.0f;

   // Draw it

   while ( mCoronaMatInst->setupPass( state, sgData ) )
   {
      mCoronaMatInst->setTransforms( *mMatrixSet, state );
      mCoronaMatInst->setSceneInfo( state, sgData );

      GFX->setVertexBuffer( vb );      
      GFX->drawPrimitive( GFXTriangleFan, 0, 2 );
   }
}
开发者ID:AlkexGas,项目名称:Torque3D,代码行数:78,代码来源:sun.cpp

示例9: end

void end( bool useGenericShaders )
{
   if ( mCurVertIndex == 0 ) 
      return; 

   VERTEX_SIZE_CHECK();

   U32 vertStride = 1;
   U32 stripStart = 0;

   AssertFatal( mType >= GFXPT_FIRST && mType < GFXPT_COUNT, "PrimBuilder::end() - Bad primitive type!" );
               
   switch( mType )
   {
      default:
      case GFXPointList:
      {
         vertStride = 1;
         break;
      }

      case GFXLineList:
      {
         vertStride = 2;
         break;
      }

      case GFXTriangleList:
      {
         vertStride = 3;
         break;
      }

      case GFXLineStrip:
      {
         stripStart = 1;
         vertStride = 1;
         break;
      }

      case GFXTriangleStrip:
      case GFXTriangleFan:
      {
         stripStart = 2;
         vertStride = 1;
         break;
      }
   }

   if ( useGenericShaders )
      GFX->setupGenericShaders( GFXDevice::GSModColorTexture );

   const GFXVertexPCT *srcVerts = mTempVertBuff.address();
   U32 numVerts = mCurVertIndex;
   
   // Make sure we don't have a dirty prim buffer left.
   GFX->setPrimitiveBuffer( NULL );

   if ( stripStart > 0 )
   {
      // TODO: Fix this to allow > MAX_DYNAMIC_VERTS!

      U32 copyVerts = getMin( (U32)MAX_DYNAMIC_VERTS, numVerts );
      mVertBuff.set( GFX, copyVerts, GFXBufferTypeVolatile );

      GFXVertexPCT *verts = mVertBuff.lock();
      dMemcpy( verts, srcVerts, copyVerts * sizeof( GFXVertexPCT ) );
      mVertBuff.unlock();

      U32 numPrims = ( copyVerts / vertStride ) - stripStart;
      GFX->setVertexBuffer( mVertBuff );
      GFX->drawPrimitive( mType, 0, numPrims );
   }
   else
   {
      while ( numVerts > 0 )
      {
         U32 copyVerts = getMin( (U32)MAX_DYNAMIC_VERTS, numVerts );
         copyVerts -= copyVerts % vertStride;

         mVertBuff.set( GFX, copyVerts, GFXBufferTypeVolatile );

         GFXVertexPCT *verts = mVertBuff.lock();
         dMemcpy( verts, srcVerts, copyVerts * sizeof( GFXVertexPCT ) );
         mVertBuff.unlock();

         U32 numPrims = copyVerts / vertStride;
         GFX->setVertexBuffer( mVertBuff );
         GFX->drawPrimitive( mType, 0, numPrims );

         srcVerts += copyVerts;
         numVerts -= copyVerts;
      }
   }
}
开发者ID:Adhdcrazzy,项目名称:Torque3D,代码行数:95,代码来源:primBuilder.cpp


注:本文中的GFXVertexBufferHandle::lock方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。