Object Draw: Account for parallaxity when zooming

Also zoom a parallax sky correctly.
floating-point
Günther Brammer 2010-09-24 19:51:34 +02:00
parent 5dc10647e2
commit 3dde77508a
11 changed files with 60 additions and 31 deletions

View File

@ -398,7 +398,7 @@ bool C4EditCursor::Duplicate()
return true;
}
void C4EditCursor::Draw(C4TargetFacet &cgo, float Zoom)
void C4EditCursor::Draw(C4TargetFacet &cgo)
{
// Draw selection marks
C4Object *cobj; C4ObjectLink *clnk;
@ -406,7 +406,7 @@ void C4EditCursor::Draw(C4TargetFacet &cgo, float Zoom)
{
// target pos (parallax)
float offX, offY, newzoom;
cobj->GetDrawPosition(cgo, Zoom, offX, offY, newzoom);
cobj->GetDrawPosition(cgo, offX, offY, newzoom);
FLOAT_RECT frame =
{
(offX+cobj->Shape.x-cgo.X)*newzoom + cgo.X,
@ -426,7 +426,7 @@ void C4EditCursor::Draw(C4TargetFacet &cgo, float Zoom)
if (~cobj->Category & C4D_Foreground)
{
lpDDraw->GetZoom(&zd);
lpDDraw->SetZoom(cgo.X, cgo.Y, Zoom);
lpDDraw->SetZoom(cgo.X, cgo.Y, cgo.Zoom);
}
StdMeshInstance::FaceOrdering old_fo = StdMeshInstance::FO_Fixed;
@ -447,6 +447,7 @@ void C4EditCursor::Draw(C4TargetFacet &cgo, float Zoom)
cobj->BlitMode = dwOldBlitMode;
}
}
float Zoom = cgo.Zoom;
// Draw drag frame
if (DragFrame)
Application.DDraw->DrawFrameDw(cgo.Surface,Min(X,X2)*Zoom+cgo.X-cgo.TargetX*Zoom,Min(Y,Y2)*Zoom+cgo.Y-cgo.TargetY*Zoom,Max(X,X2)*Zoom+cgo.X-cgo.TargetX*Zoom,Max(Y,Y2)*Zoom+cgo.Y-cgo.TargetY*Zoom,0xffffffff);

View File

@ -61,7 +61,7 @@ public:
void Execute();
void ClearPointers(C4Object *pObj);
bool ToggleMode();
void Draw(C4TargetFacet &cgo, float Zoom);
void Draw(C4TargetFacet &cgo);
int32_t GetMode();
C4Object* GetTarget();
bool SetMode(int32_t iMode);

View File

@ -222,9 +222,25 @@ void C4Sky::Draw(C4TargetFacet &cgo)
if (Surface)
{
// blit parallax sky
int iParX = cgo.TargetX * 10 / ParX - fixtoi(x);
int iParY = cgo.TargetY * 10 / ParY - fixtoi(y);
Application.DDraw->BlitSurfaceTile2(Surface, cgo.Surface, cgo.X, cgo.Y, cgo.Wdt, cgo.Hgt, iParX, iParY, false);
float zoom = cgo.Zoom;
float targetx = cgo.TargetX; float targety = cgo.TargetY;
int width = cgo.Wdt; int height = cgo.Hgt;
float parx = 10.0f / ParX; float pary = 10.0f / ParY;
float par = parx; //todo: pary?
// Step 1: project to landscape coordinates
float resultzoom = 1.0 / (1.0 - (par - par/zoom));
float rx = ((1 - parx) * targetx) * resultzoom + fixtof(x);
float ry = ((1 - pary) * targety) * resultzoom + fixtof(y);
// Step 2: convert to screen coordinates
float resultx = (rx - targetx) * zoom / resultzoom;
float resulty = (ry - targety) * zoom / resultzoom;
ZoomDataStackItem zdsi(resultzoom);
Application.DDraw->BlitSurfaceTile2(Surface, cgo.Surface, cgo.X, cgo.Y, cgo.Wdt * zoom / resultzoom, cgo.Hgt * zoom / resultzoom, -resultx, -resulty, false);
}
else
{

View File

@ -990,7 +990,8 @@ void C4GraphicsOverlay::Draw(C4TargetFacet &cgo, C4Object *pForObj, int32_t iByP
// get target pos
float offX, offY;
float newzoom;
pForObj->GetDrawPosition(cgo, 1.0, offX, offY, newzoom);
pForObj->GetDrawPosition(cgo, offX, offY, newzoom);
ZoomDataStackItem zdsi(newzoom);
// special blit mode
if (dwBlitMode == C4GFXBLIT_PARENT)

View File

@ -2306,8 +2306,9 @@ void C4Object::Draw(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDrawMode, f
float newzoom;
if (eDrawMode!=ODM_Overlay)
{
if (!GetDrawPosition(cgo, 1.0, offX, offY, newzoom)) return;
if (!GetDrawPosition(cgo, offX, offY, newzoom)) return;
}
ZoomDataStackItem zdsi(newzoom);
bool fYStretchObject=false;
C4PropList* pActionDef = GetAction();
@ -2356,9 +2357,10 @@ void C4Object::Draw(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDrawMode, f
// Angle
int32_t iAngle; iAngle=Angle(ccx,ccy,pCom->Tx._getInt(),pCom->Ty); while (iAngle>180) iAngle-=360;
// Path
if(GetDrawPosition(cgo, ccx, ccy, 1.0, offX1, offY1, newzoom) &&
GetDrawPosition(cgo, pCom->Tx._getInt(), pCom->Ty, 1.0, offX2, offY2, newzoom))
if(GetDrawPosition(cgo, ccx, ccy, cgo.Zoom, offX1, offY1, newzoom) &&
GetDrawPosition(cgo, pCom->Tx._getInt(), pCom->Ty, cgo.Zoom, offX2, offY2, newzoom))
{
ZoomDataStackItem zdsi(newzoom);
Application.DDraw->DrawLineDw(cgo.Surface,offX1,offY1,offX2,offY2,C4RGB(0xca,0,0));
Application.DDraw->DrawFrameDw(cgo.Surface,offX2-1,offY2-1,offX2+1,offY2+1,C4RGB(0xca,0,0));
}
@ -2389,9 +2391,10 @@ void C4Object::Draw(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDrawMode, f
break;
case C4CMD_Transfer:
// Path
if(GetDrawPosition(cgo, ccx, ccy, 1.0, offX1, offY1, newzoom) &&
GetDrawPosition(cgo, pCom->Tx._getInt(), pCom->Ty, 1.0, offX2, offY2, newzoom))
if(GetDrawPosition(cgo, ccx, ccy, cgo.Zoom, offX1, offY1, newzoom) &&
GetDrawPosition(cgo, pCom->Tx._getInt(), pCom->Ty, cgo.Zoom, offX2, offY2, newzoom))
{
ZoomDataStackItem zdsi(newzoom);
Application.DDraw->DrawLineDw(cgo.Surface,offX1,offY1,offX2,offY2,C4RGB(0,0xca,0));
Application.DDraw->DrawFrameDw(cgo.Surface,offX2-1,offY2-1,offX2+1,offY2+1,C4RGB(0,0xca,0));
}
@ -2576,7 +2579,8 @@ void C4Object::DrawTopFace(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDraw
if (!IsVisible(iByPlayer, eDrawMode==ODM_Overlay)) return;
// target pos (parallax)
float newzoom;
if (eDrawMode!=ODM_Overlay) GetDrawPosition(cgo, 1.0, offX, offY, newzoom);
if (eDrawMode!=ODM_Overlay) GetDrawPosition(cgo, offX, offY, newzoom);
ZoomDataStackItem zdsi(newzoom);
// Clonk name
// Name of Owner/Clonk (only when Crew Member; never in films)
if (OCF & OCF_CrewMember)
@ -3159,7 +3163,7 @@ void C4Object::SyncClearance()
}
}
void C4Object::DrawSelectMark(C4TargetFacet &cgo, float Zoom)
void C4Object::DrawSelectMark(C4TargetFacet &cgo)
{
// Status
if (!Status) return;
@ -3167,13 +3171,13 @@ void C4Object::DrawSelectMark(C4TargetFacet &cgo, float Zoom)
if (Game.C4S.Head.Film && Game.C4S.Head.Replay) return;
// target pos (parallax)
float offX, offY, newzoom;
GetDrawPosition(cgo, Zoom, offX, offY, newzoom);
GetDrawPosition(cgo, offX, offY, newzoom);
// Output boundary
if (!Inside<float>(offX, cgo.X, cgo.X + cgo.Wdt)
|| !Inside<float>(offY, cgo.Y, cgo.Y + cgo.Hgt)) return;
// Draw select marks
float cox = (offX + Shape.GetX() - cgo.X) * Zoom + cgo.X - 2;
float coy = (offY + Shape.GetY() - cgo.Y) * Zoom + cgo.Y - 2;
float cox = (offX + Shape.GetX() - cgo.X) * newzoom + cgo.X - 2;
float coy = (offY + Shape.GetY() - cgo.Y) * newzoom + cgo.Y - 2;
GfxR->fctSelectMark.Draw(cgo.Surface,cox,coy,0);
GfxR->fctSelectMark.Draw(cgo.Surface,cox+Shape.Wdt*newzoom,coy,1);
GfxR->fctSelectMark.Draw(cgo.Surface,cox,coy+Shape.Hgt*newzoom,2);
@ -4852,7 +4856,7 @@ void C4Object::SetAudibilityAt(C4TargetFacet &cgo, int32_t iX, int32_t iY)
{
// target pos (parallax)
float offX, offY, newzoom;
GetDrawPosition(cgo, iX, iY, 1.0, offX, offY, newzoom);
GetDrawPosition(cgo, iX, iY, cgo.Zoom, offX, offY, newzoom);
Audible = Max<int>(Audible, BoundBy(100 - 100 * Distance(cgo.X + cgo.Wdt / 2, cgo.Y + cgo.Hgt / 2, offX, offY) / 700, 0, 100));
AudiblePan = BoundBy<int>(200 * (offX - cgo.X - (cgo.Wdt / 2)) / cgo.Wdt, -100, 100);
}
@ -5119,10 +5123,10 @@ void C4Object::UnSelect()
Call(PSF_CrewSelection, &C4AulParSet(C4VBool(true)));
}
bool C4Object::GetDrawPosition(const C4TargetFacet & cgo, float zoom,
bool C4Object::GetDrawPosition(const C4TargetFacet & cgo,
float & resultx, float & resulty, float & resultzoom)
{
return GetDrawPosition(cgo, fixtof(fix_x), fixtof(fix_y), zoom, resultx, resulty, resultzoom);
return GetDrawPosition(cgo, fixtof(fix_x), fixtof(fix_y), cgo.Zoom, resultx, resulty, resultzoom);
}
bool C4Object::GetDrawPosition(const C4TargetFacet & cgo, float objx, float objy, float zoom, float & resultx, float & resulty, float & resultzoom)
@ -5134,7 +5138,7 @@ bool C4Object::GetDrawPosition(const C4TargetFacet & cgo, float objx, float objy
float parx = iParX/100.0f; float pary = iParY / 100.0f;
float par = parx; //todo: pary?
// Old
resultzoom = zoom;
/*resultzoom = zoom;
if(parx == 0 && fix_x < 0)
resultx = cgo.X + objx + cgo.Wdt;
@ -5146,7 +5150,7 @@ bool C4Object::GetDrawPosition(const C4TargetFacet & cgo, float objx, float objy
else
resulty = cgo.Y + objy - targety*pary;
return true;
return true;*/
// New

View File

@ -225,7 +225,7 @@ public:
C4Command *FindCommand(int32_t iCommandType); // find a command of the given type
void ClearCommand(C4Command *pUntil);
void ClearCommands();
void DrawSelectMark(C4TargetFacet &cgo, float Zoom);
void DrawSelectMark(C4TargetFacet &cgo);
void UpdateActionFace();
void SyncClearance();
void SetSolidMask(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY);
@ -365,7 +365,7 @@ public:
bool ShiftContents(bool fShiftBack, bool fDoCalls); // rotate through contents
void DirectComContents(C4Object *pTarget, bool fDoCalls); // direct com: scroll contents to given ID
void GetParallaxity(int32_t *parX, int32_t *parY);
bool GetDrawPosition(const C4TargetFacet & cgo, float zoom, float & resultx, float & resulty, float & resultzoom); // converts the object's position into screen coordinates
bool GetDrawPosition(const C4TargetFacet & cgo, float & resultx, float & resulty, float & resultzoom); // converts the object's position into screen coordinates
bool GetDrawPosition(const C4TargetFacet & cgo, float x, float y, float zoom, float & resultx, float & resulty, float & resultzoom); // converts object coordinates into screen coordinates
bool IsInLiquidCheck(); // returns whether the Clonk is within liquid material
void UpdateInLiquid(); // makes splash when a liquid is entered

View File

@ -739,11 +739,11 @@ void C4ObjectList::UpdateFaces(bool bUpdateShapes)
cLnk->Obj->UpdateFace(bUpdateShapes);
}
void C4ObjectList::DrawSelectMark(C4TargetFacet &cgo, float Zoom)
void C4ObjectList::DrawSelectMark(C4TargetFacet &cgo)
{
C4ObjectLink *cLnk;
for (cLnk=Last; cLnk; cLnk=cLnk->Prev)
cLnk->Obj->DrawSelectMark(cgo, Zoom);
cLnk->Obj->DrawSelectMark(cgo);
}
void C4ObjectList::CloseMenus()

View File

@ -100,7 +100,7 @@ public:
void Draw(C4TargetFacet &cgo, int iPlayer = -1); // draw all objects
void DrawList(C4Facet &cgo, int iSelection=-1, DWORD dwCategory=C4D_All);
void DrawIDList(C4Facet &cgo, int iSelection, C4DefList &rDefs, int32_t dwCategory, C4RegionList *pRegions=NULL, int iRegionCom=COM_None, bool fDrawOneCounts=true);
void DrawSelectMark(C4TargetFacet &cgo, float Zoom);
void DrawSelectMark(C4TargetFacet &cgo);
void CloseMenus();
void UpdateGraphics(bool fGraphicsChanged);
void UpdateFaces(bool bUpdateShape);

View File

@ -400,7 +400,7 @@ void C4MouseControl::Draw(C4TargetFacet &cgo, const ZoomData &GameZoom)
// Draw selection
if (!IsPassive())
{
Selection.DrawSelectMark(cgo, 1.0f);
Selection.DrawSelectMark(cgo);
}
// Draw control

View File

@ -996,6 +996,7 @@ void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawOverlay)
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;
@ -1055,7 +1056,7 @@ void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawOverlay)
Application.DDraw->SetPrimaryClipper(DrawX,DrawY,DrawX+(ViewWdt-1),DrawY+(ViewHgt-1));
cgo.Set(cgo0);
cgo.X = DrawX; cgo.Y = DrawY;
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;
@ -1067,7 +1068,7 @@ void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawOverlay)
// Draw overlay
C4ST_STARTNEW(OvrStat, "C4Viewport::Draw: Overlay")
if (!Application.isFullScreen) Console.EditCursor.Draw(cgo, Zoom);
if (!Application.isFullScreen) Console.EditCursor.Draw(cgo);
DrawOverlay(cgo, GameZoom);

View File

@ -343,6 +343,12 @@ protected:
friend class CStdD3DShader;
};
struct ZoomDataStackItem: public ZoomData
{
ZoomDataStackItem(float newzoom) { lpDDraw->GetZoom(this); lpDDraw->SetZoom(X, Y, newzoom); }
~ZoomDataStackItem() { lpDDraw->SetZoom(*this); }
};
bool LockSurfaceGlobal(SURFACE sfcTarget);
bool UnLockSurfaceGlobal(SURFACE sfcTarget);
bool DLineSPix(int32_t x, int32_t y, int32_t col);