Skip to content

Commit 0b0d63a

Browse files
committed
[[ AccelRender ]] Implement adjacency calculations for adding / removing layers
1 parent 70f4680 commit 0b0d63a

File tree

3 files changed

+141
-36
lines changed

3 files changed

+141
-36
lines changed

engine/src/card.cpp

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,12 +1594,12 @@ void MCCard::relayercontrol(MCControl *p_source, MCControl *p_target)
15941594
t_target_ptr = nil;
15951595

15961596
// Get the previous / next ptrs.
1597-
MCObjptr *t_previous, *t_next;
1598-
t_previous = t_source_ptr -> prev() != objptrs ? t_source_ptr -> prev() : nil;
1599-
t_next = t_source_ptr -> next() != objptrs ? t_source_ptr -> next() : nil;
1597+
MCControl *t_previous, *t_next;
1598+
t_previous = MCControlPreviousByLayer(p_source);
1599+
t_next = MCControlNextByLayer(p_source);
16001600

16011601
// If the source control already precedes the target then we are done.
1602-
if (t_next == t_target_ptr)
1602+
if (t_next == p_target)
16031603
return;
16041604

16051605
// Otherwise, remove the layer.
@@ -1616,17 +1616,17 @@ void MCCard::relayercontrol(MCControl *p_source, MCControl *p_target)
16161616
}
16171617
else
16181618
t_source_ptr -> appendto(objptrs);
1619-
layer_added(p_source, t_source_ptr -> prev() != objptrs ? t_source_ptr -> prev() : nil, t_source_ptr -> next() != objptrs ? t_source_ptr -> next() : nil);
1619+
layer_added(p_source, MCControlPreviousByLayer(p_source), MCControlNextByLayer(p_source));
16201620
}
16211621

16221622
void MCCard::relayercontrol_remove(MCControl *p_control)
16231623
{
16241624
MCObjptr *t_control_ptr;
16251625
t_control_ptr = getobjptrforcontrol(p_control);
16261626

1627-
MCObjptr *t_previous, *t_next;
1628-
t_previous = t_control_ptr -> prev() != objptrs ? t_control_ptr -> prev() : nil;
1629-
t_next = t_control_ptr -> next() != objptrs ? t_control_ptr -> next() : nil;
1627+
MCControl *t_previous, *t_next;
1628+
t_previous = MCControlPreviousByLayer(p_control);
1629+
t_next = MCControlNextByLayer(p_control);
16301630

16311631
// Remove the control from the card's objptr list.
16321632
t_control_ptr -> remove(objptrs);
@@ -1668,7 +1668,7 @@ void MCCard::relayercontrol_insert(MCControl *p_control, MCControl *p_target)
16681668
}
16691669
else
16701670
t_control_ptr -> appendto(objptrs);
1671-
layer_added(p_control, t_control_ptr -> prev() != objptrs ? t_control_ptr -> prev() : nil, t_control_ptr -> next() != objptrs ? t_control_ptr -> next() : nil);
1671+
layer_added(p_control, MCControlPreviousByLayer(p_control), MCControlNextByLayer(p_control));
16721672
}
16731673

16741674
Exec_stat MCCard::relayer(MCControl *optr, uint2 newlayer)
@@ -1799,9 +1799,7 @@ Exec_stat MCCard::relayer(MCControl *optr, uint2 newlayer)
17991799
t_insert_iter->append(newptr);
18001800
}
18011801

1802-
layer_added(optr,
1803-
(newptr->prev() != objptrs->prev()) ? newptr->prev() : nil,
1804-
(newptr->next() != objptrs) ? newptr->next() : nil);
1802+
layer_added(optr, MCControlPreviousByLayer(optr), MCControlNextByLayer(optr));
18051803
}
18061804

18071805
if (oldparent == this)
@@ -2491,7 +2489,6 @@ Boolean MCCard::removecontrol(MCControl *cptr, Boolean needredraw, Boolean cf)
24912489
t_stack = getstack();
24922490

