From 3264ac439095b9bdde0375d8a9f9f4445babf839 Mon Sep 17 00:00:00 2001
From: Perttu Ahola <celeron55@gmail.com>
Date: Thu, 17 Feb 2011 19:07:14 +0200
Subject: [PATCH] Better texture handling. Textures are not added to atlas if
 they are big, and atlas is not further made after it is full.

---
 data/mineral_coal.png | Bin 1620 -> 952 bytes
 data/mineral_iron.png | Bin 1616 -> 1614 bytes
 src/main.cpp          |   2 +-
 src/tile.cpp          | 191 +++++++++++++++++++++++++++++++++++-------
 4 files changed, 160 insertions(+), 33 deletions(-)

diff --git a/data/mineral_coal.png b/data/mineral_coal.png
index 58a4d2b7959a849ae1e347346fd141ac5ae44b48..3ff9692fb483347662c6b1aa37ff7214d1bd125d 100644
GIT binary patch
delta 146
zcmcb@vx9wuK65=ov8Rh;h{fr%lMML|DDW`PHGThK&j0<*Gs{za)m0W`u3oiem3d3j
ziJJ$qCh|=BICEtT?<y@XO(upkv3Gn7E4H3WxUm0%-v8x2uDcHDgvy??ZNIxN%}m0y
zVZG<3_vbYy^ej$!!V_`qz}@S|{_OB5+RlFZ_AbWQKFjVo%+Ep?7`PZ1JYD@<);T3K
F0RTPuLnr_M

