add wraparound support to C2 physics
[openc2e.git] / Bubble.cpp
blobdcfd128b51611ca82e84182bc5adc9dd669ed607
1 /*
2 * Bubble.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Sat Apr 26 2008.
6 * Copyright (c) 2008 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 "Bubble.h"
21 #include "World.h"
22 #include "Engine.h"
23 #include "Backend.h"
25 // class BubblePart *ourPart;
27 Bubble::Bubble(unsigned char family, unsigned char genus, unsigned short species, unsigned int plane,
28 std::string spritefile, unsigned int firstimage, unsigned int imagecount,
29 unsigned int tx, unsigned int ty, unsigned int twidth, unsigned int theight,
30 unsigned int bgcolour, unsigned int tcolour)
31 : CompoundAgent(family, genus, species, plane, spritefile, firstimage, imagecount) {
32 ourPart = new BubblePart(this, 1, tx, ty);
33 addPart(ourPart);
34 ourPart->textwidth = twidth;
35 ourPart->textheight = theight;
36 ourPart->backgroundcolour = bgcolour;
37 ourPart->textcolour = tcolour;
39 ourPart->editable = false;
42 void Bubble::setText(std::string s) {
43 ourPart->setText(s);
46 std::string Bubble::getText() {
47 return ourPart->text;
50 void Bubble::setEditing(bool e) {
51 ourPart->editable = e;
52 if (e)
53 world.setFocus(ourPart); // gain focus
54 else if (world.focusagent == AgentRef(this) && world.focuspart == ourPart->id)
55 world.setFocus(0); // lose focus
58 void Bubble::setTimeout(unsigned int t) {
59 timeout = t;
62 void Bubble::tick() {
63 CompoundAgent::tick();
65 if (!paused && timeout) {
66 timeout--;
67 if (timeout == 0) kill();
71 void Bubble::turnIntoSpeech() {
72 newBubble((Agent *)world.hand(), true, getText());
74 // TODO: announce via shou
75 // TODO: add to speech history
77 kill();
80 Bubble *Bubble::newBubble(Agent *parent, bool speech, std::string text) {
81 assert(engine.version < 3);
83 assert(parent);
85 bool leftside = false;
86 // TODO: cope with wrap
87 if (parent->x - world.camera.getX() < world.camera.getWidth() / 2) leftside = true;
89 int pose;
90 if (engine.version == 1) {
91 // C1 poses
92 if (speech)
93 pose = leftside ? 10 : 9;
94 else
95 pose = leftside ? 12 : 11;
96 } else {
97 // C2 poses
98 // TODO: extend to fit text
99 if (speech)
100 pose = leftside ? 21 : 18;
101 else
102 pose = leftside ? 27 : 24;
105 int plane;
106 if (engine.version == 1) {
107 plane = 9000;
108 } else {
109 // C2
110 if (parent == (Agent *)world.hand())
111 plane = 9999;
112 else
113 plane = 9995;
116 int xoffset = (engine.version == 1) ? 6 : 8;
117 int yoffset = (engine.version == 1) ? 3 : 8;
118 int twidth = (engine.version == 1) ? 144 : 95; // TODO: extend to fit text
120 Bubble *ourBubble = new Bubble(2, 1, speech ? 2 : 1, plane, "syst", pose, engine.version == 1 ? 1 : 3, xoffset, yoffset, twidth, 12, 0, 0);
121 ourBubble->finishInit();
123 ourBubble->attr = 32; // floating
124 ourBubble->floatTo(parent);
126 // TODO: fix positioning
127 if (leftside)
128 ourBubble->moveTo(parent->x + parent->getWidth() - 2, parent->y - ourBubble->getHeight());
129 else
130 ourBubble->moveTo(parent->x - ourBubble->getWidth() + 2, parent->y - ourBubble->getHeight());
132 ourBubble->setText(text);
134 if (speech)
135 ourBubble->setTimeout(2 * 10); // TODO: 2s is probably not right
136 else
137 ourBubble->setEditing(true);
139 return ourBubble;
143 class BubblePart : public CompoundPart {
144 bool editable;
145 std::string text;
146 unsigned int textwidth, textheight;
147 unsigned int backgroundcolour, textcolour;
150 BubblePart::BubblePart(Bubble *p, unsigned int _id, int x, int y) : CompoundPart(p, _id, x, y, 1) {
151 editable = false;
152 textwidth = 0;
153 textheight = 0;
154 textoffset = 0; // doesn't matter when text is empty
157 void BubblePart::partRender(class Surface *renderer, int xoffset, int yoffset) {
158 renderer->renderText(xoffset + x + textoffset, yoffset + y, text, textcolour, backgroundcolour);
161 void BubblePart::gainFocus() {
162 assert(editable);
165 void BubblePart::loseFocus() {
166 parent->kill();
169 void BubblePart::handleKey(char c) {
170 // TODO: reject invalid chars
172 setText(text + c);
175 void BubblePart::handleSpecialKey(char c) {
176 switch (c) {
177 case 8: // backspace
178 if (text.size() == 0) { loseFocus(); return; }
179 { std::string s = text;
180 s.erase(s.begin() + (s.size() - 1));
181 setText(s); }
182 if (text.size() == 0) { loseFocus(); return; }
183 break;
185 case 13: // return
186 ((Bubble *)parent)->turnIntoSpeech(); // TODO: omg hax
187 break;
191 void BubblePart::setText(std::string s) {
192 unsigned int twidth = engine.backend->textWidth(s);
193 if (twidth > textwidth) return;
195 text = s;
196 textoffset = (textwidth - twidth) / 2;
199 /* vim: set noet: */