allow any CompoundPart to gain focus, if it canGainFocus()
[openc2e.git] / PointerAgent.cpp
blob89e9e8ddc17aed1e784a3bb4fa494fc54aff48e2
1 /*
2 * PointerAgent.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Tue Aug 30 2005.
6 * Copyright (c) 2005 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 "PointerAgent.h"
21 #include "openc2e.h"
22 #include "World.h"
23 #include "Engine.h"
24 #include "caosVM.h"
25 #include "Room.h"
26 #include "MetaRoom.h"
28 // TODO: change imagecount?
29 PointerAgent::PointerAgent(std::string spritefile) : SimpleAgent(2, 1, 1, INT_MAX, spritefile, 0, 0) {
30 name = "hand";
31 handle_events = true;
32 holdingWire = 0;
33 wireOriginID = 0;
34 // TODO: verify attributes on the pointer in c2e
35 attr.setInt(256); // camera shy
38 void PointerAgent::finishInit() {
39 Agent::finishInit();
41 // float relative to main camera
42 attr.setInt(attr.getInt() & 32);
43 floatSetup();
46 void PointerAgent::carry(AgentRef a) {
47 Agent::carry(a);
49 int eve; if (engine.version < 3) eve = 53; else eve = 104;
50 firePointerScript(eve, a); // Pointer Pickup
53 void PointerAgent::drop(AgentRef a) {
54 Agent::drop(a);
56 int eve; if (engine.version < 3) eve = 54; else eve = 105;
57 firePointerScript(eve, a); // Pointer Drop
60 // TODO: this should have a queueScript equiv too
61 void PointerAgent::firePointerScript(unsigned short event, Agent *src) {
62 assert(src); // TODO: I /think/ this should only be called by the engine..
63 shared_ptr<script> s = src->findScript(event);
64 if (!s && engine.version < 3) { // TODO: are we sure this doesn't apply to c2e?
65 s = findScript(event); // TODO: we should make sure this actually belongs to the pointer agent and isn't a fallback, maybe
67 if (!s) return;
68 if (!vm) vm = world.getVM(this);
69 if (vm->fireScript(s, false, src)) { // TODO: should FROM be src?
70 vm->setTarg(this);
71 zotstack();
75 void PointerAgent::physicsTick() {
76 // TODO: this is a hack, which does nothing, because we set a velocity in main() but also move the cursor manually
79 void PointerAgent::kill() {
80 // pointer agent isn't killable
83 void PointerAgent::setHotspot(int x, int y) {
84 hotspotx = x;
85 hotspoty = y;
88 void PointerAgent::handleEvent(SomeEvent &event) {
89 int x = pointerX(), y = pointerY();
91 if (event.type == eventmousemove) {
92 moveTo(event.x + world.camera.getX() - hotspotx, event.y + world.camera.getY() - hotspoty);
93 velx.setInt(event.xrel * 4);
94 vely.setInt(event.yrel * 4);
96 if (editAgent)
97 editAgent->moveTo(pointerX(), pointerY());
99 // middle mouse button scrolling
100 if (event.button & buttonmiddle)
101 world.camera.moveTo(world.camera.getX() - event.xrel, world.camera.getY() - event.yrel, jump);
102 } else if (!handle_events) {
103 /* mouse move events are (apparently - see eg C3 agent help) still handled with handle_events disabled, but nothing else */
104 return;
105 } else if (event.type == eventmousebuttondown) {
106 // do our custom handling
107 if (event.button == buttonleft) {
108 CompoundPart *a = world.partAt(x, y);
109 if (a /* && a->canActivate() */) { // TODO
110 Agent* parent = a->getParent();
112 int eve = -1;
114 bool foundport = false;
115 if (engine.version > 2) {
116 for (std::map<unsigned int, boost::shared_ptr<OutputPort> >::iterator i = parent->outports.begin();
117 i != parent->outports.end(); i++) {
118 // TODO: 4 is a magic number i pulled out of nooooowhere
119 if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
120 foundport = true;
121 if (holdingWire == 2) {
122 parent->join(i->first, wireOriginAgent, wireOriginID);
123 holdingWire = 0;
124 eve = 111;
125 } else if (holdingWire == 0) {
126 eve = 110;
127 holdingWire = 1;
128 wireOriginAgent = parent;
129 wireOriginID = i->first;
131 break;
134 if (!foundport) {
135 for (std::map<unsigned int, boost::shared_ptr<InputPort> >::iterator i = parent->inports.begin();
136 i != parent->inports.end(); i++) {
137 // TODO: 4 is a magic number i pulled out of nooooowhere
138 if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
139 foundport = true;
140 if (holdingWire == 1) {
141 if (i->second->source) {
142 eve = 114;
143 } else {
144 wireOriginAgent->join(wireOriginID, parent, i->first);
145 holdingWire = 0;
146 eve = 111;
148 } else if (holdingWire == 0) {
149 if (i->second->source) {
150 eve = 112;
151 holdingWire = 1;
152 wireOriginAgent = i->second->source;
153 wireOriginID = i->second->sourceid;
154 i->second->source->outports[i->second->sourceid]->dests.remove(std::pair<AgentRef, unsigned int>(parent, i->first));
155 i->second->source.clear();
156 } else {
157 eve = 110;
158 holdingWire = 2;
159 wireOriginAgent = parent;
160 wireOriginID = i->first;
163 break;
169 if (!foundport) {
170 if (holdingWire) {
171 holdingWire = 0;
172 eve = 113;
173 } else {
174 // if the agent isn't paused, tell it to handle a click
175 int scriptid = a->handleClick(x - a->x - parent->x, y - a->y - parent->y);
176 if (scriptid != -1) {
177 // fire the script
178 // _p1_ is id of part for button clicks, according to Edynn code
179 // TODO: should _p1_ always be set? :)
180 if (!parent->paused) parent->queueScript(scriptid, world.hand(), (int)a->id);
182 // annoyingly queueScript doesn't reliably tell us if it did anything useful.
183 // TODO: work out the mess which is queueScript's return values etc
184 if (!parent->findScript(scriptid)) return;
186 // fire the associated pointer script too, if necessary
187 // TODO: fuzzie has no idea if this code is remotely correct
188 if (engine.version < 3) {
189 eve = 50;
190 } else {
191 eve = 101; // Pointer Activate 1
193 switch (scriptid) {
194 case 0: eve += 2; break; // deactivate
195 case 1: break; // activate 1
196 case 2: eve += 1; break; // activate 2
197 default: return;
203 if (eve != -1) firePointerScript(eve, a->getParent());
204 } else if (engine.version > 2) {
205 if (holdingWire) {
206 holdingWire = 0;
207 queueScript(113, 0);
208 } else {
209 queueScript(116, 0); // Pointer Clicked Background
212 } else if (event.button == buttonright) {
213 if (editAgent) {
214 editAgent.clear();
215 return;
218 if (world.paused) return; // TODO: wrong?
220 // picking up and dropping are implictly handled by the scripts (well,
221 // messages) 4 and 5 TODO: check if this is correct behaviour, one issue
222 // is that this isn't instant, another is the messages might only be
223 // fired in c2e when you use MESG WRIT, in which case we'll need to
224 // manually set carrying to NULL and a here, respectively - fuzzie
225 if (carrying) {
226 if (engine.version == 1) {
227 // ensure there's a room to drop into, in C1
228 MetaRoom* m = world.map.metaRoomAt(x, y);
229 if (!m) return;
230 shared_ptr<Room> r = m->nextFloorFromPoint(x, y);
231 if (!r) return;
233 carrying->queueScript(5, this); // drop
235 return;
236 } else if (!carrying->suffercollisions() || carrying->validInRoomSystem()) {
237 carrying->queueScript(5, this); // drop
239 // TODO: is this the correct check?
240 if (carrying->sufferphysics() && carrying->suffercollisions()) {
241 // TODO: do this in the pointer agent?
242 carrying->velx.setFloat(velx.getFloat());
243 carrying->vely.setFloat(vely.getFloat());
246 return;
249 // TODO: some kind of "fail to drop" animation/sound?
250 } else {
251 Agent *a = world.agentAt(x, y, false, true);
252 if (a) {
253 a->queueScript(4, this); // pickup
256 } else if (event.button == buttonmiddle) {
257 std::vector<shared_ptr<Room> > rooms = world.map.roomsAt(x, y);
258 if (rooms.size() > 0) std::cout << "Room at cursor is " << rooms[0]->id << std::endl;
259 Agent *a = world.agentAt(x, y, true);
260 if (a)
261 std::cout << "Agent under mouse is " << a->identify();
262 else
263 std::cout << "No agent under cursor";
264 std::cout << std::endl;
269 /* vim: set noet: */