Better Sprite Packer

CrazyPanda

Ex Rune-Scaper
Jun 2, 2008
3,532
273
0
For Galkons format use...
v1.44

Better Sprite Packer 3 (View on GitHub)

Is a tool designed to pack sprites in a way they can be random-accessed.

Features
  • No needed libraries! (you just need the SpriteCache class)
  • You can randomly access any sprite (extremely fast and less memory consumption especially for sprites that aren't used right away such as sprites on interfaces)
  • Images are fully preserved even the meta data, compression is done by the image format
  • Transparency is never set, if you have transparent images they will remain transparent
  • Displays image meta data
  • Indexes are preserved (any image removed and if its not the last element will create a placeholder 0 byte)
  • Import sprites from a directory
  • Import from binary
  • Select the sprites you want to add (with multi-selection)
  • Export to raw formats
  • Export to binary
  • Search an image by it's imdex
  • Modern, clean looking
  • Made in Kotlin programming language
  • Works on Windows, Mac, and Linux
  • Supports PNG, JPEG, and GIF

Info

The programs exports your files in a binary format in 2 files

  1. main_file_sprites.dat (this is where all of the image data is kept)
  2. main_file_sprites.idx (this is the meta data that contains meta information)

main_file_sprites.dat
Code:
HEADER
signature: "bsp" (3 byte)

PAYLOAD
foreach image
	data[]: (variable byte)

main_file_sprites.idx

Code:
HEADER
NONE

PAYLOAD
foreach sprite
	dataOffset: 24uint
	offsetX: ushort
	offsetY: ushort
	length: 24uint

m2yigqJ.png


dBZei2e.png


EkZ6IzT.png


memory consumption

pvFzusE.png
 
Last edited:
It's nice to see your always releasing useful things and pay attention to small details.
Appreciate Seven.
 
Awesome Seven nice work thanks for the release this will come in very useful to the community
 
It's nice to see your always releasing useful things and pay attention to small details.
Appreciate Seven.

Thanks man appreciate it.

Thank you so much for this, will definitely come in handy.

You're welcome :)

Awesome Seven nice work thanks for the release this will come in very useful to the community

Thanks, you're welcome. :)

Could u try changing the sprite loading/saving similar to what it is for cache packed sprites..? (so that this feature would work: http://www.rune-server.org/runescap...5389-magic-spell-outlining-new-spellbook.html)

Cache sprite doesn't have anything to do with drawing the outline of sprites, iirc.

This method in Sprite class does that.

Code:
      private void method349(int ai[], int ai1[], int j, int k, int l, int i1, int j1, int k1) {
            int i;// was parameter
            int l1 = -(l >> 2);
            l = -(l & 3);
            for (int i2 = -i1; i2 < 0; i2++) {
                  for (int j2 = l1; j2 < 0; j2++) {
                        i = ai1[j++];
                        if (i != 0 && i != -1) {
                              ai[k++] = i;
                        } else {
                              k++;
                        }
                        i = ai1[j++];
                        if (i != 0 && i != -1) {
                              ai[k++] = i;
                        } else {
                              k++;
                        }
                        i = ai1[j++];
                        if (i != 0 && i != -1) {
                              ai[k++] = i;
                        } else {
                              k++;
                        }
                        i = ai1[j++];
                        if (i != 0 && i != -1) {
                              ai[k++] = i;
                        } else {
                              k++;
                        }
                  }

                  for (int k2 = l; k2 < 0; k2++) {
                        i = ai1[j++];
                        if (i != 0 && i != -1) {
                              ai[k++] = i;
                        } else {
                              k++;
                        }
                  }
                  k += j1;
                  j += k1;
            }
      }

Refactored version

Code:
	private void draw(int raster[], int[] image, int colour, int sourceIndex, int destIndex, int width, int height, int destStep,
			int sourceStep) {
		int minX = -(width >> 2);
		width = -(width & 3);

		for (int y = -height; y < 0; y++) {
			for (int x = minX; x < 0; x++) {
				colour = image[sourceIndex++];
				if (colour != 0) {
					raster[destIndex++] = colour;
				} else {
					destIndex++;
				}
				colour = image[sourceIndex++];

				if (colour != 0) {
					raster[destIndex++] = colour;
				} else {
					destIndex++;
				}
				colour = image[sourceIndex++];

				if (colour != 0) {
					raster[destIndex++] = colour;
				} else {
					destIndex++;
				}
				colour = image[sourceIndex++];

				if (colour != 0) {
					raster[destIndex++] = colour;
				} else {
					destIndex++;
				}
			}

			for (int k2 = width; k2 < 0; k2++) {
				colour = image[sourceIndex++];
				if (colour != 0) {
					raster[destIndex++] = colour;
				} else {
					destIndex++;
				}
			}

			destIndex += destStep;
			sourceIndex += sourceStep;
		}
	}

Just make sure when you're loading your cache sprites that method above is being called correctly.
 
Thanks man appreciate it.



You're welcome :)



Thanks, you're welcome. :)



Cache sprite doesn't have anything to do with drawing the outline of sprites, iirc.

This method in Sprite class does that.

Code:
      private void method349(int ai[], int ai1[], int j, int k, int l, int i1, int j1, int k1) {
            int i;// was parameter
            int l1 = -(l >> 2);
            l = -(l & 3);
            for (int i2 = -i1; i2 < 0; i2++) {
                  for (int j2 = l1; j2 < 0; j2++) {
                        i = ai1[j++];
                        if (i != 0 && i != -1) {
                              ai[k++] = i;
                        } else {
                              k++;
                        }
                        i = ai1[j++];
                        if (i != 0 && i != -1) {
                              ai[k++] = i;
                        } else {
                              k++;
                        }
                        i = ai1[j++];
                        if (i != 0 && i != -1) {
                              ai[k++] = i;
                        } else {
                              k++;
                        }
                        i = ai1[j++];
                        if (i != 0 && i != -1) {
                              ai[k++] = i;
                        } else {
                              k++;
                        }
                  }

                  for (int k2 = l; k2 < 0; k2++) {
                        i = ai1[j++];
                        if (i != 0 && i != -1) {
                              ai[k++] = i;
                        } else {
                              k++;
                        }
                  }
                  k += j1;
                  j += k1;
            }
      }

Refactored version

Code:
	private void draw(int raster[], int[] image, int colour, int sourceIndex, int destIndex, int width, int height, int destStep,
			int sourceStep) {
		int minX = -(width >> 2);
		width = -(width & 3);

		for (int y = -height; y < 0; y++) {
			for (int x = minX; x < 0; x++) {
				colour = image[sourceIndex++];
				if (colour != 0) {
					raster[destIndex++] = colour;
				} else {
					destIndex++;
				}
				colour = image[sourceIndex++];

				if (colour != 0) {
					raster[destIndex++] = colour;
				} else {
					destIndex++;
				}
				colour = image[sourceIndex++];

				if (colour != 0) {
					raster[destIndex++] = colour;
				} else {
					destIndex++;
				}
				colour = image[sourceIndex++];

				if (colour != 0) {
					raster[destIndex++] = colour;
				} else {
					destIndex++;
				}
			}

			for (int k2 = width; k2 < 0; k2++) {
				colour = image[sourceIndex++];
				if (colour != 0) {
					raster[destIndex++] = colour;
				} else {
					destIndex++;
				}
			}

			destIndex += destStep;
			sourceIndex += sourceStep;
		}
	}

Just make sure when you're loading your cache sprites that method above is being called correctly.

the method is being called correctly... but once I pack the sprites instead of loading them externally it starts working..

I think its the way the myPixels array is handled when loading from cache:
Code:
 public Sprite(StreamLoader streamLoader, String s, int i) {
      Stream stream = new Stream(streamLoader.getDataForName(s + ".dat"));
      Stream stream_1 = new Stream(streamLoader.getDataForName("index.dat"));
      stream_1.currentOffset = stream.readUnsignedWord();
      this.anInt1444 = stream_1.readUnsignedWord();
      this.anInt1445 = stream_1.readUnsignedWord();
      int j = stream_1.readUnsignedByte();
      int[] ai = new int[j];

      int i1;
      for(i1 = 0; i1 < j - 1; ++i1) {
         ai[i1 + 1] = stream_1.read3Bytes();
         if(ai[i1 + 1] == 0) {
            ai[i1 + 1] = 1;
         }
      }

      for(i1 = 0; i1 < i; ++i1) {
         stream_1.currentOffset += 2;
         stream.currentOffset += stream_1.readUnsignedWord() * stream_1.readUnsignedWord();
         ++stream_1.currentOffset;
      }

      this.anInt1442 = stream_1.readUnsignedByte();
      this.anInt1443 = stream_1.readUnsignedByte();
      this.myWidth = stream_1.readUnsignedWord();
      this.myHeight = stream_1.readUnsignedWord();
      i1 = stream_1.readUnsignedByte();
      int j1 = this.myWidth * this.myHeight;
      this.myPixels = new int[j1];
      int l1;
      if(i1 == 0) {
         for(l1 = 0; l1 < j1; ++l1) {
            this.myPixels[l1] = ai[stream.readUnsignedByte()];
         }

      } else {
         if(i1 == 1) {
            for(l1 = 0; l1 < this.myWidth; ++l1) {
               for(int i2 = 0; i2 < this.myHeight; ++i2) {
                  this.myPixels[l1 + i2 * this.myWidth] = ai[stream.readUnsignedByte()];
               }
            }
         }

      }
   }

and this is the external loading method:
Code:
public Sprite(byte spriteData[]) {
		try {
			Image image = Toolkit.getDefaultToolkit().createImage(spriteData);
			ImageIcon sprite = new ImageIcon(image);
			myWidth = sprite.getIconWidth();
			myHeight = sprite.getIconHeight();
			anInt1444 = myWidth;
			anInt1445 = myHeight;
			anInt1442 = 0;
			anInt1443 = 0;
			myPixels = new int[myWidth * myHeight];
			PixelGrabber pixelgrabber = new PixelGrabber(image, 0, 0, myWidth,
					myHeight, myPixels, 0, myWidth);
			pixelgrabber.grabPixels();
			image = null;
			setTransparency(255, 0, 255);
		} catch (Exception _ex) {
			System.out.println(_ex);
		}
	}
 
the method is being called correctly... but once I pack the sprites instead of loading them externally it starts working..

I think its the way the myPixels array is handled when loading from cache:
Code:
 public Sprite(StreamLoader streamLoader, String s, int i) {
      Stream stream = new Stream(streamLoader.getDataForName(s + ".dat"));
      Stream stream_1 = new Stream(streamLoader.getDataForName("index.dat"));
      stream_1.currentOffset = stream.readUnsignedWord();
      this.anInt1444 = stream_1.readUnsignedWord();
      this.anInt1445 = stream_1.readUnsignedWord();
      int j = stream_1.readUnsignedByte();
      int[] ai = new int[j];

      int i1;
      for(i1 = 0; i1 < j - 1; ++i1) {
         ai[i1 + 1] = stream_1.read3Bytes();
         if(ai[i1 + 1] == 0) {
            ai[i1 + 1] = 1;
         }
      }

      for(i1 = 0; i1 < i; ++i1) {
         stream_1.currentOffset += 2;
         stream.currentOffset += stream_1.readUnsignedWord() * stream_1.readUnsignedWord();
         ++stream_1.currentOffset;
      }

      this.anInt1442 = stream_1.readUnsignedByte();
      this.anInt1443 = stream_1.readUnsignedByte();
      this.myWidth = stream_1.readUnsignedWord();
      this.myHeight = stream_1.readUnsignedWord();
      i1 = stream_1.readUnsignedByte();
      int j1 = this.myWidth * this.myHeight;
      this.myPixels = new int[j1];
      int l1;
      if(i1 == 0) {
         for(l1 = 0; l1 < j1; ++l1) {
            this.myPixels[l1] = ai[stream.readUnsignedByte()];
         }

      } else {
         if(i1 == 1) {
            for(l1 = 0; l1 < this.myWidth; ++l1) {
               for(int i2 = 0; i2 < this.myHeight; ++i2) {
                  this.myPixels[l1 + i2 * this.myWidth] = ai[stream.readUnsignedByte()];
               }
            }
         }

      }
   }

and this is the external loading method:
Code:
public Sprite(byte spriteData[]) {
		try {
			Image image = Toolkit.getDefaultToolkit().createImage(spriteData);
			ImageIcon sprite = new ImageIcon(image);
			myWidth = sprite.getIconWidth();
			myHeight = sprite.getIconHeight();
			anInt1444 = myWidth;
			anInt1445 = myHeight;
			anInt1442 = 0;
			anInt1443 = 0;
			myPixels = new int[myWidth * myHeight];
			PixelGrabber pixelgrabber = new PixelGrabber(image, 0, 0, myWidth,
					myHeight, myPixels, 0, myWidth);
			pixelgrabber.grabPixels();
			image = null;
			setTransparency(255, 0, 255);
		} catch (Exception _ex) {
			System.out.println(_ex);
		}
	}

Interesting, well the myPixels doesn't do anything with creating the colored outline.

Code:
      public void drawSprite(int i, int k, int color) {
            int tempWidth = width + 2;
            int tempHeight = height + 2;
            int[] tempArray = new int[tempWidth * tempHeight];
            for (int x = 0; x < width; x++) {
                  for (int y = 0; y < height; y++) {
                        if (raster[x + y * width] != 0)
                              tempArray[(x + 1) + (y + 1) * tempWidth] = raster[x + y * width];
                  }
            }
            for (int x2 = 0; x2 < tempWidth; x2++) {                  
                  for (int y = 0; y < tempHeight; y++) {
                        if (tempArray[(x2) + (y) * tempWidth] == 0) {
                              if (x2 < tempWidth - 1 && tempArray[(x2 + 1) + ((y) * tempWidth)] > 0
                                          && tempArray[(x2 + 1) + ((y) * tempWidth)] != 0xffffff) {
                                    tempArray[(x2) + (y) * tempWidth] = color;
                              }
                              if (x2 > 0 && tempArray[(x2 - 1) + ((y) * tempWidth)] > 0
                                          && tempArray[(x2 - 1) + ((y) * tempWidth)] != 0xffffff) {
                                    tempArray[(x2) + (y) * tempWidth] = color;
                              }
                              if (y < tempHeight - 1 && tempArray[(x2) + ((y + 1) * tempWidth)] > 0
                                          && tempArray[(x2) + ((y + 1) * tempWidth)] != 0xffffff) {
                                    tempArray[(x2) + (y) * tempWidth] = color;
                              }
                              if (y > 0 && tempArray[(x2) + ((y - 1) * tempWidth)] > 0
                                          && tempArray[(x2) + ((y - 1) * tempWidth)] != 0xffffff) {
                                    tempArray[(x2) + (y) * tempWidth] = color;
                              }
                        }
                  }
            }
            i--;
            k--;
            i += drawOffsetX;
            k += drawOffsetY;
            int l = i + k * Raster.width;
            int i1 = 0;
            int j1 = tempHeight;
            int k1 = tempWidth;
            int l1 = Raster.width - k1;
            int i2 = 0;
            if (k < Raster.topY) {
                  int j2 = Raster.topY - k;
                  j1 -= j2;
                  k = Raster.topY;
                  i1 += j2 * k1;
                  l += j2 * Raster.width;
            }
            if (k + j1 > Raster.bottomY) {
                  j1 -= (k + j1) - Raster.bottomY;
            }
            if (i < Raster.topX) {
                  int k2 = Raster.topX - i;
                  k1 -= k2;
                  i = Raster.topX;
                  i1 += k2;
                  l += k2;
                  i2 += k2;
                  l1 += k2;
            }
            if (i + k1 > Raster.bottomX) {
                  int l2 = (i + k1) - Raster.bottomX;
                  k1 -= l2;
                  i2 += l2;
                  l1 += l2;
            }
            if (!(k1 < 0 || j1 < 0)) {
                  method349(Raster.pixels, tempArray, i1, l, k1, j1, l1, i2); // magic sprite outline
            }
      }

This part here looks like its taking all the outermost pixels and setting its hexadecimal value to what ever the specified color is.
Code:
            for (int x2 = 0; x2 < tempWidth; x2++) {                  
                  for (int y = 0; y < tempHeight; y++) {
                        if (tempArray[(x2) + (y) * tempWidth] == 0) {
                              if (x2 < tempWidth - 1 && tempArray[(x2 + 1) + ((y) * tempWidth)] > 0
                                          && tempArray[(x2 + 1) + ((y) * tempWidth)] != 0xffffff) {
                                    tempArray[(x2) + (y) * tempWidth] = color;
                              }
                              if (x2 > 0 && tempArray[(x2 - 1) + ((y) * tempWidth)] > 0
                                          && tempArray[(x2 - 1) + ((y) * tempWidth)] != 0xffffff) {
                                    tempArray[(x2) + (y) * tempWidth] = color;
                              }
                              if (y < tempHeight - 1 && tempArray[(x2) + ((y + 1) * tempWidth)] > 0
                                          && tempArray[(x2) + ((y + 1) * tempWidth)] != 0xffffff) {
                                    tempArray[(x2) + (y) * tempWidth] = color;
                              }
                              if (y > 0 && tempArray[(x2) + ((y - 1) * tempWidth)] > 0
                                          && tempArray[(x2) + ((y - 1) * tempWidth)] != 0xffffff) {
                                    tempArray[(x2) + (y) * tempWidth] = color;
                              }
                        }
                  }
            }
 
Nice, never cba to add more features to it. Thanks :p
 
Great release!

Worked the first time, but why not anymore? I can load from archive but not directly from sprites folder.

Code:
java.lang.NumberFormatException: For input string: ".DS_Store"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Integer.parseInt(Integer.java:569)
	at java.lang.Integer.valueOf(Integer.java:766)
	at seven.controller.MainController.loadSprites(MainController.java:330)
	at seven.controller.MainController.openSpriteDirectory(MainController.java:200)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
	at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
	at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.control.MenuItem.fire(MenuItem.java:462)
	at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1405)
	at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$343(ContextMenuContent.java:1358)
	at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
	at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
	at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
	at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:388)
	at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
	at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
	at com.sun.glass.ui.View.notifyMouse(View.java:937)
 
Great release!

Worked the first time, but why not anymore? I can load from archive but not directly from sprites folder.

Code:
java.lang.NumberFormatException: For input string: ".DS_Store"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Integer.parseInt(Integer.java:569)
	at java.lang.Integer.valueOf(Integer.java:766)
	at seven.controller.MainController.loadSprites(MainController.java:330)
	at seven.controller.MainController.openSpriteDirectory(MainController.java:200)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
	at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
	at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.control.MenuItem.fire(MenuItem.java:462)
	at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1405)
	at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$343(ContextMenuContent.java:1358)
	at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
	at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
	at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
	at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:388)
	at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
	at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
	at com.sun.glass.ui.View.notifyMouse(View.java:937)

For the sprites folder it only works if the folder's name is "Sprites", I'll fix it when I have some time.
 
Updates: May 17, 2016

  • The list now shows the sprites and their indices
  • Added Context menus over ListView
  • Can now dump a single sprite
  • Can view the current directory
  • Added some animations (Progress bars, ProgressIndicator, ProgressText)
  • Added some CSS styling

aktV1gR.gif
 

Users who are viewing this thread (total: 1, members: 0, guests: 1)