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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
#include "stdafx.h"
#include "TextureHolder.h"
#include "..\Minecraft.World\StringHelpers.h"
#include "StitchSlot.h"
StitchSlot::StitchSlot(int originX, int originY, int width, int height) : originX(originX), originY(originY), width(width), height(height)
{
subSlots = nullptr;
textureHolder = nullptr;
}
TextureHolder *StitchSlot::getHolder()
{
return textureHolder;
}
int StitchSlot::getX()
{
return originX;
}
int StitchSlot::getY()
{
return originY;
}
bool StitchSlot::add(TextureHolder *textureHolder)
{
// Already holding a texture -- doesn't account for subslots.
if (this->textureHolder != nullptr)
{
return false;
}
int textureWidth = textureHolder->getWidth();
int textureHeight = textureHolder->getHeight();
// We're too small to fit the texture
if (textureWidth > width || textureHeight > height)
{
return false;
}
// Exact fit! best-case-solution
if (textureWidth == width && textureHeight == height && subSlots == nullptr)
{
// Store somehow
this->textureHolder = textureHolder;
return true;
}
// See if we're already divided before, if not, setup subSlots
if (subSlots == nullptr)
{
subSlots = new vector<StitchSlot *>();
// First slot is for the new texture
subSlots->push_back(new StitchSlot(originX, originY, textureWidth, textureHeight));
int spareWidth = width - textureWidth;
int spareHeight = height - textureHeight;
if (spareHeight > 0 && spareWidth > 0)
{
// Space below AND right
//
// <-right->
// +-----+-------+
// | | |
// | Tex | |
// | | |
// |-----+ | ^
// | | |- bottom
// +-------------+ v
// We need to add two more areas, the one with the 'biggest' dimensions should be used
// (In the case of this ASCII drawing, it's the 'right hand side' that should win)
// The 'fattest' area should be used (or when tied, the right hand one)
int right = max(height, spareWidth);
int bottom = max(width, spareHeight);
if (right >= bottom)
{
subSlots->push_back(new StitchSlot(originX, originY + textureHeight, textureWidth, spareHeight));
subSlots->push_back(new StitchSlot(originX + textureWidth, originY, spareWidth, height));
}
else
{
subSlots->push_back(new StitchSlot(originX + textureWidth, originY, spareWidth, textureHeight));
subSlots->push_back(new StitchSlot(originX, originY + textureHeight, width, spareHeight));
}
}
else if (spareWidth == 0)
{
// We just have space left below
//
// +-------------+
// | |
// | Tex |
// | |
// |-------------+ ^
// | | |- bottom
// +-------------+ v
subSlots->push_back(new StitchSlot(originX, originY + textureHeight, textureWidth, spareHeight));
}
else if (spareHeight == 0)
{
// Only space to the right
//
// <-right->
// +-----+-------+
// | | |
// | Tex | |
// | | |
// | | |
// | | |
// +-----+-------+
subSlots->push_back(new StitchSlot(originX + textureWidth, originY, spareWidth, textureHeight));
}
}
//for (final StitchSlot subSlot : subSlots)
for ( StitchSlot *subSlot : *subSlots )
{
if (subSlot->add(textureHolder))
{
return true;
}
}
return false;
}
void StitchSlot::collectAssignments(vector<StitchSlot *> *result)
{
if (textureHolder)
{
result->push_back(this);
}
else if (subSlots)
{
for(StitchSlot *subSlot : *subSlots)
{
subSlot->collectAssignments(result);
}
}
}
|