gusucode.com > 三维模仿源码程序 > 三维模仿源码程序/MathRubik2/SetColors.m

    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);