/// <summary> /// Shift given shiftedBlock behind target, if possible /// </summary> /// <param name="shiftedBlock"></param> /// <param name="target"></param> /// <param name="view"></param> private bool shiftBehind(ExecutedBlock shiftedBlock, ExecutedBlock target, ExecutionView view) { //cumulative list of blocks that has to be shifted //It has reverse ordering of transformations that will be generated var shiftedBlocks = new List <ExecutedBlock>(); shiftedBlocks.Add(shiftedBlock); var borderInstances = new HashSet <Instance>(); borderInstances.UnionWith(view.AffectedInstances(shiftedBlock)); //find all colliding blocks, so we can move them with shifted block if possible var currentBlock = shiftedBlock; while (currentBlock != target) { currentBlock = view.NextBlock(currentBlock); if (!canCross(currentBlock, borderInstances, view)) { //this block cannot be crossed borderInstances.UnionWith(view.AffectedInstances(currentBlock)); shiftedBlocks.Add(currentBlock); } } //shifting is not possible, due to collisions between blocks if (!canCross(target, borderInstances, view)) { return(false); } shiftedBlocks.Reverse(); foreach (var block in shiftedBlocks) { view.ShiftBehind(block, target); } return(true); }