ImageComponent.cpp 7.13 KB
Newer Older
1
#include "ImageComponent.h"
2
#include <iostream>
3
#include <boost/filesystem.hpp>
Aloshi's avatar
Aloshi committed
4
#include <math.h>
Aloshi's avatar
Aloshi committed
5
#include "../Log.h"
Aloshi's avatar
Aloshi committed
6
#include "../Renderer.h"
7
#include "../ThemeData.h"
8

9
Eigen::Vector2i ImageComponent::getTextureSize() const
10 11 12 13
{
	if(mTexture)
		return mTexture->getSize();
	else
14
		return Eigen::Vector2i(0, 0);
15
}
16

17 18 19 20 21 22
Eigen::Vector2f ImageComponent::getCenter() const
{
	return Eigen::Vector2f(mPosition.x() - (getSize().x() * mOrigin.x()) + getSize().x() / 2, 
		mPosition.y() - (getSize().y() * mOrigin.y()) + getSize().y() / 2);
}

23
ImageComponent::ImageComponent(Window* window, const Eigen::Vector2f& pos, const std::string& path) : GuiComponent(window), 
24
	mTargetIsMax(false), mFlipX(false), mFlipY(false), mOrigin(0.0, 0.0), mTargetSize(0, 0), mColorShift(0xFFFFFFFF)
25
{
26
	setPosition(pos.x(), pos.y());
Aloshi's avatar
Aloshi committed
27

28 29 30 31
	if(!path.empty())
		setImage(path);
}

32
ImageComponent::~ImageComponent()
33 34 35
{
}

36
void ImageComponent::resize()
37
{
38
	if(!mTexture)
Aloshi's avatar
Aloshi committed
39
		return;
Aloshi's avatar
Aloshi committed
40

41
	const Eigen::Vector2f textureSize((float)getTextureSize().x(), (float)getTextureSize().y());
42

43
	if(mTexture->isTiled())
44 45 46 47
	{
		mSize = mTargetSize;
	}else{
		if(mTargetIsMax)
48
		{
49
			mSize = textureSize;
50

51 52 53 54 55 56 57 58 59 60
			Eigen::Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y()));
			
			if(resizeScale.x() < resizeScale.y())
			{
				mSize[0] *= resizeScale.x();
				mSize[1] *= resizeScale.x();
			}else{
				mSize[0] *= resizeScale.y();
				mSize[1] *= resizeScale.y();
			}
61

62 63 64 65 66 67 68 69
		}else{
			// if both components are set, we just stretch
			// if no components are set, we don't resize at all
			mSize = mTargetSize.isZero() ? textureSize : mTargetSize;

			// if only one component is set, we resize in a way that maintains aspect ratio
			if(!mTargetSize.x() && mTargetSize.y())
			{
70
				mSize[0] = (mTargetSize.y() / textureSize.y()) * textureSize.x();
71 72 73 74
				mSize[1] = mTargetSize.y();
			}else if(mTargetSize.x() && !mTargetSize.y())
			{
				mSize[0] = mTargetSize.x();
75
				mSize[1] = (mTargetSize.x() / textureSize.x()) * textureSize.y();
76 77
			}
		}
78
	}
root's avatar
root committed
79 80
}

81
void ImageComponent::setImage(std::string path, bool tile)
82
{
83
	if(path.empty() || !ResourceManager::getInstance()->fileExists(path))
84 85
		mTexture.reset();
	else
86
		mTexture = TextureResource::get(path, tile);
87

88 89 90
	resize();
}

91
void ImageComponent::setImage(const char* path, size_t length, bool tile)
Aloshi's avatar
Aloshi committed
92 93 94
{
	mTexture.reset();

95
	mTexture = TextureResource::get("", tile);
Aloshi's avatar
Aloshi committed
96
	mTexture->initFromMemory(path, length);
97
	
Aloshi's avatar
Aloshi committed
98 99 100
	resize();
}

