diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 269 |
1 files changed, 261 insertions, 8 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 185f9ce..580c005 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Timers; | ||
29 | using System.Collections; | 30 | using System.Collections; |
30 | using System.Collections.Generic; | 31 | using System.Collections.Generic; |
31 | using System.IO; | 32 | using System.IO; |
@@ -60,7 +61,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
60 | 61 | ||
61 | public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); | 62 | public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); |
62 | 63 | ||
63 | public delegate void NewInventoryItem(UUID userID, InventoryItemBase item); | 64 | public delegate void NewInventoryItem(UUID userID, InventoryItemBase item, uint cost); |
64 | 65 | ||
65 | public delegate void NewAsset(AssetBase asset); | 66 | public delegate void NewAsset(AssetBase asset); |
66 | 67 | ||
@@ -96,7 +97,10 @@ namespace OpenSim.Region.ClientStack.Linden | |||
96 | // private static readonly string m_fetchInventoryPath = "0006/"; | 97 | // private static readonly string m_fetchInventoryPath = "0006/"; |
97 | private static readonly string m_copyFromNotecardPath = "0007/"; | 98 | private static readonly string m_copyFromNotecardPath = "0007/"; |
98 | // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. | 99 | // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. |
99 | 100 | private static readonly string m_getObjectPhysicsDataPath = "0101/"; | |
101 | private static readonly string m_getObjectCostPath = "0102/"; | ||
102 | private static readonly string m_ResourceCostSelectedPath = "0103/"; | ||
103 | |||
100 | 104 | ||
101 | // These are callbacks which will be setup by the scene so that we can update scene data when we | 105 | // These are callbacks which will be setup by the scene so that we can update scene data when we |
102 | // receive capability calls | 106 | // receive capability calls |
@@ -204,6 +208,14 @@ namespace OpenSim.Region.ClientStack.Linden | |||
204 | m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); | 208 | m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); |
205 | m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); | 209 | m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); |
206 | m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); | 210 | m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); |
211 | IRequestHandler getObjectPhysicsDataHandler = new RestStreamHandler("POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData); | ||
212 | m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler); | ||
213 | IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost); | ||
214 | m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler); | ||
215 | IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected); | ||
216 | m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler); | ||
217 | |||
218 | |||
207 | 219 | ||
208 | m_HostCapsObj.RegisterHandler( | 220 | m_HostCapsObj.RegisterHandler( |
209 | "CopyInventoryFromNotecard", | 221 | "CopyInventoryFromNotecard", |
@@ -375,6 +387,37 @@ namespace OpenSim.Region.ClientStack.Linden | |||
375 | return UUID.Zero; | 387 | return UUID.Zero; |
376 | } | 388 | } |
377 | 389 | ||
390 | private delegate void UploadWithCostCompleteDelegate(string assetName, | ||
391 | string assetDescription, UUID assetID, UUID inventoryItem, | ||
392 | UUID parentFolder, byte[] data, string inventoryType, | ||
393 | string assetType, uint cost); | ||
394 | |||
395 | private class AssetUploaderWithCost : AssetUploader | ||
396 | { | ||
397 | private uint m_cost; | ||
398 | |||
399 | public event UploadWithCostCompleteDelegate OnUpLoad; | ||
400 | |||
401 | public AssetUploaderWithCost(string assetName, string description, UUID assetID, | ||
402 | UUID inventoryItem, UUID parentFolderID, string invType, string assetType, | ||
403 | string path, IHttpServer httpServer, bool dumpAssetsToFile, uint cost) : | ||
404 | base(assetName, description, assetID, inventoryItem, parentFolderID, | ||
405 | invType, assetType, path, httpServer, dumpAssetsToFile) | ||
406 | { | ||
407 | m_cost = cost; | ||
408 | |||
409 | base.OnUpLoad += UploadCompleteHandler; | ||
410 | } | ||
411 | |||
412 | private void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, | ||
413 | UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, | ||
414 | string assetType) | ||
415 | { | ||
416 | OnUpLoad(assetName, assetDescription, assetID, inventoryItem, parentFolder, | ||
417 | data, inventoryType, assetType, m_cost); | ||
418 | } | ||
419 | } | ||
420 | |||
378 | /// <summary> | 421 | /// <summary> |
379 | /// | 422 | /// |
380 | /// </summary> | 423 | /// </summary> |
@@ -385,8 +428,11 @@ namespace OpenSim.Region.ClientStack.Linden | |||
385 | //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString()); | 428 | //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString()); |
386 | //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type); | 429 | //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type); |
387 | 430 | ||
431 | uint cost = 0; | ||
432 | |||
388 | if (llsdRequest.asset_type == "texture" || | 433 | if (llsdRequest.asset_type == "texture" || |
389 | llsdRequest.asset_type == "animation" || | 434 | llsdRequest.asset_type == "animation" || |
435 | llsdRequest.asset_type == "mesh" || | ||
390 | llsdRequest.asset_type == "sound") | 436 | llsdRequest.asset_type == "sound") |
391 | { | 437 | { |
392 | ScenePresence avatar = null; | 438 | ScenePresence avatar = null; |
@@ -417,7 +463,33 @@ namespace OpenSim.Region.ClientStack.Linden | |||
417 | 463 | ||
418 | if (mm != null) | 464 | if (mm != null) |
419 | { | 465 | { |
420 | if (!mm.UploadCovered(client.AgentId, mm.UploadCharge)) | 466 | // XPTO: The cost should be calculated about here |
467 | |||
468 | if (llsdRequest.asset_type == "mesh") | ||
469 | { | ||
470 | cost += 20; // Constant for now to test showing a price | ||
471 | |||
472 | if (llsdRequest.asset_resources == null) | ||
473 | { | ||
474 | client.SendAgentAlertMessage("Unable to upload asset. missing information.", false); | ||
475 | |||
476 | LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); | ||
477 | errorResponse.uploader = ""; | ||
478 | errorResponse.state = "error"; | ||
479 | return errorResponse; | ||
480 | } | ||
481 | |||
482 | uint textures_cost = (uint)llsdRequest.asset_resources.texture_list.Array.Count; | ||
483 | textures_cost *= (uint)mm.UploadCharge; | ||
484 | |||
485 | cost += textures_cost; | ||
486 | } | ||
487 | else | ||
488 | { | ||
489 | cost = (uint)mm.UploadCharge; | ||
490 | } | ||
491 | |||
492 | if (!mm.UploadCovered(client.AgentId, (int)cost)) | ||
421 | { | 493 | { |
422 | client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); | 494 | client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); |
423 | 495 | ||
@@ -438,9 +510,9 @@ namespace OpenSim.Region.ClientStack.Linden | |||
438 | UUID parentFolder = llsdRequest.folder_id; | 510 | UUID parentFolder = llsdRequest.folder_id; |
439 | string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); | 511 | string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); |
440 | 512 | ||
441 | AssetUploader uploader = | 513 | AssetUploaderWithCost uploader = |
442 | new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, | 514 | new AssetUploaderWithCost(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, |
443 | llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); | 515 | llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost); |
444 | 516 | ||
445 | m_HostCapsObj.HttpListener.AddStreamHandler( | 517 | m_HostCapsObj.HttpListener.AddStreamHandler( |
446 | new BinaryStreamHandler( | 518 | new BinaryStreamHandler( |
@@ -458,11 +530,31 @@ namespace OpenSim.Region.ClientStack.Linden | |||
458 | string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + | 530 | string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + |
459 | uploaderPath; | 531 | uploaderPath; |
460 | 532 | ||
533 | |||
461 | LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); | 534 | LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); |
462 | uploadResponse.uploader = uploaderURL; | 535 | uploadResponse.uploader = uploaderURL; |
463 | uploadResponse.state = "upload"; | 536 | uploadResponse.state = "upload"; |
537 | uploadResponse.upload_price = (int)cost; | ||
538 | |||
539 | // use fake values for now | ||
540 | if (llsdRequest.asset_type == "mesh") | ||
541 | { | ||
542 | uploadResponse.data = new LLSDAssetUploadResponseData(); | ||
543 | uploadResponse.data.model_streaming_cost = 1.0; | ||
544 | uploadResponse.data.simulation_cost = 1.5; | ||
545 | |||
546 | uploadResponse.data.physics_cost = 2.0; | ||
547 | uploadResponse.data.resource_cost = 3.0; | ||
548 | uploadResponse.data.upload_price_breakdown.mesh_instance = 1; | ||
549 | uploadResponse.data.upload_price_breakdown.mesh_physics = 2; | ||
550 | uploadResponse.data.upload_price_breakdown.mesh_streaming = 3; | ||
551 | uploadResponse.data.upload_price_breakdown.texture = 5; | ||
552 | uploadResponse.data.upload_price_breakdown.model = 4; | ||
553 | } | ||
554 | |||
464 | uploader.OnUpLoad += UploadCompleteHandler; | 555 | uploader.OnUpLoad += UploadCompleteHandler; |
465 | return uploadResponse; | 556 | return uploadResponse; |
557 | |||
466 | } | 558 | } |
467 | 559 | ||
468 | /// <summary> | 560 | /// <summary> |
@@ -473,7 +565,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
473 | /// <param name="data"></param> | 565 | /// <param name="data"></param> |
474 | public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, | 566 | public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, |
475 | UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, | 567 | UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, |
476 | string assetType) | 568 | string assetType, uint cost) |
477 | { | 569 | { |
478 | m_log.DebugFormat( | 570 | m_log.DebugFormat( |
479 | "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", | 571 | "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", |
@@ -692,7 +784,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
692 | 784 | ||
693 | if (AddNewInventoryItem != null) | 785 | if (AddNewInventoryItem != null) |
694 | { | 786 | { |
695 | AddNewInventoryItem(m_HostCapsObj.AgentID, item); | 787 | AddNewInventoryItem(m_HostCapsObj.AgentID, item, cost); |
696 | } | 788 | } |
697 | } | 789 | } |
698 | 790 | ||
@@ -854,10 +946,158 @@ namespace OpenSim.Region.ClientStack.Linden | |||
854 | response["int_response_code"] = 200; | 946 | response["int_response_code"] = 200; |
855 | return LLSDHelpers.SerialiseLLSDReply(response); | 947 | return LLSDHelpers.SerialiseLLSDReply(response); |
856 | } | 948 | } |
949 | |||
950 | public string GetObjectPhysicsData(string request, string path, | ||
951 | string param, IOSHttpRequest httpRequest, | ||
952 | IOSHttpResponse httpResponse) | ||
953 | { | ||
954 | OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request); | ||
955 | OSDMap resp = new OSDMap(); | ||
956 | OSDArray object_ids = (OSDArray)req["object_ids"]; | ||
957 | |||
958 | for (int i = 0 ; i < object_ids.Count ; i++) | ||
959 | { | ||
960 | UUID uuid = object_ids[i].AsUUID(); | ||
961 | |||
962 | SceneObjectPart obj = m_Scene.GetSceneObjectPart(uuid); | ||
963 | if (obj != null) | ||
964 | { | ||
965 | OSDMap object_data = new OSDMap(); | ||
966 | |||
967 | object_data["PhysicsShapeType"] = obj.PhysicsShapeType; | ||
968 | object_data["Density"] = obj.Density; | ||
969 | object_data["Friction"] = obj.Friction; | ||
970 | object_data["Restitution"] = obj.Bounciness; | ||
971 | object_data["GravityMultiplier"] = obj.GravityModifier; | ||
972 | |||
973 | resp[uuid.ToString()] = object_data; | ||
974 | } | ||
975 | } | ||
976 | |||
977 | string response = OSDParser.SerializeLLSDXmlString(resp); | ||
978 | return response; | ||
979 | } | ||
980 | |||
981 | public string GetObjectCost(string request, string path, | ||
982 | string param, IOSHttpRequest httpRequest, | ||
983 | IOSHttpResponse httpResponse) | ||
984 | { | ||
985 | OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request); | ||
986 | OSDMap resp = new OSDMap(); | ||
987 | |||
988 | OSDArray object_ids = (OSDArray)req["object_ids"]; | ||
989 | |||
990 | for (int i = 0; i < object_ids.Count; i++) | ||
991 | { | ||
992 | UUID uuid = object_ids[i].AsUUID(); | ||
993 | |||
994 | SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid); | ||
995 | |||
996 | if (part != null) | ||
997 | { | ||
998 | SceneObjectGroup grp = part.ParentGroup; | ||
999 | if (grp != null) | ||
1000 | { | ||
1001 | float linksetCost; | ||
1002 | float linksetPhysCost; | ||
1003 | float partCost; | ||
1004 | float partPhysCost; | ||
1005 | |||
1006 | grp.GetResourcesCosts(part, out linksetCost, out linksetPhysCost, out partCost, out partPhysCost); | ||
1007 | |||
1008 | OSDMap object_data = new OSDMap(); | ||
1009 | object_data["linked_set_resource_cost"] = linksetCost; | ||
1010 | object_data["resource_cost"] = partCost; | ||
1011 | object_data["physics_cost"] = partPhysCost; | ||
1012 | object_data["linked_set_physics_cost"] = linksetPhysCost; | ||
1013 | |||
1014 | resp[uuid.ToString()] = object_data; | ||
1015 | } | ||
1016 | } | ||
1017 | } | ||
1018 | |||
1019 | string response = OSDParser.SerializeLLSDXmlString(resp); | ||
1020 | return response; | ||
1021 | } | ||
1022 | |||
1023 | public string ResourceCostSelected(string request, string path, | ||
1024 | string param, IOSHttpRequest httpRequest, | ||
1025 | IOSHttpResponse httpResponse) | ||
1026 | { | ||
1027 | OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request); | ||
1028 | OSDMap resp = new OSDMap(); | ||
1029 | |||
1030 | |||
1031 | float phys=0; | ||
1032 | float stream=0; | ||
1033 | float simul=0; | ||
1034 | |||
1035 | if (req.ContainsKey("selected_roots")) | ||
1036 | { | ||
1037 | OSDArray object_ids = (OSDArray)req["selected_roots"]; | ||
1038 | |||
1039 | // should go by SOG suming costs for all parts | ||
1040 | // ll v3 works ok with several objects select we get the list and adds ok | ||
1041 | // FS calls per object so results are wrong guess fs bug | ||
1042 | for (int i = 0; i < object_ids.Count; i++) | ||
1043 | { | ||
1044 | UUID uuid = object_ids[i].AsUUID(); | ||
1045 | float Physc; | ||
1046 | float simulc; | ||
1047 | float streamc; | ||
1048 | |||
1049 | SceneObjectGroup grp = m_Scene.GetGroupByPrim(uuid); | ||
1050 | if (grp != null) | ||
1051 | { | ||
1052 | grp.GetSelectedCosts(out Physc, out streamc, out simulc); | ||
1053 | phys += Physc; | ||
1054 | stream += streamc; | ||
1055 | simul += simulc; | ||
1056 | } | ||
1057 | } | ||
1058 | } | ||
1059 | else if (req.ContainsKey("selected_prims")) | ||
1060 | { | ||
1061 | OSDArray object_ids = (OSDArray)req["selected_prims"]; | ||
1062 | |||
1063 | // don't see in use in any of the 2 viewers | ||
1064 | // guess it should be for edit linked but... nothing | ||
1065 | // should go to SOP per part | ||
1066 | for (int i = 0; i < object_ids.Count; i++) | ||
1067 | { | ||
1068 | UUID uuid = object_ids[i].AsUUID(); | ||
1069 | |||
1070 | SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid); | ||
1071 | if (part != null) | ||
1072 | { | ||
1073 | phys += part.PhysicsCost; | ||
1074 | stream += part.StreamingCost; | ||
1075 | simul += part.SimulationCost; | ||
1076 | } | ||
1077 | } | ||
1078 | } | ||
1079 | |||
1080 | if (simul != 0) | ||
1081 | { | ||
1082 | OSDMap object_data = new OSDMap(); | ||
1083 | |||
1084 | object_data["physics"] = phys; | ||
1085 | object_data["streaming"] = stream; | ||
1086 | object_data["simulation"] = simul; | ||
1087 | |||
1088 | resp["selected"] = object_data; | ||
1089 | } | ||
1090 | |||
1091 | string response = OSDParser.SerializeLLSDXmlString(resp); | ||
1092 | return response; | ||
1093 | } | ||
857 | } | 1094 | } |
858 | 1095 | ||
859 | public class AssetUploader | 1096 | public class AssetUploader |
860 | { | 1097 | { |
1098 | private static readonly ILog m_log = | ||
1099 | LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
1100 | |||
861 | public event UpLoadedAsset OnUpLoad; | 1101 | public event UpLoadedAsset OnUpLoad; |
862 | private UpLoadedAsset handlerUpLoad = null; | 1102 | private UpLoadedAsset handlerUpLoad = null; |
863 | 1103 | ||
@@ -872,6 +1112,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
872 | 1112 | ||
873 | private string m_invType = String.Empty; | 1113 | private string m_invType = String.Empty; |
874 | private string m_assetType = String.Empty; | 1114 | private string m_assetType = String.Empty; |
1115 | private Timer m_timeoutTimer = new Timer(); | ||
875 | 1116 | ||
876 | public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, | 1117 | public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, |
877 | UUID parentFolderID, string invType, string assetType, string path, | 1118 | UUID parentFolderID, string invType, string assetType, string path, |
@@ -887,6 +1128,11 @@ namespace OpenSim.Region.ClientStack.Linden | |||
887 | m_assetType = assetType; | 1128 | m_assetType = assetType; |
888 | m_invType = invType; | 1129 | m_invType = invType; |
889 | m_dumpAssetsToFile = dumpAssetsToFile; | 1130 | m_dumpAssetsToFile = dumpAssetsToFile; |
1131 | |||
1132 | m_timeoutTimer.Elapsed += TimedOut; | ||
1133 | m_timeoutTimer.Interval = 120000; | ||
1134 | m_timeoutTimer.AutoReset = false; | ||
1135 | m_timeoutTimer.Start(); | ||
890 | } | 1136 | } |
891 | 1137 | ||
892 | /// <summary> | 1138 | /// <summary> |
@@ -908,6 +1154,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
908 | res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); | 1154 | res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); |
909 | 1155 | ||
910 | httpListener.RemoveStreamHandler("POST", uploaderPath); | 1156 | httpListener.RemoveStreamHandler("POST", uploaderPath); |
1157 | m_timeoutTimer.Stop(); | ||
911 | 1158 | ||
912 | // TODO: probably make this a better set of extensions here | 1159 | // TODO: probably make this a better set of extensions here |
913 | string extension = ".jp2"; | 1160 | string extension = ".jp2"; |
@@ -929,6 +1176,12 @@ namespace OpenSim.Region.ClientStack.Linden | |||
929 | return res; | 1176 | return res; |
930 | } | 1177 | } |
931 | 1178 | ||
1179 | private void TimedOut(object sender, ElapsedEventArgs args) | ||
1180 | { | ||
1181 | m_log.InfoFormat("[CAPS]: Removing URL and handler for timed out mesh upload"); | ||
1182 | httpListener.RemoveStreamHandler("POST", uploaderPath); | ||
1183 | } | ||
1184 | |||
932 | ///Left this in and commented in case there are unforseen issues | 1185 | ///Left this in and commented in case there are unforseen issues |
933 | //private void SaveAssetToFile(string filename, byte[] data) | 1186 | //private void SaveAssetToFile(string filename, byte[] data) |
934 | //{ | 1187 | //{ |