static void ParseImagePlist(int firstGid, int tileWidth, int tileHeight, string filename, Dictionary<int, string> gidToFiles, NSDictionary tilesetCaches){
			string path = filename + "-tp.txt";
			NSDictionary plist = null;
			if(tilesetCaches!=null)
				plist = tilesetCaches.objectForKey<NSDictionary>(path);
			if(plist==null)
				plist = NSDictionary.DictionaryWithContentsOfFileFromResources(filename + "-tp.txt");
			NSDictionary metaDataDict = plist.objectForKey<NSDictionary>("metadata");
			NSDictionary framesDict = plist.objectForKey<NSDictionary>("frames");
			int format = 0;
			if (metaDataDict != null) {
				format = metaDataDict.objectForKey<int> ("format");
			}

			int width = 0;
			if (metaDataDict != null) {
				Vector2 size = ccUtils.PointFromString ((string)metaDataDict ["size"]);	
				width = Mathf.RoundToInt(size.x);
			} else {
				NSDictionary texture = metaDataDict.objectForKey<NSDictionary>("texture");
				width = texture.objectForKey<int>("width");
			}
			
			var enumerator = framesDict.GetEnumerator();
			while (enumerator.MoveNext()) {
				KeyValuePair<object, object> frameDictKeyValue = enumerator.Current;
				string frameDictKey = (string)frameDictKeyValue.Key;
				NSDictionary frameDict = (NSDictionary)frameDictKeyValue.Value;
				int x=0, y=0, w=0, h=0;
				if(format == 0) {
					float ox = frameDict.objectForKey<float>("x");
					float oy = frameDict.objectForKey<float>("y");
					float ow = frameDict.objectForKey<float>("width");
					float oh = frameDict.objectForKey<float>("height");
					x = Mathf.RoundToInt(ox);
					y = Mathf.RoundToInt(oy);
					w = Mathf.RoundToInt(ow);
					h = Mathf.RoundToInt(oh);
				} else if(format == 1 || format == 2) {
					Rect frame = ccUtils.RectFromString(frameDict.objectForKey<string>("frame"));
					x = Mathf.RoundToInt(frame.x);
					y = Mathf.RoundToInt(frame.y);
					w = Mathf.RoundToInt(frame.width);
					h = Mathf.RoundToInt(frame.height);
				} else if(format == 3) {
					Rect frame = ccUtils.RectFromString(frameDict.objectForKey<string>("textureRect"));
					x = Mathf.RoundToInt(frame.x);
					y = Mathf.RoundToInt(frame.y);
					w = Mathf.RoundToInt(frame.width);
					h = Mathf.RoundToInt(frame.height);
				}else{
					NSUtils.Assert(false, "cocos2d:CCTMXMap: Uknown TexturePack format.");
				}
				NSUtils.Assert(w==tileWidth && h==tileHeight, "cocos2d:CCTMXMap: Frame size of tileset file must be same with tmx tilesize.");
				int col = Mathf.RoundToInt(x / tileWidth);
				int row = Mathf.RoundToInt(y / tileHeight);
				int cols = Mathf.RoundToInt(width / tileWidth); 
				int gid = firstGid + col + row * cols;
				gidToFiles[gid] = frameDictKey;
			}	
		}
		void addSpriteFrames(NSDictionary dictionary, Sprite[] sprites){
			Dictionary<string ,Sprite> spritesDict = new Dictionary<string, Sprite> ();
			for(int i=0; i<sprites.Length; i++){
				Sprite s = sprites[i];
				spritesDict.Add(s.name, s);			
			}

			NSDictionary metadataDict = dictionary.objectForKey<NSDictionary>("metadata");
			NSDictionary framesDict = dictionary.objectForKey<NSDictionary>("frames");

			int format = 0;
			// get the format
			if (metadataDict != null) {
				format = metadataDict.objectForKey<int> ("format");
			}
			
			
			// SpriteFrame info
//			Rect rect = new Rect();
			bool isRotated = false;
			Vector2 frameOffset = Vector2.zero;
			Vector2 originalSize = Vector2.zero;
			
			// add real frames
			
			var enumerator = framesDict.GetEnumerator();
			while (enumerator.MoveNext()) {
				KeyValuePair<object, object> frameDictKeyValue = enumerator.Current;
				string frameDictKey = (string)frameDictKeyValue.Key;
				NSDictionary frameDict = (NSDictionary)frameDictKeyValue.Value;
				CCSpriteFrame spriteFrame=null;
				if(format == 0) {
//					float x = frameDict.objectForKey<float>("x");
//					float y = frameDict.objectForKey<float>("y");
//					float w = frameDict.objectForKey<float>("width");
//					float h = frameDict.objectForKey<float>("height");
					float ox = frameDict.objectForKey<float>("offsetX");
					float oy = frameDict.objectForKey<float>("offsetY");
					int ow = frameDict.objectForKey<int>("originalWidth");
					int oh = frameDict.objectForKey<int>("originalHeight");
					// check ow/oh
					if(ow==0 || oh==0)
						CCDebug.Warning("cocos2d: WARNING: originalWidth/Height not found on the CCSpriteFrame. AnchorPoint won't work as expected. Regenerate the .plist");
					
					// abs ow/oh
					ow = Math.Abs(ow);
					oh = Math.Abs(oh);
					
					// set frame info
//					rect = new Rect(x, y, w, h);
					isRotated = false;
					frameOffset = new Vector2(ox, oy);
					originalSize = new Vector2(ow, oh);
					
//					if(isRotated)
//						rect.size = new Vector2(rect.size.y, rect.size.x);
				} else if(format == 1 || format == 2) {
//					Rect frame = ccUtils.RectFromString(frameDict.objectForKey<string>("frame"));
					bool rotated = false;
					
					// rotation
					if(format == 2)
						rotated = frameDict.objectForKey<bool>("rotated");
					
					Vector2 offset = ccUtils.PointFromString(frameDict.objectForKey<string>("offset"));
					Vector2 sourceSize = ccUtils.PointFromString(frameDict.objectForKey<string>("sourceSize"));
					
					// set frame info
//					rect = frame;
					isRotated = rotated;
					frameOffset = offset;
					originalSize = sourceSize;
				} else if(format == 3) {
					// get values
//					Vector2 spriteSize = ccUtils.PointFromString(frameDict.objectForKey<string>("spriteSize"));
					Vector2 spriteOffset = ccUtils.PointFromString(frameDict.objectForKey<string>("spriteOffset"));
					Vector2 spriteSourceSize = ccUtils.PointFromString(frameDict.objectForKey<string>("spriteSourceSize"));
//					Rect textureRect = ccUtils.RectFromString(frameDict.objectForKey<string>("textureRect"));
					bool textureRotated = frameDict.objectForKey<bool>("textureRotated");
					
					// get aliases
					NSArray aliases = frameDict.objectForKey<NSArray>("aliases");
					
					var aliasesEnumerator = aliases.GetEnumerator();
					while (aliasesEnumerator.MoveNext()) {
						string alias = (string)aliasesEnumerator.Current;
						if( _spriteFramesAliases.ContainsKey(alias) )
							CCDebug.Warning("cocos2d: WARNING: an alias with name {0} already exists",alias);
						
						_spriteFramesAliases[alias] = frameDictKey;
					}
					
					// set frame info
//					rect = new Rect(textureRect.position.x, textureRect.position.y, spriteSize.x, spriteSize.y);
					isRotated = textureRotated;
					frameOffset = spriteOffset;
					originalSize = spriteSourceSize;
				}
				
				Sprite spt;
				if(!spritesDict.TryGetValue(frameDictKey, out spt)){
					CCDebug.Warning("cocos2d: WARNING: a sprite frame with name {0} not found", frameDictKey);
					continue;
				}
				// add sprite frame
				spriteFrame = new CCSpriteFrame(spt, originalSize, frameOffset, isRotated);
				_spriteFrames.Add(frameDictKey, spriteFrame);
			}
		}
		/** Adds an animation from an NSDictionary
		 Make sure that the frames were previously loaded in the CCSpriteFrameCache.
		 @since v1.1
		 */
		public void addAnimationsWithDictionary(NSDictionary dictionary)
		{
			NSDictionary animations = dictionary.objectForKey<NSDictionary>("animations");
			
			if ( animations == null ) {
				CCDebug.Log("cocos2d: CCAnimationCache: No animations were found in provided dictionary.");
				return;
			}
			
			int version = 1;
			NSDictionary properties = dictionary.objectForKey<NSDictionary>("properties");
			if( properties != null )
				version = properties.objectForKey<int>("format");
			
			NSArray spritesheets = properties.objectForKey<NSArray>("spritesheets");

			var enumerator = spritesheets.GetEnumerator();
			while (enumerator.MoveNext()) {
				string name = (string)enumerator.Current;
				CCSpriteFrameCache.sharedSpriteFrameCache.addSpriteFramesWithFile(name);
			}
			switch (version) {
			case 1:
				parseVersion1(animations);
				break;
			case 2:
				parseVersion2(animations);
				break;
			default:
				NSUtils.Assert(false, "Invalid animation format");
				break;
			}
		}
		void removeSpriteFramesFromDictionary(NSDictionary dictionary)
		{
			NSDictionary framesDict = dictionary.objectForKey<NSDictionary>("frames");
//			List<string> keysToRemove = new List<string> ();

			var enumerator = framesDict.GetEnumerator();
			while (enumerator.MoveNext()) {
				KeyValuePair<object, object> kv = enumerator.Current;
				string frameDictKey = (string)kv.Key;
				_spriteFrames.Remove(frameDictKey);
			}
		}