From e0186b3eb88ed991588c6765063429a1d2a271df Mon Sep 17 00:00:00 2001 From: OldTeaOwl Date: Tue, 12 Nov 2024 15:26:55 +0700 Subject: [PATCH 1/3] Storing sprites in Entity objects now, moderate ListGUI refactoring to simplify list icons creation. See more in the task description https://trello.com/c/tkAjRpcG --- src/gui/ListGUI.java | 25 +++++++++---------------- src/model/Entity.java | 16 ++++++++++++++++ src/repository/Project.java | 28 ++++++++++++++++++---------- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/src/gui/ListGUI.java b/src/gui/ListGUI.java index c703bb5..22f324f 100644 --- a/src/gui/ListGUI.java +++ b/src/gui/ListGUI.java @@ -43,7 +43,6 @@ public class ListGUI extends JPanel { JButton addListElementEntity; JButton removeListElementEntity; JButton addPicEntity; - String pathImage; JList list; JScrollPane scroll; ActionListener removeEntity; @@ -91,7 +90,7 @@ public class ListGUI extends JPanel { return (String) list.getSelectedValue(); } - public void addListElement(String name,String solid) throws DuplicateEntryException { + public void addListElement(String name, String solid) throws DuplicateEntryException { // плейсхолдеры для новых хитбоксов и дроубоксов, иначе всё валится с NPE List hitboxPoints = new LinkedList(); List drawboxPoints = new LinkedList(); @@ -107,13 +106,15 @@ public class ListGUI extends JPanel { } public void updateList() { - String[] nameList = createNameList(); testModel.removeAllElements(); - for (String name : nameList) - testModel.addElement(name); + + for (Entity e: Project.getInstance()) { + testModel.addElement(e.getName()); - pathImage = Project.getInstance().getXMLPath(); - createImageMap(nameList); + // Create and store JList items icons in a map to prevent their unneccessary re-creation + iconMap.put(e.getName(), createListIconFromSprite( e.getImage() )); + } + list.updateUI(); } @@ -136,7 +137,7 @@ public class ListGUI extends JPanel { } private final float iconMaxWidth = 40, iconMaxHeight = 40; - public Icon imageScaling(BufferedImage image) { + private Icon createListIconFromSprite(BufferedImage image) { CustomIcon icon = null; try { int imageWidth = image.getWidth(), imageHeight = image.getHeight(); @@ -184,14 +185,6 @@ public class ListGUI extends JPanel { } } - private void createImageMap(String[] nameList) { - for (int i = 0; i < nameList.length; i++) { - String name = nameList[i]; - BufferedImage image = Project.getInstance().loadImageByName(name); - iconMap.put(name, imageScaling(image)); - } - } - private JButton createButton(int width,int height,ActionListener listener,String pathImage) { JButton button = new JButton(new ImageIcon(pathImage)); button.setSize(110, 46); diff --git a/src/model/Entity.java b/src/model/Entity.java index 82786ec..608cdef 100644 --- a/src/model/Entity.java +++ b/src/model/Entity.java @@ -1,10 +1,13 @@ package model; +import java.awt.image.BufferedImage; + public class Entity { private String thisName; private Drawbox thisDrawbox; private Hitbox thisHitbox; private String type; + private BufferedImage sprite; public Entity(String name,String drawbox,String hitbox) { thisName = new String(name); @@ -50,6 +53,19 @@ public class Entity { return thisHitbox; }; + public Drawbox getThisDrawbox() { + return thisDrawbox; + } + + /** @return BufferedImage object or null if an image is not set */ + public BufferedImage getImage() { + return sprite; + } + + public void setImage(BufferedImage sprite) { + this.sprite = sprite; + } + public void PrintEntity() { System.out.println("---------------------"); System.out.println("Name: "+thisName); diff --git a/src/repository/Project.java b/src/repository/Project.java index 3223def..11087e0 100644 --- a/src/repository/Project.java +++ b/src/repository/Project.java @@ -132,6 +132,7 @@ public class Project implements Iterable, EntityDrawboxChangedListener { factory = DocumentBuilderFactory.newInstance(); builder = factory.newDocumentBuilder(); document = builder.parse(new File(path+fileName)); + // TODO: remove this from Project, it should not know SHIT about MainGUI if(Launcher.getMainGUI() != null) // at the first program launch, main gui creates list gui before static link to main gui is set Launcher.getMainGUI().setTitle("Hitbox/Drawbox Editor: " + path + fileName); // Получение списка всех элементов objecttype внутри корневого элемента (getDocumentElement возвращает ROOT элемент XML файла). @@ -144,14 +145,18 @@ public class Project implements Iterable, EntityDrawboxChangedListener { } } - // эта колбаса парсит сущности из XML в программные объекты внутри модели, является частью внутренней кухни так что обычно её не нужно трогать - private void parsingElementXMLtoElementList(String entityName,Node objecttype) { + private void parsingElementXMLtoElementList(String entityName, Node objecttype) { String newDrawbox = null; String newHitbox = null; - String type = null; + String type = null; + BufferedImage sprite = null; Element element = (Element)objecttype; NodeList propertyElements = element.getElementsByTagName("property"); - if(propertyElements!=null) { + if(propertyElements != null) { + + // do not lazy load images here - Hitbox parser needs real image sizes + sprite = loadImageByName(entityName); + for(int i = 0; i < propertyElements.getLength(); i++) { Element property = (Element)propertyElements.item(i); String propertyName = property.getAttribute("name"); @@ -168,8 +173,10 @@ public class Project implements Iterable, EntityDrawboxChangedListener { break; } } - Entity e = new Entity(entityName,newDrawbox,newHitbox); + + Entity e = new Entity(entityName, newDrawbox, newHitbox); e.setType(type); + e.setImage(sprite); listEntity.add(e); } } @@ -179,9 +186,6 @@ public class Project implements Iterable, EntityDrawboxChangedListener { * XML-файл. Возвращает null если изображение не найдено. * */ public BufferedImage loadImageByName(String name) { - //TODO: сделать кеширование - не дело подгружать одну и ту же картинку по десять раз! - - String path = Project.getInstance().getXMLPath(); String extension = "png"; // TODO: изображения следует подгружать в отдельном потоке! @@ -209,6 +213,9 @@ public class Project implements Iterable, EntityDrawboxChangedListener { if(getEntityByName(e.getName()) != null) throw new DuplicateEntryException("The entity with the name '" + e.getName() + "' already exists!"); + //TODO: move image loading to AddListElementEntityListener and make it lazy + e.setImage(loadImageByName(e.getName())); + listEntity.add(e); Element objecttypeElement = document.createElement("objecttype"); @@ -365,8 +372,9 @@ public class Project implements Iterable, EntityDrawboxChangedListener { return null; } - //https://stackoverflow.com/a/64659614/6929164 - public static void stripEmptyElements(Node node) + // https://stackoverflow.com/a/64659614/6929164 + // new empty lines will appear on every XML save without this function + private static void stripEmptyElements(Node node) { NodeList children = node.getChildNodes(); for(int i = 0; i < children.getLength(); ++i) { From 6062a8e0d542533e6de646b3718dcafd1d534221 Mon Sep 17 00:00:00 2001 From: OldTeaOwl Date: Tue, 12 Nov 2024 15:38:19 +0700 Subject: [PATCH 2/3] removed unnecessary Drawbox getter accidentally generated by IDE --- src/model/Entity.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/model/Entity.java b/src/model/Entity.java index 608cdef..b2dd800 100644 --- a/src/model/Entity.java +++ b/src/model/Entity.java @@ -53,10 +53,6 @@ public class Entity { return thisHitbox; }; - public Drawbox getThisDrawbox() { - return thisDrawbox; - } - /** @return BufferedImage object or null if an image is not set */ public BufferedImage getImage() { return sprite; From 3943a9a49033629aec9d1d75834fcb99a3909596 Mon Sep 17 00:00:00 2001 From: OldTeaOwl Date: Tue, 12 Nov 2024 17:08:51 +0700 Subject: [PATCH 3/3] fix errors after code review, added entity height and width properties for inner editor use --- src/model/Entity.java | 26 +++++++++++++++++++++++++- src/repository/Project.java | 3 +-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/model/Entity.java b/src/model/Entity.java index b2dd800..2ec8ce9 100644 --- a/src/model/Entity.java +++ b/src/model/Entity.java @@ -8,10 +8,13 @@ public class Entity { private Hitbox thisHitbox; private String type; private BufferedImage sprite; + private int width = 0; + private int height = 0; - public Entity(String name,String drawbox,String hitbox) { + public Entity(String name, String drawbox, String hitbox, BufferedImage sprite) { thisName = new String(name); thisDrawbox = new Drawbox(drawbox); + setImage(sprite); // updates entity width and height, should be called before creating hitbox thisHitbox = new Hitbox(hitbox); } @@ -58,8 +61,13 @@ public class Entity { return sprite; } + /** NOTE: Image setter updates entity width and height */ public void setImage(BufferedImage sprite) { this.sprite = sprite; + if(sprite != null) { + width = sprite.getHeight(); + height = sprite.getHeight(); + } } public void PrintEntity() { @@ -69,4 +77,20 @@ public class Entity { this.thisHitbox.printToConsole(); System.out.println("---------------------"); } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public int getHeight() { + return height; + } + + public void setHeight(int height) { + this.height = height; + } } diff --git a/src/repository/Project.java b/src/repository/Project.java index 11087e0..48667f1 100644 --- a/src/repository/Project.java +++ b/src/repository/Project.java @@ -174,9 +174,8 @@ public class Project implements Iterable, EntityDrawboxChangedListener { } } - Entity e = new Entity(entityName, newDrawbox, newHitbox); + Entity e = new Entity(entityName, newDrawbox, newHitbox, sprite); e.setType(type); - e.setImage(sprite); listEntity.add(e); } }