forked from Mirrors/openclonk
168 lines
5.1 KiB
C
168 lines
5.1 KiB
C
/**
|
|
ConstructionPreviewer
|
|
|
|
|
|
@author Clonkonaut
|
|
*/
|
|
|
|
static const CONSTRUCTION_STICK_Left = 1;
|
|
static const CONSTRUCTION_STICK_Right = 2;
|
|
static const CONSTRUCTION_STICK_Bottom = 4;
|
|
|
|
local dimension_x, dimension_y, clonk, structure, direction, stick_to, blocked;
|
|
local GFX_StructureOverlay = 1;
|
|
local GFX_CombineIconOverlay = 2;
|
|
|
|
public func GetFlipDescription() { return "$TxtFlipDesc$"; }
|
|
|
|
func Initialize()
|
|
{
|
|
SetProperty("Visibility", VIS_Owner);
|
|
}
|
|
|
|
func Set(id to_construct, object constructing_clonk)
|
|
{
|
|
SetGraphics(nil, to_construct, GFX_StructureOverlay, GFXOV_MODE_Base);
|
|
SetGraphics(nil, to_construct, 3, GFXOV_MODE_Picture, nil, GFX_BLIT_Wireframe);
|
|
dimension_x = to_construct->GetDefWidth();
|
|
dimension_y = to_construct->GetDefHeight();
|
|
|
|
clonk = constructing_clonk;
|
|
structure = to_construct;
|
|
direction = DIR_Left;
|
|
blocked = true;
|
|
AdjustPreview(structure->~IsBelowSurfaceConstruction());
|
|
return;
|
|
}
|
|
|
|
// Positions the preview according to the landscape, coloring it green, yellow or red
|
|
public func AdjustPreview(bool below_surface, bool look_up, bool no_call)
|
|
{
|
|
var half_y = dimension_y / 2;
|
|
blocked = false;
|
|
// Do only if not sticking to another object
|
|
if (!stick_to)
|
|
{
|
|
// Place on material
|
|
var search_dir = 1;
|
|
if (look_up) search_dir = -1;
|
|
var x = 0, y = 0;
|
|
while (!(!GBackSolid(x,y + half_y) && GBackSolid(x,y + half_y + 1)))
|
|
{
|
|
y += search_dir;
|
|
if (Abs(y) > half_y)
|
|
{
|
|
blocked = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (blocked && !no_call)
|
|
return AdjustPreview(below_surface, !look_up, true);
|
|
if (blocked)
|
|
return SetClrModulation(RGBa(255,50,50, 100), GFX_StructureOverlay);
|
|
// Position depends on whether the object should below surface.
|
|
if (!below_surface)
|
|
SetPosition(GetX(), GetY() + y);
|
|
else
|
|
SetPosition(GetX(), GetY() + y + dimension_y + 1);
|
|
}
|
|
// Check for construction site.
|
|
if (!below_surface && !CheckConstructionSite(structure, 0, half_y))
|
|
blocked = true;
|
|
// intersection-check with all other construction sites... bah
|
|
for (var other_site in FindObjects(Find_ID(ConstructionSite)))
|
|
{
|
|
if (!(other_site->GetLeftEdge() > GetX()+dimension_x/2 || other_site->GetRightEdge() < GetX()-dimension_x/2 || other_site->GetTopEdge() < GetY()+half_y || other_site->GetBottomEdge() > GetY()-half_y))
|
|
blocked = true;
|
|
}
|
|
|
|
if(!blocked)
|
|
{
|
|
if (!stick_to)
|
|
SetClrModulation(RGBa(50,255,50, 100), GFX_StructureOverlay);
|
|
else
|
|
SetClrModulation(RGBa(255,255,50, 200), GFX_StructureOverlay);
|
|
}
|
|
else
|
|
SetClrModulation(RGBa(255,50,50, 100), GFX_StructureOverlay);
|
|
}
|
|
|
|
// Positions the preview according to the mouse cursor, calls AdjustPreview afterwards
|
|
// x and y are refined mouse coordinates so always centered at the clonk
|
|
func Reposition(int x, int y)
|
|
{
|
|
x = BoundBy(x, -dimension_x/2, dimension_x/2);
|
|
y = BoundBy(y, -dimension_y/2, dimension_y/2);
|
|
// Try to combine the structure with other structures.
|
|
var found = false;
|
|
if (structure->~ConstructionCombineWith())
|
|
{
|
|
var stick_dir = structure->~ConstructionCombineDirection();
|
|
var find_rect = Find_InRect(AbsX(clonk->GetX() + x - dimension_x/2 - 10), AbsY(clonk->GetY() + y - dimension_y/2 - 10), dimension_x + 20, dimension_y + 20);
|
|
if ((stick_dir & CONSTRUCTION_STICK_Bottom))
|
|
find_rect = Find_AtPoint(AbsX(clonk->GetX() + x), AbsY(clonk->GetY() + y));
|
|
var other = FindObject(Find_Func(structure->ConstructionCombineWith(), this),
|
|
find_rect,
|
|
Find_OCF(OCF_Fullcon),
|
|
Find_Layer(clonk->GetObjectLayer()),
|
|
Find_Allied(clonk->GetOwner()),
|
|
Find_NoContainer());
|
|
if (other)
|
|
{
|
|
x = other->GetX();
|
|
y = other->GetY();
|
|
// Combine to different directions.
|
|
if ((stick_dir & CONSTRUCTION_STICK_Left) && other->GetX() >= GetX())
|
|
x = other->GetX() - other->GetObjWidth()/2 - dimension_x / 2;
|
|
if ((stick_dir & CONSTRUCTION_STICK_Right) && other->GetX() < GetX())
|
|
x = other->GetX() + other->GetObjWidth()/2 + dimension_x / 2;
|
|
if ((stick_dir & CONSTRUCTION_STICK_Bottom))
|
|
y = other->GetY() + other->GetObjHeight()/2 + dimension_y / 2;
|
|
stick_to = other;
|
|
found = true;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
x = clonk->GetX() + x;
|
|
y = clonk->GetY() + y;
|
|
}
|
|
|
|
if (!found && stick_to)
|
|
{
|
|
stick_to = nil;
|
|
SetGraphics(nil, nil, GFX_CombineIconOverlay);
|
|
}
|
|
else if (stick_to)
|
|
{
|
|
SetGraphics(nil, ConstructionPreviewer_IconCombine, GFX_CombineIconOverlay, GFXOV_MODE_Base);
|
|
var dir = 1;
|
|
if (stick_to->GetX() < GetX()) dir = -1;
|
|
if (structure->~CombineToBottom())
|
|
dir = 0;
|
|
SetObjDrawTransform(1000, 0, dimension_x/2 * 1000 * dir, 0, 1000, 0, GFX_CombineIconOverlay);
|
|
}
|
|
|
|
SetPosition(x, y);
|
|
AdjustPreview(structure->~IsBelowSurfaceConstruction());
|
|
}
|
|
|
|
// Flips the preview horizontally
|
|
func Flip()
|
|
{
|
|
// Flip not allowed?
|
|
if (structure->~NoConstructionFlip()) return;
|
|
|
|
if (direction == DIR_Left)
|
|
{
|
|
direction = DIR_Right;
|
|
SetObjDrawTransform(-1000,0,0, 0,1000,0, GFX_StructureOverlay);
|
|
} else {
|
|
direction = DIR_Left;
|
|
SetObjDrawTransform(1000,0,0, 0,1000,0, GFX_StructureOverlay);
|
|
}
|
|
}
|
|
|
|
// UI not saved.
|
|
func SaveScenarioObject() { return false; } |