Skip to content

Commit 5779716

Browse files
committed
[[ TileCache ]] Selection Layer
This patch ensures that all selection related decorations (i.e. size handles and edit-tool handlers) are drawn in the card's foreground layer, and any changes to their appearance causes that layer to be dirtied in the appropriate places. This fixes a number of rendering issues with selection handles both in accelerated rendering mode and outside of it.
1 parent 245c85c commit 5779716

File tree

15 files changed

+245
-304
lines changed

15 files changed

+245
-304
lines changed

engine/src/card.cpp

Lines changed: 33 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
5656
#include "vclip.h"
5757
#include "redraw.h"
5858
#include "widget.h"
59+
#include "graphics_util.h"
5960

6061
#include "globals.h"
6162
#include "mctheme.h"
@@ -665,8 +666,10 @@ Boolean MCCard::mfocus(int2 x, int2 y)
665666

666667
MCRedrawUnlockScreen();
667668

668-
// MW-2011-08-19: [[ Layers ]] Ensure the selection rect is updated.
669-
layer_selectedrectchanged(oldrect, selrect);
669+
/* The set of selected controls has changed so dirty the old
670+
* rect, and the new. */
671+
dirtyselection(oldrect);
672+
dirtyselection(selrect);
670673
}
671674
message_with_args(MCM_mouse_move, x, y);
672675
return true;
@@ -918,8 +921,10 @@ Boolean MCCard::mup(uint2 which, bool p_release)
918921
if (state & CS_SIZE)
919922
{
920923
state &= ~CS_SIZE;
921-
// MW-2011-08-18: // MW-2011-08-19: [[ Layers ]] Ensure the selection rect is updated.
922-
layer_dirtyrect(selrect);
924+
925+
/* The selection marquee has finished, so update the selection
926+
* layer. */
927+
dirtyselection(selrect);
923928

924929
// MM-2012-11-05: [[ Object selection started/ended message ]]
925930
if (m_selecting_objects)
@@ -3028,78 +3033,51 @@ void MCCard::drawbackground(MCContext *p_context, const MCRectangle &p_dirty)
30283033
p_context->fillrect(p_dirty);
30293034
}
30303035

3031-
// IM-2013-09-13: [[ RefactorGraphics ]] Factor out card selection rect drawing to separate method
3032-
void MCCard::drawselectionrect(MCContext *p_context)
3033-
{
3034-
drawmarquee(p_context, selrect);
3035-
}
3036-
3037-
void MCCard::drawselectedchildren(MCDC *dc)
3036+
/* The card's drawselection method first renders the selections of all children
3037+
* and then renders the marquee. */
3038+
void MCCard::drawselection(MCContext *p_context, const MCRectangle& p_dirty)
30383039
{
30393040
MCObjptr *tptr = objptrs;
30403041
if (tptr == nil)
30413042
return;
3043+
30423044
do
30433045
{
30443046
MCControl *t_control = tptr->getref();
3045-
if (t_control != nullptr)
3047+
if (t_control != nullptr &&
3048+
t_control->getopened() != 0 &&
3049+
(t_control->getflag(F_VISIBLE) || showinvisible()))
30463050
{
3047-
if (tptr -> getref() -> getstate(CS_SELECTED))
3048-
tptr->getref()->drawselected(dc);
3049-
3050-
if (tptr -> getrefasgroup() != nil)
3051-
tptr -> getrefasgroup() -> drawselectedchildren(dc);
3051+
t_control->drawselection(p_context, p_dirty);
30523052
}
30533053

30543054
tptr = tptr->next();
30553055
}
30563056
while (tptr != objptrs);
3057+
3058+
if (getstate(CS_SIZE))
3059+
{
3060+
drawmarquee(p_context, selrect);
3061+
}
30573062
}
30583063

30593064
void MCCard::dirtyselection(const MCRectangle &p_rect)
30603065
{
3061-
// redraw marquee rect
3062-
// selrect with 0 width or height will still draw a 1px line, so increase rect size to account for this.
3063-
layer_dirtyrect(MCU_reduce_rect(p_rect, -1));
3064-
3065-
// redraw selection handles
3066-
MCRectangle t_handles[8];
3067-
MCControl::sizerects(p_rect, t_handles);
3068-
3069-
for (uint32_t i = 0; i < 8; i++)
3070-
layer_dirtyrect(t_handles[i]);
3071-
}
3072-
3073-
bool MCCard::updatechildselectedrect(MCRectangle& x_rect)
3074-
{
3075-
bool t_updated;
3076-
t_updated = false;
3066+
MCRectangle t_rect = MCU_reduce_rect(p_rect, -(1 + MCsizewidth / 2));
30773067

3078-
MCObjptr *t_objptr = objptrs;
3079-
if (t_objptr == nil)
3080-
return t_updated;
3081-
do
3068+
MCTileCacheRef t_tilecache = getstack()->view_gettilecache();
3069+
if (t_tilecache != nullptr)
30823070
{
3083-
MCControl *t_control;
3084-
t_control = t_objptr -> getref();
3071+
MCGAffineTransform t_transform =
3072+
getstack()->getdevicetransform();
30853073

3086-
if (t_control -> getstate(CS_SELECTED))
3087-
{
3088-
x_rect = MCU_union_rect(t_control -> geteffectiverect(), x_rect);
3089-
t_updated = true;
3090-
}
3074+
MCRectangle32 t_device_rect =
3075+
MCRectangle32GetTransformedBounds(t_rect, t_transform);
30913076

3092-
if (t_control -> gettype() == CT_GROUP)
3093-
{
3094-
MCGroup *t_group = static_cast<MCGroup *>(t_control);
3095-
t_updated = t_updated | t_group -> updatechildselectedrect(x_rect);
3096-
}
3097-
3098-
t_objptr = t_objptr->next();
3077+
MCTileCacheUpdateScenery(t_tilecache, m_fg_layer_id, t_device_rect);
30993078
}
3100-
while (t_objptr != objptrs);
31013079

3102-
return t_updated;
3080+
layer_dirtyrect(t_rect);
31033081
}
31043082

