Object Draw: Really fix message display

floating-point
Günther Brammer 2010-09-25 22:52:43 +02:00
parent e40fbcad03
commit e6ad5d3bd4
5 changed files with 45 additions and 42 deletions

View File

@ -5084,6 +5084,11 @@ void C4Object::GetParallaxity(int32_t *parX, int32_t *parY)
{
assert(parX); assert(parY);
*parX = 100; *parY = 100;
if (Category & C4D_Foreground)
{
*parX = 0; *parY = 0;
return;
}
if (!(Category & C4D_Parallax)) return;
C4Value parV; GetPropertyVal(P_Parallaxity, &parV);
C4ValueArray *par = parV.getArray();
@ -5135,7 +5140,7 @@ bool C4Object::GetDrawPosition(const C4TargetFacet & cgo, float objx, float objy
GetParallaxity(&iParX, &iParY);
float targetx = cgo.TargetX; float targety = cgo.TargetY;
int width = cgo.Wdt; int height = cgo.Hgt;
float parx = iParX/100.0f; float pary = iParY / 100.0f;
float parx = iParX / 100.0f; float pary = iParY / 100.0f;
float par = parx; //todo: pary?
// Old
/*resultzoom = zoom;
@ -5156,7 +5161,7 @@ bool C4Object::GetDrawPosition(const C4TargetFacet & cgo, float objx, float objy
// Step 1: project to landscape coordinates
resultzoom = 1.0 / (1.0 - (par - par/zoom));
if (resultzoom < 0 || resultzoom > 100) // FIXME: optimize treshhold
if (resultzoom <= 0 || resultzoom > 100) // FIXME: optimize treshhold
return false;
float rx = ((1 - parx) * targetx) * resultzoom + objx;

View File

@ -106,7 +106,7 @@ int32_t DrawMessageOffset = -35; // For finding the optimum place to draw startu
int32_t PortraitWidth = 64;
int32_t PortraitIndent = 10;
void C4GameMessage::Draw(C4TargetFacet &cgo, int32_t iPlayer, float Zoom)
void C4GameMessage::Draw(C4TargetFacet &cgo, int32_t iPlayer)
{
// Globals or player
if (Type == C4GM_Global || ((Type == C4GM_GlobalPlayer) && (iPlayer == Player)))
@ -188,17 +188,12 @@ void C4GameMessage::Draw(C4TargetFacet &cgo, int32_t iPlayer, float Zoom)
{
// adjust position by object; care about parallaxity
float iMsgX, iMsgY, newzoom;
if (Type == C4GM_Target || Type == C4GM_TargetPlayer)
{
Target->GetDrawPosition(cgo, iMsgX, iMsgY, newzoom);
iMsgY -= Target->Def->Shape.Hgt/2+5;
iMsgX+=X; iMsgY+=Y;
}
else
{ iMsgX=X; iMsgY=Y; }
Target->GetDrawPosition(cgo, iMsgX, iMsgY, newzoom);
iMsgY -= Target->Def->Shape.Hgt/2+5;
iMsgX+=X; iMsgY+=Y;
// check output bounds
if (Inside<float>((iMsgX - cgo.X) * newzoom, 0, cgo.Wdt - 1))
if (Inside<float>((iMsgY - cgo.Y) * newzoom, 0, cgo.Hgt - 1))
if (Inside<float>((iMsgX - cgo.X) * newzoom, 0, cgo.Wdt * cgo.Zoom - 1))
if (Inside<float>((iMsgY - cgo.Y) * newzoom, 0, cgo.Hgt * cgo.Zoom - 1))
{
// if the message is attached to an object and the object
// is invisible for that player, the message won't be drawn
@ -208,7 +203,7 @@ void C4GameMessage::Draw(C4TargetFacet &cgo, int32_t iPlayer, float Zoom)
// check fog of war
C4Player *pPlr = ::Players.Get(iPlayer);
if (pPlr && pPlr->fFogOfWar)
if (!pPlr->FoWIsVisible(iMsgX, iMsgY))
if (!pPlr->FoWIsVisible(iMsgX + cgo.TargetX - cgo.X, iMsgY + cgo.TargetY - cgo.Y))
{
// special: Target objects that ignore FoW should display the message even if within FoW
if (Type != C4GM_Target && Type != C4GM_TargetPlayer) return;
@ -217,22 +212,25 @@ void C4GameMessage::Draw(C4TargetFacet &cgo, int32_t iPlayer, float Zoom)
// Word wrap to cgo width
StdStrBuf sText;
if (~dwFlags & C4GM_NoBreak)
::GraphicsResource.FontRegular.BreakMessage(Text.getData(), BoundBy<int32_t>(cgo.Wdt, 50, 200), &sText, true);
::GraphicsResource.FontRegular.BreakMessage(Text.getData(), BoundBy<int32_t>(cgo.Wdt * cgo.Zoom, 50, 200), &sText, true);
else
sText.Ref(Text);
// Adjust position by output boundaries
int32_t iTX,iTY,iTWdt,iTHgt;
float iTX,iTY;
int iTWdt,iTHgt;
::GraphicsResource.FontRegular.GetTextExtent(sText.getData(),iTWdt,iTHgt,true);
// +0.5f for proper rounding; avoids oscillations near pixel border:
iTX = BoundBy<float>((iMsgX - cgo.X) * newzoom, iTWdt/2, cgo.Wdt - iTWdt / 2) + 0.5f;
iTY = BoundBy<float>((iMsgY - cgo.Y) * newzoom - iTHgt, 0, cgo.Hgt - iTHgt) + 0.5f;
iTX = BoundBy<float>((iMsgX - cgo.X) * newzoom, iTWdt/2, cgo.Wdt * cgo.Zoom - iTWdt / 2) + 0.5f;
iTY = BoundBy<float>((iMsgY - cgo.Y) * newzoom - iTHgt, 0, cgo.Hgt * cgo.Zoom - iTHgt) + 0.5f;
// Draw
Application.DDraw->TextOut(sText.getData(), ::GraphicsResource.FontRegular, 1.0,
cgo.Surface,
cgo.X + iTX,
cgo.Y + iTY,
ColorDw,ACenter);
return;
}
fprintf(stderr, "%f %f '%s'\n", iMsgX, iMsgY, Text.getData());
}
}
@ -377,17 +375,15 @@ void C4GameMessageList::UpdateDef(C4ID idUpdDef)
for (cmsg=First; cmsg; cmsg=cmsg->Next) cmsg->UpdateDef(idUpdDef);
}
void C4GameMessageList::Draw(C4TargetFacet &cgo, int32_t iPlayer, float Zoom)
void C4GameMessageList::Draw(C4TargetFacet &gui_cgo, C4TargetFacet &cgo, int32_t iPlayer)
{
C4GameMessage *cmsg;
for (cmsg=First; cmsg; cmsg=cmsg->Next)
{
// determine zoom: GUI object messages need to be drawn in GUI zoom
float msg_zoom = Zoom;
if ((cmsg->Target && (cmsg->Target->Category & C4D_Foreground)) || cmsg->Type == C4GM_Global || cmsg->Type == C4GM_GlobalPlayer)
msg_zoom = C4GUI::GetZoom();
// draw msg
cmsg->Draw(cgo,iPlayer,msg_zoom);
cmsg->Draw(gui_cgo,iPlayer);
else
cmsg->Draw(cgo,iPlayer);
}
}

View File

@ -54,7 +54,7 @@ class C4GameMessage
{
friend class C4GameMessageList;
public:
void Draw(C4TargetFacet &cgo, int32_t iPlayer, float Zoom);
void Draw(C4TargetFacet &cgo, int32_t iPlayer);
C4GameMessage();
~C4GameMessage();
protected:
@ -91,7 +91,7 @@ public:
void Default();
void Clear();
void Execute();
void Draw(C4TargetFacet &cgo, int32_t iPlayer, float Zoom);
void Draw(C4TargetFacet &gui_cgo, C4TargetFacet &cgo, int32_t iPlayer);
void ClearPlayers(int32_t iPlayer, int32_t dwPositioningFlags);
void ClearPointers(C4Object *pObj);
void UpdateDef(C4ID idUpdDef); // called after reloaddef

View File

@ -891,10 +891,6 @@ void C4Viewport::DrawOverlay(C4TargetFacet &cgo, const ZoomData &GameZoom)
DrawMenu(cgo);
C4ST_STOP(MenuStat)
}
// Game messages
C4ST_STARTNEW(MsgStat, "C4Viewport::DrawOverlay: Messages")
::Messages.Draw(cgo, Player, Zoom);
C4ST_STOP(MsgStat)
// Control overlays (if not film/replay)
if (!Game.C4S.Head.Film || !Game.C4S.Head.Replay)
@ -980,7 +976,7 @@ void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawOverlay)
C4TargetFacet cgo; cgo.Set(cgo0);
ZoomData GameZoom;
GameZoom.X = cgo.X; GameZoom.Y = cgo.Y;
GameZoom.Zoom = Zoom;
GameZoom.Zoom = cgo.Zoom;
if (fDrawOverlay)
{
@ -991,12 +987,11 @@ void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawOverlay)
if (BorderBottom)Application.DDraw->BlitSurfaceTile(::GraphicsResource.fctBackground.Surface,cgo.Surface,DrawX+BorderLeft,DrawY+ViewHgt-BorderBottom,ViewWdt-BorderLeft-BorderRight,BorderBottom,-DrawX-BorderLeft,-DrawY-ViewHgt+BorderBottom);
// Set clippers
cgo.X += BorderLeft; cgo.Y += BorderTop; cgo.Wdt -= int(float(BorderLeft+BorderRight)/Zoom); cgo.Hgt -= int(float(BorderTop+BorderBottom)/Zoom);
cgo.X += BorderLeft; cgo.Y += BorderTop; cgo.Wdt -= int(float(BorderLeft+BorderRight)/cgo.Zoom); cgo.Hgt -= int(float(BorderTop+BorderBottom)/cgo.Zoom);
GameZoom.X = cgo.X; GameZoom.Y = cgo.Y;
cgo.TargetX += BorderLeft/Zoom; cgo.TargetY += BorderTop/Zoom;
// Apply Zoom
lpDDraw->SetZoom(GameZoom);
cgo.Zoom = GameZoom.Zoom;
Application.DDraw->SetPrimaryClipper(cgo.X,cgo.Y,DrawX+ViewWdt-1-BorderRight,DrawY+ViewHgt-1-BorderBottom);
}
last_game_draw_cgo = cgo;
@ -1054,27 +1049,33 @@ void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawOverlay)
// now restore complete cgo range for overlay drawing
lpDDraw->SetZoom(DrawX,DrawY, fGUIZoom);
Application.DDraw->SetPrimaryClipper(DrawX,DrawY,DrawX+(ViewWdt-1),DrawY+(ViewHgt-1));
cgo.Set(cgo0);
C4TargetFacet gui_cgo;
gui_cgo.Set(cgo0);
cgo.X = DrawX; cgo.Y = DrawY; cgo.Zoom = fGUIZoom;
cgo.Wdt = int(float(ViewWdt)/fGUIZoom); cgo.Hgt = int(float(ViewHgt)/fGUIZoom);
cgo.TargetX = ViewX; cgo.TargetY = ViewY;
gui_cgo.X = DrawX; gui_cgo.Y = DrawY; gui_cgo.Zoom = fGUIZoom;
gui_cgo.Wdt = int(float(ViewWdt)/fGUIZoom); gui_cgo.Hgt = int(float(ViewHgt)/fGUIZoom);
gui_cgo.TargetX = ViewX; gui_cgo.TargetY = ViewY;
last_gui_draw_cgo = cgo;
last_gui_draw_cgo = gui_cgo;
// draw custom GUI objects
::Objects.ForeObjects.DrawIfCategory(cgo, Player, C4D_Foreground, false);
::Objects.ForeObjects.DrawIfCategory(gui_cgo, Player, C4D_Foreground, false);
// Draw overlay
C4ST_STARTNEW(OvrStat, "C4Viewport::Draw: Overlay")
if (!Application.isFullScreen) Console.EditCursor.Draw(cgo);
DrawOverlay(cgo, GameZoom);
DrawOverlay(gui_cgo, GameZoom);
// Game messages
C4ST_STARTNEW(MsgStat, "C4Viewport::DrawOverlay: Messages")
::Messages.Draw(gui_cgo, cgo, Player);
C4ST_STOP(MsgStat)
// Netstats
if (::GraphicsSystem.ShowNetstatus)
::Network.DrawStatus(cgo);
::Network.DrawStatus(gui_cgo);
C4ST_STOP(OvrStat)
@ -1115,7 +1116,7 @@ void C4Viewport::Execute()
C4TargetFacet cgo;
CStdWindow * w = pWindow;
if (!w) w = &FullScreen;
cgo.Set(w->pSurface,DrawX,DrawY,int32_t(ceilf(float(ViewWdt)/Zoom)),int32_t(ceilf(float(ViewHgt)/Zoom)),ViewX,ViewY);
cgo.Set(w->pSurface,DrawX,DrawY,int32_t(ceilf(float(ViewWdt)/Zoom)),int32_t(ceilf(float(ViewHgt)/Zoom)),ViewX,ViewY,Zoom);
lpDDraw->PrepareRendering(w->pSurface);
// Draw
Draw(cgo, true);

View File

@ -346,6 +346,7 @@ protected:
struct ZoomDataStackItem: public ZoomData
{
ZoomDataStackItem(float newzoom) { lpDDraw->GetZoom(this); lpDDraw->SetZoom(X, Y, newzoom); }
ZoomDataStackItem(int X, int Y, float newzoom) { lpDDraw->GetZoom(this); lpDDraw->SetZoom(X, Y, newzoom); }
~ZoomDataStackItem() { lpDDraw->SetZoom(*this); }
};