11package org .dimdev .vanillafix .dynamicresources ;
22
33import com .google .common .collect .Lists ;
4- import com .google .common .collect .Sets ;
54import net .minecraft .client .renderer .StitcherException ;
65import net .minecraft .client .renderer .texture .Stitcher .Holder ;
76import net .minecraft .client .renderer .texture .TextureAtlasSprite ;
87import net .minecraft .util .math .MathHelper ;
98
109import java .util .List ;
11- import java .util .Set ;
1210
1311public class DynamicStitcher {
14- private final int mipmapLevelStitcher ;
15- private final Set <Holder > setStitchHolders = Sets .newHashSetWithExpectedSize (256 );
16- private final List <Slot > stitchSlots = Lists .newArrayListWithCapacity (256 );
12+ public static final int BASE_WIDTH = 32 ;
13+ public static final int BASE_HEIGHT = 32 ;
14+
15+ private final int mipmapLevels ;
16+ private final List <Slot > slots = Lists .newArrayListWithCapacity (256 );
1717 private int currentWidth ;
1818 private int currentHeight ;
1919 private final int maxWidth ;
2020 private final int maxHeight ;
21- private final int maxTileDimension ;
22-
23- public DynamicStitcher (int maxWidthIn , int maxHeightIn , int maxTileDimensionIn , int mipmapLevelStitcherIn ) {
24- mipmapLevelStitcher = mipmapLevelStitcherIn ;
25- maxWidth = maxWidthIn ;
26- maxHeight = maxHeightIn ;
27- maxTileDimension = maxTileDimensionIn ;
21+ private final int maxSpriteSize ;
2822
29- currentWidth = 512 ;
30- currentHeight = 512 ;
31- stitchSlots .add (new Slot (0 , 0 , currentWidth , currentHeight ));
23+ public DynamicStitcher (int maxWidth , int maxHeight , int maxSpriteSize , int mipmapLevels ) {
24+ this .mipmapLevels = mipmapLevels ;
25+ this .maxWidth = maxWidth ;
26+ this .maxHeight = maxHeight ;
27+ this .maxSpriteSize = maxSpriteSize ;
3228 }
3329
34- public int getCurrentWidth () {
35- return currentWidth ;
30+ public int getImageWidth () {
31+ return Math . max ( BASE_WIDTH , MathHelper . smallestEncompassingPowerOfTwo ( currentWidth )) ;
3632 }
3733
38- public int getCurrentHeight () {
39- return currentHeight ;
34+ public int getImageHeight () {
35+ return Math . max ( BASE_HEIGHT , MathHelper . smallestEncompassingPowerOfTwo ( currentHeight )) ;
4036 }
4137
4238 public void addSprite (TextureAtlasSprite sprite ) {
43- Holder holder = new Holder (sprite , mipmapLevelStitcher );
39+ Holder holder = new Holder (sprite , mipmapLevels );
4440
45- if (maxTileDimension > 0 ) {
46- holder .setNewDimension (maxTileDimension );
41+ if (maxSpriteSize > 0 ) {
42+ holder .setNewDimension (maxSpriteSize );
4743 }
4844
49- setStitchHolders .add (holder );
50-
5145 Slot slot = allocateSlot (holder );
5246
5347 if (slot == null ) {
54- throw new StitcherException (null , String .format ("Unable to fit: %s - size: %dx%d" , holder . getAtlasSprite (). getIconName (), holder . getAtlasSprite (). getIconWidth (), holder . getAtlasSprite () .getIconHeight ()));
48+ throw new StitcherException (null , String .format ("Unable to fit %s ( size %dx%d) " , sprite . getIconName (), sprite . getIconWidth (), sprite .getIconHeight ()));
5549 }
5650
57- currentWidth = MathHelper .smallestEncompassingPowerOfTwo (currentWidth );
58- currentHeight = MathHelper .smallestEncompassingPowerOfTwo (currentHeight );
59-
60- sprite .initSprite (currentWidth , currentHeight , slot .getOriginX (), slot .getOriginY (), holder .isRotated ());
51+ sprite .initSprite (BASE_WIDTH , BASE_HEIGHT , slot .getOriginX (), slot .getOriginY (), holder .isRotated ());
6152 }
6253
63- public List <TextureAtlasSprite > getStichSlots () {
64- List <Slot > slots = Lists .newArrayList ();
54+ public List <TextureAtlasSprite > getAllSprites () {
55+ List <Slot > allSlots = Lists .newArrayList ();
6556
66- for (Slot stitchSlot : stitchSlots ) {
67- stitchSlot .getAllStitchSlots (slots );
57+ for (Slot slot : slots ) {
58+ slot .getAllStitchSlots (allSlots );
6859 }
6960
7061 List <TextureAtlasSprite > sprites = Lists .newArrayList ();
7162
72- for (Slot slot : slots ) {
73- Holder holder = slot .getStitchHolder ();
74- TextureAtlasSprite sprite = holder .getAtlasSprite ();
75- sprite .initSprite (currentWidth , currentHeight , slot .getOriginX (), slot .getOriginY (), holder .isRotated ());
76- sprites .add (sprite );
63+ for (Slot slot : allSlots ) {
64+ sprites .add (slot .getStitchHolder ().getAtlasSprite ());
7765 }
7866
7967 return sprites ;
@@ -83,7 +71,7 @@ private Slot allocateSlot(Holder holder) {
8371 TextureAtlasSprite sprite = holder .getAtlasSprite ();
8472 boolean notSquare = sprite .getIconWidth () != sprite .getIconHeight ();
8573
86- for (Slot stitchSlot : stitchSlots ) {
74+ for (Slot stitchSlot : slots ) {
8775 Slot slot = stitchSlot .addSlot (holder );
8876 if (slot != null ) {
8977 return slot ;
@@ -102,59 +90,63 @@ private Slot allocateSlot(Holder holder) {
10290 }
10391 }
10492
105- // TODO: Fix this, expanding the atlas changes all previous UV coordinates
10693 return expandAndAllocateSlot (holder );
10794 }
10895
10996 private Slot expandAndAllocateSlot (Holder holder ) {
110- int i = Math .min (holder .getWidth (), holder .getHeight ());
111- int k = MathHelper .smallestEncompassingPowerOfTwo (currentWidth );
112- int l = MathHelper .smallestEncompassingPowerOfTwo (currentHeight );
113- int i1 = MathHelper .smallestEncompassingPowerOfTwo (currentWidth + i );
114- int j1 = MathHelper .smallestEncompassingPowerOfTwo (currentHeight + i );
115- boolean flag1 = i1 <= maxWidth ;
116- boolean flag2 = j1 <= maxHeight ;
117-
118- if (!flag1 && !flag2 ) {
97+ int smallestDimension = Math .min (holder .getWidth (), holder .getHeight ());
98+
99+ int currentImageWidth = MathHelper .smallestEncompassingPowerOfTwo (currentWidth );
100+ int currentImageHeight = MathHelper .smallestEncompassingPowerOfTwo (currentHeight );
101+
102+ int increasedImageWidth = MathHelper .smallestEncompassingPowerOfTwo (currentWidth + smallestDimension );
103+ int increasedImageHeight = MathHelper .smallestEncompassingPowerOfTwo (currentHeight + smallestDimension );
104+
105+ boolean canExpandWidth = increasedImageWidth <= maxWidth ;
106+ boolean canExpandHeight = increasedImageHeight <= maxHeight ;
107+
108+ if (!canExpandWidth && !canExpandHeight ) {
119109 return null ;
120- } else {
121- boolean flag3 = flag1 && k != i1 ;
122- boolean flag4 = flag2 && l != j1 ;
123- boolean flag ;
110+ }
124111
125- if (flag3 ^ flag4 ) {
126- flag = !flag3 && flag1 ; //Forge: Fix DynamicStitcher not expanding entire height before growing width, and {potentially} growing larger then the max size.
127- } else {
128- flag = flag1 && k <= l ;
129- }
112+ boolean imageWidthWouldIncrease = canExpandWidth && increasedImageWidth != currentImageWidth ;
113+ boolean imageHeightWouldIncrease = canExpandHeight && increasedImageHeight != currentImageHeight ;
130114
131- Slot newSlot ;
115+ boolean expandWidth = imageWidthWouldIncrease == imageHeightWouldIncrease
116+ ? currentImageWidth <= currentImageHeight
117+ : !imageWidthWouldIncrease ;
132118
133- if (flag ) {
134- if (holder .getWidth () > holder .getHeight ()) {
135- holder .rotate ();
136- }
119+ expandWidth &= canExpandWidth ;
137120
138- if (currentHeight == 0 ) {
139- currentHeight = holder .getHeight ();
140- }
121+ Slot newSlot ;
122+ if (expandWidth ) {
123+ if (holder .getWidth () > holder .getHeight ()) {
124+ holder .rotate ();
125+ }
141126
142- if (currentWidth == 0 ) {
143- currentWidth = holder .getWidth ();
144- }
127+ if (currentHeight == 0 ) {
128+ currentHeight = holder .getHeight ();
129+ }
145130
146- newSlot = new Slot (currentWidth , 0 , holder .getWidth (), currentHeight );
147- currentWidth += holder .getWidth ();
148- } else {
149- newSlot = new Slot (0 , currentHeight , currentWidth , holder .getHeight ());
150- currentHeight += holder .getHeight ();
131+ if (currentWidth == 0 ) {
132+ currentWidth = holder .getWidth ();
151133 }
152134
153- Slot slot = newSlot .addSlot (holder );
154- stitchSlots .add (newSlot );
135+ newSlot = new Slot (currentWidth , 0 , holder .getWidth (), currentHeight );
136+ currentWidth += holder .getWidth ();
137+ } else {
138+ // if (holder.getHeight() > holder.getWidth()) {
139+ // holder.rotate();
140+ // }
155141
156- return slot ;
142+ newSlot = new Slot (0 , currentHeight , currentWidth , holder .getHeight ());
143+ currentHeight += holder .getHeight ();
157144 }
145+
146+ Slot slot = newSlot .addSlot (holder );
147+ slots .add (newSlot );
148+
149+ return slot ;
158150 }
159151
160152 public static class Slot {
@@ -165,11 +157,11 @@ public static class Slot {
165157 private List <Slot > subSlots ;
166158 private Holder holder ;
167159
168- public Slot (int originXIn , int originYIn , int widthIn , int heightIn ) {
169- originX = originXIn ;
170- originY = originYIn ;
171- width = widthIn ;
172- height = heightIn ;
160+ public Slot (int originX , int originY , int width , int height ) {
161+ this . originX = originX ;
162+ this . originY = originY ;
163+ this . width = width ;
164+ this . height = height ;
173165 }
174166
175167 public Holder getStitchHolder () {
@@ -233,15 +225,16 @@ public Slot addSlot(Holder holder) {
233225 }
234226
235227 return null ;
228+
236229 }
237230 }
238231
239232 public void getAllStitchSlots (List <Slot > target ) {
240233 if (holder != null ) {
241234 target .add (this );
242235 } else if (subSlots != null ) {
243- for (Slot stitcher$ slot : subSlots ) {
244- stitcher$ slot .getAllStitchSlots (target );
236+ for (Slot slot : subSlots ) {
237+ slot .getAllStitchSlots (target );
245238 }
246239 }
247240 }
0 commit comments