diff --git a/.classpath b/.classpath index e1fc3b4..e8e2af4 100644 --- a/.classpath +++ b/.classpath @@ -1,7 +1,7 @@ - + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index c95e8e6..2b6231d 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,9 +1,9 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=15 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=22 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=23 +org.eclipse.jdt.core.compiler.compliance=22 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate @@ -12,4 +12,4 @@ org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.release=enabled -org.eclipse.jdt.core.compiler.source=15 +org.eclipse.jdt.core.compiler.source=22 diff --git a/res/.png b/res/.png new file mode 100644 index 0000000..94ebe6b Binary files /dev/null and b/res/.png differ diff --git a/res/NewName.png b/res/NewName.png new file mode 100644 index 0000000..e728478 Binary files /dev/null and b/res/NewName.png differ diff --git a/res/newtest.png b/res/newtest.png new file mode 100644 index 0000000..94ebe6b Binary files /dev/null and b/res/newtest.png differ diff --git a/res/objecttypes.xml b/res/objecttypes.xml index 3d5ddee..7c07663 100644 --- a/res/objecttypes.xml +++ b/res/objecttypes.xml @@ -20,4 +20,9 @@ + + + + + diff --git a/src/events/EntityHitboxChangedEvent.java b/src/events/EntityHitboxChangedEvent.java new file mode 100644 index 0000000..4bd8e14 --- /dev/null +++ b/src/events/EntityHitboxChangedEvent.java @@ -0,0 +1,18 @@ +package events; + +import model.Entity; +import model.Hitbox; + +/* + * Structure-like class no getters + */ +public class EntityHitboxChangedEvent { + public Hitbox hitbox; + //storing entity object instead of just entity name will allow to get entity data without extra calls + public Entity owner; + + public EntityHitboxChangedEvent(Hitbox hitbox, Entity owner) { + this.hitbox = hitbox; + this.owner = owner; + } +} diff --git a/src/events/EntityHitboxChangedListener.java b/src/events/EntityHitboxChangedListener.java new file mode 100644 index 0000000..9532c18 --- /dev/null +++ b/src/events/EntityHitboxChangedListener.java @@ -0,0 +1,7 @@ +package events; + +public interface EntityHitboxChangedListener { + + void hitboxChanged(EntityHitboxChangedEvent event); + +} diff --git a/src/gui/CircleRenderingFunction.java b/src/gui/CircleRenderingFunction.java deleted file mode 100644 index 41b9807..0000000 --- a/src/gui/CircleRenderingFunction.java +++ /dev/null @@ -1,5 +0,0 @@ -package gui; - -public class CircleRenderingFunction implements ShapeRenderingFunction { - -} diff --git a/src/gui/DrawboxEditor.java b/src/gui/DrawboxEditor.java index 5094560..fea35e2 100644 --- a/src/gui/DrawboxEditor.java +++ b/src/gui/DrawboxEditor.java @@ -1,5 +1,6 @@ package gui; +import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics2D; import java.awt.event.ActionEvent; @@ -16,146 +17,48 @@ import javax.swing.JTabbedPane; import events.EntityDrawboxChangedEvent; import events.EntityDrawboxChangedListener; +import gui.render.DrawboxRectengleRenderingFunction; import model.Drawbox; import model.Point; import repository.Project; public class DrawboxEditor extends Editable { - private List drawboxPoints; - private List basePoints; Logger logger = Logger.getLogger("gui.DrawboxRectangleEditor"); - Point currentPoint = new Point(0, 0); - private List listeners = new ArrayList<>(); - DrawboxEditor(ListGUI listGUI) { super(listGUI); + //Если будет ошибка, попробовать в Editable прокинуть canvas, как сделано с ListGUI + canvas = new EditableCanvas(entity, image); + add(canvas,BorderLayout.CENTER); + canvas.setBackground(Color.GRAY); + canvas.setDrawboxRectengleRenderingFunction(); + canvas.setVisible(true); logger.setLevel(Level.CONFIG); } - @Override - public void drawing(Graphics2D g) { - Drawbox drawbox = entity.getDrawbox(); - drawboxPoints = drawbox.getDrawboxlistPoints(); - basePoints = drawbox.getbaseListPoints(); - logger.finest("drawbox point size: "+ drawboxPoints.size()); - for(Point p: drawboxPoints) - logger.finest("DrawBoxPoint: ["+ p.x + ":"+p.y+"]"); - for(Point p: basePoints) - logger.finest("BasePoint: ["+ p.x + ":"+p.y+"]"); - - if(drawboxPoints.size() >= 1 && drawboxPoints.size() < 4) { - Point lastPoint = drawboxPoints.get(drawboxPoints.size()-1); - g.drawLine((int)lastPoint.x, (int)lastPoint.y, (int)currentPoint.x, (int)currentPoint.y); - for(int i = 0; i < drawboxPoints.size()-1;i++) { - int x1 = (int)drawboxPoints.get(i).x; - int y1 = (int)drawboxPoints.get(i).y; - int x2 = (int)drawboxPoints.get(i+1).x; - int y2 = (int)drawboxPoints.get(i+1).y; - g.drawLine(x1, y1, x2, y2); - } - } else { - for(int i = 0; i < drawboxPoints.size();i++) { - int x1 = (int)drawboxPoints.get(i % drawboxPoints.size()).x; - int y1 = (int)drawboxPoints.get(i % drawboxPoints.size()).y; - int x2 = (int)drawboxPoints.get((i+1) % drawboxPoints.size()).x; - int y2 = (int)drawboxPoints.get((i+1) % drawboxPoints.size()).y; - g.drawLine(x1, y1, x2, y2); - } -// ОТРИСОВКА ОСНОВАНИЯ - g.setColor(Color.BLUE); - for(int i = 0; i < basePoints.size()-1;i++) { - int x1 = (int)basePoints.get(i).x; - int y1 = (int)basePoints.get(i).y; - int x2 = (int)basePoints.get(i+1).x; - int y2 = (int)basePoints.get(i+1).y; - g.drawLine(x1, y1+3, x2, y2+3); - } - } - } - - @Override - public void saveDataInEntity() { - entity.setDrawbox(new Drawbox(drawboxPoints)); - } @Override public void mousePressed(MouseEvent e) { - if(drawboxPoints.size() < 4) { - Point p = new Point(e.getX(), e.getY()); - drawboxPoints.add(p); - if(drawboxPoints.size() == 4) { - sortingDrawboxPoints(); - saveDataInEntity(); - //при выборе 4-й точки и формировании данных drawbox, уведомляем всех подписчит - if(listeners!=null) { - notifySubscribers(); - } - - } - } - } - /*Точки должны идти в определенном порядке: - * левая верхняя точка, правая верхняя, нижняя правая, нижняя левая; - * Обе нижние точки, т.е. 3 и 4 являются основанием - хардкод. - * P.s. возможно это не критично, и в сторе предусмотрено, что бы они сортировались, - * но на данном этапе на всякий случай стоит так поступить*/ - private void sortingDrawboxPoints() { - //окей, это написано плохо, но... Похуй, пляшем) - Collections.sort( - drawboxPoints, - (point1, point2) -> Float.compare(point1.y, point2.y) - ); - if(drawboxPoints.get(0).x>drawboxPoints.get(1).x) { - Collections.swap(drawboxPoints, 0, 1); - } - if(drawboxPoints.get(2).x drawboxPoints; + private List basePoints; + Point currentPoint = new Point(0, 0); + private List listeners = new ArrayList<>(); + Entity entity; + Logger logger = Logger.getLogger("gui.DrawboxRectangleEditor"); + public DrawboxRectengleRenderingFunction(Entity entity) { + this.entity = entity; + } + + @Override + public void drawing(Graphics2D g) { + Drawbox drawbox = entity.getDrawbox(); + drawboxPoints = drawbox.getDrawboxlistPoints(); + basePoints = drawbox.getbaseListPoints(); + logger.finest("drawbox point size: "+ drawboxPoints.size()); + for(Point p: drawboxPoints) + logger.finest("DrawBoxPoint: ["+ p.x + ":"+p.y+"]"); + for(Point p: basePoints) + logger.finest("BasePoint: ["+ p.x + ":"+p.y+"]"); + + if(drawboxPoints.size() >= 1 && drawboxPoints.size() < 4) { + Point lastPoint = drawboxPoints.get(drawboxPoints.size()-1); + g.drawLine((int)lastPoint.x, (int)lastPoint.y, (int)currentPoint.x, (int)currentPoint.y); + for(int i = 0; i < drawboxPoints.size()-1;i++) { + int x1 = (int)drawboxPoints.get(i).x; + int y1 = (int)drawboxPoints.get(i).y; + int x2 = (int)drawboxPoints.get(i+1).x; + int y2 = (int)drawboxPoints.get(i+1).y; + g.drawLine(x1, y1, x2, y2); + } + } else { + for(int i = 0; i < drawboxPoints.size();i++) { + int x1 = (int)drawboxPoints.get(i % drawboxPoints.size()).x; + int y1 = (int)drawboxPoints.get(i % drawboxPoints.size()).y; + int x2 = (int)drawboxPoints.get((i+1) % drawboxPoints.size()).x; + int y2 = (int)drawboxPoints.get((i+1) % drawboxPoints.size()).y; + g.drawLine(x1, y1, x2, y2); + } +// ОТРИСОВКА ОСНОВАНИЯ + g.setColor(Color.BLUE); + for(int i = 0; i < basePoints.size()-1;i++) { + int x1 = (int)basePoints.get(i).x; + int y1 = (int)basePoints.get(i).y; + int x2 = (int)basePoints.get(i+1).x; + int y2 = (int)basePoints.get(i+1).y; + g.drawLine(x1, y1+3, x2, y2+3); + } + } + + } + + @Override + public void mousePressed(MouseEvent e) { + if(drawboxPoints.size() < 4) { + Point p = new Point(e.getX(), e.getY()); + drawboxPoints.add(p); + if(drawboxPoints.size() == 4) { + sortingDrawboxPoints(); + saveDataInEntity(); + //при выборе 4-й точки и формировании данных drawbox, уведомляем всех подписчит + if(listeners!=null) { + notifySubscribers(); + } + + } + } + } + + @Override + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseMoved(MouseEvent e) { + currentPoint.x = e.getX(); + currentPoint.y = e.getY(); + } + + /*Точки должны идти в определенном порядке: + * левая верхняя точка, правая верхняя, нижняя правая, нижняя левая; + * Обе нижние точки, т.е. 3 и 4 являются основанием - хардкод. + * P.s. возможно это не критично, и в сторе предусмотрено, что бы они сортировались, + * но на данном этапе на всякий случай стоит так поступить*/ + private void sortingDrawboxPoints() { + //окей, это написано плохо, но... Похуй, пляшем) + Collections.sort( + drawboxPoints, + (point1, point2) -> Float.compare(point1.y, point2.y) + ); + if(drawboxPoints.get(0).x>drawboxPoints.get(1).x) { + Collections.swap(drawboxPoints, 0, 1); + } + if(drawboxPoints.get(2).x getDrawboxlistPoints() { return drawboxlistPoints; } diff --git a/src/model/Entity.java b/src/model/Entity.java index 9556368..07db454 100644 --- a/src/model/Entity.java +++ b/src/model/Entity.java @@ -15,14 +15,21 @@ public class Entity { 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,this); + if(hitbox != null) { + String[] dataHitbox = hitbox.split(" "); + System.out.println("Создается обьект /"+name+"/. Shape Hitbox = /"+dataHitbox[0]+"/. Размер dataHitbox = /"+dataHitbox.length+"/."); + if(dataHitbox[0].equals("Rectangle")) { + thisHitbox = new HitboxRectangle(dataHitbox,this); + }else if(dataHitbox[0].equals("Circle")) { + thisHitbox = new HitboxCircle(dataHitbox,this); + } + } } - +// при добавлении новой сущности по умолчанию создается у нее прямоугольный хитбокс public Entity(String name) { this.thisName = name; - this.thisHitbox = new Hitbox(); + this.thisHitbox = new HitboxRectangle("Rectangle",this); this.thisDrawbox = new Drawbox(); - thisHitbox.setOwnerEntity(this); } public void setName(String outName) { diff --git a/src/model/Hitbox.java b/src/model/Hitbox.java index 89ecd9f..3d77ddf 100644 --- a/src/model/Hitbox.java +++ b/src/model/Hitbox.java @@ -3,34 +3,35 @@ package model; import java.util.ArrayList; import java.util.List; -public class Hitbox { +public abstract class Hitbox { String shape = null;// shape - Форма хитбокса. Понадобится при написании сохранения. Один из параметров в xml-file. Point referencePoint = new Point(0, 0); //Точка отсчета хитбокса, от нее рассчитывается высота+ширина/радиус(при круге) хитбокса. Entity owner; public Hitbox(){ } + //Либо так передавать shape, либо создать setShape. Но по сути shape определяется при создании обьекта, и тогда set - предоставление не нужных возможностей. public Hitbox(String shape){ this.shape = new String(shape); } //informationHitbox - default="Rectangle 0 0 96 98" + //Предварительно, я бы сказал что вообще этот конструктор бесполезен и его можно удалить, + // т.к. Hitbox конструктор вызывается из дочерних элементов, а они уже владеют всей необходимой инфой, и entity owner задают сами + // кстати забавно. сейчас устанавливается entity через serOwnerEntity, но как будто этот метод тоже излишек, ведь владелец хитбокса только один. + //Но нет. у нас может быть хитбокс создан программно раньше entity, помню было такое где то, так что этот метод еще обоснован. public Hitbox(String informationHitbox, Entity owner){ if(informationHitbox!= null) { setOwnerEntity(owner); String[] informations = informationHitbox.split(" "); shape = new String(informations[0]); - if(shape.equals("Rectangle")) { - /*parseStringToRectangleHitbox(informations); - createCartesianPointsFromWidthAndHeigh(); - convertCartesianPointsToIso(); - printToConsole();*/ - }else if(shape.equals("Circle")) { - //parseStringToCircleHitbox(informations); - } } } + + public abstract String listPointsToString(); + + /** * @param result - Point object to store the result * @return x and y converted to isometic coords diff --git a/src/model/HitboxCircle.java b/src/model/HitboxCircle.java index 0e91589..896e6b4 100644 --- a/src/model/HitboxCircle.java +++ b/src/model/HitboxCircle.java @@ -5,12 +5,22 @@ public class HitboxCircle extends Hitbox { public HitboxCircle(String[] dataHitbox, Entity owner){ super(dataHitbox[0]); + setOwnerEntity(owner); parseStringToCircleHitbox(dataHitbox); } - + public HitboxCircle(String shape, Entity owner){ + super(shape); + setOwnerEntity(owner); + radiusHitbox = 0; + } private void parseStringToCircleHitbox(String[] informations) { referencePoint.x = Float.parseFloat(informations[1]); referencePoint.y = Float.parseFloat(informations[2]); radiusHitbox = Float.parseFloat(informations[3]); } + @Override + public String listPointsToString() { + return "Circle"+referencePoint.x+referencePoint.x+" "+referencePoint.y+" "+radiusHitbox; + } + } diff --git a/src/model/HitboxRectangle.java b/src/model/HitboxRectangle.java index 79474e6..a29b3c1 100644 --- a/src/model/HitboxRectangle.java +++ b/src/model/HitboxRectangle.java @@ -8,7 +8,9 @@ public class HitboxRectangle extends Hitbox { private List listPointsCartesian = new ArrayList(); private float widthHitbox = 0,heightHitbox = 0; // Ширина и высота хитбокса в декартовых координатах. - public HitboxRectangle(){ + public HitboxRectangle(String shape, Entity owner){ + super(shape); + setOwnerEntity(owner); initListsPoints(); } public HitboxRectangle(String shape,List listPointsIso,List listPointsCartesian){ @@ -85,4 +87,8 @@ public class HitboxRectangle extends Hitbox { public List getListPointsCartesian() { return listPointsCartesian; } + @Override + public String listPointsToString() { + return "Rectangle "+referencePoint.x+" "+referencePoint.y+" "+widthHitbox+" "+heightHitbox; + } } diff --git a/src/repository/Project.java b/src/repository/Project.java index 9ceeee3..9ce92d7 100644 --- a/src/repository/Project.java +++ b/src/repository/Project.java @@ -32,6 +32,8 @@ import org.xml.sax.SAXException; import events.EntityDrawboxChangedEvent; import events.EntityDrawboxChangedListener; +import events.EntityHitboxChangedEvent; +import events.EntityHitboxChangedListener; import exception.DuplicateEntryException; import launch.Launcher; import model.Entity; @@ -41,7 +43,7 @@ import model.Entity; * Класс данных, который оперирует их сохранением, загрузкой, и хранением в памяти. * ВАЖНО: данный класс хранит так же актуальную копию XML-представления файла * */ -public class Project implements Iterable, EntityDrawboxChangedListener { +public class Project implements Iterable, EntityDrawboxChangedListener, EntityHitboxChangedListener { /** * Путь к XML по-умолчанию. @@ -125,7 +127,7 @@ public class Project implements Iterable, EntityDrawboxChangedListener { } /** - * Загружает типы сущностей из файла с заданным именем и расположением.
+ * Загружает типы сущностей из файла с заданным именем и расположением.
0 * */ public void load() throws SAXException, IOException, ParserConfigurationException { listEntity.clear(); @@ -237,14 +239,14 @@ public class Project implements Iterable, EntityDrawboxChangedListener { Element drawboxProperty = document.createElement("property"); drawboxProperty.setAttribute("name", "drawbox"); drawboxProperty.setAttribute("type", "string"); - drawboxProperty.setAttribute("default", ""); // empty, because on creation there is no drawbox yet + drawboxProperty.setAttribute("default", "0 0 0 0 0 0 0 0"); // empty, because on creation there is no drawbox yet objecttypeElement.appendChild(drawboxProperty); // format: Element hitboxProperty = document.createElement("property"); hitboxProperty.setAttribute("name", "hitbox"); hitboxProperty.setAttribute("type", "string"); - hitboxProperty.setAttribute("default", ""); // empty, no hitbox yet + hitboxProperty.setAttribute("default", "Rectangle 0 0 0 0"); // empty, no hitbox yet objecttypeElement.appendChild(hitboxProperty); //printXMlToConsole(); //DEBUG! @@ -355,7 +357,27 @@ public class Project implements Iterable, EntityDrawboxChangedListener { //we have hitbox, drawbox and class, gotta set the right one Element propertyElement = ((Element)properties.item(i)); if (propertyElement.getAttribute("name").equals("drawbox")) { - propertyElement.setAttribute("default", event.owner.getDrawbox().toString()); + propertyElement.setAttribute("default", event.owner.getDrawbox().listPointsToString()); + } + } + } + } + + /** + * Получение события при отрисовке нового Hitbox, для изменения XML-дерева. + * Объект event хранит в себе ссылку на новый объект Hitbox и объект entity, для которой он был создан. + * */ + @Override + public void hitboxChanged(EntityHitboxChangedEvent event) { + String entityName = event.owner.getName(); + Node entityToUpdate = getEntityXMLNodeByName(entityName); + NodeList properties = entityToUpdate.getChildNodes(); + for(int i = 0; i < properties.getLength(); i++) { + if(properties.item(i) instanceof Element) { // ignoring #text nodes + //we have hitbox, drawbox and class, gotta set the right one + Element propertyElement = ((Element)properties.item(i)); + if (propertyElement.getAttribute("name").equals("hitbox")) { + propertyElement.setAttribute("default", event.owner.getHitbox().listPointsToString()); } } } @@ -388,6 +410,8 @@ public class Project implements Iterable, EntityDrawboxChangedListener { stripEmptyElements(child); } } + + } //в момент окончания рисования, в зависимости в какой мы рисуем вкладке хитбокса, //в зависимости от того в какой панельке(jpanel)и подклассе интерфейса Editable