Code covered by the BSD License

# Mathworks Rubik version 2

### Thomas Beneder (view profile)

04 Apr 2013 (Updated )

Display, tester and solver of the Rubik's game, including "full cubes".

... Cube.Color(:,iCube(end)); set(D.hAxRub,'UserData',Cube); D=PlotTheCube(D,Cube); elseif strcmp(selType,'alt')
```function SetColors(varargin)
%SetColors - UI for setting up a cube

% houd per kleur bij welke "soorten kubussen" gekleurd zijn:
%    hoek, rand, midden
%   dit kan eenvoudig getoond worden in de kleuren-palet-plot

if nargin==0|isnumeric(varargin{1})|isstruct(varargin{1})
hAxes=[];
Cube=[];
if nargin==0
try
hAxes=FindRubikAxes;
catch
Cube=[];
end
elseif isnumeric(varargin{1})
hAxes=varargin{1};
if nargin>1
if isstruct(varargin{2})
Cube=varargin{2};
end
end
end
if isempty(Cube)
if isempty(hAxes)
Cube=InitCube;
else
Cube=get(hAxes,'UserData');
end
Cube.Color(:,setdiff(1:27,[5 11 13 15 17 23]))=0;
end
Cube.history=[];
Cube.sol=[];
Cube.iSol=0;
[f,hAxRub,Cube]=Rubik(Cube,'bPlot',false);
axis off
p=get(f,'Position');
set(f,'Position',[p(1:2) p(3)+120 p(4)],'Name','Rubik Cube Set Up'	...
,'WindowButtonMotionFcn','1;'	...
,'KeyPressFcn','SetColors(''key'')'	...
,'Tag','RubikSettingUp'	...
);
hM=findobj(get(f,'Children'),'flat','Type','uimenu');
delete(get(hM,'Children'));
sOnOff={'off','on'};
uimenu(hM,'Label','Clear Cube'	...
,'Callback','SetColors(''clear'');');
uimenu(hM,'Label','Clear Cube all'	...
,'Callback','SetColors(''clearall'');');
uimenu(hM,'Label','Set mid cubes'	...
,'Callback','SetColors(''midcubes'');');
uimenu(hM,'Label','Full clean Cube',...
'Callback','SetColors(''clean'');');
uimenu(hM,'Label','Reset to default'	...
,'Callback','SetColors(''reset'')'	...
,'Separator','on');
uimenu(hM,'Label','Reset to original'	...
,'Callback','SetColors(''tooriginal'')');
uimenu(hM,'Label','Set Texture...'	...
,'Callback','SetColors(''texture'')'	...
,'Separator','on');
uimenu(hM,'Label','Copy Cube'	...
,'Callback','SetColors(''copy'')');
uimenu(hM,'Label','full Cube'	...
,'Checked',sOnOff{Cube.bFullCube+1}	...
,'Tag','MenuFullCube'	...
,'Callback','SetColors(''fullcube'')'	...
,'Separator','on');
uimenu(hM,'Label','Show whole textures in pallette'	...
,'Checked','off'	...
,'Tag','MenuWholeTexture'	...
,'Callback','SetColors(''wholetexture'')');
%hM1=uimenu(hM,'Label','Small Cubes'	...
%	,'Tag','MenuWholeTexture');
uimenu(hM,'Label','Toggle separate cubes'	...
,'Tag','MenuWholeTexture'	...
,'Callback','SetColors(''togglesepcubes'')');
hAxPal=axes('Units','pixel','Position',[p(3) 1 100 p(4)-2],'Tag','Palette');
hPal=zeros(1,6);
hold on
for i=1:6
C=repmat(reshape(Cube.ValColor(i+1,:),1,1,3),3,3);
hPal(i)=image(1:3,i*3.2+(1:3),C	...
,'ButtonDownFcn',sprintf('SetColors(''setColor'',%d);',i)	...
,'UserData',i);
end
hold off
axis off
axis ij
axis auto
axis equal
axLim=[-3.2 3.2];
hAxMids=axes('Units','pixel','Position',[0 0 140 140]	...
,'CameraPosition',[4.5 4 3.5]...
,'XLim',axLim,'YLim',axLim,'ZLim',axLim...
,'Tag','MidFaces');
hMid=zeros(1,6);
ccc=Cube.ValColor;
ccc(1,:)=[0.4 0.4 0.4];
for i=1:6
iC=Cube.RotLayerCube(i,5);
k=Cube.Order(i,:);
hMid(i)=patch(Cube.Nodes(k,1,iC),Cube.Nodes(k,2,iC),Cube.Nodes(k,3,iC)	...
,ccc(Cube.Color(i,iC)+1,:)	...
,'UserData',i	...
);
end
axis off
posCorner=zeros(3,8);
posEdge=zeros(2,12);
c=[6;4];
for i=1:4
posCorner(:,i)=[2;c];
posCorner(:,i+4)=[1;c([2 1])];
posEdge(:,i)=[2;c(1)];
posEdge(:,i+4)=[1;c(1)];
posEdge(:,i+8)=c;
c1=c(2);
c(2)=bitxor(c(1)-1,1)+1;
c(1)=c1;
end
%!!!?vreemde (?juiste?) omslachtige manier om orientatie te bepalen?
C1=InitCube;
orCorner=zeros(3,8);
for i=1:8
c=C1.Color(:,C1.iCorner(i));
c=c(c>0);
sc=sort(c);
for j=1:8
if all(sc==sort(posCorner(:,j)))
while c(1)~=posCorner(1,j)
c=c([2:3 1]);
end
if c(2)~=posCorner(2,j)
c=c([1 3 2]);
end
orCorner(:,i)=c;
break
end
end
end
D=struct('f',f	...
,'hAxes',hAxes,'hAxPal',hAxPal	...
,'Cube0',Cube	...
,'C1',C1	...
,'hAxRub',hAxRub,'hPal',hPal	...
,'hAxMids',hAxMids,'hMid',hMid	...
,'hCube',[]	...
,'orCorner',orCorner	...
,'nMid',0	...
,'ccc',ccc	...
,'colSel',0	...
,'posEdge',posEdge	...
,'availCorner',zeros(1,8),'availEdge',zeros(1,12)	...
,'bHoldColor',false	...
,'bShowWholeTexture',false	...
,'bCubeOK',true	...
);
UpdateTexture(D,Cube)
D=UpdatePalette(D,Cube);
return
end

D=get(gcf,'UserData');
switch lower(varargin{1})
case {'clear','clearall'}
Cube=get(D.hAxRub,'UserData');
if strcmp(lower(varargin{1}),'clear')
ClearCube(D,Cube)
else
ClearAllCube(D,Cube)
end
case 'clean'
CreateNewGame(0,D.hAxRub);
case 'midcubes'
Cube=get(D.hAxRub,'UserData');
i=setdiff(1:6,Cube.Color(Cube.iMidInd));
k=0;
for j=1:6
if Cube.Color(Cube.iMidInd(j))==0
k=k+1;
Cube.Color(Cube.iMidInd(j))=i(k);
end
end
set(D.hAxRub,'UserData',Cube)
D=UpdatePalette(D,Cube);
case 'reset'
Cube=get(D.hAxRub,'UserData');
Cube.Color(:)=0;
Cube.ValColor=[0 0 0;1 0 0;1 0 1;0 0 1;0 1 0;1 1 0;1 1 1];
D.ccc=Cube.ValColor;
set(D.hAxRub,'UserData',Cube)
D=UpdatePalette(D,Cube);
case 'tooriginal'
Cube=D.Cube0;
D.ccc=Cube.ValColor;
set(D.hAxRub,'UserData',Cube)
D=UpdatePalette(D,Cube);
case 'texture'
Cube=get(D.hAxRub,'UserData');
[fName,fPath]=uigetfile('*.mat','Give a file with texture data');
if ischar(fName)
texture=load(fullfile(fPath,fName));
if ~Cube.bFullCube
Cube.bFullCube=true;
Cube=SetFullCube(D,Cube);
end
else
if ~isempty(Cube.texture)
b=questdlg('Do you want to remove the texture?','SetColor question'	...
,'Yes','No','Yes');
if strcmp(b,'No')
return
end
end
texture=[];
end
D.colSel=0;
set(get(D.hAxRub,'Parent'),'UserData',D)
Cube.texture=texture;
UpdateTexture(D,Cube)
ClearCube(D,Cube)
case 'setcolor'
selType=get(D.f,'SelectionType');
Cube=get(D.hAxRub,'UserData');
if strcmp(selType,'alt')&isempty(Cube.texture)
C=uisetcolor(Cube.ValColor(varargin{2}+1,:),'Set the color of this face');
if length(C)==3
Cube.ValColor(varargin{2}+1,:)=C;
D.ccc=Cube.ValColor;
set(D.hAxRub,'UserData',Cube);
D=UpdatePalette(D,Cube);
end
elseif strcmp(selType,'open')	% double click
set(D.f,'Pointer','arrow')
if ~isempty(Cube.texture)&D.colSel
i=D.colSel;
Cube.texture.XX{i}=Cube.texture.XX{i}(end:-1:1,:)';
set(D.hAxRub,'UserData',Cube)
D=UpdatePalette(D,Cube);
end
D.colSel=0;
else	% not alt-click
if strcmp(selType,'alt')
% (only possible if texture)
% select the right part
X=get(gco,'XData');
Y=get(gco,'YData');
p=get(gca,'CurrentPoint');
rX=(p(1)-min(X))/(max(X)-min(X));
rY=(p(1,2)-min(Y))/(max(Y)-min(Y));
end
for i=1:6
set(D.hMid(i),'ButtonDownFcn'	...
,sprintf('SetColors(''setmid'',%d,%d)',i,varargin{2})	...
);
end
set(D.f,'Pointer','cross')
D.colSel=varargin{2};
D.bHoldColor=strcmp(selType,'extend');
end
set(D.f,'UserData',D);
case 'setcube'	% used in colour mode
Cube=get(D.hAxRub,'UserData');
iCube=get(gco,'UserData');
iN=[0	0	2	0	0	2	4	4	2	0	0	2	0	0	2	4	4	2	6	6	2	6	6	2	4	4	2
0	0	0	0	0	0	0	0	4	0	0	0	0	0	0	0	0	4	0	0	6	0	0	6	6	6	4
0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	6];
iL=iN(:,iCube);
iL(iL<1)=[];
if isempty(iL)
error('Kan niet')
elseif length(iL)==1
% found
else
Xsel=get(gca,'CurrentPoint');
DXsel=diff(Xsel);
A=[DXsel(1) -DXsel(2) 0;DXsel(1) 0 -DXsel(3);0 0 0];
B=A*Xsel(1,:)';
for i=iL'
iNodes=Cube.Order(i,[1 2 4]);
P=squeeze(Cube.Nodes(iNodes,:,iCube));
A(3,:)=cross(P(1,:)-P(3,:),P(2,:)-P(3,:));
B(3)=A(3,:)*P(1,:)';
XX=A\B;
if XX(1)>=min(P(:,1))-1e-4&XX(1)<=max(P(:,1))+1e-4	...
&XX(2)>=min(P(:,2))-1e-4&XX(2)<=max(P(:,2))+1e-4	...
&XX(3)>=min(P(:,3))-1e-4&XX(3)<=max(P(:,3))+1e-4
iL=i;
break;
end
end	% for all possible colored faces of the small cube
if length(iL)>1
warning('!!!!!!toch nog niet juist?')
iL=iL(1);
end
end
if any(iCube==Cube.iMid)
Cube.Color(:,iCube)=0;
end
Cube.Color(iL,iCube)=D.colSel;
set(D.hAxRub,'UserData',Cube)
D=UpdatePalette(D,Cube,iCube,iL);
if ~D.bHoldColor
D.colSel=0;
set(D.f,'Pointer','arrow')
end
set(D.f,'UserData',D);
case 'setface'	% used in texture mode
Cube=get(D.hAxRub,'UserData');
iCube=get(gco,'UserData');
Cube.Color(iCube(1),iCube(2))=D.colSel;
set(D.hAxRub,'UserData',Cube)
D=UpdatePalette(D,Cube,iCube,iCube(1));
if ~D.bHoldColor
D.colSel=0;
set(D.f,'Pointer','arrow')
end
set(D.f,'UserData',D);
case 'setmid'
if D.colSel==0
return
end
Cube=get(D.hAxRub,'UserData');
i=varargin{2};
Cube.Color(Cube.iMidInd(i))=D.colSel;
Cube.Color(Cube.iExtraFaces(i,:),Cube.iMid(i))=0;
set(D.hAxRub,'UserData',Cube)
if ~D.bHoldColor
D.colSel=0;
set(D.f,'Pointer','arrow')
end
D=UpdatePalette(D,Cube,Cube.iMidInd(varargin{2}),varargin{2});
set(D.f,'UserData',D)
case 'cubebutton'
iCube=get(gco,'UserData');
Cube=get(D.hAxRub,'UserData');
selType=get(D.f,'SelectionType');
if D.colSel
if isempty(Cube.texture)
SetColors('setCube')
else
SetColors('setFace')
end
elseif any(iCube(end)==Cube.iMid)	% rotate mid cube
ind=find(Cube.iMid==iCube(end));
Cube.Color(Cube.RotCubeFlat(ind,:),iCube(end)) = ...
Cube.Color(:,iCube(end));
set(D.hAxRub,'UserData',Cube);
D=PlotTheCube(D,Cube);
elseif strcmp(selType,'alt')	% clear colours of selected cube
iCube=get(gco,'UserData');
iCube=iCube(end);
Cube.Color(:,iCube)=0;
set(D.hAxRub,'UserData',Cube)
D=UpdatePalette(D,Cube);
set(D.f,'UserData',D);
else
RotateWithMouse(1);
end
case 'key'
if D.colSel
D.colSel=0;
set(D.f,'Pointer','arrow')
set(D.f,'UserData',D)
end
case 'rotated'
UpdateLittleCube(D)
case 'copy'
if ~D.bCubeOK
errordlg('Cube must not have any errors before I want to copy to a Rubik-figure!')
return
end
Cube=get(D.hAxRub,'UserData');
if ~CheckComplete(Cube)
errordlg('Cube has to be complete before I want to copy to a Rubik-figure!')
return
end
Cube.history=[];
Cube.sol=[];
if isempty(D.hAxes)|D.hAxes==0|~ishandle(D.hAxes)|~strcmp(get(D.hAxes,'Tag'),'RubikAxes')
fRub=Rubik(Cube);
D.hAxes=FindRubikAxes;
set(D.f,'UserData',D);
else
set(D.hAxes,'UserData',Cube)
PlotCube(D.hAxes,Cube)
ShowTitle(D.hAxes,Cube)
end
case 'fullcube'
Cube=get(D.hAxRub,'UserData');
Cube.bFullCube=~Cube.bFullCube;
set(D.hAxRub,'UserData',Cube);
Cube=SetFullCube(D,Cube);
PlotCube(D.hAxRub,Cube)
set(D.hAxRub,'UserData',Cube);
case 'wholetexture'
ToggleWholeTexture(D)
case 'togglesepcubes'
Cube=get(D.hAxRub,'UserData');
Cube.Nodes=InitCube('toggleoffset',Cube);
set(D.hAxRub,'UserData',Cube);
PlotCube(D.hAxRub,Cube)
otherwise
warning(sprintf('Unknown use of SetColors (%s)',varargin{1}))
end

function D=UpdatePalette(D,Cube,iCube,iL)	%!!!!!!iCube,iL nog niet gebruikt
% bedoeld voor snellere (minder) bepalingen
hAxPal=D.hAxPal;
Cmid=Cube.Color(Cube.iMidInd);
nMid=sum(Cmid>0);
iImpossible=sum(Cmid>0)>length(unique(Cmid(Cmid>0)));
bTexture=~isempty(Cube.texture);
if iImpossible
if D.nMid>=0
D.nMid=-1;
end
else
if nMid==5
i=find(Cmid==0);
Cube.Color(Cube.iMidInd(i))=setdiff(1:6,Cmid);
nMid=6;
end
if nMid~=D.nMid
D.nMid=nMid;
if nMid==6
% Test of re-order of colors is necessary
bReorder=false;
C=Cube.Color;
CO=C(Cube.iMidInd);
CO2=floor((CO-1)/2);
if any(CO2(1:2:6)~=CO2(2:2:6))
bReorder=true;
else
cc=diag(Cube.Color(1:2:5,Cube.RotLayerCube(1:2:5,5)));
cnr=floor((cc-1)/2);
csign=bitand(cc-1,1);
s=rem(sum(csign),2);
if mod(cnr(2)-cnr(1),3)>1
s=1-s;
end
if s
bReorder=true;
end
end
if bReorder
% change order of colors (in place of other recalculations)
%  match (for current cube orientation) colors with face
%  positions
for i=1:6
Cube.Color(C==CO(i))=i;
end
Cube.ValColor(2:end,:)=Cube.ValColor(CO+1,:);
D.ccc(2:end,:)=Cube.ValColor(2:end,:);
if bTexture
Cube.texture.XX=Cube.texture.XX(CO);
end
end	% reorder
if Cube.bFullCube
for i=1:6
iCube=Cube.iMid(i);
if Cube.Color(Cube.iExtraFaces(i,1),Cube.iMid(i))==0
k=Cube.iExtraFaces(i,:);
Cube.Color(k,Cube.iMid(i))=Cube.Color(Cube.iMidInd(k));
end
end
end	% full cube - fill mid cubes
end	% nMid==6
end	% nMid~=previous nMid
if nMid==6
Cnrs=zeros(8,2);
Ccs=zeros(6,3);
Enrs=zeros(6,6);
% Check Corners
for i=1:8	% corners
c=Cube.Color(D.orCorner(:,i),Cube.iCorner(i));
cc=c(c>0);
nc=length(cc);
cnr=floor((cc-1)/2);
csign=bitand(cc-1,1);
Cnr=sum(csign.*2.^cnr)+1;
Cnrs(Cnr,2)=nc;
for j=cc'
Ccs(j)=Ccs(j)+1;
end
if nc>0&length(unique(cnr))~=nc
iImpossible=10;
elseif nc==3
s=rem(sum(csign),2);
if mod(cnr(2)-cnr(1),3)>1
s=1-s;
end
if s
iImpossible=20;
end
elseif nc==2
j=setdiff(0:2,cnr);
nxt=2*j+rem(csign(1)+csign(2)+(c(2)==0)+(mod(cnr(2)-cnr(1),3)>1),2)+1;
Cube.Color(D.orCorner(c==0,i),Cube.iCorner(i))=nxt;
Ccs(nxt)=Ccs(nxt)+1;
c=Cube.Color(D.orCorner(:,i),Cube.iCorner(i));
cc=c(c>0);
nc=length(cc);
cnr=floor((cc-1)/2);
csign=bitand(cc-1,1);
Cnr=sum(csign.*2.^cnr)+1;
Cnrs(Cnr,2)=nc;
elseif nc==1
Ccs(cc,2)=Ccs(cc,2)+1;
Ccs(cc,3)=i;
end
if nc==3&~iImpossible
if Cnrs(Cnr)
iImpossible=30;
else
Cnrs(Cnr)=1;
end
end
end	% for i (corners)
if ~iImpossible
% Check edges
for i=1:12
c=Cube.Color(:,Cube.iEdge(i));
cc=c(c>0);
nc=length(cc);
if nc==1
Enrs(cc,cc)=i;
elseif nc==2
fcc=floor((cc-1)/2);
if fcc(1)==fcc(2)
iImpossible=11;
elseif Enrs(cc(1),cc(2))
iImpossible=31;
else
Enrs(cc(1),cc(2))=1;
Enrs(cc(2),cc(1))=1;
end
end
end
end
if ~iImpossible
for i=1:6	% colors
% Auto-fill corners
if Ccs(i)==4&Ccs(i,2)==1
iCorner=Ccs(i,3);
iCube=Cube.iCorner(iCorner);
k=floor((i-1)/2);
cnr=setdiff(0:2,k);
cnr=cnr([1 1 1 1],:);
CSlist=[0 0;0 1;1 0;1 1];
bi=rem(i-1,2);
C=sum(CSlist.*2.^cnr,2)+bi*2^k+1;
if sum(Cnrs(C))~=3
warning('!!!!!!!het loopt hier fout!!!!')
end
j=find(Cnrs(C)==0);
c=cnr(1,:)*2+CSlist(j,:)+1;
csign=rem(sum(CSlist(j,:))+bi,2);
j=D.orCorner(:,iCorner);
bEmpty=Cube.Color(j,iCube)==0;
Cube.Color(j(bEmpty),iCube)=c';
cnr=floor((Cube.Color(j,iCube)-1)/2);
if csign~=(mod(cnr(2)-cnr(1),3)>1)
Cube.Color(j(bEmpty),iCube)=c([2 1])';
end
end
% Auto-fill corners
e=setdiff(1:6,[i bitxor(i-1,1)+1]);
if Enrs(i,i)>0&sum(Enrs(i,e))==3
c=e(Enrs(i,e)==0);
iCube=Cube.iEdge(Enrs(i,i));
j=find(D.C1.Color(:,iCube)&Cube.Color(:,iCube)==0);
Cube.Color(j,iCube)=c;
end
end
end
else	% not all mid-faces
D.availCorner(:)=0;
D.availEdge(:)=0;
end
end
Left0=repmat([4,4,1],6,1);
Left=Left0;
TP=[1 2 1 2 3 2 1 2 1];
for i=1:6
for j=1:9
c=Cube.Color(i,Cube.RotLayerCube(i,j));
if c
Left(c,TP(j))=Left(c,TP(j))-1;
end
end
end
if any(Left(:)<0)
iImpossible=40;
end
if iImpossible
warning(sprintf('!!onmogelijke plaatsing!!! (%d)',iImpossible))
end
D.bCubeOK=iImpossible==0;
[D,faces]=PlotTheCube(D,Cube);
set(D.hAxRub,'UserData',Cube)
set(D.f,'UserData',D)
CCs={[3 3;3 1;1 3;1 1],[3 2;2 3;2 1;1 2],[2 2]};
Dleft=Left0-Left;
if bTexture
[sY,sX]=size(Cube.texture.XX{1});
iY=1:floor(sY/3);
iX=1:floor(sX/3);
end
for i=1:6
if bTexture
C=Cube.texture.XX{i};
else
C=repmat(reshape(Cube.ValColor(i+1,:),1,1,3),3,3);
end
if isempty(faces)
for j=1:3
for k=1:min(Dleft(i,j),Left0(i,j))
if bTexture
if ~D.bShowWholeTexture
C(round((CCs{j}(k,1)-1)*sY/3)+iY,round((CCs{j}(k,2)-1)*sX/3)+iX)=1;
end
else
C(CCs{j}(k,1),CCs{j}(k,2),:)=0.4;
end
end
end
else	% data for used small surfaces came from PlotCube
% this data is giving the right positions
for j=1:3
for k=1:3
if faces(j,k,i)
if bTexture
if ~D.bShowWholeTexture
C(round((j-1)*sY/3)+iY,round((k-1)*sX/3)+iX)=1;
end
else	% this is currently not possible
C(j,k,:)=0.4;
end
end
end
end
end
set(D.hPal(i),'CData',C)
end
UpdateLittleCube(D)

function ClearCube(D,Cube)
i=setdiff(1:27,[5 11 13 15 17 23]);
Cube.Color(:,i)=0;
set(D.hAxRub,'UserData',Cube)
D=UpdatePalette(D,Cube);

function ClearAllCube(D,Cube)
i=1:27;
Cube.Color(:,i)=0;
set(D.hAxRub,'UserData',Cube)
D=UpdatePalette(D,Cube);

function UpdateLittleCube(D)
Cube=get(D.hAxRub,'UserData');
if isempty(Cube.texture)
for i=1:6
set(D.hMid(i),'FaceColor',D.ccc(Cube.Color(Cube.iMidInd(i))+1,:))
end
else
C=D.ccc(1:2,:);
C(2,:)=[1 1 1];
for i=1:6
set(D.hMid(i),'FaceColor',C(min(Cube.Color(Cube.iMidInd(i)),1)+1,:))
end
end

function UpdateTexture(D,Cube)
if isempty(Cube.texture)
X=3;
Y=3;
else
[Y,X]=size(Cube.texture.XX{1});
colormap(Cube.texture.map)
end
dx=3/X;
x=dx/2+(0:X-1)*dx;
dy=3/Y;
y=dy/2+(0:Y-1)*dy;
for i=1:6
set(D.hPal(i)	...
,'XData',x,'YData',y+3.2*i	...
)
end

function [D,faces]=PlotTheCube(D,Cube)
[bNew,faces]=PlotCube(D.hAxRub,Cube,0,1);
if bNew
hL=findobj(D.hAxRub,'Tag','PCdummyLine');
DhL=get(hL,'UserData');
hCube=DhL.hCube;
D.hCube=hCube;
set(D.f,'UserData',D)
set(D.hCube,'ButtonDownFcn','SetColors cubebutton')
if isempty(Cube.texture)
set(D.hCube,'EdgeColor',[0.8 0.8 0.8])
end
set(D.f,'UserData',D)
end
if ~D.bCubeOK
set(get(D.hAxRub,'Title'),'String','Impossible cube!');
end

function Cube=SetFullCube(D,Cube)
hM=findobj(D.f,'Tag','MenuFullCube');
sOnOff={'off','on'};
set(hM,'Checked',sOnOff{Cube.bFullCube+1})
if Cube.bFullCube
Cube=MakeFullCube(Cube);
end

function ToggleWholeTexture(D)
D.bShowWholeTexture=~D.bShowWholeTexture;
hM=findobj(D.f,'Tag','MenuWholeTexture');
sOnOff={'off','on'};
set(hM,'Checked',sOnOff{D.bShowWholeTexture+1})
D=UpdatePalette(D,get(D.hAxRub,'UserData'));
set(D.f,'UserData',D)

function bComplete=CheckComplete(Cube)
% Check if all required faces are filled
NFilled=sum(Cube.Color>0);
nFilled=sum(NFilled);
% if full cube, easy check by the total number of filled faces.
bComplete=all(NFilled(Cube.iCorner)>=3)	...
&all(NFilled(Cube.iEdge)>=2)	...
&all(NFilled(Cube.iMid)>=1)	...
&(~Cube.bFullCube|nFilled>=78);
```

Contact us