Compare commits
94 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5eb2526e88 | ||
|
|
641b08aa78 | ||
|
|
15d5f3d09d | ||
|
|
07dbe46ba3 | ||
|
|
ff867b59cf | ||
|
|
d4b8a13a1d | ||
|
|
a858c5daee | ||
|
|
8d431c6359 | ||
|
|
663bfbb372 | ||
|
|
d297eb39e5 | ||
|
|
29218cdb31 | ||
|
|
359f9efc76 | ||
|
|
fb211c64fd | ||
|
|
a3d140b57c | ||
|
|
f7b88d1c40 | ||
|
|
32b534f324 | ||
|
|
ffdc798720 | ||
|
|
ae852bb873 | ||
|
|
d3adf9b2b3 | ||
|
|
7c140570db | ||
|
|
7b6987ce83 | ||
|
|
0376b8ddbc | ||
|
|
2d2495cc45 | ||
|
|
a0eda6eb16 | ||
|
|
dac31303b7 | ||
|
|
edd3577b66 | ||
|
|
054db94d5d | ||
|
|
794c5f5a6d | ||
|
|
b625579780 | ||
|
|
7e41559917 | ||
|
|
8cd415c2b0 | ||
|
|
4c58c1b116 | ||
|
|
e6f43023b6 | ||
|
|
bcf944db48 | ||
|
|
7a9eee8538 | ||
|
|
05648c2c4a | ||
|
|
dff746df7b | ||
|
|
973f2e8be5 | ||
|
|
3c019bea8c | ||
|
|
68814f904e | ||
|
|
3bd3f448a2 | ||
|
|
7c6e8fab15 | ||
|
|
3ed0d79b00 | ||
|
|
d89b974680 | ||
|
|
c76c63725b | ||
|
|
6b277394c0 | ||
|
|
adce58b33a | ||
|
|
1f88179a65 | ||
|
|
ec726413dd | ||
|
|
3d736d575f | ||
|
|
0c3061f973 | ||
|
|
3bf7bd6359 | ||
|
|
7ea832d47c | ||
|
|
c1cece4b82 | ||
|
|
aa44df9c04 | ||
|
|
1e18f0f26a | ||
|
|
8a7fbfb06a | ||
|
|
e916b1399f | ||
|
|
72c2d13ac6 | ||
|
|
a6d689c529 | ||
|
|
ab9bfe5156 | ||
|
|
4e26d039d6 | ||
|
|
3082fdd0f6 | ||
|
|
e90168c738 | ||
|
|
a5c6cb2fc9 | ||
|
|
6ea95a3294 | ||
|
|
6e86b23012 | ||
|
|
58714b0aca | ||
|
|
5203665bb2 | ||
|
|
2a2e120470 | ||
|
|
a8044999fb | ||
|
|
3d504261b0 | ||
|
|
a0d178b284 | ||
|
|
f8a89a79eb | ||
|
|
e04047152f | ||
|
|
f3a5e3a02b | ||
|
|
ba58331b29 | ||
|
|
476996bee8 | ||
|
|
01771aca40 | ||
|
|
cd325fdf02 | ||
|
|
67477290ad | ||
|
|
582a256646 | ||
|
|
d188272462 | ||
|
|
632908db9e | ||
|
|
82b23f7cc1 | ||
|
|
a08687aef3 | ||
|
|
2ad9d656b3 | ||
|
|
1747030d19 | ||
|
|
c557684666 | ||
|
|
a3cbda0d74 | ||
|
|
4f3fabae5b | ||
|
|
aede42b875 | ||
|
|
a533db7e27 | ||
|
|
4820dfd733 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -26,9 +26,14 @@
|
||||
bin/Debug/*.dll
|
||||
bin/*.dll.mdb
|
||||
bin/*.db
|
||||
bin/*.db-journal
|
||||
bin/addin-db-*
|
||||
bin/*.dll
|
||||
bin/OpenSim.vshost.exe.config
|
||||
bin/OpenSim.32BitLaunch.vshost.exe.config
|
||||
bin/OpenSim.32BitLaunch.log
|
||||
UpgradeLog.XML
|
||||
_UpgradeReport_Files/
|
||||
bin/ScriptEngines/*-*-*-*-*
|
||||
bin/ScriptEngines/*.dll
|
||||
bin/ScriptEngines/*/*.dll
|
||||
|
||||
@@ -135,14 +135,25 @@
|
||||
<delete dir="%temp%"/>
|
||||
</target>
|
||||
|
||||
<target name="torture" depends="build, find-nunit">
|
||||
<target name="test-stress" depends="build, find-nunit">
|
||||
<setenv name="MONO_THREADS_PER_CPU" value="100" />
|
||||
|
||||
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.torture">
|
||||
<arg value="./bin/OpenSim.Tests.Torture.dll" />
|
||||
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.stress">
|
||||
<arg value="./bin/OpenSim.Tests.Stress.dll" />
|
||||
</exec>
|
||||
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.torture)==0}" />
|
||||
<fail message="Failures reported in stress tests." unless="${int::parse(testresult.opensim.tests.stress)==0}" />
|
||||
<delete dir="%temp%"/>
|
||||
</target>
|
||||
|
||||
<target name="test-perf" depends="build, find-nunit">
|
||||
<setenv name="MONO_THREADS_PER_CPU" value="100" />
|
||||
|
||||
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.performance">
|
||||
<arg value="./bin/OpenSim.Tests.Performance.dll" />
|
||||
</exec>
|
||||
|
||||
<fail message="Failures reported in performance tests." unless="${int::parse(testresult.opensim.tests.performance)==0}" />
|
||||
<delete dir="%temp%"/>
|
||||
</target>
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ what it is today.
|
||||
* Flyte Xevious
|
||||
* Garmin Kawaguichi
|
||||
* Gryc Ueusp
|
||||
* Hiro Lecker
|
||||
* Imaze Rhiano
|
||||
* Intimidated
|
||||
* Jeremy Bongio (IBM)
|
||||
|
||||
@@ -40,6 +40,11 @@ namespace OpenSim.Data
|
||||
public UUID folderID;
|
||||
public UUID agentID;
|
||||
public UUID parentFolderID;
|
||||
|
||||
public XInventoryFolder Clone()
|
||||
{
|
||||
return (XInventoryFolder)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
public class XInventoryItem
|
||||
@@ -64,6 +69,11 @@ namespace OpenSim.Data
|
||||
public UUID avatarID;
|
||||
public UUID parentFolderID;
|
||||
public int inventoryGroupPermissions;
|
||||
|
||||
public XInventoryItem Clone()
|
||||
{
|
||||
return (XInventoryItem)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
public interface IXInventoryData
|
||||
|
||||
@@ -719,95 +719,99 @@ namespace OpenSim.Data.MySQL
|
||||
RegionLightShareData nWP = new RegionLightShareData();
|
||||
nWP.OnSave += StoreRegionWindlightSettings;
|
||||
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
lock (m_dbLock)
|
||||
{
|
||||
dbcon.Open();
|
||||
|
||||
string command = "select * from `regionwindlight` where region_id = ?regionID";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(command))
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
{
|
||||
cmd.Connection = dbcon;
|
||||
|
||||
cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString());
|
||||
|
||||
IDataReader result = ExecuteReader(cmd);
|
||||
if (!result.Read())
|
||||
dbcon.Open();
|
||||
|
||||
string command = "select * from `regionwindlight` where region_id = ?regionID";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(command))
|
||||
{
|
||||
//No result, so store our default windlight profile and return it
|
||||
nWP.regionID = regionUUID;
|
||||
StoreRegionWindlightSettings(nWP);
|
||||
return nWP;
|
||||
}
|
||||
else
|
||||
{
|
||||
nWP.regionID = DBGuid.FromDB(result["region_id"]);
|
||||
nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]);
|
||||
nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]);
|
||||
nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]);
|
||||
nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]);
|
||||
nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]);
|
||||
nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]);
|
||||
nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]);
|
||||
nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]);
|
||||
nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]);
|
||||
nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]);
|
||||
nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]);
|
||||
nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]);
|
||||
nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]);
|
||||
nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]);
|
||||
nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]);
|
||||
nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]);
|
||||
nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]);
|
||||
UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture);
|
||||
nWP.horizon.X = Convert.ToSingle(result["horizon_r"]);
|
||||
nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]);
|
||||
nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]);
|
||||
nWP.horizon.W = Convert.ToSingle(result["horizon_i"]);
|
||||
nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]);
|
||||
nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]);
|
||||
nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]);
|
||||
nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]);
|
||||
nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]);
|
||||
nWP.hazeDensity = Convert.ToSingle(result["haze_density"]);
|
||||
nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]);
|
||||
nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]);
|
||||
nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]);
|
||||
nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]);
|
||||
nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]);
|
||||
nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]);
|
||||
nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]);
|
||||
nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]);
|
||||
nWP.ambient.X = Convert.ToSingle(result["ambient_r"]);
|
||||
nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]);
|
||||
nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]);
|
||||
nWP.ambient.W = Convert.ToSingle(result["ambient_i"]);
|
||||
nWP.eastAngle = Convert.ToSingle(result["east_angle"]);
|
||||
nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]);
|
||||
nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]);
|
||||
nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]);
|
||||
nWP.starBrightness = Convert.ToSingle(result["star_brightness"]);
|
||||
nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]);
|
||||
nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]);
|
||||
nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]);
|
||||
nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]);
|
||||
nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]);
|
||||
nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]);
|
||||
nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]);
|
||||
nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]);
|
||||
nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]);
|
||||
nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]);
|
||||
nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]);
|
||||
nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]);
|
||||
nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]);
|
||||
nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]);
|
||||
nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]);
|
||||
nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]);
|
||||
nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]);
|
||||
nWP.valid = true;
|
||||
cmd.Connection = dbcon;
|
||||
|
||||
cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString());
|
||||
|
||||
IDataReader result = ExecuteReader(cmd);
|
||||
if (!result.Read())
|
||||
{
|
||||
//No result, so store our default windlight profile and return it
|
||||
nWP.regionID = regionUUID;
|
||||
StoreRegionWindlightSettings(nWP);
|
||||
return nWP;
|
||||
}
|
||||
else
|
||||
{
|
||||
nWP.regionID = DBGuid.FromDB(result["region_id"]);
|
||||
nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]);
|
||||
nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]);
|
||||
nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]);
|
||||
nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]);
|
||||
nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]);
|
||||
nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]);
|
||||
nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]);
|
||||
nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]);
|
||||
nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]);
|
||||
nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]);
|
||||
nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]);
|
||||
nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]);
|
||||
nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]);
|
||||
nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]);
|
||||
nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]);
|
||||
nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]);
|
||||
nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]);
|
||||
UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture);
|
||||
nWP.horizon.X = Convert.ToSingle(result["horizon_r"]);
|
||||
nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]);
|
||||
nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]);
|
||||
nWP.horizon.W = Convert.ToSingle(result["horizon_i"]);
|
||||
nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]);
|
||||
nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]);
|
||||
nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]);
|
||||
nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]);
|
||||
nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]);
|
||||
nWP.hazeDensity = Convert.ToSingle(result["haze_density"]);
|
||||
nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]);
|
||||
nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]);
|
||||
nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]);
|
||||
nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]);
|
||||
nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]);
|
||||
nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]);
|
||||
nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]);
|
||||
nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]);
|
||||
nWP.ambient.X = Convert.ToSingle(result["ambient_r"]);
|
||||
nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]);
|
||||
nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]);
|
||||
nWP.ambient.W = Convert.ToSingle(result["ambient_i"]);
|
||||
nWP.eastAngle = Convert.ToSingle(result["east_angle"]);
|
||||
nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]);
|
||||
nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]);
|
||||
nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]);
|
||||
nWP.starBrightness = Convert.ToSingle(result["star_brightness"]);
|
||||
nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]);
|
||||
nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]);
|
||||
nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]);
|
||||
nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]);
|
||||
nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]);
|
||||
nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]);
|
||||
nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]);
|
||||
nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]);
|
||||
nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]);
|
||||
nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]);
|
||||
nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]);
|
||||
nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]);
|
||||
nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]);
|
||||
nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]);
|
||||
nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]);
|
||||
nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]);
|
||||
nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]);
|
||||
nWP.valid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nWP;
|
||||
}
|
||||
|
||||
@@ -853,118 +857,124 @@ namespace OpenSim.Data.MySQL
|
||||
|
||||
public void StoreRegionWindlightSettings(RegionLightShareData wl)
|
||||
{
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
lock (m_dbLock)
|
||||
{
|
||||
dbcon.Open();
|
||||
|
||||
using (MySqlCommand cmd = dbcon.CreateCommand())
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
{
|
||||
cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, ";
|
||||
cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, ";
|
||||
cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, ";
|
||||
cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, ";
|
||||
cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, ";
|
||||
cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, ";
|
||||
cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, ";
|
||||
cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, ";
|
||||
cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, ";
|
||||
cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, ";
|
||||
cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, ";
|
||||
cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, ";
|
||||
cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, ";
|
||||
cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, ";
|
||||
cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, ";
|
||||
cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, ";
|
||||
cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, ";
|
||||
cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, ";
|
||||
cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, ";
|
||||
cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, ";
|
||||
cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, ";
|
||||
cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, ";
|
||||
cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, ";
|
||||
cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, ";
|
||||
cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)";
|
||||
|
||||
cmd.Parameters.AddWithValue("region_id", wl.regionID);
|
||||
cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X);
|
||||
cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y);
|
||||
cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z);
|
||||
cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent);
|
||||
cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier);
|
||||
cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X);
|
||||
cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y);
|
||||
cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z);
|
||||
cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale);
|
||||
cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset);
|
||||
cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove);
|
||||
cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow);
|
||||
cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier);
|
||||
cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X);
|
||||
cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y);
|
||||
cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X);
|
||||
cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y);
|
||||
cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture);
|
||||
cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X);
|
||||
cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y);
|
||||
cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z);
|
||||
cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W);
|
||||
cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon);
|
||||
cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X);
|
||||
cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y);
|
||||
cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z);
|
||||
cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W);
|
||||
cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity);
|
||||
cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier);
|
||||
cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier);
|
||||
cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude);
|
||||
cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X);
|
||||
cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y);
|
||||
cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z);
|
||||
cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W);
|
||||
cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition);
|
||||
cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X);
|
||||
cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y);
|
||||
cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z);
|
||||
cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W);
|
||||
cmd.Parameters.AddWithValue("east_angle", wl.eastAngle);
|
||||
cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus);
|
||||
cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize);
|
||||
cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma);
|
||||
cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness);
|
||||
cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X);
|
||||
cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y);
|
||||
cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z);
|
||||
cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W);
|
||||
cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X);
|
||||
cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y);
|
||||
cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z);
|
||||
cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage);
|
||||
cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale);
|
||||
cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X);
|
||||
cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y);
|
||||
cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z);
|
||||
cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX);
|
||||
cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock);
|
||||
cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY);
|
||||
cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock);
|
||||
cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds);
|
||||
|
||||
ExecuteNonQuery(cmd);
|
||||
dbcon.Open();
|
||||
|
||||
using (MySqlCommand cmd = dbcon.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, ";
|
||||
cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, ";
|
||||
cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, ";
|
||||
cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, ";
|
||||
cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, ";
|
||||
cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, ";
|
||||
cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, ";
|
||||
cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, ";
|
||||
cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, ";
|
||||
cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, ";
|
||||
cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, ";
|
||||
cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, ";
|
||||
cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, ";
|
||||
cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, ";
|
||||
cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, ";
|
||||
cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, ";
|
||||
cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, ";
|
||||
cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, ";
|
||||
cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, ";
|
||||
cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, ";
|
||||
cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, ";
|
||||
cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, ";
|
||||
cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, ";
|
||||
cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, ";
|
||||
cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)";
|
||||
|
||||
cmd.Parameters.AddWithValue("region_id", wl.regionID);
|
||||
cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X);
|
||||
cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y);
|
||||
cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z);
|
||||
cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent);
|
||||
cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier);
|
||||
cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X);
|
||||
cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y);
|
||||
cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z);
|
||||
cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale);
|
||||
cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset);
|
||||
cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove);
|
||||
cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow);
|
||||
cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier);
|
||||
cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X);
|
||||
cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y);
|
||||
cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X);
|
||||
cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y);
|
||||
cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture);
|
||||
cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X);
|
||||
cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y);
|
||||
cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z);
|
||||
cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W);
|
||||
cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon);
|
||||
cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X);
|
||||
cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y);
|
||||
cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z);
|
||||
cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W);
|
||||
cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity);
|
||||
cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier);
|
||||
cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier);
|
||||
cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude);
|
||||
cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X);
|
||||
cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y);
|
||||
cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z);
|
||||
cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W);
|
||||
cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition);
|
||||
cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X);
|
||||
cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y);
|
||||
cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z);
|
||||
cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W);
|
||||
cmd.Parameters.AddWithValue("east_angle", wl.eastAngle);
|
||||
cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus);
|
||||
cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize);
|
||||
cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma);
|
||||
cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness);
|
||||
cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X);
|
||||
cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y);
|
||||
cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z);
|
||||
cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W);
|
||||
cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X);
|
||||
cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y);
|
||||
cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z);
|
||||
cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage);
|
||||
cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale);
|
||||
cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X);
|
||||
cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y);
|
||||
cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z);
|
||||
cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX);
|
||||
cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock);
|
||||
cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY);
|
||||
cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock);
|
||||
cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds);
|
||||
|
||||
ExecuteNonQuery(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveRegionWindlightSettings(UUID regionID)
|
||||
{
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
lock (m_dbLock)
|
||||
{
|
||||
dbcon.Open();
|
||||
|
||||
using (MySqlCommand cmd = dbcon.CreateCommand())
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
{
|
||||
cmd.CommandText = "delete from `regionwindlight` where `region_id`=?regionID";
|
||||
cmd.Parameters.AddWithValue("?regionID", regionID.ToString());
|
||||
ExecuteNonQuery(cmd);
|
||||
dbcon.Open();
|
||||
|
||||
using (MySqlCommand cmd = dbcon.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "delete from `regionwindlight` where `region_id`=?regionID";
|
||||
cmd.Parameters.AddWithValue("?regionID", regionID.ToString());
|
||||
ExecuteNonQuery(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -972,26 +982,29 @@ namespace OpenSim.Data.MySQL
|
||||
#region RegionEnvironmentSettings
|
||||
public string LoadRegionEnvironmentSettings(UUID regionUUID)
|
||||
{
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
lock (m_dbLock)
|
||||
{
|
||||
dbcon.Open();
|
||||
|
||||
string command = "select * from `regionenvironment` where region_id = ?region_id";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(command))
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
{
|
||||
cmd.Connection = dbcon;
|
||||
|
||||
cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
|
||||
|
||||
IDataReader result = ExecuteReader(cmd);
|
||||
if (!result.Read())
|
||||
dbcon.Open();
|
||||
|
||||
string command = "select * from `regionenvironment` where region_id = ?region_id";
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand(command))
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Convert.ToString(result["llsd_settings"]);
|
||||
cmd.Connection = dbcon;
|
||||
|
||||
cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
|
||||
|
||||
IDataReader result = ExecuteReader(cmd);
|
||||
if (!result.Read())
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Convert.ToString(result["llsd_settings"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -999,33 +1012,39 @@ namespace OpenSim.Data.MySQL
|
||||
|
||||
public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
|
||||
{
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
lock (m_dbLock)
|
||||
{
|
||||
dbcon.Open();
|
||||
|
||||
using (MySqlCommand cmd = dbcon.CreateCommand())
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
{
|
||||
cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)";
|
||||
|
||||
cmd.Parameters.AddWithValue("region_id", regionUUID);
|
||||
cmd.Parameters.AddWithValue("llsd_settings", settings);
|
||||
|
||||
ExecuteNonQuery(cmd);
|
||||
dbcon.Open();
|
||||
|
||||
using (MySqlCommand cmd = dbcon.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)";
|
||||
|
||||
cmd.Parameters.AddWithValue("region_id", regionUUID);
|
||||
cmd.Parameters.AddWithValue("llsd_settings", settings);
|
||||
|
||||
ExecuteNonQuery(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveRegionEnvironmentSettings(UUID regionUUID)
|
||||
{
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
lock (m_dbLock)
|
||||
{
|
||||
dbcon.Open();
|
||||
|
||||
using (MySqlCommand cmd = dbcon.CreateCommand())
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
{
|
||||
cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id";
|
||||
cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
|
||||
ExecuteNonQuery(cmd);
|
||||
dbcon.Open();
|
||||
|
||||
using (MySqlCommand cmd = dbcon.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id";
|
||||
cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
|
||||
ExecuteNonQuery(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,33 +73,27 @@ namespace OpenSim.Framework
|
||||
{
|
||||
}
|
||||
|
||||
public InventoryFolderBase(UUID id)
|
||||
public InventoryFolderBase(UUID id) : this()
|
||||
{
|
||||
ID = id;
|
||||
}
|
||||
|
||||
public InventoryFolderBase(UUID id, UUID owner)
|
||||
public InventoryFolderBase(UUID id, UUID owner) : this(id)
|
||||
{
|
||||
ID = id;
|
||||
Owner = owner;
|
||||
}
|
||||
|
||||
public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent)
|
||||
public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) : this(id, owner)
|
||||
{
|
||||
ID = id;
|
||||
Name = name;
|
||||
Owner = owner;
|
||||
ParentID = parent;
|
||||
}
|
||||
|
||||
public InventoryFolderBase(UUID id, string name, UUID owner, short type, UUID parent, ushort version)
|
||||
public InventoryFolderBase(
|
||||
UUID id, string name, UUID owner, short type, UUID parent, ushort version) : this(id, name, owner, parent)
|
||||
{
|
||||
ID = id;
|
||||
Name = name;
|
||||
Owner = owner;
|
||||
Type = type;
|
||||
ParentID = parent;
|
||||
Version = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,9 +65,14 @@ namespace OpenSim.Framework.Serialization
|
||||
|
||||
UserAccount account = userService.GetUserAccount(UUID.Zero, userId);
|
||||
if (account != null)
|
||||
{
|
||||
return MakeOspa(account.FirstName, account.LastName);
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId);
|
||||
// System.Console.WriteLine("[OSP RESOLVER]: No user account for {0}", userId);
|
||||
// }
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -79,10 +84,13 @@ namespace OpenSim.Framework.Serialization
|
||||
/// <returns></returns>
|
||||
public static string MakeOspa(string firstName, string lastName)
|
||||
{
|
||||
// m_log.DebugFormat("[OSP RESOLVER]: Making OSPA for {0} {1}", firstName, lastName);
|
||||
string ospa
|
||||
= OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
|
||||
|
||||
// m_log.DebugFormat("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
|
||||
// System.Console.WriteLine("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
|
||||
|
||||
return
|
||||
OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
|
||||
return ospa;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace OpenSim
|
||||
{
|
||||
public class VersionInfo
|
||||
{
|
||||
private const string VERSION_NUMBER = "0.7.4";
|
||||
private const string VERSION_NUMBER = "0.7.5";
|
||||
private const Flavour VERSION_FLAVOUR = Flavour.Dev;
|
||||
|
||||
public enum Flavour
|
||||
|
||||
@@ -4451,37 +4451,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||
if (bl[i].BannedUserID == UUID.Zero)
|
||||
continue;
|
||||
BannedUsers.Add(bl[i].BannedUserID);
|
||||
|
||||
if (BannedUsers.Count >= 50 || (i == (bl.Length - 1) && BannedUsers.Count > 0))
|
||||
{
|
||||
EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
|
||||
packet.AgentData.TransactionID = UUID.Random();
|
||||
packet.AgentData.AgentID = AgentId;
|
||||
packet.AgentData.SessionID = SessionId;
|
||||
packet.MethodData.Invoice = invoice;
|
||||
packet.MethodData.Method = Utils.StringToBytes("setaccess");
|
||||
|
||||
EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count];
|
||||
|
||||
int j;
|
||||
for (j = 0; j < (6 + BannedUsers.Count); j++)
|
||||
{
|
||||
returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
|
||||
}
|
||||
j = 0;
|
||||
|
||||
returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
|
||||
returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
|
||||
returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
|
||||
returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
|
||||
returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++;
|
||||
returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
|
||||
|
||||
foreach (UUID banned in BannedUsers)
|
||||
{
|
||||
returnblock[j].Parameter = banned.GetBytes(); j++;
|
||||
}
|
||||
packet.ParamList = returnblock;
|
||||
packet.Header.Reliable = true;
|
||||
OutPacket(packet, ThrottleOutPacketType.Task);
|
||||
|
||||
BannedUsers.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
|
||||
packet.AgentData.TransactionID = UUID.Random();
|
||||
packet.AgentData.AgentID = AgentId;
|
||||
packet.AgentData.SessionID = SessionId;
|
||||
packet.MethodData.Invoice = invoice;
|
||||
packet.MethodData.Method = Utils.StringToBytes("setaccess");
|
||||
|
||||
EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count];
|
||||
|
||||
for (int i = 0; i < (6 + BannedUsers.Count); i++)
|
||||
{
|
||||
returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
|
||||
}
|
||||
int j = 0;
|
||||
|
||||
returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
|
||||
returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
|
||||
returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
|
||||
returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
|
||||
returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++;
|
||||
returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
|
||||
|
||||
foreach (UUID banned in BannedUsers)
|
||||
{
|
||||
returnblock[j].Parameter = banned.GetBytes(); j++;
|
||||
}
|
||||
packet.ParamList = returnblock;
|
||||
packet.Header.Reliable = false;
|
||||
OutPacket(packet, ThrottleOutPacketType.Task);
|
||||
}
|
||||
|
||||
public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args)
|
||||
|
||||
@@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
|
||||
Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
|
||||
/// an account exists with the same name as the creator, though not the same id.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestLoadIarV0_1SameNameCreator()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
|
||||
UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
|
||||
|
||||
m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
|
||||
InventoryItemBase foundItem1
|
||||
= InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
|
||||
|
||||
Assert.That(
|
||||
foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
|
||||
"Loaded item non-uuid creator doesn't match original");
|
||||
Assert.That(
|
||||
foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
|
||||
"Loaded item uuid creator doesn't match original");
|
||||
Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
|
||||
"Loaded item owner doesn't match inventory reciever");
|
||||
|
||||
AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
|
||||
string xmlData = Utils.BytesToString(asset1.Data);
|
||||
SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
|
||||
|
||||
Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
|
||||
}
|
||||
// /// <summary>
|
||||
// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
|
||||
// /// an account exists with the same name as the creator, though not the same id.
|
||||
// /// </summary>
|
||||
// [Test]
|
||||
// public void TestLoadIarV0_1SameNameCreator()
|
||||
// {
|
||||
// TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
//
|
||||
// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
|
||||
// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
|
||||
//
|
||||
// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
|
||||
// InventoryItemBase foundItem1
|
||||
// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
|
||||
//
|
||||
// Assert.That(
|
||||
// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
|
||||
// "Loaded item non-uuid creator doesn't match original");
|
||||
// Assert.That(
|
||||
// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
|
||||
// "Loaded item uuid creator doesn't match original");
|
||||
// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
|
||||
// "Loaded item owner doesn't match inventory reciever");
|
||||
//
|
||||
// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
|
||||
// string xmlData = Utils.BytesToString(asset1.Data);
|
||||
// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
|
||||
//
|
||||
// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
|
||||
|
||||
@@ -49,6 +49,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
public const int DISP_EXPIRE = 1;
|
||||
public const int DISP_TEMP = 2;
|
||||
|
||||
/// <summary>
|
||||
/// If true then where possible dynamic textures are reused.
|
||||
/// </summary>
|
||||
public bool ReuseTextures { get; set; }
|
||||
|
||||
private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
|
||||
|
||||
private Dictionary<string, IDynamicTextureRender> RenderPlugins =
|
||||
@@ -56,6 +61,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
|
||||
private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>();
|
||||
|
||||
/// <summary>
|
||||
/// Record dynamic textures that we can reuse for a given data and parameter combination rather than
|
||||
/// regenerate.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Key is string.Format("{0}{1}", data
|
||||
/// </remarks>
|
||||
private Cache m_reuseableDynamicTextures;
|
||||
|
||||
#region IDynamicTextureManager Members
|
||||
|
||||
public void RegisterRender(string handleType, IDynamicTextureRender render)
|
||||
@@ -71,7 +85,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="data"></param>
|
||||
public void ReturnData(UUID id, byte[] data)
|
||||
/// <param name="isReuseable">True if the data generated can be reused for subsequent identical requests</param>
|
||||
public void ReturnData(UUID id, byte[] data, bool isReuseable)
|
||||
{
|
||||
DynamicTextureUpdater updater = null;
|
||||
|
||||
@@ -88,7 +103,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
if (RegisteredScenes.ContainsKey(updater.SimUUID))
|
||||
{
|
||||
Scene scene = RegisteredScenes[updater.SimUUID];
|
||||
updater.DataReceived(data, scene);
|
||||
UUID newTextureID = updater.DataReceived(data, scene);
|
||||
|
||||
if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture)
|
||||
m_reuseableDynamicTextures.Store(
|
||||
GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,22 +186,61 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
|
||||
string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face)
|
||||
{
|
||||
if (RenderPlugins.ContainsKey(contentType))
|
||||
{
|
||||
DynamicTextureUpdater updater = new DynamicTextureUpdater();
|
||||
updater.SimUUID = simID;
|
||||
updater.PrimID = primID;
|
||||
updater.ContentType = contentType;
|
||||
updater.BodyData = data;
|
||||
updater.UpdateTimer = updateTimer;
|
||||
updater.UpdaterID = UUID.Random();
|
||||
updater.Params = extraParams;
|
||||
updater.BlendWithOldTexture = SetBlending;
|
||||
updater.FrontAlpha = AlphaValue;
|
||||
updater.Face = face;
|
||||
updater.Url = "Local image";
|
||||
updater.Disp = disp;
|
||||
if (!RenderPlugins.ContainsKey(contentType))
|
||||
return UUID.Zero;
|
||||
|
||||
Scene scene;
|
||||
RegisteredScenes.TryGetValue(simID, out scene);
|
||||
|
||||
if (scene == null)
|
||||
return UUID.Zero;
|
||||
|
||||
SceneObjectPart part = scene.GetSceneObjectPart(primID);
|
||||
|
||||
if (part == null)
|
||||
return UUID.Zero;
|
||||
|
||||
// If we want to reuse dynamic textures then we have to ignore any request from the caller to expire
|
||||
// them.
|
||||
if (ReuseTextures)
|
||||
disp = disp & ~DISP_EXPIRE;
|
||||
|
||||
DynamicTextureUpdater updater = new DynamicTextureUpdater();
|
||||
updater.SimUUID = simID;
|
||||
updater.PrimID = primID;
|
||||
updater.ContentType = contentType;
|
||||
updater.BodyData = data;
|
||||
updater.UpdateTimer = updateTimer;
|
||||
updater.UpdaterID = UUID.Random();
|
||||
updater.Params = extraParams;
|
||||
updater.BlendWithOldTexture = SetBlending;
|
||||
updater.FrontAlpha = AlphaValue;
|
||||
updater.Face = face;
|
||||
updater.Url = "Local image";
|
||||
updater.Disp = disp;
|
||||
|
||||
object objReusableTextureUUID = null;
|
||||
|
||||
if (ReuseTextures && !updater.BlendWithOldTexture)
|
||||
{
|
||||
string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams);
|
||||
objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey);
|
||||
|
||||
if (objReusableTextureUUID != null)
|
||||
{
|
||||
// If something else has removed this temporary asset from the cache, detect and invalidate
|
||||
// our cached uuid.
|
||||
if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null)
|
||||
{
|
||||
m_reuseableDynamicTextures.Invalidate(reuseableTextureKey);
|
||||
objReusableTextureUUID = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We cannot reuse a dynamic texture if the data is going to be blended with something already there.
|
||||
if (objReusableTextureUUID == null)
|
||||
{
|
||||
lock (Updaters)
|
||||
{
|
||||
if (!Updaters.ContainsKey(updater.UpdaterID))
|
||||
@@ -192,10 +250,20 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
}
|
||||
|
||||
RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
|
||||
return updater.UpdaterID;
|
||||
}
|
||||
|
||||
return UUID.Zero;
|
||||
else
|
||||
{
|
||||
// No need to add to updaters as the texture is always the same. Not that this functionality
|
||||
// apppears to be implemented anyway.
|
||||
updater.UpdatePart(part, (UUID)objReusableTextureUUID);
|
||||
}
|
||||
|
||||
return updater.UpdaterID;
|
||||
}
|
||||
|
||||
private string GenerateReusableTextureKey(string data, string extraParams)
|
||||
{
|
||||
return string.Format("{0}{1}", data, extraParams);
|
||||
}
|
||||
|
||||
public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
|
||||
@@ -215,6 +283,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
|
||||
public void Initialise(Scene scene, IConfigSource config)
|
||||
{
|
||||
IConfig texturesConfig = config.Configs["Textures"];
|
||||
if (texturesConfig != null)
|
||||
ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
|
||||
|
||||
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
|
||||
{
|
||||
RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
|
||||
@@ -224,6 +296,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
if (ReuseTextures)
|
||||
{
|
||||
m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
|
||||
m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
@@ -268,10 +345,61 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
BodyData = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the given part with the new texture.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The old texture UUID.
|
||||
/// </returns>
|
||||
public UUID UpdatePart(SceneObjectPart part, UUID textureID)
|
||||
{
|
||||
UUID oldID;
|
||||
|
||||
lock (part)
|
||||
{
|
||||
// mostly keep the values from before
|
||||
Primitive.TextureEntry tmptex = part.Shape.Textures;
|
||||
|
||||
// FIXME: Need to return the appropriate ID if only a single face is replaced.
|
||||
oldID = tmptex.DefaultTexture.TextureID;
|
||||
|
||||
if (Face == ALL_SIDES)
|
||||
{
|
||||
oldID = tmptex.DefaultTexture.TextureID;
|
||||
tmptex.DefaultTexture.TextureID = textureID;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
|
||||
texface.TextureID = textureID;
|
||||
tmptex.FaceTextures[Face] = texface;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
tmptex.DefaultTexture.TextureID = textureID;
|
||||
}
|
||||
}
|
||||
|
||||
// I'm pretty sure we always want to force this to true
|
||||
// I'm pretty sure noone whats to set fullbright true if it wasn't true before.
|
||||
// tmptex.DefaultTexture.Fullbright = true;
|
||||
|
||||
part.UpdateTextureEntry(tmptex.GetBytes());
|
||||
}
|
||||
|
||||
return oldID;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called once new texture data has been received for this updater.
|
||||
/// </summary>
|
||||
public void DataReceived(byte[] data, Scene scene)
|
||||
/// <param name="data"></param>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="isReuseable">True if the data given is reuseable.</param>
|
||||
/// <returns>The asset UUID given to the incoming data.</returns>
|
||||
public UUID DataReceived(byte[] data, Scene scene)
|
||||
{
|
||||
SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
|
||||
|
||||
@@ -281,7 +409,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
|
||||
scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,
|
||||
0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false);
|
||||
return;
|
||||
|
||||
return UUID.Zero;
|
||||
}
|
||||
|
||||
byte[] assetData = null;
|
||||
@@ -323,52 +452,23 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
cacheLayerDecode = null;
|
||||
}
|
||||
|
||||
UUID oldID = UUID.Zero;
|
||||
|
||||
lock (part)
|
||||
{
|
||||
// mostly keep the values from before
|
||||
Primitive.TextureEntry tmptex = part.Shape.Textures;
|
||||
|
||||
// remove the old asset from the cache
|
||||
oldID = tmptex.DefaultTexture.TextureID;
|
||||
|
||||
if (Face == ALL_SIDES)
|
||||
{
|
||||
tmptex.DefaultTexture.TextureID = asset.FullID;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
|
||||
texface.TextureID = asset.FullID;
|
||||
tmptex.FaceTextures[Face] = texface;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
tmptex.DefaultTexture.TextureID = asset.FullID;
|
||||
}
|
||||
}
|
||||
|
||||
// I'm pretty sure we always want to force this to true
|
||||
// I'm pretty sure noone whats to set fullbright true if it wasn't true before.
|
||||
// tmptex.DefaultTexture.Fullbright = true;
|
||||
|
||||
part.UpdateTextureEntry(tmptex.GetBytes());
|
||||
}
|
||||
UUID oldID = UpdatePart(part, asset.FullID);
|
||||
|
||||
if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
|
||||
{
|
||||
if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString());
|
||||
if (oldAsset == null)
|
||||
oldAsset = scene.AssetService.Get(oldID.ToString());
|
||||
|
||||
if (oldAsset != null)
|
||||
{
|
||||
if (oldAsset.Temporary == true)
|
||||
if (oldAsset.Temporary)
|
||||
{
|
||||
scene.AssetService.Delete(oldID.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return asset.FullID;
|
||||
}
|
||||
|
||||
private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
public string body;
|
||||
public int responseCode;
|
||||
public string responseBody;
|
||||
public string responseType = "text/plain";
|
||||
//public ManualResetEvent ev;
|
||||
public bool requestDone;
|
||||
public int startTime;
|
||||
@@ -302,6 +303,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
}
|
||||
}
|
||||
|
||||
public void HttpContentType(UUID request, string type)
|
||||
{
|
||||
lock (m_UrlMap)
|
||||
{
|
||||
if (m_RequestMap.ContainsKey(request))
|
||||
{
|
||||
UrlData urlData = m_RequestMap[request];
|
||||
urlData.requests[request].responseType = type;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void HttpResponse(UUID request, int status, string body)
|
||||
{
|
||||
lock (m_UrlMap)
|
||||
@@ -504,7 +521,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
//put response
|
||||
response["int_response_code"] = requestData.responseCode;
|
||||
response["str_response_string"] = requestData.responseBody;
|
||||
response["content_type"] = "text/plain";
|
||||
response["content_type"] = requestData.responseType;
|
||||
// response["content_type"] = "text/plain";
|
||||
response["keepalive"] = false;
|
||||
response["reusecontext"] = false;
|
||||
|
||||
|
||||
@@ -67,12 +67,18 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||
return true;
|
||||
}
|
||||
|
||||
// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
|
||||
// {
|
||||
// // We don't support conversion of body data.
|
||||
// return false;
|
||||
// }
|
||||
|
||||
public byte[] ConvertUrl(string url, string extraParams)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] ConvertStream(Stream data, string extraParams)
|
||||
public byte[] ConvertData(string bodyData, string extraParams)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -236,9 +242,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}",
|
||||
imageJ2000.Length, state.RequestID);
|
||||
m_textureManager.ReturnData(state.RequestID, imageJ2000);
|
||||
|
||||
m_textureManager.ReturnData(state.RequestID, imageJ2000, false);
|
||||
}
|
||||
|
||||
#region Nested type: RequestState
|
||||
|
||||
@@ -45,31 +45,250 @@ using OpenSim.Tests.Common.Mock;
|
||||
namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class VectorRenderModuleTests
|
||||
public class VectorRenderModuleTests : OpenSimTestCase
|
||||
{
|
||||
Scene m_scene;
|
||||
DynamicTextureModule m_dtm;
|
||||
VectorRenderModule m_vrm;
|
||||
|
||||
private void SetupScene(bool reuseTextures)
|
||||
{
|
||||
m_scene = new SceneHelpers().SetupScene();
|
||||
|
||||
m_dtm = new DynamicTextureModule();
|
||||
m_dtm.ReuseTextures = reuseTextures;
|
||||
|
||||
m_vrm = new VectorRenderModule();
|
||||
|
||||
SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDraw()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
Scene scene = new SceneHelpers().SetupScene();
|
||||
DynamicTextureModule dtm = new DynamicTextureModule();
|
||||
VectorRenderModule vrm = new VectorRenderModule();
|
||||
SceneHelpers.SetupSceneModules(scene, dtm, vrm);
|
||||
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
|
||||
SetupScene(false);
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
|
||||
UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
|
||||
|
||||
dtm.AddDynamicTextureData(
|
||||
scene.RegionInfo.RegionID,
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
vrm.GetContentType(),
|
||||
m_vrm.GetContentType(),
|
||||
"PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
|
||||
"",
|
||||
0);
|
||||
|
||||
Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRepeatSameDraw()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
|
||||
|
||||
SetupScene(false);
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"",
|
||||
0);
|
||||
|
||||
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"",
|
||||
0);
|
||||
|
||||
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRepeatSameDrawDifferentExtraParams()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
|
||||
|
||||
SetupScene(false);
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"",
|
||||
0);
|
||||
|
||||
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"alpha:250",
|
||||
0);
|
||||
|
||||
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRepeatSameDrawContainingImage()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
string dtText
|
||||
= "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
|
||||
|
||||
SetupScene(false);
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"",
|
||||
0);
|
||||
|
||||
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"",
|
||||
0);
|
||||
|
||||
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDrawReusingTexture()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
SetupScene(true);
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
|
||||
UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
"PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
|
||||
"",
|
||||
0);
|
||||
|
||||
Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRepeatSameDrawReusingTexture()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
|
||||
|
||||
SetupScene(true);
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"",
|
||||
0);
|
||||
|
||||
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"",
|
||||
0);
|
||||
|
||||
Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
|
||||
|
||||
SetupScene(true);
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"",
|
||||
0);
|
||||
|
||||
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"alpha:250",
|
||||
0);
|
||||
|
||||
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRepeatSameDrawContainingImageReusingTexture()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
string dtText
|
||||
= "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
|
||||
|
||||
SetupScene(true);
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"",
|
||||
0);
|
||||
|
||||
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"",
|
||||
0);
|
||||
|
||||
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
@@ -47,7 +48,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private string m_name = "VectorRenderModule";
|
||||
private Scene m_scene;
|
||||
private IDynamicTextureManager m_textureManager;
|
||||
private Graphics m_graph;
|
||||
@@ -61,12 +61,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
|
||||
public string GetContentType()
|
||||
{
|
||||
return ("vector");
|
||||
return "vector";
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return m_name;
|
||||
return Name;
|
||||
}
|
||||
|
||||
public bool SupportsAsynchronous()
|
||||
@@ -74,14 +74,26 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
return true;
|
||||
}
|
||||
|
||||
// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
|
||||
// {
|
||||
// string[] lines = GetLines(bodyData);
|
||||
// return lines.Any((str, r) => str.StartsWith("Image"));
|
||||
// }
|
||||
|
||||
public byte[] ConvertUrl(string url, string extraParams)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] ConvertStream(Stream data, string extraParams)
|
||||
public byte[] ConvertData(string bodyData, string extraParams)
|
||||
{
|
||||
return null;
|
||||
bool reuseable;
|
||||
return Draw(bodyData, extraParams, out reuseable);
|
||||
}
|
||||
|
||||
private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable)
|
||||
{
|
||||
return Draw(bodyData, extraParams, out reuseable);
|
||||
}
|
||||
|
||||
public bool AsyncConvertUrl(UUID id, string url, string extraParams)
|
||||
@@ -91,7 +103,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
|
||||
public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
|
||||
{
|
||||
Draw(bodyData, id, extraParams);
|
||||
// XXX: This isn't actually being done asynchronously!
|
||||
bool reuseable;
|
||||
byte[] data = ConvertData(bodyData, extraParams, out reuseable);
|
||||
|
||||
m_textureManager.ReturnData(id, data, reuseable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -152,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return m_name; }
|
||||
get { return "VectorRenderModule"; }
|
||||
}
|
||||
|
||||
public bool IsSharedModule
|
||||
@@ -162,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
|
||||
#endregion
|
||||
|
||||
private void Draw(string data, UUID id, string extraParams)
|
||||
private byte[] Draw(string data, string extraParams, out bool reuseable)
|
||||
{
|
||||
// We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
|
||||
// we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
|
||||
@@ -343,7 +360,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
}
|
||||
}
|
||||
|
||||
GDIDraw(data, graph, altDataDelim);
|
||||
GDIDraw(data, graph, altDataDelim, out reuseable);
|
||||
}
|
||||
|
||||
byte[] imageJ2000 = new byte[0];
|
||||
@@ -359,7 +376,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
|
||||
m_textureManager.ReturnData(id, imageJ2000);
|
||||
return imageJ2000;
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -434,8 +451,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
}
|
||||
*/
|
||||
|
||||
private void GDIDraw(string data, Graphics graph, char dataDelim)
|
||||
/// <summary>
|
||||
/// Split input data into discrete command lines.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <param name='data'></param>
|
||||
/// <param name='dataDelim'></param>
|
||||
private string[] GetLines(string data, char dataDelim)
|
||||
{
|
||||
char[] lineDelimiter = { dataDelim };
|
||||
return data.Split(lineDelimiter);
|
||||
}
|
||||
|
||||
private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable)
|
||||
{
|
||||
reuseable = true;
|
||||
Point startPoint = new Point(0, 0);
|
||||
Point endPoint = new Point(0, 0);
|
||||
Pen drawPen = null;
|
||||
@@ -450,11 +480,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
myFont = new Font(fontName, fontSize);
|
||||
myBrush = new SolidBrush(Color.Black);
|
||||
|
||||
char[] lineDelimiter = {dataDelim};
|
||||
char[] partsDelimiter = {','};
|
||||
string[] lines = data.Split(lineDelimiter);
|
||||
|
||||
foreach (string line in lines)
|
||||
foreach (string line in GetLines(data, dataDelim))
|
||||
{
|
||||
string nextLine = line.Trim();
|
||||
//replace with switch, or even better, do some proper parsing
|
||||
@@ -485,6 +513,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
}
|
||||
else if (nextLine.StartsWith("Image"))
|
||||
{
|
||||
// We cannot reuse any generated texture involving fetching an image via HTTP since that image
|
||||
// can change.
|
||||
reuseable = false;
|
||||
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
|
||||
|
||||
@@ -414,6 +414,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
private void LoadPlugins()
|
||||
{
|
||||
m_plugineffects = new Dictionary<string, ITerrainEffect>();
|
||||
LoadPlugins(Assembly.GetCallingAssembly());
|
||||
string plugineffectsPath = "Terrain";
|
||||
|
||||
// Load the files in the Terrain/ dir
|
||||
@@ -427,32 +428,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
try
|
||||
{
|
||||
Assembly library = Assembly.LoadFrom(file);
|
||||
foreach (Type pluginType in library.GetTypes())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (pluginType.IsAbstract || pluginType.IsNotPublic)
|
||||
continue;
|
||||
|
||||
string typeName = pluginType.Name;
|
||||
|
||||
if (pluginType.GetInterface("ITerrainEffect", false) != null)
|
||||
{
|
||||
ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString()));
|
||||
|
||||
InstallPlugin(typeName, terEffect);
|
||||
}
|
||||
else if (pluginType.GetInterface("ITerrainLoader", false) != null)
|
||||
{
|
||||
ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString()));
|
||||
m_loaders[terLoader.FileExtension] = terLoader;
|
||||
m_log.Info("L ... " + typeName);
|
||||
}
|
||||
}
|
||||
catch (AmbiguousMatchException)
|
||||
{
|
||||
}
|
||||
}
|
||||
LoadPlugins(library);
|
||||
}
|
||||
catch (BadImageFormatException)
|
||||
{
|
||||
@@ -460,6 +436,36 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadPlugins(Assembly library)
|
||||
{
|
||||
foreach (Type pluginType in library.GetTypes())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (pluginType.IsAbstract || pluginType.IsNotPublic)
|
||||
continue;
|
||||
|
||||
string typeName = pluginType.Name;
|
||||
|
||||
if (pluginType.GetInterface("ITerrainEffect", false) != null)
|
||||
{
|
||||
ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString()));
|
||||
|
||||
InstallPlugin(typeName, terEffect);
|
||||
}
|
||||
else if (pluginType.GetInterface("ITerrainLoader", false) != null)
|
||||
{
|
||||
ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString()));
|
||||
m_loaders[terLoader.FileExtension] = terLoader;
|
||||
m_log.Info("L ... " + typeName);
|
||||
}
|
||||
}
|
||||
catch (AmbiguousMatchException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void InstallPlugin(string pluginName, ITerrainEffect effect)
|
||||
{
|
||||
lock (m_plugineffects)
|
||||
@@ -1176,7 +1182,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
|
||||
private void InterfaceRunPluginEffect(Object[] args)
|
||||
{
|
||||
if ((string) args[0] == "list")
|
||||
string firstArg = (string)args[0];
|
||||
if (firstArg == "list")
|
||||
{
|
||||
m_log.Info("List of loaded plugins");
|
||||
foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
|
||||
@@ -1185,14 +1192,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((string) args[0] == "reload")
|
||||
if (firstArg == "reload")
|
||||
{
|
||||
LoadPlugins();
|
||||
return;
|
||||
}
|
||||
if (m_plugineffects.ContainsKey((string) args[0]))
|
||||
if (m_plugineffects.ContainsKey(firstArg))
|
||||
{
|
||||
m_plugineffects[(string) args[0]].RunEffect(m_channel);
|
||||
m_plugineffects[firstArg].RunEffect(m_channel);
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -208,6 +208,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@@ -673,4 +676,4 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
public interface IDynamicTextureManager
|
||||
{
|
||||
void RegisterRender(string handleType, IDynamicTextureRender render);
|
||||
void ReturnData(UUID id, byte[] data);
|
||||
void ReturnData(UUID id, byte[] data, bool isReuseable);
|
||||
|
||||
UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
|
||||
int updateTimer);
|
||||
@@ -113,8 +113,20 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
string GetName();
|
||||
string GetContentType();
|
||||
bool SupportsAsynchronous();
|
||||
|
||||
// /// <summary>
|
||||
// /// Return true if converting the input body and extra params data will always result in the same byte[] array
|
||||
// /// </summary>
|
||||
// /// <remarks>
|
||||
// /// This method allows the caller to use a previously generated asset if it has one.
|
||||
// /// </remarks>
|
||||
// /// <returns></returns>
|
||||
// /// <param name='bodyData'></param>
|
||||
// /// <param name='extraParams'></param>
|
||||
// bool AlwaysIdenticalConversion(string bodyData, string extraParams);
|
||||
|
||||
byte[] ConvertUrl(string url, string extraParams);
|
||||
byte[] ConvertStream(Stream data, string extraParams);
|
||||
byte[] ConvertData(string bodyData, string extraParams);
|
||||
bool AsyncConvertUrl(UUID id, string url, string extraParams);
|
||||
bool AsyncConvertData(UUID id, string bodyData, string extraParams);
|
||||
void GetDrawStringSize(string text, string fontName, int fontSize,
|
||||
|
||||
@@ -46,9 +46,38 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// </summary>
|
||||
event ScriptCommand OnScriptCommand;
|
||||
|
||||
/// <summary>
|
||||
/// Register an instance method as a script call by method name
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="method"></param>
|
||||
void RegisterScriptInvocation(object target, string method);
|
||||
|
||||
/// <summary>
|
||||
/// Register a static or instance method as a script call by method info
|
||||
/// </summary>
|
||||
/// <param name="target">If target is a Type object, will assume method is static.</param>
|
||||
/// <param name="method"></param>
|
||||
void RegisterScriptInvocation(object target, MethodInfo method);
|
||||
|
||||
/// <summary>
|
||||
/// Register one or more instance methods as script calls by method name
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="methods"></param>
|
||||
void RegisterScriptInvocation(object target, string[] methods);
|
||||
|
||||
/// <summary>
|
||||
/// Register one or more static methods as script calls by method name
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="methods"></param>
|
||||
void RegisterScriptInvocation(Type target, string[] methods);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of all registered script calls
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Delegate[] GetScriptInvocationList();
|
||||
|
||||
Delegate LookupScriptInvocation(string fname);
|
||||
|
||||
@@ -39,6 +39,8 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID);
|
||||
void ReleaseURL(string url);
|
||||
void HttpResponse(UUID request, int status, string body);
|
||||
void HttpContentType(UUID request, string type);
|
||||
|
||||
string GetHttpHeader(UUID request, string header);
|
||||
int GetFreeUrls();
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// </summary>
|
||||
public void StartScripts()
|
||||
{
|
||||
m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName);
|
||||
// m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName);
|
||||
|
||||
IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
|
||||
|
||||
@@ -1943,6 +1943,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
deleteIDs.Add(localID);
|
||||
deleteGroups.Add(grp);
|
||||
|
||||
// If child prims have invalid perms, fix them
|
||||
grp.AdjustChildPrimPermissions();
|
||||
|
||||
if (remoteClient == null)
|
||||
{
|
||||
// Autoreturn has a null client. Nothing else does. So
|
||||
|
||||
@@ -468,7 +468,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
if (!InventoryService.AddFolder(folder))
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[AGENT INVENTORY]: Failed to move create folder for user {0} {1}",
|
||||
"[AGENT INVENTORY]: Failed to create folder for user {0} {1}",
|
||||
remoteClient.Name, remoteClient.AgentId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3562,7 +3562,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
"[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
|
||||
sp.Name, sp.UUID, RegionInfo.RegionName);
|
||||
|
||||
sp.ControllingClient.Close();
|
||||
sp.ControllingClient.Close(true);
|
||||
sp = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -300,7 +300,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
public bool AddNewSceneObject(
|
||||
SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel)
|
||||
{
|
||||
AddNewSceneObject(sceneObject, true, false);
|
||||
AddNewSceneObject(sceneObject, attachToBackup, false);
|
||||
|
||||
if (pos != null)
|
||||
sceneObject.AbsolutePosition = (Vector3)pos;
|
||||
|
||||
@@ -2131,6 +2131,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
// Can't do this yet since backup still makes use of the root part without any synchronization
|
||||
// objectGroup.m_rootPart = null;
|
||||
|
||||
// If linking prims with different permissions, fix them
|
||||
AdjustChildPrimPermissions();
|
||||
|
||||
AttachToBackup();
|
||||
|
||||
// Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
|
||||
@@ -2622,12 +2625,21 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
}
|
||||
|
||||
public void AdjustChildPrimPermissions()
|
||||
{
|
||||
ForEachPart(part =>
|
||||
{
|
||||
if (part != RootPart)
|
||||
part.ClonePermissions(RootPart);
|
||||
});
|
||||
}
|
||||
|
||||
public void UpdatePermissions(UUID AgentID, byte field, uint localID,
|
||||
uint mask, byte addRemTF)
|
||||
{
|
||||
SceneObjectPart[] parts = m_parts.GetArray();
|
||||
for (int i = 0; i < parts.Length; i++)
|
||||
parts[i].UpdatePermissions(AgentID, field, localID, mask, addRemTF);
|
||||
RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
|
||||
|
||||
AdjustChildPrimPermissions();
|
||||
|
||||
HasGroupChanged = true;
|
||||
|
||||
|
||||
@@ -3890,6 +3890,27 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
}
|
||||
|
||||
public void ClonePermissions(SceneObjectPart source)
|
||||
{
|
||||
bool update = false;
|
||||
|
||||
if (BaseMask != source.BaseMask ||
|
||||
OwnerMask != source.OwnerMask ||
|
||||
GroupMask != source.GroupMask ||
|
||||
EveryoneMask != source.EveryoneMask ||
|
||||
NextOwnerMask != source.NextOwnerMask)
|
||||
update = true;
|
||||
|
||||
BaseMask = source.BaseMask;
|
||||
OwnerMask = source.OwnerMask;
|
||||
GroupMask = source.GroupMask;
|
||||
EveryoneMask = source.EveryoneMask;
|
||||
NextOwnerMask = source.NextOwnerMask;
|
||||
|
||||
if (update)
|
||||
SendFullUpdateToAllClients();
|
||||
}
|
||||
|
||||
public bool IsHingeJoint()
|
||||
{
|
||||
// For now, we use the NINJA naming scheme for identifying joints.
|
||||
|
||||
@@ -891,7 +891,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
{
|
||||
if (wasChild && HasAttachments())
|
||||
{
|
||||
m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
|
||||
m_log.DebugFormat(
|
||||
"[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
|
||||
|
||||
// Resume scripts
|
||||
foreach (SceneObjectGroup sog in m_attachments)
|
||||
{
|
||||
@@ -3416,13 +3418,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
public List<SceneObjectGroup> GetAttachments(uint attachmentPoint)
|
||||
{
|
||||
List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
|
||||
|
||||
lock (m_attachments)
|
||||
|
||||
if (attachmentPoint >= 0)
|
||||
{
|
||||
foreach (SceneObjectGroup so in m_attachments)
|
||||
lock (m_attachments)
|
||||
{
|
||||
if (attachmentPoint == so.AttachmentPoint)
|
||||
attachments.Add(so);
|
||||
foreach (SceneObjectGroup so in m_attachments)
|
||||
{
|
||||
if (attachmentPoint == so.AttachmentPoint)
|
||||
attachments.Add(so);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,8 +50,40 @@ using OpenSim.Tests.Common.Mock;
|
||||
namespace OpenSim.Region.Framework.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class UserInventoryTests
|
||||
public class UserInventoryTests : OpenSimTestCase
|
||||
{
|
||||
[Test]
|
||||
public void TestCreateInventoryFolders()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
// For this test both folders will have the same name which is legal in SL user inventories.
|
||||
string foldersName = "f1";
|
||||
|
||||
Scene scene = new SceneHelpers().SetupScene();
|
||||
UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
|
||||
|
||||
UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
|
||||
|
||||
List<InventoryFolderBase> oneFolder
|
||||
= UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
|
||||
|
||||
Assert.That(oneFolder.Count, Is.EqualTo(1));
|
||||
InventoryFolderBase firstRetrievedFolder = oneFolder[0];
|
||||
Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName));
|
||||
|
||||
UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
|
||||
|
||||
List<InventoryFolderBase> twoFolders
|
||||
= UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
|
||||
|
||||
Assert.That(twoFolders.Count, Is.EqualTo(2));
|
||||
Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName));
|
||||
Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName));
|
||||
Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGiveInventoryItem()
|
||||
{
|
||||
@@ -83,7 +115,7 @@ namespace OpenSim.Region.Framework.Tests
|
||||
public void TestGiveInventoryFolder()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
Scene scene = new SceneHelpers().SetupScene();
|
||||
UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
|
||||
|
||||
@@ -130,13 +130,25 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
|
||||
m_scriptModule.PostScriptEvent(script, "link_message", args);
|
||||
}
|
||||
|
||||
private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods)
|
||||
{
|
||||
BindingFlags getMethodFlags =
|
||||
BindingFlags.NonPublic | BindingFlags.Public;
|
||||
|
||||
if (searchInstanceMethods)
|
||||
getMethodFlags |= BindingFlags.Instance;
|
||||
else
|
||||
getMethodFlags |= BindingFlags.Static;
|
||||
|
||||
return target.GetMethod(meth, getMethodFlags);
|
||||
}
|
||||
|
||||
public void RegisterScriptInvocation(object target, string meth)
|
||||
{
|
||||
MethodInfo mi = target.GetType().GetMethod(meth,
|
||||
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
|
||||
if (mi == null)
|
||||
{
|
||||
m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth);
|
||||
m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -151,38 +163,54 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
|
||||
|
||||
public void RegisterScriptInvocation(object target, MethodInfo mi)
|
||||
{
|
||||
m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name);
|
||||
m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
|
||||
|
||||
Type delegateType;
|
||||
var typeArgs = mi.GetParameters()
|
||||
List<Type> typeArgs = mi.GetParameters()
|
||||
.Select(p => p.ParameterType)
|
||||
.ToList();
|
||||
|
||||
if (mi.ReturnType == typeof(void))
|
||||
{
|
||||
delegateType = Expression.GetActionType(typeArgs.ToArray());
|
||||
delegateType = Expression.GetActionType(typeArgs.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
typeArgs.Add(mi.ReturnType);
|
||||
delegateType = Expression.GetFuncType(typeArgs.ToArray());
|
||||
typeArgs.Add(mi.ReturnType);
|
||||
delegateType = Expression.GetFuncType(typeArgs.ToArray());
|
||||
}
|
||||
|
||||
Delegate fcall = Delegate.CreateDelegate(delegateType, target, mi);
|
||||
Delegate fcall;
|
||||
if (!(target is Type))
|
||||
fcall = Delegate.CreateDelegate(delegateType, target, mi);
|
||||
else
|
||||
fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name);
|
||||
|
||||
lock (m_scriptInvocation)
|
||||
{
|
||||
ParameterInfo[] parameters = fcall.Method.GetParameters ();
|
||||
ParameterInfo[] parameters = fcall.Method.GetParameters();
|
||||
if (parameters.Length < 2) // Must have two UUID params
|
||||
return;
|
||||
|
||||
// Hide the first two parameters
|
||||
Type[] parmTypes = new Type[parameters.Length - 2];
|
||||
for (int i = 2 ; i < parameters.Length ; i++)
|
||||
for (int i = 2; i < parameters.Length; i++)
|
||||
parmTypes[i - 2] = parameters[i].ParameterType;
|
||||
m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterScriptInvocation(Type target, string[] methods)
|
||||
{
|
||||
foreach (string method in methods)
|
||||
{
|
||||
MethodInfo mi = GetMethodInfoFromType(target, method, false);
|
||||
if (mi == null)
|
||||
m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method);
|
||||
else
|
||||
RegisterScriptInvocation(target, mi);
|
||||
}
|
||||
}
|
||||
|
||||
public Delegate[] GetScriptInvocationList()
|
||||
{
|
||||
|
||||
@@ -34,13 +34,12 @@ using OpenSim.Region.Physics.Manager;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public class BSCharacter : PhysicsActor
|
||||
public class BSCharacter : BSPhysObject
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly string LogHeader = "[BULLETS CHAR]";
|
||||
|
||||
private BSScene _scene;
|
||||
public BSScene Scene { get { return _scene; } }
|
||||
public BSScene Scene { get; private set; }
|
||||
private String _avName;
|
||||
// private bool _stopped;
|
||||
private Vector3 _size;
|
||||
@@ -74,11 +73,8 @@ public class BSCharacter : PhysicsActor
|
||||
private bool _kinematic;
|
||||
private float _buoyancy;
|
||||
|
||||
private BulletBody m_body;
|
||||
public BulletBody Body {
|
||||
get { return m_body; }
|
||||
set { m_body = value; }
|
||||
}
|
||||
public override BulletBody Body { get; set; }
|
||||
public override BSLinkset Linkset { get; set; }
|
||||
|
||||
private int _subscribedEventsMs = 0;
|
||||
private int _nextCollisionOkTime = 0;
|
||||
@@ -95,7 +91,7 @@ public class BSCharacter : PhysicsActor
|
||||
{
|
||||
_localID = localID;
|
||||
_avName = avName;
|
||||
_scene = parent_scene;
|
||||
Scene = parent_scene;
|
||||
_position = pos;
|
||||
_size = size;
|
||||
_flying = isFlying;
|
||||
@@ -104,10 +100,12 @@ public class BSCharacter : PhysicsActor
|
||||
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
||||
// The dimensions of the avatar capsule are kept in the scale.
|
||||
// Physics creates a unit capsule which is scaled by the physics engine.
|
||||
_scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z);
|
||||
_density = _scene.Params.avatarDensity;
|
||||
_scale = new Vector3(Scene.Params.avatarCapsuleRadius, Scene.Params.avatarCapsuleRadius, size.Z);
|
||||
_density = Scene.Params.avatarDensity;
|
||||
ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
|
||||
|
||||
Linkset = new BSLinkset(Scene, this);
|
||||
|
||||
ShapeData shapeData = new ShapeData();
|
||||
shapeData.ID = _localID;
|
||||
shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
|
||||
@@ -118,19 +116,19 @@ public class BSCharacter : PhysicsActor
|
||||
shapeData.Mass = _mass;
|
||||
shapeData.Buoyancy = _buoyancy;
|
||||
shapeData.Static = ShapeData.numericFalse;
|
||||
shapeData.Friction = _scene.Params.avatarFriction;
|
||||
shapeData.Restitution = _scene.Params.avatarRestitution;
|
||||
shapeData.Friction = Scene.Params.avatarFriction;
|
||||
shapeData.Restitution = Scene.Params.avatarRestitution;
|
||||
|
||||
// do actual create at taint time
|
||||
_scene.TaintedObject("BSCharacter.create", delegate()
|
||||
Scene.TaintedObject("BSCharacter.create", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.create", _localID);
|
||||
BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData);
|
||||
BulletSimAPI.CreateObject(Scene.WorldID, shapeData);
|
||||
|
||||
// Set the buoyancy for flying. This will be refactored when all the settings happen in C#
|
||||
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
|
||||
BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
|
||||
|
||||
m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID));
|
||||
// avatars get all collisions no matter what (makes walking on ground and such work)
|
||||
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
});
|
||||
@@ -139,12 +137,12 @@ public class BSCharacter : PhysicsActor
|
||||
}
|
||||
|
||||
// called when this character is being destroyed and the resources should be released
|
||||
public void Destroy()
|
||||
public override void Destroy()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.Destroy", LocalID);
|
||||
_scene.TaintedObject("BSCharacter.destroy", delegate()
|
||||
Scene.TaintedObject("BSCharacter.destroy", delegate()
|
||||
{
|
||||
BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
|
||||
BulletSimAPI.DestroyObject(Scene.WorldID, _localID);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -173,9 +171,9 @@ public class BSCharacter : PhysicsActor
|
||||
|
||||
ComputeAvatarVolumeAndMass();
|
||||
|
||||
_scene.TaintedObject("BSCharacter.setSize", delegate()
|
||||
Scene.TaintedObject("BSCharacter.setSize", delegate()
|
||||
{
|
||||
BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true);
|
||||
BulletSimAPI.SetObjectScaleMass(Scene.WorldID, LocalID, _scale, _mass, true);
|
||||
});
|
||||
|
||||
}
|
||||
@@ -204,17 +202,17 @@ public class BSCharacter : PhysicsActor
|
||||
|
||||
public override Vector3 Position {
|
||||
get {
|
||||
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
|
||||
return _position;
|
||||
}
|
||||
set {
|
||||
_position = value;
|
||||
PositionSanityCheck();
|
||||
|
||||
_scene.TaintedObject("BSCharacter.setPosition", delegate()
|
||||
Scene.TaintedObject("BSCharacter.setPosition", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
||||
BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -227,16 +225,35 @@ public class BSCharacter : PhysicsActor
|
||||
bool ret = false;
|
||||
|
||||
// If below the ground, move the avatar up
|
||||
float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position);
|
||||
if (_position.Z < terrainHeight)
|
||||
float terrainHeight = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position);
|
||||
if (Position.Z < terrainHeight)
|
||||
{
|
||||
DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
|
||||
_position.Z = terrainHeight + 2.0f;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// TODO: check for out of bounds
|
||||
return ret;
|
||||
}
|
||||
|
||||
// A version of the sanity check that also makes sure a new position value is
|
||||
// pushed back to the physics engine. This routine would be used by anyone
|
||||
// who is not already pushing the value.
|
||||
private bool PositionSanityCheck2()
|
||||
{
|
||||
bool ret = false;
|
||||
if (PositionSanityCheck())
|
||||
{
|
||||
// The new position value must be pushed into the physics engine but we can't
|
||||
// just assign to "Position" because of potential call loops.
|
||||
Scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
|
||||
});
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -245,6 +262,10 @@ public class BSCharacter : PhysicsActor
|
||||
return _mass;
|
||||
}
|
||||
}
|
||||
|
||||
// used when we only want this prim's mass and not the linkset thing
|
||||
public override float MassRaw { get {return _mass; } }
|
||||
|
||||
public override Vector3 Force {
|
||||
get { return _force; }
|
||||
set {
|
||||
@@ -277,10 +298,10 @@ public class BSCharacter : PhysicsActor
|
||||
set {
|
||||
_velocity = value;
|
||||
// m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
|
||||
_scene.TaintedObject("BSCharacter.setVelocity", delegate()
|
||||
Scene.TaintedObject("BSCharacter.setVelocity", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
|
||||
BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity);
|
||||
BulletSimAPI.SetObjectVelocity(Scene.WorldID, _localID, _velocity);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -303,10 +324,10 @@ public class BSCharacter : PhysicsActor
|
||||
set {
|
||||
_orientation = value;
|
||||
// m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
|
||||
_scene.TaintedObject("BSCharacter.setOrientation", delegate()
|
||||
Scene.TaintedObject("BSCharacter.setOrientation", delegate()
|
||||
{
|
||||
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
||||
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
|
||||
BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -343,11 +364,11 @@ public class BSCharacter : PhysicsActor
|
||||
set { _throttleUpdates = value; }
|
||||
}
|
||||
public override bool IsColliding {
|
||||
get { return (_collidingStep == _scene.SimulationStep); }
|
||||
get { return (_collidingStep == Scene.SimulationStep); }
|
||||
set { _isColliding = value; }
|
||||
}
|
||||
public override bool CollidingGround {
|
||||
get { return (_collidingGroundStep == _scene.SimulationStep); }
|
||||
get { return (_collidingGroundStep == Scene.SimulationStep); }
|
||||
set { _collidingGround = value; }
|
||||
}
|
||||
public override bool CollidingObj {
|
||||
@@ -369,10 +390,10 @@ public class BSCharacter : PhysicsActor
|
||||
public override float Buoyancy {
|
||||
get { return _buoyancy; }
|
||||
set { _buoyancy = value;
|
||||
_scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
|
||||
Scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
||||
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
|
||||
BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -416,7 +437,7 @@ public class BSCharacter : PhysicsActor
|
||||
_force.Y += force.Y;
|
||||
_force.Z += force.Z;
|
||||
// m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
|
||||
_scene.TaintedObject("BSCharacter.AddForce", delegate()
|
||||
Scene.TaintedObject("BSCharacter.AddForce", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
|
||||
BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
|
||||
@@ -448,6 +469,12 @@ public class BSCharacter : PhysicsActor
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override void ZeroMotion()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop collision events
|
||||
public override void UnSubscribeEvents() {
|
||||
_subscribedEventsMs = 0;
|
||||
@@ -481,7 +508,7 @@ public class BSCharacter : PhysicsActor
|
||||
|
||||
// The physics engine says that properties have updated. Update same and inform
|
||||
// the world that things have changed.
|
||||
public void UpdateProperties(EntityProperties entprop)
|
||||
public override void UpdateProperties(EntityProperties entprop)
|
||||
{
|
||||
_position = entprop.Position;
|
||||
_orientation = entprop.Rotation;
|
||||
@@ -491,30 +518,33 @@ public class BSCharacter : PhysicsActor
|
||||
// Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
|
||||
// base.RequestPhysicsterseUpdate();
|
||||
|
||||
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
||||
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
|
||||
entprop.Acceleration, entprop.RotationalVelocity);
|
||||
// Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
|
||||
PositionSanityCheck2();
|
||||
|
||||
float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug
|
||||
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}",
|
||||
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere);
|
||||
}
|
||||
|
||||
// Called by the scene when a collision with this object is reported
|
||||
// The collision, if it should be reported to the character, is placed in a collection
|
||||
// that will later be sent to the simulator when SendCollisions() is called.
|
||||
CollisionEventUpdate collisionCollection = null;
|
||||
public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
|
||||
public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
|
||||
{
|
||||
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
|
||||
|
||||
// The following makes IsColliding() and IsCollidingGround() work
|
||||
_collidingStep = _scene.SimulationStep;
|
||||
_collidingStep = Scene.SimulationStep;
|
||||
if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
|
||||
{
|
||||
_collidingGroundStep = _scene.SimulationStep;
|
||||
_collidingGroundStep = Scene.SimulationStep;
|
||||
}
|
||||
// DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
|
||||
|
||||
// throttle collisions to the rate specified in the subscription
|
||||
if (_subscribedEventsMs != 0) {
|
||||
int nowTime = _scene.SimulationNowTime;
|
||||
int nowTime = Scene.SimulationNowTime;
|
||||
if (nowTime >= _nextCollisionOkTime) {
|
||||
_nextCollisionOkTime = nowTime + _subscribedEventsMs;
|
||||
|
||||
@@ -525,7 +555,7 @@ public class BSCharacter : PhysicsActor
|
||||
}
|
||||
}
|
||||
|
||||
public void SendCollisions()
|
||||
public override void SendCollisions()
|
||||
{
|
||||
/*
|
||||
if (collisionCollection != null && collisionCollection.Count > 0)
|
||||
|
||||
@@ -48,11 +48,10 @@ public abstract class BSConstraint : IDisposable
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
// BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
|
||||
m_enabled = false;
|
||||
bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
|
||||
m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
|
||||
m_constraint.Ptr = System.IntPtr.Zero;
|
||||
m_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -465,6 +465,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
}
|
||||
}//end SetDefaultsForType
|
||||
|
||||
// One step of the vehicle properties for the next 'pTimestep' seconds.
|
||||
internal void Step(float pTimestep)
|
||||
{
|
||||
if (m_type == Vehicle.TYPE_NONE) return;
|
||||
@@ -592,9 +593,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
}
|
||||
|
||||
// If below the terrain, move us above the ground a little.
|
||||
if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos))
|
||||
if (pos.Z < m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos))
|
||||
{
|
||||
pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2;
|
||||
pos.Z = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2;
|
||||
m_prim.Position = pos;
|
||||
VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
|
||||
}
|
||||
@@ -609,7 +610,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
}
|
||||
if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
|
||||
{
|
||||
m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
|
||||
m_VhoverTargetHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
|
||||
}
|
||||
if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
|
||||
{
|
||||
@@ -673,7 +674,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
grav.Z = (float)(grav.Z * 1.125);
|
||||
}
|
||||
float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos);
|
||||
float terraintemp = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos);
|
||||
float postemp = (pos.Z - terraintemp);
|
||||
if (postemp > 2.5f)
|
||||
{
|
||||
|
||||
@@ -36,8 +36,8 @@ public class BSLinkset
|
||||
{
|
||||
private static string LogHeader = "[BULLETSIM LINKSET]";
|
||||
|
||||
private BSPrim m_linksetRoot;
|
||||
public BSPrim LinksetRoot { get { return m_linksetRoot; } }
|
||||
private BSPhysObject m_linksetRoot;
|
||||
public BSPhysObject LinksetRoot { get { return m_linksetRoot; } }
|
||||
|
||||
private BSScene m_physicsScene;
|
||||
public BSScene PhysicsScene { get { return m_physicsScene; } }
|
||||
@@ -46,7 +46,7 @@ public class BSLinkset
|
||||
public int LinksetID { get; private set; }
|
||||
|
||||
// The children under the root in this linkset
|
||||
private List<BSPrim> m_children;
|
||||
private List<BSPhysObject> m_children;
|
||||
|
||||
// We lock the diddling of linkset classes to prevent any badness.
|
||||
// This locks the modification of the instances of this class. Changes
|
||||
@@ -74,7 +74,7 @@ public class BSLinkset
|
||||
get { return ComputeLinksetGeometricCenter(); }
|
||||
}
|
||||
|
||||
public BSLinkset(BSScene scene, BSPrim parent)
|
||||
public BSLinkset(BSScene scene, BSPhysObject parent)
|
||||
{
|
||||
// A simple linkset of one (no children)
|
||||
LinksetID = m_nextLinksetID++;
|
||||
@@ -83,14 +83,14 @@ public class BSLinkset
|
||||
m_nextLinksetID = 1;
|
||||
m_physicsScene = scene;
|
||||
m_linksetRoot = parent;
|
||||
m_children = new List<BSPrim>();
|
||||
m_children = new List<BSPhysObject>();
|
||||
m_mass = parent.MassRaw;
|
||||
}
|
||||
|
||||
// Link to a linkset where the child knows the parent.
|
||||
// Parent changing should not happen so do some sanity checking.
|
||||
// We return the parent's linkset so the child can track its membership.
|
||||
public BSLinkset AddMeToLinkset(BSPrim child)
|
||||
public BSLinkset AddMeToLinkset(BSPhysObject child)
|
||||
{
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
@@ -102,7 +102,7 @@ public class BSLinkset
|
||||
// Remove a child from a linkset.
|
||||
// Returns a new linkset for the child which is a linkset of one (just the
|
||||
// orphened child).
|
||||
public BSLinkset RemoveMeFromLinkset(BSPrim child)
|
||||
public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
|
||||
{
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
@@ -129,7 +129,7 @@ public class BSLinkset
|
||||
}
|
||||
|
||||
// Return 'true' if the passed object is the root object of this linkset
|
||||
public bool IsRoot(BSPrim requestor)
|
||||
public bool IsRoot(BSPhysObject requestor)
|
||||
{
|
||||
return (requestor.LocalID == m_linksetRoot.LocalID);
|
||||
}
|
||||
@@ -140,12 +140,12 @@ public class BSLinkset
|
||||
public bool HasAnyChildren { get { return (m_children.Count > 0); } }
|
||||
|
||||
// Return 'true' if this child is in this linkset
|
||||
public bool HasChild(BSPrim child)
|
||||
public bool HasChild(BSPhysObject child)
|
||||
{
|
||||
bool ret = false;
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
foreach (BSPrim bp in m_children)
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
{
|
||||
if (child.LocalID == bp.LocalID)
|
||||
{
|
||||
@@ -160,7 +160,7 @@ public class BSLinkset
|
||||
private float ComputeLinksetMass()
|
||||
{
|
||||
float mass = m_linksetRoot.MassRaw;
|
||||
foreach (BSPrim bp in m_children)
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
{
|
||||
mass += bp.MassRaw;
|
||||
}
|
||||
@@ -174,7 +174,7 @@ public class BSLinkset
|
||||
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
foreach (BSPrim bp in m_children)
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
{
|
||||
com += bp.Position * bp.MassRaw;
|
||||
totalMass += bp.MassRaw;
|
||||
@@ -192,7 +192,7 @@ public class BSLinkset
|
||||
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
foreach (BSPrim bp in m_children)
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
{
|
||||
com += bp.Position * bp.MassRaw;
|
||||
}
|
||||
@@ -204,7 +204,7 @@ public class BSLinkset
|
||||
|
||||
// When physical properties are changed the linkset needs to recalculate
|
||||
// its internal properties.
|
||||
public void Refresh(BSPrim requestor)
|
||||
public void Refresh(BSPhysObject requestor)
|
||||
{
|
||||
// If there are no children, there aren't any constraints to recompute
|
||||
if (!HasAnyChildren)
|
||||
@@ -230,7 +230,7 @@ public class BSLinkset
|
||||
float linksetMass = LinksetMass;
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
foreach (BSPrim child in m_children)
|
||||
foreach (BSPhysObject child in m_children)
|
||||
{
|
||||
BSConstraint constrain;
|
||||
if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain))
|
||||
@@ -255,14 +255,14 @@ public class BSLinkset
|
||||
|
||||
// I am the root of a linkset and a new child is being added
|
||||
// Called while LinkActivity is locked.
|
||||
private void AddChildToLinkset(BSPrim child)
|
||||
private void AddChildToLinkset(BSPhysObject child)
|
||||
{
|
||||
if (!HasChild(child))
|
||||
{
|
||||
m_children.Add(child);
|
||||
|
||||
BSPrim rootx = LinksetRoot; // capture the root as of now
|
||||
BSPrim childx = child;
|
||||
BSPhysObject rootx = LinksetRoot; // capture the root as of now
|
||||
BSPhysObject childx = child;
|
||||
m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
|
||||
{
|
||||
DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
|
||||
@@ -277,7 +277,7 @@ public class BSLinkset
|
||||
// it's still connected to the linkset.
|
||||
// Normal OpenSimulator operation will never do this because other SceneObjectPart information
|
||||
// has to be updated also (like pointer to prim's parent).
|
||||
private void RemoveChildFromOtherLinkset(BSPrim pchild)
|
||||
private void RemoveChildFromOtherLinkset(BSPhysObject pchild)
|
||||
{
|
||||
pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
|
||||
RemoveChildFromLinkset(pchild);
|
||||
@@ -285,12 +285,12 @@ public class BSLinkset
|
||||
|
||||
// I am the root of a linkset and one of my children is being removed.
|
||||
// Safe to call even if the child is not really in my linkset.
|
||||
private void RemoveChildFromLinkset(BSPrim child)
|
||||
private void RemoveChildFromLinkset(BSPhysObject child)
|
||||
{
|
||||
if (m_children.Remove(child))
|
||||
{
|
||||
BSPrim rootx = LinksetRoot; // capture the root as of now
|
||||
BSPrim childx = child;
|
||||
BSPhysObject rootx = LinksetRoot; // capture the root as of now
|
||||
BSPhysObject childx = child;
|
||||
m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
|
||||
{
|
||||
DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
|
||||
@@ -310,7 +310,7 @@ public class BSLinkset
|
||||
|
||||
// Create a constraint between me (root of linkset) and the passed prim (the child).
|
||||
// Called at taint time!
|
||||
private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim)
|
||||
private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||
{
|
||||
// Zero motion for children so they don't interpolate
|
||||
childPrim.ZeroMotion();
|
||||
@@ -383,7 +383,7 @@ public class BSLinkset
|
||||
|
||||
// Remove linkage between myself and a particular child
|
||||
// Called at taint time!
|
||||
private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim)
|
||||
private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||
{
|
||||
DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
|
||||
|
||||
@@ -396,7 +396,7 @@ public class BSLinkset
|
||||
|
||||
// Remove linkage between myself and any possible children I might have
|
||||
// Called at taint time!
|
||||
private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim)
|
||||
private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
|
||||
{
|
||||
DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
|
||||
|
||||
|
||||
60
OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
Executable file
60
OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
Executable file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyrightD
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using OMV = OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
// Class to wrap all objects.
|
||||
// The rest of BulletSim doesn't need to keep checking for avatars or prims
|
||||
// unless the difference is significant.
|
||||
public abstract class BSPhysObject : PhysicsActor
|
||||
{
|
||||
public abstract BSLinkset Linkset { get; set; }
|
||||
|
||||
public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type,
|
||||
OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth);
|
||||
public abstract void SendCollisions();
|
||||
|
||||
// Return the object mass without calculating it or side effects
|
||||
public abstract float MassRaw { get; }
|
||||
|
||||
public abstract BulletBody Body { get; set; }
|
||||
public abstract void ZeroMotion();
|
||||
|
||||
public virtual void StepVehicle(float timeStep) { }
|
||||
|
||||
public abstract void UpdateProperties(EntityProperties entprop);
|
||||
|
||||
public abstract void Destroy();
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet;
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class BSPrim : PhysicsActor
|
||||
public sealed class BSPrim : BSPhysObject
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly string LogHeader = "[BULLETS PRIM]";
|
||||
@@ -88,23 +88,14 @@ public sealed class BSPrim : PhysicsActor
|
||||
private float _buoyancy;
|
||||
|
||||
// Membership in a linkset is controlled by this class.
|
||||
private BSLinkset _linkset;
|
||||
public BSLinkset Linkset
|
||||
{
|
||||
get { return _linkset; }
|
||||
set { _linkset = value; }
|
||||
}
|
||||
public override BSLinkset Linkset { get; set; }
|
||||
|
||||
private int _subscribedEventsMs = 0;
|
||||
private int _nextCollisionOkTime = 0;
|
||||
long _collidingStep;
|
||||
long _collidingGroundStep;
|
||||
|
||||
private BulletBody m_body;
|
||||
public BulletBody Body {
|
||||
get { return m_body; }
|
||||
set { m_body = value; }
|
||||
}
|
||||
public override BulletBody Body { get; set; }
|
||||
|
||||
private BSDynamics _vehicle;
|
||||
|
||||
@@ -139,7 +130,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
_friction = _scene.Params.defaultFriction; // TODO: compute based on object material
|
||||
_density = _scene.Params.defaultDensity; // TODO: compute based on object material
|
||||
_restitution = _scene.Params.defaultRestitution;
|
||||
_linkset = new BSLinkset(Scene, this); // a linkset of one
|
||||
Linkset = new BSLinkset(Scene, this); // a linkset of one
|
||||
_vehicle = new BSDynamics(Scene, this); // add vehicleness
|
||||
_mass = CalculateMass();
|
||||
// do the actual object creation at taint time
|
||||
@@ -151,23 +142,23 @@ public sealed class BSPrim : PhysicsActor
|
||||
// Get the pointer to the physical body for this object.
|
||||
// At the moment, we're still letting BulletSim manage the creation and destruction
|
||||
// of the object. Someday we'll move that into the C# code.
|
||||
m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
});
|
||||
}
|
||||
|
||||
// called when this prim is being destroyed and we should free all the resources
|
||||
public void Destroy()
|
||||
public override void Destroy()
|
||||
{
|
||||
// m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
|
||||
|
||||
// Undo any links between me and any other object
|
||||
BSPrim parentBefore = _linkset.LinksetRoot;
|
||||
int childrenBefore = _linkset.NumberOfChildren;
|
||||
BSPhysObject parentBefore = Linkset.LinksetRoot;
|
||||
int childrenBefore = Linkset.NumberOfChildren;
|
||||
|
||||
_linkset = _linkset.RemoveMeFromLinkset(this);
|
||||
Linkset = Linkset.RemoveMeFromLinkset(this);
|
||||
|
||||
DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
|
||||
LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
|
||||
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
|
||||
|
||||
// Undo any vehicle properties
|
||||
this.VehicleType = (int)Vehicle.TYPE_NONE;
|
||||
@@ -230,13 +221,13 @@ public sealed class BSPrim : PhysicsActor
|
||||
BSPrim parent = obj as BSPrim;
|
||||
if (parent != null)
|
||||
{
|
||||
BSPrim parentBefore = _linkset.LinksetRoot;
|
||||
int childrenBefore = _linkset.NumberOfChildren;
|
||||
BSPhysObject parentBefore = Linkset.LinksetRoot;
|
||||
int childrenBefore = Linkset.NumberOfChildren;
|
||||
|
||||
_linkset = parent.Linkset.AddMeToLinkset(this);
|
||||
Linkset = parent.Linkset.AddMeToLinkset(this);
|
||||
|
||||
DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
|
||||
LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
|
||||
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -246,13 +237,13 @@ public sealed class BSPrim : PhysicsActor
|
||||
// TODO: decide if this parent checking needs to happen at taint time
|
||||
// Race condition here: if link() and delink() in same simulation tick, the delink will not happen
|
||||
|
||||
BSPrim parentBefore = _linkset.LinksetRoot;
|
||||
int childrenBefore = _linkset.NumberOfChildren;
|
||||
BSPhysObject parentBefore = Linkset.LinksetRoot;
|
||||
int childrenBefore = Linkset.NumberOfChildren;
|
||||
|
||||
_linkset = _linkset.RemoveMeFromLinkset(this);
|
||||
Linkset = Linkset.RemoveMeFromLinkset(this);
|
||||
|
||||
DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
|
||||
LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
|
||||
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -260,7 +251,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
// Do it to the properties so the values get set in the physics engine.
|
||||
// Push the setting of the values to the viewer.
|
||||
// Called at taint time!
|
||||
public void ZeroMotion()
|
||||
public override void ZeroMotion()
|
||||
{
|
||||
_velocity = OMV.Vector3.Zero;
|
||||
_acceleration = OMV.Vector3.Zero;
|
||||
@@ -281,7 +272,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
|
||||
public override OMV.Vector3 Position {
|
||||
get {
|
||||
if (!_linkset.IsRoot(this))
|
||||
if (!Linkset.IsRoot(this))
|
||||
// child prims move around based on their parent. Need to get the latest location
|
||||
_position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||
|
||||
@@ -306,23 +297,23 @@ public sealed class BSPrim : PhysicsActor
|
||||
{
|
||||
get
|
||||
{
|
||||
return _linkset.LinksetMass;
|
||||
return Linkset.LinksetMass;
|
||||
}
|
||||
}
|
||||
|
||||
// used when we only want this prim's mass and not the linkset thing
|
||||
public float MassRaw { get { return _mass; } }
|
||||
public override float MassRaw { get { return _mass; } }
|
||||
|
||||
// Is this used?
|
||||
public override OMV.Vector3 CenterOfMass
|
||||
{
|
||||
get { return _linkset.CenterOfMass; }
|
||||
get { return Linkset.CenterOfMass; }
|
||||
}
|
||||
|
||||
// Is this used?
|
||||
public override OMV.Vector3 GeometricCenter
|
||||
{
|
||||
get { return _linkset.GeometricCenter; }
|
||||
get { return Linkset.GeometricCenter; }
|
||||
}
|
||||
|
||||
public override OMV.Vector3 Force {
|
||||
@@ -386,7 +377,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
|
||||
// Called each simulation step to advance vehicle characteristics.
|
||||
// Called from Scene when doing simulation step so we're in taint processing time.
|
||||
public void StepVehicle(float timeStep)
|
||||
public override void StepVehicle(float timeStep)
|
||||
{
|
||||
if (IsPhysical)
|
||||
_vehicle.Step(timeStep);
|
||||
@@ -431,7 +422,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
}
|
||||
public override OMV.Quaternion Orientation {
|
||||
get {
|
||||
if (!_linkset.IsRoot(this))
|
||||
if (!Linkset.IsRoot(this))
|
||||
{
|
||||
// Children move around because tied to parent. Get a fresh value.
|
||||
_orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
|
||||
@@ -490,7 +481,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
|
||||
|
||||
// recompute any linkset parameters
|
||||
_linkset.Refresh(this);
|
||||
Linkset.Refresh(this);
|
||||
|
||||
CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr);
|
||||
DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf);
|
||||
@@ -1299,7 +1290,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
const float ACCELERATION_TOLERANCE = 0.01f;
|
||||
const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
|
||||
|
||||
public void UpdateProperties(EntityProperties entprop)
|
||||
public override void UpdateProperties(EntityProperties entprop)
|
||||
{
|
||||
/*
|
||||
UpdatedProperties changed = 0;
|
||||
@@ -1347,7 +1338,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
// Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
|
||||
|
||||
// Updates only for individual prims and for the root object of a linkset.
|
||||
if (_linkset.IsRoot(this))
|
||||
if (Linkset.IsRoot(this))
|
||||
{
|
||||
// Assign to the local variables so the normal set action does not happen
|
||||
_position = entprop.Position;
|
||||
@@ -1375,7 +1366,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
// I've collided with something
|
||||
// Called at taint time from within the Step() function
|
||||
CollisionEventUpdate collisionCollection;
|
||||
public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
|
||||
public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
|
||||
{
|
||||
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
|
||||
|
||||
@@ -1387,18 +1378,15 @@ public sealed class BSPrim : PhysicsActor
|
||||
}
|
||||
|
||||
// DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
|
||||
BSPrim collidingWithPrim;
|
||||
if (_scene.Prims.TryGetValue(collidingWith, out collidingWithPrim))
|
||||
|
||||
// prims in the same linkset cannot collide with each other
|
||||
if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
|
||||
{
|
||||
// prims in the same linkset cannot collide with each other
|
||||
if (this.Linkset.LinksetID == collidingWithPrim.Linkset.LinksetID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// if someone is subscribed to collision events....
|
||||
if (_subscribedEventsMs != 0) {
|
||||
// if someone has subscribed for collision events....
|
||||
if (SubscribedEvents()) {
|
||||
// throttle the collisions to the number of milliseconds specified in the subscription
|
||||
int nowTime = _scene.SimulationNowTime;
|
||||
if (nowTime >= _nextCollisionOkTime) {
|
||||
@@ -1412,7 +1400,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
}
|
||||
|
||||
// The scene is telling us it's time to pass our collected collisions into the simulator
|
||||
public void SendCollisions()
|
||||
public override void SendCollisions()
|
||||
{
|
||||
if (collisionCollection != null && collisionCollection.Count > 0)
|
||||
{
|
||||
|
||||
@@ -39,8 +39,6 @@ using log4net;
|
||||
using OpenMetaverse;
|
||||
|
||||
// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
|
||||
// Debug linkset
|
||||
// Test with multiple regions in one simulator
|
||||
// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight)
|
||||
// Test sculpties
|
||||
// Compute physics FPS reasonably
|
||||
@@ -54,10 +52,8 @@ using OpenMetaverse;
|
||||
// Use collision masks for collision with terrain and phantom objects
|
||||
// Check out llVolumeDetect. Must do something for that.
|
||||
// Should prim.link() and prim.delink() membership checking happen at taint time?
|
||||
// changing the position and orientation of a linked prim must rebuild the constraint with the root.
|
||||
// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
|
||||
// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
|
||||
// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
|
||||
// Implement LockAngularMotion
|
||||
// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
|
||||
// Does NeedsMeshing() really need to exclude all the different shapes?
|
||||
@@ -78,27 +74,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
public string BulletSimVersion = "?";
|
||||
|
||||
private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>();
|
||||
public Dictionary<uint, BSCharacter> Characters { get { return m_avatars; } }
|
||||
|
||||
private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>();
|
||||
public Dictionary<uint, BSPrim> Prims { get { return m_prims; } }
|
||||
public Dictionary<uint, BSPhysObject> PhysObjects = new Dictionary<uint, BSPhysObject>();
|
||||
|
||||
private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>();
|
||||
// Following is a kludge and can be removed when avatar animation updating is
|
||||
// moved to a better place.
|
||||
private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
|
||||
private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>();
|
||||
|
||||
private List<BSPrim> m_vehicles = new List<BSPrim>();
|
||||
|
||||
private float[] m_heightMap;
|
||||
private float m_waterLevel;
|
||||
private uint m_worldID;
|
||||
public uint WorldID { get { return m_worldID; } }
|
||||
// List of all the objects that have vehicle properties and should be called
|
||||
// to update each physics step.
|
||||
private List<BSPhysObject> m_vehicles = new List<BSPhysObject>();
|
||||
|
||||
// let my minuions use my logger
|
||||
public ILog Logger { get { return m_log; } }
|
||||
|
||||
private bool m_initialized = false;
|
||||
|
||||
// If non-zero, the number of simulation steps between calls to the physics
|
||||
// engine to output detailed physics stats. Debug logging level must be on also.
|
||||
private int m_detailedStatsStep = 0;
|
||||
|
||||
public IMesher mesher;
|
||||
@@ -108,29 +99,31 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
public float MeshMegaPrimThreshold { get; private set; }
|
||||
public float SculptLOD { get; private set; }
|
||||
|
||||
private BulletSim m_worldSim;
|
||||
public BulletSim World
|
||||
{
|
||||
get { return m_worldSim; }
|
||||
}
|
||||
private BSConstraintCollection m_constraintCollection;
|
||||
public BSConstraintCollection Constraints
|
||||
{
|
||||
get { return m_constraintCollection; }
|
||||
}
|
||||
public uint WorldID { get; private set; }
|
||||
public BulletSim World { get; private set; }
|
||||
|
||||
// All the constraints that have been allocated in this instance.
|
||||
public BSConstraintCollection Constraints { get; private set; }
|
||||
|
||||
// Simulation parameters
|
||||
private int m_maxSubSteps;
|
||||
private float m_fixedTimeStep;
|
||||
private long m_simulationStep = 0;
|
||||
public long SimulationStep { get { return m_simulationStep; } }
|
||||
|
||||
// The length of the last timestep we were asked to simulate.
|
||||
// This is used by the vehicle code. Since the vehicle code is called
|
||||
// once per simulation step, its constants need to be scaled by this.
|
||||
public float LastSimulatedTimestep { get; private set; }
|
||||
|
||||
// A value of the time now so all the collision and update routines do not have to get their own
|
||||
// Set to 'now' just before all the prims and actors are called for collisions and updates
|
||||
private int m_simulationNowTime;
|
||||
public int SimulationNowTime { get { return m_simulationNowTime; } }
|
||||
public int SimulationNowTime { get; private set; }
|
||||
|
||||
// True if initialized and ready to do simulation steps
|
||||
private bool m_initialized = false;
|
||||
|
||||
// Pinned memory used to pass step information between managed and unmanaged
|
||||
private int m_maxCollisionsPerFrame;
|
||||
private CollisionDesc[] m_collisionArray;
|
||||
private GCHandle m_collisionArrayPinnedHandle;
|
||||
@@ -147,6 +140,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
|
||||
public const uint GROUNDPLANE_ID = 1;
|
||||
public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
|
||||
|
||||
private float m_waterLevel;
|
||||
public BSTerrainManager TerrainManager { get; private set; }
|
||||
|
||||
public ConfigurationParameters Params
|
||||
{
|
||||
@@ -157,12 +154,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
get { return new Vector3(0f, 0f, Params.gravity); }
|
||||
}
|
||||
|
||||
private float m_maximumObjectMass;
|
||||
public float MaximumObjectMass
|
||||
{
|
||||
get { return m_maximumObjectMass; }
|
||||
}
|
||||
public float MaximumObjectMass { get; private set; }
|
||||
|
||||
// When functions in the unmanaged code must be called, it is only
|
||||
// done at a known time just before the simulation step. The taint
|
||||
// system saves all these function calls and executes them in
|
||||
// order before the simulation.
|
||||
public delegate void TaintCallback();
|
||||
private struct TaintCallbackEntry
|
||||
{
|
||||
@@ -178,6 +175,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
private Object _taintLock = new Object();
|
||||
|
||||
// A pointer to an instance if this structure is passed to the C++ code
|
||||
// Used to pass basic configuration values to the unmanaged code.
|
||||
ConfigurationParameters[] m_params;
|
||||
GCHandle m_paramsHandle;
|
||||
|
||||
@@ -192,10 +190,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
private string m_physicsLoggingDir;
|
||||
private string m_physicsLoggingPrefix;
|
||||
private int m_physicsLoggingFileMinutes;
|
||||
// 'true' of the vehicle code is to log lots of details
|
||||
public bool VehicleLoggingEnabled { get; private set; }
|
||||
|
||||
private bool m_vehicleLoggingEnabled;
|
||||
public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
|
||||
|
||||
#region Construction and Initialization
|
||||
public BSScene(string identifier)
|
||||
{
|
||||
m_initialized = false;
|
||||
@@ -218,6 +216,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
|
||||
m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
|
||||
|
||||
mesher = meshmerizer;
|
||||
_taintedObjects = new List<TaintCallbackEntry>();
|
||||
|
||||
// Enable very detailed logging.
|
||||
// By creating an empty logger when not logging, the log message invocation code
|
||||
// can be left in and every call doesn't have to check for null.
|
||||
@@ -230,38 +231,43 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
PhysicsLogging = new Logging.LogWriter();
|
||||
}
|
||||
|
||||
// If Debug logging level, enable logging from the unmanaged code
|
||||
m_DebugLogCallbackHandle = null;
|
||||
if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
|
||||
{
|
||||
m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
|
||||
if (PhysicsLogging.Enabled)
|
||||
// The handle is saved in a variable to make sure it doesn't get freed after this call
|
||||
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
|
||||
else
|
||||
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
|
||||
}
|
||||
|
||||
// Get the version of the DLL
|
||||
// TODO: this doesn't work yet. Something wrong with marshaling the returned string.
|
||||
// BulletSimVersion = BulletSimAPI.GetVersion();
|
||||
// m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
|
||||
|
||||
// if Debug, enable logging from the unmanaged code
|
||||
if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
|
||||
{
|
||||
m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
|
||||
if (PhysicsLogging.Enabled)
|
||||
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
|
||||
else
|
||||
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
|
||||
// the handle is saved in a variable to make sure it doesn't get freed after this call
|
||||
BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
|
||||
}
|
||||
|
||||
_taintedObjects = new List<TaintCallbackEntry>();
|
||||
|
||||
mesher = meshmerizer;
|
||||
// The bounding box for the simulated world
|
||||
// The bounding box for the simulated world. The origin is 0,0,0 unless we're
|
||||
// a child in a mega-region.
|
||||
// Turns out that Bullet really doesn't care about the extents of the simulated
|
||||
// area. It tracks active objects no matter where they are.
|
||||
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f);
|
||||
|
||||
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
|
||||
m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
|
||||
WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
|
||||
m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
|
||||
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
|
||||
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
|
||||
m_DebugLogCallbackHandle);
|
||||
|
||||
// Initialization to support the transition to a new API which puts most of the logic
|
||||
// into the C# code so it is easier to modify and add to.
|
||||
m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID));
|
||||
m_constraintCollection = new BSConstraintCollection(World);
|
||||
World = new BulletSim(WorldID, this, BulletSimAPI.GetSimHandle2(WorldID));
|
||||
|
||||
Constraints = new BSConstraintCollection(World);
|
||||
|
||||
TerrainManager = new BSTerrainManager(this);
|
||||
TerrainManager.CreateInitialGroundPlaneAndTerrain();
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
@@ -289,7 +295,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
|
||||
m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
|
||||
// Very detailed logging for vehicle debugging
|
||||
m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
|
||||
VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
|
||||
|
||||
// Do any replacements in the parameters
|
||||
m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
|
||||
@@ -324,6 +330,38 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
// m_log.DebugFormat("{0}: Dispose()", LogHeader);
|
||||
|
||||
// make sure no stepping happens while we're deleting stuff
|
||||
m_initialized = false;
|
||||
|
||||
TerrainManager.ReleaseGroundPlaneAndTerrain();
|
||||
|
||||
foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
|
||||
{
|
||||
kvp.Value.Destroy();
|
||||
}
|
||||
PhysObjects.Clear();
|
||||
|
||||
// Now that the prims are all cleaned up, there should be no constraints left
|
||||
if (Constraints != null)
|
||||
{
|
||||
Constraints.Dispose();
|
||||
Constraints = null;
|
||||
}
|
||||
|
||||
// Anything left in the unmanaged code should be cleaned out
|
||||
BulletSimAPI.Shutdown(WorldID);
|
||||
|
||||
// Not logging any more
|
||||
PhysicsLogging.Close();
|
||||
}
|
||||
#endregion // Construction and Initialization
|
||||
|
||||
#region Prim and Avatar addition and removal
|
||||
|
||||
public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
|
||||
{
|
||||
m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader);
|
||||
@@ -337,7 +375,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
if (!m_initialized) return null;
|
||||
|
||||
BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
|
||||
lock (m_avatars) m_avatars.Add(localID, actor);
|
||||
lock (PhysObjects) PhysObjects.Add(localID, actor);
|
||||
|
||||
// TODO: Remove kludge someday.
|
||||
// We must generate a collision for avatars whether they collide or not.
|
||||
// This is required by OpenSim to update avatar animations, etc.
|
||||
lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor);
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
@@ -352,7 +396,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (m_avatars) m_avatars.Remove(actor.LocalID);
|
||||
lock (PhysObjects) PhysObjects.Remove(actor.LocalID);
|
||||
// Remove kludge someday
|
||||
lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Remove(bsactor);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -374,7 +420,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
|
||||
try
|
||||
{
|
||||
lock (m_prims) m_prims.Remove(bsprim.LocalID);
|
||||
lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -399,7 +445,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
DetailLog("{0},AddPrimShape,call", localID);
|
||||
|
||||
BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
|
||||
lock (m_prims) m_prims.Add(localID, prim);
|
||||
lock (PhysObjects) PhysObjects.Add(localID, prim);
|
||||
return prim;
|
||||
}
|
||||
|
||||
@@ -408,6 +454,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// information call is not needed.
|
||||
public override void AddPhysicsActorTaint(PhysicsActor prim) { }
|
||||
|
||||
#endregion // Prim and Avatar addition and removal
|
||||
|
||||
#region Simulation
|
||||
// Simulate one timestep
|
||||
public override float Simulate(float timeStep)
|
||||
{
|
||||
@@ -424,6 +473,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
int simulateStartTime = Util.EnvironmentTickCount();
|
||||
|
||||
// update the prim states while we know the physics engine is not busy
|
||||
int numTaints = _taintedObjects.Count;
|
||||
ProcessTaints();
|
||||
|
||||
// Some of the prims operate with special vehicle properties
|
||||
@@ -435,14 +485,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
int numSubSteps = 0;
|
||||
try
|
||||
{
|
||||
numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
||||
numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
||||
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
|
||||
DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
|
||||
DetailLog("{0},Simulate,call, nTaints= {1}, substeps={2}, updates={3}, colliders={4}",
|
||||
DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e);
|
||||
// DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
|
||||
m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}",
|
||||
LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e);
|
||||
DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}",
|
||||
DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
|
||||
updatedEntityCount = 0;
|
||||
collidersCount = 0;
|
||||
}
|
||||
@@ -451,7 +504,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
|
||||
|
||||
// Get a value for 'now' so all the collision and update routines don't have to get their own
|
||||
m_simulationNowTime = Util.EnvironmentTickCount();
|
||||
SimulationNowTime = Util.EnvironmentTickCount();
|
||||
|
||||
// If there were collisions, process them by sending the event to the prim.
|
||||
// Collisions must be processed before updates.
|
||||
@@ -470,19 +523,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
// The above SendCollision's batch up the collisions on the objects.
|
||||
// Now push the collisions into the simulator.
|
||||
foreach (BSPrim bsp in m_primsWithCollisions)
|
||||
foreach (BSPhysObject bsp in m_objectsWithCollisions)
|
||||
bsp.SendCollisions();
|
||||
m_primsWithCollisions.Clear();
|
||||
m_objectsWithCollisions.Clear();
|
||||
|
||||
// This is a kludge to get avatar movement updated.
|
||||
// Don't send collisions only if there were collisions -- send everytime.
|
||||
// ODE sends collisions even if there are none and this is used to update
|
||||
// avatar animations and stuff.
|
||||
// foreach (BSCharacter bsc in m_avatarsWithCollisions)
|
||||
// bsc.SendCollisions();
|
||||
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
|
||||
kvp.Value.SendCollisions();
|
||||
m_avatarsWithCollisions.Clear();
|
||||
foreach (BSPhysObject bpo in m_avatarsWithCollisions)
|
||||
bpo.SendCollisions();
|
||||
// m_avatarsWithCollisions.Clear();
|
||||
|
||||
// If any of the objects had updated properties, tell the object it has been changed by the physics engine
|
||||
if (updatedEntityCount > 0)
|
||||
@@ -490,16 +540,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
for (int ii = 0; ii < updatedEntityCount; ii++)
|
||||
{
|
||||
EntityProperties entprop = m_updateArray[ii];
|
||||
BSPrim prim;
|
||||
if (m_prims.TryGetValue(entprop.ID, out prim))
|
||||
BSPhysObject pobj;
|
||||
if (PhysObjects.TryGetValue(entprop.ID, out pobj))
|
||||
{
|
||||
prim.UpdateProperties(entprop);
|
||||
continue;
|
||||
}
|
||||
BSCharacter actor;
|
||||
if (m_avatars.TryGetValue(entprop.ID, out actor))
|
||||
{
|
||||
actor.UpdateProperties(entprop);
|
||||
pobj.UpdateProperties(entprop);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -529,58 +573,47 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
}
|
||||
|
||||
// Something has collided
|
||||
private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration)
|
||||
private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration)
|
||||
{
|
||||
if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID)
|
||||
if (localID <= TerrainManager.HighestTerrainID)
|
||||
{
|
||||
return; // don't send collisions to the terrain
|
||||
}
|
||||
|
||||
BSPhysObject collider = PhysObjects[localID];
|
||||
// TODO: as of this code, terrain was not in the physical object list.
|
||||
// When BSTerrain is created and it will be in the list, we can remove
|
||||
// the possibility that it's not there and just fetch the collidee.
|
||||
BSPhysObject collidee = null;
|
||||
|
||||
ActorTypes type = ActorTypes.Prim;
|
||||
if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID)
|
||||
if (collidingWith <= TerrainManager.HighestTerrainID)
|
||||
{
|
||||
type = ActorTypes.Ground;
|
||||
else if (m_avatars.ContainsKey(collidingWith))
|
||||
type = ActorTypes.Agent;
|
||||
}
|
||||
else
|
||||
{
|
||||
collidee = PhysObjects[collidingWith];
|
||||
if (collidee is BSCharacter)
|
||||
type = ActorTypes.Agent;
|
||||
}
|
||||
|
||||
// DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
|
||||
|
||||
BSPrim prim;
|
||||
if (m_prims.TryGetValue(localID, out prim)) {
|
||||
prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
|
||||
m_primsWithCollisions.Add(prim);
|
||||
return;
|
||||
}
|
||||
BSCharacter actor;
|
||||
if (m_avatars.TryGetValue(localID, out actor)) {
|
||||
actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
|
||||
m_avatarsWithCollisions.Add(actor);
|
||||
return;
|
||||
}
|
||||
collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration);
|
||||
m_objectsWithCollisions.Add(collider);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endregion // Simulation
|
||||
|
||||
public override void GetResults() { }
|
||||
|
||||
#region Terrain
|
||||
|
||||
public override void SetTerrain(float[] heightMap) {
|
||||
m_heightMap = heightMap;
|
||||
this.TaintedObject("BSScene.SetTerrain", delegate()
|
||||
{
|
||||
BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
|
||||
});
|
||||
}
|
||||
|
||||
// Someday we will have complex terrain with caves and tunnels
|
||||
// For the moment, it's flat and convex
|
||||
public float GetTerrainHeightAtXYZ(Vector3 loc)
|
||||
{
|
||||
return GetTerrainHeightAtXY(loc.X, loc.Y);
|
||||
}
|
||||
|
||||
public float GetTerrainHeightAtXY(float tX, float tY)
|
||||
{
|
||||
if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize)
|
||||
return 30;
|
||||
return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
|
||||
TerrainManager.SetTerrain(heightMap);
|
||||
}
|
||||
|
||||
public override void SetWaterLevel(float baseheight)
|
||||
@@ -598,38 +631,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
// Although no one seems to check this, I do support combining.
|
||||
public override bool SupportsCombining()
|
||||
{
|
||||
// m_log.DebugFormat("{0}: Dispose()", LogHeader);
|
||||
|
||||
// make sure no stepping happens while we're deleting stuff
|
||||
m_initialized = false;
|
||||
|
||||
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
|
||||
{
|
||||
kvp.Value.Destroy();
|
||||
}
|
||||
m_avatars.Clear();
|
||||
|
||||
foreach (KeyValuePair<uint, BSPrim> kvp in m_prims)
|
||||
{
|
||||
kvp.Value.Destroy();
|
||||
}
|
||||
m_prims.Clear();
|
||||
|
||||
// Now that the prims are all cleaned up, there should be no constraints left
|
||||
if (m_constraintCollection != null)
|
||||
{
|
||||
m_constraintCollection.Dispose();
|
||||
m_constraintCollection = null;
|
||||
}
|
||||
|
||||
// Anything left in the unmanaged code should be cleaned out
|
||||
BulletSimAPI.Shutdown(WorldID);
|
||||
|
||||
// Not logging any more
|
||||
PhysicsLogging.Close();
|
||||
return TerrainManager.SupportsCombining();
|
||||
}
|
||||
// This call says I am a child to region zero in a mega-region. 'pScene' is that
|
||||
// of region zero, 'offset' is my offset from regions zero's origin, and
|
||||
// 'extents' is the largest XY that is handled in my region.
|
||||
public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
|
||||
{
|
||||
TerrainManager.Combine(pScene, offset, extents);
|
||||
}
|
||||
|
||||
// Unhook all the combining that I know about.
|
||||
public override void UnCombine(PhysicsScene pScene)
|
||||
{
|
||||
TerrainManager.UnCombine(pScene);
|
||||
}
|
||||
|
||||
#endregion // Terrain
|
||||
|
||||
public override Dictionary<uint, float> GetTopColliders()
|
||||
{
|
||||
@@ -840,14 +861,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// no locking because only called when physics engine is not busy
|
||||
private void ProcessVehicles(float timeStep)
|
||||
{
|
||||
foreach (BSPrim prim in m_vehicles)
|
||||
foreach (BSPhysObject pobj in m_vehicles)
|
||||
{
|
||||
prim.StepVehicle(timeStep);
|
||||
pobj.StepVehicle(timeStep);
|
||||
}
|
||||
}
|
||||
#endregion Vehicles
|
||||
|
||||
#region Parameters
|
||||
#region INI and command line parameter processing
|
||||
|
||||
delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
|
||||
delegate float ParamGet(BSScene scene);
|
||||
@@ -950,9 +971,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
(s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
|
||||
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
|
||||
10000.01f,
|
||||
(s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)s.m_maximumObjectMass; },
|
||||
(s,p,l,v) => { s.m_maximumObjectMass = v; } ),
|
||||
(s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)s.MaximumObjectMass; },
|
||||
(s,p,l,v) => { s.MaximumObjectMass = v; } ),
|
||||
|
||||
new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
|
||||
2200f,
|
||||
@@ -996,42 +1017,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
0f,
|
||||
(s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].linearDamping; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); } ),
|
||||
new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
|
||||
0f,
|
||||
(s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].angularDamping; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); } ),
|
||||
new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
|
||||
0.2f,
|
||||
(s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].deactivationTime; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); } ),
|
||||
new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
|
||||
0.8f,
|
||||
(s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].linearSleepingThreshold; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
|
||||
new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
|
||||
1.0f,
|
||||
(s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].angularSleepingThreshold; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
|
||||
new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
|
||||
0f, // set to zero to disable
|
||||
(s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].ccdMotionThreshold; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
|
||||
new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
|
||||
0f,
|
||||
(s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].ccdSweptSphereRadius; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
|
||||
new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
|
||||
0.1f,
|
||||
(s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].contactProcessingThreshold; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
|
||||
|
||||
new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
||||
0.5f,
|
||||
@@ -1049,35 +1070,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
(s) => { return s.m_params[0].terrainRestitution; },
|
||||
(s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
|
||||
new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
|
||||
0.5f,
|
||||
0.2f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarFriction; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
|
||||
new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
|
||||
60f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarDensity; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ),
|
||||
new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
|
||||
0f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarRestitution; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
|
||||
new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
|
||||
0.37f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarCapsuleRadius; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
|
||||
new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
|
||||
1.5f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarCapsuleHeight; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
|
||||
new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
|
||||
0.1f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarContactProcessingThreshold; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
|
||||
|
||||
|
||||
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
|
||||
@@ -1214,6 +1235,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
|
||||
|
||||
// This creates an array in the correct format for returning the list of
|
||||
// parameters. This is used by the 'list' option of the 'physics' command.
|
||||
private void BuildParameterTable()
|
||||
{
|
||||
if (SettableParameters.Length < ParameterDefinitions.Length)
|
||||
@@ -1264,18 +1287,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
}
|
||||
|
||||
// check to see if we are updating a parameter for a particular or all of the prims
|
||||
protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val)
|
||||
protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val)
|
||||
{
|
||||
List<uint> operateOn;
|
||||
lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
|
||||
UpdateParameterSet(operateOn, ref loc, parm, localID, val);
|
||||
}
|
||||
|
||||
// check to see if we are updating a parameter for a particular or all of the avatars
|
||||
protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
|
||||
{
|
||||
List<uint> operateOn;
|
||||
lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys);
|
||||
lock (PhysObjects) operateOn = new List<uint>(PhysObjects.Keys);
|
||||
UpdateParameterSet(operateOn, ref loc, parm, localID, val);
|
||||
}
|
||||
|
||||
@@ -1298,7 +1313,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
TaintedObject("BSScene.UpdateParameterSet", delegate() {
|
||||
foreach (uint lID in objectIDs)
|
||||
{
|
||||
BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval);
|
||||
BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval);
|
||||
}
|
||||
});
|
||||
break;
|
||||
@@ -1316,7 +1331,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
string xparm = parm.ToLower();
|
||||
float xval = val;
|
||||
TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
|
||||
BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval);
|
||||
BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
464
OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
Executable file
464
OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
Executable file
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyrightD
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework;
|
||||
using OpenSim.Region.CoreModules;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
using Nini.Config;
|
||||
using log4net;
|
||||
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public class BSTerrainManager
|
||||
{
|
||||
static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
|
||||
|
||||
// These height values are fractional so the odd values will be
|
||||
// noticable when debugging.
|
||||
public const float HEIGHT_INITIALIZATION = 24.987f;
|
||||
public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f;
|
||||
public const float HEIGHT_GETHEIGHT_RET = 24.765f;
|
||||
|
||||
// If the min and max height are equal, we reduce the min by this
|
||||
// amount to make sure that a bounding box is built for the terrain.
|
||||
public const float HEIGHT_EQUAL_FUDGE = 0.2f;
|
||||
|
||||
public const float TERRAIN_COLLISION_MARGIN = 0.0f;
|
||||
|
||||
// Until the whole simulator is changed to pass us the region size, we rely on constants.
|
||||
public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, 0f);
|
||||
|
||||
// The scene that I am part of
|
||||
private BSScene m_physicsScene;
|
||||
|
||||
// The ground plane created to keep thing from falling to infinity.
|
||||
private BulletBody m_groundPlane;
|
||||
|
||||
// If doing mega-regions, if we're region zero we will be managing multiple
|
||||
// region terrains since region zero does the physics for the whole mega-region.
|
||||
private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps;
|
||||
|
||||
// True of the terrain has been modified.
|
||||
// Used to force recalculation of terrain height after terrain has been modified
|
||||
private bool m_terrainModified;
|
||||
|
||||
// If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount.
|
||||
// This is incremented before assigning to new region so it is the last ID allocated.
|
||||
private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1;
|
||||
public uint HighestTerrainID { get {return m_terrainCount; } }
|
||||
|
||||
// If doing mega-regions, this holds our offset from region zero of
|
||||
// the mega-regions. "parentScene" points to the PhysicsScene of region zero.
|
||||
private Vector3 m_worldOffset;
|
||||
// If the parent region (region 0), this is the extent of the combined regions
|
||||
// relative to the origin of region zero
|
||||
private Vector3 m_worldMax;
|
||||
private PhysicsScene m_parentScene;
|
||||
|
||||
public BSTerrainManager(BSScene physicsScene)
|
||||
{
|
||||
m_physicsScene = physicsScene;
|
||||
m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>();
|
||||
m_terrainModified = false;
|
||||
|
||||
// Assume one region of default size
|
||||
m_worldOffset = Vector3.Zero;
|
||||
m_worldMax = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, 4096f);
|
||||
m_parentScene = null;
|
||||
}
|
||||
|
||||
// Create the initial instance of terrain and the underlying ground plane.
|
||||
// The objects are allocated in the unmanaged space and the pointers are tracked
|
||||
// by the managed code.
|
||||
// The terrains and the groundPlane are not added to the list of PhysObjects.
|
||||
// This is called from the initialization routine so we presume it is
|
||||
// safe to call Bullet in real time. We hope no one is moving prims around yet.
|
||||
public void CreateInitialGroundPlaneAndTerrain()
|
||||
{
|
||||
// The ground plane is here to catch things that are trying to drop to negative infinity
|
||||
BulletShape groundPlaneShape = new BulletShape(BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN));
|
||||
m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
|
||||
BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.Ptr, Vector3.Zero, Quaternion.Identity));
|
||||
BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
|
||||
|
||||
Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE);
|
||||
Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION);
|
||||
int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
|
||||
float[] initialMap = new float[totalHeights];
|
||||
for (int ii = 0; ii < totalHeights; ii++)
|
||||
{
|
||||
initialMap[ii] = HEIGHT_INITIALIZATION;
|
||||
}
|
||||
UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true);
|
||||
}
|
||||
|
||||
// Release all the terrain structures we might have allocated
|
||||
public void ReleaseGroundPlaneAndTerrain()
|
||||
{
|
||||
if (m_groundPlane.Ptr != IntPtr.Zero)
|
||||
{
|
||||
if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr))
|
||||
{
|
||||
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
|
||||
}
|
||||
m_groundPlane.Ptr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
ReleaseTerrain();
|
||||
}
|
||||
|
||||
// Release all the terrain we have allocated
|
||||
public void ReleaseTerrain()
|
||||
{
|
||||
foreach (KeyValuePair<Vector2, BulletHeightMapInfo> kvp in m_heightMaps)
|
||||
{
|
||||
if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr))
|
||||
{
|
||||
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr);
|
||||
BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr);
|
||||
}
|
||||
}
|
||||
m_heightMaps.Clear();
|
||||
}
|
||||
|
||||
// The simulator wants to set a new heightmap for the terrain.
|
||||
public void SetTerrain(float[] heightMap) {
|
||||
if (m_worldOffset != Vector3.Zero && m_parentScene != null)
|
||||
{
|
||||
// If a child of a mega-region, we shouldn't have any terrain allocated for us
|
||||
ReleaseGroundPlaneAndTerrain();
|
||||
// If doing the mega-prim stuff and we are the child of the zero region,
|
||||
// the terrain is added to our parent
|
||||
if (m_parentScene is BSScene)
|
||||
{
|
||||
DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
|
||||
BSScene.DetailLogZero, m_worldOffset, m_worldMax);
|
||||
((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
|
||||
heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If not doing the mega-prim thing, just change the terrain
|
||||
DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
|
||||
|
||||
UpdateOrCreateTerrain(BSScene.TERRAIN_ID, heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
|
||||
}
|
||||
}
|
||||
|
||||
// If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
|
||||
// based on the passed information. The 'id' should be either the terrain id or
|
||||
// BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
|
||||
// The latter feature is for creating child terrains for mega-regions.
|
||||
// If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0)
|
||||
// then a new body and shape is created and the mapInfo is filled.
|
||||
// This call is used for doing the initial terrain creation.
|
||||
// If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
|
||||
// terrain shape is created and added to the body.
|
||||
// This call is most often used to update the heightMap and parameters of the terrain.
|
||||
// The 'doNow' boolean says whether to do all the unmanaged activities right now (like when
|
||||
// calling this routine from initialization or taint-time routines) or whether to delay
|
||||
// all the unmanaged activities to taint-time.
|
||||
private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool doNow)
|
||||
{
|
||||
DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},doNow={3}",
|
||||
BSScene.DetailLogZero, minCoords, maxCoords, doNow);
|
||||
|
||||
float minZ = float.MaxValue;
|
||||
float maxZ = float.MinValue;
|
||||
Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y);
|
||||
|
||||
int heightMapSize = heightMap.Length;
|
||||
for (int ii = 0; ii < heightMapSize; ii++)
|
||||
{
|
||||
float height = heightMap[ii];
|
||||
if (height < minZ) minZ = height;
|
||||
if (height > maxZ) maxZ = height;
|
||||
}
|
||||
|
||||
// The shape of the terrain is from its base to its extents.
|
||||
minCoords.Z = minZ;
|
||||
maxCoords.Z = maxZ;
|
||||
|
||||
BulletHeightMapInfo mapInfo;
|
||||
if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo))
|
||||
{
|
||||
// If this is terrain we know about, it's easy to update
|
||||
|
||||
mapInfo.heightMap = heightMap;
|
||||
mapInfo.minCoords = minCoords;
|
||||
mapInfo.maxCoords = maxCoords;
|
||||
mapInfo.minZ = minZ;
|
||||
mapInfo.maxZ = maxZ;
|
||||
mapInfo.sizeX = maxCoords.X - minCoords.X;
|
||||
mapInfo.sizeY = maxCoords.Y - minCoords.Y;
|
||||
DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
|
||||
BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
|
||||
|
||||
BSScene.TaintCallback rebuildOperation = delegate()
|
||||
{
|
||||
if (m_parentScene != null)
|
||||
{
|
||||
// It's possible that Combine() was called after this code was queued.
|
||||
// If we are a child of combined regions, we don't create any terrain for us.
|
||||
DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);
|
||||
|
||||
// Get rid of any terrain that may have been allocated for us.
|
||||
ReleaseGroundPlaneAndTerrain();
|
||||
|
||||
// I hate doing this, but just bail
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapInfo.terrainBody.Ptr != IntPtr.Zero)
|
||||
{
|
||||
// Updating an existing terrain.
|
||||
DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
|
||||
BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
|
||||
|
||||
// Remove from the dynamics world because we're going to mangle this object
|
||||
BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||
|
||||
// Get rid of the old terrain
|
||||
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||
BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr);
|
||||
mapInfo.Ptr = IntPtr.Zero;
|
||||
|
||||
/*
|
||||
// NOTE: This routine is half here because I can't get the terrain shape replacement
|
||||
// to work. In the short term, the above three lines completely delete the old
|
||||
// terrain and the code below recreates one from scratch.
|
||||
// Hopefully the Bullet community will help me out on this one.
|
||||
|
||||
// First, release the old collision shape (there is only one terrain)
|
||||
BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr);
|
||||
|
||||
// Fill the existing height map info with the new location and size information
|
||||
BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID,
|
||||
mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
|
||||
|
||||
// Create a terrain shape based on the new info
|
||||
mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
|
||||
|
||||
// Stuff the shape into the existing terrain body
|
||||
BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr);
|
||||
*/
|
||||
}
|
||||
// else
|
||||
{
|
||||
// Creating a new terrain.
|
||||
DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}",
|
||||
BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ);
|
||||
|
||||
mapInfo.ID = id;
|
||||
mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.ID,
|
||||
mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
|
||||
|
||||
// The terrain object initial position is at the center of the object
|
||||
Vector3 centerPos;
|
||||
centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
|
||||
centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
|
||||
centerPos.Z = minZ + ((maxZ - minZ) / 2f);
|
||||
|
||||
// Create the terrain shape from the mapInfo
|
||||
mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
|
||||
|
||||
mapInfo.terrainBody = new BulletBody(mapInfo.ID,
|
||||
BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.Ptr,
|
||||
centerPos, Quaternion.Identity));
|
||||
}
|
||||
|
||||
// Make sure the entry is in the heightmap table
|
||||
m_heightMaps[terrainRegionBase] = mapInfo;
|
||||
|
||||
// Set current terrain attributes
|
||||
BulletSimAPI.SetFriction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainFriction);
|
||||
BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction);
|
||||
BulletSimAPI.SetRestitution2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainRestitution);
|
||||
BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
|
||||
|
||||
BulletSimAPI.SetMassProps2(mapInfo.terrainBody.Ptr, 0f, Vector3.Zero);
|
||||
BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.Ptr);
|
||||
|
||||
// Return the new terrain to the world of physical objects
|
||||
BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||
|
||||
// redo its bounding box now that it is in the world
|
||||
BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||
|
||||
// Make sure the new shape is processed.
|
||||
BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true);
|
||||
};
|
||||
|
||||
// There is the option to do the changes now (we're already in 'taint time'), or
|
||||
// to do the Bullet operations later.
|
||||
if (doNow)
|
||||
rebuildOperation();
|
||||
else
|
||||
m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't know about this terrain so either we are creating a new terrain or
|
||||
// our mega-prim child is giving us a new terrain to add to the phys world
|
||||
|
||||
// if this is a child terrain, calculate a unique terrain id
|
||||
uint newTerrainID = id;
|
||||
if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
|
||||
newTerrainID = ++m_terrainCount;
|
||||
|
||||
float[] heightMapX = heightMap;
|
||||
Vector3 minCoordsX = minCoords;
|
||||
Vector3 maxCoordsX = maxCoords;
|
||||
|
||||
DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}",
|
||||
BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
|
||||
|
||||
// Code that must happen at taint-time
|
||||
BSScene.TaintCallback createOperation = delegate()
|
||||
{
|
||||
DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y);
|
||||
// Create a new mapInfo that will be filled with the new info
|
||||
mapInfo = new BulletHeightMapInfo(id, heightMapX,
|
||||
BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, newTerrainID,
|
||||
minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN));
|
||||
// Put the unfilled heightmap info into the collection of same
|
||||
m_heightMaps.Add(terrainRegionBase, mapInfo);
|
||||
// Build the terrain
|
||||
UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
|
||||
};
|
||||
|
||||
// If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
|
||||
if (doNow)
|
||||
createOperation();
|
||||
else
|
||||
m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
|
||||
}
|
||||
}
|
||||
|
||||
// Someday we will have complex terrain with caves and tunnels
|
||||
public float GetTerrainHeightAtXYZ(Vector3 loc)
|
||||
{
|
||||
// For the moment, it's flat and convex
|
||||
return GetTerrainHeightAtXY(loc.X, loc.Y);
|
||||
}
|
||||
|
||||
// Given an X and Y, find the height of the terrain.
|
||||
// Since we could be handling multiple terrains for a mega-region,
|
||||
// the base of the region is calcuated assuming all regions are
|
||||
// the same size and that is the default.
|
||||
// Once the heightMapInfo is found, we have all the information to
|
||||
// compute the offset into the array.
|
||||
private float lastHeightTX = 999999f;
|
||||
private float lastHeightTY = 999999f;
|
||||
private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
|
||||
public float GetTerrainHeightAtXY(float tX, float tY)
|
||||
{
|
||||
// You'd be surprized at the number of times this routine is called
|
||||
// with the same parameters as last time.
|
||||
if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY)
|
||||
return lastHeight;
|
||||
|
||||
lastHeightTX = tX;
|
||||
lastHeightTY = tY;
|
||||
float ret = HEIGHT_GETHEIGHT_RET;
|
||||
|
||||
int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
|
||||
int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
|
||||
Vector2 terrainBaseXY = new Vector2(offsetX, offsetY);
|
||||
|
||||
BulletHeightMapInfo mapInfo;
|
||||
if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo))
|
||||
{
|
||||
float regionX = tX - offsetX;
|
||||
float regionY = tY - offsetY;
|
||||
if (regionX > mapInfo.sizeX) regionX = 0;
|
||||
if (regionY > mapInfo.sizeY) regionY = 0;
|
||||
int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX;
|
||||
ret = mapInfo.heightMap[mapIndex];
|
||||
m_terrainModified = false;
|
||||
DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
|
||||
BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
|
||||
LogHeader, m_physicsScene.RegionName, tX, tY);
|
||||
}
|
||||
lastHeight = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Although no one seems to check this, I do support combining.
|
||||
public bool SupportsCombining()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// This routine is called two ways:
|
||||
// One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum
|
||||
// extent of the combined regions. This is to inform the parent of the size
|
||||
// of the combined regions.
|
||||
// and one with 'offset' as the offset of the child region to the base region,
|
||||
// 'pScene' pointing to the parent and 'extents' of zero. This informs the
|
||||
// child of its relative base and new parent.
|
||||
public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
|
||||
{
|
||||
m_worldOffset = offset;
|
||||
m_worldMax = extents;
|
||||
m_parentScene = pScene;
|
||||
if (pScene != null)
|
||||
{
|
||||
// We are a child.
|
||||
// We want m_worldMax to be the highest coordinate of our piece of terrain.
|
||||
m_worldMax = offset + DefaultRegionSize;
|
||||
}
|
||||
DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}",
|
||||
BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax);
|
||||
}
|
||||
|
||||
// Unhook all the combining that I know about.
|
||||
public void UnCombine(PhysicsScene pScene)
|
||||
{
|
||||
// Just like ODE, for the moment a NOP
|
||||
DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
|
||||
}
|
||||
|
||||
|
||||
private void DetailLog(string msg, params Object[] args)
|
||||
{
|
||||
m_physicsScene.PhysicsLogging.Write(msg, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,15 +33,25 @@ using OpenMetaverse;
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin {
|
||||
|
||||
// Classes to allow some type checking for the API
|
||||
// These hold pointers to allocated objects in the unmanaged space.
|
||||
|
||||
// The physics engine controller class created at initialization
|
||||
public struct BulletSim
|
||||
{
|
||||
public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; }
|
||||
public uint ID;
|
||||
public BulletSim(uint worldId, BSScene bss, IntPtr xx) { worldID = worldId; scene = bss; Ptr = xx; }
|
||||
public uint worldID;
|
||||
// The scene is only in here so very low level routines have a handle to print debug/error messages
|
||||
public BSScene scene;
|
||||
public IntPtr Ptr;
|
||||
}
|
||||
|
||||
public struct BulletShape
|
||||
{
|
||||
public BulletShape(IntPtr xx) { Ptr = xx; }
|
||||
public IntPtr Ptr;
|
||||
}
|
||||
|
||||
// An allocated Bullet btRigidBody
|
||||
public struct BulletBody
|
||||
{
|
||||
public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
|
||||
@@ -49,12 +59,41 @@ public struct BulletBody
|
||||
public uint ID;
|
||||
}
|
||||
|
||||
// An allocated Bullet btConstraint
|
||||
public struct BulletConstraint
|
||||
{
|
||||
public BulletConstraint(IntPtr xx) { Ptr = xx; }
|
||||
public IntPtr Ptr;
|
||||
}
|
||||
|
||||
// An allocated HeightMapThing which hold various heightmap info
|
||||
// Made a class rather than a struct so there would be only one
|
||||
// instance of this and C# will pass around pointers rather
|
||||
// than making copies.
|
||||
public class BulletHeightMapInfo
|
||||
{
|
||||
public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) {
|
||||
ID = id;
|
||||
Ptr = xx;
|
||||
heightMap = hm;
|
||||
terrainRegionBase = new Vector2(0f, 0f);
|
||||
minCoords = new Vector3(100f, 100f, 25f);
|
||||
maxCoords = new Vector3(101f, 101f, 26f);
|
||||
minZ = maxZ = 0f;
|
||||
sizeX = sizeY = 256f;
|
||||
}
|
||||
public uint ID;
|
||||
public IntPtr Ptr;
|
||||
public float[] heightMap;
|
||||
public Vector2 terrainRegionBase;
|
||||
public Vector3 minCoords;
|
||||
public Vector3 maxCoords;
|
||||
public float sizeX, sizeY;
|
||||
public float minZ, maxZ;
|
||||
public BulletShape terrainShape;
|
||||
public BulletBody terrainBody;
|
||||
}
|
||||
|
||||
// ===============================================================================
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ConvexHull
|
||||
@@ -221,6 +260,10 @@ public enum ConstraintParamAxis : int
|
||||
// ===============================================================================
|
||||
static class BulletSimAPI {
|
||||
|
||||
// Link back to the managed code for outputting log messages
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
public static extern string GetVersion();
|
||||
@@ -228,7 +271,11 @@ public static extern string GetVersion();
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern uint Initialize(Vector3 maxPosition, IntPtr parms,
|
||||
int maxCollisions, IntPtr collisionArray,
|
||||
int maxUpdates, IntPtr updateArray);
|
||||
int maxUpdates, IntPtr updateArray,
|
||||
DebugLogCallback logRoutine);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
|
||||
@@ -342,8 +389,6 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id);
|
||||
public static extern void DumpBulletStatistics();
|
||||
|
||||
// Log a debug message
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetDebugLogCallback(DebugLogCallback callback);
|
||||
|
||||
@@ -377,7 +422,7 @@ public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
|
||||
public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetHeightmap2(IntPtr world, float[] heightmap);
|
||||
public static extern void SetHeightMap2(IntPtr world, float[] heightmap);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void Shutdown2(IntPtr sim);
|
||||
@@ -392,23 +437,53 @@ public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSt
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool PushUpdate2(IntPtr obj);
|
||||
|
||||
/*
|
||||
// =====================================================================================
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices );
|
||||
public static extern IntPtr CreateMeshShape2(IntPtr world,
|
||||
int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
|
||||
int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool BuildHull2(IntPtr world, IntPtr mesh);
|
||||
public static extern IntPtr CreateHullShape2(IntPtr world,
|
||||
int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh);
|
||||
public static extern IntPtr BuildHullShape2(IntPtr world, IntPtr meshShape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh);
|
||||
public static extern IntPtr BuildNativeShape2(IntPtr world,
|
||||
float shapeType, float collisionMargin, Vector3 scale);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData);
|
||||
*/
|
||||
public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetBodyShape2(IntPtr sim, IntPtr obj, IntPtr shape);
|
||||
// =====================================================================================
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
|
||||
[MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords,
|
||||
[MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo);
|
||||
|
||||
// =====================================================================================
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||
Vector3 frame1loc, Quaternion frame1rot,
|
||||
@@ -460,11 +535,16 @@ public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
|
||||
|
||||
// =====================================================================================
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj);
|
||||
public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
|
||||
public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
|
||||
|
||||
// =====================================================================================
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void Activate2(IntPtr obj, bool forceActivation);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetPosition2(IntPtr obj);
|
||||
@@ -508,6 +588,9 @@ public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val);
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetFriction2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetHitFraction2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetRestitution2(IntPtr obj, float val);
|
||||
|
||||
@@ -551,7 +634,7 @@ public static extern bool SetMargin2(IntPtr obj, float val);
|
||||
public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool DestroyObject2(IntPtr world, uint id);
|
||||
public static extern bool DestroyObject2(IntPtr world, IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void DumpPhysicsStatistics2(IntPtr sim);
|
||||
|
||||
@@ -247,7 +247,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
return GetLinkParts(m_host, linkType);
|
||||
}
|
||||
|
||||
private List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
|
||||
public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
|
||||
{
|
||||
List<SceneObjectPart> ret = new List<SceneObjectPart>();
|
||||
ret.Add(part);
|
||||
@@ -1341,11 +1341,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y));
|
||||
scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z));
|
||||
}
|
||||
|
||||
// Next we clamp the scale to the non-physical min/max
|
||||
scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x));
|
||||
scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y));
|
||||
scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z));
|
||||
else
|
||||
{
|
||||
// If not physical, then we clamp the scale to the non-physical min/max
|
||||
scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x));
|
||||
scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y));
|
||||
scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z));
|
||||
}
|
||||
|
||||
Vector3 tmp = part.Scale;
|
||||
tmp.X = (float)scale.x;
|
||||
@@ -5163,25 +5165,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
/// separated list. There is a space after
|
||||
/// each comma.
|
||||
/// </summary>
|
||||
|
||||
public LSL_String llList2CSV(LSL_List src)
|
||||
{
|
||||
|
||||
string ret = String.Empty;
|
||||
int x = 0;
|
||||
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
if (src.Data.Length > 0)
|
||||
{
|
||||
ret = src.Data[x++].ToString();
|
||||
for (; x < src.Data.Length; x++)
|
||||
{
|
||||
ret += ", "+src.Data[x].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return string.Join(", ",
|
||||
(new List<object>(src.Data)).ConvertAll<string>(o =>
|
||||
{
|
||||
return o.ToString();
|
||||
}).ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -5836,7 +5828,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
List<SceneObjectPart> parts = GetLinkParts(linknumber);
|
||||
|
||||
foreach (var part in parts)
|
||||
foreach (SceneObjectPart part in parts)
|
||||
{
|
||||
SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
|
||||
}
|
||||
@@ -6198,7 +6190,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
List<SceneObjectPart> parts = GetLinkParts(linknumber);
|
||||
|
||||
foreach (var part in parts)
|
||||
foreach (SceneObjectPart part in parts)
|
||||
{
|
||||
SetParticleSystem(part, rules);
|
||||
}
|
||||
@@ -7216,7 +7208,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules);
|
||||
setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams");
|
||||
|
||||
ScriptSleep(200);
|
||||
}
|
||||
@@ -7225,7 +7217,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
setLinkPrimParams(linknumber, rules);
|
||||
setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
|
||||
|
||||
ScriptSleep(200);
|
||||
}
|
||||
@@ -7234,32 +7226,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
setLinkPrimParams(linknumber, rules);
|
||||
setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
|
||||
}
|
||||
|
||||
protected void setLinkPrimParams(int linknumber, LSL_List rules)
|
||||
protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
|
||||
{
|
||||
List<SceneObjectPart> parts = GetLinkParts(linknumber);
|
||||
|
||||
LSL_List remaining = null;
|
||||
uint rulesParsed = 0;
|
||||
|
||||
foreach (SceneObjectPart part in parts)
|
||||
remaining = SetPrimParams(part, rules);
|
||||
remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed);
|
||||
|
||||
while(remaining != null && remaining.Length > 2)
|
||||
while (remaining != null && remaining.Length > 2)
|
||||
{
|
||||
linknumber = remaining.GetLSLIntegerItem(0);
|
||||
rules = remaining.GetSublist(1,-1);
|
||||
rules = remaining.GetSublist(1, -1);
|
||||
parts = GetLinkParts(linknumber);
|
||||
|
||||
foreach (SceneObjectPart part in parts)
|
||||
remaining = SetPrimParams(part, rules);
|
||||
remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed);
|
||||
}
|
||||
}
|
||||
|
||||
protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules)
|
||||
protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
|
||||
{
|
||||
int idx = 0;
|
||||
int idxStart = 0;
|
||||
|
||||
bool positionChanged = false;
|
||||
LSL_Vector currentPosition = GetPartLocalPos(part);
|
||||
@@ -7268,9 +7262,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
{
|
||||
while (idx < rules.Length)
|
||||
{
|
||||
++rulesParsed;
|
||||
int code = rules.GetLSLIntegerItem(idx++);
|
||||
|
||||
int remain = rules.Length - idx;
|
||||
idxStart = idx;
|
||||
|
||||
int face;
|
||||
LSL_Vector v;
|
||||
@@ -7647,7 +7643,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
}
|
||||
catch (InvalidCastException e)
|
||||
{
|
||||
ShoutError(e.Message);
|
||||
ShoutError(string.Format(
|
||||
"{0} error running rule #{1}: arg #{2} ",
|
||||
originFunc, rulesParsed, idx - idxStart) + e.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -7918,7 +7916,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
public LSL_List llGetPrimitiveParams(LSL_List rules)
|
||||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
return GetLinkPrimitiveParams(m_host, rules);
|
||||
|
||||
LSL_List result = new LSL_List();
|
||||
|
||||
LSL_List remaining = GetPrimParams(m_host, rules, ref result);
|
||||
|
||||
while (remaining != null && remaining.Length > 2)
|
||||
{
|
||||
int linknumber = remaining.GetLSLIntegerItem(0);
|
||||
rules = remaining.GetSublist(1, -1);
|
||||
List<SceneObjectPart> parts = GetLinkParts(linknumber);
|
||||
|
||||
foreach (SceneObjectPart part in parts)
|
||||
remaining = GetPrimParams(part, rules, ref result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
|
||||
@@ -7928,19 +7941,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
List<SceneObjectPart> parts = GetLinkParts(linknumber);
|
||||
|
||||
LSL_List res = new LSL_List();
|
||||
LSL_List remaining = null;
|
||||
|
||||
foreach (var part in parts)
|
||||
foreach (SceneObjectPart part in parts)
|
||||
{
|
||||
LSL_List partRes = GetLinkPrimitiveParams(part, rules);
|
||||
res += partRes;
|
||||
remaining = GetPrimParams(part, rules, ref res);
|
||||
}
|
||||
|
||||
while (remaining != null && remaining.Length > 2)
|
||||
{
|
||||
linknumber = remaining.GetLSLIntegerItem(0);
|
||||
rules = remaining.GetSublist(1, -1);
|
||||
parts = GetLinkParts(linknumber);
|
||||
|
||||
foreach (SceneObjectPart part in parts)
|
||||
remaining = GetPrimParams(part, rules, ref res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules)
|
||||
public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res)
|
||||
{
|
||||
LSL_List res = new LSL_List();
|
||||
int idx=0;
|
||||
while (idx < rules.Length)
|
||||
{
|
||||
@@ -8085,7 +8107,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
case (int)ScriptBaseClass.PRIM_TEXTURE:
|
||||
if (remain < 1)
|
||||
return res;
|
||||
return null;
|
||||
|
||||
int face = (int)rules.GetLSLIntegerItem(idx++);
|
||||
Primitive.TextureEntry tex = part.Shape.Textures;
|
||||
@@ -8125,7 +8147,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
case (int)ScriptBaseClass.PRIM_COLOR:
|
||||
if (remain < 1)
|
||||
return res;
|
||||
return null;
|
||||
|
||||
face=(int)rules.GetLSLIntegerItem(idx++);
|
||||
|
||||
@@ -8154,7 +8176,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
|
||||
if (remain < 1)
|
||||
return res;
|
||||
return null;
|
||||
|
||||
face=(int)rules.GetLSLIntegerItem(idx++);
|
||||
|
||||
@@ -8185,7 +8207,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
|
||||
if (remain < 1)
|
||||
return res;
|
||||
return null;
|
||||
|
||||
face=(int)rules.GetLSLIntegerItem(idx++);
|
||||
|
||||
@@ -8227,7 +8249,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
case (int)ScriptBaseClass.PRIM_TEXGEN:
|
||||
if (remain < 1)
|
||||
return res;
|
||||
return null;
|
||||
|
||||
face=(int)rules.GetLSLIntegerItem(idx++);
|
||||
|
||||
@@ -8268,7 +8290,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
case (int)ScriptBaseClass.PRIM_GLOW:
|
||||
if (remain < 1)
|
||||
return res;
|
||||
return null;
|
||||
|
||||
face=(int)rules.GetLSLIntegerItem(idx++);
|
||||
|
||||
@@ -8320,9 +8342,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
0
|
||||
));
|
||||
break;
|
||||
case (int)ScriptBaseClass.PRIM_LINK_TARGET:
|
||||
if(remain < 3)
|
||||
return null;
|
||||
|
||||
return rules.GetSublist(idx, -1);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
|
||||
@@ -10091,31 +10119,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
public LSL_Float llListStatistics(int operation, LSL_List src)
|
||||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
LSL_List nums = LSL_List.ToDoubleList(src);
|
||||
switch (operation)
|
||||
{
|
||||
case ScriptBaseClass.LIST_STAT_RANGE:
|
||||
return nums.Range();
|
||||
return src.Range();
|
||||
case ScriptBaseClass.LIST_STAT_MIN:
|
||||
return nums.Min();
|
||||
return src.Min();
|
||||
case ScriptBaseClass.LIST_STAT_MAX:
|
||||
return nums.Max();
|
||||
return src.Max();
|
||||
case ScriptBaseClass.LIST_STAT_MEAN:
|
||||
return nums.Mean();
|
||||
return src.Mean();
|
||||
case ScriptBaseClass.LIST_STAT_MEDIAN:
|
||||
return nums.Median();
|
||||
return LSL_List.ToDoubleList(src).Median();
|
||||
case ScriptBaseClass.LIST_STAT_NUM_COUNT:
|
||||
return nums.NumericLength();
|
||||
return src.NumericLength();
|
||||
case ScriptBaseClass.LIST_STAT_STD_DEV:
|
||||
return nums.StdDev();
|
||||
return src.StdDev();
|
||||
case ScriptBaseClass.LIST_STAT_SUM:
|
||||
return nums.Sum();
|
||||
return src.Sum();
|
||||
case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
|
||||
return nums.SumSqrs();
|
||||
return src.SumSqrs();
|
||||
case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
|
||||
return nums.GeometricMean();
|
||||
return src.GeometricMean();
|
||||
case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
|
||||
return nums.HarmonicMean();
|
||||
return src.HarmonicMean();
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
@@ -10739,7 +10766,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
return tid.ToString();
|
||||
}
|
||||
|
||||
public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
|
||||
public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc)
|
||||
{
|
||||
SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
|
||||
if (obj == null)
|
||||
@@ -10748,28 +10775,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
if (obj.OwnerID != m_host.OwnerID)
|
||||
return;
|
||||
|
||||
LSL_List remaining = SetPrimParams(obj, rules);
|
||||
uint rulesParsed = 0;
|
||||
LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed);
|
||||
|
||||
while ((object)remaining != null && remaining.Length > 2)
|
||||
{
|
||||
LSL_Integer newLink = remaining.GetLSLIntegerItem(0);
|
||||
LSL_List newrules = remaining.GetSublist(1, -1);
|
||||
foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){
|
||||
remaining = SetPrimParams(part, newrules);
|
||||
remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
|
||||
public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
|
||||
{
|
||||
SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
|
||||
if (obj == null)
|
||||
return new LSL_List();
|
||||
|
||||
if (obj.OwnerID != m_host.OwnerID)
|
||||
return new LSL_List();
|
||||
LSL_List result = new LSL_List();
|
||||
|
||||
return GetLinkPrimitiveParams(obj, rules);
|
||||
if (obj != null && obj.OwnerID != m_host.OwnerID)
|
||||
{
|
||||
LSL_List remaining = GetPrimParams(obj, rules, ref result);
|
||||
|
||||
while (remaining != null && remaining.Length > 2)
|
||||
{
|
||||
int linknumber = remaining.GetLSLIntegerItem(0);
|
||||
rules = remaining.GetSublist(1, -1);
|
||||
List<SceneObjectPart> parts = GetLinkParts(linknumber);
|
||||
|
||||
foreach (SceneObjectPart part in parts)
|
||||
remaining = GetPrimParams(part, rules, ref result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void print(string str)
|
||||
|
||||
@@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
// ---------- Integer ----------
|
||||
else if (lslparm is LSL_Integer)
|
||||
{
|
||||
if (type == typeof(int))
|
||||
if (type == typeof(int) || type == typeof(float))
|
||||
return (int)(LSL_Integer)lslparm;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,12 +140,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
internal float m_ScriptDistanceFactor = 1.0f;
|
||||
internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
|
||||
|
||||
protected IUrlModule m_UrlModule = null;
|
||||
|
||||
public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
|
||||
{
|
||||
m_ScriptEngine = ScriptEngine;
|
||||
m_host = host;
|
||||
m_item = item;
|
||||
|
||||
m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
|
||||
|
||||
if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
|
||||
m_OSFunctionsEnabled = true;
|
||||
|
||||
@@ -1669,6 +1673,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
return;
|
||||
}
|
||||
|
||||
MessageObject(objUUID, message);
|
||||
}
|
||||
|
||||
private void MessageObject(UUID objUUID, string message)
|
||||
{
|
||||
object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) };
|
||||
|
||||
SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID);
|
||||
@@ -2246,11 +2255,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams");
|
||||
m_host.AddScriptLPS(1);
|
||||
InitLSL();
|
||||
// One needs to cast m_LSL_Api because we're using functions not
|
||||
// on the ILSL_Api interface.
|
||||
LSL_Api LSL_Api = (LSL_Api)m_LSL_Api;
|
||||
LSL_List retVal = new LSL_List();
|
||||
List<SceneObjectPart> parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber);
|
||||
LSL_List remaining = null;
|
||||
List<SceneObjectPart> parts = LSL_Api.GetLinkParts(linknumber);
|
||||
foreach (SceneObjectPart part in parts)
|
||||
{
|
||||
retVal += ((LSL_Api)m_LSL_Api).GetLinkPrimitiveParams(part, rules);
|
||||
remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
|
||||
}
|
||||
|
||||
while (remaining != null && remaining.Length > 2)
|
||||
{
|
||||
linknumber = remaining.GetLSLIntegerItem(0);
|
||||
rules = remaining.GetSublist(1, -1);
|
||||
parts = LSL_Api.GetLinkParts(linknumber);
|
||||
|
||||
foreach (SceneObjectPart part in parts)
|
||||
remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
@@ -2895,6 +2918,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public LSL_Float osGetHealth(string avatar)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.None, "osGetHealth");
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
LSL_Float health = new LSL_Float(-1);
|
||||
ScenePresence presence = World.GetScenePresence(new UUID(avatar));
|
||||
if (presence != null) health = presence.Health;
|
||||
return health;
|
||||
}
|
||||
|
||||
public void osCauseDamage(string avatar, double damage)
|
||||
{
|
||||
@@ -2954,7 +2988,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
m_host.AddScriptLPS(1);
|
||||
InitLSL();
|
||||
|
||||
return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules);
|
||||
return m_LSL_Api.GetPrimitiveParamsEx(prim, rules);
|
||||
}
|
||||
|
||||
public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules)
|
||||
@@ -2963,7 +2997,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
m_host.AddScriptLPS(1);
|
||||
InitLSL();
|
||||
|
||||
m_LSL_Api.SetPrimitiveParamsEx(prim, rules);
|
||||
m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -3195,6 +3229,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
}
|
||||
}
|
||||
|
||||
#region Attachment commands
|
||||
|
||||
public void osForceAttachToAvatar(int attachmentPoint)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar");
|
||||
@@ -3284,6 +3320,175 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
((LSL_Api)m_LSL_Api).DetachFromAvatar();
|
||||
}
|
||||
|
||||
public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments");
|
||||
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
UUID targetUUID;
|
||||
ScenePresence target;
|
||||
LSL_List resp = new LSL_List();
|
||||
|
||||
if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
|
||||
{
|
||||
foreach (object point in attachmentPoints.Data)
|
||||
{
|
||||
LSL_Integer ipoint = new LSL_Integer(
|
||||
(point is LSL_Integer || point is int || point is uint) ?
|
||||
(int)point :
|
||||
0
|
||||
);
|
||||
resp.Add(ipoint);
|
||||
if (ipoint == 0)
|
||||
{
|
||||
// indicates zero attachments
|
||||
resp.Add(new LSL_Integer(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
// gets the number of attachments on the attachment point
|
||||
resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments");
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
UUID targetUUID;
|
||||
ScenePresence target;
|
||||
|
||||
if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
|
||||
{
|
||||
List<int> aps = new List<int>();
|
||||
foreach (object point in attachmentPoints.Data)
|
||||
{
|
||||
int ipoint;
|
||||
if (int.TryParse(point.ToString(), out ipoint))
|
||||
{
|
||||
aps.Add(ipoint);
|
||||
}
|
||||
}
|
||||
|
||||
List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
|
||||
|
||||
bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL);
|
||||
bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0;
|
||||
|
||||
if (msgAll && invertPoints)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (msgAll || invertPoints)
|
||||
{
|
||||
attachments = target.GetAttachments();
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (int point in aps)
|
||||
{
|
||||
if (point > 0)
|
||||
{
|
||||
attachments.AddRange(target.GetAttachments((uint)point));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we have no attachments at this point, exit now
|
||||
if (attachments.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<SceneObjectGroup> ignoreThese = new List<SceneObjectGroup>();
|
||||
|
||||
if (invertPoints)
|
||||
{
|
||||
foreach (SceneObjectGroup attachment in attachments)
|
||||
{
|
||||
if (aps.Contains((int)attachment.AttachmentPoint))
|
||||
{
|
||||
ignoreThese.Add(attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectGroup attachment in ignoreThese)
|
||||
{
|
||||
attachments.Remove(attachment);
|
||||
}
|
||||
ignoreThese.Clear();
|
||||
|
||||
// if inverting removed all attachments to check, exit now
|
||||
if (attachments.Count < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0)
|
||||
{
|
||||
foreach (SceneObjectGroup attachment in attachments)
|
||||
{
|
||||
if (attachment.RootPart.CreatorID != m_host.CreatorID)
|
||||
{
|
||||
ignoreThese.Add(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectGroup attachment in ignoreThese)
|
||||
{
|
||||
attachments.Remove(attachment);
|
||||
}
|
||||
ignoreThese.Clear();
|
||||
|
||||
// if filtering by same object creator removed all
|
||||
// attachments to check, exit now
|
||||
if (attachments.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0)
|
||||
{
|
||||
foreach (SceneObjectGroup attachment in attachments)
|
||||
{
|
||||
if (attachment.RootPart.CreatorID != m_item.CreatorID)
|
||||
{
|
||||
ignoreThese.Add(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectGroup attachment in ignoreThese)
|
||||
{
|
||||
attachments.Remove(attachment);
|
||||
}
|
||||
ignoreThese.Clear();
|
||||
|
||||
// if filtering by object creator must match originating
|
||||
// script creator removed all attachments to check,
|
||||
// exit now
|
||||
if (attachments.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectGroup attachment in attachments)
|
||||
{
|
||||
MessageObject(attachment.RootPart.UUID, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Checks if thing is a UUID.
|
||||
/// </summary>
|
||||
@@ -3333,5 +3538,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
return new LSL_Key(m_host.ParentGroup.FromPartID.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the response type for an HTTP request/response
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public void osSetContentType(LSL_Key id, string type)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.High,"osSetResponseType");
|
||||
if (m_UrlModule != null)
|
||||
m_UrlModule.HttpContentType(new UUID(id),type);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -424,7 +424,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
LSL_String llXorBase64StringsCorrect(string str1, string str2);
|
||||
void print(string str);
|
||||
|
||||
void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
|
||||
LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
|
||||
void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc);
|
||||
LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,16 +40,75 @@ using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
|
||||
|
||||
namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// To permit region owners to enable the extended scripting functionality
|
||||
/// of OSSL, without allowing malicious scripts to access potentially
|
||||
/// troublesome functions, each OSSL function is assigned a threat level,
|
||||
/// and access to the functions is granted or denied based on a default
|
||||
/// threshold set in OpenSim.ini (which can be overridden for individual
|
||||
/// functions on a case-by-case basis)
|
||||
/// </summary>
|
||||
public enum ThreatLevel
|
||||
{
|
||||
// Not documented, presumably means permanently disabled ?
|
||||
NoAccess = -1,
|
||||
|
||||
/// <summary>
|
||||
/// Function is no threat at all. It doesn't constitute a threat to
|
||||
/// either users or the system and has no known side effects.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Abuse of this command can cause a nuisance to the region operator,
|
||||
/// such as log message spew.
|
||||
/// </summary>
|
||||
Nuisance = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Extreme levels of abuse of this function can cause impaired
|
||||
/// functioning of the region, or very gullible users can be tricked
|
||||
/// into experiencing harmless effects.
|
||||
/// </summary>
|
||||
VeryLow = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Intentional abuse can cause crashes or malfunction under certain
|
||||
/// circumstances, which can be easily rectified; or certain users can
|
||||
/// be tricked into certain situations in an avoidable manner.
|
||||
/// </summary>
|
||||
Low = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Intentional abuse can cause denial of service and crashes with
|
||||
/// potential of data or state loss; or trusting users can be tricked
|
||||
/// into embarrassing or uncomfortable situations.
|
||||
/// </summary>
|
||||
Moderate = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Casual abuse can cause impaired functionality or temporary denial
|
||||
/// of service conditions. Intentional abuse can easily cause crashes
|
||||
/// with potential data loss, or can be used to trick experienced and
|
||||
/// cautious users into unwanted situations, or changes global data
|
||||
/// permanently and without undo ability.
|
||||
/// </summary>
|
||||
High = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Even normal use may, depending on the number of instances, or
|
||||
/// frequency of use, result in severe service impairment or crash
|
||||
/// with loss of data, or can be used to cause unwanted or harmful
|
||||
/// effects on users without giving the user a means to avoid it.
|
||||
/// </summary>
|
||||
VeryHigh = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Even casual use is a danger to region stability, or function allows
|
||||
/// console or OS command execution, or function allows taking money
|
||||
/// without consent, or allows deletion or modification of user data,
|
||||
/// or allows the compromise of sensitive data by design.
|
||||
/// </summary>
|
||||
Severe = 7
|
||||
};
|
||||
|
||||
@@ -98,7 +157,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
void osAvatarPlayAnimation(string avatar, string animation);
|
||||
void osAvatarStopAnimation(string avatar, string animation);
|
||||
|
||||
// Attachment commands
|
||||
#region Attachment commands
|
||||
|
||||
/// <summary>
|
||||
/// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
|
||||
@@ -133,6 +192,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
/// <remarks>Nothing happens if the object is not attached.</remarks>
|
||||
void osForceDetachFromAvatar();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a strided list of the specified attachment points and the number of attachments on those points.
|
||||
/// </summary>
|
||||
/// <param name="avatar">avatar UUID</param>
|
||||
/// <param name="attachmentPoints">list of ATTACH_* constants</param>
|
||||
/// <returns></returns>
|
||||
LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a specified message to the specified avatar's attachments on
|
||||
/// the specified attachment points.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Behaves as osMessageObject(), without the sending script needing to know the attachment keys in advance.
|
||||
/// </remarks>
|
||||
/// <param name="avatar">avatar UUID</param>
|
||||
/// <param name="message">message string</param>
|
||||
/// <param name="attachmentPoints">list of ATTACH_* constants, or -1 for all attachments. If -1 is specified and OS_ATTACH_MSG_INVERT_POINTS is present in flags, no action is taken.</param>
|
||||
/// <param name="flags">flags further constraining the attachments to deliver the message to.</param>
|
||||
void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags);
|
||||
|
||||
#endregion
|
||||
|
||||
//texture draw functions
|
||||
string osMovePen(string drawList, int x, int y);
|
||||
string osDrawLine(string drawList, int startX, int startY, int endX, int endY);
|
||||
@@ -258,6 +340,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
int osGetSimulatorMemory();
|
||||
void osKickAvatar(string FirstName,string SurName,string alert);
|
||||
void osSetSpeed(string UUID, LSL_Float SpeedModifier);
|
||||
LSL_Float osGetHealth(string avatar);
|
||||
void osCauseHealing(string avatar, double healing);
|
||||
void osCauseDamage(string avatar, double damage);
|
||||
LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules);
|
||||
@@ -305,5 +388,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
/// </summary>
|
||||
/// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns>
|
||||
LSL_Key osGetRezzingObject();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the response type for an HTTP request/response
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
void osSetContentType(LSL_Key id, string type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +237,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
public const int ATTACH_HUD_BOTTOM = 37;
|
||||
public const int ATTACH_HUD_BOTTOM_RIGHT = 38;
|
||||
|
||||
#region osMessageAttachments constants
|
||||
|
||||
/// <summary>
|
||||
/// Instructs osMessageAttachements to send the message to attachments
|
||||
/// on every point.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// One might expect this to be named OS_ATTACH_ALL, but then one might
|
||||
/// also expect functions designed to attach or detach or get
|
||||
/// attachments to work with it too. Attaching a no-copy item to
|
||||
/// many attachments could be dangerous.
|
||||
/// when combined with OS_ATTACH_MSG_INVERT_POINTS, will prevent the
|
||||
/// message from being sent.
|
||||
/// if combined with OS_ATTACH_MSG_OBJECT_CREATOR or
|
||||
/// OS_ATTACH_MSG_SCRIPT_CREATOR, could result in no message being
|
||||
/// sent- this is expected behaviour.
|
||||
/// </remarks>
|
||||
public const int OS_ATTACH_MSG_ALL = -65535;
|
||||
|
||||
/// <summary>
|
||||
/// Instructs osMessageAttachements to invert how the attachment points
|
||||
/// list should be treated (e.g. go from inclusive operation to
|
||||
/// exclusive operation).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This might be used if you want to deliver a message to one set of
|
||||
/// attachments and a different message to everything else. With
|
||||
/// this flag, you only need to build one explicit list for both calls.
|
||||
/// </remarks>
|
||||
public const int OS_ATTACH_MSG_INVERT_POINTS = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Instructs osMessageAttachments to only send the message to
|
||||
/// attachments with a CreatorID that matches the host object CreatorID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This would be used if distributed in an object vendor/updater server.
|
||||
/// </remarks>
|
||||
public const int OS_ATTACH_MSG_OBJECT_CREATOR = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Instructs osMessageAttachments to only send the message to
|
||||
/// attachments with a CreatorID that matches the sending script CreatorID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This might be used if the script is distributed independently of a
|
||||
/// containing object.
|
||||
/// </remarks>
|
||||
public const int OS_ATTACH_MSG_SCRIPT_CREATOR = 4;
|
||||
|
||||
#endregion
|
||||
|
||||
public const int LAND_LEVEL = 0;
|
||||
public const int LAND_RAISE = 1;
|
||||
public const int LAND_LOWER = 2;
|
||||
|
||||
@@ -289,7 +289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
m_OSSL_Functions.osAvatarStopAnimation(avatar, animation);
|
||||
}
|
||||
|
||||
// Avatar functions
|
||||
#region Attachment commands
|
||||
|
||||
public void osForceAttachToAvatar(int attachmentPoint)
|
||||
{
|
||||
@@ -311,6 +311,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
m_OSSL_Functions.osForceDetachFromAvatar();
|
||||
}
|
||||
|
||||
public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
|
||||
{
|
||||
return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints);
|
||||
}
|
||||
|
||||
public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags)
|
||||
{
|
||||
m_OSSL_Functions.osMessageAttachments(avatar, message, attachmentPoints, flags);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Texture Draw functions
|
||||
|
||||
public string osMovePen(string drawList, int x, int y)
|
||||
@@ -865,7 +877,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
{
|
||||
m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier);
|
||||
}
|
||||
|
||||
|
||||
public LSL_Float osGetHealth(string avatar)
|
||||
{
|
||||
return m_OSSL_Functions.osGetHealth(avatar);
|
||||
}
|
||||
|
||||
public void osCauseDamage(string avatar, double damage)
|
||||
{
|
||||
m_OSSL_Functions.osCauseDamage(avatar, damage);
|
||||
@@ -950,5 +967,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
{
|
||||
return m_OSSL_Functions.osGetRezzingObject();
|
||||
}
|
||||
|
||||
public void osSetContentType(LSL_Key id, string type)
|
||||
{
|
||||
m_OSSL_Functions.osSetContentType(id,type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1137,7 +1137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
{
|
||||
list ret = new list();
|
||||
double entry;
|
||||
for (int i = 0; i < src.Data.Length - 1; i++)
|
||||
for (int i = 0; i < src.Data.Length; i++)
|
||||
{
|
||||
if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
|
||||
{
|
||||
|
||||
@@ -589,7 +589,19 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
if (m_Assemblies.ContainsKey(instance.AssetID))
|
||||
{
|
||||
string assembly = m_Assemblies[instance.AssetID];
|
||||
instance.SaveState(assembly);
|
||||
|
||||
try
|
||||
{
|
||||
instance.SaveState(assembly);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(
|
||||
string.Format(
|
||||
"[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
|
||||
instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
|
||||
, e);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the event queue and abort the instance thread
|
||||
@@ -707,7 +719,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
assembly = m_Assemblies[i.AssetID];
|
||||
}
|
||||
|
||||
i.SaveState(assembly);
|
||||
try
|
||||
{
|
||||
i.SaveState(assembly);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(
|
||||
string.Format(
|
||||
"[XEngine]: Failed to save state of script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
|
||||
i.PrimName, i.ScriptName, i.ItemID, i.ObjectID, World.Name)
|
||||
, e);
|
||||
}
|
||||
}
|
||||
|
||||
instances.Clear();
|
||||
@@ -900,6 +923,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
// This delay exists to stop mono problems where script compilation and startup would stop the sim
|
||||
// working properly for the session.
|
||||
System.Threading.Thread.Sleep(m_StartDelay);
|
||||
|
||||
m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name);
|
||||
}
|
||||
|
||||
object[] o;
|
||||
@@ -915,13 +940,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
if (m_InitialStartup)
|
||||
if (scriptsStarted % 50 == 0)
|
||||
m_log.InfoFormat(
|
||||
"[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.RegionInfo.RegionName);
|
||||
"[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_InitialStartup)
|
||||
m_log.InfoFormat(
|
||||
"[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.RegionInfo.RegionName);
|
||||
"[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name);
|
||||
|
||||
// NOTE: Despite having a lockless queue, this lock is required
|
||||
// to make sure there is never no compile thread while there
|
||||
|
||||
@@ -137,9 +137,14 @@ namespace OpenSim.Services.GridService
|
||||
if (regionInfos.RegionID == UUID.Zero)
|
||||
return "Invalid RegionID - cannot be zero UUID";
|
||||
|
||||
// This needs better sanity testing. What if regionInfo is registering in
|
||||
// overlapping coords?
|
||||
RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
|
||||
if ((region != null) && (region.RegionID != regionInfos.RegionID))
|
||||
{
|
||||
m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.",
|
||||
regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
|
||||
return "Region overlaps another region";
|
||||
}
|
||||
|
||||
if (region != null)
|
||||
{
|
||||
// There is a preexisting record
|
||||
@@ -176,32 +181,7 @@ namespace OpenSim.Services.GridService
|
||||
}
|
||||
}
|
||||
|
||||
if ((region != null) && (region.RegionID != regionInfos.RegionID))
|
||||
{
|
||||
m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.",
|
||||
regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
|
||||
return "Region overlaps another region";
|
||||
}
|
||||
|
||||
if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
|
||||
((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY)))
|
||||
{
|
||||
if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.NoMove) != 0)
|
||||
return "Can't move this region";
|
||||
|
||||
// Region reregistering in other coordinates. Delete the old entry
|
||||
m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.",
|
||||
regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY);
|
||||
|
||||
try
|
||||
{
|
||||
m_Database.Delete(regionInfos.RegionID);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
|
||||
}
|
||||
}
|
||||
// If we get here, the destination is clear. Now for the real check.
|
||||
|
||||
if (!m_AllowDuplicateNames)
|
||||
{
|
||||
@@ -220,6 +200,31 @@ namespace OpenSim.Services.GridService
|
||||
}
|
||||
}
|
||||
|
||||
// If there is an old record for us, delete it if it is elsewhere.
|
||||
region = m_Database.Get(regionInfos.RegionID, scopeID);
|
||||
if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
|
||||
((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY)))
|
||||
{
|
||||
if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.NoMove) != 0)
|
||||
return "Can't move this region";
|
||||
|
||||
if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.LockedOut) != 0)
|
||||
return "Region locked out";
|
||||
|
||||
// Region reregistering in other coordinates. Delete the old entry
|
||||
m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.",
|
||||
regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY);
|
||||
|
||||
try
|
||||
{
|
||||
m_Database.Delete(regionInfos.RegionID);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Everything is ok, let's register
|
||||
RegionData rdata = RegionInfo2RegionData(regionInfos);
|
||||
rdata.ScopeID = scopeID;
|
||||
@@ -227,8 +232,6 @@ namespace OpenSim.Services.GridService
|
||||
if (region != null)
|
||||
{
|
||||
int oldFlags = Convert.ToInt32(region.Data["flags"]);
|
||||
if ((oldFlags & (int)OpenSim.Data.RegionFlags.LockedOut) != 0)
|
||||
return "Region locked out";
|
||||
|
||||
oldFlags &= ~(int)OpenSim.Data.RegionFlags.Reservation;
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ namespace OpenSim.Services.InventoryService
|
||||
|
||||
m_Database = LoadPlugin<IXInventoryData>(dllName,
|
||||
new Object[] {connString, String.Empty});
|
||||
|
||||
if (m_Database == null)
|
||||
throw new Exception("Could not find a storage interface in the given module");
|
||||
}
|
||||
@@ -229,10 +230,28 @@ namespace OpenSim.Services.InventoryService
|
||||
public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
|
||||
{
|
||||
// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
|
||||
|
||||
InventoryFolderBase rootFolder = GetRootFolder(principalID);
|
||||
|
||||
if (rootFolder == null)
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[XINVENTORY]: Found no root folder for {0} in GetFolderForType() when looking for {1}",
|
||||
principalID, type);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return GetSystemFolderForType(rootFolder, type);
|
||||
}
|
||||
|
||||
private InventoryFolderBase GetSystemFolderForType(InventoryFolderBase rootFolder, AssetType type)
|
||||
{
|
||||
// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
|
||||
|
||||
XInventoryFolder[] folders = m_Database.GetFolders(
|
||||
new string[] { "agentID", "type"},
|
||||
new string[] { principalID.ToString(), ((int)type).ToString() });
|
||||
new string[] { "agentID", "parentFolderID", "type"},
|
||||
new string[] { rootFolder.Owner.ToString(), rootFolder.ID.ToString(), ((int)type).ToString() });
|
||||
|
||||
if (folders.Length == 0)
|
||||
{
|
||||
@@ -308,22 +327,38 @@ namespace OpenSim.Services.InventoryService
|
||||
if (check != null)
|
||||
return false;
|
||||
|
||||
if (folder.Type == (short)AssetType.Folder
|
||||
|| folder.Type == (short)AssetType.Unknown
|
||||
|| folder.Type == (short)AssetType.OutfitFolder
|
||||
|| GetFolderForType(folder.Owner, (AssetType)(folder.Type)) == null)
|
||||
if (folder.Type != (short)AssetType.Folder && folder.Type != (short)AssetType.Unknown)
|
||||
{
|
||||
XInventoryFolder xFolder = ConvertFromOpenSim(folder);
|
||||
return m_Database.StoreFolder(xFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[XINVENTORY]: Folder of type {0} already exists when tried to add {1} to {2} for {3}",
|
||||
folder.Type, folder.Name, folder.ParentID, folder.Owner);
|
||||
InventoryFolderBase rootFolder = GetRootFolder(folder.Owner);
|
||||
|
||||
if (rootFolder == null)
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[XINVENTORY]: Found no root folder for {0} in AddFolder() when looking for {1}",
|
||||
folder.Owner, folder.Type);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check we're not trying to add this as a system folder.
|
||||
if (folder.ParentID == rootFolder.ID)
|
||||
{
|
||||
InventoryFolderBase existingSystemFolder
|
||||
= GetSystemFolderForType(rootFolder, (AssetType)folder.Type);
|
||||
|
||||
if (existingSystemFolder != null)
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[XINVENTORY]: System folder of type {0} already exists when tried to add {1} to {2} for {3}",
|
||||
folder.Type, folder.Name, folder.ParentID, folder.Owner);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
XInventoryFolder xFolder = ConvertFromOpenSim(folder);
|
||||
return m_Database.StoreFolder(xFolder);
|
||||
}
|
||||
|
||||
public virtual bool UpdateFolder(InventoryFolderBase folder)
|
||||
|
||||
@@ -245,7 +245,7 @@ namespace OpenSim.Tests.Common
|
||||
config.AddConfig("Modules");
|
||||
config.AddConfig("InventoryService");
|
||||
config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector");
|
||||
config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:InventoryService");
|
||||
config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService");
|
||||
config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
|
||||
|
||||
LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector();
|
||||
|
||||
@@ -199,7 +199,9 @@ namespace OpenSim.Tests.Common
|
||||
string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
|
||||
|
||||
InventoryFolderBase newFolder
|
||||
= new InventoryFolderBase(UUID.Random(), components[0], parentFolder.Owner, parentFolder.ID);
|
||||
= new InventoryFolderBase(
|
||||
UUID.Random(), components[0], parentFolder.Owner, (short)AssetType.Unknown, parentFolder.ID, 0);
|
||||
|
||||
inventoryService.AddFolder(newFolder);
|
||||
|
||||
if (components.Length > 1)
|
||||
|
||||
131
OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
Normal file
131
OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Data;
|
||||
|
||||
namespace OpenSim.Tests.Common.Mock
|
||||
{
|
||||
public class TestXInventoryDataPlugin : IXInventoryData
|
||||
{
|
||||
private Dictionary<UUID, XInventoryFolder> m_allFolders = new Dictionary<UUID, XInventoryFolder>();
|
||||
private Dictionary<UUID, XInventoryItem> m_allItems = new Dictionary<UUID, XInventoryItem>();
|
||||
|
||||
public TestXInventoryDataPlugin(string conn, string realm) {}
|
||||
|
||||
public XInventoryItem[] GetItems(string[] fields, string[] vals)
|
||||
{
|
||||
List<XInventoryItem> origItems = Get<XInventoryItem>(fields, vals, m_allItems.Values.ToList());
|
||||
|
||||
return origItems.Select(i => i.Clone()).ToArray();
|
||||
}
|
||||
|
||||
public XInventoryFolder[] GetFolders(string[] fields, string[] vals)
|
||||
{
|
||||
List<XInventoryFolder> origFolders
|
||||
= Get<XInventoryFolder>(fields, vals, m_allFolders.Values.ToList());
|
||||
|
||||
return origFolders.Select(f => f.Clone()).ToArray();
|
||||
}
|
||||
|
||||
private List<T> Get<T>(string[] fields, string[] vals, List<T> inputEntities)
|
||||
{
|
||||
List<T> entities = inputEntities;
|
||||
|
||||
for (int i = 0; i < fields.Length; i++)
|
||||
{
|
||||
entities
|
||||
= entities.Where(
|
||||
e =>
|
||||
{
|
||||
FieldInfo fi = typeof(T).GetField(fields[i]);
|
||||
if (fi == null)
|
||||
throw new NotImplementedException(string.Format("No field {0} for val {1}", fields[i], vals[i]));
|
||||
|
||||
return fi.GetValue(e).ToString() == vals[i];
|
||||
}
|
||||
).ToList();
|
||||
}
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
public bool StoreFolder(XInventoryFolder folder)
|
||||
{
|
||||
m_allFolders[folder.folderID] = folder.Clone();
|
||||
|
||||
// Console.WriteLine("Added folder {0} {1}", folder.folderName, folder.folderID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool StoreItem(XInventoryItem item)
|
||||
{
|
||||
m_allItems[item.inventoryID] = item.Clone();
|
||||
|
||||
// Console.WriteLine("Added item {0} {1}, creator {2}, owner {3}", item.inventoryName, item.inventoryID, item.creatorID, item.avatarID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DeleteFolders(string field, string val)
|
||||
{
|
||||
return DeleteFolders(new string[] { field }, new string[] { val });
|
||||
}
|
||||
|
||||
public bool DeleteFolders(string[] fields, string[] vals)
|
||||
{
|
||||
XInventoryFolder[] foldersToDelete = GetFolders(fields, vals);
|
||||
Array.ForEach(foldersToDelete, f => m_allFolders.Remove(f.folderID));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DeleteItems(string field, string val)
|
||||
{
|
||||
return DeleteItems(new string[] { field }, new string[] { val });
|
||||
}
|
||||
|
||||
public bool DeleteItems(string[] fields, string[] vals)
|
||||
{
|
||||
XInventoryItem[] itemsToDelete = GetItems(fields, vals);
|
||||
Array.ForEach(itemsToDelete, i => m_allItems.Remove(i.inventoryID));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool MoveItem(string id, string newParent) { throw new NotImplementedException(); }
|
||||
public XInventoryItem[] GetActiveGestures(UUID principalID) { throw new NotImplementedException(); }
|
||||
public int GetAssetPermissions(UUID principalID, UUID assetID) { throw new NotImplementedException(); }
|
||||
}
|
||||
}
|
||||
@@ -95,6 +95,7 @@ namespace OpenSim.Tests.Common
|
||||
public static void EnableLogging()
|
||||
{
|
||||
log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream);
|
||||
EnableLoggingConfigStream.Position = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -47,10 +47,10 @@ using OpenSim.Services.AvatarService;
|
||||
using OpenSim.Tests.Common;
|
||||
using OpenSim.Tests.Common.Mock;
|
||||
|
||||
namespace OpenSim.Tests.Torture
|
||||
namespace OpenSim.Tests.Performance
|
||||
{
|
||||
/// <summary>
|
||||
/// NPC torture tests
|
||||
/// NPC performance tests
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
|
||||
@@ -58,7 +58,7 @@ namespace OpenSim.Tests.Torture
|
||||
/// earlier tests.
|
||||
/// </remarks>
|
||||
[TestFixture]
|
||||
public class NPCTortureTests
|
||||
public class NPCPerformanceTests
|
||||
{
|
||||
private TestScene scene;
|
||||
private AvatarFactoryModule afm;
|
||||
@@ -36,10 +36,10 @@ using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Tests.Common;
|
||||
using OpenSim.Tests.Common.Mock;
|
||||
|
||||
namespace OpenSim.Tests.Torture
|
||||
namespace OpenSim.Tests.Performance
|
||||
{
|
||||
/// <summary>
|
||||
/// Object torture tests
|
||||
/// Object performance tests
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
|
||||
@@ -47,7 +47,7 @@ namespace OpenSim.Tests.Torture
|
||||
/// earlier tests.
|
||||
/// </remarks>
|
||||
[TestFixture]
|
||||
public class ObjectTortureTests
|
||||
public class ObjectPerformanceTests
|
||||
{
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
@@ -42,10 +42,10 @@ using OpenSim.Region.ScriptEngine.XEngine;
|
||||
using OpenSim.Tests.Common;
|
||||
using OpenSim.Tests.Common.Mock;
|
||||
|
||||
namespace OpenSim.Tests.Torture
|
||||
namespace OpenSim.Tests.Performance
|
||||
{
|
||||
/// <summary>
|
||||
/// Script torture tests
|
||||
/// Script performance tests
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
|
||||
@@ -53,7 +53,7 @@ namespace OpenSim.Tests.Torture
|
||||
/// earlier tests.
|
||||
/// </remarks>
|
||||
[TestFixture]
|
||||
public class ScriptTortureTests
|
||||
public class ScriptPerformanceTests
|
||||
{
|
||||
private TestScene m_scene;
|
||||
private XEngine m_xEngine;
|
||||
132
OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs
Normal file
132
OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using log4net.Config;
|
||||
using NUnit.Framework;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Assets;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
|
||||
using OpenSim.Region.CoreModules.Scripting.VectorRender;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||
using OpenSim.Tests.Common;
|
||||
using OpenSim.Tests.Common.Mock;
|
||||
|
||||
namespace OpenSim.Tests.Stress
|
||||
{
|
||||
[TestFixture]
|
||||
public class VectorRenderModuleStressTests : OpenSimTestCase
|
||||
{
|
||||
public Scene Scene { get; private set; }
|
||||
public DynamicTextureModule Dtm { get; private set; }
|
||||
public VectorRenderModule Vrm { get; private set; }
|
||||
|
||||
private void SetupScene(bool reuseTextures)
|
||||
{
|
||||
Scene = new SceneHelpers().SetupScene();
|
||||
|
||||
Dtm = new DynamicTextureModule();
|
||||
Dtm.ReuseTextures = reuseTextures;
|
||||
|
||||
Vrm = new VectorRenderModule();
|
||||
|
||||
SceneHelpers.SetupSceneModules(Scene, Dtm, Vrm);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestConcurrentRepeatedDraw()
|
||||
{
|
||||
int threads = 4;
|
||||
TestHelpers.InMethod();
|
||||
|
||||
SetupScene(false);
|
||||
|
||||
List<Drawer> drawers = new List<Drawer>();
|
||||
|
||||
for (int i = 0; i < threads; i++)
|
||||
{
|
||||
Drawer d = new Drawer(this, i);
|
||||
drawers.Add(d);
|
||||
Console.WriteLine("Starting drawer {0}", i);
|
||||
Util.FireAndForget(o => d.Draw());
|
||||
}
|
||||
|
||||
Thread.Sleep(10 * 60 * 1000);
|
||||
|
||||
drawers.ForEach(d => d.Ready = false);
|
||||
drawers.ForEach(d => Console.WriteLine("Drawer {0} drew {1} textures", d.Number, d.Pass + 1));
|
||||
}
|
||||
|
||||
class Drawer
|
||||
{
|
||||
public int Number { get; private set; }
|
||||
public int Pass { get; private set; }
|
||||
public bool Ready { get; set; }
|
||||
|
||||
private VectorRenderModuleStressTests m_tests;
|
||||
|
||||
public Drawer(VectorRenderModuleStressTests tests, int number)
|
||||
{
|
||||
m_tests = tests;
|
||||
Number = number;
|
||||
Ready = true;
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_tests.Scene);
|
||||
|
||||
while (Ready)
|
||||
{
|
||||
UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
|
||||
|
||||
// Ensure unique text
|
||||
string text = string.Format("{0:D2}{1}", Number, Pass);
|
||||
|
||||
m_tests.Dtm.AddDynamicTextureData(
|
||||
m_tests.Scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_tests.Vrm.GetContentType(),
|
||||
string.Format("PenColour BLACK; MoveTo 40,220; FontSize 32; Text {0};", text),
|
||||
"",
|
||||
0);
|
||||
|
||||
Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
|
||||
Pass++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
Json.NET
|
||||
License: The MIT License
|
||||
Copyright (c) 2007 James Newton-King
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -693,6 +693,17 @@
|
||||
;LevelUpload = 0
|
||||
|
||||
|
||||
[Textures]
|
||||
; If true, textures generated dynamically (i.e. through osSetDynamicTextureData() and similar OSSL functions) are reused where possible
|
||||
; Chiefly, reuse occurs if a texture has already been generated with identical data and settings, and that texture contains no dynamic components
|
||||
; (e.g. images pulled from an external HTTP address).
|
||||
; Reusing previously generated textures results in a much faster update on the viewer but may cause issues if the viewer didn't receive all resolutions of the texture.
|
||||
; Currently, it will also increase asset cache use since temporary dynamic textures are no longer deleted.
|
||||
; Hence, currently considered experimental.
|
||||
; Default is false.
|
||||
ReuseDynamicTextures = false
|
||||
|
||||
|
||||
[ODEPhysicsSettings]
|
||||
; ##
|
||||
; ## Physics stats settings
|
||||
|
||||
@@ -7,6 +7,16 @@
|
||||
[AssetService]
|
||||
ConnectionString = "URI=file:Asset.db,version=3"
|
||||
|
||||
; The HGAssetService section controls the connection given to the AssetService in a Hypergrid configuration.
|
||||
; This has to be separate from [AssetService] because the Hypergrid facing connector uses [HGAssetService] for its config data instead.
|
||||
; However, the internal asset service will still use the [AssetService] section.
|
||||
; Therefore, you will almost certainly want the ConnectionString in [HGAssetService] to be the same as in [AssetService]
|
||||
; so that they both access the same database.
|
||||
; This issue does not apply to normal MySQL/MSSQL configurations, since by default they use the settings in [DatabaseService] and
|
||||
; do not have separate connection strings for different services.
|
||||
[HGAssetService]
|
||||
ConnectionString = "URI=file:Asset.db,version=3"
|
||||
|
||||
[InventoryService]
|
||||
;ConnectionString = "URI=file:inventory.db,version=3"
|
||||
; if you have a legacy inventory store use the connection string below
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
43
prebuild.xml
43
prebuild.xml
@@ -3250,7 +3250,48 @@
|
||||
</Files>
|
||||
</Project>
|
||||
|
||||
<Project frameworkVersion="v3_5" name="OpenSim.Tests.Torture" path="OpenSim/Tests/Torture" type="Library">
|
||||
<Project frameworkVersion="v3_5" name="OpenSim.Tests.Stress" path="OpenSim/Tests/Stress" type="Library">
|
||||
<Configuration name="Debug">
|
||||
<Options>
|
||||
<OutputPath>../../../bin/</OutputPath>
|
||||
</Options>
|
||||
</Configuration>
|
||||
<Configuration name="Release">
|
||||
<Options>
|
||||
<OutputPath>../../../bin/</OutputPath>
|
||||
</Options>
|
||||
</Configuration>
|
||||
|
||||
<ReferencePath>../../../bin/</ReferencePath>
|
||||
<Reference name="System"/>
|
||||
<Reference name="System.Core"/>
|
||||
<Reference name="System.Xml"/>
|
||||
<Reference name="System.Data"/>
|
||||
<Reference name="log4net" path="../../../bin/"/>
|
||||
<Reference name="Nini" path="../../../bin/"/>
|
||||
<Reference name="nunit.framework" path="../../../bin/"/>
|
||||
<Reference name="OpenMetaverse" path="../../../bin/"/>
|
||||
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
|
||||
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
|
||||
<Reference name="XMLRPC" path="../../../bin/"/>
|
||||
<Reference name="OpenSim.Framework"/>
|
||||
<Reference name="OpenSim.Framework.Communications"/>
|
||||
<Reference name="OpenSim.Framework.Console"/>
|
||||
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
|
||||
<Reference name="OpenSim.Region.CoreModules"/>
|
||||
<Reference name="OpenSim.Region.Framework"/>
|
||||
<Reference name="OpenSim.Region.OptionalModules"/>
|
||||
<Reference name="OpenSim.Region.ScriptEngine.Shared"/>
|
||||
<Reference name="OpenSim.Region.ScriptEngine.XEngine"/>
|
||||
<Reference name="OpenSim.Services.Interfaces"/>
|
||||
<Reference name="OpenSim.Services.AvatarService"/>
|
||||
<Reference name="OpenSim.Tests.Common"/>
|
||||
<Files>
|
||||
<Match pattern="*.cs" recurse="false"/>
|
||||
</Files>
|
||||
</Project>
|
||||
|
||||
<Project frameworkVersion="v3_5" name="OpenSim.Tests.Performance" path="OpenSim/Tests/Performance" type="Library">
|
||||
<Configuration name="Debug">
|
||||
<Options>
|
||||
<OutputPath>../../../bin/</OutputPath>
|
||||
|
||||
Reference in New Issue
Block a user