aboutsummaryrefslogtreecommitdiff
path: root/doc/changelog.txt
blob: 5a01b6bc48a23cfdacf158d30a5ed9731ffbd0cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
Minetest-c55 changelog
----------------------
This should contain all the major changes.
For minor stuff, refer to the commit log of the repository.

2011-06-02:
- Password crash on windows fixed
- Optimized server CPU usage a lot
- Furnaces now work also while players are not near to them

2011-05-29:
- Optimized smooth lighting
- A number of small fixes
- Added clouds and simple skyboxes
- The glass block added
- Added key configuration to config file
- Player privileges on server
- Slightly updated map format
- Player passwords
- All textures first searched from texture_path
- Map directory ("map") has been renamed to "world" (just rename it to load an old world)
- Mouse inversion (invert_mouse)
- Grass doesn't grow immediately anymore
- Fence added

2011-04-24:
- Smooth lighting with simple ambient occlusion
- Updated main menu

2011-04-23_0_test:
- Small bug fixes
- Item drop multiplication fixed
- HP added
- Added A simple monster which spawns to dark places at map generation time
- Some code refactoring and cleaning (possibly new bugs)

2011-04-11:
- Fixed crafting a bit

2011-04-10_0:
- Asynchronous map generation
- New object system

2011-04-06:
- Mesh update of node addition/removal is now done asynchronously on client, removing frametime spike
- Node addition/removal is sent directly only to clients that are closer than 100 nodes to the modification. For the others, the modified blocks are set unsent. (and are re-sent when applicable)

2011-04-05:
- Made furnace usable
- Added cobblestone
- Added wood, stone and steel tools: pickaxes, shovels and axes
- Incremented to version 0.0.2

2011-04-04:
- Cleaned client to be completely synchronous, except for the mesh calculation, which is now done with queues in a separate thread.
- Added node metadata support
- Added chests

2011-02-17:
- Added better handling of textures. Now many file extensions are searched. Also too large textures are not put on the texture atlas, and the construction of the texture atlas is stopped when it is full.

2011-02-16:
- Better handling of Ctrl-C on POSIX systems

2011-02-15:
- Fixed a problem of not saving and loading the "lighting expired" value of MapBlocks properly. This caused high server CPU usage.
- Ctrl-C handling on POSIX systems
- Added simple command support to server
- Added settings enable_texture_atlas and texture_path

2011-02-14:
- Created changelog.txt
- Added sneaking/crouching
- Modified the looks of the hotbar and cleaned code
- Added code to allow generating 3D cube images for inventory

7 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
/*
Copyright (C) 2015 Aaron Suen <warr1024@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "guiscalingfilter.h"
#include "imagefilters.h"
#include "porting.h"
#include "settings.h"
#include "util/numeric.h"
#include <cstdio>
#include "client/renderingengine.h"
#include "client/tile.h" // hasNPotSupport()

/* Maintain a static cache to store the images that correspond to textures
 * in a format that's manipulable by code.  Some platforms exhibit issues
 * converting textures back into images repeatedly, and some don't even
 * allow it at all.
 */
std::map<io::path, video::IImage *> g_imgCache;

/* Maintain a static cache of all pre-scaled textures.  These need to be
 * cleared as well when the cached images.
 */
std::map<io::path, video::ITexture *> g_txrCache;

/* Manually insert an image into the cache, useful to avoid texture-to-image
 * conversion whenever we can intercept it.
 */
void guiScalingCache(const io::path &key, video::IVideoDriver *driver, video::IImage *value)
{
	if (!g_settings->getBool("gui_scaling_filter"))
		return;
	video::IImage *copied = driver->createImage(value->getColorFormat(),
			value->getDimension());
	value->copyTo(copied);
	g_imgCache[key] = copied;
}

// Manually clear the cache, e.g. when switching to different worlds.
void guiScalingCacheClear()
{
	for (auto &it : g_imgCache) {
		if (it.second)
			it.second->drop();
	}
	g_imgCache.clear();
	for (auto &it : g_txrCache) {
		if (it.second)
			RenderingEngine::get_video_driver()->removeTexture(it.second);
	}
	g_txrCache.clear();
}

/* Get a cached, high-quality pre-scaled texture for display purposes.  If the
 * texture is not already cached, attempt to create it.  Returns a pre-scaled texture,
 * or the original texture if unable to pre-scale it.
 */
