/*
** 2013 May 23
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
*/
package info.ata4.bspsrc.modules;
import info.ata4.bsplib.BspFileReader;
import info.ata4.bsplib.entity.Entity;
import info.ata4.bspsrc.VmfWriter;
import info.ata4.bspsrc.modules.entity.Camera;
import info.ata4.log.LogUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* VMF metadata control class.
*
* @author Nico Bergemann <barracuda415 at yahoo.de>
*/
public class VmfMeta extends ModuleDecompile {
// logger
private static final Logger L = LogUtils.getLogger();
// UID mappings
private Map<Integer, Integer> faceUIDs = new HashMap<>();
private Map<Integer, Integer> origFaceUIDs = new HashMap<>();
private Map<Short, Integer> dispinfoUIDs = new HashMap<>();
// UID blacklist
private Set<Integer> uidbl = new HashSet<>();
// VMF unique ID
private int uid = 0;
// visgroup list
private List<String> visgroups = new ArrayList<>();
// camera list
private List<Camera> cameras = new ArrayList<>();
private Entity worldspawn;
private String comment;
public VmfMeta(BspFileReader reader, VmfWriter writer) {
super(reader, writer);
worldspawn = bsp.entities.get(0);
// check for existing map comment
if (worldspawn.getValue("comment") != null) {
L.log(Level.INFO, "Map comment: {0}", worldspawn.getValue("comment"));
}
}
public Set<Integer> getUIDBlackList() {
return uidbl;
}
/**
* Returns a new VMF unique ID.
*
* @return UID
*/
public int getUID() {
if (uidbl.isEmpty()) {
return uid++;
} else {
// increment ID until it's not found in the blacklist anymore
do {
uid++;
} while (uidbl.contains(uid));
return uid;
}
}
/**
* Returns the VMF UID for the corresponding face index.
* It automatically looks up the original face if the split face wasn't found.
*
* @param iface face index
* @return brush side ID or -1 if the index isn't mapped yet
*/
public int getFaceUID(int iface) {
if (faceUIDs.containsKey(iface)) {
return faceUIDs.get(iface);
} else {
// try origface
int ioface = bsp.faces.get(iface).origFace;
if (origFaceUIDs.containsKey(ioface)) {
return origFaceUIDs.get(ioface);
}
}
// not found
return -1;
}
/**
* Sets the VMF UID for the given face index.
*
* @param iface face index
* @param id VMF UID generated by {@link #getUID}
* @return previously mapped UID or <tt>null</tt> if there was no mapping
*/
public Integer setFaceUID(int iface, int id) {
return faceUIDs.put(iface, id);
}
/**
* Sets the VMF UID for the given original face index.
*
* @param iface face index
* @param id VMF UID generated by {@link #getUID}
* @return previously mapped UID or <tt>null</tt> if there was no mapping
*/
public Integer setOrigFaceUID(int iface, int id) {
return origFaceUIDs.put(iface, id);
}
/**
* Returns the VMF UID for the corresponding dispInfo index.
*
* @param idispinfo dispinfo index
* @return brush side ID or -1 if the index isn't mapped yet
*/
public int getDispInfoUID(short idispinfo) {
if (dispinfoUIDs.containsKey(idispinfo)) {
return dispinfoUIDs.get(idispinfo);
}
// not found
return -1;
}
/**
* Sets the VMF UID for the given displacement info index.
*
* @param idispinfo dispinfo index
* @param id VMF UID generated by {@link #getUID}
* @return previously mapped UID or <tt>null</tt> if there was no mapping
*/
public Integer setDispInfoUID(short idispinfo, int id) {
return dispinfoUIDs.put(idispinfo, id);
}
public void setComment(String comment) {
this.comment = comment;
}
public String getComment() {
return comment;
}
/**
* Writes the worldspawn header
*/
public void writeWorldHeader() {
writer.start("world");
writer.put("id", getUID());
writer.put(worldspawn);
// write comment
if (comment != null) {
writer.put("comment", comment);
}
writer.put("classname", "worldspawn");
}
/**
* Writes the worldspawn footer
*/
public void writeWorldFooter() {
writer.end("world");
}
public void writeVisgroups() {
if (visgroups.isEmpty()) {
return;
}
String[] visgroupArray = visgroups.toArray(new String[0]);
writer.start("visgroups");
for (String visgroup : visgroupArray) {
writer.start("visgroup");
writer.put("name", visgroup);
writer.put("visgroupid", visgroups.indexOf(visgroup));
writer.end("visgroup");
}
writer.end("visgroups");
}
public void writeMetaVisgroup(String visgroupName) {
writer.start("editor");
writer.put("visgroupid", getVisgroupID(visgroupName));
writer.end("editor");
}
public void writeMetaVisgroups(List<String> visgroupNames) {
writer.start("editor");
for (String visgroupName : visgroupNames) {
writer.put("visgroupid", getVisgroupID(visgroupName));
}
writer.end("editor");
}
public int getVisgroupID(String visgroupName) {
if (!visgroups.contains(visgroupName)) {
visgroups.add(visgroupName);
}
return visgroups.indexOf(visgroupName);
}
public void writeCameras() {
writer.start("cameras");
if (cameras.isEmpty()) {
writer.put("activecamera", -1);
} else {
writer.put("activecamera", 0);
for (Camera camera : cameras) {
writer.start("camera");
writer.put("position", camera.pos, 2);
writer.put("look", camera.look, 2);
writer.end("camera");
}
}
writer.end("cameras");
}
public List<Camera> getCameras() {
return cameras;
}
}