101
void ImageComponent::setImage(const std::shared_ptr<TextureResource>& texture)
root's avatar
root committed
102
{
103 104
	mTexture = texture;
	resize();
root's avatar
root committed
105 106
}

107
void ImageComponent::setOrigin(float originX, float originY)
root's avatar
root committed
108
{
109
	mOrigin << originX, originY;
110
}
111

112 113 114 115
void ImageComponent::setResize(float width, float height)
{
	mTargetSize << width, height;
	mTargetIsMax = false;
116
	resize();
root's avatar
root committed
117 118
}

119
void ImageComponent::setMaxSize(float width, float height)
120
{
121
	mTargetSize << width, height;
122
	mTargetIsMax = true;
123 124 125
	resize();
}

126
void ImageComponent::setFlipX(bool flip)
Aloshi's avatar
Aloshi committed
127 128 129 130
{
	mFlipX = flip;
}

131
void ImageComponent::setFlipY(bool flip)
Aloshi's avatar
Aloshi committed
132 133 134 135
{
	mFlipY = flip;
}

136 137 138 139 140
void ImageComponent::setColorShift(unsigned int color)
{
	mColorShift = color;
}

141
void ImageComponent::render(const Eigen::Affine3f& parentTrans)
142
{
143 144 145
	Eigen::Affine3f trans = parentTrans * getTransform();
	Renderer::setMatrix(trans);
	
146
	if(mTexture && getOpacity() > 0)
root's avatar
root committed
147
	{
Aloshi's avatar
Aloshi committed
148 149 150
		GLfloat points[12], texs[12];
		GLubyte colors[6*4];

151
		if(mTexture->isTiled())
152
		{
153 154
			float xCount = mSize.x() / getTextureSize().x();
			float yCount = mSize.y() / getTextureSize().y();
155
			
156
			Renderer::buildGLColorArray(colors, (mColorShift >> 8 << 8)| (getOpacity()), 6);
157
			buildImageArray(0, 0, points, texs, xCount, yCount);
158
		}else{
159
			Renderer::buildGLColorArray(colors, (mColorShift >> 8 << 8) | (getOpacity()), 6);
160
			buildImageArray(0, 0, points, texs);
161
		}
Aloshi's avatar
Aloshi committed
162 163

		drawImageArray(points, texs, colors, 6);
164
	}
165

166
	GuiComponent::renderChildren(trans);
167
}
Aloshi's avatar
Aloshi committed
168

169
void ImageComponent::buildImageArray(int posX, int posY, GLfloat* points, GLfloat* texs, float px, float py)
170
{
171 172 173
	points[0] = posX - (mSize.x() * mOrigin.x());		points[1] = posY - (mSize.y() * mOrigin.y());
	points[2] = posX - (mSize.x() * mOrigin.x());		points[3] = posY + (mSize.y() * (1 - mOrigin.y()));
	points[4] = posX + (mSize.x() * (1 - mOrigin.x()));		points[5] = posY - (mSize.y() * mOrigin.y());
Aloshi's avatar
Aloshi committed
174

175 176 177
	points[6] = posX + (mSize.x() * (1 - mOrigin.x()));		points[7] = posY - (mSize.y() * mOrigin.y());
	points[8] = posX - (mSize.x() * mOrigin.x());		points[9] = posY + (mSize.y() * (1 - mOrigin.y()));
	points[10] = posX + (mSize.x() * (1 -mOrigin.x()));		points[11] = posY + (mSize.y() * (1 - mOrigin.y()));
Aloshi's avatar
Aloshi committed
178 179


Aloshi's avatar
Aloshi committed
180

181
	texs[0] = 0;		texs[1] = py;
Aloshi's avatar
Aloshi committed
182
	texs[2] = 0;		texs[3] = 0;
183
	texs[4] = px;		texs[5] = py;
Aloshi's avatar
Aloshi committed
184

185
	texs[6] = px;		texs[7] = py;
Aloshi's avatar
Aloshi committed
186
	texs[8] = 0;		texs[9] = 0;
187
	texs[10] = px;		texs[11] = 0;
Aloshi's avatar
Aloshi committed
188 189 190 191

	if(mFlipX)
	{
		for(int i = 0; i < 11; i += 2)
192
			if(texs[i] == px)
Aloshi's avatar
Aloshi committed
193 194
				texs[i] = 0;
			else
195
				texs[i] = px;
Aloshi's avatar
Aloshi committed
196 197 198 199
	}
	if(mFlipY)
	{
		for(int i = 1; i < 12; i += 2)
200
			if(texs[i] == py)
Aloshi's avatar
Aloshi committed
201 202
				texs[i] = 0;
			else
203
				texs[i] = py;
Aloshi's avatar
Aloshi committed
204
	}
Aloshi's avatar
Aloshi committed
205 206
}