video::ITexture *guiScalingResizeCached(video::IVideoDriver *driver,
		video::ITexture *src, const core::rect<s32> &srcrect,
		const core::rect<s32> &destrect)
{
	if (src == NULL)
		return src;
	if (!g_settings->getBool("gui_scaling_filter"))
		return src;

	// Calculate scaled texture name.
	char rectstr[200];
	porting::mt_snprintf(rectstr, sizeof(rectstr), "%d:%d:%d:%d:%d:%d",
		srcrect.UpperLeftCorner.X,
		srcrect.UpperLeftCorner.Y,
		srcrect.getWidth(),
		srcrect.getHeight(),
		destrect.getWidth(),
		destrect.getHeight());
	io::path origname = src->getName().getPath();
	io::path scalename = origname + "@guiScalingFilter:" + rectstr;

	// Search for existing scaled texture.
	video::ITexture *scaled = g_txrCache[scalename];
	if (scaled)
		return scaled;

	// Try to find the texture converted to an image in the cache.
	// If the image was not found, try to extract it from the texture.
	video::IImage* srcimg = g_imgCache[origname];
	if (srcimg == NULL) {
		if (!g_settings->getBool("gui_scaling_filter_txr2img"))
			return src;
		srcimg = driver->createImageFromData(src->getColorFormat(),
			src->getSize(), src->lock(), false);
		src->unlock();
		g_imgCache[origname] = srcimg;
	}

	// Create a new destination image and scale the source into it.
	imageCleanTransparent(srcimg, 0);
	video::IImage *destimg = driver->createImage(src->getColorFormat(),
			core::dimension2d<u32>((u32)destrect.getWidth(),
			(u32)destrect.getHeight()));
	imageScaleNNAA(srcimg, srcrect, destimg);

#if ENABLE_GLES
	// Some platforms are picky about textures being powers of 2, so expand
	// the image dimensions to the next power of 2, if necessary.
	if (!hasNPotSupport()) {
		video::IImage *po2img = driver->createImage(src->getColorFormat(),
				core::dimension2d<u32>(npot2((u32)destrect.getWidth()),
				npot2((u32)destrect.getHeight())));
		po2img->fill(video::SColor(0, 0, 0, 0));
		destimg->copyTo(po2img);
		destimg->drop();
		destimg = po2img;
	}
#endif

	// Convert the scaled image back into a texture.
	scaled = driver->addTexture(scalename, destimg, NULL);
	destimg->drop();
	g_txrCache[scalename] = scaled;

	return scaled;
}

/* Convenience wrapper for guiScalingResizeCached that accepts parameters that
 * are available at GUI imagebutton creation time.
 */
video::ITexture *guiScalingImageButton(video::IVideoDriver *driver,
		video::ITexture *src, s32 width, s32 height)
{
	if (src == NULL)
		return src;
	return guiScalingResizeCached(driver, src,
		core::rect<s32>(0, 0, src->getSize().Width, src->getSize().Height),
		core::rect<s32>(0, 0, width, height));
}

/* Replacement for driver->draw2DImage() that uses the high-quality pre-scaled
 * texture, if configured.
 */
void draw2DImageFilterScaled(video::IVideoDriver *driver, video::ITexture *txr,
		const core::rect<s32> &destrect, const core::rect<s32> &srcrect,
		const core::rect<s32> *cliprect, const video::SColor *const colors,
		bool usealpha)
{
	// Attempt to pre-scale image in software in high quality.
	video::ITexture *scaled = guiScalingResizeCached(driver, txr, srcrect, destrect);
	if (scaled == NULL)
		return;

	// Correct source rect based on scaled image.
	const core::rect<s32> mysrcrect = (scaled != txr)
		? core::rect<s32>(0, 0, destrect.getWidth(), destrect.getHeight())
		: srcrect;

	driver->draw2DImage(scaled, destrect, mysrcrect, cliprect, colors, usealpha);
}

void draw2DImage9Slice(video::IVideoDriver *driver, video::ITexture *texture,
		const core::rect<s32> &rect, const core::rect<s32> &middle,
		const core::rect<s32> *cliprect, const video::SColor *const colors)
{
	auto originalSize = texture->getOriginalSize();
	core::vector2di lowerRightOffset = core::vector2di(originalSize.Width, originalSize.Height) - middle.LowerRightCorner;

	for (int y = 0; y < 3; ++y) {
		for (int x = 0; x < 3; ++x) {
			core::rect<s32> src({0, 0}, originalSize);
			core::rect<s32> dest = rect;

			switch (x) {
			case 0:
				dest.LowerRightCorner.X = rect.UpperLeftCorner.X + middle.UpperLeftCorner.X;
				src.LowerRightCorner.X = middle.UpperLeftCorner.X;
				break;

			case 1:
				dest.UpperLeftCorner.X += middle.UpperLeftCorner.X;
				dest.LowerRightCorner.X -= lowerRightOffset.X;
				src.UpperLeftCorner.X = middle.UpperLeftCorner.X;
				src.LowerRightCorner.X = middle.LowerRightCorner.X;
				break;

			case 2:
				dest.UpperLeftCorner.X = rect.LowerRightCorner.X - lowerRightOffset.X;
				src.UpperLeftCorner.X = middle.LowerRightCorner.X;
				break;
			}

			switch (y) {
			case 0:
				dest.LowerRightCorner.Y = rect.UpperLeftCorner.Y + middle.UpperLeftCorner.Y;
				src.LowerRightCorner.Y = middle.UpperLeftCorner.Y;
				break;

			case 1:
				dest.UpperLeftCorner.Y += middle.UpperLeftCorner.Y;
				dest.LowerRightCorner.Y -= lowerRightOffset.Y;
				src.UpperLeftCorner.Y = middle.UpperLeftCorner.Y;
				src.LowerRightCorner.Y = middle.LowerRightCorner.Y;
				break;

			case 2:
				dest.UpperLeftCorner.Y = rect.LowerRightCorner.Y - lowerRightOffset.Y;
				src.UpperLeftCorner.Y = middle.LowerRightCorner.Y;
				break;
			}

			draw2DImageFilterScaled(driver, texture, dest, src, cliprect, colors, true);
		}
	}
}