add wraparound support to C2 physics
[openc2e.git] / caosVM_camera.cpp
blob74f1ece51d445dde5c5b8c5ecf77f7928d1f8763
1 /*
2 * caosVM_camera.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Tue May 25 2004.
6 * Copyright (c) 2004 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
20 #include "caosVM.h"
21 #include "World.h"
22 #include "CompoundAgent.h"
23 #include "CameraPart.h"
24 #include "MetaRoom.h"
26 Camera *caosVM::getCamera() {
27 Camera *c = camera.lock().get();
28 if (!c) c = &world.camera;
29 return c;
32 bool agentOnCamera(Agent *targ, bool checkall) {
33 MetaRoom *m = world.map.metaRoomAt(targ->x, targ->y);
34 if (!m || m != world.camera.getMetaRoom()) return false;
36 // TODO: check non-main cameras?
37 // TODO: do compound parts stick out of the agent?
39 // y coordinates don't wrap
40 if (targ->y + targ->getHeight() < world.camera.getY()) return false;
41 if (targ->y > world.camera.getY() + world.camera.getHeight()) return false;
43 // if an agent is off-camera to the right, it's not visible
44 if (targ->x > world.camera.getX() + world.camera.getWidth()) return false;
46 if (targ->x + targ->getWidth() < world.camera.getX()) {
47 // if an agent is off-camera to the left, it might be wrapping
48 if (!m->wraparound() || (targ->x + targ->getWidth() + m->width() < world.camera.getX()))
49 return false;
52 return true;
55 /**
56 VISI (integer) checkall (integer)
57 %status maybe
59 Returns 1 if the TARG agent is on camera, or 0 otherwise. If checkall is 0, only checks
60 main camera, otherwise checks all.
62 void caosVM::v_VISI() {
63 VM_PARAM_INTEGER(checkall)
65 valid_agent(targ);
67 if (agentOnCamera(targ, checkall))
68 result.setInt(1);
69 else
70 result.setInt(0);
73 /**
74 ONTV (integer) agent (agent) checkall (integer)
75 %status maybe
77 Returns 1 if the specified agent is on camera, or 0 otherwise. If checkall is 0, only checks
78 main camera, otherwise checks all.
80 void caosVM::v_ONTV() {
81 VM_PARAM_INTEGER(checkall)
82 VM_PARAM_VALIDAGENT(agent)
84 if (agentOnCamera(agent.get(), checkall))
85 result.setInt(1);
86 else
87 result.setInt(0);
90 /**
91 META (command) metaroom_id (integer) camera_x (integer) camera_y (integer) transition (integer)
92 %status maybe
94 Sets the metaroom that the current camera is pointing at. Coordinates point to top left of new
95 camera position. Set a coordinate to -1 to use the top-left corner of the metaroom.
97 Transition: 0 for none, 1 for flip horzizontally, 2 for burst.
99 void caosVM::c_META() {
100 VM_VERIFY_SIZE(4)
101 VM_PARAM_INTEGER(transition)
102 VM_PARAM_INTEGER(camera_y)
103 VM_PARAM_INTEGER(camera_x)
104 VM_PARAM_INTEGER(metaroom_id)
106 caos_assert(metaroom_id >= 0);
107 MetaRoom *m = world.map.getMetaRoom(metaroom_id);
108 if (!m) return; // DS does 'meta 0 -1 -1 0' in !map.cos for some stupid reason
110 int camerax = camera_x; if (camerax == -1) camerax = m->x();
111 int cameray = camera_y; if (cameray == -1) cameray = m->y();
113 getCamera()->goToMetaRoom(metaroom_id, camerax, cameray, (cameratransition)transition);
117 META (integer)
118 %status maybe
120 Returns the metaroom the current camera is looking at.
122 void caosVM::v_META() {
123 if (getCamera()->getMetaRoom())
124 result.setInt(getCamera()->getMetaRoom()->id);
125 else // this is a hack for empathic vendor.cos in DS, which uses META before it's setup
126 // TODO: work out what we should do instead of the hack
127 result.setInt(-1);
131 CMRT (command) pan (integer)
132 %status maybe
134 Focuses the current camera on the TARG agent.
136 Set pan to 0 for no panning (jump), 1 for smooth scrolling if in the same metaroom, or 2
137 for smooth scrolling if the given location is already visible.
139 void caosVM::c_CMRT() {
140 VM_VERIFY_SIZE(1)
141 VM_PARAM_INTEGER(pan)
143 valid_agent(targ);
145 MetaRoom *r = world.map.metaRoomAt(targ->x, targ->y);
146 int xpos = (int)(targ->x - (getCamera()->getWidth() / 2.0f) + (targ->getWidth() / 2.0f));
147 int ypos = (int)(targ->y - (getCamera()->getHeight() / 2.0f) + (targ->getHeight() / 2.0f));
148 if (r)
149 getCamera()->goToMetaRoom(r->id, xpos, ypos, (cameratransition)pan); // TODO: pan okay?
153 CMRA (command) x (integer) y (integer) pan (integer)
154 %status maybe
156 Sets the position of the current camera so that the top left corner of the view is at the
157 given coordinates.
159 Set pan to 0 for no panning (jump), or 1 for smooth scrolling if in the same metaroom.
161 void caosVM::c_CMRA() {
162 VM_VERIFY_SIZE(3)
163 VM_PARAM_INTEGER(pan)
164 VM_PARAM_INTEGER(y)
165 VM_PARAM_INTEGER(x)
167 getCamera()->moveTo(x, y, (panstyle)pan);
171 CMRP (command) x (integer) y (integer) pan (integer)
172 %status maybe
174 Sets the position of the current camera so that the view centers on the given coordinates.
176 Set pan to 0 for no panning (jump), 1 for smooth scrolling if in the same metaroom, or 2
177 for smooth scrolling if the given location is already visible.
179 void caosVM::c_CMRP() {
180 VM_VERIFY_SIZE(3)
181 VM_PARAM_INTEGER(pan)
182 VM_PARAM_INTEGER(y)
183 VM_PARAM_INTEGER(x)
185 getCamera()->moveTo(x - (getCamera()->getWidth() / 2), y - (getCamera()->getHeight() / 2), (panstyle)pan);
189 CMRX (integer)
190 %status maybe
191 %pragma variants c2 cv c3
193 Returns the X position at the center of the current camera's view.
195 void caosVM::v_CMRX() {
196 VM_VERIFY_SIZE(0)
198 result.setInt(getCamera()->getXCentre());
202 CMRY (integer)
203 %status maybe
204 %pragma variants c2 cv c3
206 Returns the Y position at the center of the current camera's view.
208 void caosVM::v_CMRY() {
209 VM_VERIFY_SIZE(0)
211 result.setInt(getCamera()->getYCentre());
215 WNDW (integer)
216 %status maybe
218 Returns the width of the current camera's view.
220 void caosVM::v_WNDW() {
221 VM_VERIFY_SIZE(0)
223 result.setInt(getCamera()->getWidth());
227 WNDH (integer)
228 %status maybe
230 Returns the height of the current camera's view.
232 void caosVM::v_WNDH() {
233 VM_VERIFY_SIZE(0)
235 result.setInt(getCamera()->getHeight());
239 WNDB (integer)
240 %status maybe
242 Returns the position of the bottom edge of the current camera's view.
244 void caosVM::v_WNDB() {
245 VM_VERIFY_SIZE(0)
247 result.setInt(getCamera()->getY() + getCamera()->getHeight());
251 WNDL (integer)
252 %status maybe
254 Returns the position of the left edge of the current camera's view.
256 void caosVM::v_WNDL() {
257 VM_VERIFY_SIZE(0)
259 result.setInt(getCamera()->getX());
263 WNDR (integer)
264 %status maybe
266 Returns the position of the right edge of the current camera's view.
268 void caosVM::v_WNDR() {
269 VM_VERIFY_SIZE(0)
271 result.setInt(getCamera()->getX() + getCamera()->getWidth());
275 WNDT (integer)
276 %status maybe
278 Returns the position of the top edge of the current camera's view.
280 void caosVM::v_WNDT() {
281 VM_VERIFY_SIZE(0)
283 result.setInt(getCamera()->getY());
287 WDOW (command)
288 %status stub
290 Toggles full-screen mode on and off.
292 void caosVM::c_WDOW() {
293 // TODO
297 WDOW (integer)
298 %status stub
300 Returns 1 if in full-screen mode, or 0 otherwise (windowed).
302 void caosVM::v_WDOW() {
303 result.setInt(0);
307 TRCK (command) agent (agent) xpercent (integer) ypercent (integer) style (integer) transition (integer)
308 %status maybe
310 Tell the current camera to track the specified agent, or set to NULL to stop tracking.
311 xpercent and ypercent define a rectangle on the screen which the camera should keep the tracked agent inside.
312 Style 0 is brittle-- tracking is broken easily. Style 1 is flexible-- moving the camera
313 back inside the rectangle resumes tracking. Style 3 is hard-- you can't move outside the
314 rectangle.
315 Rransition: 0 for none, 1 for flip horizontal, 2 for burst.
317 void caosVM::c_TRCK() {
318 VM_PARAM_INTEGER(transition)
319 VM_PARAM_INTEGER(style)
320 VM_PARAM_INTEGER(ypercent)
321 VM_PARAM_INTEGER(xpercent)
322 VM_PARAM_AGENT(agent)
324 getCamera()->trackAgent(agent, xpercent, ypercent, (trackstyle)style, (cameratransition)transition);
328 TRCK (agent)
329 %status maybe
331 Returns agent being tracked by the current camera, if any.
333 void caosVM::v_TRCK() {
334 result.setAgent(getCamera()->trackedAgent());
338 LINE (command) x1 (integer) y1 (integer) x2 (integer) y2 (integer) r (integer) g (integer) b (integer) stipple_on (integer) stipple_off (integer)
339 %status stub
341 Draw a line between two endpoints with the given coordinates, in the color specified by
342 the given red, green, and blue values.
344 Set stipple_on to a number of pixels to alternate for stippling, or set stipple_off to
345 turn stippling off.
347 Setting the the endpoints to the same point will remove all lines for the agent.
349 void caosVM::c_LINE() {
350 VM_PARAM_INTEGER(stipple_off)
351 VM_PARAM_INTEGER(stipple_on)
352 VM_PARAM_INTEGER(b)
353 VM_PARAM_INTEGER(g)
354 VM_PARAM_INTEGER(r)
355 VM_PARAM_INTEGER(y2)
356 VM_PARAM_INTEGER(x2)
357 VM_PARAM_INTEGER(y1)
358 VM_PARAM_INTEGER(x1)
360 valid_agent(targ);
361 // TODO
365 SNAX (integer) filename (string)
366 %status maybe
368 Determines whether or not the given image file exists in the world
369 images directory (0 or 1).
371 void caosVM::v_SNAX() {
372 VM_PARAM_STRING(filename)
374 result.setInt(0);
375 if (!world.findFile(std::string("/Images/") + filename + ".s16").empty())
376 result.setInt(1);
377 else if (!world.findFile(std::string("/Images/") + filename + ".c16").empty())
378 result.setInt(1);
382 SCAM (command) agent (agent) part (integer)
383 %status maybe
385 Sets which camera to use in camera macro commands. If 'agent' and
386 'part' are NULL, the main camera will be used.
388 void caosVM::c_SCAM() {
389 VM_PARAM_INTEGER(part)
390 VM_PARAM_AGENT(agent)
392 if (!agent) {
393 camera.reset();
394 return;
397 CompoundAgent *a = dynamic_cast<CompoundAgent *>(agent.get());
398 caos_assert(a);
399 CompoundPart *p = a->part(part);
400 caos_assert(p);
401 CameraPart *c = dynamic_cast<CameraPart *>(p);
402 caos_assert(c);
404 camera = c->getCamera();
408 ZOOM (command) pixels (integer) x (integer) y (integer)
409 %status stub
411 Zoom the current camera by the given number of pixels on the given x/y
412 coordinates in the world. If the coordinates are set to -1, the
413 current center position of the camera's view will be used.
415 void caosVM::c_ZOOM() {
416 VM_PARAM_INTEGER(y)
417 VM_PARAM_INTEGER(x)
418 VM_PARAM_INTEGER(pixels)
420 // TODO
424 SNAP (command) filename (string) x (integer) y (integer) width (integer) height (integer) zoom (integer)
425 %status stub
427 Take a snapshot and save it to the given filename (don't include the extension). x/y are the centerpoint, width/height the size, and zoom the percentage to zoom out.
429 void caosVM::c_SNAP() {
430 VM_PARAM_INTEGER(zoom)
431 VM_PARAM_INTEGER(height)
432 VM_PARAM_INTEGER(width)
433 VM_PARAM_INTEGER(y)
434 VM_PARAM_INTEGER(x)
435 VM_PARAM_STRING(filename)
437 // TODO
441 LOFT (integer) filename (string)
442 %status stub
444 void caosVM::v_LOFT() {
445 VM_PARAM_STRING(filename)
447 result.setInt(0); // TODO
451 BKGD (command) metaroom_id (integer) background (string) transition (integer)
452 %status stub
454 void caosVM::c_BKGD() {
455 VM_PARAM_INTEGER(transition)
456 VM_PARAM_STRING(background)
457 VM_PARAM_INTEGER(metaroomid)
459 MetaRoom *metaroom = world.map.getMetaRoom(metaroomid);
460 caos_assert(metaroom);
462 // TODO
466 BKGD (string) metaroom_id (integer)
467 %status stub
469 void caosVM::v_BKGD() {
470 VM_PARAM_INTEGER(metaroomid)
472 MetaRoom *metaroom = world.map.getMetaRoom(metaroomid);
473 caos_assert(metaroom);
475 result.setString(""); // TODO
479 FRSH (command)
480 %status stub
482 void caosVM::c_FRSH() {
483 // TODO
487 SYS: CMRP (command) x (integer) y (integer)
488 %status maybe
489 %pragma variants c2
491 Smooth scroll the camera so that the specified coordinates are in the center of the window.
492 (Yes, this differs from what the incorrect C2 documentation says.)
494 void caosVM::c_SYS_CMRP() {
495 VM_PARAM_INTEGER(y)
496 VM_PARAM_INTEGER(x)
498 getCamera()->moveTo(x - (getCamera()->getWidth() / 2), y - (getCamera()->getWidth() / 2), smoothscroll);
502 SYS: CMRA (command) x (integer) y (integer)
503 %status maybe
504 %pragma variants c1 c2
506 void caosVM::c_SYS_CMRA() {
507 VM_PARAM_INTEGER(y)
508 VM_PARAM_INTEGER(x)
510 getCamera()->moveTo(x, y);
514 SYS: CAMT (command)
515 %status maybe
516 %pragma variants c1 c2
518 void caosVM::c_SYS_CAMT() {
519 // TODO: does CAMT behave like this in c1/c2?
520 int xpos = (int)(targ->x - (getCamera()->getWidth() / 2.0f) + (targ->getWidth() / 2.0f));
521 int ypos = (int)(targ->y - (getCamera()->getHeight() / 2.0f) + (targ->getHeight() / 2.0f));
522 getCamera()->moveTo(xpos, ypos);
526 SYS: WTOP (command)
527 %status stub
528 %pragma variants c1 c2
530 Move the main window to the front of the screen.
532 void caosVM::c_SYS_WTOP() {
533 // TODO
536 /* vim: set noet: */