diff --git a/src/org/infinity/datatype/WmpLinkBitmap.java b/src/org/infinity/datatype/WmpLinkBitmap.java new file mode 100644 index 000000000..3e503cda7 --- /dev/null +++ b/src/org/infinity/datatype/WmpLinkBitmap.java @@ -0,0 +1,61 @@ +// Near Infinity - An Infinity Engine Browser and Editor +// Copyright (C) 2001 Jon Olav Hauglid +// See LICENSE.txt for license information + +package org.infinity.datatype; + +import java.awt.event.ActionListener; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.TreeMap; + +import javax.swing.JComponent; + +import org.infinity.resource.wmp.AreaEntry; +import org.infinity.resource.wmp.AreaLink; +import org.infinity.resource.wmp.MapEntry; + +/** + * A specialized bitmap to represent linked areas in a WMP resource. + *

+ * The bitmap list is lazily populated to avoid performing read-ahead operations. + *

+ */ +public class WmpLinkBitmap extends AbstractBitmap { + public WmpLinkBitmap(ByteBuffer buffer, int offset, int length, String name) { + super(buffer, offset, length, name, new TreeMap<>()); + setFormatter(formatterHashBitmapReverse); + } + + // --------------------- Begin Interface Editable --------------------- + + @Override + public JComponent edit(ActionListener container) { + updateLinkList(); + return super.edit(container); + } + + // --------------------- End Interface Editable --------------------- + + @Override + public String toString() { + updateLinkList(); + return super.toString(); + } + + private void updateLinkList() { + if (getBitmap().isEmpty() && + getParent() instanceof AreaLink && + getParent().getParent() instanceof AreaEntry && + getParent().getParent().getParent() instanceof MapEntry) { + final TreeMap map = getBitmap(); + final MapEntry mapEntry = (MapEntry)getParent().getParent().getParent(); + final List areas = mapEntry.getCachedAreas(); + for (int i = 0, count = areas.size(); i < count; i++) { + final ResourceRef currentArea = (ResourceRef)areas.get(i).getAttribute(AreaEntry.WMP_AREA_CURRENT); + String label = (currentArea != null) ? currentArea.toString() : "[Unknown]"; + map.put(Long.valueOf(i), label); + } + } + } +} diff --git a/src/org/infinity/resource/wmp/AreaLink.java b/src/org/infinity/resource/wmp/AreaLink.java index f569076d2..28fcb9d55 100644 --- a/src/org/infinity/resource/wmp/AreaLink.java +++ b/src/org/infinity/resource/wmp/AreaLink.java @@ -11,6 +11,7 @@ import org.infinity.datatype.ResourceRef; import org.infinity.datatype.TextString; import org.infinity.datatype.Unknown; +import org.infinity.datatype.WmpLinkBitmap; import org.infinity.resource.AbstractStruct; import org.infinity.util.io.StreamUtils; @@ -35,7 +36,8 @@ public AreaLink(AbstractStruct superStruct, ByteBuffer buffer, int offset, Strin @Override public int read(ByteBuffer buffer, int offset) throws Exception { - addField(new DecNumber(buffer, offset, 4, WMP_LINK_TARGET_AREA)); +// addField(new DecNumber(buffer, offset, 4, WMP_LINK_TARGET_AREA)); + addField(new WmpLinkBitmap(buffer, offset, 4, WMP_LINK_TARGET_AREA)); addField(new TextString(buffer, offset + 4, 32, WMP_LINK_TARGET_ENTRANCE)); addField(new DecNumber(buffer, offset + 36, 4, WMP_LINK_DISTANCE_SCALE)); addField(new Flag(buffer, offset + 40, 4, WMP_LINK_DEFAULT_ENTRANCE, ENTRANCE_ARRAY)); diff --git a/src/org/infinity/resource/wmp/MapEntry.java b/src/org/infinity/resource/wmp/MapEntry.java index b7672c6f4..3848379c1 100644 --- a/src/org/infinity/resource/wmp/MapEntry.java +++ b/src/org/infinity/resource/wmp/MapEntry.java @@ -5,6 +5,9 @@ package org.infinity.resource.wmp; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import javax.swing.JComponent; @@ -40,6 +43,8 @@ public class MapEntry extends AbstractStruct implements HasViewerTabs { private static final String[] FLAGS_ARRAY = { "No flags set", "Colored icon", "Ignore palette" }; + private List areaCache; + public MapEntry(AbstractStruct superStruct, ByteBuffer buffer, int offset, int nr) throws Exception { super(superStruct, WMP_MAP + " " + nr, buffer, offset); } @@ -103,9 +108,29 @@ public int read(ByteBuffer buffer, int offset) throws Exception { AreaEntry areaEntry = new AreaEntry(this, buffer, curOfs, i); curOfs = areaEntry.getEndOffset(); addField(areaEntry); + addCachedArea(areaEntry); areaEntry.readLinks(buffer, linkOffset); } return offset + 128 + 56; } + + /** Provides quick read access to available {@link AreaEntry} instances. */ + public List getCachedAreas() { + ensureCachedArea(); + return Collections.unmodifiableList(areaCache); + } + + private void addCachedArea(AreaEntry areaEntry) { + ensureCachedArea(); + if (areaEntry != null) { + areaCache.add(areaEntry); + } + } + + private void ensureCachedArea() { + if (areaCache == null) { + areaCache = new ArrayList<>(); + } + } }