aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps
diff options
context:
space:
mode:
authorUbitUmarov2015-09-01 14:54:35 +0100
committerUbitUmarov2015-09-01 14:54:35 +0100
commit371c9dd2af01a2e7422ec901ee1f80757284a78c (patch)
tree058d2a513cacb12efcce0c0df0ae14ad135dbfe2 /OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps
parentremove lixo (diff)
parentdont change camera on crossings (diff)
downloadopensim-SC_OLD-371c9dd2af01a2e7422ec901ee1f80757284a78c.zip
opensim-SC_OLD-371c9dd2af01a2e7422ec901ee1f80757284a78c.tar.gz
opensim-SC_OLD-371c9dd2af01a2e7422ec901ee1f80757284a78c.tar.bz2
opensim-SC_OLD-371c9dd2af01a2e7422ec901ee1f80757284a78c.tar.xz
bad merge?
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs978
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs703
2 files changed, 1554 insertions, 127 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 774202e..4e6d196 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
28using System; 28using System;
29using System.Timers;
29using System.Collections; 30using System.Collections;
30using System.Collections.Generic; 31using System.Collections.Generic;
31using System.IO; 32using System.IO;
@@ -55,14 +56,16 @@ using PermissionMask = OpenSim.Framework.PermissionMask;
55namespace OpenSim.Region.ClientStack.Linden 56namespace OpenSim.Region.ClientStack.Linden
56{ 57{
57 public delegate void UpLoadedAsset( 58 public delegate void UpLoadedAsset(
58 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, 59 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
59 byte[] data, string inventoryType, string assetType); 60 byte[] data, string inventoryType, string assetType,
61 int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
62 bool IsAtestUpload, ref string error);
60 63
61 public delegate UUID UpdateItem(UUID itemID, byte[] data); 64 public delegate UUID UpdateItem(UUID itemID, byte[] data);
62 65
63 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); 66 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
64 67
65 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item); 68 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item, uint cost);
66 69
67 public delegate void NewAsset(AssetBase asset); 70 public delegate void NewAsset(AssetBase asset);
68 71
@@ -88,6 +91,7 @@ namespace OpenSim.Region.ClientStack.Linden
88 91
89 private Scene m_Scene; 92 private Scene m_Scene;
90 private Caps m_HostCapsObj; 93 private Caps m_HostCapsObj;
94 private ModelCost m_ModelCost;
91 95
92 private static readonly string m_requestPath = "0000/"; 96 private static readonly string m_requestPath = "0000/";
93 // private static readonly string m_mapLayerPath = "0001/"; 97 // private static readonly string m_mapLayerPath = "0001/";
@@ -99,8 +103,10 @@ namespace OpenSim.Region.ClientStack.Linden
99 private static readonly string m_copyFromNotecardPath = "0007/"; 103 private static readonly string m_copyFromNotecardPath = "0007/";
100 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. 104 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
101 private static readonly string m_getObjectPhysicsDataPath = "0101/"; 105 private static readonly string m_getObjectPhysicsDataPath = "0101/";
102 /* 0102 - 0103 RESERVED */ 106 private static readonly string m_getObjectCostPath = "0102/";
107 private static readonly string m_ResourceCostSelectedPath = "0103/";
103 private static readonly string m_UpdateAgentInformationPath = "0500/"; 108 private static readonly string m_UpdateAgentInformationPath = "0500/";
109 private static readonly string m_animSetTaskUpdatePath = "0260/";
104 110
105 // These are callbacks which will be setup by the scene so that we can update scene data when we 111 // These are callbacks which will be setup by the scene so that we can update scene data when we
106 // receive capability calls 112 // receive capability calls
@@ -115,12 +121,50 @@ namespace OpenSim.Region.ClientStack.Linden
115 private IAssetService m_assetService; 121 private IAssetService m_assetService;
116 private bool m_dumpAssetsToFile = false; 122 private bool m_dumpAssetsToFile = false;
117 private string m_regionName; 123 private string m_regionName;
124
118 private int m_levelUpload = 0; 125 private int m_levelUpload = 0;
119 126
127 private bool m_enableFreeTestUpload = false; // allows "TEST-" prefix hack
128 private bool m_ForceFreeTestUpload = false; // forces all uploads to be test
129
130 private bool m_enableModelUploadTextureToInventory = false; // place uploaded textures also in inventory
131 // may not be visible till relog
132
133 private bool m_RestrictFreeTestUploadPerms = false; // reduces also the permitions. Needs a creator defined!!
134 private UUID m_testAssetsCreatorID = UUID.Zero;
135
136 private float m_PrimScaleMin = 0.001f;
137
138 private enum FileAgentInventoryState : int
139 {
140 idle = 0,
141 processRequest = 1,
142 waitUpload = 2,
143 processUpload = 3
144 }
145 private FileAgentInventoryState m_FileAgentInventoryState = FileAgentInventoryState.idle;
146
120 public BunchOfCaps(Scene scene, Caps caps) 147 public BunchOfCaps(Scene scene, Caps caps)
121 { 148 {
122 m_Scene = scene; 149 m_Scene = scene;
123 m_HostCapsObj = caps; 150 m_HostCapsObj = caps;
151
152 // create a model upload cost provider
153 m_ModelCost = new ModelCost();
154 // tell it about scene object limits
155 m_ModelCost.NonPhysicalPrimScaleMax = m_Scene.m_maxNonphys;
156 m_ModelCost.PhysicalPrimScaleMax = m_Scene.m_maxPhys;
157
158// m_ModelCost.ObjectLinkedPartsMax = ??
159// m_ModelCost.PrimScaleMin = ??
160
161 m_PrimScaleMin = m_ModelCost.PrimScaleMin;
162 float modelTextureUploadFactor = m_ModelCost.ModelTextureCostFactor;
163 float modelUploadFactor = m_ModelCost.ModelMeshCostFactor;
164 float modelMinUploadCostFactor = m_ModelCost.ModelMinCostFactor;
165 float modelPrimCreationCost = m_ModelCost.primCreationCost;
166 float modelMeshByteCost = m_ModelCost.bytecost;
167
124 IConfigSource config = m_Scene.Config; 168 IConfigSource config = m_Scene.Config;
125 if (config != null) 169 if (config != null)
126 { 170 {
@@ -135,6 +179,37 @@ namespace OpenSim.Region.ClientStack.Linden
135 { 179 {
136 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); 180 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
137 } 181 }
182 // economy for model upload
183 IConfig EconomyConfig = config.Configs["Economy"];
184 if (EconomyConfig != null)
185 {
186 modelUploadFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", modelUploadFactor);
187 modelTextureUploadFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", modelTextureUploadFactor);
188 modelMinUploadCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", modelMinUploadCostFactor);
189 // next 2 are normalized so final cost is afected by modelUploadFactor above and normal cost
190 modelPrimCreationCost = EconomyConfig.GetFloat("ModelPrimCreationCost", modelPrimCreationCost);
191 modelMeshByteCost = EconomyConfig.GetFloat("ModelMeshByteCost", modelMeshByteCost);
192
193 m_enableModelUploadTextureToInventory = EconomyConfig.GetBoolean("MeshModelAllowTextureToInventory", m_enableModelUploadTextureToInventory);
194
195 m_RestrictFreeTestUploadPerms = EconomyConfig.GetBoolean("m_RestrictFreeTestUploadPerms", m_RestrictFreeTestUploadPerms);
196 m_enableFreeTestUpload = EconomyConfig.GetBoolean("AllowFreeTestUpload", m_enableFreeTestUpload);
197 m_ForceFreeTestUpload = EconomyConfig.GetBoolean("ForceFreeTestUpload", m_ForceFreeTestUpload);
198 string testcreator = EconomyConfig.GetString("TestAssetsCreatorID", "");
199 if (testcreator != "")
200 {
201 UUID id;
202 UUID.TryParse(testcreator, out id);
203 if (id != null)
204 m_testAssetsCreatorID = id;
205 }
206
207 m_ModelCost.ModelMeshCostFactor = modelUploadFactor;
208 m_ModelCost.ModelTextureCostFactor = modelTextureUploadFactor;
209 m_ModelCost.ModelMinCostFactor = modelMinUploadCostFactor;
210 m_ModelCost.primCreationCost = modelPrimCreationCost;
211 m_ModelCost.bytecost = modelMeshByteCost;
212 }
138 } 213 }
139 214
140 m_assetService = m_Scene.AssetService; 215 m_assetService = m_Scene.AssetService;
@@ -146,6 +221,8 @@ namespace OpenSim.Region.ClientStack.Linden
146 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset; 221 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset;
147 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset; 222 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
148 GetClient = m_Scene.SceneGraph.GetControllingClient; 223 GetClient = m_Scene.SceneGraph.GetControllingClient;
224
225 m_FileAgentInventoryState = FileAgentInventoryState.idle;
149 } 226 }
150 227
151 /// <summary> 228 /// <summary>
@@ -173,13 +250,31 @@ namespace OpenSim.Region.ClientStack.Linden
173 //m_capsHandlers["MapLayer"] = 250 //m_capsHandlers["MapLayer"] =
174 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST", 251 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
175 // capsBase + m_mapLayerPath, 252 // capsBase + m_mapLayerPath,
176 // GetMapLayer); 253 // GetMapLayer);
254
255 IRequestHandler getObjectPhysicsDataHandler
256 = new RestStreamHandler(
257 "POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData, "GetObjectPhysicsData", null);
258 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
259
260 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost);
261 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler);
262 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected);
263 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
264
265
177 IRequestHandler req 266 IRequestHandler req
178 = new RestStreamHandler( 267 = new RestStreamHandler(
179 "POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory, "UpdateScript", null); 268 "POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory, "UpdateScript", null);
180 269
181 m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req); 270 m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req);
182 m_HostCapsObj.RegisterHandler("UpdateScriptTask", req); 271 m_HostCapsObj.RegisterHandler("UpdateScriptTask", req);
272
273// IRequestHandler animSetRequestHandler
274// = new RestStreamHandler(
275// "POST", capsBase + m_animSetTaskUpdatePath, AnimSetTaskInventory, "UpdateScript", null);
276
277// m_HostCapsObj.RegisterHandler("UpdateAnimSetTaskInventory", animSetRequestHandler);
183 } 278 }
184 catch (Exception e) 279 catch (Exception e)
185 { 280 {
@@ -191,7 +286,6 @@ namespace OpenSim.Region.ClientStack.Linden
191 { 286 {
192 try 287 try
193 { 288 {
194 // I don't think this one works...
195 m_HostCapsObj.RegisterHandler( 289 m_HostCapsObj.RegisterHandler(
196 "NewFileAgentInventory", 290 "NewFileAgentInventory",
197 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>( 291 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>(
@@ -206,13 +300,11 @@ namespace OpenSim.Region.ClientStack.Linden
206 "POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory, "Update*", null); 300 "POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory, "Update*", null);
207 301
208 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); 302 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
303 m_HostCapsObj.RegisterHandler("UpdateAnimSetAgentInventory", req);
209 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); 304 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
210 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); 305 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
211 306
212 IRequestHandler getObjectPhysicsDataHandler 307
213 = new RestStreamHandler(
214 "POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData, "GetObjectPhysicsData", null);
215 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
216 308
217 IRequestHandler UpdateAgentInformationHandler 309 IRequestHandler UpdateAgentInformationHandler
218 = new RestStreamHandler( 310 = new RestStreamHandler(
@@ -271,6 +363,9 @@ namespace OpenSim.Region.ClientStack.Linden
271// m_log.DebugFormat( 363// m_log.DebugFormat(
272// "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID); 364// "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
273 365
366 if (!m_HostCapsObj.WaitForActivation())
367 return string.Empty;
368
274 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) 369 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
275 { 370 {
276 m_log.WarnFormat( 371 m_log.WarnFormat(
@@ -400,62 +495,178 @@ namespace OpenSim.Region.ClientStack.Linden
400 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString()); 495 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
401 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type); 496 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
402 497
498 // start by getting the client
499 IClientAPI client = null;
500 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
501
502 // check current state so we only have one service at a time
503 lock (m_ModelCost)
504 {
505 switch (m_FileAgentInventoryState)
506 {
507 case FileAgentInventoryState.processRequest:
508 case FileAgentInventoryState.processUpload:
509 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
510 resperror.message = "Uploader busy processing previus request";
511 resperror.identifier = UUID.Zero;
512
513 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
514 errorResponse.uploader = "";
515 errorResponse.state = "error";
516 errorResponse.error = resperror;
517 return errorResponse;
518 break;
519 case FileAgentInventoryState.waitUpload:
520 // todo stop current uploader server
521 break;
522 case FileAgentInventoryState.idle:
523 default:
524 break;
525 }
526
527 m_FileAgentInventoryState = FileAgentInventoryState.processRequest;
528 }
529
530 int cost = 0;
531 int nreqtextures = 0;
532 int nreqmeshs= 0;
533 int nreqinstances = 0;
534 bool IsAtestUpload = false;
535
536 string assetName = llsdRequest.name;
537
538 LLSDAssetUploadResponseData meshcostdata = new LLSDAssetUploadResponseData();
539
403 if (llsdRequest.asset_type == "texture" || 540 if (llsdRequest.asset_type == "texture" ||
404 llsdRequest.asset_type == "animation" || 541 llsdRequest.asset_type == "animation" ||
542 llsdRequest.asset_type == "animatn" || // this is the asset name actually used by viewers
543 llsdRequest.asset_type == "mesh" ||
405 llsdRequest.asset_type == "sound") 544 llsdRequest.asset_type == "sound")
406 { 545 {
407 ScenePresence avatar = null; 546 ScenePresence avatar = null;
408 IClientAPI client = null;
409 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar); 547 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar);
410 548
411 // check user level 549 // check user level
412 if (avatar != null) 550 if (avatar != null)
413 { 551 {
414 client = avatar.ControllingClient;
415
416 if (avatar.UserLevel < m_levelUpload) 552 if (avatar.UserLevel < m_levelUpload)
417 { 553 {
418 if (client != null) 554 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
419 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false); 555 resperror.message = "Insufficient permissions to upload";
556 resperror.identifier = UUID.Zero;
420 557
421 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 558 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
422 errorResponse.uploader = ""; 559 errorResponse.uploader = "";
423 errorResponse.state = "error"; 560 errorResponse.state = "error";
561 errorResponse.error = resperror;
562 lock (m_ModelCost)
563 m_FileAgentInventoryState = FileAgentInventoryState.idle;
424 return errorResponse; 564 return errorResponse;
425 } 565 }
426 } 566 }
427 567
428 // check funds 568 // check test upload and funds
429 if (client != null) 569 if (client != null)
430 { 570 {
431 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>(); 571 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
432 572
573 int baseCost = 0;
433 if (mm != null) 574 if (mm != null)
575 baseCost = mm.UploadCharge;
576
577 string warning = String.Empty;
578
579 if (llsdRequest.asset_type == "mesh")
434 { 580 {
435 if (!mm.UploadCovered(client.AgentId, mm.UploadCharge)) 581 string error;
582 int modelcost;
583
584
585 if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost,
586 meshcostdata, out error, ref warning))
436 { 587 {
437 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); 588 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
589 resperror.message = error;
590 resperror.identifier = UUID.Zero;
438 591
439 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 592 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
440 errorResponse.uploader = ""; 593 errorResponse.uploader = "";
441 errorResponse.state = "error"; 594 errorResponse.state = "error";
595 errorResponse.error = resperror;
596
597 lock (m_ModelCost)
598 m_FileAgentInventoryState = FileAgentInventoryState.idle;
442 return errorResponse; 599 return errorResponse;
443 } 600 }
601 cost = modelcost;
444 } 602 }
603 else
604 {
605 cost = baseCost;
606 }
607
608 if (cost > 0 && mm != null)
609 {
610 // check for test upload
611
612 if (m_ForceFreeTestUpload) // all are test
613 {
614 if (!(assetName.Length > 5 && assetName.StartsWith("TEST-"))) // has normal name lets change it
615 assetName = "TEST-" + assetName;
616
617 IsAtestUpload = true;
618 }
619
620 else if (m_enableFreeTestUpload) // only if prefixed with "TEST-"
621 {
622
623 IsAtestUpload = (assetName.Length > 5 && assetName.StartsWith("TEST-"));
624 }
625
626
627 if(IsAtestUpload) // let user know, still showing cost estimation
628 warning += "Upload will have no cost, for testing purposes only. Other uses are prohibited. Items will not work after 48 hours or on other regions";
629
630 // check funds
631 else
632 {
633 if (!mm.UploadCovered(client.AgentId, (int)cost))
634 {
635 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
636 resperror.message = "Insuficient funds";
637 resperror.identifier = UUID.Zero;
638
639 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
640 errorResponse.uploader = "";
641 errorResponse.state = "error";
642 errorResponse.error = resperror;
643 lock (m_ModelCost)
644 m_FileAgentInventoryState = FileAgentInventoryState.idle;
645 return errorResponse;
646 }
647 }
648 }
649
650 if (client != null && warning != String.Empty)
651 client.SendAgentAlertMessage(warning, true);
445 } 652 }
446 } 653 }
447 654
448 string assetName = llsdRequest.name;
449 string assetDes = llsdRequest.description; 655 string assetDes = llsdRequest.description;
450 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; 656 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
451 UUID newAsset = UUID.Random(); 657 UUID newAsset = UUID.Random();
452 UUID newInvItem = UUID.Random(); 658 UUID newInvItem = UUID.Random();
453 UUID parentFolder = llsdRequest.folder_id; 659 UUID parentFolder = llsdRequest.folder_id;
454 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); 660 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
661 UUID texturesFolder = UUID.Zero;
662
663 if(!IsAtestUpload && m_enableModelUploadTextureToInventory)
664 texturesFolder = llsdRequest.texture_folder_id;
455 665
456 AssetUploader uploader = 666 AssetUploader uploader =
457 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, 667 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
458 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); 668 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost,
669 texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload);
459 670
460 m_HostCapsObj.HttpListener.AddStreamHandler( 671 m_HostCapsObj.HttpListener.AddStreamHandler(
461 new BinaryStreamHandler( 672 new BinaryStreamHandler(
@@ -473,10 +684,22 @@ namespace OpenSim.Region.ClientStack.Linden
473 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + 684 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
474 uploaderPath; 685 uploaderPath;
475 686
687
476 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); 688 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
477 uploadResponse.uploader = uploaderURL; 689 uploadResponse.uploader = uploaderURL;
478 uploadResponse.state = "upload"; 690 uploadResponse.state = "upload";
691 uploadResponse.upload_price = (int)cost;
692
693 if (llsdRequest.asset_type == "mesh")
694 {
695 uploadResponse.data = meshcostdata;
696 }
697
479 uploader.OnUpLoad += UploadCompleteHandler; 698 uploader.OnUpLoad += UploadCompleteHandler;
699
700 lock (m_ModelCost)
701 m_FileAgentInventoryState = FileAgentInventoryState.waitUpload;
702
480 return uploadResponse; 703 return uploadResponse;
481 } 704 }
482 705
@@ -488,8 +711,14 @@ namespace OpenSim.Region.ClientStack.Linden
488 /// <param name="data"></param> 711 /// <param name="data"></param>
489 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, 712 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
490 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, 713 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
491 string assetType) 714 string assetType, int cost,
715 UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
716 bool IsAtestUpload, ref string error)
492 { 717 {
718
719 lock (m_ModelCost)
720 m_FileAgentInventoryState = FileAgentInventoryState.processUpload;
721
493 m_log.DebugFormat( 722 m_log.DebugFormat(
494 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", 723 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}",
495 assetID, inventoryItem, inventoryType, assetType); 724 assetID, inventoryItem, inventoryType, assetType);
@@ -497,6 +726,34 @@ namespace OpenSim.Region.ClientStack.Linden
497 sbyte assType = 0; 726 sbyte assType = 0;
498 sbyte inType = 0; 727 sbyte inType = 0;
499 728
729 IClientAPI client = null;
730
731 UUID owner_id = m_HostCapsObj.AgentID;
732 UUID creatorID;
733
734 bool istest = IsAtestUpload && m_enableFreeTestUpload && (cost > 0);
735
736 bool restrictPerms = m_RestrictFreeTestUploadPerms && istest;
737
738 if (istest && m_testAssetsCreatorID != UUID.Zero)
739 creatorID = m_testAssetsCreatorID;
740 else
741 creatorID = owner_id;
742
743 string creatorIDstr = creatorID.ToString();
744
745 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
746 if (mm != null)
747 {
748 // make sure client still has enougth credit
749 if (!mm.UploadCovered(m_HostCapsObj.AgentID, (int)cost))
750 {
751 error = "Insufficient funds.";
752 return;
753 }
754 }
755
756 // strings to types
500 if (inventoryType == "sound") 757 if (inventoryType == "sound")
501 { 758 {
502 inType = (sbyte)InventoryType.Sound; 759 inType = (sbyte)InventoryType.Sound;
@@ -511,6 +768,12 @@ namespace OpenSim.Region.ClientStack.Linden
511 inType = (sbyte)InventoryType.Animation; 768 inType = (sbyte)InventoryType.Animation;
512 assType = (sbyte)AssetType.Animation; 769 assType = (sbyte)AssetType.Animation;
513 } 770 }
771 else if (inventoryType == "animset")
772 {
773 inType = (sbyte)CustomInventoryType.AnimationSet;
774 assType = (sbyte)CustomAssetType.AnimationSet;
775 m_log.Debug("got animset upload request");
776 }
514 else if (inventoryType == "wearable") 777 else if (inventoryType == "wearable")
515 { 778 {
516 inType = (sbyte)InventoryType.Wearable; 779 inType = (sbyte)InventoryType.Wearable;
@@ -526,6 +789,7 @@ namespace OpenSim.Region.ClientStack.Linden
526 } 789 }
527 else if (inventoryType == "object") 790 else if (inventoryType == "object")
528 { 791 {
792<<<<<<< HEAD
529 inType = (sbyte)InventoryType.Object; 793 inType = (sbyte)InventoryType.Object;
530 assType = (sbyte)AssetType.Object; 794 assType = (sbyte)AssetType.Object;
531 795
@@ -612,73 +876,255 @@ namespace OpenSim.Region.ClientStack.Linden
612 { 876 {
613 clientInv.SendBulkUpdateInventory(foldersToUpdate.ToArray(), itemsToUpdate.ToArray()); 877 clientInv.SendBulkUpdateInventory(foldersToUpdate.ToArray(), itemsToUpdate.ToArray());
614 } 878 }
615 879=======
616 for (int i = 0; i < mesh_list.Count; i++) 880 if (assetType == "mesh") // this code for now is for mesh models uploads only
617 { 881 {
618 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); 882 inType = (sbyte)InventoryType.Object;
883 assType = (sbyte)AssetType.Object;
884>>>>>>> avn/ubitvar
619 885
620 Primitive.TextureEntry textureEntry 886 List<Vector3> positions = new List<Vector3>();
621 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE); 887 List<Quaternion> rotations = new List<Quaternion>();
622 OSDMap inner_instance_list = (OSDMap)instance_list[i]; 888 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
889
890 // compare and get updated information
891/* does nothing still we do need something to avoid special viewer to upload something diferent from the cost estimation
892 bool mismatchError = true;
893
894 while (mismatchError)
895 {
896 mismatchError = false;
897 }
623 898
624 OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; 899 if (mismatchError)
625 for (uint face = 0; face < face_list.Count; face++)
626 { 900 {
627 OSDMap faceMap = (OSDMap)face_list[(int)face]; 901 error = "Upload and fee estimation information don't match";
628 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face); 902 lock (m_ModelCost)
629 if(faceMap.ContainsKey("fullbright")) 903 m_FileAgentInventoryState = FileAgentInventoryState.idle;
630 f.Fullbright = faceMap["fullbright"].AsBoolean();
631 if (faceMap.ContainsKey ("diffuse_color"))
632 f.RGBA = faceMap["diffuse_color"].AsColor4();
633 904
634 int textureNum = faceMap["image"].AsInteger(); 905 return;
635 float imagerot = faceMap["imagerot"].AsInteger(); 906 }
636 float offsets = (float)faceMap["offsets"].AsReal(); 907*/
637 float offsett = (float)faceMap["offsett"].AsReal(); 908 OSDArray instance_list = (OSDArray)request["instance_list"];
638 float scales = (float)faceMap["scales"].AsReal(); 909 OSDArray mesh_list = (OSDArray)request["mesh_list"];
639 float scalet = (float)faceMap["scalet"].AsReal(); 910 OSDArray texture_list = (OSDArray)request["texture_list"];
911 SceneObjectGroup grp = null;
640 912
641 if(imagerot != 0) 913 // create and store texture assets
642 f.Rotation = imagerot; 914 bool doTextInv = (!istest && m_enableModelUploadTextureToInventory &&
915 texturesFolder != UUID.Zero);
643 916
644 if(offsets != 0)
645 f.OffsetU = offsets;
646 917
647 if (offsett != 0) 918 List<UUID> textures = new List<UUID>();
648 f.OffsetV = offsett;
649 919
650 if (scales != 0) 920
651 f.RepeatU = scales; 921// if (doTextInv)
922 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
652 923
653 if (scalet != 0) 924 if(client == null) // don't put textures in inventory if there is no client
654 f.RepeatV = scalet; 925 doTextInv = false;
655 926
656 if (textures.Count > textureNum) 927 for (int i = 0; i < texture_list.Count; i++)
657 f.TextureID = textures[textureNum]; 928 {
658 else 929 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, creatorIDstr);
659 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE; 930 textureAsset.Data = texture_list[i].AsBinary();
931 if (istest)
932 textureAsset.Local = true;
933 m_assetService.Store(textureAsset);
934 textures.Add(textureAsset.FullID);
935
936 if (doTextInv)
937 {
938 string name = assetName;
939 if (name.Length > 25)
940 name = name.Substring(0, 24);
941 name += "_Texture#" + i.ToString();
942 InventoryItemBase texitem = new InventoryItemBase();
943 texitem.Owner = m_HostCapsObj.AgentID;
944 texitem.CreatorId = creatorIDstr;
945 texitem.CreatorData = String.Empty;
946 texitem.ID = UUID.Random();
947 texitem.AssetID = textureAsset.FullID;
948 texitem.Description = "mesh model texture";
949 texitem.Name = name;
950 texitem.AssetType = (int)AssetType.Texture;
951 texitem.InvType = (int)InventoryType.Texture;
952 texitem.Folder = texturesFolder;
953
954 texitem.CurrentPermissions
955 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export);
956
957 texitem.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
958 texitem.EveryOnePermissions = 0;
959 texitem.NextPermissions = (uint)PermissionMask.All;
960 texitem.CreationDate = Util.UnixTimeSinceEpoch();
961
962 m_Scene.AddInventoryItem(client, texitem);
963 texitem = null;
964 }
965 }
966
967 // create and store meshs assets
968 List<UUID> meshAssets = new List<UUID>();
969 List<bool> meshAvatarSkeletons = new List<bool>();
970 List<bool> meshAvatarColliders = new List<bool>();
971
972 bool curAvSkeleton;
973 bool curAvCollider;
974 for (int i = 0; i < mesh_list.Count; i++)
975 {
976 curAvSkeleton = false;
977 curAvCollider = false;
660 978
661 textureEntry.FaceTextures[face] = f; 979 // we do need to parse the mesh now
980 OSD osd = OSDParser.DeserializeLLSDBinary(mesh_list[i]);
981 if (osd is OSDMap)
982 {
983 OSDMap mosd = (OSDMap)osd;
984 if (mosd.ContainsKey("skeleton"))
985 {
986 OSDMap skeleton = (OSDMap)mosd["skeleton"];
987 int sksize = skeleton["size"].AsInteger();
988 if (sksize > 0)
989 curAvSkeleton = true;
990 }
991 }
992
993 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, creatorIDstr);
994 meshAsset.Data = mesh_list[i].AsBinary();
995 if (istest)
996 meshAsset.Local = true;
997 m_assetService.Store(meshAsset);
998 meshAssets.Add(meshAsset.FullID);
999 meshAvatarSkeletons.Add(curAvSkeleton);
1000 meshAvatarColliders.Add(curAvCollider);
1001
1002 // test code
1003 if (curAvSkeleton && client != null)
1004 {
1005 string name = assetName;
1006 if (name.Length > 25)
1007 name = name.Substring(0, 24);
1008 name += "_Mesh#" + i.ToString();
1009 InventoryItemBase meshitem = new InventoryItemBase();
1010 meshitem.Owner = m_HostCapsObj.AgentID;
1011 meshitem.CreatorId = creatorIDstr;
1012 meshitem.CreatorData = String.Empty;
1013 meshitem.ID = UUID.Random();
1014 meshitem.AssetID = meshAsset.FullID;
1015 meshitem.Description = "mesh ";
1016 meshitem.Name = name;
1017 meshitem.AssetType = (int)AssetType.Mesh;
1018 meshitem.InvType = (int)InventoryType.Mesh;
1019 // meshitem.Folder = UUID.Zero; // send to default
1020
1021 meshitem.Folder = parentFolder; // dont let it go to folder Meshes that viewers dont show
1022
1023 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
1024 // (owner) permissions. This becomes a problem if next permissions are changed.
1025 meshitem.CurrentPermissions
1026 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
1027
1028 meshitem.BasePermissions = (uint)PermissionMask.All;
1029 meshitem.EveryOnePermissions = 0;
1030 meshitem.NextPermissions = (uint)PermissionMask.All;
1031 meshitem.CreationDate = Util.UnixTimeSinceEpoch();
1032
1033 m_Scene.AddInventoryItem(client, meshitem);
1034 meshitem = null;
1035 }
662 } 1036 }
663 1037
664 pbs.TextureEntry = textureEntry.GetBytes(); 1038 int skipedMeshs = 0;
1039 // build prims from instances
1040 for (int i = 0; i < instance_list.Count; i++)
1041 {
1042 OSDMap inner_instance_list = (OSDMap)instance_list[i];
665 1043
666 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, ""); 1044 // skip prims that are 2 small
667 meshAsset.Data = mesh_list[i].AsBinary(); 1045 Vector3 scale = inner_instance_list["scale"].AsVector3();
668 m_assetService.Store(meshAsset);
669 1046
670 pbs.SculptEntry = true; 1047 if (scale.X < m_PrimScaleMin || scale.Y < m_PrimScaleMin || scale.Z < m_PrimScaleMin)
671 pbs.SculptTexture = meshAsset.FullID; 1048 {
672 pbs.SculptType = (byte)SculptType.Mesh; 1049 skipedMeshs++;
673 pbs.SculptData = meshAsset.Data; 1050 continue;
1051 }
1052
1053 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
1054
1055 Primitive.TextureEntry textureEntry
1056 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
1057
1058
1059 OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
1060 for (uint face = 0; face < face_list.Count; face++)
1061 {
1062 OSDMap faceMap = (OSDMap)face_list[(int)face];
1063 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
1064 if (faceMap.ContainsKey("fullbright"))
1065 f.Fullbright = faceMap["fullbright"].AsBoolean();
1066 if (faceMap.ContainsKey("diffuse_color"))
1067 f.RGBA = faceMap["diffuse_color"].AsColor4();
1068
1069 int textureNum = faceMap["image"].AsInteger();
1070 float imagerot = faceMap["imagerot"].AsInteger();
1071 float offsets = (float)faceMap["offsets"].AsReal();
1072 float offsett = (float)faceMap["offsett"].AsReal();
1073 float scales = (float)faceMap["scales"].AsReal();
1074 float scalet = (float)faceMap["scalet"].AsReal();
1075
1076 if (imagerot != 0)
1077 f.Rotation = imagerot;
1078
1079 if (offsets != 0)
1080 f.OffsetU = offsets;
674 1081
675 Vector3 position = inner_instance_list["position"].AsVector3(); 1082 if (offsett != 0)
676 Vector3 scale = inner_instance_list["scale"].AsVector3(); 1083 f.OffsetV = offsett;
677 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); 1084
1085 if (scales != 0)
1086 f.RepeatU = scales;
1087
1088 if (scalet != 0)
1089 f.RepeatV = scalet;
1090
1091 if (textures.Count > textureNum)
1092 f.TextureID = textures[textureNum];
1093 else
1094 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
1095
1096 textureEntry.FaceTextures[face] = f;
1097 }
1098
1099 pbs.TextureEntry = textureEntry.GetBytes();
1100
1101 bool hasmesh = false;
1102 if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ...
1103 {
1104 int meshindx = inner_instance_list["mesh"].AsInteger();
1105 if (meshAssets.Count > meshindx)
1106 {
1107 pbs.SculptEntry = true;
1108 pbs.SculptType = (byte)SculptType.Mesh;
1109 pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
1110 // data will be requested from asset on rez (i hope)
1111 hasmesh = true;
1112 }
1113 }
1114
1115 Vector3 position = inner_instance_list["position"].AsVector3();
1116 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
1117
1118 // for now viwers do send fixed defaults
1119 // but this may change
1120// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
1121 byte physicsShapeType = (byte)PhysShapeType.prim; // default for mesh is simple convex
1122 if(hasmesh)
1123 physicsShapeType = (byte) PhysShapeType.convex; // default for mesh is simple convex
1124// int material = inner_instance_list["material"].AsInteger();
1125 byte material = (byte)Material.Wood;
678 1126
679// no longer used - begin ------------------------ 1127// no longer used - begin ------------------------
680// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
681// int material = inner_instance_list["material"].AsInteger();
682// int mesh = inner_instance_list["mesh"].AsInteger(); 1128// int mesh = inner_instance_list["mesh"].AsInteger();
683 1129
684// OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; 1130// OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
@@ -693,24 +1139,49 @@ namespace OpenSim.Region.ClientStack.Linden
693// UUID owner_id = permissions["owner_id"].AsUUID(); 1139// UUID owner_id = permissions["owner_id"].AsUUID();
694// int owner_mask = permissions["owner_mask"].AsInteger(); 1140// int owner_mask = permissions["owner_mask"].AsInteger();
695// no longer used - end ------------------------ 1141// no longer used - end ------------------------
1142
1143
1144 SceneObjectPart prim
1145 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
1146
1147 prim.Scale = scale;
1148 rotations.Add(rotation);
1149 positions.Add(position);
1150 prim.UUID = UUID.Random();
1151 prim.CreatorID = creatorID;
1152 prim.OwnerID = owner_id;
1153 prim.GroupID = UUID.Zero;
1154 prim.LastOwnerID = creatorID;
1155 prim.CreationDate = Util.UnixTimeSinceEpoch();
1156
1157 if (grp == null)
1158 prim.Name = assetName;
1159 else
1160 prim.Name = assetName + "#" + i.ToString();
696 1161
697 UUID owner_id = m_HostCapsObj.AgentID; 1162 prim.EveryoneMask = 0;
1163 prim.GroupMask = 0;
1164
1165 if (restrictPerms)
1166 {
1167 prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
1168 prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
1169 prim.NextOwnerMask = 0;
1170 }
1171 else
1172 {
1173 prim.BaseMask = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1174 prim.OwnerMask = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1175 prim.NextOwnerMask = (uint)PermissionMask.Transfer;
1176 }
698 1177
699 SceneObjectPart prim 1178 if(istest)
700 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); 1179 prim.Description = "For testing only. Other uses are prohibited";
1180 else
1181 prim.Description = "";
701 1182
702 prim.Scale = scale; 1183 prim.Material = material;
703 //prim.OffsetPosition = position; 1184 prim.PhysicsShapeType = physicsShapeType;
704 rotations.Add(rotation);
705 positions.Add(position);
706 prim.UUID = UUID.Random();
707 prim.CreatorID = owner_id;
708 prim.OwnerID = owner_id;
709 prim.GroupID = UUID.Zero;
710 prim.LastOwnerID = prim.OwnerID;
711 prim.CreationDate = Util.UnixTimeSinceEpoch();
712 prim.Name = assetName;
713 prim.Description = "";
714 1185
715// prim.BaseMask = (uint)base_mask; 1186// prim.BaseMask = (uint)base_mask;
716// prim.EveryoneMask = (uint)everyone_mask; 1187// prim.EveryoneMask = (uint)everyone_mask;
@@ -718,52 +1189,64 @@ namespace OpenSim.Region.ClientStack.Linden
718// prim.NextOwnerMask = (uint)next_owner_mask; 1189// prim.NextOwnerMask = (uint)next_owner_mask;
719// prim.OwnerMask = (uint)owner_mask; 1190// prim.OwnerMask = (uint)owner_mask;
720 1191
721 if (grp == null) 1192 if (grp == null)
722 grp = new SceneObjectGroup(prim); 1193 {
723 else 1194 grp = new SceneObjectGroup(prim);
724 grp.AddPart(prim); 1195 grp.LastOwnerID = creatorID;
725 } 1196 }
1197 else
1198 grp.AddPart(prim);
1199 }
726 1200
727 Vector3 rootPos = positions[0]; 1201 Vector3 rootPos = positions[0];
728 1202
729 if (grp.Parts.Length > 1) 1203 if (grp.Parts.Length > 1)
730 { 1204 {
731 // Fix first link number 1205 // Fix first link number
732 grp.RootPart.LinkNum++; 1206 grp.RootPart.LinkNum++;
733 1207
734 Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]); 1208 Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]);
735 Quaternion tmprot; 1209 Quaternion tmprot;
736 Vector3 offset; 1210 Vector3 offset;
737 1211
738 // fix children rotations and positions 1212 // fix children rotations and positions
739 for (int i = 1; i < rotations.Count; i++) 1213 for (int i = 1; i < rotations.Count; i++)
740 { 1214 {
741 tmprot = rotations[i]; 1215 tmprot = rotations[i];
742 tmprot = rootRotConj * tmprot; 1216 tmprot = rootRotConj * tmprot;
1217
1218 grp.Parts[i].RotationOffset = tmprot;
743 1219
744 grp.Parts[i].RotationOffset = tmprot; 1220 offset = positions[i] - rootPos;
745 1221
746 offset = positions[i] - rootPos; 1222 offset *= rootRotConj;
1223 grp.Parts[i].OffsetPosition = offset;
1224 }
747 1225
748 offset *= rootRotConj; 1226 grp.AbsolutePosition = rootPos;
749 grp.Parts[i].OffsetPosition = offset; 1227 grp.UpdateGroupRotationR(rotations[0]);
1228 }
1229 else
1230 {
1231 grp.AbsolutePosition = rootPos;
1232 grp.UpdateGroupRotationR(rotations[0]);
750 } 1233 }
751 1234
752 grp.AbsolutePosition = rootPos; 1235 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
753 grp.UpdateGroupRotationR(rotations[0]);
754 } 1236 }
755 else 1237
1238 else // not a mesh model
756 { 1239 {
757 grp.AbsolutePosition = rootPos; 1240 m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
758 grp.UpdateGroupRotationR(rotations[0]); 1241 return;
759 } 1242 }
760
761 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
762 } 1243 }
763 1244
764 AssetBase asset; 1245 AssetBase asset;
765 asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString()); 1246 asset = new AssetBase(assetID, assetName, assType, creatorIDstr);
766 asset.Data = data; 1247 asset.Data = data;
1248 if (istest)
1249 asset.Local = true;
767 if (AddNewAsset != null) 1250 if (AddNewAsset != null)
768 AddNewAsset(asset); 1251 AddNewAsset(asset);
769 else if (m_assetService != null) 1252 else if (m_assetService != null)
@@ -771,11 +1254,17 @@ namespace OpenSim.Region.ClientStack.Linden
771 1254
772 InventoryItemBase item = new InventoryItemBase(); 1255 InventoryItemBase item = new InventoryItemBase();
773 item.Owner = m_HostCapsObj.AgentID; 1256 item.Owner = m_HostCapsObj.AgentID;
774 item.CreatorId = m_HostCapsObj.AgentID.ToString(); 1257 item.CreatorId = creatorIDstr;
775 item.CreatorData = String.Empty; 1258 item.CreatorData = String.Empty;
776 item.ID = inventoryItem; 1259 item.ID = inventoryItem;
777 item.AssetID = asset.FullID; 1260 item.AssetID = asset.FullID;
778 item.Description = assetDescription; 1261 if (istest)
1262 {
1263 item.Description = "For testing only. Other uses are prohibited";
1264 item.Flags = (uint) (InventoryItemFlags.SharedSingleReference);
1265 }
1266 else
1267 item.Description = assetDescription;
779 item.Name = assetName; 1268 item.Name = assetName;
780 item.AssetType = assType; 1269 item.AssetType = assType;
781 item.InvType = inType; 1270 item.InvType = inType;
@@ -783,18 +1272,61 @@ namespace OpenSim.Region.ClientStack.Linden
783 1272
784 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current 1273 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
785 // (owner) permissions. This becomes a problem if next permissions are changed. 1274 // (owner) permissions. This becomes a problem if next permissions are changed.
786 item.CurrentPermissions
787 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export);
788 1275
789 item.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export; 1276 if (inType == (sbyte)CustomInventoryType.AnimationSet)
790 item.EveryOnePermissions = 0; 1277 {
791 item.NextPermissions = (uint)PermissionMask.All; 1278 AnimationSet.setCreateItemPermitions(item);
1279 }
1280
1281 else if (restrictPerms)
1282 {
1283 item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
1284 item.CurrentPermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
1285 item.EveryOnePermissions = 0;
1286 item.NextPermissions = 0;
1287 }
1288 else
1289 {
1290 item.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1291 item.CurrentPermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1292 item.EveryOnePermissions = 0;
1293 item.NextPermissions = (uint)PermissionMask.Transfer;
1294 }
1295
792 item.CreationDate = Util.UnixTimeSinceEpoch(); 1296 item.CreationDate = Util.UnixTimeSinceEpoch();
793 1297
1298 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
1299
794 if (AddNewInventoryItem != null) 1300 if (AddNewInventoryItem != null)
795 { 1301 {
796 AddNewInventoryItem(m_HostCapsObj.AgentID, item); 1302 if (istest)
1303 {
1304 m_Scene.AddInventoryItem(client, item);
1305/*
1306 AddNewInventoryItem(m_HostCapsObj.AgentID, item, 0);
1307 if (client != null)
1308 client.SendAgentAlertMessage("Upload will have no cost, for personal test purposes only. Other uses are forbiden. Items may not work on a another region" , true);
1309 */
1310 }
1311 else
1312 {
1313 AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
1314// if (client != null)
1315// {
1316// // let users see anything.. i don't so far
1317// string str;
1318// if (cost > 0)
1319// // dont remember where is money unit name to put here
1320// str = "Upload complete. charged " + cost.ToString() + "$";
1321// else
1322// str = "Upload complete";
1323// client.SendAgentAlertMessage(str, true);
1324// }
1325 }
797 } 1326 }
1327
1328 lock (m_ModelCost)
1329 m_FileAgentInventoryState = FileAgentInventoryState.idle;
798 } 1330 }
799 1331
800 /// <summary> 1332 /// <summary>
@@ -995,6 +1527,131 @@ namespace OpenSim.Region.ClientStack.Linden
995 return response; 1527 return response;
996 } 1528 }
997 1529
1530 public string GetObjectCost(string request, string path,
1531 string param, IOSHttpRequest httpRequest,
1532 IOSHttpResponse httpResponse)
1533 {
1534 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1535 OSDMap resp = new OSDMap();
1536
1537 OSDArray object_ids = (OSDArray)req["object_ids"];
1538
1539 for (int i = 0; i < object_ids.Count; i++)
1540 {
1541 UUID uuid = object_ids[i].AsUUID();
1542
1543 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1544
1545 if (part != null)
1546 {
1547 SceneObjectGroup grp = part.ParentGroup;
1548 if (grp != null)
1549 {
1550 float linksetCost;
1551 float linksetPhysCost;
1552 float partCost;
1553 float partPhysCost;
1554
1555 grp.GetResourcesCosts(part, out linksetCost, out linksetPhysCost, out partCost, out partPhysCost);
1556
1557 OSDMap object_data = new OSDMap();
1558 object_data["linked_set_resource_cost"] = linksetCost;
1559 object_data["resource_cost"] = partCost;
1560 object_data["physics_cost"] = partPhysCost;
1561 object_data["linked_set_physics_cost"] = linksetPhysCost;
1562
1563 resp[uuid.ToString()] = object_data;
1564 }
1565 else
1566 {
1567 OSDMap object_data = new OSDMap();
1568 object_data["linked_set_resource_cost"] = 0;
1569 object_data["resource_cost"] = 0;
1570 object_data["physics_cost"] = 0;
1571 object_data["linked_set_physics_cost"] = 0;
1572
1573 resp[uuid.ToString()] = object_data;
1574 }
1575
1576 }
1577 }
1578
1579 string response = OSDParser.SerializeLLSDXmlString(resp);
1580 return response;
1581 }
1582
1583 public string ResourceCostSelected(string request, string path,
1584 string param, IOSHttpRequest httpRequest,
1585 IOSHttpResponse httpResponse)
1586 {
1587 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1588 OSDMap resp = new OSDMap();
1589
1590
1591 float phys=0;
1592 float stream=0;
1593 float simul=0;
1594
1595 if (req.ContainsKey("selected_roots"))
1596 {
1597 OSDArray object_ids = (OSDArray)req["selected_roots"];
1598
1599 // should go by SOG suming costs for all parts
1600 // ll v3 works ok with several objects select we get the list and adds ok
1601 // FS calls per object so results are wrong guess fs bug
1602 for (int i = 0; i < object_ids.Count; i++)
1603 {
1604 UUID uuid = object_ids[i].AsUUID();
1605 float Physc;
1606 float simulc;
1607 float streamc;
1608
1609 SceneObjectGroup grp = m_Scene.GetGroupByPrim(uuid);
1610 if (grp != null)
1611 {
1612 grp.GetSelectedCosts(out Physc, out streamc, out simulc);
1613 phys += Physc;
1614 stream += streamc;
1615 simul += simulc;
1616 }
1617 }
1618 }
1619 else if (req.ContainsKey("selected_prims"))
1620 {
1621 OSDArray object_ids = (OSDArray)req["selected_prims"];
1622
1623 // don't see in use in any of the 2 viewers
1624 // guess it should be for edit linked but... nothing
1625 // should go to SOP per part
1626 for (int i = 0; i < object_ids.Count; i++)
1627 {
1628 UUID uuid = object_ids[i].AsUUID();
1629
1630 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1631 if (part != null)
1632 {
1633 phys += part.PhysicsCost;
1634 stream += part.StreamingCost;
1635 simul += part.SimulationCost;
1636 }
1637 }
1638 }
1639
1640 // if (simul != 0)
1641 {
1642 OSDMap object_data = new OSDMap();
1643
1644 object_data["physics"] = phys;
1645 object_data["streaming"] = stream;
1646 object_data["simulation"] = simul;
1647
1648 resp["selected"] = object_data;
1649 }
1650
1651 string response = OSDParser.SerializeLLSDXmlString(resp);
1652 return response;
1653 }
1654
998 public string UpdateAgentInformation(string request, string path, 1655 public string UpdateAgentInformation(string request, string path,
999 string param, IOSHttpRequest httpRequest, 1656 string param, IOSHttpRequest httpRequest,
1000 IOSHttpResponse httpResponse) 1657 IOSHttpResponse httpResponse)
@@ -1015,6 +1672,10 @@ namespace OpenSim.Region.ClientStack.Linden
1015 1672
1016 public class AssetUploader 1673 public class AssetUploader
1017 { 1674 {
1675 private static readonly ILog m_log =
1676 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
1677
1678
1018 public event UpLoadedAsset OnUpLoad; 1679 public event UpLoadedAsset OnUpLoad;
1019 private UpLoadedAsset handlerUpLoad = null; 1680 private UpLoadedAsset handlerUpLoad = null;
1020 1681
@@ -1029,10 +1690,21 @@ namespace OpenSim.Region.ClientStack.Linden
1029 1690
1030 private string m_invType = String.Empty; 1691 private string m_invType = String.Empty;
1031 private string m_assetType = String.Empty; 1692 private string m_assetType = String.Empty;
1032 1693 private int m_cost;
1694 private string m_error = String.Empty;
1695
1696 private Timer m_timeoutTimer = new Timer();
1697 private UUID m_texturesFolder;
1698 private int m_nreqtextures;
1699 private int m_nreqmeshs;
1700 private int m_nreqinstances;
1701 private bool m_IsAtestUpload;
1702
1033 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, 1703 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
1034 UUID parentFolderID, string invType, string assetType, string path, 1704 UUID parentFolderID, string invType, string assetType, string path,
1035 IHttpServer httpServer, bool dumpAssetsToFile) 1705 IHttpServer httpServer, bool dumpAssetsToFile,
1706 int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
1707 bool IsAtestUpload)
1036 { 1708 {
1037 m_assetName = assetName; 1709 m_assetName = assetName;
1038 m_assetDes = description; 1710 m_assetDes = description;
@@ -1044,6 +1716,18 @@ namespace OpenSim.Region.ClientStack.Linden
1044 m_assetType = assetType; 1716 m_assetType = assetType;
1045 m_invType = invType; 1717 m_invType = invType;
1046 m_dumpAssetsToFile = dumpAssetsToFile; 1718 m_dumpAssetsToFile = dumpAssetsToFile;
1719 m_cost = totalCost;
1720
1721 m_texturesFolder = texturesFolder;
1722 m_nreqtextures = nreqtextures;
1723 m_nreqmeshs = nreqmeshs;
1724 m_nreqinstances = nreqinstances;
1725 m_IsAtestUpload = IsAtestUpload;
1726
1727 m_timeoutTimer.Elapsed += TimedOut;
1728 m_timeoutTimer.Interval = 120000;
1729 m_timeoutTimer.AutoReset = false;
1730 m_timeoutTimer.Start();
1047 } 1731 }
1048 1732
1049 /// <summary> 1733 /// <summary>
@@ -1058,12 +1742,14 @@ namespace OpenSim.Region.ClientStack.Linden
1058 UUID inv = inventoryItemID; 1742 UUID inv = inventoryItemID;
1059 string res = String.Empty; 1743 string res = String.Empty;
1060 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); 1744 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
1745/*
1061 uploadComplete.new_asset = newAssetID.ToString(); 1746 uploadComplete.new_asset = newAssetID.ToString();
1062 uploadComplete.new_inventory_item = inv; 1747 uploadComplete.new_inventory_item = inv;
1063 uploadComplete.state = "complete"; 1748 uploadComplete.state = "complete";
1064 1749
1065 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); 1750 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
1066 1751*/
1752 m_timeoutTimer.Stop();
1067 httpListener.RemoveStreamHandler("POST", uploaderPath); 1753 httpListener.RemoveStreamHandler("POST", uploaderPath);
1068 1754
1069 // TODO: probably make this a better set of extensions here 1755 // TODO: probably make this a better set of extensions here
@@ -1080,12 +1766,50 @@ namespace OpenSim.Region.ClientStack.Linden
1080 handlerUpLoad = OnUpLoad; 1766 handlerUpLoad = OnUpLoad;
1081 if (handlerUpLoad != null) 1767 if (handlerUpLoad != null)
1082 { 1768 {
1083 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType); 1769 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType,
1770 m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload,
1771 ref m_error);
1084 } 1772 }
1773 if (m_IsAtestUpload)
1774 {
1775 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1776 resperror.message = "Upload SUCESSEFULL for testing purposes only. Other uses are prohibited. Item will not work after 48 hours or on other regions";
1777 resperror.identifier = inv;
1778
1779 uploadComplete.error = resperror;
1780 uploadComplete.state = "Upload4Testing";
1781 }
1782 else
1783 {
1784 if (m_error == String.Empty)
1785 {
1786 uploadComplete.new_asset = newAssetID.ToString();
1787 uploadComplete.new_inventory_item = inv;
1788 // if (m_texturesFolder != UUID.Zero)
1789 // uploadComplete.new_texture_folder_id = m_texturesFolder;
1790 uploadComplete.state = "complete";
1791 }
1792 else
1793 {
1794 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1795 resperror.message = m_error;
1796 resperror.identifier = inv;
1085 1797
1798 uploadComplete.error = resperror;
1799 uploadComplete.state = "failed";
1800 }
1801 }
1802
1803 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
1086 return res; 1804 return res;
1087 } 1805 }
1088 1806
1807 private void TimedOut(object sender, ElapsedEventArgs args)
1808 {
1809 m_log.InfoFormat("[CAPS]: Removing URL and handler for timed out mesh upload");
1810 httpListener.RemoveStreamHandler("POST", uploaderPath);
1811 }
1812
1089 ///Left this in and commented in case there are unforseen issues 1813 ///Left this in and commented in case there are unforseen issues
1090 //private void SaveAssetToFile(string filename, byte[] data) 1814 //private void SaveAssetToFile(string filename, byte[] data)
1091 //{ 1815 //{
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
new file mode 100644
index 0000000..546bcd9
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
@@ -0,0 +1,703 @@
1// Proprietary code of Avination Virtual Limited
2// (c) 2012 Melanie Thielker, Leal Duarte
3//
4
5using System;
6using System.IO;
7using System.Collections;
8using System.Collections.Generic;
9using System.Text;
10
11using OpenMetaverse;
12using OpenMetaverse.StructuredData;
13
14using OpenSim.Framework;
15using OpenSim.Region.Framework;
16using OpenSim.Region.Framework.Scenes;
17using OpenSim.Framework.Capabilities;
18
19using ComponentAce.Compression.Libs.zlib;
20
21using OSDArray = OpenMetaverse.StructuredData.OSDArray;
22using OSDMap = OpenMetaverse.StructuredData.OSDMap;
23
24namespace OpenSim.Region.ClientStack.Linden
25{
26 public struct ModelPrimLimits
27 {
28
29 }
30
31 public class ModelCost
32 {
33
34 // upload fee defaults
35 // fees are normalized to 1.0
36 // this parameters scale them to basic cost ( so 1.0 translates to 10 )
37
38 public float ModelMeshCostFactor = 0.0f; // scale total cost relative to basic (excluding textures)
39 public float ModelTextureCostFactor = 1.0f; // scale textures fee to basic.
40 public float ModelMinCostFactor = 0.0f; // 0.5f; // minimum total model free excluding textures
41
42 // itens costs in normalized values
43 // ie will be multiplied by basicCost and factors above
44 public float primCreationCost = 0.002f; // extra cost for each prim creation overhead
45 // weigthed size to normalized cost
46 public float bytecost = 1e-5f;
47
48 // mesh upload fees based on compressed data sizes
49 // several data sections are counted more that once
50 // to promote user optimization
51 // following parameters control how many extra times they are added
52 // to global size.
53 // LOD meshs
54 const float medSizeWth = 1f; // 2x
55 const float lowSizeWth = 1.5f; // 2.5x
56 const float lowestSizeWth = 2f; // 3x
57 // favor potencially physical optimized meshs versus automatic decomposition
58 const float physMeshSizeWth = 6f; // counts 7x
59 const float physHullSizeWth = 8f; // counts 9x
60
61 // stream cost area factors
62 // more or less like SL
63 const float highLodFactor = 17.36f;
64 const float midLodFactor = 277.78f;
65 const float lowLodFactor = 1111.11f;
66
67 // physics cost is below, identical to SL, assuming shape type convex
68 // server cost is below identical to SL assuming non scripted non physical object
69
70 // internal
71 const int bytesPerCoord = 6; // 3 coords, 2 bytes per each
72
73 // control prims dimensions
74 public float PrimScaleMin = 0.001f;
75 public float NonPhysicalPrimScaleMax = 256f;
76 public float PhysicalPrimScaleMax = 10f;
77 public int ObjectLinkedPartsMax = 512;
78
79 // storage for a single mesh asset cost parameters
80 private class ameshCostParam
81 {
82 // LOD sizes for size dependent streaming cost
83 public int highLODSize;
84 public int medLODSize;
85 public int lowLODSize;
86 public int lowestLODSize;
87 // normalized fee based on compressed data sizes
88 public float costFee;
89 // physics cost
90 public float physicsCost;
91 }
92
93 // calculates a mesh model costs
94 // returns false on error, with a reason on parameter error
95 // resources input LLSD request
96 // basicCost input region assets upload cost
97 // totalcost returns model total upload fee
98 // meshcostdata returns detailed costs for viewer
99 // avatarSkeleton if mesh includes a avatar skeleton
100 // useAvatarCollider if we should use physics mesh for avatar
101 public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost,
102 LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning)
103 {
104 totalcost = 0;
105 error = string.Empty;
106
107 bool avatarSkeleton = false;
108
109 if (resources == null ||
110 resources.instance_list == null ||
111 resources.instance_list.Array.Count == 0)
112 {
113 error = "missing model information.";
114 return false;
115 }
116
117 int numberInstances = resources.instance_list.Array.Count;
118
119 if( numberInstances > ObjectLinkedPartsMax )
120 {
121 error = "Model whould have more than " + ObjectLinkedPartsMax.ToString() + " linked prims";
122 return false;
123 }
124
125 meshcostdata.model_streaming_cost = 0.0;
126 meshcostdata.simulation_cost = 0.0;
127 meshcostdata.physics_cost = 0.0;
128 meshcostdata.resource_cost = 0.0;
129
130 meshcostdata.upload_price_breakdown.mesh_instance = 0;
131 meshcostdata.upload_price_breakdown.mesh_physics = 0;
132 meshcostdata.upload_price_breakdown.mesh_streaming = 0;
133 meshcostdata.upload_price_breakdown.model = 0;
134
135 int itmp;
136
137 // textures cost
138 if (resources.texture_list != null && resources.texture_list.Array.Count > 0)
139 {
140 float textures_cost = (float)(resources.texture_list.Array.Count * basicCost);
141 textures_cost *= ModelTextureCostFactor;
142
143 itmp = (int)(textures_cost + 0.5f); // round
144 meshcostdata.upload_price_breakdown.texture = itmp;
145 totalcost += itmp;
146 }
147
148 // meshs assets cost
149 float meshsfee = 0;
150 int numberMeshs = 0;
151 bool haveMeshs = false;
152
153 bool curskeleton;
154 bool curAvatarPhys;
155
156 List<ameshCostParam> meshsCosts = new List<ameshCostParam>();
157
158 if (resources.mesh_list != null && resources.mesh_list.Array.Count > 0)
159 {
160 numberMeshs = resources.mesh_list.Array.Count;
161
162 for (int i = 0; i < numberMeshs; i++)
163 {
164 ameshCostParam curCost = new ameshCostParam();
165 byte[] data = (byte[])resources.mesh_list.Array[i];
166
167 if (!MeshCost(data, curCost,out curskeleton, out curAvatarPhys, out error))
168 {
169 return false;
170 }
171
172 if (curskeleton)
173 {
174 if (avatarSkeleton)
175 {
176 error = "model can only contain a avatar skeleton";
177 return false;
178 }
179 avatarSkeleton = true;
180 }
181 meshsCosts.Add(curCost);
182 meshsfee += curCost.costFee;
183 }
184 haveMeshs = true;
185 }
186
187 // instances (prims) cost
188
189
190 int mesh;
191 int skipedSmall = 0;
192 for (int i = 0; i < numberInstances; i++)
193 {
194 Hashtable inst = (Hashtable)resources.instance_list.Array[i];
195
196 ArrayList ascale = (ArrayList)inst["scale"];
197 Vector3 scale;
198 double tmp;
199 tmp = (double)ascale[0];
200 scale.X = (float)tmp;
201 tmp = (double)ascale[1];
202 scale.Y = (float)tmp;
203 tmp = (double)ascale[2];
204 scale.Z = (float)tmp;
205
206 if (scale.X < PrimScaleMin || scale.Y < PrimScaleMin || scale.Z < PrimScaleMin)
207 {
208 skipedSmall++;
209 continue;
210 }
211
212 if (scale.X > NonPhysicalPrimScaleMax || scale.Y > NonPhysicalPrimScaleMax || scale.Z > NonPhysicalPrimScaleMax)
213 {
214 error = "Model contains parts with sides larger than " + NonPhysicalPrimScaleMax.ToString() + "m. Please ajust scale";
215 return false;
216 }
217
218 if (haveMeshs && inst.ContainsKey("mesh"))
219 {
220 mesh = (int)inst["mesh"];
221
222 if (mesh >= numberMeshs)
223 {
224 error = "Incoerent model information.";
225 return false;
226 }
227
228 // streamming cost
229
230 float sqdiam = scale.LengthSquared();
231
232 ameshCostParam curCost = meshsCosts[mesh];
233 float mesh_streaming = streamingCost(curCost, sqdiam);
234
235 meshcostdata.model_streaming_cost += mesh_streaming;
236 meshcostdata.physics_cost += curCost.physicsCost;
237 }
238 else // instance as no mesh ??
239 {
240 // to do later if needed
241 meshcostdata.model_streaming_cost += 0.5f;
242 meshcostdata.physics_cost += 1.0f;
243 }
244
245 // assume unscripted and static prim server cost
246 meshcostdata.simulation_cost += 0.5f;
247 // charge for prims creation
248 meshsfee += primCreationCost;
249 }
250
251 if (skipedSmall > 0)
252 {
253 if (skipedSmall > numberInstances / 2)
254 {
255 error = "Model contains too many prims smaller than " + PrimScaleMin.ToString() +
256 "m minimum allowed size. Please check scalling";
257 return false;
258 }
259 else
260 warning += skipedSmall.ToString() + " of the requested " +numberInstances.ToString() +
261 " model prims will not upload because they are smaller than " + PrimScaleMin.ToString() +
262 "m minimum allowed size. Please check scalling ";
263 }
264
265 if (meshcostdata.physics_cost <= meshcostdata.model_streaming_cost)
266 meshcostdata.resource_cost = meshcostdata.model_streaming_cost;
267 else
268 meshcostdata.resource_cost = meshcostdata.physics_cost;
269
270 if (meshcostdata.resource_cost < meshcostdata.simulation_cost)
271 meshcostdata.resource_cost = meshcostdata.simulation_cost;
272
273 // scale cost
274 // at this point a cost of 1.0 whould mean basic cost
275 meshsfee *= ModelMeshCostFactor;
276
277 if (meshsfee < ModelMinCostFactor)
278 meshsfee = ModelMinCostFactor;
279
280 // actually scale it to basic cost
281 meshsfee *= (float)basicCost;
282
283 meshsfee += 0.5f; // rounding
284
285 totalcost += (int)meshsfee;
286
287 // breakdown prices
288 // don't seem to be in use so removed code for now
289
290 return true;
291 }
292
293 // single mesh asset cost
294 private bool MeshCost(byte[] data, ameshCostParam cost,out bool skeleton, out bool avatarPhys, out string error)
295 {
296 cost.highLODSize = 0;
297 cost.medLODSize = 0;
298 cost.lowLODSize = 0;
299 cost.lowestLODSize = 0;
300 cost.physicsCost = 0.0f;
301 cost.costFee = 0.0f;
302
303 error = string.Empty;
304
305 skeleton = false;
306 avatarPhys = false;
307
308 if (data == null || data.Length == 0)
309 {
310 error = "Missing model information.";
311 return false;
312 }
313
314 OSD meshOsd = null;
315 int start = 0;
316
317 error = "Invalid model data";
318
319 using (MemoryStream ms = new MemoryStream(data))
320 {
321 try
322 {
323 OSD osd = OSDParser.DeserializeLLSDBinary(ms);
324 if (osd is OSDMap)
325 meshOsd = (OSDMap)osd;
326 else
327 return false;
328 }
329 catch (Exception e)
330 {
331 return false;
332 }
333 start = (int)ms.Position;
334 }
335
336 OSDMap map = (OSDMap)meshOsd;
337 OSDMap tmpmap;
338
339 int highlod_size = 0;
340 int medlod_size = 0;
341 int lowlod_size = 0;
342 int lowestlod_size = 0;
343 int skin_size = 0;
344
345 int hulls_size = 0;
346 int phys_nhulls;
347 int phys_hullsvertices = 0;
348
349 int physmesh_size = 0;
350 int phys_ntriangles = 0;
351
352 int submesh_offset = -1;
353
354 if (map.ContainsKey("skeleton"))
355 {
356 tmpmap = (OSDMap)map["skeleton"];
357 if (tmpmap.ContainsKey("offset") && tmpmap.ContainsKey("size"))
358 {
359 int sksize = tmpmap["size"].AsInteger();
360 if(sksize > 0)
361 skeleton = true;
362 }
363 }
364
365 if (map.ContainsKey("physics_convex"))
366 {
367 tmpmap = (OSDMap)map["physics_convex"];
368 if (tmpmap.ContainsKey("offset"))
369 submesh_offset = tmpmap["offset"].AsInteger() + start;
370 if (tmpmap.ContainsKey("size"))
371 hulls_size = tmpmap["size"].AsInteger();
372 }
373
374 if (submesh_offset < 0 || hulls_size == 0)
375 {
376 error = "Missing physics_convex block";
377 return false;
378 }
379
380 if (!hulls(data, submesh_offset, hulls_size, out phys_hullsvertices, out phys_nhulls))
381 {
382 error = "Bad physics_convex block";
383 return false;
384 }
385
386 submesh_offset = -1;
387
388 // only look for LOD meshs sizes
389
390 if (map.ContainsKey("high_lod"))
391 {
392 tmpmap = (OSDMap)map["high_lod"];
393 // see at least if there is a offset for this one
394 if (tmpmap.ContainsKey("offset"))
395 submesh_offset = tmpmap["offset"].AsInteger() + start;
396 if (tmpmap.ContainsKey("size"))
397 highlod_size = tmpmap["size"].AsInteger();
398 }
399
400 if (submesh_offset < 0 || highlod_size <= 0)
401 {
402 error = "Missing high_lod block";
403 return false;
404 }
405
406 bool haveprev = true;
407
408 if (map.ContainsKey("medium_lod"))
409 {
410 tmpmap = (OSDMap)map["medium_lod"];
411 if (tmpmap.ContainsKey("size"))
412 medlod_size = tmpmap["size"].AsInteger();
413 else
414 haveprev = false;
415 }
416
417 if (haveprev && map.ContainsKey("low_lod"))
418 {
419 tmpmap = (OSDMap)map["low_lod"];
420 if (tmpmap.ContainsKey("size"))
421 lowlod_size = tmpmap["size"].AsInteger();
422 else
423 haveprev = false;
424 }
425
426 if (haveprev && map.ContainsKey("lowest_lod"))
427 {
428 tmpmap = (OSDMap)map["lowest_lod"];
429 if (tmpmap.ContainsKey("size"))
430 lowestlod_size = tmpmap["size"].AsInteger();
431 }
432
433 if (map.ContainsKey("skin"))
434 {
435 tmpmap = (OSDMap)map["skin"];
436 if (tmpmap.ContainsKey("size"))
437 skin_size = tmpmap["size"].AsInteger();
438 }
439
440 cost.highLODSize = highlod_size;
441 cost.medLODSize = medlod_size;
442 cost.lowLODSize = lowlod_size;
443 cost.lowestLODSize = lowestlod_size;
444
445 submesh_offset = -1;
446
447 tmpmap = null;
448 if(map.ContainsKey("physics_mesh"))
449 tmpmap = (OSDMap)map["physics_mesh"];
450 else if (map.ContainsKey("physics_shape")) // old naming
451 tmpmap = (OSDMap)map["physics_shape"];
452
453 if(tmpmap != null)
454 {
455 if (tmpmap.ContainsKey("offset"))
456 submesh_offset = tmpmap["offset"].AsInteger() + start;
457 if (tmpmap.ContainsKey("size"))
458 physmesh_size = tmpmap["size"].AsInteger();
459
460 if (submesh_offset >= 0 || physmesh_size > 0)
461 {
462
463 if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles))
464 {
465 error = "Model data parsing error";
466 return false;
467 }
468 }
469 }
470
471 // upload is done in convex shape type so only one hull
472 phys_hullsvertices++;
473 cost.physicsCost = 0.04f * phys_hullsvertices;
474
475 float sfee;
476
477 sfee = data.Length; // start with total compressed data size
478
479 // penalize lod meshs that should be more builder optimized
480 sfee += medSizeWth * medlod_size;
481 sfee += lowSizeWth * lowlod_size;
482 sfee += lowestSizeWth * lowlod_size;
483
484 // physics
485 // favor potencial optimized meshs versus automatic decomposition
486 if (physmesh_size != 0)
487 sfee += physMeshSizeWth * (physmesh_size + hulls_size / 4); // reduce cost of mandatory convex hull
488 else
489 sfee += physHullSizeWth * hulls_size;
490
491 // bytes to money
492 sfee *= bytecost;
493
494 cost.costFee = sfee;
495 return true;
496 }
497
498 // parses a LOD or physics mesh component
499 private bool submesh(byte[] data, int offset, int size, out int ntriangles)
500 {
501 ntriangles = 0;
502
503 OSD decodedMeshOsd = new OSD();
504 byte[] meshBytes = new byte[size];
505 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
506 try
507 {
508 using (MemoryStream inMs = new MemoryStream(meshBytes))
509 {
510 using (MemoryStream outMs = new MemoryStream())
511 {
512 using (ZOutputStream zOut = new ZOutputStream(outMs))
513 {
514 byte[] readBuffer = new byte[4096];
515 int readLen = 0;
516 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
517 {
518 zOut.Write(readBuffer, 0, readLen);
519 }
520 zOut.Flush();
521 outMs.Seek(0, SeekOrigin.Begin);
522
523 byte[] decompressedBuf = outMs.GetBuffer();
524 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
525 }
526 }
527 }
528 }
529 catch (Exception e)
530 {
531 return false;
532 }
533
534 OSDArray decodedMeshOsdArray = null;
535 if ((!decodedMeshOsd is OSDArray))
536 return false;
537
538 byte[] dummy;
539
540 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
541 foreach (OSD subMeshOsd in decodedMeshOsdArray)
542 {
543 if (subMeshOsd is OSDMap)
544 {
545 OSDMap subtmpmap = (OSDMap)subMeshOsd;
546 if (subtmpmap.ContainsKey("NoGeometry") && ((OSDBoolean)subtmpmap["NoGeometry"]))
547 continue;
548
549 if (!subtmpmap.ContainsKey("Position"))
550 return false;
551
552 if (subtmpmap.ContainsKey("TriangleList"))
553 {
554 dummy = subtmpmap["TriangleList"].AsBinary();
555 ntriangles += dummy.Length / bytesPerCoord;
556 }
557 else
558 return false;
559 }
560 }
561
562 return true;
563 }
564
565 // parses convex hulls component
566 private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls)
567 {
568 nvertices = 0;
569 nhulls = 1;
570
571 OSD decodedMeshOsd = new OSD();
572 byte[] meshBytes = new byte[size];
573 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
574 try
575 {
576 using (MemoryStream inMs = new MemoryStream(meshBytes))
577 {
578 using (MemoryStream outMs = new MemoryStream())
579 {
580 using (ZOutputStream zOut = new ZOutputStream(outMs))
581 {
582 byte[] readBuffer = new byte[4096];
583 int readLen = 0;
584 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
585 {
586 zOut.Write(readBuffer, 0, readLen);
587 }
588 zOut.Flush();
589 outMs.Seek(0, SeekOrigin.Begin);
590
591 byte[] decompressedBuf = outMs.GetBuffer();
592 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
593 }
594 }
595 }
596 }
597 catch (Exception e)
598 {
599 return false;
600 }
601
602 OSDMap cmap = (OSDMap)decodedMeshOsd;
603 if (cmap == null)
604 return false;
605
606 byte[] dummy;
607
608 // must have one of this
609 if (cmap.ContainsKey("BoundingVerts"))
610 {
611 dummy = cmap["BoundingVerts"].AsBinary();
612 nvertices = dummy.Length / bytesPerCoord;
613 }
614 else
615 return false;
616
617/* upload is done with convex shape type
618 if (cmap.ContainsKey("HullList"))
619 {
620 dummy = cmap["HullList"].AsBinary();
621 nhulls += dummy.Length;
622 }
623
624
625 if (cmap.ContainsKey("Positions"))
626 {
627 dummy = cmap["Positions"].AsBinary();
628 nvertices = dummy.Length / bytesPerCoord;
629 }
630 */
631
632 return true;
633 }
634
635 // returns streaming cost from on mesh LODs sizes in curCost and square of prim size length
636 private float streamingCost(ameshCostParam curCost, float sqdiam)
637 {
638 // compute efective areas
639 float ma = 262144f;
640
641 float mh = sqdiam * highLodFactor;
642 if (mh > ma)
643 mh = ma;
644 float mm = sqdiam * midLodFactor;
645 if (mm > ma)
646 mm = ma;
647
648 float ml = sqdiam * lowLodFactor;
649 if (ml > ma)
650 ml = ma;
651
652 float mlst = ma;
653
654 mlst -= ml;
655 ml -= mm;
656 mm -= mh;
657
658 if (mlst < 1.0f)
659 mlst = 1.0f;
660 if (ml < 1.0f)
661 ml = 1.0f;
662 if (mm < 1.0f)
663 mm = 1.0f;
664 if (mh < 1.0f)
665 mh = 1.0f;
666
667 ma = mlst + ml + mm + mh;
668
669 // get LODs compressed sizes
670 // giving 384 bytes bonus
671 int lst = curCost.lowestLODSize - 384;
672 int l = curCost.lowLODSize - 384;
673 int m = curCost.medLODSize - 384;
674 int h = curCost.highLODSize - 384;
675
676 // use previus higher LOD size on missing ones
677 if (m <= 0)
678 m = h;
679 if (l <= 0)
680 l = m;
681 if (lst <= 0)
682 lst = l;
683
684 // force minumum sizes
685 if (lst < 16)
686 lst = 16;
687 if (l < 16)
688 l = 16;
689 if (m < 16)
690 m = 16;
691 if (h < 16)
692 h = 16;
693
694 // compute cost weighted by relative effective areas
695 float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh;
696 cost /= ma;
697
698 cost *= 0.004f; // overall tunning parameter
699
700 return cost;
701 }
702 }
703}