SizeInt Viewer::calculateCappedImageSize( const SizeInt& imageSize, const SizeInt &windowEdges ) { wxDisplay display(DisplayFromPointFallback(PositionScreen())); auto rtDesktop = wxToRect(display.GetClientArea()); return SizeInt( std::max<int>(MinWindowWidth, std::min<int>(rtDesktop.Width(), imageSize.Width + windowEdges.Width)), std::max<int>(MinWindowHeight, std::min<int>(rtDesktop.Height(),imageSize.Height + windowEdges.Height))); }
SizeInt Viewer::calculateImageSize( ResizeBehaviour mode, float xratio, float yratio, const SizeInt &imageSize, const SizeInt &windowEdges ) { wxDisplay display(DisplayFromPointFallback(PositionScreen())); auto rtDesktop = wxToRect(display.GetClientArea()); // The image is larger than the desktop. The image is not supposed // to be downscaled so fill the screen. if ((mode == ResizeEnlargeOnly) && (xratio < 1.0) && (yratio < 1.0)) return rtDesktop.Dimensions(); // The image is smaller than the desktop. It must not be made // smaller needlessly so size the window after the image. else if ((mode == ResizeReduceOnly) && (xratio > 1.0) && (yratio > 1.0)) return SizeInt( std::max<int>(MinWindowWidth, imageSize.Width + windowEdges.Width), std::max<int>(MinWindowHeight,imageSize.Height + windowEdges.Height)); return Maximum(SizeInt(MinWindowWidth, MinWindowHeight), Minimum(RoundCast(imageSize * std::min(xratio, yratio)) + windowEdges, rtDesktop.Dimensions())); }
ButtonUnit::ButtonUnit() { m_Flags |= NOCLIP; m_Style = HAS_BACK | EFFECT_HIGHLIGHT | EFFECT_FADEIN | SMOOTH_LL; m_Alpha = 0.75f; setWindow( RectInt( PointInt(0,0), SizeInt( 32, 24 ) ) ); setEnable( false ); }
ViewEngineering::ButtonGadget::ButtonGadget() { m_Flags |= NOCLIP; m_Style = HAS_BACK | EFFECT_HIGHLIGHT | EFFECT_FADEIN | SMOOTH_LL | LOCK_ICON_SIZE; m_Alpha = 0.75f; setWindow( RectInt( PointInt(0,0), SizeInt( 32, 24 ) ) ); setEnable( false ); }
ButtonBuildStructure::ButtonBuildStructure() { m_Flags |= NOCLIP; m_Style = HAS_BACK | EFFECT_HIGHLIGHT | EFFECT_FADEIN | SMOOTH_LL | LOCK_ICON_SIZE; m_Alpha = 0.75f; setWindow( RectInt( PointInt(0,0), SizeInt( 32, 24 ) ) ); setEnable( false ); }
void ButtonUnit::onRender( RenderContext & context, const RectInt & window ) { WindowButton::onRender( context, window ); if ( enabled() && m_Unit.valid() ) { GameDocument * pDoc = (GameDocument *)document(); ASSERT( pDoc ); NounShip * pShip = pDoc->ship(); if (! pShip ) return; DisplayDevice * pDisplay = context.display(); ASSERT( pDisplay ); // draw the gadget icon if ( m_Icon.valid() ) { RectInt iconBox( PointInt( window.left, window.top ), SizeInt( 32, 16 ) ); RectFloat iconUV(0,0,1,1); Material::push( context, m_Icon ); PrimitiveWindow::push( pDisplay, iconBox, iconUV, pShip->isFriend( m_Unit ) ? GREEN : pShip->isEnemy( m_Unit ) ? RED : YELLOW ); } // draw the unit health on the button Font * pFont = windowStyle()->font(); ASSERT( pFont ); WideString sHealth; sHealth.format( STR("%d%%"), 100 - ((m_Unit->damage() * 100) / m_Unit->maxDamage()) ); SizeInt szHealth( pFont->size( sHealth ) ); PointInt ptHealth( window.right - szHealth.width, window.bottom - szHealth.height ); Font::push( context.display(), pFont, ptHealth, sHealth, WHITE ); // display damage bar if ( m_Unit->damage() > 0 ) { float damage = 1.0f - (m_Unit->damage() / m_Unit->maxDamage()); RectInt bar( window.m_Left, window.m_Bottom + 1, window.m_Right - (window.width() * (1.0f - damage)), window.m_Bottom + 3 ); RectFloat barUV(0,0,1,1); Color barColor( 255 * (1.0f - damage), 255 * damage,0,255 ); PrimitiveMaterial::push( pDisplay, PrimitiveMaterial::NONE ); PrimitiveWindow::push( pDisplay, bar, barUV, barColor ); } // display blinking border if this unit is the current target if ( pDoc->target() == m_Unit && (pDoc->tick() % 10) < 6) renderGlow( context ); } }
ButtonGadget::ButtonGadget() : m_bCursorOver( false ) { m_Flags |= NOCLIP; m_Style = HAS_BACK | EFFECT_HIGHLIGHT | EFFECT_FADEIN | SMOOTH_LL; m_Alpha = 0.75f; m_IconColor = GREEN; setWindow( RectInt( PointInt(0,0), SizeInt( 32, 24 ) ) ); setEnable( false ); }
ButtonContact::ButtonContact() : m_IsObjective( false ), m_bGroupLeader( false ), m_bGroupPending( false ) { m_Flags |= NOCLIP; m_Style = HAS_BACK | EFFECT_HIGHLIGHT | SMOOTH_LL | EFFECT_FADEIN; m_Alpha = 0.75f; setWindow( RectInt( PointInt(0,0), SizeInt( BUTTON_WIDTH, BUTTON_HEIGHT ) ) ); }
ButtonContact::ButtonContact( NodeWindow * pParent, Noun * pNoun ) : m_IsObjective( false ), m_bGroupLeader( false ), m_bGroupPending( false ) { m_Flags |= NOCLIP; m_Style = HAS_BACK | EFFECT_HIGHLIGHT | SMOOTH_LL | EFFECT_FADEIN; m_Alpha = 0.75f; setWindow( RectInt( PointInt(0,0), SizeInt( BUTTON_WIDTH, BUTTON_HEIGHT ) ) ); // attach this button to the parent pParent->attachNode( this ); // set this button setButton( pNoun ); }
void Viewer::PanHorizontal(int length) { m_viewPort.Pan(SizeInt(length, 0)); }
void Viewer::PanVertical(int length) { m_viewPort.Pan(SizeInt(0, length)); }
PrimitiveSurface * Material::getSurface( DisplayDevice * pDisplay, Image::Link pImage, int nFrame, bool bMipMap ) { // generate a unique key from the components WidgetKey nKey = pImage.key() + nFrame; if ( bMipMap ) nKey += MIPMAP_KEY; AutoLock lock( &sm_SurfaceHashLock ); SurfaceHash::Iterator it = sm_SurfaceHash.find( nKey ); if ( it.valid() ) return *it; lock.release(); // surface not found, create and cache the surface PrimitiveSurface::Ref pSurface; if ( pImage.valid() && pImage->frameCount() > 0 ) { // find a format for our surface first, findBestFormat() will always try to use the images current format // if supported by the hardware. ColorFormat::Format eFormat = findBestFormat( pDisplay, pImage, true ); if ( eFormat == ColorFormat::INVALID ) { TRACE( "ERROR: Failed to find a suitable surface format for texture!" ); return NULL; } SizeInt imageSize( pImage->size() ); SizeInt maxSize( pDisplay->textureMaxSize() ); SizeInt minSize( pDisplay->textureMinSize() ); // use the smaller max size maxSize.width = Min( sm_MaxTextureSize.width, maxSize.width ); maxSize.height = Min( sm_MaxTextureSize.height, maxSize.height ); // validate the texture dimensions SizeInt validSize( Max( Min( imageSize.width, maxSize.width ), minSize.width), Max( Min( imageSize.height, maxSize.height ), minSize.height) ); if ( pDisplay->textureP2() && !pImage->isP2() ) validSize = SizeInt( 1 << GetLastBit( validSize.width ), 1 << GetLastBit( validSize.height) ); if ( pDisplay->textureSquare() && validSize.width != validSize.height ) validSize = SizeInt( Max( validSize.width, validSize.height ), Max( validSize.width, validSize.height) ); if ( validSize != imageSize || eFormat != pImage->format() ) { // image is the wrong size or format, make a copy so we don't modify the original.. pImage = new Image( *pImage ); if ( pImage->size() != validSize ) { // image has to be resized - switch the format to an uncompressed format, DXT compression is too slow // to do on the fly.. eFormat = findBestFormat( pDisplay, pImage, false ); if ( eFormat != pImage->format() ) { TRACE( CharString().format( "Image: Reformat %s -> %s", ColorFormat::formatText( pImage->format() ), ColorFormat::formatText( eFormat ) ) ); if (! pImage->setFormat( eFormat ) ) return NULL; } TRACE( CharString().format( "Image: Resize %dx%d -> %dx%d", imageSize.width, imageSize.height, validSize.width, validSize.height ) ); pImage->resample( validSize ); if ( bMipMap && pImage->mipMap() != NULL ) pImage->createMipMaps(); } else if ( pImage->format() != eFormat ) { TRACE( CharString().format( "Image: Reformat %s -> %s", ColorFormat::formatText( pImage->format() ), ColorFormat::formatText( eFormat ) ) ); if (! pImage->setFormat( eFormat ) ) return NULL; // failed to convert to the desired format.. } } if ( bMipMap && pImage->mipMap() == NULL ) bMipMap = false; // no mipmap levels in image, disable mipmaps // create the primitives, note having neither a diffuse or alpha texture is also a valid material pDisplay->create( pSurface ); // create the surface SizeInt surfaceSize( pImage->size() ); pSurface->initialize( surfaceSize.width, surfaceSize.height, eFormat, bMipMap ); nFrame = nFrame % pImage->frameCount(); Image * pMipMap = pImage; for(int i=0;i<pSurface->levels();++i) { if (! pMipMap ) { TRACE( CharString().format("ERROR: Mipmap level %d is missing!", i ) ); break; } void * pPixels = pSurface->lock( i ); if (! pPixels ) { TRACE( "ERROR: Failed to lock surface!" ); break; } memcpy( pPixels, pMipMap->frame( nFrame ), pMipMap->frameSize( nFrame ) ); pSurface->unlock(); // next mipmap level of our image.. pMipMap = pMipMap->mipMap(); } } // cache the surface now lock.set( &sm_SurfaceHashLock ); sm_SurfaceHash[ nKey ] = pSurface; return pSurface; }
void WindowEdit::onRender( RenderContext & context, const RectInt & window ) { if (! windowStyle() ) return; DisplayDevice * pDisplay = context.display(); ASSERT( pDisplay ); Font * pFont = windowStyle()->font(); ASSERT( pFont ); // calculate the total text size SizeInt textSize( pFont->size( WideString( m_Text ) ) ); // get the text color Color textColor( windowStyle()->color() ); textColor.m_A = m_Editing ? ACTIVE_ALPHA : INACTIVE_ALPHA; SizeInt windowSize( window.size() ); // check the size of the window compared to the text size m_EditBegin = 0; m_EditEnd = m_Text.length() - 1; while ( textSize.m_Width > windowSize.m_Width ) { if ( m_EditBegin < m_Cursor ) { textSize.m_Width -= pFont->characterWidth( m_Text[ m_EditBegin ] ); m_EditBegin++; } else if ( m_EditEnd > m_Cursor ) { textSize.m_Width -= pFont->characterWidth( m_Text[ m_EditEnd ] ); m_EditEnd--; } else // not enough room, the font is probably too large so just return return; } // extract the displayable part of the text WideString display( m_Text ); display.mid( m_EditBegin, (m_EditEnd - m_EditBegin) + 1 ); // draw text left justified and centered vertically PointInt ptText( window.m_Left, window.m_Top + ((windowSize.m_Height / 2) - (textSize.m_Height / 2)) ); // draw the text, construct another PointInt on the stack because Font::push will modify the point PointInt ptText2 = ptText; Font::push( pDisplay, pFont, ptText2, display, textColor ); // display cursor if editing if ( m_Editing ) { // draw cursor for(int i=m_EditBegin;i<m_Cursor;i++) ptText.m_X += pFont->characterWidth( m_Text[i] ); Color cursorColor( textColor ); cursorColor.m_A = (u8)(fmod( m_ActiveTime, CURSOR_BLINK_RATE ) * 255); RectInt cursorRect( ptText, SizeInt( CURSOR_WIDTH, textSize.height ) ); PrimitiveMaterial::push( pDisplay, PrimitiveMaterial::ADDITIVE ); PrimitiveWindow::push( pDisplay, cursorRect , RectFloat(0,0,0,0), cursorColor ); } }
TEST_FIXTURE(FixtureRound, PanRoundDown) { p.Pan(SizeInt(-1, -1)); CHECK_EQUAL(PointInt(0, 0), p.TopLeft()); CHECK_EQUAL(PointInt(717, 448), p.BottomRight()); }
void ButtonContact::onRender( RenderContext & context, const RectInt & window ) { WindowButton::onRender( context, window ); DisplayDevice * pDisplay = context.display(); ASSERT( pDisplay ); GameDocument * pDoc = (GameDocument *)document(); ASSERT( pDoc ); NounShip * pShip = pDoc->ship(); if (! pShip ) return; WindowStyle * pStyle = windowStyle(); ASSERT( pStyle ); Font * pFont = pStyle->font(); ASSERT( pFont ); // get a pointer to our gadget Noun * pContact = m_Noun; if (! pContact ) return; RectInt iconBox( PointInt( window.left, window.top ), SizeInt( 16, 16 ) ); Color iconColor( YELLOW ); if ( pShip->isFriend( pContact ) ) iconColor = GREEN; else if ( pShip->isEnemy( pContact ) ) iconColor = RED; // draw the gadget icon Material::push( context, m_Icon ); PrimitiveWindow::push( pDisplay, iconBox, WINDOW_UV, iconColor ); if ( WidgetCast<NounShip>( pContact ) && ((NounShip *)pContact)->canOrder( pShip ) ) { Material::push( context, WidgetCast<Material>( resource("team") ) ); iconBox += PointInt( 16, 0 ); PrimitiveWindow::push( pDisplay, iconBox, WINDOW_UV, WHITE ); } else if ( m_IsObjective ) { Material::push( context, WidgetCast<Material>( resource("objective") ) ); iconBox += PointInt( 16, 0 ); PrimitiveWindow::push( pDisplay, iconBox, WINDOW_UV, WHITE ); } // display status text CharString sStatus = pContact->displayName( false ); if ( m_HotKey != 0 ) sStatus = CharString().format("%c:%s", m_HotKey, sStatus ); if ( sStatus.length() > 0 ) { SizeInt stringSize( pFont->size( sStatus ) ); // make sure the text fits on the label while( stringSize.width > (BUTTON_WIDTH - 5 ) ) { // remove the right most character and check the width again sStatus.left( sStatus.length() - 1 ); stringSize = pFont->size( sStatus ); } PointInt stringPos( window.m_Right - stringSize.width, window.m_Bottom - stringSize.height ); Font::push( pDisplay, pFont, stringPos, sStatus, m_bGroupLeader ? YELLOW : (m_bGroupPending ? GREY : WHITE) ); } // display the damage bar if ( WidgetCast<NounShip>( pContact ) ) { if ( ((NounShip *)pContact)->damage() > 0 ) { float damage = ((NounShip *)pContact)->damageRatioInv(); RectInt bar( window.m_Left, window.m_Bottom + 1, window.m_Right - (window.width() * (1.0f - damage)), window.m_Bottom + 3 ); Color barColor( 255 * (1.0f - damage), 255 * damage,0,255 ); PrimitiveMaterial::push( pDisplay, PrimitiveMaterial::NONE ); PrimitiveWindow::push( pDisplay, bar, WINDOW_UV, barColor ); } } // render additional border if this contact is our current target if ( pDoc->rootTarget() == m_Noun && (pDoc->tick() % 10) < 6 ) renderGlow( context ); }
void ButtonGadget::onRender( RenderContext & context, const RectInt & window ) { WindowButton::onRender( context, window ); // get a pointer to our gadget NounGadget * pGadget = m_Gadget; if ( pGadget != NULL ) { DisplayDevice * pDisplay = context.display(); ASSERT( pDisplay ); GameDocument * pDoc = (GameDocument *)document(); ASSERT( pDoc ); WindowStyle * pStyle = windowStyle(); ASSERT( pStyle ); Font * pFont = pStyle->font(); ASSERT( pFont ); // display bar if gadget has delay before usabled int delay = pGadget->usableWhen(); if ( delay > 0 ) { if ( (pDoc->tick() % 10) < 6 ) // make the bar blink { RectInt bar( window.left, window.top, window.right - ((window.width() * delay) / 100), window.top + 16 ); PrimitiveMaterial::push( pDisplay, PrimitiveMaterial::ADDITIVE ); PrimitiveWindow::push( pDisplay, bar, WINDOW_UV, Color(0,0,255,255) ); } } // draw the gadget icon Material * pIcon = pGadget->icon(); if ( pIcon != NULL ) { RectInt iconBox( PointInt( window.left, window.top ), SizeInt( 32, 16 ) ); Material::push( context, pIcon ); PrimitiveWindow::push( pDisplay, iconBox, WINDOW_UV, m_IconColor ); } // display any gadget status text WideString sStatus( pGadget->status() ); if ( sStatus.length() > 0 ) { SizeInt stringSize( pFont->size( sStatus ) ); Font::push( pDisplay, pFont, PointInt( window.m_Right - stringSize.width, window.top ), sStatus, YELLOW ); } // display hotkey in lower-left corner of button CharString sHotKey; if ( pGadget->hotkey() != 0 && pGadget->hotkey() != HK_SPACE ) sHotKey += keyText( Keyboard::unmap( pGadget->hotkey() ) ); if ( m_Gadget->group() != 0 ) sHotKey += CharString().format(" %c", m_Gadget->group() ); if ( WidgetCast<GadgetBeamWeapon>( pGadget ) && ((GadgetBeamWeapon *)pGadget)->pointDefense() ) sHotKey += " PD"; if ( sHotKey.length() > 0 ) { WideString sWide = sHotKey; SizeInt stringSize( pFont->size( sWide ) ); Font::push( pDisplay, pFont, PointInt( window.m_Right - stringSize.width, window.m_Bottom - stringSize.height ), sWide, YELLOW ); } // display the damage bar if ( pGadget->damage() > 0 ) { if ( (pDoc->tick() % 10) < 6 ) // make the bar blink { float damage = pGadget->damageRatioInv(); RectInt bar( window.m_Left, window.m_Bottom + 1, window.m_Right - (window.width() * (1.0f - damage)), window.m_Bottom + 3 ); Color barColor( 255 * (1.0f - damage), 255 * damage,0,255 ); PrimitiveMaterial::push( pDisplay, PrimitiveMaterial::NONE ); PrimitiveWindow::push( pDisplay, bar, WINDOW_UV, barColor ); } } // blink a white border if this is the current target if ( pDoc->target() == m_Gadget && (pDoc->tick() % 10) < 6 ) renderGlow( context ); } }