//----------------------------------------------------------------------------- // Enumerate D3D adapters //----------------------------------------------------------------------------- void GFXPCD3D9Device::enumerateAdapters( Vector<GFXAdapter*> &adapterList ) { // Grab a D3D9 handle here to first get the D3D9 devices LPDIRECT3D9 d3d9; LPDIRECT3D9EX d3d9ex; createDirect3D9( d3d9, d3d9ex); // If we could not create the d3d9 object then either the system // is corrupt or they need to update the directx runtime. if ( !d3d9 ) { Con::errorf( "Unsupported DirectX version!" ); Platform::messageBox( Con::getVariable( "$appName" ), "DirectX could not be started!\r\n" "Please be sure you have the latest version of DirectX installed.", MBOk, MIStop ); Platform::forceShutdown( -1 ); } for( U32 adapterIndex = 0; adapterIndex < d3d9->GetAdapterCount(); adapterIndex++ ) { GFXAdapter *toAdd = new GFXAdapter; toAdd->mType = Direct3D9; toAdd->mIndex = adapterIndex; toAdd->mCreateDeviceInstanceDelegate = mCreateDeviceInstance; // Grab the shader model. D3DCAPS9 caps; d3d9->GetDeviceCaps(adapterIndex, D3DDEVTYPE_HAL, &caps); U8 *pxPtr = (U8*) &caps.PixelShaderVersion; toAdd->mShaderModel = pxPtr[1] + pxPtr[0] * 0.1; // Get the device description string. D3DADAPTER_IDENTIFIER9 temp; d3d9->GetAdapterIdentifier( adapterIndex, NULL, &temp ); // The NULL is the flags which deal with WHQL dStrncpy(toAdd->mName, temp.Description, GFXAdapter::MaxAdapterNameLen); dStrncat(toAdd->mName, " (D3D9)", GFXAdapter::MaxAdapterNameLen); // And the output display device name dStrncpy(toAdd->mOutputName, temp.DeviceName, GFXAdapter::MaxAdapterNameLen); // Video mode enumeration. Vector<D3DFORMAT> formats( __FILE__, __LINE__ ); formats.push_back( D3DFMT_R5G6B5 ); // D3DFMT_R5G6B5 - 16bit format formats.push_back( D3DFMT_X8R8G8B8 ); // D3DFMT_X8R8G8B8 - 32bit format for( S32 i = 0; i < formats.size(); i++ ) { DWORD MaxSampleQualities; d3d9->CheckDeviceMultiSampleType(adapterIndex, D3DDEVTYPE_HAL, formats[i], FALSE, D3DMULTISAMPLE_NONMASKABLE, &MaxSampleQualities); for( U32 j = 0; j < d3d9->GetAdapterModeCount( adapterIndex, formats[i] ); j++ ) { D3DDISPLAYMODE mode; d3d9->EnumAdapterModes( adapterIndex, formats[i], j, &mode ); GFXVideoMode vmAdd; vmAdd.bitDepth = ( i == 0 ? 16 : 32 ); // This will need to be changed later vmAdd.fullScreen = true; vmAdd.refreshRate = mode.RefreshRate; vmAdd.resolution = Point2I( mode.Width, mode.Height ); vmAdd.antialiasLevel = MaxSampleQualities; toAdd->mAvailableModes.push_back( vmAdd ); } } adapterList.push_back( toAdd ); } d3d9->Release(); }
void TerrCell::_init( TerrainBlock *terrain, const Point2I &point, U32 size, U32 level ) { PROFILE_SCOPE( TerrCell_Init ); mTerrain = terrain; mPoint = point; mSize = size; mLevel = level; // Generate a VB (and maybe a PB) for this cell, unless we are the Root cell. if ( level > 0 ) { _updateVertexBuffer(); _updatePrimitiveBuffer(); } if ( mSize <= smMinCellSize ) { // Update our bounds and materials... the // parent will use it to update itself. _updateBounds(); _updateMaterials(); return; } // Create our children and update our // bounds and materials from them. const U32 childSize = mSize / 2; const U32 childLevel = mLevel + 1; mChildren[0] = new TerrCell; mChildren[0]->_init( mTerrain, Point2I( mPoint.x, mPoint.y ), childSize, childLevel ); mBounds = mChildren[0]->getBounds(); mMaterials = mChildren[0]->getMaterials(); mChildren[1] = new TerrCell; mChildren[1]->_init( mTerrain, Point2I( mPoint.x + childSize, mPoint.y ), childSize, childLevel ); mBounds.intersect( mChildren[1]->getBounds() ); mMaterials |= mChildren[1]->getMaterials(); mChildren[2] = new TerrCell; mChildren[2]->_init( mTerrain, Point2I( mPoint.x, mPoint.y + childSize ), childSize, childLevel ); mBounds.intersect( mChildren[2]->getBounds() ); mMaterials |= mChildren[2]->getMaterials(); mChildren[3] = new TerrCell; mChildren[3]->_init( mTerrain, Point2I( mPoint.x + childSize, mPoint.y + childSize ), childSize, childLevel ); mBounds.intersect( mChildren[3]->getBounds() ); mMaterials |= mChildren[3]->getMaterials(); mRadius = mBounds.len() * 0.5f; _updateOBB(); }
void GuiRiverEditorCtrl::_process3DMouseDown( const Gui3DMouseEvent& event ) { // Get the raycast collision position Point3F tPos; if ( !getStaticPos( event, tPos ) ) return; mouseLock(); // Construct a LineSegment from the camera position to 1000 meters away in // the direction clicked. // If that segment hits the terrain, truncate the ray to only be that length. // We will use a LineSegment/Sphere intersection test to determine if a RiverNode // was clicked. Point3F startPnt = event.pos; Point3F endPnt = event.pos + event.vec * 1000.0f; RayInfo ri; if ( gServerContainer.castRay(startPnt, endPnt, StaticShapeObjectType, &ri) ) endPnt = ri.point; River *riverPtr = NULL; River *clickedRiverPtr = NULL; // Did we click on a river? check current selection first U32 insertNodeIdx = -1; Point3F collisionPnt; if ( mSelRiver != NULL && mSelRiver->collideRay( event.pos, event.vec, &insertNodeIdx, &collisionPnt ) ) { clickedRiverPtr = mSelRiver; } else { for ( SimSetIterator iter(mRiverSet); *iter; ++iter ) { riverPtr = static_cast<River*>( *iter ); // Do not select or edit a River within a Prefab. if ( Prefab::getPrefabByChild(riverPtr) ) continue; if ( riverPtr->collideRay( event.pos, event.vec, &insertNodeIdx, &collisionPnt ) ) { clickedRiverPtr = riverPtr; break; } } } // Did we click on a riverNode? bool nodeClicked = false; S32 clickedNodeIdx = -1; F32 clickedNodeDist = mNodeSphereRadius; // If we clicked on the currently selected river, only scan its nodes if ( mSelRiver != NULL && clickedRiverPtr == mSelRiver ) { for ( U32 i = 0; i < mSelRiver->mNodes.size(); i++ ) { const Point3F &nodePos = mSelRiver->mNodes[i].point; Point3F screenPos; project( nodePos, &screenPos ); F32 dist = ( event.mousePoint - Point2I(screenPos.x, screenPos.y) ).len(); if ( dist < clickedNodeDist ) { clickedNodeDist = dist; clickedNodeIdx = i; insertNodeIdx = i; nodeClicked = true; } } } else { for ( SimSetIterator iter(mRiverSet); *iter; ++iter ) { riverPtr = static_cast<River*>( *iter ); // Do not select or edit a River within a Prefab. if ( Prefab::getPrefabByChild(riverPtr) ) continue; for ( U32 i = 0; i < riverPtr->mNodes.size(); i++ ) { const Point3F &nodePos = riverPtr->mNodes[i].point; Point3F screenPos; project( nodePos, &screenPos ); F32 dist = ( event.mousePoint - Point2I(screenPos.x, screenPos.y) ).len(); if ( dist < clickedNodeDist ) { // we found a hit! clickedNodeDist = dist; clickedNodeIdx = i; insertNodeIdx = i; nodeClicked = true; clickedRiverPtr = riverPtr; } } } } // shortcuts bool dblClick = ( event.mouseClickCount > 1 ); if( dblClick ) { if( mMode == mSelectRiverMode ) { setMode( mAddRiverMode, true ); return; } if( mMode == mAddNodeMode ) { // Delete the node attached to the cursor. deleteSelectedNode(); mMode = mAddRiverMode; return; } } //this check is here in order to bounce back from deleting a whole road with ctrl+z //this check places the editor back into addrivermode if ( mMode == mAddNodeMode ) { if ( !mSelRiver ) mMode = mAddRiverMode; } if ( mMode == mSelectRiverMode ) { // Did not click on a River or a node. if ( !clickedRiverPtr ) { setSelectedRiver( NULL ); setSelectedNode( -1 ); return; } // Clicked on a River that wasn't the currently selected River. if ( clickedRiverPtr != mSelRiver ) { setSelectedRiver( clickedRiverPtr ); setSelectedNode( clickedNodeIdx ); return; } // Clicked on a node in the currently selected River that wasn't // the currently selected node. if ( nodeClicked ) { setSelectedNode( clickedNodeIdx ); return; } } else if ( mMode == mAddRiverMode ) { if ( nodeClicked ) { // A double-click on a node in Normal mode means set AddNode mode. if ( clickedNodeIdx == 0 ) { setSelectedRiver( clickedRiverPtr ); setSelectedNode( clickedNodeIdx ); mAddNodeIdx = clickedNodeIdx; mMode = mAddNodeMode; mSelNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx ); mIsDirty = true; return; } else if ( clickedNodeIdx == clickedRiverPtr->mNodes.size() - 1 ) { setSelectedRiver( clickedRiverPtr ); setSelectedNode( clickedNodeIdx ); mAddNodeIdx = U32_MAX; mMode = mAddNodeMode; mSelNode = mSelRiver->addNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal); mIsDirty = true; setSelectedNode( mSelNode ); return; } } if ( !isMethod( "createRiver" ) ) { Con::errorf( "GuiRiverEditorCtrl::on3DMouseDown - createRiver method does not exist." ); return; } const char *res = Con::executef( this, "createRiver" ); River *newRiver; if ( !Sim::findObject( res, newRiver ) ) { Con::errorf( "GuiRiverEditorCtrl::on3DMouseDown - createRiver method did not return a river object." ); return; } // Add to MissionGroup SimGroup *missionGroup; if ( !Sim::findObject( "MissionGroup", missionGroup ) ) Con::errorf( "GuiRiverEditorCtrl - could not find MissionGroup to add new River" ); else missionGroup->addObject( newRiver ); Point3F pos( endPnt ); pos.z += mDefaultDepth * 0.5f; newRiver->insertNode( pos, mDefaultWidth, mDefaultDepth, mDefaultNormal, 0 ); U32 newNode = newRiver->insertNode( pos, mDefaultWidth, mDefaultDepth, mDefaultNormal, 1 ); // Always add to the end of the road, the first node is the start. mAddNodeIdx = U32_MAX; setSelectedRiver( newRiver ); setSelectedNode( newNode ); mMode = mAddNodeMode; // Disable the hover node while in addNodeMode, we // don't want some random node enlarged. mHoverNode = -1; // Grab the mission editor undo manager. UndoManager *undoMan = NULL; if ( !Sim::findObject( "EUndoManager", undoMan ) ) { Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" ); return; } // Create the UndoAction. MECreateUndoAction *action = new MECreateUndoAction("Create MeshRoad"); action->addObject( newRiver ); // Submit it. undoMan->addAction( action ); return; } else if ( mMode == mAddNodeMode ) { // Oops the road got deleted, maybe from an undo action? // Back to NormalMode. if ( mSelRiver ) { // A double-click on a node in Normal mode means set AddNode mode. if ( clickedNodeIdx == 0 ) { submitUndo( "Add Node" ); mAddNodeIdx = clickedNodeIdx; mMode = mAddNodeMode; mSelNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx ); mIsDirty = true; setSelectedNode( mSelNode ); return; } else { if( clickedRiverPtr && clickedNodeIdx == clickedRiverPtr->mNodes.size() - 1 ) { submitUndo( "Add Node" ); mAddNodeIdx = U32_MAX; mMode = mAddNodeMode; U32 newNode = mSelRiver->addNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal); mIsDirty = true; setSelectedNode( newNode ); return; } else { submitUndo( "Insert Node" ); // A single-click on empty space while in // AddNode mode means insert / add a node. //submitUndo( "Add Node" ); //F32 width = mSelRiver->getNodeWidth( mSelNode ); U32 newNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx); mIsDirty = true; setSelectedNode( newNode ); return; } } } } else if ( mMode == mInsertPointMode && mSelRiver != NULL ) { if ( clickedRiverPtr == mSelRiver ) { // NOTE: I guess we have to determine the if the clicked ray intersects a road but not a specific node... // in order to handle inserting nodes in the same way as for DecalRoad U32 prevNodeIdx = insertNodeIdx; U32 nextNodeIdx = ( prevNodeIdx + 1 > mSelRiver->mNodes.size() - 1 ) ? prevNodeIdx : prevNodeIdx + 1; const RiverNode &prevNode = mSelRiver->mNodes[prevNodeIdx]; const RiverNode &nextNode = mSelRiver->mNodes[nextNodeIdx]; F32 width = ( prevNode.width + nextNode.width ) * 0.5f; F32 depth = ( prevNode.depth + nextNode.depth ) * 0.5f; Point3F normal = ( prevNode.normal + nextNode.normal ) * 0.5f; normal.normalize(); submitUndo( "Insert Node" ); U32 newNode = mSelRiver->insertNode( collisionPnt, width, depth, normal, insertNodeIdx + 1 ); mIsDirty = true; setSelectedNode( newNode ); return; } } else if ( mMode == mRemovePointMode && mSelRiver != NULL ) { if ( nodeClicked && clickedRiverPtr == mSelRiver ) { setSelectedNode( clickedNodeIdx ); deleteSelectedNode(); return; } } else if ( mMode == mMovePointMode ) { if ( nodeClicked && clickedRiverPtr == mSelRiver ) { setSelectedNode( clickedNodeIdx ); return; } } else if ( mMode == mScalePointMode ) { if ( nodeClicked && clickedRiverPtr == mSelRiver ) { setSelectedNode( clickedNodeIdx ); return; } } else if ( mMode == mRotatePointMode ) { if ( nodeClicked && clickedRiverPtr == mSelRiver ) { setSelectedNode( clickedNodeIdx ); return; } } }
void GuiRiverEditorCtrl::on3DMouseMove(const Gui3DMouseEvent & event) { if ( mSelRiver != NULL && mMode == mAddNodeMode ) { Point3F pos; if ( getStaticPos( event, pos ) ) { pos.z += mSelRiver->getNodeDepth(mSelNode) * 0.5f; mSelRiver->setNodePosition( mSelNode, pos ); mIsDirty = true; } return; } if ( mSelRiver != NULL && mSelNode != -1 ) mGizmo->on3DMouseMove( event ); // Is cursor hovering over a river? if ( mMode == mSelectRiverMode ) { mHoverRiver = NULL; Point3F startPnt = event.pos; Point3F endPnt = event.pos + event.vec * 1000.0f; RayInfo ri; if ( gServerContainer.castRay(startPnt, endPnt, StaticShapeObjectType, &ri) ) endPnt = ri.point; River *pRiver = NULL; for ( SimSetIterator iter(mRiverSet); *iter; ++iter ) { pRiver = static_cast<River*>( *iter ); // Do not select or edit a River within a Prefab. if ( Prefab::getPrefabByChild(pRiver) ) continue; if ( pRiver->collideRay( event.pos, event.vec ) ) { mHoverRiver = pRiver; break; } } } // Is cursor hovering over a RiverNode? if ( mHoverRiver ) { River *pRiver = mHoverRiver; S32 hoverNodeIdx = -1; F32 hoverNodeDist = mNodeSphereRadius; //for ( SimSetIterator iter(mRiverSet); *iter; ++iter ) //{ // River *pRiver = static_cast<River*>( *iter ); for ( U32 i = 0; i < pRiver->mNodes.size(); i++ ) { const Point3F &nodePos = pRiver->mNodes[i].point; Point3F screenPos; project( nodePos, &screenPos ); F32 dist = ( event.mousePoint - Point2I(screenPos.x, screenPos.y) ).len(); if ( dist < hoverNodeDist ) { // we found a hit! hoverNodeDist = dist; hoverNodeIdx = i; } } //} mHoverNode = hoverNodeIdx; } }
void TSLastDetail::_update() { #if 0 // We're gonna render... make sure we can. bool sceneBegun = GFX->canCurrentlyRender(); if ( !sceneBegun ) GFX->beginScene(); _validateDim(); Vector<GBitmap*> bitmaps; Vector<GBitmap*> normalmaps; // We need to create our own instance to render with. TSShapeInstance *shape = new TSShapeInstance( mShape, true ); // Animate the shape once. shape->animate( mDl ); // So we don't have to change it everywhere. const GFXFormat format = GFXFormatR8G8B8A8; S32 imposterCount = ( ((2*mNumPolarSteps) + 1 ) * mNumEquatorSteps ) + ( mIncludePoles ? 2 : 0 ); // Figure out the optimal texture size. Point2I texSize( smMaxTexSize, smMaxTexSize ); while ( true ) { Point2I halfSize( texSize.x / 2, texSize.y / 2 ); U32 count = ( halfSize.x / mDim ) * ( halfSize.y / mDim ); if ( count < imposterCount ) { // Try half of the height. count = ( texSize.x / mDim ) * ( halfSize.y / mDim ); if ( count >= imposterCount ) texSize.y = halfSize.y; break; } texSize = halfSize; } GBitmap *imposter = NULL; GBitmap *normalmap = NULL; GBitmap destBmp( texSize.x, texSize.y, true, format ); GBitmap destNormal( texSize.x, texSize.y, true, format ); U32 mipLevels = destBmp.getNumMipLevels(); ImposterCapture *imposterCap = new ImposterCapture(); F32 equatorStepSize = M_2PI_F / (F32)mNumEquatorSteps; static const MatrixF topXfm( EulerF( -M_PI_F / 2.0f, 0, 0 ) ); static const MatrixF bottomXfm( EulerF( M_PI_F / 2.0f, 0, 0 ) ); MatrixF angMat; F32 polarStepSize = 0.0f; if ( mNumPolarSteps > 0 ) polarStepSize = -( 0.5f * M_PI_F - mDegToRad( mPolarAngle ) ) / (F32)mNumPolarSteps; PROFILE_START(TSLastDetail_snapshots); S32 currDim = mDim; for ( S32 mip = 0; mip < mipLevels; mip++ ) { if ( currDim < 1 ) currDim = 1; dMemset( destBmp.getWritableBits(mip), 0, destBmp.getWidth(mip) * destBmp.getHeight(mip) * GFXFormat_getByteSize( format ) ); dMemset( destNormal.getWritableBits(mip), 0, destNormal.getWidth(mip) * destNormal.getHeight(mip) * GFXFormat_getByteSize( format ) ); bitmaps.clear(); normalmaps.clear(); F32 rotX = 0.0f; if ( mNumPolarSteps > 0 ) rotX = -( mDegToRad( mPolarAngle ) - 0.5f * M_PI_F ); // We capture the images in a particular order which must // match the order expected by the imposter renderer. imposterCap->begin( shape, mDl, currDim, mRadius, mCenter ); for ( U32 j=0; j < (2 * mNumPolarSteps + 1); j++ ) { F32 rotZ = -M_PI_F / 2.0f; for ( U32 k=0; k < mNumEquatorSteps; k++ ) { angMat.mul( MatrixF( EulerF( rotX, 0, 0 ) ), MatrixF( EulerF( 0, 0, rotZ ) ) ); imposterCap->capture( angMat, &imposter, &normalmap ); bitmaps.push_back( imposter ); normalmaps.push_back( normalmap ); rotZ += equatorStepSize; } rotX += polarStepSize; if ( mIncludePoles ) { imposterCap->capture( topXfm, &imposter, &normalmap ); bitmaps.push_back(imposter); normalmaps.push_back( normalmap ); imposterCap->capture( bottomXfm, &imposter, &normalmap ); bitmaps.push_back( imposter ); normalmaps.push_back( normalmap ); } } imposterCap->end(); Point2I texSize( destBmp.getWidth(mip), destBmp.getHeight(mip) ); // Ok... pack in bitmaps till we run out. for ( S32 y=0; y+currDim <= texSize.y; ) { for ( S32 x=0; x+currDim <= texSize.x; ) { // Copy the next bitmap to the dest texture. GBitmap* bmp = bitmaps.first(); bitmaps.pop_front(); destBmp.copyRect( bmp, RectI( 0, 0, currDim, currDim ), Point2I( x, y ), 0, mip ); delete bmp; // Copy the next normal to the dest texture. GBitmap* normalmap = normalmaps.first(); normalmaps.pop_front(); destNormal.copyRect( normalmap, RectI( 0, 0, currDim, currDim ), Point2I( x, y ), 0, mip ); delete normalmap; // Did we finish? if ( bitmaps.empty() ) break; x += currDim; } // Did we finish? if ( bitmaps.empty() ) break; y += currDim; } // Next mip... currDim /= 2; } PROFILE_END(); // TSLastDetail_snapshots delete imposterCap; delete shape; // Should we dump the images? if ( Log::getBoolVariable( "$TSLastDetail::dumpImposters", false ) ) { String imposterPath = mCachePath + ".imposter.png"; String normalsPath = mCachePath + ".imposter_normals.png"; FileStream stream; if ( stream.open( imposterPath, FileStream::Write ) ) destBmp.writeBitmap( "png", stream ); stream.close(); if ( stream.open( normalsPath, FileStream::Write ) ) destNormal.writeBitmap( "png", stream ); stream.close(); } // DEBUG: Some code to force usage of a test image. //GBitmap* tempMap = GBitmap::load( "./forest/data/test1234.png" ); //tempMap->extrudeMipLevels(); //mTexture.set( tempMap, &GFXDefaultStaticDiffuseProfile, false ); //delete tempMap; DDSFile *ddsDest = DDSFile::createDDSFileFromGBitmap( &destBmp ); DDSUtil::squishDDS( ddsDest, GFXFormatDXT3 ); DDSFile *ddsNormals = DDSFile::createDDSFileFromGBitmap( &destNormal ); DDSUtil::squishDDS( ddsNormals, GFXFormatDXT5 ); // Finally save the imposters to disk. FileStream fs; if ( fs.open( _getDiffuseMapPath(), FileStream::Write ) ) { ddsDest->write( fs ); fs.close(); } if ( fs.open( _getNormalMapPath(), FileStream::Write ) ) { ddsNormals->write( fs ); fs.close(); } delete ddsDest; delete ddsNormals; // If we did a begin then end it now. if ( !sceneBegun ) GFX->endScene(); #endif }
/// Function to draw a set of boxes blending throughout an array of colors void GuiGradientCtrl::drawBlendRangeBox(RectI &bounds, bool vertical, Vector<ColorRange> colorRange) { GFX->setStateBlock(mStateBlock); // Create new global dimensions S32 l = bounds.point.x + mSwatchFactor, r = bounds.point.x + bounds.extent.x - mSwatchFactor; S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y - mSwatchFactor; // Draw border using new global dimensions if (mProfile->mBorder) GFX->getDrawUtil()->drawRect(RectI(Point2I(l, t), Point2I(r, b)), mProfile->mBorderColor); // Update local dimensions mBlendRangeBox.point = globalToLocalCoord(Point2I(l, t)); mBlendRangeBox.extent = globalToLocalCoord(Point2I(r, b)); if (colorRange.size() == 1) // Only one color to draw { PrimBuild::begin(GFXTriangleStrip, 4); PrimBuild::color(colorRange.first().swatch->getColor()); PrimBuild::vertex2i(l, t); PrimBuild::vertex2i(r, t); PrimBuild::color(colorRange.first().swatch->getColor()); PrimBuild::vertex2i(l, b); PrimBuild::vertex2i(r, b); PrimBuild::end(); } else { PrimBuild::begin(GFXTriangleStrip, 4); PrimBuild::color(colorRange.first().swatch->getColor()); PrimBuild::vertex2i(l, t); PrimBuild::vertex2i(l + colorRange.first().swatch->getPosition().x, t); PrimBuild::color(colorRange.first().swatch->getColor()); PrimBuild::vertex2i(l, b); PrimBuild::vertex2i(l + colorRange.first().swatch->getPosition().x, b); PrimBuild::end(); for (U16 i = 0; i < colorRange.size() - 1; i++) { PrimBuild::begin(GFXTriangleStrip, 4); if (!vertical) // Horizontal (+x) { // First color PrimBuild::color(colorRange[i].swatch->getColor()); PrimBuild::vertex2i(l + colorRange[i].swatch->getPosition().x, t); PrimBuild::color(colorRange[i + 1].swatch->getColor()); PrimBuild::vertex2i(l + colorRange[i + 1].swatch->getPosition().x, t); // First color PrimBuild::color(colorRange[i].swatch->getColor()); PrimBuild::vertex2i(l + colorRange[i].swatch->getPosition().x, b); PrimBuild::color(colorRange[i + 1].swatch->getColor()); PrimBuild::vertex2i(l + colorRange[i + 1].swatch->getPosition().x, b); } PrimBuild::end(); } PrimBuild::begin(GFXTriangleStrip, 4); PrimBuild::color(colorRange.last().swatch->getColor()); PrimBuild::vertex2i(l + colorRange.last().swatch->getPosition().x, t); PrimBuild::vertex2i(r, t); PrimBuild::color(colorRange.last().swatch->getColor()); PrimBuild::vertex2i(l + colorRange.last().swatch->getPosition().x, b); PrimBuild::vertex2i(r, b); PrimBuild::end(); } }
void GuiTextEditSliderCtrl::onRender(Point2I offset, const RectI &updateRect) { if(mTextAreaHit != None) { U32 elapseTime = Sim::getCurrentTime() - mMouseDownTime; if(elapseTime > 750 || mTextAreaHit == Slider) { timeInc(elapseTime); mIncCounter += mMulInc; if(mIncCounter >= 1.0f || mIncCounter <= -1.0f) { mValue = (mMulInc > 0.0f) ? mValue+mIncAmount : mValue-mIncAmount; mIncCounter = (mIncCounter > 0.0f) ? mIncCounter-1 : mIncCounter+1; checkRange(); setValue(); mCursorPos = 0; } } } Parent::onRender(offset, updateRect); Point2I start(offset.x + getWidth() - 14, offset.y); Point2I midPoint(start.x + 7, start.y + (getExtent().y/2)); GFX->getDrawUtil()->drawRectFill(Point2I(start.x+1,start.y+1), Point2I(start.x+13,start.y+getExtent().y-1) , mProfile->mFillColor); GFX->getDrawUtil()->drawLine(start, Point2I(start.x, start.y+getExtent().y),mProfile->mFontColor); GFX->getDrawUtil()->drawLine(Point2I(start.x,midPoint.y), Point2I(start.x+14,midPoint.y), mProfile->mFontColor); GFXVertexBufferHandle<GFXVertexPCT> verts(GFX, 6, GFXBufferTypeVolatile); verts.lock(); verts[0].color.set( 0, 0, 0 ); verts[1].color.set( 0, 0, 0 ); verts[2].color.set( 0, 0, 0 ); verts[3].color.set( 0, 0, 0 ); verts[4].color.set( 0, 0, 0 ); verts[5].color.set( 0, 0, 0 ); if(mTextAreaHit == ArrowUp) { verts[0].point.set( (F32)midPoint.x, (F32)start.y + 1.0f, 0.0f ); verts[1].point.set( (F32)start.x + 11.0f, (F32)midPoint.y - 2.0f, 0.0f ); verts[2].point.set( (F32)start.x + 3.0f, (F32)midPoint.y - 2.0f, 0.0f ); } else { verts[0].point.set( (F32)midPoint.x, (F32)start.y + 2.0f, 0.0f ); verts[1].point.set( (F32)start.x + 11.0f, (F32)midPoint.y - 1.0f, 0.0f ); verts[2].point.set( (F32)start.x + 3.0f, (F32)midPoint.y - 1.0f, 0.0f ); } if(mTextAreaHit == ArrowDown) { verts[3].point.set( (F32)midPoint.x, (F32)(start.y + getExtent().y - 1), 0.0f ); verts[4].point.set( (F32)start.x + 11.0f, (F32)midPoint.y + 3.0f, 0.0f ); verts[5].point.set( (F32)start.x + 3.0f, (F32)midPoint.y + 3.0f, 0.0f ); } else { verts[3].point.set( (F32)midPoint.x, (F32)(start.y + getExtent().y - 2), 0.0f ); verts[4].point.set( (F32)start.x + 11.0f, (F32)midPoint.y + 2.0f, 0.0f ); verts[5].point.set( (F32)start.x + 3.0f, (F32)midPoint.y + 2.0f, 0.0f ); } verts.unlock(); GFX->setVertexBuffer( verts ); GFX->setupGenericShaders(); GFX->drawPrimitive( GFXTriangleList, 0, 2 ); }
Point3F(1.0f,1.0f,0.0f), Point3F(0.0f,1.0f,0.0f), }; #if 0 Point4I vPoints[4] = { Point4I(0,0,0,0.0f), Point4I(0,0,0,0.0f), Point4I(0,0,0,0.0f), Point4I(0,0,0,0.0f), }; Point2I dpvPoints[4] = { Point2I(0,0), Point2I(0,0), Point2I(0,0), Point2I(0,0), }; Point4I* pVPoints[4] = { &vPoints[0], &vPoints[1], &vPoints[2], &vPoints[3], }; Point2I* dpVPoints[4] = {
"@tsexample\n" "new MissionArea(GlobalMissionArea)\n" "{\n" " Area = \"-152 -352 1008 864\";\n" " flightCeiling = \"300\";\n" " flightCeilingRange = \"20\";\n" " canSaveDynamicFields = \"1\";\n" " enabled = \"1\";\n" " TypeBool locked = \"false\";\n" "};\n" "@endtsexample\n\n" "@ingroup enviroMisc\n" ); RectI MissionArea::smMissionArea(Point2I(768, 768), Point2I(512, 512)); MissionArea * MissionArea::smServerObject = NULL; //------------------------------------------------------------------------------ MissionArea::MissionArea() { mArea.set(Point2I(768, 768), Point2I(512, 512)); mNetFlags.set(Ghostable | ScopeAlways); mFlightCeiling = 2000; mFlightCeilingRange = 50; } //------------------------------------------------------------------------------
void ServerInfoCtrl::onWake(void) { setSize(Point2I(1, 0)); if (parent) cellSize.set(parent->extent.x, hFont->getHeight() + 2); }
//---------------------------------------------------------------------------- /// Core rendering method for this control. /// /// This method scans through all the current client ShapeBase objects. /// If one is named, it displays the name and damage information for it. /// /// Information is offset from the center of the object's bounding box, /// unless the object is a PlayerObjectType, in which case the eye point /// is used. /// /// @param updateRect Extents of control. void afxGuiTextHud::onRender( Point2I, const RectI &updateRect) { // Background fill first if (mShowFill) GFX->getDrawUtil()->drawRectFill(updateRect, mFillColor.toColorI()); // Must be in a TS Control GuiTSCtrl *parent = dynamic_cast<GuiTSCtrl*>(getParent()); if (!parent) return; // Must have a connection and control object GameConnection* conn = GameConnection::getConnectionToServer(); if (!conn) return; GameBase * control = dynamic_cast<GameBase*>(conn->getControlObject()); if (!control) return; // Get control camera info MatrixF cam; Point3F camPos; VectorF camDir; conn->getControlCameraTransform(0,&cam); cam.getColumn(3, &camPos); cam.getColumn(1, &camDir); F32 camFovCos; conn->getControlCameraFov(&camFovCos); camFovCos = mCos(mDegToRad(camFovCos) / 2); // Visible distance info & name fading F32 visDistance = gClientSceneGraph->getVisibleDistance(); F32 visDistanceSqr = visDistance * visDistance; F32 fadeDistance = visDistance * mDistanceFade; // Collision info. We're going to be running LOS tests and we // don't want to collide with the control object. static U32 losMask = TerrainObjectType | TerrainLikeObjectType | ShapeBaseObjectType; if (!mEnableControlObjectOcclusion) control->disableCollision(); if (mLabelAllShapes) { // This section works just like GuiShapeNameHud and renders labels for // all the shapes. // All ghosted objects are added to the server connection group, // so we can find all the shape base objects by iterating through // our current connection. for (SimSetIterator itr(conn); *itr; ++itr) { ///if ((*itr)->getTypeMask() & ShapeBaseObjectType) ///{ ShapeBase* shape = dynamic_cast<ShapeBase*>(*itr); if ( shape ) { if (shape != control && shape->getShapeName()) { // Target pos to test, if it's a player run the LOS to his eye // point, otherwise we'll grab the generic box center. Point3F shapePos; if (shape->getTypeMask() & PlayerObjectType) { MatrixF eye; // Use the render eye transform, otherwise we'll see jittering shape->getRenderEyeTransform(&eye); eye.getColumn(3, &shapePos); } else { // Use the render transform instead of the box center // otherwise it'll jitter. MatrixF srtMat = shape->getRenderTransform(); srtMat.getColumn(3, &shapePos); } VectorF shapeDir = shapePos - camPos; // Test to see if it's in range F32 shapeDist = shapeDir.lenSquared(); if (shapeDist == 0 || shapeDist > visDistanceSqr) continue; shapeDist = mSqrt(shapeDist); // Test to see if it's within our viewcone, this test doesn't // actually match the viewport very well, should consider // projection and box test. shapeDir.normalize(); F32 dot = mDot(shapeDir, camDir); if (dot < camFovCos) continue; // Test to see if it's behind something, and we want to // ignore anything it's mounted on when we run the LOS. RayInfo info; shape->disableCollision(); SceneObject *mount = shape->getObjectMount(); if (mount) mount->disableCollision(); bool los = !gClientContainer.castRay(camPos, shapePos,losMask, &info); shape->enableCollision(); if (mount) mount->enableCollision(); if (!los) continue; // Project the shape pos into screen space and calculate // the distance opacity used to fade the labels into the // distance. Point3F projPnt; shapePos.z += mVerticalOffset; if (!parent->project(shapePos, &projPnt)) continue; F32 opacity = (shapeDist < fadeDistance)? 1.0: 1.0 - (shapeDist - fadeDistance) / (visDistance - fadeDistance); // Render the shape's name drawName(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getShapeName(),opacity); } } } } // This section renders all text added by afxGuiText effects. for (S32 i = 0; i < text_items.size(); i++) { HudTextSpec* spec = &text_items[i]; if (spec->text && spec->text[0] != '\0') { VectorF shapeDir = spec->pos - camPos; // do range test F32 shapeDist = shapeDir.lenSquared(); if (shapeDist == 0 || shapeDist > visDistanceSqr) continue; shapeDist = mSqrt(shapeDist); // Test to see if it's within our viewcone, this test doesn't // actually match the viewport very well, should consider // projection and box test. shapeDir.normalize(); F32 dot = mDot(shapeDir, camDir); if (dot < camFovCos) continue; // Test to see if it's behind something, and we want to // ignore anything it's mounted on when we run the LOS. RayInfo info; if (spec->obj) spec->obj->disableCollision(); bool los = !gClientContainer.castRay(camPos, spec->pos, losMask, &info); if (spec->obj) spec->obj->enableCollision(); if (!los) continue; // Project the shape pos into screen space. Point3F projPnt; if (!parent->project(spec->pos, &projPnt)) continue; // Calculate the distance opacity used to fade text into the distance. F32 opacity = (shapeDist < fadeDistance)? 1.0 : 1.0 - (shapeDist - fadeDistance) / (25.0f); if (opacity > 0.01f) drawName(Point2I((S32)projPnt.x, (S32)projPnt.y), spec->text, opacity, &spec->text_clr); } } // Restore control object collision if (!mEnableControlObjectOcclusion) control->enableCollision(); // Border last if (mShowFrame) GFX->getDrawUtil()->drawRect(updateRect, mFrameColor.toColorI()); reset(); }