31053083
void MCCard::draw(MCDC *dc, const MCRectangle& dirty, bool p_isolated)
@@ -3127,18 +3105,14 @@ void MCCard::draw(MCDC *dc, const MCRectangle& dirty, bool p_isolated)
31273105
}
31283106
while (tptr != objptrs);
31293107
}
3130-
3131-
// Draw the selection outline and handles on top of everything
3132-
drawselectedchildren(dc);
3133-
3108+
31343109
dc -> setopacity(255);
31353110
dc -> setfunction(GXcopy);
31363111

31373112
if (t_draw_cardborder)
31383113
drawcardborder(dc, dirty);
31393114

3140-
if (getstate(CS_SIZE))
3141-
drawselectionrect(dc);
3115+
drawselection(dc, dirty);
31423116
}
31433117

31443118
///////////////////////////////////////////////////////////////////////////////

engine/src/card.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,15 +216,14 @@ class MCCard : public MCObject, public MCMixinObjectHandle<MCCard>
216216

217217
// IM-2013-09-13: [[ RefactorGraphics ]] render the card background
218218
void drawbackground(MCContext *p_context, const MCRectangle &p_dirty);
219-
// IM-2013-09-13: [[ RefactorGraphics ]] render the card selection rect
220-
void drawselectionrect(MCContext *);
221-
void drawselectedchildren(MCDC *dc);
222-
219+
220+
/* The drawselection method renders the 'selection layer' - i.e. all the
221+
* selection decorations for all controls on the card. */
222+
void drawselection(MCContext *p_context, const MCRectangle& p_dirty);
223+
223224
// IM-2016-09-26: [[ Bug 17247 ]] request redraw of the area occupied by
224225
// selection marquee + handles
225226
void dirtyselection(const MCRectangle &p_rect);
226-
227-
bool updatechildselectedrect(MCRectangle& x_rect);
228227

229228
Exec_stat openbackgrounds(bool p_is_preopen, MCCard *p_other);
230229
Exec_stat closebackgrounds(MCCard *p_other);
@@ -240,8 +239,6 @@ class MCCard : public MCObject, public MCMixinObjectHandle<MCCard>
240239
void layer_removed(MCControl *control, MCObjptr *previous, MCObjptr *next);
241240
// MW-2011-08-19: [[ Layers ]] The viewport displayed in the stack has changed.
242241
void layer_setviewport(int32_t x, int32_t y, int32_t width, int32_t height);
243-
// MW-2011-09-23: [[ Layers ]] The selected rectangle has changed.
244-
void layer_selectedrectchanged(const MCRectangle& old_rect, const MCRectangle& new_rect);
245242

246243
// MW-2011-08-26: [[ TileCache ]] Render all layers into the stack's tilecache.
247244
void render(void);

engine/src/control.cpp

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -428,27 +428,13 @@ void MCControl::select()
428428
state |= CS_SELECTED;
429429
kunfocus();
430430

431-
// MW-2011-09-23: [[ Layers ]] Mark the layer attrs as having changed - the selection
432-
// setting can influence the layer type.
433-
m_layer_attr_changed = true;
434-
435-
// MW-2011-08-18: [[ Layers ]] Invalidate the whole object.
436-
layer_redrawall();
437-
438431
getcard()->dirtyselection(rect);
439432
}
440433

