diff --git a/OpenSim/Capabilities/LLSDAssetUploadComplete.cs b/OpenSim/Capabilities/LLSDAssetUploadComplete.cs index ab6cee55b7..ae8eb09345 100644 --- a/OpenSim/Capabilities/LLSDAssetUploadComplete.cs +++ b/OpenSim/Capabilities/LLSDAssetUploadComplete.cs @@ -30,12 +30,15 @@ using OpenMetaverse; namespace OpenSim.Framework.Capabilities { + [LLSDType("MAP")] public class LLSDAssetUploadComplete { public string new_asset = String.Empty; public UUID new_inventory_item = UUID.Zero; +// public UUID new_texture_folder_id = UUID.Zero; public string state = String.Empty; + public LLSDAssetUploadError error = null; //public bool success = false; public LLSDAssetUploadComplete() diff --git a/OpenSim/Capabilities/LLSDAssetUploadRequest.cs b/OpenSim/Capabilities/LLSDAssetUploadRequest.cs index f981bf0fc1..6779cc1fce 100644 --- a/OpenSim/Capabilities/LLSDAssetUploadRequest.cs +++ b/OpenSim/Capabilities/LLSDAssetUploadRequest.cs @@ -45,6 +45,10 @@ namespace OpenSim.Framework.Capabilities public string asset_type = String.Empty; public string description = String.Empty; public UUID folder_id = UUID.Zero; + public UUID texture_folder_id = UUID.Zero; + public int next_owner_mask = 0; + public int group_mask = 0; + public int everyone_mask = 0; public string inventory_type = String.Empty; public string name = String.Empty; public LLSDAssetResource asset_resources = new LLSDAssetResource(); diff --git a/OpenSim/Capabilities/LLSDAssetUploadResponse.cs b/OpenSim/Capabilities/LLSDAssetUploadResponse.cs index 18285b581f..7c4bc97476 100644 --- a/OpenSim/Capabilities/LLSDAssetUploadResponse.cs +++ b/OpenSim/Capabilities/LLSDAssetUploadResponse.cs @@ -26,9 +26,17 @@ */ using System; +using OpenMetaverse; namespace OpenSim.Framework.Capabilities { + [OSDMap] + public class LLSDAssetUploadError + { + public string message = String.Empty; + public UUID identifier = UUID.Zero; + } + [OSDMap] public class LLSDAssetUploadResponsePricebrkDown { @@ -56,11 +64,13 @@ namespace OpenSim.Framework.Capabilities public string state = String.Empty; public int upload_price = 0; public LLSDAssetUploadResponseData data = null; + public LLSDAssetUploadError error = null; public LLSDAssetUploadResponse() { } } + [OSDMap] public class LLSDNewFileAngentInventoryVariablePriceReplyResponse { diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index d66076d6ba..21a1005877 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -54,8 +54,10 @@ using OSDMap = OpenMetaverse.StructuredData.OSDMap; namespace OpenSim.Region.ClientStack.Linden { public delegate void UpLoadedAsset( - string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, - byte[] data, string inventoryType, string assetType); + string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, + byte[] data, string inventoryType, string assetType, + int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances, + bool IsAtestUpload, ref string error); public delegate UUID UpdateItem(UUID itemID, byte[] data); @@ -118,6 +120,9 @@ namespace OpenSim.Region.ClientStack.Linden private string m_regionName; private int m_levelUpload = 0; private float m_PrimScaleMin = 0.001f; + private bool m_enableFreeTestUpload = false; + private bool m_enableModelUploadTextureToInventory = false; + private UUID m_testAssetsCreatorID = UUID.Zero; private enum FileAgentInventoryState : int { @@ -128,9 +133,6 @@ namespace OpenSim.Region.ClientStack.Linden } private FileAgentInventoryState m_FileAgentInventoryState = FileAgentInventoryState.idle; -// private bool m_addNewTextures = false; -// private bool m_addNewMeshes = false; - public BunchOfCaps(Scene scene, Caps caps) { m_Scene = scene; @@ -145,6 +147,13 @@ namespace OpenSim.Region.ClientStack.Linden // m_ModelCost.ObjectLinkedPartsMax = ?? // m_PrimScaleMin = ?? + float modelTextureUploadFactor = m_ModelCost.ModelTextureCostFactor; + float modelUploadFactor = m_ModelCost.ModelMeshCostFactor; + float modelMinUploadCostFactor = m_ModelCost.ModelMinCostFactor; + + // can be UUID.zero. This is me at OSG, should be a valid grid ID, is case a bad config + UUID.TryParse("58e06f33-ea8c-4ff6-9af5-420606926118", out m_testAssetsCreatorID); + IConfigSource config = m_Scene.Config; if (config != null) { @@ -159,6 +168,29 @@ namespace OpenSim.Region.ClientStack.Linden { m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); } + // economy for model upload + IConfig EconomyConfig = config.Configs["Economy"]; + if (EconomyConfig != null) + { + modelUploadFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", modelUploadFactor); + modelTextureUploadFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", modelTextureUploadFactor); + modelMinUploadCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", modelMinUploadCostFactor); + m_enableModelUploadTextureToInventory = EconomyConfig.GetBoolean("MeshModelAllowTextureToInventory", false); + + m_enableFreeTestUpload = EconomyConfig.GetBoolean("AllowFreeTestUpload", false); + string testcreator = EconomyConfig.GetString("TestAssetsCreatorID", m_testAssetsCreatorID.ToString()); + if (testcreator != "") + { + UUID id; + UUID.TryParse(testcreator, out id); + if (id != null) + m_testAssetsCreatorID = id; + } + + m_ModelCost.ModelMeshCostFactor = modelUploadFactor; + m_ModelCost.ModelTextureCostFactor = modelTextureUploadFactor; + m_ModelCost.ModelMinCostFactor = modelMinUploadCostFactor; + } } m_assetService = m_Scene.AssetService; @@ -410,37 +442,6 @@ namespace OpenSim.Region.ClientStack.Linden return UUID.Zero; } - private delegate void UploadWithCostCompleteDelegate(string assetName, - string assetDescription, UUID assetID, UUID inventoryItem, - UUID parentFolder, byte[] data, string inventoryType, - string assetType, uint cost); - - private class AssetUploaderWithCost : AssetUploader - { - private uint m_cost; - - public event UploadWithCostCompleteDelegate OnUpLoad; - - public AssetUploaderWithCost(string assetName, string description, UUID assetID, - UUID inventoryItem, UUID parentFolderID, string invType, string assetType, - string path, IHttpServer httpServer, bool dumpAssetsToFile, uint cost) : - base(assetName, description, assetID, inventoryItem, parentFolderID, - invType, assetType, path, httpServer, dumpAssetsToFile) - { - m_cost = cost; - - base.OnUpLoad += UploadCompleteHandler; - } - - private void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, - UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, - string assetType) - { - OnUpLoad(assetName, assetDescription, assetID, inventoryItem, parentFolder, - data, inventoryType, assetType, m_cost); - } - } - /// /// /// @@ -462,11 +463,14 @@ namespace OpenSim.Region.ClientStack.Linden { case FileAgentInventoryState.processRequest: case FileAgentInventoryState.processUpload: - if (client != null) - client.SendAgentAlertMessage("Unable to upload asset. Processing previus request", false); + LLSDAssetUploadError resperror = new LLSDAssetUploadError(); + resperror.message = "Uploader busy processing previus request"; + resperror.identifier = UUID.Zero; + LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); errorResponse.uploader = ""; errorResponse.state = "error"; + errorResponse.error = resperror; return errorResponse; break; case FileAgentInventoryState.waitUpload: @@ -480,7 +484,12 @@ namespace OpenSim.Region.ClientStack.Linden m_FileAgentInventoryState = FileAgentInventoryState.processRequest; } - uint cost = 0; + int cost = 0; + int nreqtextures = 0; + int nreqmeshs= 0; + int nreqinstances = 0; + bool IsAtestUpload = false; + LLSDAssetUploadResponseData meshcostdata = new LLSDAssetUploadResponseData(); if (llsdRequest.asset_type == "texture" || @@ -496,12 +505,14 @@ namespace OpenSim.Region.ClientStack.Linden { if (avatar.UserLevel < m_levelUpload) { - if (client != null) - client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false); + LLSDAssetUploadError resperror = new LLSDAssetUploadError(); + resperror.message = "Insufficient permissions to upload"; + resperror.identifier = UUID.Zero; LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); errorResponse.uploader = ""; errorResponse.state = "error"; + errorResponse.error = resperror; lock (m_ModelCost) m_FileAgentInventoryState = FileAgentInventoryState.idle; return errorResponse; @@ -517,40 +528,62 @@ namespace OpenSim.Region.ClientStack.Linden if (mm != null) baseCost = mm.UploadCharge; + string warning = String.Empty; + if (llsdRequest.asset_type == "mesh") { string error; int modelcost; - + if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost, - meshcostdata, out error)) + meshcostdata, out error, ref warning)) { - client.SendAgentAlertMessage(error, false); + LLSDAssetUploadError resperror = new LLSDAssetUploadError(); + resperror.message = error; + resperror.identifier = UUID.Zero; LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); errorResponse.uploader = ""; errorResponse.state = "error"; + errorResponse.error = resperror; + lock (m_ModelCost) m_FileAgentInventoryState = FileAgentInventoryState.idle; return errorResponse; } - cost = (uint)modelcost; + cost = modelcost; } else { - cost = (uint)baseCost; + cost = baseCost; } + if (m_enableFreeTestUpload && cost > 0 && mm != null) + { + string str = llsdRequest.name; + if (str.Length > 5 && str.StartsWith("TEST-")) + { + warning += "Upload will have no cost, but for personal test purposes only. Other uses are forbiden"; + IsAtestUpload = true; + } + } + + if (client != null && warning != String.Empty) + client.SendAgentAlertMessage(warning, true); + // check funds - if (mm != null) + if (!IsAtestUpload && mm != null && cost >0) { if (!mm.UploadCovered(client.AgentId, (int)cost)) { - client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); + LLSDAssetUploadError resperror = new LLSDAssetUploadError(); + resperror.message = "Insuficient funds"; + resperror.identifier = UUID.Zero; LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); errorResponse.uploader = ""; errorResponse.state = "error"; + errorResponse.error = resperror; lock (m_ModelCost) m_FileAgentInventoryState = FileAgentInventoryState.idle; return errorResponse; @@ -566,10 +599,15 @@ namespace OpenSim.Region.ClientStack.Linden UUID newInvItem = UUID.Random(); UUID parentFolder = llsdRequest.folder_id; string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); + UUID texturesFolder = UUID.Zero; - AssetUploaderWithCost uploader = - new AssetUploaderWithCost(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, - llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost); + if(!IsAtestUpload && m_enableModelUploadTextureToInventory) + texturesFolder = llsdRequest.texture_folder_id; + + AssetUploader uploader = + new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, + llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost, + texturesFolder, nreqtextures, nreqmeshs, nreqinstances,IsAtestUpload); m_HostCapsObj.HttpListener.AddStreamHandler( new BinaryStreamHandler( @@ -614,8 +652,11 @@ namespace OpenSim.Region.ClientStack.Linden /// public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, - string assetType, uint cost) + string assetType, int cost, + UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances, + bool IsAtestUpload, ref string error) { + lock (m_ModelCost) m_FileAgentInventoryState = FileAgentInventoryState.processUpload; @@ -626,7 +667,17 @@ namespace OpenSim.Region.ClientStack.Linden sbyte assType = 0; sbyte inType = 0; - IClientAPI client = null; + UUID owner_id = m_HostCapsObj.AgentID; + UUID creatorID; + + bool istest = IsAtestUpload && m_enableFreeTestUpload && (cost > 0); + + if (istest) + creatorID = m_testAssetsCreatorID; + else + creatorID = owner_id; + + string creatorIDstr = creatorID.ToString(); IMoneyModule mm = m_Scene.RequestModuleInterface(); if (mm != null) @@ -634,13 +685,12 @@ namespace OpenSim.Region.ClientStack.Linden // make sure client still has enougth credit if (!mm.UploadCovered(m_HostCapsObj.AgentID, (int)cost)) { - m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client); - if (client != null) - client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); + error = "Insufficient funds."; return; } } + // strings to types if (inventoryType == "sound") { inType = (sbyte)InventoryType.Sound; @@ -674,109 +724,87 @@ namespace OpenSim.Region.ClientStack.Linden List positions = new List(); List rotations = new List(); OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data); + + // compare and get updated information + + bool mismatchError = true; + + while (mismatchError) + { + mismatchError = false; + } + + if (mismatchError) + { + error = "Upload and fee estimation information don't match"; + lock (m_ModelCost) + m_FileAgentInventoryState = FileAgentInventoryState.idle; + + return; + } + OSDArray instance_list = (OSDArray)request["instance_list"]; OSDArray mesh_list = (OSDArray)request["mesh_list"]; OSDArray texture_list = (OSDArray)request["texture_list"]; SceneObjectGroup grp = null; // create and store texture assets + bool doTextInv = (!istest && m_enableModelUploadTextureToInventory && + texturesFolder != UUID.Zero); + + List textures = new List(); + for (int i = 0; i < texture_list.Count; i++) { - AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, ""); + AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, creatorIDstr); textureAsset.Data = texture_list[i].AsBinary(); m_assetService.Store(textureAsset); textures.Add(textureAsset.FullID); - /* - don't do this - replace it by optionaly making model textures cost less than if individually uploaded - since they can't be used for other purpuses - - // save it to inventory - if (m_addNewTextures && AddNewInventoryItem != null) - { - string name = assetName; - if (name.Length > 25) - name = name.Substring(0, 24); - name += "_Texture#" + i.ToString(); - InventoryItemBase texitem = new InventoryItemBase(); - texitem.Owner = m_HostCapsObj.AgentID; - texitem.CreatorId = m_HostCapsObj.AgentID.ToString(); - texitem.CreatorData = String.Empty; - texitem.ID = UUID.Random(); - texitem.AssetID = textureAsset.FullID; - texitem.Description = "mesh model texture"; - texitem.Name = name; - texitem.AssetType = (int)AssetType.Texture; - texitem.InvType = (int)InventoryType.Texture; - texitem.Folder = UUID.Zero; // send to default - // If we set PermissionMask.All then when we rez the item the next permissions will replace the current - // (owner) permissions. This becomes a problem if next permissions are changed. - texitem.CurrentPermissions - = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); + if (doTextInv) + { + string name = assetName; + if (name.Length > 25) + name = name.Substring(0, 24); + name += "_Texture#" + i.ToString(); + InventoryItemBase texitem = new InventoryItemBase(); + texitem.Owner = m_HostCapsObj.AgentID; + texitem.CreatorId = creatorIDstr; + texitem.CreatorData = String.Empty; + texitem.ID = UUID.Random(); + texitem.AssetID = textureAsset.FullID; + texitem.Description = "mesh model texture"; + texitem.Name = name; + texitem.AssetType = (int)AssetType.Texture; + texitem.InvType = (int)InventoryType.Texture; + texitem.Folder = texturesFolder; - texitem.BasePermissions = (uint)PermissionMask.All; - texitem.EveryOnePermissions = 0; - texitem.NextPermissions = (uint)PermissionMask.All; - texitem.CreationDate = Util.UnixTimeSinceEpoch(); + texitem.CurrentPermissions + = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); - AddNewInventoryItem(m_HostCapsObj.AgentID, texitem, 0); - texitem = null; - } - */ - textureAsset = null; + texitem.BasePermissions = (uint)PermissionMask.All; + texitem.EveryOnePermissions = 0; + texitem.NextPermissions = (uint)PermissionMask.All; + texitem.CreationDate = Util.UnixTimeSinceEpoch(); + + AddNewInventoryItem(m_HostCapsObj.AgentID, texitem, 0); + texitem = null; + // this aren't showing up in viewer until relog :( + } } // create and store meshs assets List meshAssets = new List(); for (int i = 0; i < mesh_list.Count; i++) { - AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, ""); + AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, creatorIDstr); meshAsset.Data = mesh_list[i].AsBinary(); m_assetService.Store(meshAsset); meshAssets.Add(meshAsset.FullID); - - /* this was a test, funny and showed viewers deal with mesh inventory itens - * nut also same reason as for textures - * let integrated in a model cost eventually less than hipotetical independent meshs assets - * that will be in inventory - // save it to inventory - if (m_addNewMeshes && AddNewInventoryItem != null) - { - string name = assetName; - if (name.Length > 25) - name = name.Substring(0, 24); - name += "_Mesh#" + i.ToString(); - InventoryItemBase meshitem = new InventoryItemBase(); - meshitem.Owner = m_HostCapsObj.AgentID; - meshitem.CreatorId = m_HostCapsObj.AgentID.ToString(); - meshitem.CreatorData = String.Empty; - meshitem.ID = UUID.Random(); - meshitem.AssetID = meshAsset.FullID; - meshitem.Description = "mesh "; - meshitem.Name = name; - meshitem.AssetType = (int)AssetType.Mesh; - meshitem.InvType = (int)InventoryType.Mesh; - meshitem.Folder = UUID.Zero; // send to default - - // If we set PermissionMask.All then when we rez the item the next permissions will replace the current - // (owner) permissions. This becomes a problem if next permissions are changed. - meshitem.CurrentPermissions - = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); - - meshitem.BasePermissions = (uint)PermissionMask.All; - meshitem.EveryOnePermissions = 0; - meshitem.NextPermissions = (uint)PermissionMask.All; - meshitem.CreationDate = Util.UnixTimeSinceEpoch(); - - AddNewInventoryItem(m_HostCapsObj.AgentID, meshitem, 0); - meshitem = null; - } - */ - meshAsset = null; } + int skipedMeshs = 0; // build prims from instances for (int i = 0; i < instance_list.Count; i++) { @@ -784,9 +812,12 @@ namespace OpenSim.Region.ClientStack.Linden // skip prims that are 2 small Vector3 scale = inner_instance_list["scale"].AsVector3(); - + if (scale.X < m_PrimScaleMin || scale.Y < m_PrimScaleMin || scale.Z < m_PrimScaleMin) + { + skipedMeshs++; continue; + } PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); @@ -836,21 +867,33 @@ namespace OpenSim.Region.ClientStack.Linden pbs.TextureEntry = textureEntry.GetBytes(); - int meshindx = inner_instance_list["mesh"].AsInteger(); - if (meshAssets.Count > meshindx) + bool hasmesh = false; + if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ... { - pbs.SculptEntry = true; - pbs.SculptType = (byte)SculptType.Mesh; - pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction - // data will be requested from asset on rez (i hope) + int meshindx = inner_instance_list["mesh"].AsInteger(); + if (meshAssets.Count > meshindx) + { + pbs.SculptEntry = true; + pbs.SculptType = (byte)SculptType.Mesh; + pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction + // data will be requested from asset on rez (i hope) + hasmesh = true; + } } Vector3 position = inner_instance_list["position"].AsVector3(); Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); + // for now viwers do send fixed defaults + // but this may change +// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger(); + byte physicsShapeType = (byte)PhysShapeType.prim; // default for mesh is simple convex + if(hasmesh) + physicsShapeType = (byte) PhysShapeType.convex; // default for mesh is simple convex +// int material = inner_instance_list["material"].AsInteger(); + byte material = (byte)Material.Wood; + // no longer used - begin ------------------------ -// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger(); -// int material = inner_instance_list["material"].AsInteger(); // int mesh = inner_instance_list["mesh"].AsInteger(); // OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; @@ -866,23 +909,41 @@ namespace OpenSim.Region.ClientStack.Linden // int owner_mask = permissions["owner_mask"].AsInteger(); // no longer used - end ------------------------ - UUID owner_id = m_HostCapsObj.AgentID; + SceneObjectPart prim = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); prim.Scale = scale; - prim.OffsetPosition = position; +// prim.OffsetPosition = position; rotations.Add(rotation); positions.Add(position); prim.UUID = UUID.Random(); - prim.CreatorID = owner_id; + prim.CreatorID = creatorID; prim.OwnerID = owner_id; prim.GroupID = UUID.Zero; - prim.LastOwnerID = prim.OwnerID; + prim.LastOwnerID = creatorID; prim.CreationDate = Util.UnixTimeSinceEpoch(); - prim.Name = assetName; - prim.Description = ""; + + if (grp == null) + prim.Name = assetName; + else + prim.Name = assetName + "#" + i.ToString(); + + if (istest) + { + prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify); + prim.EveryoneMask = 0; + prim.GroupMask = 0; + prim.NextOwnerMask = 0; + prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify); + + prim.Description = "For personal testing only. Other uses are forbiden"; + } + else + prim.Description = ""; + prim.Material = material; + prim.PhysicsShapeType = physicsShapeType; // prim.BaseMask = (uint)base_mask; // prim.EveryoneMask = (uint)everyone_mask; @@ -891,30 +952,48 @@ namespace OpenSim.Region.ClientStack.Linden // prim.OwnerMask = (uint)owner_mask; if (grp == null) + { grp = new SceneObjectGroup(prim); + grp.LastOwnerID = creatorID; + } else grp.AddPart(prim); } - // Fix first link number + Vector3 rootPos = positions[0]; + if (grp.Parts.Length > 1) + { + // Fix first link number grp.RootPart.LinkNum++; - Vector3 rootPos = positions[0]; - grp.AbsolutePosition = rootPos; - for (int i = 0; i < positions.Count; i++) + Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]); + Quaternion tmprot; + Vector3 offset; + + // fix children rotations and positions + for (int i = 1; i < rotations.Count; i++) + { + tmprot = rotations[i]; + tmprot = rootRotConj * tmprot; + + grp.Parts[i].RotationOffset = tmprot; + + offset = positions[i] - rootPos; + + offset *= rootRotConj; + grp.Parts[i].OffsetPosition = offset; + } + + grp.AbsolutePosition = rootPos; + grp.UpdateGroupRotationR(rotations[0]); + } + else { - Vector3 offset = positions[i] - rootPos; - grp.Parts[i].OffsetPosition = offset; + grp.AbsolutePosition = rootPos; + grp.UpdateGroupRotationR(rotations[0]); } - for (int i = 0; i < rotations.Count; i++) - { - if (i != 0) - grp.Parts[i].RotationOffset = rotations[i]; - } - - grp.UpdateGroupRotationR(rotations[0]); data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp)); } @@ -926,7 +1005,7 @@ namespace OpenSim.Region.ClientStack.Linden } AssetBase asset; - asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString()); + asset = new AssetBase(assetID, assetName, assType, creatorIDstr); asset.Data = data; if (AddNewAsset != null) AddNewAsset(asset); @@ -935,11 +1014,14 @@ namespace OpenSim.Region.ClientStack.Linden InventoryItemBase item = new InventoryItemBase(); item.Owner = m_HostCapsObj.AgentID; - item.CreatorId = m_HostCapsObj.AgentID.ToString(); + item.CreatorId = creatorIDstr; item.CreatorData = String.Empty; item.ID = inventoryItem; item.AssetID = asset.FullID; - item.Description = assetDescription; + if (istest) + item.Description = "For personal testing only. Other uses are forbiden"; + else + item.Description = assetDescription; item.Name = assetName; item.AssetType = assType; item.InvType = inType; @@ -947,18 +1029,56 @@ namespace OpenSim.Region.ClientStack.Linden // If we set PermissionMask.All then when we rez the item the next permissions will replace the current // (owner) permissions. This becomes a problem if next permissions are changed. - item.CurrentPermissions - = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); - item.BasePermissions = (uint)PermissionMask.All; - item.EveryOnePermissions = 0; - item.NextPermissions = (uint)PermissionMask.All; + if (istest) + { + item.CurrentPermissions + = (uint)(PermissionMask.Move | PermissionMask.Modify); + + item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify); + item.EveryOnePermissions = 0; + item.NextPermissions = 0; + } + else + { + item.CurrentPermissions + = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); + + item.BasePermissions = (uint)PermissionMask.All; + item.EveryOnePermissions = 0; + item.NextPermissions = (uint)PermissionMask.All; + } + item.CreationDate = Util.UnixTimeSinceEpoch(); + IClientAPI client = null; + m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client); + if (AddNewInventoryItem != null) { - AddNewInventoryItem(m_HostCapsObj.AgentID, item, cost); + if (istest) + { + AddNewInventoryItem(m_HostCapsObj.AgentID, item, 0); + if (client != null) + client.SendAgentAlertMessage("Upload complete with no cost for personal testing purposes only. Other uses are forbiden", true); + } + else + { + AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost); + if (client != null) + { + // let users see anything.. i don't so far + string str; + if (cost > 0) + // dont remember where is money unit name to put here + str = "Upload complete. charged " + cost.ToString() + "$"; + else + str = "Upload complete"; + client.SendAgentAlertMessage(str, true); + } + } } + lock (m_ModelCost) m_FileAgentInventoryState = FileAgentInventoryState.idle; } @@ -1273,6 +1393,7 @@ namespace OpenSim.Region.ClientStack.Linden private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + public event UpLoadedAsset OnUpLoad; private UpLoadedAsset handlerUpLoad = null; @@ -1287,11 +1408,21 @@ namespace OpenSim.Region.ClientStack.Linden private string m_invType = String.Empty; private string m_assetType = String.Empty; + private int m_cost; + private string m_error = String.Empty; + private Timer m_timeoutTimer = new Timer(); + private UUID m_texturesFolder; + private int m_nreqtextures; + private int m_nreqmeshs; + private int m_nreqinstances; + private bool m_IsAtestUpload; public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolderID, string invType, string assetType, string path, - IHttpServer httpServer, bool dumpAssetsToFile) + IHttpServer httpServer, bool dumpAssetsToFile, + int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances, + bool IsAtestUpload) { m_assetName = assetName; m_assetDes = description; @@ -1303,6 +1434,13 @@ namespace OpenSim.Region.ClientStack.Linden m_assetType = assetType; m_invType = invType; m_dumpAssetsToFile = dumpAssetsToFile; + m_cost = totalCost; + + m_texturesFolder = texturesFolder; + m_nreqtextures = nreqtextures; + m_nreqmeshs = nreqmeshs; + m_nreqinstances = nreqinstances; + m_IsAtestUpload = IsAtestUpload; m_timeoutTimer.Elapsed += TimedOut; m_timeoutTimer.Interval = 120000; @@ -1322,12 +1460,13 @@ namespace OpenSim.Region.ClientStack.Linden UUID inv = inventoryItemID; string res = String.Empty; LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); +/* uploadComplete.new_asset = newAssetID.ToString(); uploadComplete.new_inventory_item = inv; uploadComplete.state = "complete"; res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); - +*/ m_timeoutTimer.Stop(); httpListener.RemoveStreamHandler("POST", uploaderPath); @@ -1345,8 +1484,28 @@ namespace OpenSim.Region.ClientStack.Linden handlerUpLoad = OnUpLoad; if (handlerUpLoad != null) { - handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType); + handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType, + m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload, ref m_error); } + if(m_error == String.Empty) + { + uploadComplete.new_asset = newAssetID.ToString(); + uploadComplete.new_inventory_item = inv; +// if (m_texturesFolder != UUID.Zero) +// uploadComplete.new_texture_folder_id = m_texturesFolder; + uploadComplete.state = "complete"; + } + else + { + LLSDAssetUploadError resperror = new LLSDAssetUploadError(); + resperror.message = m_error; + resperror.identifier = inv; + + uploadComplete.error = resperror; + uploadComplete.state = "failed"; + } + + res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); return res; } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs index da701baa02..66bb42921d 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs @@ -31,7 +31,7 @@ namespace OpenSim.Region.ClientStack.Linden public class ModelCost { - // upload fee tunning paramenters + // upload fee defaults // fees are normalized to 1.0 // this parameters scale them to basic cost ( so 1.0 translates to 10 ) @@ -42,7 +42,6 @@ namespace OpenSim.Region.ClientStack.Linden public float ModelTextureCostFactor = 1.00f; // keep full price because texture price // is based on it's storage needs not on usability - // itens costs in normalized values // ie will be multiplied by basicCost and factors above const float primCreationCost = 0.002f; // extra cost for each prim creation overhead @@ -100,7 +99,8 @@ namespace OpenSim.Region.ClientStack.Linden // basicCost input region assets upload cost // totalcost returns model total upload fee // meshcostdata returns detailed costs for viewer - public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost, LLSDAssetUploadResponseData meshcostdata, out string error) + public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost, + LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning) { totalcost = 0; error = string.Empty; @@ -109,7 +109,7 @@ namespace OpenSim.Region.ClientStack.Linden resources.instance_list == null || resources.instance_list.Array.Count == 0) { - error = "Unable to upload mesh model. missing information."; + error = "missing model information."; return false; } @@ -117,7 +117,7 @@ namespace OpenSim.Region.ClientStack.Linden if( numberInstances > ObjectLinkedPartsMax ) { - error = "upload failed: Model whould have two many linked prims"; + error = "Model whould have more than " + ObjectLinkedPartsMax.ToString() + " linked prims"; return false; } @@ -190,15 +190,13 @@ namespace OpenSim.Region.ClientStack.Linden if (scale.X < PrimScaleMin || scale.Y < PrimScaleMin || scale.Z < PrimScaleMin) { -// error = " upload fail: Model contains parts with a dimension lower than 0.001. Please adjust scaling"; -// return false; skipedSmall++; continue; } if (scale.X > NonPhysicalPrimScaleMax || scale.Y > NonPhysicalPrimScaleMax || scale.Z > NonPhysicalPrimScaleMax) { - error = "upload fail: Model contains parts larger than maximum allowed. Please adjust scaling"; + error = "Model contains parts with sides larger than " + NonPhysicalPrimScaleMax.ToString() + "m. Please ajust scale"; return false; } @@ -208,7 +206,7 @@ namespace OpenSim.Region.ClientStack.Linden if (mesh >= numberMeshs) { - error = "Unable to upload mesh model. incoerent information."; + error = "Incoerent model information."; return false; } @@ -235,10 +233,18 @@ namespace OpenSim.Region.ClientStack.Linden meshsfee += primCreationCost; } - if (skipedSmall >0 && skipedSmall > numberInstances / 2) + if (skipedSmall > 0) { - error = "Upload failed: Model contains too much prims smaller than minimum size to ignore"; - return false; + if (skipedSmall > numberInstances / 2) + { + error = "Model contains too many prims smaller than " + PrimScaleMin.ToString() + + "m minimum allowed size. Please check scalling"; + return false; + } + else + warning += skipedSmall.ToString() + " of the requested " +numberInstances.ToString() + + " model prims will not upload because they are smaller than " + PrimScaleMin.ToString() + + "m minimum allowed size. Please check scalling "; } if (meshcostdata.physics_cost <= meshcostdata.model_streaming_cost) @@ -283,14 +289,14 @@ namespace OpenSim.Region.ClientStack.Linden if (data == null || data.Length == 0) { - error = "Unable to upload mesh model. missing information."; + error = "Missing model information."; return false; } OSD meshOsd = null; int start = 0; - error = "Unable to upload mesh model. Invalid data"; + error = "Invalid model data"; using (MemoryStream ms = new MemoryStream(data)) { @@ -338,13 +344,13 @@ namespace OpenSim.Region.ClientStack.Linden if (submesh_offset < 0 || hulls_size == 0) { - error = "Unable to upload mesh model. missing physics_convex block"; + error = "Missing physics_convex block"; return false; } if (!hulls(data, submesh_offset, hulls_size, out phys_hullsvertices, out phys_nhulls)) { - error = "Unable to upload mesh model. bad physics_convex block"; + error = "Bad physics_convex block"; return false; } @@ -364,7 +370,7 @@ namespace OpenSim.Region.ClientStack.Linden if (submesh_offset < 0 || highlod_size <= 0) { - error = "Unable to upload mesh model. missing high_lod"; + error = "Missing high_lod block"; return false; } @@ -409,9 +415,14 @@ namespace OpenSim.Region.ClientStack.Linden submesh_offset = -1; - if (map.ContainsKey("physics_mesh")) - { + tmpmap = null; + if(map.ContainsKey("physics_mesh")) tmpmap = (OSDMap)map["physics_mesh"]; + else if (map.ContainsKey("physics_shape")) // old naming + tmpmap = (OSDMap)map["physics_shape"]; + + if(tmpmap != null) + { if (tmpmap.ContainsKey("offset")) submesh_offset = tmpmap["offset"].AsInteger() + start; if (tmpmap.ContainsKey("size")) @@ -422,7 +433,7 @@ namespace OpenSim.Region.ClientStack.Linden if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles)) { - error = "Unable to upload mesh model. parsing error"; + error = "Model data parsing error"; return false; } } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs index 44a68839ca..0251ac4d99 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs @@ -129,15 +129,15 @@ namespace OpenSim.Region.ClientStack.Linden // m_log.DebugFormat("[MESH UPLOAD FLAG MODULE]: MeshUploadFlag request"); OSDMap data = new OSDMap(); - ScenePresence sp = m_scene.GetScenePresence(m_agentID); - data["username"] = sp.Firstname + "." + sp.Lastname; - data["display_name_next_update"] = new OSDDate(DateTime.Now); - data["legacy_first_name"] = sp.Firstname; +// ScenePresence sp = m_scene.GetScenePresence(m_agentID); +// data["username"] = sp.Firstname + "." + sp.Lastname; +// data["display_name_next_update"] = new OSDDate(DateTime.Now); +// data["legacy_first_name"] = sp.Firstname; data["mesh_upload_status"] = "valid"; - data["display_name"] = sp.Firstname + " " + sp.Lastname; - data["legacy_last_name"] = sp.Lastname; - data["id"] = m_agentID; - data["is_display_name_default"] = true; +// data["display_name"] = sp.Firstname + " " + sp.Lastname; +// data["legacy_last_name"] = sp.Lastname; +// data["id"] = m_agentID; +// data["is_display_name_default"] = true; //Send back data Hashtable responsedata = new Hashtable();