24932491
MCObjptr *optr = objptrs;
2494-
MCObjptr *t_previous_optr = nil;
24952492
do
24962493
{
24972494
if (optr->getref() == cptr)
@@ -2502,17 +2499,16 @@ Boolean MCCard::removecontrol(MCControl *cptr, Boolean needredraw, Boolean cf)
25022499
removedcontrol = optr;
25032500

25042501
// MW-2011-08-19: [[ Layers ]] Compute the next objptr, or nil if we are at the end.
2505-
MCObjptr *t_next_optr;
2506-
t_next_optr = optr -> next();
2507-
if (t_next_optr == objptrs)
2508-
t_next_optr = nil;
2502+
MCControl *t_previous, *t_next;
2503+
t_previous = MCControlPreviousByLayer(optr->getref());
2504+
t_next = MCControlNextByLayer(optr->getref());
25092505

25102506
// Remove the control from the card and close it.
25112507
optr->remove(objptrs);
25122508
delete optr;
25132509

25142510
// MW-2011-08-19: [[ Layers ]] Notify the stack that a layer has been removed.
2515-
layer_removed(cptr, t_previous_optr, t_next_optr);
2511+
layer_removed(cptr, t_previous, t_next);
25162512

25172513
if (opened)
25182514
{
@@ -2522,7 +2518,6 @@ Boolean MCCard::removecontrol(MCControl *cptr, Boolean needredraw, Boolean cf)
25222518

25232519
return True;
25242520
}
2525-
t_previous_optr = optr;
25262521
optr = optr->next();
25272522
}
25282523
while (optr != objptrs);
@@ -2571,7 +2566,7 @@ MCObjptr *MCCard::newcontrol(MCControl *cptr, Boolean needredraw)
25712566
newptr->appendto(objptrs);
25722567

25732568
// MW-2011-08-19: [[ Layers ]] Notify the stack that a layer may have ben inserted.
2574-
layer_added(cptr, objptrs != newptr ? newptr -> prev() : nil, nil);
2569+
layer_added(cptr, MCControlPreviousByLayer(cptr), MCControlNextByLayer(cptr));
25752570

25762571
if (opened)
25772572
cptr->open();

engine/src/card.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,9 @@ class MCCard : public MCObject, public MCMixinObjectHandle<MCCard>
234234
// MW-2011-08-19: [[ Layers ]] Dirty the given rect of the viewport.
235235
void layer_dirtyrect(const MCRectangle& dirty_rect);
236236
// MW-2011-08-19: [[ Layers ]] A layer has been added to the card.
237-
void layer_added(MCControl *control, MCObjptr *previous, MCObjptr *next);
237+
void layer_added(MCControl *control, MCControl *previous, MCControl *next);
238238
// MW-2011-08-19: [[ Layers ]] A layer has been removed from the card.
239-
void layer_removed(MCControl *control, MCObjptr *previous, MCObjptr *next);
239+
void layer_removed(MCControl *control, MCControl *previous, MCControl *next);
240240
// MW-2011-08-19: [[ Layers ]] The viewport displayed in the stack has changed.
241241
void layer_setviewport(int32_t x, int32_t y, int32_t width, int32_t height);
242242

@@ -354,4 +354,12 @@ class MCCard : public MCObject, public MCMixinObjectHandle<MCCard>
354354
virtual void SetTheme(MCExecContext& ctxt, intenum_t p_theme);
355355
};
356356

357+
////////////////////////////////////////////////////////////////////////////////
358+
359+
// navigate controls by layer
360+
MCControl *MCControlPreviousByLayer(MCControl *p_control);
361+
MCControl *MCControlNextByLayer(MCControl *p_control);
362+
363+
////////////////////////////////////////////////////////////////////////////////
364+
357365
#endif

engine/src/redraw.cpp

