#include "stdafx.h" #include "convert.h" #include "rmgen.h" #include "simpleconstraints.h" #include "simplepainters.h" #include "rectplacer.h" #include "layeredpainter.h" #include "clumpplacer.h" #include "smoothelevationpainter.h" #include "simplegroup.h" using namespace std; bool GetTileClassField(JSContext* cx, jsval obj, const char* name, TileClass*& ret) { jsval val; if(!GetJsvalField(cx, obj, name, val)) return false; if(JSVAL_IS_NULL(val)) { ret = 0; return true; } if(!JSVAL_IS_INT(val)) return false; int id = JSVAL_TO_INT(val); if(id < 0 || id > theMap->tileClasses.size()) return false; ret = (id==0? 0 : theMap->tileClasses[id-1]); return true; } int GetType(JSContext* cx, jsval val) { int ret; if(!GetIntField(cx, val, "TYPE", ret)) return 0; return ret; } bool GetIntField(JSContext* cx, jsval obj, const char* name, int& ret) { jsval val; if(!GetJsvalField(cx, obj, name, val)) return false; if(!JSVAL_IS_INT(val)) return false; ret = JSVAL_TO_INT(val); return true; } bool GetBoolField(JSContext* cx, jsval obj, const char* name, bool& ret) { jsval val; if(!GetJsvalField(cx, obj, name, val)) return false; if(!JSVAL_IS_BOOLEAN(val)) return false; ret = JSVAL_TO_BOOLEAN(val); return true; } bool GetFloatField(JSContext* cx, jsval obj, const char* name, float& ret) { jsval val; if(!GetJsvalField(cx, obj, name, val)) return false; if(!JSVAL_IS_NUMBER(val)) return false; jsdouble jsdbl; JS_ValueToNumber(cx, val, &jsdbl); ret = jsdbl; return true; } bool GetStringField(JSContext* cx, jsval obj, const char* name, std::string& ret) { jsval val; if(!GetJsvalField(cx, obj, name, val)) return false; if(!JSVAL_IS_STRING(val)) return false; ret = JS_GetStringBytes(JSVAL_TO_STRING(val)); return true; } bool GetArrayField(JSContext* cx, jsval obj, const char* name, std::vector& ret) { ret.clear(); jsval val; if(!GetJsvalField(cx, obj, name, val)) return false; if(!ParseArray(cx, val, ret)) return false; return true; } bool GetJsvalField(JSContext* cx, jsval obj, const char* name, jsval& ret) { if(!JSVAL_IS_OBJECT(obj)) return false; JSObject* fieldObj = JSVAL_TO_OBJECT(obj); return JS_GetProperty(cx, fieldObj, name, &ret); } bool ParseArray(JSContext* cx, jsval val, vector& ret) { ret.clear(); if(!JSVAL_IS_OBJECT(val)) return false; JSObject* obj = JSVAL_TO_OBJECT(val); if(!JS_IsArrayObject(cx, obj)) return false; jsuint len; JS_GetArrayLength(cx, obj, &len); for(int i=0; i array; jsval jsv, jsv2; Terrain* terrain = 0; float elevation; int type; int blendRadius; TileClass* tileClass; vector terrains; vector widths; if(ParseArray(cx, val, array)) { // MultiPainter is encoded as an array of painters vector painters(array.size()); for(int i=0; i array; int x, y; bool avoidSelf; TileClass* tileClass; vector elements; switch(GetType(cx, val)) { case TYPE_SIMPLE_GROUP: // convert x and y if(!GetIntField(cx, val, "x", x)) return 0; if(!GetIntField(cx, val, "y", y)) return 0; if(!GetBoolField(cx, val, "avoidSelf", avoidSelf)) return 0; if(!GetTileClassField(cx, val, "tileClass", tileClass)) return 0; // convert the elements (which will be JS SimpleElement objects) if(!GetJsvalField(cx, val, "elements", jsv)) return 0; if(!ParseArray(cx, jsv, array)) return 0; elements.resize(array.size()); for(int i=0; i array; int areaId; TileClass* tileClass; float distance; float distance2; string texture; jsval jsv, jsv2; if(JSVAL_IS_NULL(val)) { // convenience way of specifying a NullConstraint return new NullConstraint(); } if(ParseArray(cx, val, array)) { // AndConstraint is encoded as an array of constraints vector constraints(array.size()); for(int i=0; i theMap->areas.size()) return 0; return new AvoidAreaConstraint(theMap->areas[areaId-1]); case TYPE_AVOID_TEXTURE_CONSTRAINT: if(!GetStringField(cx, val, "texture", texture)) return 0; return new AvoidTextureConstraint(theMap->getId(texture)); case TYPE_AVOID_TILE_CLASS_CONSTRAINT: if(!GetFloatField(cx, val, "distance", distance)) return 0; if(!GetTileClassField(cx, val, "tileClass", tileClass)) return 0; return new AvoidTileClassConstraint(tileClass, distance); case TYPE_STAY_IN_TILE_CLASS_CONSTRAINT: if(!GetFloatField(cx, val, "distance", distance)) return 0; if(!GetTileClassField(cx, val, "tileClass", tileClass)) return 0; return new StayInTileClassConstraint(tileClass, distance); case TYPE_BORDER_TILE_CLASS_CONSTRAINT: if(!GetFloatField(cx, val, "distanceInside", distance)) return 0; if(!GetFloatField(cx, val, "distanceOutside", distance2)) return 0; if(!GetTileClassField(cx, val, "tileClass", tileClass)) return 0; return new BorderTileClassConstraint(tileClass, distance, distance2); default: return 0; } } Terrain* ParseTerrain(JSContext* cx, jsval val) { vector array; if(JSVAL_IS_STRING(val)) { // simple terrains are just encoded as strings string str = JS_GetStringBytes(JS_ValueToString(cx, val)); return SimpleTerrain::parse(str); } if(ParseArray(cx, val, array)) { // RandomTerrain is encoded as an array of terrains vector terrains(array.size()); for(int i=0; i