aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorCharles Krinke2007-12-10 21:38:01 +0000
committerCharles Krinke2007-12-10 21:38:01 +0000
commit22acc237558b88234dde3fed2bad3e434ec28a62 (patch)
treef22e718bb80119c2d169e4ae646c8dda141fc417 /OpenSim/Region
parent* Added comments to many methods in the listed files. (diff)
downloadopensim-SC-22acc237558b88234dde3fed2bad3e434ec28a62.zip
opensim-SC-22acc237558b88234dde3fed2bad3e434ec28a62.tar.gz
opensim-SC-22acc237558b88234dde3fed2bad3e434ec28a62.tar.bz2
opensim-SC-22acc237558b88234dde3fed2bad3e434ec28a62.tar.xz
Great Salutations to Alondria for providing implementations for:
llFrand, llSetColor, llGetColor, llSetTexture, llGetTexture, llSetAlpha, llGetAlpha, llRotateTexture, llScaleTexture, llOffsetTexture, llGetTextureOffset, llGetTextureScale, llGetTextureRot. With these changes the "kan-ed" script #2 should be working.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectPart.cs27
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs271
2 files changed, 271 insertions, 27 deletions
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
index 8eef40b..3a4129e 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
@@ -1211,6 +1211,33 @@ namespace OpenSim.Region.Environment.Scenes
1211 ScheduleFullUpdate(); 1211 ScheduleFullUpdate();
1212 } 1212 }
1213 1213
1214 // Added to handle bug in libsecondlife's TextureEntry.ToBytes()
1215 // not handling RGBA properly. Cycles through, and "fixes" the color
1216 // info
1217 public void UpdateTexture(LLObject.TextureEntry tex)
1218 {
1219 LLColor tmpcolor;
1220 for (uint i = 0; i < 32; i++)
1221 {
1222 if (tex.FaceTextures[i] != null)
1223 {
1224 tmpcolor = tex.GetFace((uint)i).RGBA;
1225 tmpcolor.A = tmpcolor.A * 255;
1226 tmpcolor.R = tmpcolor.R * 255;
1227 tmpcolor.G = tmpcolor.G * 255;
1228 tmpcolor.B = tmpcolor.B * 255;
1229 tex.FaceTextures[i].RGBA = tmpcolor;
1230 }
1231 }
1232 tmpcolor = tex.DefaultTexture.RGBA;
1233 tmpcolor.A = tmpcolor.A * 255;
1234 tmpcolor.R = tmpcolor.R * 255;
1235 tmpcolor.G = tmpcolor.G * 255;
1236 tmpcolor.B = tmpcolor.B * 255;
1237 tex.DefaultTexture.RGBA = tmpcolor;
1238 UpdateTextureEntry(tex.ToBytes());
1239 }
1240
1214 #endregion 1241 #endregion
1215 1242
1216 #region ParticleSystem 1243 #region ParticleSystem
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs
index e160fd3..0edff14 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs
@@ -143,7 +143,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
143 { 143 {
144 lock (Util.RandomClass) 144 lock (Util.RandomClass)
145 { 145 {
146 return Util.RandomClass.Next((int) mag); 146 return Util.RandomClass.NextDouble() * mag;
147 } 147 }
148 } 148 }
149 149
@@ -441,54 +441,248 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
441 441
442 public void llSetColor(LSL_Types.Vector3 color, int face) 442 public void llSetColor(LSL_Types.Vector3 color, int face)
443 { 443 {
444 LLObject.TextureEntry tex = new LLObject.TextureEntry(m_host.Shape.TextureEntry, 0, m_host.Shape.TextureEntry.Length);
445 LLColor texcolor;
446 if (face > -1)
447 {
448 texcolor = tex.CreateFace((uint)face).RGBA;
449 texcolor.R = (float)Math.Abs(color.X - 1);
450 texcolor.G = (float)Math.Abs(color.Y - 1);
451 texcolor.B = (float)Math.Abs(color.Z - 1);
452 tex.FaceTextures[face].RGBA = texcolor;
453 m_host.UpdateTexture(tex);
454 return;
455 }
456 else if (face == -1)
457 {
458 texcolor = tex.DefaultTexture.RGBA;
459 texcolor.R = (float)Math.Abs(color.X - 1);
460 texcolor.G = (float)Math.Abs(color.Y - 1);
461 texcolor.B = (float)Math.Abs(color.Z - 1);
462 tex.DefaultTexture.RGBA = texcolor;
463 for (uint i = 0; i < 32; i++)
464 {
465 if (tex.FaceTextures[i] != null)
466 {
467 texcolor = tex.FaceTextures[i].RGBA;
468 texcolor.R = (float)Math.Abs(color.X - 1);
469 texcolor.G = (float)Math.Abs(color.Y - 1);
470 texcolor.B = (float)Math.Abs(color.Z - 1);
471 tex.FaceTextures[i].RGBA = texcolor;
472 }
473 }
474 m_host.UpdateTexture(tex);
475 return;
476 }
444 NotImplemented("llSetColor"); 477 NotImplemented("llSetColor");
445 return; 478 return;
446 } 479 }
447 480
448 public double llGetAlpha(int face) 481 public double llGetAlpha(int face)
449 { 482 {
450 NotImplemented("llGetAlpha"); 483 LLObject.TextureEntry tex = new LLObject.TextureEntry(m_host.Shape.TextureEntry, 0, m_host.Shape.TextureEntry.Length);
484 if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color
485 {
486 return (double)((tex.DefaultTexture.RGBA.A * 255) / 255);
487 }
488 if (face > -1)
489 {
490 return (double)((tex.GetFace((uint)face).RGBA.A * 255) / 255);
491 }
451 return 0; 492 return 0;
452 } 493 }
453 494
454 public void llSetAlpha(double alpha, int face) 495 public void llSetAlpha(double alpha, int face)
455 { 496 {
497 LLObject.TextureEntry tex = new LLObject.TextureEntry(m_host.Shape.TextureEntry, 0, m_host.Shape.TextureEntry.Length);
498 LLColor texcolor;
499 if (face > -1)
500 {
501 texcolor = tex.CreateFace((uint)face).RGBA;
502 texcolor.A = (float)Math.Abs(alpha - 1);
503 tex.FaceTextures[face].RGBA = texcolor;
504 m_host.UpdateTexture(tex);
505 return;
506 }
507 else if (face == -1)
508 {
509 texcolor = tex.DefaultTexture.RGBA;
510 texcolor.A = (float)Math.Abs(alpha - 1);
511 tex.DefaultTexture.RGBA = texcolor;
512 for (int i = 0; i < 32; i++)
513 {
514 if (tex.FaceTextures[i] != null)
515 {
516 texcolor = tex.FaceTextures[i].RGBA;
517 texcolor.A = (float)Math.Abs(alpha - 1);
518 tex.FaceTextures[i].RGBA = texcolor;
519 }
520 }
521 m_host.UpdateTexture(tex);
522 return;
523 }
456 NotImplemented("llSetAlpha"); 524 NotImplemented("llSetAlpha");
457 return; 525 return;
458 } 526 }
459 527
460 public LSL_Types.Vector3 llGetColor(int face) 528 public LSL_Types.Vector3 llGetColor(int face)
461 { 529 {
530 LLObject.TextureEntry tex = new LLObject.TextureEntry(m_host.Shape.TextureEntry, 0, m_host.Shape.TextureEntry.Length);
531 LLColor texcolor;
532 LSL_Types.Vector3 rgb;
533 if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color
534 {
535 texcolor = tex.DefaultTexture.RGBA;
536 rgb.X = (255 - (texcolor.R * 255)) / 255;
537 rgb.Y = (255 - (texcolor.G * 255)) / 255;
538 rgb.Z = (255 - (texcolor.B * 255)) / 255;
539 return rgb;
540 }
541 if (face > -1)
542 {
543 texcolor = tex.GetFace((uint)face).RGBA;
544 rgb.X = (255 - (texcolor.R * 255)) / 255;
545 rgb.Y = (255 - (texcolor.G * 255)) / 255;
546 rgb.Z = (255 - (texcolor.B * 255)) / 255;
547 return rgb;
548 }
462 NotImplemented("llGetColor"); 549 NotImplemented("llGetColor");
463 return new LSL_Types.Vector3(); 550 return new LSL_Types.Vector3();
464 } 551 }
465 552
466 public void llSetTexture(string texture, int face) 553 public void llSetTexture(string texture, int face)
467 { 554 {
555 LLObject.TextureEntry tex = new LLObject.TextureEntry(m_host.Shape.TextureEntry, 0, m_host.Shape.TextureEntry.Length);
556 if (face > -1)
557 {
558 LLObject.TextureEntryFace texface = tex.CreateFace((uint)face);
559 texface.TextureID = new LLUUID(texture);
560 tex.FaceTextures[face] = texface;
561 m_host.UpdateTexture(tex);
562 return;
563 }
564 else if (face == -1)
565 {
566 for (uint i = 0; i < 32; i++)
567 {
568 if (tex.FaceTextures[i] != null)
569 {
570 tex.FaceTextures[i].TextureID = new LLUUID(texture);
571 }
572 }
573 tex.DefaultTexture.TextureID = new LLUUID(texture);
574 m_host.UpdateTexture(tex);
575 return;
576 }
468 NotImplemented("llSetTexture"); 577 NotImplemented("llSetTexture");
469 return; 578 return;
470 } 579 }
471 580
472 public void llScaleTexture(double u, double v, int face) 581 public void llScaleTexture(double u, double v, int face)
473 { 582 {
583 LLObject.TextureEntry tex = new LLObject.TextureEntry(m_host.Shape.TextureEntry, 0, m_host.Shape.TextureEntry.Length);
584 if (face > -1)
585 {
586 LLObject.TextureEntryFace texface = tex.CreateFace((uint)face);
587 texface.RepeatU = (float)u;
588 texface.RepeatV = (float)v;
589 tex.FaceTextures[face] = texface;
590 m_host.UpdateTexture(tex);
591 return;
592 }
593 if (face == -1)
594 {
595 for (int i = 0; i < 32; i++)
596 {
597 if (tex.FaceTextures[i] != null)
598 {
599 tex.FaceTextures[i].RepeatU = (float)u;
600 tex.FaceTextures[i].RepeatV = (float)v;
601
602 }
603 }
604 tex.DefaultTexture.RepeatU = (float)u;
605 tex.DefaultTexture.RepeatV = (float)v;
606 m_host.UpdateTexture(tex);
607 return;
608 }
474 NotImplemented("llScaleTexture"); 609 NotImplemented("llScaleTexture");
475 return; 610 return;
476 } 611 }
477 612
478 public void llOffsetTexture(double u, double v, int face) 613 public void llOffsetTexture(double u, double v, int face)
479 { 614 {
615 LLObject.TextureEntry tex = new LLObject.TextureEntry(m_host.Shape.TextureEntry, 0, m_host.Shape.TextureEntry.Length);
616 if (face > -1)
617 {
618 LLObject.TextureEntryFace texface = tex.CreateFace((uint)face);
619 texface.OffsetU = (float)u;
620 texface.OffsetV = (float)v;
621 tex.FaceTextures[face] = texface;
622 m_host.UpdateTexture(tex);
623 return;
624 }
625 if (face == -1)
626 {
627 LLObject.TextureEntryFace texface;
628 for (int i = 0; i < 32; i++)
629 {
630 if (tex.FaceTextures[i] != null)
631 {
632 tex.FaceTextures[i].OffsetU = (float)u;
633 tex.FaceTextures[i].OffsetV = (float)v;
634 }
635 }
636 tex.DefaultTexture.OffsetU = (float)u;
637 tex.DefaultTexture.OffsetV = (float)v;
638 m_host.UpdateTexture(tex);
639 return;
640 }
480 NotImplemented("llOffsetTexture"); 641 NotImplemented("llOffsetTexture");
481 return; 642 return;
482 } 643 }
483 644
484 public void llRotateTexture(double rotation, int face) 645 public void llRotateTexture(double rotation, int face)
485 { 646 {
647 LLObject.TextureEntry tex = new LLObject.TextureEntry(m_host.Shape.TextureEntry, 0, m_host.Shape.TextureEntry.Length);
648 if (face > -1)
649 {
650 LLObject.TextureEntryFace texface = tex.CreateFace((uint)face);
651 texface.Rotation = (float)rotation;
652 tex.FaceTextures[face] = texface;
653 m_host.UpdateTexture(tex);
654 return;
655 }
656 if (face == -1)
657 {
658 for (int i = 0; i < 32; i++)
659 {
660 if (tex.FaceTextures[i] != null)
661 {
662 tex.FaceTextures[i].Rotation = (float)rotation;
663 }
664 }
665 tex.DefaultTexture.Rotation = (float)rotation;
666 m_host.UpdateTexture(tex);
667 return;
668 }
486 NotImplemented("llRotateTexture"); 669 NotImplemented("llRotateTexture");
487 return; 670 return;
488 } 671 }
489 672
490 public string llGetTexture(int face) 673 public string llGetTexture(int face)
491 { 674 {
675 LLObject.TextureEntry tex = new LLObject.TextureEntry(m_host.Shape.TextureEntry, 0, m_host.Shape.TextureEntry.Length);
676 if (face == -1)
677 {
678 face = 0;
679 }
680 if (face > -1)
681 {
682 LLObject.TextureEntryFace texface;
683 texface = tex.GetFace((uint)face);
684 return texface.TextureID.ToStringHyphenated();
685 }
492 NotImplemented("llGetTexture"); 686 NotImplemented("llGetTexture");
493 return ""; 687 return "";
494 } 688 }
@@ -1151,17 +1345,40 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
1151 1345
1152 public LSL_Types.Vector3 llGetTextureOffset(int face) 1346 public LSL_Types.Vector3 llGetTextureOffset(int face)
1153 { 1347 {
1154 return new LSL_Types.Vector3(); 1348 LLObject.TextureEntry tex = new LLObject.TextureEntry(m_host.Shape.TextureEntry, 0, m_host.Shape.TextureEntry.Length);
1349 LSL_Types.Vector3 offset;
1350 if (face == -1)
1351 {
1352 face = 0;
1353 }
1354 offset.X = tex.GetFace((uint)face).OffsetU;
1355 offset.Y = tex.GetFace((uint)face).OffsetV;
1356 offset.Z = 0.0;
1357 return offset;
1155 } 1358 }
1156 1359
1157 public LSL_Types.Vector3 llGetTextureScale(int side) 1360 public LSL_Types.Vector3 llGetTextureScale(int side)
1158 { 1361 {
1159 return new LSL_Types.Vector3(); 1362 LLObject.TextureEntry tex = new LLObject.TextureEntry(m_host.Shape.TextureEntry, 0, m_host.Shape.TextureEntry.Length);
1363 LSL_Types.Vector3 scale;
1364 if (side == -1)
1365 {
1366 side = 0;
1367 }
1368 scale.X = tex.GetFace((uint)side).RepeatU;
1369 scale.Y = tex.GetFace((uint)side).RepeatV;
1370 scale.Z = 0.0;
1371 return scale;
1160 } 1372 }
1161 1373
1162 public double llGetTextureRot(int side) 1374 public double llGetTextureRot(int face)
1163 { 1375 {
1164 return 0; 1376 LLObject.TextureEntry tex = new LLObject.TextureEntry(m_host.Shape.TextureEntry, 0, m_host.Shape.TextureEntry.Length);
1377 if (face == -1)
1378 {
1379 face = 0;
1380 }
1381 return tex.GetFace((uint)face).Rotation;
1165 } 1382 }
1166 1383
1167 public int llSubStringIndex(string source, string pattern) 1384 public int llSubStringIndex(string source, string pattern)
@@ -1604,87 +1821,87 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
1604 { 1821 {
1605 switch ((int) rules[i]) 1822 switch ((int) rules[i])
1606 { 1823 {
1607 case (int) PrimitiveRule.PSYS_PART_FLAGS: 1824 case (int) LSL_BaseClass.PSYS_PART_FLAGS:
1608 prules.PartFlags = (uint) rules[i + 1]; 1825 prules.PartFlags = (uint) rules[i + 1];
1609 break; 1826 break;
1610 1827
1611 case (int) PrimitiveRule.PSYS_PART_START_COLOR: 1828 case (int)LSL_BaseClass.PSYS_PART_START_COLOR:
1612 prules.PartStartColor = (LLColor) rules[i + 1]; 1829 prules.PartStartColor = (LLColor) rules[i + 1];
1613 break; 1830 break;
1614 1831
1615 case (int) PrimitiveRule.PSYS_PART_START_ALPHA: 1832 case (int)LSL_BaseClass.PSYS_PART_START_ALPHA:
1616 //what is the cast? prules.PartStartColor = (LSL_Types.Vec)rules[i + 1]; 1833 //what is the cast? prules.PartStartColor = (LSL_Types.Vec)rules[i + 1];
1617 break; 1834 break;
1618 1835
1619 case (int) PrimitiveRule.PSYS_PART_END_COLOR: 1836 case (int)LSL_BaseClass.PSYS_PART_END_COLOR:
1620 prules.PartEndColor = (LLColor) rules[i + 1]; 1837 prules.PartEndColor = (LLColor) rules[i + 1];
1621 break; 1838 break;
1622 1839
1623 case (int) PrimitiveRule.PSYS_PART_END_ALPHA: 1840 case (int)LSL_BaseClass.PSYS_PART_END_ALPHA:
1624 //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; 1841 //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1];
1625 break; 1842 break;
1626 1843
1627 case (int) PrimitiveRule.PSYS_PART_START_SCALE: 1844 case (int)LSL_BaseClass.PSYS_PART_START_SCALE:
1628 //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; 1845 //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1];
1629 break; 1846 break;
1630 1847
1631 case (int) PrimitiveRule.PSYS_PART_END_SCALE: 1848 case (int)LSL_BaseClass.PSYS_PART_END_SCALE:
1632 //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; 1849 //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1];
1633 break; 1850 break;
1634 1851
1635 case (int) PrimitiveRule.PSYS_PART_MAX_AGE: 1852 case (int)LSL_BaseClass.PSYS_PART_MAX_AGE:
1636 prules.MaxAge = (float) rules[i + 1]; 1853 prules.MaxAge = (float) rules[i + 1];
1637 break; 1854 break;
1638 1855
1639 case (int) PrimitiveRule.PSYS_SRC_ACCEL: 1856 case (int)LSL_BaseClass.PSYS_SRC_ACCEL:
1640 //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; 1857 //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1];
1641 break; 1858 break;
1642 1859
1643 case (int) PrimitiveRule.PSYS_SRC_PATTERN: 1860 case (int)LSL_BaseClass.PSYS_SRC_PATTERN:
1644 //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; 1861 //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1];
1645 break; 1862 break;
1646 1863
1647 case (int) PrimitiveRule.PSYS_SRC_TEXTURE: 1864 case (int)LSL_BaseClass.PSYS_SRC_TEXTURE:
1648 prules.Texture = (LLUUID) rules[i + 1]; 1865 prules.Texture = (LLUUID) rules[i + 1];
1649 break; 1866 break;
1650 1867
1651 case (int) PrimitiveRule.PSYS_SRC_BURST_RATE: 1868 case (int)LSL_BaseClass.PSYS_SRC_BURST_RATE:
1652 prules.BurstRate = (float) rules[i + 1]; 1869 prules.BurstRate = (float) rules[i + 1];
1653 break; 1870 break;
1654 1871
1655 case (int) PrimitiveRule.PSYS_SRC_BURST_PART_COUNT: 1872 case (int)LSL_BaseClass.PSYS_SRC_BURST_PART_COUNT:
1656 prules.BurstPartCount = (byte) rules[i + 1]; 1873 prules.BurstPartCount = (byte) rules[i + 1];
1657 break; 1874 break;
1658 1875
1659 case (int) PrimitiveRule.PSYS_SRC_BURST_RADIUS: 1876 case (int)LSL_BaseClass.PSYS_SRC_BURST_RADIUS:
1660 prules.BurstRadius = (float) rules[i + 1]; 1877 prules.BurstRadius = (float) rules[i + 1];
1661 break; 1878 break;
1662 1879
1663 case (int) PrimitiveRule.PSYS_SRC_BURST_SPEED_MIN: 1880 case (int)LSL_BaseClass.PSYS_SRC_BURST_SPEED_MIN:
1664 prules.BurstSpeedMin = (float) rules[i + 1]; 1881 prules.BurstSpeedMin = (float) rules[i + 1];
1665 break; 1882 break;
1666 1883
1667 case (int) PrimitiveRule.PSYS_SRC_BURST_SPEED_MAX: 1884 case (int)LSL_BaseClass.PSYS_SRC_BURST_SPEED_MAX:
1668 prules.BurstSpeedMax = (float) rules[i + 1]; 1885 prules.BurstSpeedMax = (float) rules[i + 1];
1669 break; 1886 break;
1670 1887
1671 case (int) PrimitiveRule.PSYS_SRC_MAX_AGE: 1888 case (int)LSL_BaseClass.PSYS_SRC_MAX_AGE:
1672 prules.MaxAge = (float) rules[i + 1]; 1889 prules.MaxAge = (float) rules[i + 1];
1673 break; 1890 break;
1674 1891
1675 case (int) PrimitiveRule.PSYS_SRC_TARGET_KEY: 1892 case (int)LSL_BaseClass.PSYS_SRC_TARGET_KEY:
1676 prules.Target = (LLUUID) rules[i + 1]; 1893 prules.Target = (LLUUID) rules[i + 1];
1677 break; 1894 break;
1678 1895
1679 case (int) PrimitiveRule.PSYS_SRC_OMEGA: 1896 case (int)LSL_BaseClass.PSYS_SRC_OMEGA:
1680 //cast?? prules.MaxAge = (float)rules[i + 1]; 1897 //cast?? prules.MaxAge = (float)rules[i + 1];
1681 break; 1898 break;
1682 1899
1683 case (int) PrimitiveRule.PSYS_SRC_ANGLE_BEGIN: 1900 case (int)LSL_BaseClass.PSYS_SRC_ANGLE_BEGIN:
1684 prules.InnerAngle = (float) rules[i + 1]; 1901 prules.InnerAngle = (float) rules[i + 1];
1685 break; 1902 break;
1686 1903
1687 case (int) PrimitiveRule.PSYS_SRC_ANGLE_END: 1904 case (int)LSL_BaseClass.PSYS_SRC_ANGLE_END:
1688 prules.OuterAngle = (float) rules[i + 1]; 1905 prules.OuterAngle = (float) rules[i + 1];
1689 break; 1906 break;
1690 } 1907 }