aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorDr Scofield2009-05-22 16:22:49 +0000
committerDr Scofield2009-05-22 16:22:49 +0000
commit3b689e506f82ea45fcf703b22eb50a00e40baa4f (patch)
tree4c99a98342400d3f9f49670e3f6754554d3c8235 /OpenSim
parentFrom: Alan Webb <alan_webb@us.ibm.com> (diff)
downloadopensim-SC_OLD-3b689e506f82ea45fcf703b22eb50a00e40baa4f.zip
opensim-SC_OLD-3b689e506f82ea45fcf703b22eb50a00e40baa4f.tar.gz
opensim-SC_OLD-3b689e506f82ea45fcf703b22eb50a00e40baa4f.tar.bz2
opensim-SC_OLD-3b689e506f82ea45fcf703b22eb50a00e40baa4f.tar.xz
From: Alan Webb <alan_webb@us.ibm.com>
Changes to support client-side image pre-caching in the region. This commit adds an additional calling sequence to the DynamicTexture data and URL calls. The new interface allows a dynamic image to be loaded into a specific object face (rather than the mandatory ALL_SIDES supported today. This is in part fulfilment of ticket #458.
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs59
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs96
-rw-r--r--OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs51
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs14
6 files changed, 178 insertions, 50 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index 259a333..6509bf3 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -42,6 +42,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
42{ 42{
43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager 43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 private const int ALL_SIDES = -1;
48
45 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); 49 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
46 50
47 private Dictionary<string, IDynamicTextureRender> RenderPlugins = 51 private Dictionary<string, IDynamicTextureRender> RenderPlugins =
@@ -106,6 +110,12 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
106 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, 110 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
107 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) 111 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
108 { 112 {
113 return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, SetBlending, AlphaValue, ALL_SIDES);
114 }
115
116 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
117 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue, int face)
118 {
109 if (RenderPlugins.ContainsKey(contentType)) 119 if (RenderPlugins.ContainsKey(contentType))
110 { 120 {
111 //m_log.Debug("dynamic texture being created: " + url + " of type " + contentType); 121 //m_log.Debug("dynamic texture being created: " + url + " of type " + contentType);
@@ -120,6 +130,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
120 updater.Params = extraParams; 130 updater.Params = extraParams;
121 updater.BlendWithOldTexture = SetBlending; 131 updater.BlendWithOldTexture = SetBlending;
122 updater.FrontAlpha = AlphaValue; 132 updater.FrontAlpha = AlphaValue;
133 updater.Face = face;
123 134
124 lock (Updaters) 135 lock (Updaters)
125 { 136 {
@@ -144,6 +155,12 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
144 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, 155 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
145 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) 156 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
146 { 157 {
158 return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, SetBlending, AlphaValue, ALL_SIDES);
159 }
160
161 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
162 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue, int face)
163 {
147 if (RenderPlugins.ContainsKey(contentType)) 164 if (RenderPlugins.ContainsKey(contentType))
148 { 165 {
149 DynamicTextureUpdater updater = new DynamicTextureUpdater(); 166 DynamicTextureUpdater updater = new DynamicTextureUpdater();
@@ -156,6 +173,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
156 updater.Params = extraParams; 173 updater.Params = extraParams;
157 updater.BlendWithOldTexture = SetBlending; 174 updater.BlendWithOldTexture = SetBlending;
158 updater.FrontAlpha = AlphaValue; 175 updater.FrontAlpha = AlphaValue;
176 updater.Face = face;
177 updater.Url = "Local image";
159 178
160 lock (Updaters) 179 lock (Updaters)
161 { 180 {
@@ -232,6 +251,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
232 public UUID SimUUID; 251 public UUID SimUUID;
233 public UUID UpdaterID; 252 public UUID UpdaterID;
234 public int UpdateTimer; 253 public int UpdateTimer;
254 public int Face;
235 public string Url; 255 public string Url;
236 256
237 public DynamicTextureUpdater() 257 public DynamicTextureUpdater()
@@ -249,7 +269,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
249 269
250 SceneObjectPart part = scene.GetSceneObjectPart(PrimID); 270 SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
251 271
252 if (data == null) 272 if (data == null || data.Length <= 1)
253 { 273 {
254 string msg = 274 string msg =
255 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); 275 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
@@ -287,34 +307,51 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
287 asset.Data = assetData; 307 asset.Data = assetData;
288 asset.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000); 308 asset.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000);
289 asset.Type = 0; 309 asset.Type = 0;
290 asset.Description = "dynamic image"; 310 asset.Description = String.Format("URL image : {0}", Url);
291 asset.Local = false; 311 asset.Local = false;
292 asset.Temporary = true; 312 asset.Temporary = true;
293 scene.AssetService.Store(asset); 313 scene.AssetService.Store(asset);
294 314
295 LastAssetID = asset.FullID;
296
297 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>(); 315 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
298 if (cacheLayerDecode != null) 316 if (cacheLayerDecode != null)
299 { 317 {
300 cacheLayerDecode.syncdecode(asset.FullID, asset.Data); 318 cacheLayerDecode.syncdecode(asset.FullID, asset.Data);
319 cacheLayerDecode = null;
320 LastAssetID = asset.FullID;
301 } 321 }
302 cacheLayerDecode = null;
303 322
304 // mostly keep the values from before 323 // mostly keep the values from before
305 Primitive.TextureEntry tmptex = part.Shape.Textures; 324 Primitive.TextureEntry tmptex = part.Shape.Textures;
306 325
307 // remove the old asset from the cache 326 // remove the old asset from the cache later
308 // UUID oldID = tmptex.DefaultTexture.TextureID; 327 UUID oldID = tmptex.DefaultTexture.TextureID;
309 328
310 tmptex.DefaultTexture.TextureID = asset.FullID; 329 if (Face == ALL_SIDES)
330 {
331 tmptex.DefaultTexture.TextureID = asset.FullID;
332 }
333 else
334 {
335 try
336 {
337 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
338 texface.TextureID = asset.FullID;
339 tmptex.FaceTextures[Face] = texface;
340 }
341 catch(Exception)
342 {
343 tmptex.DefaultTexture.TextureID = asset.FullID;
344 }
345 }
346
311 // I'm pretty sure we always want to force this to true 347 // I'm pretty sure we always want to force this to true
312 // I'm pretty sure noone whats to set fullbright true if it wasn't true before. 348 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
313 // tmptex.DefaultTexture.Fullbright = true; 349 // tmptex.DefaultTexture.Fullbright = true;
314 350
315 part.Shape.Textures = tmptex; 351 part.UpdateTexture(tmptex);
316 part.ScheduleFullUpdate(); 352
317 353 // scene.CommsManager.AssetCache.ExpireAsset(oldID);
354 scene.AssetService.Delete(oldID.ToString());
318 } 355 }
319 356
320 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) 357 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 864d6ac..61c37b9 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -162,62 +162,80 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
162 162
163 private void HttpRequestReturn(IAsyncResult result) 163 private void HttpRequestReturn(IAsyncResult result)
164 { 164 {
165
165 RequestState state = (RequestState) result.AsyncState; 166 RequestState state = (RequestState) result.AsyncState;
166 WebRequest request = (WebRequest) state.Request; 167 WebRequest request = (WebRequest) state.Request;
168 Stream stream = null;
169 byte[] imageJ2000 = new byte[0];
170
167 try 171 try
168 { 172 {
169 HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result); 173 HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
170 if (response.StatusCode == HttpStatusCode.OK) 174 if (response != null && response.StatusCode == HttpStatusCode.OK)
171 { 175 {
172 Bitmap image = new Bitmap(response.GetResponseStream()); 176 stream = response.GetResponseStream();
173 Size newsize; 177 if(stream != null)
174
175 // TODO: make this a bit less hard coded
176 if ((image.Height < 64) && (image.Width < 64))
177 {
178 newsize = new Size(32, 32);
179 }
180 else if ((image.Height < 128) && (image.Width < 128))
181 {
182 newsize = new Size(64, 64);
183 }
184 else if ((image.Height < 256) && (image.Width < 256))
185 {
186 newsize = new Size(128, 128);
187 }
188 else if ((image.Height < 512 && image.Width < 512))
189 {
190 newsize = new Size(256, 256);
191 }
192 else if ((image.Height < 1024 && image.Width < 1024))
193 { 178 {
194 newsize = new Size(512, 512); 179 Bitmap image = new Bitmap(stream);
180 Size newsize;
181
182 // TODO: make this a bit less hard coded
183 if ((image.Height < 64) && (image.Width < 64))
184 {
185 newsize = new Size(32, 32);
186 }
187 else if ((image.Height < 128) && (image.Width < 128))
188 {
189 newsize = new Size(64, 64);
190 }
191 else if ((image.Height < 256) && (image.Width < 256))
192 {
193 newsize = new Size(128, 128);
194 }
195 else if ((image.Height < 512 && image.Width < 512))
196 {
197 newsize = new Size(256, 256);
198 }
199 else if ((image.Height < 1024 && image.Width < 1024))
200 {
201 newsize = new Size(512, 512);
202 }
203 else
204 {
205 newsize = new Size(1024, 1024);
206 }
207
208 Bitmap resize = new Bitmap(image, newsize);
209
210 try
211 {
212 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
213 }
214 catch (Exception)
215 {
216 m_log.Error("[LOADIMAGEURLMODULE]: OpenJpeg Encode Failed. Empty byte data returned!");
217 }
195 } 218 }
196 else 219 else
197 { 220 {
198 newsize = new Size(1024, 1024); 221 m_log.WarnFormat("[LOADIMAGEURLMODULE] No data returned");
199 }
200
201 Bitmap resize = new Bitmap(image, newsize);
202 byte[] imageJ2000 = new byte[0];
203
204 try
205 {
206 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
207 }
208 catch (Exception)
209 {
210 m_log.Error("[LOADIMAGEURLMODULE]: OpenJpeg Encode Failed. Empty byte data returned!");
211 } 222 }
212
213 m_textureManager.ReturnData(state.RequestID, imageJ2000);
214 return;
215 } 223 }
216 } 224 }
217 catch (WebException) 225 catch (WebException)
218 { 226 {
219 227
220 } 228 }
229 finally
230 {
231 if(stream != null)
232 {
233 stream.Close();
234 }
235 }
236 m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}",
237 imageJ2000.Length, state.RequestID);
238 m_textureManager.ReturnData(state.RequestID, imageJ2000);
221 } 239 }
222 240
223 #region Nested type: RequestState 241 #region Nested type: RequestState
diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
index 9b29209..80592d7 100644
--- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
@@ -39,10 +39,14 @@ namespace OpenSim.Region.Framework.Interfaces
39 int updateTimer); 39 int updateTimer);
40 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, 40 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
41 int updateTimer, bool SetBlending, byte AlphaValue); 41 int updateTimer, bool SetBlending, byte AlphaValue);
42 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
43 int updateTimer, bool SetBlending, byte AlphaValue, int face);
42 UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams, 44 UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
43 int updateTimer); 45 int updateTimer);
44 UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams, 46 UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
45 int updateTimer, bool SetBlending, byte AlphaValue); 47 int updateTimer, bool SetBlending, byte AlphaValue);
48 UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
49 int updateTimer, bool SetBlending, byte AlphaValue, int face);
46 void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, 50 void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
47 out double xSize, out double ySize); 51 out double xSize, out double ySize);
48 } 52 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index fbae9c8..91ee1b3 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -427,6 +427,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
427 return UUID.Zero.ToString(); 427 return UUID.Zero.ToString();
428 } 428 }
429 429
430 public string osSetDynamicTextureURLBlendFace(string dynamicID, string contentType, string url, string extraParams,
431 bool blend, int timer, int alpha, int face)
432 {
433 CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureURLBlendFace");
434
435 m_host.AddScriptLPS(1);
436 if (dynamicID == String.Empty)
437 {
438 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
439 UUID createdTexture =
440 textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url,
441 extraParams, timer, blend, (byte) alpha, face);
442 return createdTexture.ToString();
443 }
444 else
445 {
446 //TODO update existing dynamic textures
447 }
448
449 return UUID.Zero.ToString();
450 }
451
430 public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, 452 public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams,
431 int timer) 453 int timer)
432 { 454 {
@@ -485,6 +507,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
485 return UUID.Zero.ToString(); 507 return UUID.Zero.ToString();
486 } 508 }
487 509
510 public string osSetDynamicTextureDataBlendFace(string dynamicID, string contentType, string data, string extraParams,
511 bool blend, int timer, int alpha, int face)
512 {
513 CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureDataBlendFace");
514
515 m_host.AddScriptLPS(1);
516 if (dynamicID == String.Empty)
517 {
518 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
519 if (textureManager != null)
520 {
521 if (extraParams == String.Empty)
522 {
523 extraParams = "256";
524 }
525 UUID createdTexture =
526 textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data,
527 extraParams, timer, blend, (byte) alpha, face);
528 return createdTexture.ToString();
529 }
530 }
531 else
532 {
533 //TODO update existing dynamic textures
534 }
535
536 return UUID.Zero.ToString();
537 }
538
488 public bool osConsoleCommand(string command) 539 public bool osConsoleCommand(string command)
489 { 540 {
490 CheckThreatLevel(ThreatLevel.Severe, "osConsoleCommand"); 541 CheckThreatLevel(ThreatLevel.Severe, "osConsoleCommand");
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 7c0f086..3360abe 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -58,9 +58,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
58 string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, int timer); 58 string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, int timer);
59 string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams, 59 string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams,
60 int timer, int alpha); 60 int timer, int alpha);
61 string osSetDynamicTextureURLBlendFace(string dynamicID, string contentType, string url, string extraParams,
62 bool blend, int timer, int alpha, int face);
61 string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, int timer); 63 string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, int timer);
62 string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams, 64 string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams,
63 int timer, int alpha); 65 int timer, int alpha);
66 string osSetDynamicTextureDataBlendFace(string dynamicID, string contentType, string data, string extraParams,
67 bool blend, int timer, int alpha, int face);
64 68
65 LSL_Float osTerrainGetHeight(int x, int y); 69 LSL_Float osTerrainGetHeight(int x, int y);
66 LSL_Integer osTerrainSetHeight(int x, int y, double val); 70 LSL_Integer osTerrainSetHeight(int x, int y, double val);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index a66ed30..9d8920f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -134,6 +134,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
134 return m_OSSL_Functions.osSetDynamicTextureDataBlend(dynamicID, contentType, data, extraParams, timer, alpha); 134 return m_OSSL_Functions.osSetDynamicTextureDataBlend(dynamicID, contentType, data, extraParams, timer, alpha);
135 } 135 }
136 136
137 public string osSetDynamicTextureURLBlendFace(string dynamicID, string contentType, string url, string extraParams,
138 bool blend, int timer, int alpha, int face)
139 {
140 return m_OSSL_Functions.osSetDynamicTextureURLBlendFace(dynamicID, contentType, url, extraParams,
141 blend, timer, alpha, face);
142 }
143
144 public string osSetDynamicTextureDataBlendFace(string dynamicID, string contentType, string data, string extraParams,
145 bool blend, int timer, int alpha, int face)
146 {
147 return m_OSSL_Functions.osSetDynamicTextureDataBlendFace(dynamicID, contentType, data, extraParams,
148 blend, timer, alpha, face);
149 }
150
137 public LSL_Float osTerrainGetHeight(int x, int y) 151 public LSL_Float osTerrainGetHeight(int x, int y)
138 { 152 {
139 return m_OSSL_Functions.osTerrainGetHeight(x, y); 153 return m_OSSL_Functions.osTerrainGetHeight(x, y);