Browse Source

Merge remote-tracking branch 'origin/LWRdocs' into BP_FinalMaster

# Conflicts:
#	src/ui/view/AbstractCanvas.java
Ludwig Tietze 6 years ago
parent
commit
f68704a18e

+ 17 - 3
src/classes/HolonElement.java

@@ -67,7 +67,7 @@ public class HolonElement implements IGraphedElement{
 
     /**
      * Create a new HolonElement with a user-defined name, amount of the same
-     * element and energyPerElement.
+     * element, energyPerElement and corresponding model.
      *
      * @param eleName String
      * @param amount  int
@@ -78,7 +78,21 @@ public class HolonElement implements IGraphedElement{
     	this(eleName, amount, energy, IdCounterElem.nextId(),model);
     }
     
-    public HolonElement(String eleName, int amount, float energy) {
+    /**
+     * Create a new HolonElement with a user-defined name, amount of the same
+     * element and energyPerElement.
+     *
+     * @param eleName String
+     * @param amount  int
+     * @param energy  float
+     * @param model Model
+     * @deprecated Constructing a HolonElement without a model
+     * make sit detached from a real simulation.
+     * 
+     * This constructor only exists for dry tests
+     * for whether HolonElements generally function as intended.
+     */
+    @Deprecated public HolonElement(String eleName, int amount, float energy) {
     	this(eleName, amount, energy, IdCounterElem.nextId(),null);//TODO: This is just for the old tests...
     }
 
@@ -158,7 +172,7 @@ public class HolonElement implements IGraphedElement{
     }
 
     /**
-     * Get the energyPerElement currently available
+     * Get the energyPerElement currently(at given time step) available
      */
     public float getAvailableEnergyAt(int timestep) {
         return this.availableEnergyPerElementAt[UnitGraph.getEffectiveIndex(this, timestep)];

+ 5 - 9
src/classes/HolonSwitch.java

@@ -125,8 +125,7 @@ public class HolonSwitch extends AbstractCpsObject implements IGraphedElement {
 	/**
 	 * Getter for the status of the Switch at a given timestep.
 	 * 
-	 * @param timeStep
-	 *            int
+	 * @param timeStep state at given iteration.
 	 * @return state value
 	 */
 	public boolean getState(int timeStep) {
@@ -154,8 +153,7 @@ public class HolonSwitch extends AbstractCpsObject implements IGraphedElement {
 	/**
 	 * Change the state of the Switch to manual.
 	 * 
-	 * @param state
-	 *            the State
+	 * @param state the State
 	 */
 	public void setManualState(boolean state) {
 		this.manualActive = state;
@@ -165,8 +163,7 @@ public class HolonSwitch extends AbstractCpsObject implements IGraphedElement {
 	/**
 	 * Set the state of the Switch to automatic.
 	 * 
-	 * @param state
-	 *            the State
+	 * @param state the State
 	 */
 	public void setAutoState(boolean state) {//TODO: This should probably not be public
 		this.autoActive = state;
@@ -193,7 +190,7 @@ public class HolonSwitch extends AbstractCpsObject implements IGraphedElement {
 	}
 
 	/**
-	 * For automatic use only (throught the graph).
+	 * For automatic use only (through the graph).
 	 * 
 	 * @return the Graph Points
 	 */
@@ -204,8 +201,7 @@ public class HolonSwitch extends AbstractCpsObject implements IGraphedElement {
 	/**
 	 * Set the values of the switch in the graph (auto. mode only).
 	 * 
-	 * @param points
-	 *            the Graph points
+	 * @param points the Graph points
 	 */
 	public void setGraphPoints(LinkedList<Point> points) {
 		this.graphPoints = points;

+ 25 - 1
src/classes/IGraphedElement.java

@@ -3,13 +3,37 @@ package classes;
 public interface IGraphedElement {
 	
 	public static final boolean STRETCH_BY_DEFAULT=false;
+	
+	/**
+	 * Sets the local period of the element. 
+	 * If the simulation has 100 steps and the local period is 50,
+	 * then there will be two full cycles during the simulation.
+	 * @param period The local period for this element.
+	 */
 	void setLocalPeriod(int period);
+	
+	/**
+	 * Used to query the local period of an element.
+	 * @return The local period of this element.
+	 * This should return the set local period,
+	 * which may be anything, even if the component is set to be "stretching",
+	 * that is,
+	 * acting as if the local period was the same
+	 * as the number of total iterations for this simulation.
+	 */
 	int getLocalPeriod();
 	
 	/**
-	 * @return Whether the given points should be stretched over the entire graph
+	 * @return Whether the given graph points
+	 * should be stretched(or compressed) over the entire simulation.
 	 * as opposed to repeated once the period is over.
 	 */
 	boolean isStretching();
+	
+	/**
+	 * Adjusts whether the element should act
+	 * as if local period was the same as the simulation's number of iterations.
+	 * @param stretch
+	 */
 	void setStretching(boolean stretch);
 }

+ 1 - 1
src/ui/view/AboutUsPopUp.java

@@ -53,7 +53,7 @@ public class AboutUsPopUp extends JFrame {
         contentPanel2.setLayout(new BoxLayout(contentPanel2, BoxLayout.Y_AXIS));
         contentPanel3.setLayout(new BoxLayout(contentPanel3, BoxLayout.Y_AXIS));
         
-        this.setIconImage(Util.loadImage(this,"/Images/Holeg.png",30,30));
+        this.setIconImage(Util.loadImage("/Images/Holeg.png",30,30));
         setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
         setBounds(100, 100, 500, 800);
         setLocationRelativeTo(parentFrame);

+ 3 - 3
src/ui/view/AbstractCanvas.java

@@ -315,7 +315,7 @@ public abstract class AbstractCanvas extends JPanel {
 		// node image
 		if (cps instanceof CpsNode && (cps == tempCps || model.getSelectedCpsObject() == cps
 				|| model.getSelectedCpsObjects().contains(cps) || tempSelected.contains(cps))) {
-			img = Util.loadImage(this, "/Images/node_selected.png");
+			img = Util.loadImage("/Images/node_selected.png");
 		} else {
 			if (cps instanceof HolonSwitch) {//TODO: What the hell are thes ecalls doing here?
 				if (((HolonSwitch) cps).getState(model.getCurIteration())) {
@@ -381,10 +381,10 @@ public abstract class AbstractCanvas extends JPanel {
 			// set image
 			if(cps instanceof HolonBattery)
 			{
-				img = Util.loadImage(this, ((HolonBattery) cps).getImageBattery());
+				img = Util.loadImage(((HolonBattery) cps).getImageBattery());
 			}else
 			{
-				img = Util.loadImage(this, cps.getImage());
+				img = Util.loadImage(cps.getImage());
 			}
 		}
 	}

+ 1 - 1
src/ui/view/AddElementPopUp.java

@@ -54,7 +54,7 @@ public class AddElementPopUp extends JDialog {
 	 */
 	AddElementPopUp(JFrame parentFrame, Model model) {
 		super((java.awt.Frame) null, true);
-		this.setIconImage(Util.loadImage(this, "/Images/Holeg.png", 30, 30));
+		this.setIconImage(Util.loadImage("/Images/Holeg.png", 30, 30));
 		setModalityType(java.awt.Dialog.ModalityType.APPLICATION_MODAL);
 		setBounds(100, 100, 400, 245);
 		setLocationRelativeTo(parentFrame);

+ 3 - 3
src/ui/view/AddObjectPopUp.java

@@ -80,7 +80,7 @@ public class AddObjectPopUp extends JDialog {
         toEdit = obj;
 		editState = edit;
 		this.model=model;
-		this.setIconImage(Util.loadImage(this, "/Images/Holeg.png",30,30));
+		this.setIconImage(Util.loadImage("/Images/Holeg.png",30,30));
 		setBounds(100, 100, 450, 342);
         setLocationRelativeTo(parentFrame);
         getContentPane().setLayout(new BorderLayout());
@@ -162,7 +162,7 @@ public class AddObjectPopUp extends JDialog {
 				ImageIcon icon = new ImageIcon(
 						new ImageIcon(filePath).getImage().getScaledInstance(50, 50, Image.SCALE_SMOOTH));
 						*/
-				lblImagePreview.setIcon(new ImageIcon(Util.loadImage(this, obj.getImage(), 50, 50)));
+				lblImagePreview.setIcon(new ImageIcon(Util.loadImage(obj.getImage(), 50, 50)));
 			}
 			sourcePath.setBounds(148, 77, 271, 20);
 			contentPanel.add(sourcePath);
@@ -288,7 +288,7 @@ public class AddObjectPopUp extends JDialog {
     	//TODO: Click mich <3 
     	HolonBattery editBat = (HolonBattery) obj;
     	//Window Settings
-    	this.setIconImage(Util.loadImage(this, "/Images/battery.png",30,30));
+    	this.setIconImage(Util.loadImage("/Images/battery.png",30,30));
     	this.setTitle("Edit Battery");
     	setBounds(0, 0, 285, 290);
         setLocationRelativeTo(parentFrame);

+ 1 - 1
src/ui/view/BackgroundPopUp.java

@@ -64,7 +64,7 @@ public class BackgroundPopUp extends JDialog {
 			imageWidth.setText("" + icon.getIconWidth());
 			imageHeight.setText("" + icon.getIconHeight());
 		}
-		this.setIconImage(Util.loadImage(this,"/Images/Holeg.png",30,30));
+		this.setIconImage(Util.loadImage("/Images/Holeg.png",30,30));
 		setBounds(100, 100, 600, 340);
         setLocationRelativeTo(parentFrame);
 

+ 1 - 1
src/ui/view/CanvasResizePopUp.java

@@ -38,7 +38,7 @@ public class CanvasResizePopUp extends JDialog {
 		this.canvas = canvas;
 
 		// properties and stuff
-		this.setIconImage(Util.loadImage(this,"/Images/Holeg.png",30,30));
+		this.setIconImage(Util.loadImage("/Images/Holeg.png",30,30));
 		this.setTitle("Set the Size of the View");
 		setBounds(200, 100, 200, 100);
         setLocationRelativeTo(parentFrame);

+ 4 - 4
src/ui/view/CreateTemplatePopUp.java

@@ -111,7 +111,7 @@ public class CreateTemplatePopUp extends JDialog {
 		/*
 		 * create Frame and GUI
 		 */
-		setIconImage(Util.loadImage(this, "/Images/Holeg.png", 30, 30));
+		setIconImage(Util.loadImage("/Images/Holeg.png", 30, 30));
 		setBounds(100, 100, 476, 344);
 		setLocationRelativeTo(parentFrame);
 		getContentPane().setLayout(new BorderLayout());
@@ -195,7 +195,7 @@ public class CreateTemplatePopUp extends JDialog {
 		 * Image Preview
 		 */
 		lblImagePreview = new JLabel("Image Preview");
-		lblImagePreview.setIcon(new ImageIcon(Util.loadImage(this,
+		lblImagePreview.setIcon(new ImageIcon(Util.loadImage(
 				template.getImage(), 62, 62)));
 		lblImagePreview.setBounds(298, 13, 62, 62);
 		contentPanel.add(lblImagePreview);
@@ -281,8 +281,8 @@ public class CreateTemplatePopUp extends JDialog {
 			File selectedFile = fileChooser.getSelectedFile();
 			String filePath = selectedFile.getAbsolutePath();
 			textField_imagePath.setText(filePath);
-			ImageIcon icon = new ImageIcon(Util.loadImage(this, filePath, 62,
-					62, Image.SCALE_SMOOTH));
+			ImageIcon icon = new ImageIcon(Util.loadImage(filePath, 62,
+					62));
 			lblImagePreview.setIcon(icon);
 		} else {
 			System.out.println("Failed to Load");

+ 6 - 6
src/ui/view/GUI.java

@@ -710,7 +710,7 @@ public class GUI implements CategoryListener {
 
 		frmCyberPhysical.setJMenuBar(menuBar);
 
-		frmCyberPhysical.setIconImage(Util.loadImage(this,
+		frmCyberPhysical.setIconImage(Util.loadImage(
 				"/Images/Holeg.png", 30, 30));
 
 		menuBar.add(mnNewMenu);
@@ -1724,8 +1724,8 @@ public class GUI implements CategoryListener {
 					 */
 					if(e.getKeyCode() == KeyEvent.VK_ENTER)
 						unitGraph.setLocalPeriod(localLength);						
-				}catch(Exception ex){
-					unitGraphLocalPeriod.setBackground(Color.RED);
+				}catch(NumberFormatException ex){
+					unitGraphLocalPeriod.setBackground(PALE_RED);
 				}
 				
 			}
@@ -1758,7 +1758,7 @@ public class GUI implements CategoryListener {
 					for (Category cat : model.getCategories()) {
 						for (AbstractCpsObject cps : cat.getObjects()) {
 							if (value.toString().compareTo(cps.getObjName()) == 0) {
-								imgR = Util.loadImage(this, cps.getImage(), 50,
+								imgR = Util.loadImage(cps.getImage(), 50,
 										50);
 								if (imgR != null) {
 									label.setIcon(new ImageIcon(imgR));
@@ -1776,7 +1776,7 @@ public class GUI implements CategoryListener {
 				if (label.getText().length() == 0) {
 					label.setText(value.toString());
 					if (value.toString().compareTo("Categories") != 0) {
-						label.setIcon(new ImageIcon(Util.loadImage(this,
+						label.setIcon(new ImageIcon(Util.loadImage(
 								"/Images/folder.png")));
 					}
 				}
@@ -2023,7 +2023,7 @@ public class GUI implements CategoryListener {
 														32,
 														java.awt.Image.SCALE_SMOOTH);
 									} else {
-										img = Util.loadImage(this,
+										img = Util.loadImage(
 												cps.getImage(), 32, 32);
 									}
 									tempCps = cps;

+ 1 - 1
src/ui/view/Languages.java

@@ -116,7 +116,7 @@ public class Languages {
 		String[] langArr;
 		try {
 			//read File from Jar
-			InputStreamReader reader = new InputStreamReader(Util.loadStream(Languages.class.getClassLoader(),path));
+			InputStreamReader reader = new InputStreamReader(Util.loadStream(/*Languages.class.getClassLoader(),*/path));
 			BufferedReader br = new BufferedReader(reader);
 			
 			//store Lines in Array

+ 7 - 7
src/ui/view/TimePanel.java

@@ -115,7 +115,7 @@ public class TimePanel extends JPanel implements ActionListener{
 							+ (performanceTime%1000000)/1000 + " Mikrosekunden ");
 					//*/
 					running = false;
-					playBtn.setIcon(new ImageIcon(Util.loadImage(this, "/Button_Images/play.png", 30, 30, Image.SCALE_SMOOTH)));
+					playBtn.setIcon(new ImageIcon(Util.loadImage("/Button_Images/play.png", 30, 30)));
 					timer.stop();
 				}
 			}
@@ -163,7 +163,7 @@ public class TimePanel extends JPanel implements ActionListener{
 		playBtn.setContentAreaFilled(false);
 		playBtn.setBorderPainted(false);
 		playBtn.setBorder(null);
-		playBtn.setIcon(new ImageIcon(Util.loadImage(this, "/Button_Images/play.png",30,30)));
+		playBtn.setIcon(new ImageIcon(Util.loadImage("/Button_Images/play.png",30,30)));
 		playBtn.addActionListener(new ActionListener() {
 			@Override
 			public void actionPerformed(ActionEvent e) {
@@ -184,10 +184,10 @@ public class TimePanel extends JPanel implements ActionListener{
 					//*/
 					
 					timer.start();
-					playBtn.setIcon(new ImageIcon(Util.loadImage(this, "/Button_Images/pause.png", 30, 30, Image.SCALE_SMOOTH)));
+					playBtn.setIcon(new ImageIcon(Util.loadImage("/Button_Images/pause.png", 30, 30)));
 				} else {
 					timer.stop();
-					playBtn.setIcon(new ImageIcon(Util.loadImage(this, "/Button_Images/play.png", 30, 30, Image.SCALE_SMOOTH)));
+					playBtn.setIcon(new ImageIcon(Util.loadImage("/Button_Images/play.png", 30, 30)));
 				}
 			}
 		});
@@ -195,7 +195,7 @@ public class TimePanel extends JPanel implements ActionListener{
 
 		timeResetBtn.setContentAreaFilled(false);
 		timeResetBtn.setBorder(null);
-		timeResetBtn.setIcon(new ImageIcon(Util.loadImage(this, "/Button_Images/reset.png", 30, 30)));
+		timeResetBtn.setIcon(new ImageIcon(Util.loadImage("/Button_Images/reset.png", 30, 30)));
 		timeResetBtn.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent ae) {
 				timeSlider.setValue(timeSlider.getMinimum());
@@ -211,7 +211,7 @@ public class TimePanel extends JPanel implements ActionListener{
 
 		timeForwardBtn.setContentAreaFilled(false);
 		timeForwardBtn.setBorder(null);
-		timeForwardBtn.setIcon(new ImageIcon(Util.loadImage(this,"/Button_Images/forward.png",30,30)));
+		timeForwardBtn.setIcon(new ImageIcon(Util.loadImage("/Button_Images/forward.png",30,30)));
 		timeForwardBtn.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent ae) {
 				if (!cont.getModel().getIsSimRunning()) {
@@ -224,7 +224,7 @@ public class TimePanel extends JPanel implements ActionListener{
 		timeBackwardBtn.setToolTipText(Languages.getLanguage()[92]);
 
 		timeBackwardBtn.setBorder(null);
-		timeBackwardBtn.setIcon(new ImageIcon(Util.loadImage(this, "/Button_Images/backward.png", 30,30)));
+		timeBackwardBtn.setIcon(new ImageIcon(Util.loadImage("/Button_Images/backward.png", 30,30)));
 		timeBackwardBtn.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent ae) {
 				timeSlider.setValue(timeSlider.getValue() - 1);

+ 25 - 3
src/ui/view/UnitGraph.java

@@ -627,8 +627,9 @@ public class UnitGraph extends JPanel implements MouseListener, MouseMotionListe
      * @param s which should be visualized
      */
     public void repaintWithNewSwitch(HolonSwitch s) {
-    	current=s;
+    	
         //arrayOfBooleans = s.getValueArray();
+    	current=s;
         pointList = s.getGraphPoints();
         isSwitch = true;
         isElement = false;
@@ -849,7 +850,8 @@ public class UnitGraph extends JPanel implements MouseListener, MouseMotionListe
      * @param localPeriod
      */
     public void setLocalPeriod(int localPeriod){
-    	for(IGraphedElement e:tempElements)e.setLocalPeriod(localPeriod);
+    	if(isElement)for(IGraphedElement e:tempElements)e.setLocalPeriod(localPeriod);
+    	else if(isSwitch)current.setLocalPeriod(localPeriod);
     }
     
     /**
@@ -866,20 +868,40 @@ public class UnitGraph extends JPanel implements MouseListener, MouseMotionListe
     }
     
     public void setStretching(boolean b){
-    	for(IGraphedElement e:tempElements)e.setStretching(b);
+    	if(isElement)for(IGraphedElement e:tempElements)e.setStretching(b);
+    	else if(isSwitch)current.setStretching(b);
     }
     
     static int lv=0;
     
+    /**
+     * Determines the index of the internal value array
+     * of an element that should be used, since elements only save 100 values,
+     * but iterations and local period can be anything between 1 and 100000.
+     * 
+     * @param m the corresponding model.
+     * @param e the element for which the calculation should be made.
+     * @param timeStep the iteration for which the calculation should be made.
+     * @return
+     */
     public static int getEffectiveIndex(Model m, IGraphedElement e, int timeStep){
     	if(e.isStretching())return timeStep*100/(m==null?STANDARD_GRAPH_ACCURACY:m.getIterations());
     	else return timeStep%e.getLocalPeriod()*100/e.getLocalPeriod();
     }
     
+    /**
+     * Same as getEffectiveIndex(Model, IGraphedElement, int),
+     * but using the Model obtained from the singleton controller
+     * to determine the total number of iterations(for "use global").
+     */
     public static int getEffectiveIndex(IGraphedElement e, int timeStep){
     	return getEffectiveIndex(SingletonControl.getInstance().getControl()==null?null:SingletonControl.getInstance().getControl().getModel(),e,timeStep);
     }
     
+    /**
+     * Same as getEffectiveIndex(Model, IGraphedElement),
+     * but the current iteration is also obtained from the standard model.
+     */
     public static int getEffectiveIndex(IGraphedElement e){
     	return getEffectiveIndex(e,SingletonControl.getInstance().getControl().getModel().getCurIteration());
     }

+ 2 - 2
src/ui/view/UpperNodeCanvas.java

@@ -480,7 +480,7 @@ public class UpperNodeCanvas extends AbstractCanvas implements MouseListener, Mo
             // node image
             if (cps instanceof CpsNode && (cps == tempCps || model.getSelectedCpsObject() == cps
                     || model.getSelectedCpsObjects().contains(cps) || tempSelected.contains(cps))) {
-            	img = Util.loadImage(this,"/Images/node_selected.png");
+            	img = Util.loadImage("/Images/node_selected.png");
             } else {
                 if (cps instanceof HolonSwitch) {
                     if (((HolonSwitch) cps).getState(model.getCurIteration())) {
@@ -508,7 +508,7 @@ public class UpperNodeCanvas extends AbstractCanvas implements MouseListener, Mo
                 if (checkPath.exists()) {
                     img = new ImageIcon(cps.getImage()).getImage();
                 } else {
-                	img = Util.loadImage(this,cps.getImage());
+                	img = Util.loadImage(cps.getImage());
                 }
             }
             g2.drawImage(img, (upperNode.getLeftBorder() >> 1) - 25,

+ 53 - 12
src/ui/view/Util.java

@@ -12,6 +12,12 @@ import java.util.HashMap;
 import javax.imageio.ImageIO;
 import javax.swing.JLabel;
 
+/**
+ * 
+ * @author TU-Darmstadt BP Gruppe 7 WS17/18
+ *	Centralized resource loading methods
+ *	for improved performance and easier troubleshooting.
+ */
 public class Util {
 	
 	/**
@@ -28,6 +34,7 @@ public class Util {
 	private static final byte SAVE_NOTHING=0, /*SAVE_EXTERNAL=1,*/ SAVE_RAW=2, SAVE_EVERYTHING=4,
 								SAVE_MODE=SAVE_EVERYTHING;
 	private static HashMap<String, Image> imgStorage;
+	private static Util xmp=new Util();//Used to load resources from the JAR.
 	
 	static{
 		/*
@@ -51,30 +58,54 @@ public class Util {
 		if(SAVE_MODE!=SAVE_NOTHING)imgStorage=new HashMap<String, Image>();
 	}
 	
-	static Image loadImage(Object origin, String url, int w, int h, int scale){
+	/**
+	 * The rawest function replacing the old method without any default parameters.
+	 * Currently not used in HOLEG at all(aside form calls from the convenience methods).
+	 * @param url Path to the image to be loaded.
+	 * @param w Width the loaded image should be scaled to.
+	 * @param h Height the loaded image should be scaled to.
+	 * @param hints Hints for the scaling algorithm to be used.
+	 * Same as the parameter in the getScaledInstance function of Image.
+	 * @return A loaded and scaled image from the requested path.
+	 */
+	static Image loadImage(String url, int w, int h, int hints){
 		if(SAVE_MODE==SAVE_EVERYTHING){
-			String key=url+"?"+w+"?"+h+"?"+scale;
+			String key=url+"?"+w+"?"+h+"?"+hints;
 			if(imgStorage.containsKey(key))return(imgStorage.get(key));
 			else{
-				Image img=loadImage(origin,url).getScaledInstance(w, h, scale);
+				Image img=loadImage(url).getScaledInstance(w, h, hints);
 				imgStorage.put(key, img);
 				return img;
 			}
 		}
-		return loadImage(origin,url).getScaledInstance(w, h, scale);
+		return loadImage(url).getScaledInstance(w, h, hints);
 	}
 	
-	static Image loadImage(Object origin, String url, int w, int h){
-		return loadImage(origin,url,w,h, Image.SCALE_SMOOTH);
+	/**
+	 * Loads an image from the given path and scales it using the smooth algorithm.
+	 * @param url Path to the image to be loaded.
+	 * @param w Width the loaded image should be scaled to.
+	 * @param h Height the loaded image should be scaled to.
+	 * @return A loaded and (smoothly) scaled image from the requested path.
+	 */
+	static Image loadImage(String url, int w, int h){
+		return loadImage(url,w,h, Image.SCALE_SMOOTH);
 	}
 	
-	static Image loadImage(Object origin, String url){
+	/**
+	 * Loads an image from the given path and scales it using the smooth algorithm.
+	 * @param url Path to the image to be loaded.
+	 * @param w Width the loaded image should be scaled to.
+	 * @param h Height the loaded image should be scaled to.
+	 * @return An image loaded from the requested path.
+	 */
+	static Image loadImage(String url){
 		if(SAVE_MODE!=SAVE_NOTHING){
 			if(imgStorage.containsKey(url))return imgStorage.get(url);
 			else{
 				Image img;
 				try {
-					img= ImageIO.read(loadStream(origin, url));
+					img= ImageIO.read(loadStream(url));
 				} catch (IOException e) {
 					e.printStackTrace();
 					return defaultImage;
@@ -84,15 +115,22 @@ public class Util {
 			}
 		}
 		try {
-			return ImageIO.read(loadStream(origin, url));
+			return ImageIO.read(loadStream(url));
 		} catch (IOException e) {
 			e.printStackTrace();
 			return defaultImage;
 		}
 	}
 	
-	static InputStream loadStream(Object origin, String url){
-		InputStream o=origin.getClass().getResourceAsStream(url);
+	/**
+	 * Loads any resource with a given path,
+	 * regardless of whether it is inside the jar or an external resource.
+	 * Every loadImage() function uses this as a basis.
+	 * @param url The path (and file name) of the requested resource.
+	 * @return An InputStream from the requested resource.
+	 */
+	static InputStream loadStream(String url){
+		InputStream o=xmp.getClass().getResourceAsStream(url);
 		if(o!=null)return o;
 		else{
 			boolean rootSymbol=false;	//Whether url starts with a / or \
@@ -109,5 +147,8 @@ public class Util {
 			}
 			return null;
 		}
-	}
+	}
+	
+	//Nobody needs an instance of this. I do, because I use it to load images from inside the JAR.
+	private Util(){}
 }