207
void ImageComponent::drawImageArray(GLfloat* points, GLfloat* texs, GLubyte* colors, unsigned int numArrays)
Aloshi's avatar
Aloshi committed
208
{
209 210
	mTexture->bind();

Aloshi's avatar
Aloshi committed
211 212 213
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Aloshi's avatar
Aloshi committed
214

215 216
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
Aloshi's avatar
Aloshi committed
217

Aloshi's avatar
Aloshi committed
218 219 220 221 222 223
	if(colors != NULL)
	{
		glEnableClientState(GL_COLOR_ARRAY);
		glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
	}

224 225
	glVertexPointer(2, GL_FLOAT, 0, points);
	glTexCoordPointer(2, GL_FLOAT, 0, texs);
Aloshi's avatar
Aloshi committed
226

Aloshi's avatar
Aloshi committed
227
	glDrawArrays(GL_TRIANGLES, 0, numArrays);
Aloshi's avatar
Aloshi committed
228

229 230
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Aloshi's avatar
Aloshi committed
231

Aloshi's avatar
Aloshi committed
232 233 234
	if(colors != NULL)
		glDisableClientState(GL_COLOR_ARRAY);

235 236
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_BLEND);
237
}
238

239
bool ImageComponent::hasImage()
240
{
241
	return (bool)mTexture;
242
}
Aloshi's avatar
Aloshi committed
243

244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
void ImageComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties)
{
	LOG(LogInfo) << " req image [" << view << "." << element << "]  (flags: " << properties << ")";

	using namespace ThemeFlags;

	const ThemeData::ThemeElement* elem = theme->getElement(view, element, "image");
	if(!elem)
	{
		LOG(LogInfo) << "    (missing)";
		return;
	}

	Eigen::Vector2f scale = getParent() ? getParent()->getSize() : Eigen::Vector2f((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
	
	if(properties & POSITION && elem->has("pos"))
	{
		Eigen::Vector2f denormalized = elem->get<Eigen::Vector2f>("pos").cwiseProduct(scale);
		setPosition(Eigen::Vector3f(denormalized.x(), denormalized.y(), 0));
	}

265 266 267 268 269 270 271
	if(properties & ThemeFlags::SIZE)
	{
		if(elem->has("size"))
			setResize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale));
		else if(elem->has("maxSize"))
			setMaxSize(elem->get<Eigen::Vector2f>("maxSize").cwiseProduct(scale));
	}
272

273 274
	// position + size also implies origin
	if((properties & ORIGIN || (properties & POSITION && properties & ThemeFlags::SIZE)) && elem->has("origin"))
275 276 277
		setOrigin(elem->get<Eigen::Vector2f>("origin"));

	if(properties & PATH && elem->has("path"))
278 279 280 281
	{
		bool tile = (elem->has("tile") && elem->get<bool>("tile"));
		setImage(elem->get<std::string>("path"), tile);
	}
282 283 284

	if(properties & COLOR && elem->has("color"))
		setColorShift(elem->get<unsigned int>("color"));
285
}