delta 819
zcmdnNeuZa)K65=Yzo(01h{fsLN%#GuOC^rk-!EEV`(@6hOY`T1NpyE?b-AHZu-VnP
zlsP%ACtOYM=G>cm!>bZ|>f0|`$W|>46!N|Du%P*;_Qutbjk#;LXiwRAYu>bZ-@aTZ
z-cz8L@GWMq`1{W``F52@qu=j2du(lKQlrAY0D<*7%GD`cM|Zyot6zQNklKrn7qy!&
zW^IaImpF^9x3+nM)Pm#UAB=upG1-;+==E#$c)gE@KlR^O)cvUNa(8!c%(T01%`rQV
ze2JK3E&V!UqQ*Nr$&+O)OW)eu+ZR_-%e{KxVprxR^E?9Y-Apb0x#_T@ufn3JIbLt&
zgxx23Y*Gp~e>H_Gw9TaV+daAF`sPHdX@_53N<IGkv+O7Ry3cEw4eagpjb6r22<dma
zzG;rnz7z33l^C9%JDYSv@8hF8l8NQFUhvB9z3NuF`{VDwEur?apDI0E?5T42Wzpkb
z>t%9wReTg`D1P*WGqFr&&tJw>YmHVtTAViH&&*gwu}&dw_6f(@+%3xLd`hfj-L?eQ
z@B3HO*z`zUAmnEL`-^XH#r*u)#$52+(Xr-FVc@-ci>~D;Zq520n0#0#=GPN}HOIt6
z<j(wm9uT$v@B4S>?mO-IbSpB*e_6)1=$@=XyMHAQ11{WIoz9xp{&udB-t_KEcYTwb
zIoGXQXR&g*ddrT2hrY9xJ#-PV&pzrKm=_{3Npw$rmzR>@a(_961zIWBFa2OUbR#z4
z&)*qu`Qpm$gKP?0`tANa*zd%i@N8${#j>vt_}c`hxmx{|Zjuw*A5~Lv_sK@hZ)>*+
zyx;p@&$euO+eM}M=Z(J~%A7WBy@14}g59<?A8$VA_hpZ~^18I|ydU?<b+2#Sh|rz9
z_@v17{Ch`=SPs`O6!^JTX?a|o=aWyfkA#?iUmZHn_NPtuO`VxO#~jxyp4<P?>UJ-e
zW2oZpve|BDE&lB4zwpv{xl57F%bM?hCrwziQKR{wfZuurp}L-T`;^zk?*4T`pkJr+
z;01wL>1kngLdwdEJ+>FI7X9R1wtQY<TH3Vx|2>3x*pEKBQuyVR?Jn&;?xXM1mj}6B
n7AoOkUY#k_>+<mz+Yk0Y4zG~N>jI7p3=9mOu6{1-oD!M<leVL6

diff --git a/data/mineral_iron.png b/data/mineral_iron.png
index 9698aa0060e42df0d33f8e8e6994b377aa1d4988..51b15d95da3315794e1bd43d8a47b0de6f1609a3 100644
GIT binary patch
delta 812
zcmcb>bB<?&0dqa4r;B5V#p%*XXS0)2MUK_yR~3J*ygd8%GSA5q{Mt)y-MZ-LIA_w)
zjxGz1T`vyty9J7*d|UTrf5GwxUV-LKJ3_52{M4ISH~P&j^T}Bz|8vH(*J_!0lV(5L
zr>7L^B5yHgvqgLR=f{HY>whpFWq19z_QMvxtv8Pd@&(@$$dixQTd#Mut5fXC`EOI+
z?zaDYBzg6evs!_^>i<rM3n_TJt&kHq$Fl$LzN0Po{V!(~8}2)D?{9qP@<}`H#)-Id
zbv<Qbyz09;^b!BxNiTSI*;vhgvZ8?HfcCw1A@)rldpe|~?p8GIsyuVF__W5p1^wHu
zE~~hZVkWn|zNjhDWkdU<tH;`W>X(cE=;>joIBYTP=O4D`jdxCk7M8zOKeBcE{S*_K
zQ&)dIyBUA>^!j8=y^HI@4QHz}%(!bc>v;3J*DfY=|DIB0KH8sjQc!MX*P4kB&pbUR
z{zgjDW);JM_o103tWgFnnY=gd?exu2^U@J=i}W}v7!sOuJ5A5-{PFuWntW?S64!gy
zPch70ouACYqc^o~3PXH$W}xPDgWa}M=0!SpFYU;w)6;zr$;i_1FP?SDW$woZCBAR1
z@e^w5FXB~<i>vOOx>R)6U%Ag8S;XbmoUVWN@Y<Q+rbgeNiLBF4yMD}=e<Np-<N1R{
zegfCm?{_axI5~5{xpxouttfeQ=2sI-lhnx+rmOYlo)O%eHt%-LFlsVxTJSFY!gkJz
zKN_7+ES<L7u_~|%nZI!pcfD`gXea8((_V4Sexj|ia@AiohO1G+x8I$*oEWd6yxjly
zr`3y+ziNnZ?fG!$b4lL61Czh{o_u(p=aP(fLyevLwG$knyd9jOj+xt|EG&4cna}C3
zFL-{>wk;^3-u`c&#uPqDuGW0+-$zXNx28?j4!`Gm_vS%6)+n_{YqQq}zPnO+@t$?_
zbkk!ef7`c~@}KTL{b~36d=6Eq?j#@I-~xS4OQ9Y=Rg<Xyl{;?TkeF@qV4I~taq;IJ
zMb+$U?(cD2e(%vl?(Q4k8lu*^C`l^6D1P`^%O&Zu#k*jx{`D%Izq`YamVJ_3=>L<`
c$M2JROR>9ngomst0|Nttr>mdKI;Vst0DlUKr~m)}

delta 814
zcmX@dbAe}r0dqaKr;B5V#p%`w_p_r*8IIcDf1>6)t9tXDW#*pwyUKcF-NQ>$%hvKs
z2dlq2!2VKh*@NbP>`lyxP5ySj^f~N!j<z>0Sn%M@ov7{{zp(lV>v~UKGC7@lS!eIw
zyJ!1%-&wD(G@Hk!AnyG0Im&u96%)69wNCk>^6{X`#*8T$DyQ61>nB%j?$ocDG|^(A
z#*Ve@SJuW_$%;Q;*uC&2%j2q^WcTz9d-*;V*sHES#ecp2h`8+)4|zqVHKL!d$hI#E
zO?~!3rGD+*gFZ`Na=QoCXs)>Cb>xs@&TqMS$;rz~m#Hn=u<g~H6}l&Gay(!b)M)aU
z9VxZ@woPq@km@S8o5kN(<e5m;8~NV){hNnJqQv%O=UG-uySf?2Lw@)@Yxufy^P}%m
zr8S~lmOiii<hqpUwkX4_ot8273ZMM<YW;h&WuvV0?yGLEUn?6HNjZC8*rFw|(^Dk;
zTgAe{$?l%5^X=W)cTTm`w2Jjy6TkfCrVCdrcIUO*e>$BKlxft~_v69h?iCLW?&j4`
z4=nCkzyDVgulScGZIYZ9-~OCaQa8DO-3}QE@q6!Tr`7LjymafX<LRD+J9|`OAM`LJ
zIsBGq{{Q!3Ok%81d#Zrf&a8!5p0C{F#go&fb?)Zwzc?+Z_|U78mAR2DOpL2$ryAW1
zmRYao#c<SzcVp!3DVnASr!I9ZJb6>tIdJNXRrQ88b5!5_e8DahvDIi+nt`ER>#P^c
z=hQfVc&n~)^P%&R>2|CMEGmi-zVd=^9VWP3a;T8g*50qcG3j*u=ltE-uS^;Os_JI%
zeSTl0@Aje)t&g`(uYVA;zs)Ws>HT(#ir3zjr-k=v+<9iCaBu$yIXk<!)y-Bj9_`EB
z9DYCX+0Ar~`n#(iaJD9`^l^Kgy!_^qFDs4LJo`MSKmYW3ub__ddv)EjE-S2D`6Qfs
zPxg*U|1V~}Q#Gti3974qx+>t(OcUmljwv1!jQBSF3+URs#@_JB<9O+$go2JW{NdBZ
zkG^;zkyKYVFDbKk=F8_Z=FWY5?X756dAH1LyS}?OmZ>wZ=wyjj<K@0Av+VV*3Vth=
g#g2SOc>l3oUEtE%agsNIfq{X+)78&qol`;+0QY^5NB{r;

diff --git a/src/main.cpp b/src/main.cpp
index 88a258dce..b0fe59320 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1852,7 +1852,7 @@ int main(int argc, char *argv[])
 	// Object infos are shown in this
 	gui::IGUIStaticText *guitext_info = guienv->addStaticText(
 			L"",
-			core::rect<s32>(100, 70, 100+400, 70+(text_height+5)),
+			core::rect<s32>(0,0,400,text_height+5) + v2s32(100,200),
 			false, false);
 	
 	// Chat text
diff --git a/src/tile.cpp b/src/tile.cpp
index 24cd9c014..237491aa8 100644
--- a/src/tile.cpp
+++ b/src/tile.cpp
@@ -22,6 +22,65 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "main.h" // for g_settings
 #include "filesys.h"
 
+/*
+	Replaces the filename extension.
+	eg:
+		std::string image = "a/image.png"
+		replace_ext(image, "jpg")
+		-> image = "a/image.jpg"
+	Returns true on success.
+*/
+inline bool replace_ext(std::string &path, const char *ext)
+{
+	// Find place of last dot, fail if \ or / found.
+	s32 last_dot_i = -1;
+	for(s32 i=path.size()-1; i>=0; i--)
+	{
+		if(path[i] == '.')
+		{
+			last_dot_i = i;
+			break;
+		}
+		
+		if(path[i] == '\\' || path[i] == '/')
+			break;
+	}
+	// If not found, return an empty string
+	if(last_dot_i == -1)
+		return false;
+	// Else make the new path
+	path = path.substr(0, last_dot_i+1) + ext;
+	return true;
+}
+
+/*
+	Find out the full path of an image by trying different filename
+	extensions.
+
+	If failed, return "".
+*/
+inline std::string getImagePath(std::string path)
+{
+	// A NULL-ended list of possible image extensions
+	const char *extensions[] = {
+		"png", "jpg", "bmp", "tga", "bmp",
+		"pcx", "ppm", "psd", "wal", "rgb",
+		NULL
+	};
+
+	const char **ext = extensions;
+	do{
+		bool r = replace_ext(path, *ext);
+		if(r == false)
+			return "";
+		if(fs::PathExists(path))
+			return path;
+	}
+	while((++ext) != NULL);
+	
+	return "";
+}
+
 /*
 	Gets the path to a texture by first checking if the texture exists
 	in texture_path and if not, using the data path.
@@ -32,11 +91,16 @@ inline std::string getTexturePath(std::string filename)
 	if(texture_path != "")
 	{
 		std::string fullpath = texture_path + '/' + filename;
-		if(fs::PathExists(fullpath))
+		// Check all filename extensions
+		fullpath = getImagePath(fullpath);
+		// If found, return it
+		if(fullpath != "")
 			return fullpath;
 	}
-	
-	return porting::getDataPath(filename.c_str());
+	std::string fullpath = porting::getDataPath(filename.c_str());
+	// Check all filename extensions
+	fullpath = getImagePath(fullpath);
+	return fullpath;
 }
 
 TextureSource::TextureSource(IrrlichtDevice *device):
@@ -454,6 +518,25 @@ void TextureSource::buildMainAtlas()
 		}
 
 		core::dimension2d<u32> dim = img2->getDimension();
+
+		// Don't add to atlas if image is large
+		core::dimension2d<u32> max_size_in_atlas(32,32);
+		if(dim.Width > max_size_in_atlas.Width
+		|| dim.Height > max_size_in_atlas.Height)
+		{
+			dstream<<"INFO: TextureSource::buildMainAtlas(): Not adding "
+					<<"\""<<name<<"\" because image is large"<<std::endl;
+			continue;
+		}
+
+		// Stop making atlas if atlas is full
+		if(pos_in_atlas.Y + dim.Height > atlas_dim.Height)
+		{
+			dstream<<"WARNING: TextureSource::buildMainAtlas(): "
+					<<"Atlas is full, not adding more textures."
+					<<std::endl;
+			break;
+		}
 		
 		// Tile it a few times in the X direction
 		u16 xwise_tiling = 16;
@@ -720,39 +803,83 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
 						<<", cancelling."<<std::endl;
 				return false;
 			}
-
+			
+			// Crack image number
 			u16 progression = stoi(part_of_name.substr(6));
+
 			// Size of the base image
 			core::dimension2d<u32> dim_base = baseimg->getDimension();
-			// Crack will be drawn at this size
-			u32 cracksize = 16;
-			// Size of the crack image
-			core::dimension2d<u32> dim_crack(cracksize,cracksize);
-			// Position to copy the crack from in the crack image
-			core::position2d<s32> pos_other(0, 16 * progression);
-
-			video::IImage *crackimage = driver->createImageFromFile(
+			
+			/*
+				Load crack image.
+
+				It is an image with a number of cracking stages
+				horizontally tiled.
+			*/
+			video::IImage *img_crack = driver->createImageFromFile(
 					getTexturePath("crack.png").c_str());
 		
-			if(crackimage)
+			if(img_crack)
 			{
-				/*crackimage->copyToWithAlpha(baseimg, v2s32(0,0),
-						core::rect<s32>(pos_other, dim_base),
-						video::SColor(255,255,255,255),
-						NULL);*/
-
-				for(u32 y0=0; y0<dim_base.Height/dim_crack.Height; y0++)
-				for(u32 x0=0; x0<dim_base.Width/dim_crack.Width; x0++)
+				// Dimension of original image
+				core::dimension2d<u32> dim_crack
+						= img_crack->getDimension();
+				// Count of crack stages
+				u32 crack_count = dim_crack.Height / dim_crack.Width;
+				// Limit progression
+				if(progression > crack_count-1)
+					progression = crack_count-1;
+				// Dimension of a single scaled crack stage
+				core::dimension2d<u32> dim_crack_scaled_single(
+					dim_base.Width,
+					dim_base.Height
+				);
+				// Dimension of scaled size
+				core::dimension2d<u32> dim_crack_scaled(
+					dim_crack_scaled_single.Width,
+					dim_crack_scaled_single.Height * crack_count
+				);
+				// Create scaled crack image
+				video::IImage *img_crack_scaled = driver->createImage(
+						video::ECF_A8R8G8B8, dim_crack_scaled);
+				if(img_crack_scaled)
 				{
-					// Position to copy the crack to in the base image
-					core::position2d<s32> pos_base(x0*cracksize, y0*cracksize);
-					crackimage->copyToWithAlpha(baseimg, pos_base,
-							core::rect<s32>(pos_other, dim_crack),
-							video::SColor(255,255,255,255),
-							NULL);
+					// Scale crack image by copying
+					img_crack->copyToScaling(img_crack_scaled);
+					
+					// Position to copy the crack from
+					core::position2d<s32> pos_crack_scaled(
+						0,
+						dim_crack_scaled_single.Height * progression
+					);
+					
+					// This tiling does nothing currently but is useful
+					for(u32 y0=0; y0<dim_base.Height
+							/ dim_crack_scaled_single.Height; y0++)
+					for(u32 x0=0; x0<dim_base.Width
+							/ dim_crack_scaled_single.Width; x0++)
+					{
+						// Position to copy the crack to in the base image
+						core::position2d<s32> pos_base(
+							x0*dim_crack_scaled_single.Width,
+							y0*dim_crack_scaled_single.Height
+						);
+						// Rectangle to copy the crack from on the scaled image
+						core::rect<s32> rect_crack_scaled(
+							pos_crack_scaled,
+							dim_crack_scaled_single
+						);
+						// Copy it
+						img_crack_scaled->copyToWithAlpha(baseimg, pos_base,
+								rect_crack_scaled,
+								video::SColor(255,255,255,255),
+								NULL);
+					}
+
+					img_crack_scaled->drop();
 				}
-
-				crackimage->drop();
+				
+				img_crack->drop();
 			}
 		}
 		/*
@@ -968,7 +1095,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
 			pm.buildProjectionMatrixOrthoLH(1.65, 1.65, 0, 100);
 			camera->setProjectionMatrix(pm, true);
 
-			scene::ILightSceneNode *light = smgr->addLightSceneNode(0,
+			/*scene::ILightSceneNode *light =*/ smgr->addLightSceneNode(0,
 					v3f(-50, 100, 0), video::SColorf(0.5,0.5,0.5), 1000);
 
 			// Render scene
@@ -1021,9 +1148,9 @@ void make_progressbar(float value, video::IImage *image)
 	
 	core::dimension2d<u32> size = image->getDimension();
 
-	u32 barheight = 1;
-	u32 barpad_x = 1;
-	u32 barpad_y = 1;
+	u32 barheight = size.Height/16;
+	u32 barpad_x = size.Width/16;
+	u32 barpad_y = size.Height/16;
 	u32 barwidth = size.Width - barpad_x*2;
 	v2u32 barpos(barpad_x, size.Height - barheight - barpad_y);
 
-- 
GitLab