Geom::RectInt TileManager::determineLockableRect(const RectInt& r) const { if (IsPositive(r.Dimensions()) == false) { DO_THROW(Err::InvalidParam, "Invalid dimensions"); } if (m_topLeftOffset.AtLeastInclusive({ 0, 0 }) == false) { DO_THROW(Err::CriticalError, "Invalid offset"); } auto pannedTopLeft = r.TopLeft() + m_topLeftOffset; while (pannedTopLeft.X >= MaximumTileEdgeLength) { pannedTopLeft.X -= MaximumTileEdgeLength; } while (pannedTopLeft.Y >= MaximumTileEdgeLength) { pannedTopLeft.Y -= MaximumTileEdgeLength; } auto croppedBottomRight = Geom::Minimum(r.BottomRight(), PointInt(0, 0) + m_topLeftOffset + m_viewSize); auto outSize = Maximum(SizeInt(0, 0), Minimum( SizeInt(MaximumTileEdgeLength, MaximumTileEdgeLength) + (PointInt(0, 0) - pannedTopLeft), croppedBottomRight - PointInt(0, 0), r.Dimensions())); if (IsPositive(outSize) == false) { DO_THROW(Err::CriticalError, "Calculation error, rect became empty."); } return{ pannedTopLeft, outSize }; }
bool ff::Value::CreateRect(const RectInt &rect, Value **ppValue) { assertRetVal(ppValue, false); if (!rect.IsNull()) { *ppValue = NewValueOneRef(); (*ppValue)->SetType(Type::Rect); (*ppValue)->InternalGetRect() = rect; } else { static Value::StaticValue s_data; static Value *s_val = nullptr; if (!s_val) { ScopeStaticValueAlloc scopeAlloc; if (!s_val) { s_val = s_data.AsValue(); s_val->Value::Value(); s_val->SetType(Type::Rect); s_val->InternalGetRect().SetRect(0, 0, 0, 0); } } *ppValue = s_val; } return true; }
bool WindowEdit::onCursorMove( const RectInt & window, const PointInt & position, const PointInt & delta ) { if ( window.inRect( position ) || m_Editing ) { setCursorState( EDIT ); return true; } return 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 ); } }
bool TaskClampSW::run(RunParams&) const { RectInt r = target_rect; if (!r.valid()) { VectorInt offset = get_offset(); RectInt ra = sub_task()->target_rect + r.get_min() + get_offset(); if (ra.valid()) { etl::set_intersect(ra, ra, r); if (ra.valid()) { LockWrite ldst(this); if (!ldst) return false; LockRead lsrc(sub_task()); if (!lsrc) return false; const synfig::Surface &a = lsrc->get_surface(); synfig::Surface &c = ldst->get_surface(); for(int y = ra.miny; y < ra.maxy; ++y) { const Color *ca = &a[y - r.miny + offset[1]][ra.minx - r.minx + offset[0]]; Color *cc = &c[y][ra.minx]; for(int x = ra.minx; x < ra.maxx; ++x, ++ca, ++cc) clamp_pixel(*cc, *ca); } } } } return true; }
bool WindowEdit::onLeftUp( const RectInt & window, const PointInt & position ) { if ( window.inRect( position ) ) { return true; } else { if ( m_Editing ) { onEndEdit(); return true; } } return false; }
bool WindowButton::onCursorMove( const RectInt & window, const PointInt & position, const PointInt & delta ) { bool bInRect = false; if ( !m_HotKeyDown ) { if ( visible() && window.inRect( position ) ) bInRect = true; } if ( bInRect ) { if ( !m_bGreyed ) { // display the press button context()->setCursorState( SELECT ); if ( m_HotKey != 0 ) { updateTip( CharString().format("%s '%s'", m_Tip, keyText( Keyboard::unmap( m_HotKey ) ) ) ); } else updateTip( m_Tip ); } if ( !m_CursorOver ) { if ( !m_bGreyed ) { postMessage( WB_OVERBUTTON, (dword)this, 0 ); hoverSound(); } m_CursorOver = true; return false; // return false on the first time a cursor is over a button, so that the other button can set m_CursorOver to false } return true; } else if ( m_CursorOver ) m_CursorOver = false; return NodeWindow::onCursorMove( window, position, delta ); }
bool WindowTree::onCursorMove( const RectInt & window, const PointInt & position, const PointInt & delta ) { if ( visible() ) { if ( window.inRect( position ) ) { m_CursorInWindow = true; m_LastCursorPosition = windowToScreen( position ); setCursorState( SELECT ); return true; } else { m_CursorInWindow = false; } } return NodeWindow::onCursorMove( window, position, delta ); }
void ViewEngineering::ButtonGadget::onRender( RenderContext & context, const RectInt & window ) { WindowButton::onRender( context, window ); if ( enabled() ) { DisplayDevice * pDisplay = context.display(); ASSERT( pDisplay ); Font * pFont = windowStyle()->font(); ASSERT( pFont ); // display damage percentage String status; status.format( "%d%%", int( m_rGadget->damageRatioInv() * 100) ); SizeInt stringSize( pFont->size( status ) ); PointInt stringPos( window.m_Right - stringSize.width, window.top ); Font::push( pDisplay, pFont, stringPos, status, YELLOW ); // display the damage bar if ( m_rGadget->damage() > 0 ) { if ( fmod( activeTime(), 1.0f ) < 0.5f ) // make the bar blink { float damage = m_rGadget->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, DAMAGE_BAR_UV, barColor ); } } // display white blinking box around gadget currently at the top of the queue NounShip * pShip = WidgetCast<NounShip>( m_rGadget->parentBody() ); if ( pShip != NULL && pShip->repairCount() > 0 && pShip->repair( 0 ) == m_rGadget && fmod( activeTime(), 1.0f ) < 0.5f ) renderGlow( context ); } }
bool WindowEdit::onLeftDown( const RectInt & window, const PointInt & position ) { if ( window.inRect( position ) ) { if ( m_Editing ) { Font * pFont = windowStyle()->font(); ASSERT( pFont ); // get pixel offset from left side of window int offset = position.m_X - window.m_Left; // move cursor to position in text int i = m_EditBegin; for(;i<=m_EditEnd && offset > 0;i++) offset -= pFont->characterWidth( m_Text[i] ); // set the cursor position m_Cursor = i; return true; } // begin editing onBeginEdit(); return true; } else { if ( m_Editing ) { onEndEdit(); return true; } } return false; }
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 ); } }
bool TaskBlendSW::run(RunParams & /* params */) const { const synfig::Surface &a = SurfaceSW::Handle::cast_dynamic( sub_task_a()->target_surface )->get_surface(); const synfig::Surface &b = SurfaceSW::Handle::cast_dynamic( sub_task_b()->target_surface )->get_surface(); synfig::Surface &c = SurfaceSW::Handle::cast_dynamic( target_surface )->get_surface(); //debug::DebugSurface::save_to_file(a, "TaskBlendSW__run__a"); //debug::DebugSurface::save_to_file(b, "TaskBlendSW__run__b"); RectInt r = get_target_rect(); if (r.valid()) { RectInt ra = sub_task_a()->get_target_rect() + r.get_min() + offset_a; if (ra.valid()) { etl::set_intersect(ra, ra, r); if (ra.valid() && &a != &c) { synfig::Surface::pen p = c.get_pen(ra.minx, ra.maxx); const_cast<synfig::Surface*>(&a)->blit_to( p, ra.minx - r.minx - offset_a[0], ra.miny - r.miny - offset_a[1], ra.maxx - ra.minx, ra.maxy - ra.miny ); } } RectInt fill[] = { ra, RectInt::zero(), RectInt::zero(), RectInt::zero() }; RectInt rb = sub_task_b()->get_target_rect() + r.get_min() + offset_b; if (rb.valid()) { etl::set_intersect(rb, rb, r); if (rb.valid()) { synfig::Surface::alpha_pen ap(c.get_pen(rb.minx, rb.miny)); ap.set_blend_method(blend_method); ap.set_alpha(amount); const_cast<synfig::Surface*>(&b)->blit_to( ap, rb.minx - r.minx - offset_b[0], rb.miny - r.miny - offset_b[1], rb.maxx - rb.minx, rb.maxy - rb.miny ); if (ra.valid()) { // mark unfilled regions fill[0] = fill[1] = fill[2] = fill[3] = ra; fill[0].maxx = fill[2].minx = fill[3].minx = std::max(ra.minx, std::min(ra.maxx, rb.minx)); fill[1].minx = fill[2].maxx = fill[3].maxx = std::max(ra.minx, std::min(ra.maxx, rb.maxx)); fill[2].maxy = std::max(ra.miny, std::min(ra.maxy, rb.miny)); fill[3].miny = std::max(ra.miny, std::min(ra.maxy, rb.maxy)); } } } if (Color::is_straight(blend_method)) { for(int i = 0; i < 4; ++i) { if (fill[i].valid()) { synfig::Surface::alpha_pen ap( c.get_pen(fill[i].minx, fill[i].miny) ); ap.set_blend_method(blend_method); ap.set_alpha(amount); c.fill( Color(0, 0, 0, 0), ap, fill[i].maxx - fill[i].minx, fill[i].maxy - fill[i].miny ); } } } } //debug::DebugSurface::save_to_file(c, "TaskBlendSW__run__c"); return true; }
void ButtonCargo::onRender( RenderContext & context, const RectInt & window ) { WindowButton::onRender( context, window ); if ( enabled() ) { Noun * pCargo = m_Cargo; ASSERT( pCargo ); // display white box around cargo if current target GameDocument * pDoc = (GameDocument *)document(); ASSERT( pDoc ); if ( pDoc->target() == pCargo && (pDoc->tick() % 10) < 6 ) renderGlow( context ); if ( WidgetCast<CargoEnhancement>( pCargo ) ) { // show the durability if an enhancement.. CargoEnhancement * pCargoEnh = (CargoEnhancement *)pCargo; Font * pFont = windowStyle()->font(); ASSERT( pFont ); NounEnhancement * pEnhancement = pCargoEnh->enhancement(); if ( pEnhancement != NULL ) { int nMaxDamage = pEnhancement->maxDamage(); if ( nMaxDamage > 0 ) { WideString sQuantity; sQuantity.format( "%d/%d", nMaxDamage - pCargoEnh->damage(), nMaxDamage ); SizeInt stringSize( pFont->size( sQuantity ) ); PointInt stringPos( window.m_Right - stringSize.width, window.top ); Font::push( context.display(), pFont, stringPos, sQuantity, WHITE ); } } if ( ((CargoEnhancement *)pCargo)->quantity() <= 0 ) destroy(); } else if ( WidgetCast<NounCargo>( pCargo ) ) { // draw the quantity if cargo Font * pFont = windowStyle()->font(); ASSERT( pFont ); WideString sQuantity; sQuantity.format( "%d", ((NounCargo *)pCargo)->quantity() ); SizeInt stringSize( pFont->size( sQuantity ) ); PointInt stringPos( window.m_Right - stringSize.width, window.top ); Font::push( context.display(), pFont, stringPos, sQuantity, WHITE ); if ( ((NounCargo *)pCargo)->quantity() <= 0 ) destroy(); } else if ( WidgetCast<NounUnit>( pCargo ) ) { NounUnit * pUnit = (NounUnit *)pCargo; // draw the unit health on the button Font * pFont = windowStyle()->font(); ASSERT( pFont ); WideString sHealth; sHealth.format( "%d%%", 100 - ((pUnit->damage() * 100) / pUnit->maxDamage()) ); PointInt ptHealth( window.right - pFont->size( sHealth ).width, window.top ); Font::push( context.display(), pFont, ptHealth, sHealth, WHITE ); // display damage bar if ( pUnit->damage() > 0 ) { float damage = 1.0f - (pUnit->damage() / pUnit->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( context.display(), PrimitiveMaterial::NONE ); PrimitiveWindow::push( context.display(), bar, barUV, barColor ); } } } }
bool synfig::Target_Tile::render_frame_(Context context,ProgressCallback *cb) { const RendDesc &rend_desc(desc); etl::clock total_time; etl::clock::value_type work_time(0); etl::clock::value_type find_tile_time(0); etl::clock::value_type add_tile_time(0); total_time.reset(); // If the quality is set to zero, then we // use the parametric scanline-renderer. if(get_quality()==0) { Surface surface; RendDesc tile_desc; RectInt rect; int i = 0; etl::clock tile_timer; tile_timer.reset(); while(next_tile(rect)) { find_tile_time+=tile_timer(); SuperCallback super(cb,i,i+1,10000); if(!super.amount_complete(0,1000)) return false; ++i; // Perform clipping on the tile if(clipping_) etl::set_intersect(rect, rect, RectInt(0, 0, rend_desc.get_w(), rend_desc.get_h())); tile_desc=rend_desc; tile_desc.set_subwindow(rect.minx, rect.miny, rect.maxx - rect.minx, rect.maxy - rect. miny); if(!parametric_render(context, surface, tile_desc,&super)) { // For some reason, the parametric renderer failed. if(cb)cb->error(_("Parametric Renderer Failure")); return false; } else { if(!surface) { if(cb)cb->error(_("Bad surface")); return false; } switch(get_alpha_mode()) { case TARGET_ALPHA_MODE_FILL: for(int i=0;i<surface.get_w()*surface.get_h();i++) surface[0][i]=Color::blend(surface[0][i],desc.get_bg_color(),1.0f); break; case TARGET_ALPHA_MODE_EXTRACT: for(int i=0;i<surface.get_w()*surface.get_h();i++) { float a=surface[0][i].get_a(); surface[0][i] = Color(a,a,a,a); } break; case TARGET_ALPHA_MODE_REDUCE: for(int i=0;i<surface.get_w()*surface.get_h();i++) surface[0][i].set_a(1.0f); break; default: break; } // Add the tile to the target if(!add_tile(surface, rect.minx, rect.miny)) { if(cb)cb->error(_("add_tile():Unable to put surface on target")); return false; } } tile_timer.reset(); } SuperCallback super(cb,i,10000,10000); } else // If quality is set otherwise, then we use the accelerated renderer { etl::clock tile_timer; tile_timer.reset(); // Gather tiles std::vector<RectInt> tiles; RectInt rect; while(next_tile(rect)) { if (clipping_) if (rect.minx >= rend_desc.get_w() || rect.miny >= rend_desc.get_h()) continue; tiles.push_back(rect); } find_tile_time += tile_timer(); // Render tiles for(std::vector<RectInt>::iterator i = tiles.begin(); i != tiles.end(); ++i) { // Progress callback int index = i - tiles.begin(); int count = (int)tiles.size(); SuperCallback super(cb, (count-index)*1000, (count-index+1)*1000, count*1000); if(!super.amount_complete(0,1000)) return false; // Render tile tile_timer.reset(); rect = *i; if (clipping_) etl::set_intersect(rect, rect, RectInt(0, 0, rend_desc.get_w(), rend_desc.get_h())); if (!rect.valid()) continue; RendDesc tile_desc=rend_desc; tile_desc.set_subwindow(rect.minx, rect.miny, rect.maxx - rect.minx, rect.maxy - rect.miny); async_render_tile(rect, context, tile_desc, &super); } } if (!wait_render_tiles(cb)) return false; if(cb && !cb->amount_complete(10000,10000)) return false; #ifdef SYNFIG_DISPLAY_EFFICIENCY synfig::info(">>>>>> Render Time: %fsec, Find Tile Time: %fsec, Add Tile Time: %fsec, Total Time: %fsec",work_time,find_tile_time,add_tile_time,total_time()); synfig::info(">>>>>> FRAME EFFICIENCY: %f%%",(100.0f*work_time/total_time())); #endif return true; }
void WindowButton::onRender( RenderContext & context, const RectInt & window ) { int baseAlpha = m_Alpha * 255; int alpha = Clamp( baseAlpha + (enabled() ? (m_ButtonDown ? DOWN_ALPHA : m_CursorOver ? OVER_ALPHA : 0) : DISABLED_ALPHA) , 0, 255 ); // update the image frame if ( m_Button.valid() ) { static RectFloat buttonUV( 0, 0, 1, 1 ); // get the button color //Color buttonColor( m_ButtonDown ? windowStyle()->highColor() : windowStyle()->color() ); Color buttonColor( m_ButtonDown ? m_Color * 2.0f : m_Color ); buttonColor.m_A = alpha; if ( m_bGreyed ) buttonColor.greyscale(BUTTON_GREYED_SCALE); // if the button has multiple frames, set the time to display the correct frame if ( m_Button->frames() > 1 ) { ASSERT( m_Button->fps() > 0 ); int frame = 0; if ( m_Button->frames() == 2 ) frame = m_ButtonDown ? 1 : 0; else frame = m_ButtonDown ? 1 : m_CursorOver ? 2 : 0; m_Time = (1.0f / m_Button->fps()) * frame; } RectInt buttonRect( window ); if ( (m_Style & LOCK_ICON_SIZE) != 0 ) { int nDiffuse = m_Button->findTexture( PrimitiveSurface::DIFFUSE ); if ( nDiffuse >= 0 ) { SizeInt buttonSize( m_Button->texture( nDiffuse ).m_pImage->size() ); // keep button original size buttonRect.setWidth( buttonSize.width ); buttonRect.setHeight( buttonSize.height ); } } // flush the button material, so we can have different frames for each button m_Button->flushMaterial(); // save then change the context time float fContextTime = context.time(); context.setTime( m_Time ); // push the button material Material::push( context, m_Button ); // draw the button PrimitiveWindow::push( context.display(), buttonRect, buttonUV, buttonColor ); // restore the context time context.setTime( fContextTime ); } // display the label if ( m_Label.length() > 0 ) { String sLabel = m_Label; Font * pFont = windowStyle()->font(); ASSERT( pFont ); Color cLabel = labelColor(); if ( m_Style & EFFECT_FADEIN && visibleTime() < BUTTON_FADE_IN_TIME ) cLabel.a = (visibleTime() / BUTTON_FADE_IN_TIME) * 255; else cLabel.a = 255; SizeInt labelSize( pFont->size( sLabel ) ); PointInt labelPos( window.m_Left + ((window.width() / 2) - (labelSize.width / 2)), window.m_Top + ((window.height() / 2) - (labelSize.height / 2)) ); Font::push( context.display(), pFont, labelPos, sLabel, cLabel ); } // display hotkey in lower right corner if ( (m_Style & SHOW_HOTKEY) != 0 && m_HotKey != 0 ) { Font * pFont = windowStyle()->font(); ASSERT( pFont ); Color color( ((m_CursorOver || m_ButtonDown) && enabled()) ? windowStyle()->highColor() : windowStyle()->color() ); if ( m_Style & EFFECT_FADEIN && visibleTime() < BUTTON_FADE_IN_TIME ) color.a = (visibleTime() / BUTTON_FADE_IN_TIME) * 255; else color.a = 255; if ( m_bGreyed ) color.greyscale(BUTTON_GREYED_SCALE); String sKey( Keyboard::keyShortText( Keyboard::unmap( m_HotKey ) ) ); SizeInt textSize( pFont->size( sKey ) ); PointInt textPos( window.m_Right - textSize.width, window.m_Bottom - textSize.height ); Font::push( context.display(), pFont, textPos, sKey, color ); } }
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 ); } }
Surface::Handle SurfaceResource::get_surface( const Surface::Token::Handle &token, bool exclusive, // for write access bool full, const RectInt &rect, bool create, bool any ) { if (!token && !any) return Surface::Handle(); if (!full && !rect.is_valid()) return Surface::Handle(); Glib::Threads::Mutex::Lock lock(mutex); if (width <= 0 || height <= 0) return Surface::Handle(); if (!full && !etl::contains(RectInt(0, 0, width, height), rect)) return Surface::Handle(); Surface::Handle surface; Map::const_iterator i = surfaces.find(token); if (i != surfaces.end()) surface = i->second; else if (any && !surfaces.empty()) surface = surfaces.begin()->second; else if (!create) return Surface::Handle(); if (!surface) { surface = token->fabric(); if (!surface) return Surface::Handle(); if (blank) { if (!surface->create(width, height)) return Surface::Handle(); } else { bool found = false; for(Map::const_iterator i = surfaces.begin(); i != surfaces.end() && !found; ++i) if (i->second->get_pixels_pointer() && surface->assign(*i->second)) found = true; for(Map::const_iterator i = surfaces.begin(); i != surfaces.end() && !found; ++i) if (!i->second->get_pixels_pointer() && surface->assign(*i->second)) found = true; if (!found) return Surface::Handle(); } if (exclusive) surfaces.clear(); // all other surfaces invalidated surfaces[token] = surface; } if (exclusive) { if (surfaces.size() != 1) // keep only current surface in map { surfaces.clear(); surfaces[token] = surface; } surface->touch(); blank = false; } return surface; }
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 ); }