From f9d411ace8dd4cd204b5083a3d884b956df2a0d4 Mon Sep 17 00:00:00 2001 From: fuzzie Date: Sat, 26 Apr 2008 22:14:06 +0000 Subject: [PATCH] add hacky implementation of C1 speech/thought bubbles, unfinished git-svn-id: svn://openc2e.ccdevnet.org/openc2e/trunk@1830 5a3b5b51-85f2-0310-b56e-886e3cf1dda3 --- Bubble.cpp | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Bubble.h | 76 ++++++++++++++++++++++++++ CMakeLists.txt | 1 + CompoundAgent.cpp | 2 + Engine.cpp | 4 ++ PointerAgent.cpp | 25 +++++++++ PointerAgent.h | 2 + 7 files changed, 271 insertions(+) create mode 100644 Bubble.cpp create mode 100644 Bubble.h diff --git a/Bubble.cpp b/Bubble.cpp new file mode 100644 index 0000000..8d45a08 --- /dev/null +++ b/Bubble.cpp @@ -0,0 +1,161 @@ +/* + * Bubble.cpp + * openc2e + * + * Created by Alyssa Milburn on Sat Apr 26 2008. + * Copyright (c) 2008 Alyssa Milburn. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#include "Bubble.h" +#include "World.h" +#include "Engine.h" +#include "Backend.h" + +// class BubblePart *ourPart; + +Bubble::Bubble(unsigned char family, unsigned char genus, unsigned short species, unsigned int plane, + std::string spritefile, unsigned int firstimage, unsigned int imagecount, + unsigned int tx, unsigned int ty, unsigned int twidth, unsigned int theight, + unsigned int bgcolour, unsigned int tcolour) + : CompoundAgent(family, genus, species, plane, spritefile, firstimage, imagecount) { + ourPart = new BubblePart(this, 1, tx, ty); + addPart(ourPart); + ourPart->textwidth = twidth; + ourPart->textheight = theight; + ourPart->backgroundcolour = bgcolour; + ourPart->textcolour = tcolour; + + ourPart->editable = false; +} + +void Bubble::setText(std::string s) { + ourPart->setText(s); +} + +std::string Bubble::getText() { + return ourPart->text; +} + +void Bubble::setEditing(bool e) { + ourPart->editable = e; + if (e) + world.setFocus(ourPart); // gain focus + else if (world.focusagent == AgentRef(this) && world.focuspart == ourPart->id) + world.setFocus(0); // lose focus +} + +void Bubble::setTimeout(unsigned int t) { + timeout = t; +} + +void Bubble::tick() { + CompoundAgent::tick(); + + if (!paused && timeout) { + timeout--; + if (timeout == 0) kill(); + } +} + +#include "PointerAgent.h" +void Bubble::turnIntoSpeech() { + // TODO: this should really really really be handled elsewhere, not in Bubble!!!! + + // TODO: C2 support + assert(engine.version == 1); + + bool leftside = false; + // TODO: cope with wrap + if (world.hand()->x - world.camera.getX() < world.camera.getWidth() / 2) leftside = true; + + // TODO: are 1/0 good colours? + Bubble *ourSpeechBubble = new Bubble(2, 1, 2, 9000, "syst", leftside ? 10 : 9, 1, 6, 3, 144, 12, 1, 0); + ourSpeechBubble->finishInit(); + + ourSpeechBubble->attr = 32; // floating + ourSpeechBubble->floatTo(world.hand()); + + // TODO: fix positioning + if (leftside) + ourSpeechBubble->moveTo(world.hand()->x + world.hand()->getWidth() - 2, world.hand()->y - getHeight()); + else + ourSpeechBubble->moveTo(world.hand()->x - getWidth() + 2, world.hand()->y - getHeight()); + + ourSpeechBubble->setText(getText()); + + ourSpeechBubble->setTimeout(2 * 10); // TODO: 2s is probably not right + // TODO: announce via shou + // TODO: add to speech history + + kill(); +} + +/* + class BubblePart : public CompoundPart { + bool editable; + std::string text; + unsigned int textwidth, textheight; + unsigned int backgroundcolour, textcolour; +*/ + +BubblePart::BubblePart(Bubble *p, unsigned int _id, int x, int y) : CompoundPart(p, _id, x, y, 1) { + editable = false; + textwidth = 0; + textheight = 0; + textoffset = 0; // doesn't matter when text is empty +} + +void BubblePart::partRender(class Surface *renderer, int xoffset, int yoffset) { + renderer->renderText(xoffset + x + textoffset, yoffset + y, text, textcolour, backgroundcolour); +} + +void BubblePart::gainFocus() { + assert(editable); +} + +void BubblePart::loseFocus() { + parent->kill(); +} + +void BubblePart::handleKey(char c) { + // TODO: reject invalid chars + + setText(text + c); +} + +void BubblePart::handleSpecialKey(char c) { + switch (c) { + case 8: // backspace + if (text.size() == 0) { loseFocus(); return; } + { std::string s = text; + s.erase(s.begin() + (s.size() - 1)); + setText(s); } + if (text.size() == 0) { loseFocus(); return; } + break; + + case 13: // return + ((Bubble *)parent)->turnIntoSpeech(); // TODO: omg hax + break; + } +} + +void BubblePart::setText(std::string s) { + unsigned int twidth = engine.backend->textWidth(s); + if (twidth > textwidth) return; + + text = s; + textoffset = (textwidth - twidth) / 2; +} + +/* vim: set noet: */ diff --git a/Bubble.h b/Bubble.h new file mode 100644 index 0000000..32cd378 --- /dev/null +++ b/Bubble.h @@ -0,0 +1,76 @@ +/* + * Bubble.h + * openc2e + * + * Created by Alyssa Milburn on Sat Apr 26 2008. + * Copyright (c) 2008 Alyssa Milburn. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#include "CompoundAgent.h" + +#ifndef _C2E_BUBBLE_H +#define _C2E_BUBBLE_H + +class Bubble : public CompoundAgent { + friend class BubblePart; + +protected: + class BubblePart *ourPart; + unsigned int timeout; + + void turnIntoSpeech(); + +public: + Bubble(unsigned char family, unsigned char genus, unsigned short species, unsigned int plane, + std::string spritefile, unsigned int firstimage, unsigned int imagecount, + unsigned int tx, unsigned int ty, unsigned int twidth, unsigned int theight, + unsigned int bgcolour, unsigned int tcolour); + + void setText(std::string s); + std::string getText(); + + void setEditing(bool e); + + void setTimeout(unsigned int i); + void tick(); +}; + +class BubblePart : public CompoundPart { + friend class Bubble; + +protected: + BubblePart(Bubble *p, unsigned int _id, int x, int y); + + bool editable; + std::string text; + unsigned int textwidth, textheight; + unsigned int textoffset; + unsigned int backgroundcolour, textcolour; + + void setText(std::string s); + +public: + void partRender(class Surface *renderer, int xoffset, int yoffset); + unsigned int getWidth() { return textwidth; } + unsigned int getHeight() { return textheight; } + + bool canGainFocus() { return editable; } + void gainFocus(); + void loseFocus(); + void handleKey(char c); + void handleSpecialKey(char c); +}; + +#endif +/* vim: set noet: */ diff --git a/CMakeLists.txt b/CMakeLists.txt index 03b29ae..6fa33e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ SET(OPENC2E_CORE Blackboard.cpp blkImage.cpp bmpImage.cpp + Bubble.cpp bytecode.cpp c16Image.cpp c2eBrain.cpp diff --git a/CompoundAgent.cpp b/CompoundAgent.cpp index 014ab60..daa7baa 100644 --- a/CompoundAgent.cpp +++ b/CompoundAgent.cpp @@ -70,6 +70,8 @@ CompoundAgent::CompoundAgent(unsigned char _family, unsigned char _genus, unsign CompoundPart *p = new DullPart(this, 0, spritefile, firstimage, 0, 0, 0); caos_assert(p); addPart(p); + + setZOrder(plane); // because addPart zots zorder for c1/c2, TODO: make saner? for (unsigned int i = 0; i < 6; i++) { hotspots[i].left = -1; hotspots[i].right = -1; hotspots[i].top = -1; diff --git a/Engine.cpp b/Engine.cpp index 9465e07..4ae24c5 100644 --- a/Engine.cpp +++ b/Engine.cpp @@ -384,6 +384,10 @@ void Engine::handleKeyDown(SomeEvent &event) { case 'd': d_down = true; break; } + if (version < 3 && !world.focusagent) { + world.hand()->makeNewSpeechBubble(); + } + // tell the agent with keyboard focus if (world.focusagent) { CompoundPart *t = world.focusagent.get()->part(world.focuspart); diff --git a/PointerAgent.cpp b/PointerAgent.cpp index 89e9e8d..449c2a0 100644 --- a/PointerAgent.cpp +++ b/PointerAgent.cpp @@ -266,4 +266,29 @@ void PointerAgent::handleEvent(SomeEvent &event) { } } +#include "Bubble.h" + +void PointerAgent::makeNewSpeechBubble() { + if (engine.version != 1) return; // TODO: C2 support + + bool leftside = false; + // TODO: cope with wrap + if (x - world.camera.getX() < world.camera.getWidth() / 2) leftside = true; + + // TODO: are 1/0 good colours? + Bubble *ourSpeechBubble = new Bubble(2, 1, 1, 9000, "syst", leftside ? 12 : 11, 1, 6, 3, 144, 12, 1, 0); + ourSpeechBubble->finishInit(); + + ourSpeechBubble->attr = 32; // floating + ourSpeechBubble->floatTo(this); + + // TODO: fix positioning + if (leftside) + ourSpeechBubble->moveTo(x + getWidth() - 2, y - ourSpeechBubble->getHeight()); + else + ourSpeechBubble->moveTo(x - ourSpeechBubble->getWidth() + 2, y - ourSpeechBubble->getHeight()); + + ourSpeechBubble->setEditing(true); +} + /* vim: set noet: */ diff --git a/PointerAgent.h b/PointerAgent.h index d06ee60..fddd182 100644 --- a/PointerAgent.h +++ b/PointerAgent.h @@ -48,6 +48,8 @@ public: void handleEvent(SomeEvent &event); void setHotspot(int, int); + void makeNewSpeechBubble(); + int pointerX() { return x + hotspotx; } int pointerY() { return y + hotspoty; } }; -- 2.11.4.GIT