Lines changed: 116 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ void MCControl::layer_changeeffectiverect(const MCRectangle& p_old_effective_rec
753753

754754
////////////////////////////////////////////////////////////////////////////////
755755

756-
void MCCard::layer_added(MCControl *p_control, MCObjptr *p_previous, MCObjptr *p_next)
756+
void MCCard::layer_added(MCControl *p_control, MCControl *p_previous, MCControl *p_next)
757757
{
758758
MCTileCacheRef t_tilecache;
759759
t_tilecache = getstack() -> view_gettilecache();
@@ -781,18 +781,22 @@ void MCCard::layer_added(MCControl *p_control, MCObjptr *p_previous, MCObjptr *p
781781
if (p_previous == nil || p_next == nil)
782782
return;
783783

784+
// skip previous container layers
785+
while (p_previous != nil && p_previous->layer_iscontainer())
786+
p_previous = MCControlPreviousByLayer(p_previous);
787+
784788
// If the previous (layer below) objptr has no id, then there is nothing to do
785789
// also. This will only occur if only new layers have been added above,
786790
// or if no rendering has been done yet.
787791
uint32_t t_before_layer_id;
788-
t_before_layer_id = p_previous -> getref() -> layer_getid();
792+
t_before_layer_id = p_previous -> layer_getid();
789793
if (t_before_layer_id == 0)
790794
return;
791795

792796
// MW-2013-06-21: [[ Bug 10974 ]] If the previous layer is a sprite then this layer
793797
// will change the lower limit of the scenery layers above, thus there is
794798
// nothing to do.
795-
if (p_previous -> getref() -> layer_issprite())
799+
if (p_previous -> layer_issprite())
796800
return;
797801

798802
// Now insert the scenery.
@@ -806,11 +810,12 @@ void MCCard::layer_added(MCControl *p_control, MCObjptr *p_previous, MCObjptr *p
806810
// the layer to be treated 'as one' with that layer until a redraw is done.
807811
// This means that any subsequent updates to the rect of the new layer will
808812
// appropriately flush the tiles in the cache.
809-
p_control -> layer_setid(t_before_layer_id);
813+
if (!p_control->layer_iscontainer())
814+
p_control -> layer_setid(t_before_layer_id);
810815
}
811816
}
812817

813-
void MCCard::layer_removed(MCControl *p_control, MCObjptr *p_previous, MCObjptr *p_next)
818+
void MCCard::layer_removed(MCControl *p_control, MCControl *p_previous, MCControl *p_next)
814819
{
815820
MCTileCacheRef t_tilecache;
816821
t_tilecache = getstack() -> view_gettilecache();
@@ -852,6 +857,13 @@ void MCCard::layer_removed(MCControl *p_control, MCObjptr *p_previous, MCObjptr
852857
// don't try and reuse a dead scenery layer.
853858
p_control -> layer_resetattrs();
854859

860+
// skip previous container layers
861+
while (p_previous != nil && p_previous->layer_iscontainer())
862+
p_previous = MCControlPreviousByLayer(p_previous);
863+
864+
// skip next container layers
865+
while (p_next != nil && p_next->layer_iscontainer())
866+
p_next = MCControlNextByLayer(p_next);
855867
// If there is no previous or next control we have no tweaks to ids
856868
// to perform.
857869
if (p_previous == nil || p_next == nil)
@@ -862,7 +874,7 @@ void MCCard::layer_removed(MCControl *p_control, MCObjptr *p_previous, MCObjptr
862874
// layer has a different id than us, make sure all previous layers
863875
// with the same id match it.
864876
uint32_t t_before_layer_id;
865-
t_before_layer_id = p_previous -> getref() -> layer_getid();
877+
t_before_layer_id = p_previous -> layer_getid();
866878

867879
// The layer below us has the same id so there's nothing to do, we are
868880
// removing a 'new' layer before its been redrawn.
@@ -872,20 +884,19 @@ void MCCard::layer_removed(MCControl *p_control, MCObjptr *p_previous, MCObjptr
872884
// MW-2013-06-21: [[ Bug 10974 ]] If the layer below is a sprite, then removing
873885
// this layer will increase the lower limit of the scenery stack above
874886
// thus there is nothing to do.
875-
if (p_previous -> getref() -> layer_issprite())
887+
if (p_previous -> layer_issprite())
876888
return;
877889

878890
// The layer below us has a different id, so this is an existing layer
879891
// and thus we must ensure all layers above us now use the id of the
880892
// layer below.
881-
MCObjptr *t_objptr;
882-
t_objptr = p_next;
883-
while(t_objptr != p_previous &&
884-
!t_objptr->getref()->layer_issprite() &&
885-
t_objptr -> getref() -> layer_getid() == p_control -> layer_getid())
893+
while(p_next != nil &&
894+
!p_next->layer_issprite() &&
895+
p_next->layer_getid() == p_control->layer_getid())
886896
{
887-
t_objptr -> getref() -> layer_setid(t_before_layer_id);
888-
t_objptr = t_objptr -> next();
897+
if (!p_next->layer_iscontainer())
898+
p_next->layer_setid(t_before_layer_id);
899+
p_next = MCControlNextByLayer(p_next);
889900
}
890901
}
891902
}
@@ -1471,3 +1482,94 @@ void MCRedrawDoUpdateScreen(void)
14711482

14721483
////////////////////////////////////////////////////////////////////////////////
14731484

1485+
MCControl *MCControlTopChildByLayer(MCControl *p_control)
1486+
{
1487+
if (p_control->gettype() == CT_GROUP)
1488+
{
1489+
MCControl *t_controls = static_cast<MCGroup*>(p_control)->getcontrols();
1490+
1491+
if (t_controls != nil)
1492+
return MCControlTopChildByLayer(t_controls->prev());
1493+
}
1494+
1495+
return p_control;
1496+
}
1497+
1498+
MCControl *MCControlPreviousByLayer(MCControl *p_control)
1499+
{
1500+
MCObject *t_parent = nil;
1501+
t_parent = p_control->getparent();
1502+
1503+
if (t_parent == nil || t_parent->gettype() == CT_STACK)
1504+
return nil;
1505+
1506+
if (t_parent->gettype() == CT_GROUP)
1507+
{
1508+
MCControl *t_controls = static_cast<MCGroup*>(t_parent)->getcontrols();
1509+
1510+
if (t_controls == p_control)
1511+
return static_cast<MCControl*>(t_parent);
1512+
else
1513+
return MCControlTopChildByLayer(p_control->prev());
1514+
}
1515+
else if (t_parent->gettype() == CT_CARD)
1516+
{
1517+
MCObjptr *t_object = static_cast<MCCard*>(t_parent)->getobjptrforcontrol(p_control);
1518+
if (t_object == nil)
1519+
return nil; // object not on card
1520+
1521+
// check if first object on card
1522+
if (t_object == static_cast<MCCard*>(t_parent)->getobjptrs())
1523+
return nil;
1524+
1525+
return MCControlTopChildByLayer(static_cast<MCControl*>(t_object->prev()->getref()));
1526+
}
1527+
else
1528+
{
1529+
// control not in group or on card
1530+
return nil;
1531+
}
1532+
}
1533+
1534+
MCControl *MCControlNextByLayer(MCControl *p_control)
1535+
{
1536+
if (p_control->gettype() == CT_GROUP)
1537+
{
1538+
MCControl *t_controls = static_cast<MCGroup*>(p_control)->getcontrols();
1539+
if (t_controls != nil)
1540+
return t_controls;
1541+
}
1542+
1543+
MCControl *t_child = p_control;
1544+
MCObject *t_parent = t_child->getparent();
1545+
1546+
while (true)
1547+
{
1548+
if (t_parent == nil || t_parent->gettype() == CT_STACK)
1549+
return nil;
1550+
1551+
if (t_parent->gettype() == CT_GROUP)
1552+
{
1553+
MCControl *t_controls = static_cast<MCGroup*>(t_parent)->getcontrols();
1554+
if (t_controls->prev() != t_child)
1555+
return t_child->next();
1556+
}
1557+
else if (t_parent->gettype() == CT_CARD)
1558+
{
1559+
MCObjptr *t_obj = static_cast<MCCard*>(t_parent)->getobjptrforcontrol(t_child);
1560+
if (t_obj == nil)
1561+
return nil; // object no longer on card
1562+
1563+
MCObjptr *t_next = t_obj->next();
1564+
// check for wrap-around
1565+
if (t_next == static_cast<MCCard*>(t_parent)->getobjptrs())
1566+
return nil;
1567+
else
1568+
return static_cast<MCControl*>(t_next->getref());
1569+
}
1570+
1571+
t_child = static_cast<MCControl*>(t_parent);
1572+
t_parent = t_child->getparent();
1573+
}
1574+
}
1575+

0 commit comments

Comments
 (0)