441434
void MCControl::deselect()
442435
{
443436
if (state & CS_SELECTED)
444437
{
445-
// MW-2011-09-23: [[ Layers ]] Mark the layer attrs as having changed - the selection
446-
// setting can influence the layer type.
447-
m_layer_attr_changed = true;
448-
449-
// MW-2011-08-18: [[ Layers ]] Invalidate the whole object.
450-
layer_redrawall();
451-
452438
getcard()->dirtyselection(rect);
453439

454440
state &= ~(CS_SELECTED | CS_MOVE | CS_SIZE | CS_CREATE);
@@ -869,10 +855,14 @@ void MCControl::sizerects(const MCRectangle &p_object_rect, MCRectangle r_rects[
869855
}
870856
}
871857

872-
void MCControl::drawselected(MCDC *dc)
858+
void MCControl::drawselection(MCDC *dc, const MCRectangle& p_dirty)
873859
{
874-
if (!opened || !(getflag(F_VISIBLE) || showinvisible()))
860+
MCAssert(getopened() != 0 && (getflag(F_VISIBLE) || showinvisible()));
861+
862+
if (!getselected())
863+
{
875864
return;
865+
}
876866

877867
if (MCdragging)
878868
return;

engine/src/edittool.cpp

Lines changed: 7 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ bool MCGradientEditTool::mfocus(int2 x, int2 y)
128128
return false;
129129
}
130130

131-
MCRectangle t_old_effectiverect;
132-
t_old_effectiverect = graphic -> geteffectiverect();
131+
/* Dirty the current edit tool draw rect in the selection layer. */
132+
graphic->getcard()->dirtyselection(drawrect());
133133

134134
switch (m_gradient_edit_point)
135135
{
@@ -191,8 +191,11 @@ bool MCGradientEditTool::mfocus(int2 x, int2 y)
191191
gradient->old_origin.x = MININT2;
192192
gradient->old_origin.y = MININT2;
193193

194-
// MW-2011-08-18: [[ Layers ]] Notify the graphic its effective rect has changed and invalidate all.
195-
graphic -> layer_effectiverectchangedandredrawall(t_old_effectiverect);
194+
/* Dirty the new edit tool draw rect in the selection layer. */
195+
graphic->getcard()->dirtyselection(drawrect());
196+
197+
/* Mark the graphic's content as needing redrawn. */
198+
graphic->layer_redrawall();
196199

197200
graphic->message_with_args(MCM_mouse_move, x, y);
198201

@@ -271,39 +274,6 @@ MCRectangle MCGradientEditTool::drawrect()
271274
return MCU_union_rect(drect, rects[2]);
272275
}
273276

274-
MCRectangle MCGradientEditTool::minrect()
275-
{
276-
int4 minx, miny, maxx, maxy;
277-
minx = MAXINT4; miny = MAXINT4;
278-
maxx = MININT4; maxy = MININT4;
279-
280-
MCRectangle rect = {MININT2,MININT2,0,0};
281-
282-
if (gradient != NULL)
283-
{
284-
minx = MCU_min(gradient->origin.x, gradient->primary.x);
285-
maxx = MCU_max(gradient->origin.x, gradient->primary.x);
286-
287-
minx = MCU_min(minx, gradient->secondary.x);
288-
maxx = MCU_max(maxx, gradient->secondary.x);
289-
290-
miny = MCU_min(gradient->origin.y, gradient->primary.y);
291-
maxy = MCU_max(gradient->origin.y, gradient->primary.y);
292-
293-
miny = MCU_min(miny, gradient->secondary.y);
294-
maxy = MCU_max(maxy, gradient->secondary.y);
295-
296-
if (minx <= maxx && miny <= maxy)
297-
{
298-
rect.x = minx;
299-
rect.y = miny;
300-
rect.width = maxx - minx ;
301-
rect.height = maxy - miny;
302-
}
303-
}
304-
return rect;
305-
}
306-
307277
MCPolygonEditTool::MCPolygonEditTool(MCGraphic *p_graphic) :
308278
graphic(p_graphic),
309279
m_polygon_edit_point(kInvalidEditPoint),
@@ -492,9 +462,3 @@ MCRectangle MCPolygonEditTool::drawrect()
492462
}
493463
return drect;
494464
}
495-
496-
MCRectangle MCPolygonEditTool::minrect()
497-
{
498-
MCRectangle rect = {MININT2,MININT2,0,0};
499-
return rect;
500-
}

engine/src/edittool.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ class MCEditTool
4040
virtual void drawhandles(MCDC *dc) = 0;
4141
virtual uint4 handle_under_point(int2 x, int2 y) = 0;
4242
virtual MCRectangle drawrect() = 0;
43-
virtual MCRectangle minrect() = 0;
4443
virtual MCEditMode type() = 0;
4544
};
4645

@@ -53,7 +52,6 @@ class MCGradientEditTool : public MCEditTool
5352
void drawhandles(MCDC *dc);
5453
uint4 handle_under_point(int2 x, int2 y);
5554
MCRectangle drawrect();
56-
MCRectangle minrect();
5755
MCEditMode type();
5856

5957
MCGradientEditTool(MCGraphic *p_graphic, MCGradientFill *p_gradient, MCEditMode p_mode);
@@ -76,7 +74,6 @@ class MCPolygonEditTool : public MCEditTool
7674
void drawhandles(MCDC *dc);
7775
uint4 handle_under_point(int2 x, int2 y);
7876
MCRectangle drawrect();
79-
MCRectangle minrect();
8077
MCEditMode type();
8178

8279
MCPolygonEditTool(MCGraphic *p_graphic);

0 commit comments

Comments
 (0)