mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 17:03:58 +02:00
Merge pull request #146 from ey6es/master
Basic text chat. This adds fields to AvatarData and will thus break existing clients.
This commit is contained in:
commit
d1589270e5
8 changed files with 236 additions and 4 deletions
|
@ -51,7 +51,7 @@ void attachAvatarDataToAgent(Agent *newAgent) {
|
|||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR_MIXER, AVATAR_LISTEN_PORT);
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
|
|
|
@ -517,6 +517,7 @@ float Audio::getInputLoudness() const {
|
|||
void Audio::render(int screenWidth, int screenHeight)
|
||||
{
|
||||
if (initialized) {
|
||||
glLineWidth(3);
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(1,1,1);
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@ bool usingBigSphereCollisionTest = true;
|
|||
|
||||
char iris_texture_file[] = "resources/images/green_eye.png";
|
||||
|
||||
float chatMessageScale = 0.00025;
|
||||
float chatMessageHeight = 0.4;
|
||||
|
||||
vector<unsigned char> iris_texture;
|
||||
unsigned int iris_texture_width = 512;
|
||||
unsigned int iris_texture_height = 256;
|
||||
|
@ -631,6 +634,45 @@ void Avatar::render(bool lookingInMirror) {
|
|||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
if (!_chatMessage.empty()) {
|
||||
float width = 0;
|
||||
float lastWidth;
|
||||
for (string::iterator it = _chatMessage.begin(); it != _chatMessage.end(); it++) {
|
||||
width += (lastWidth = glutStrokeWidth(GLUT_STROKE_ROMAN, *it)*chatMessageScale);
|
||||
}
|
||||
glPushMatrix();
|
||||
|
||||
// extract the view direction from the modelview matrix: transform (0, 0, 1) by the
|
||||
// transpose of the modelview to get its direction in world space, then use the X/Z
|
||||
// components to determine the angle
|
||||
float modelview[16];
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, modelview);
|
||||
|
||||
glTranslatef(_position.x, _position.y + chatMessageHeight, _position.z);
|
||||
glRotatef(atan2(-modelview[2], -modelview[10]) * 180 / PI, 0, 1, 0);
|
||||
glTranslatef(width * 0.5, 0, 0);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
if (_keyState == NoKeyDown) {
|
||||
drawtext(0, 0, chatMessageScale, 180, 1.0, 0, _chatMessage.c_str(), 0, 1, 0);
|
||||
|
||||
} else {
|
||||
// rather than using substr and allocating a new string, just replace the last
|
||||
// character with a null, then restore it
|
||||
int lastIndex = _chatMessage.size() - 1;
|
||||
char lastChar = _chatMessage[lastIndex];
|
||||
_chatMessage[lastIndex] = '\0';
|
||||
drawtext(0, 0, chatMessageScale, 180, 1.0, 0, _chatMessage.c_str(), 0, 1, 0);
|
||||
_chatMessage[lastIndex] = lastChar;
|
||||
glTranslatef(lastWidth - width, 0, 0);
|
||||
drawtext(0, 0, chatMessageScale, 180, 3.0,
|
||||
0, _chatMessage.c_str() + lastIndex, 0, 1, 0);
|
||||
}
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1227,4 +1269,4 @@ glm::vec3 Avatar::getGravity(glm::vec3 pos) {
|
|||
// If flying in space, turn gravity OFF
|
||||
return glm::vec3(0.f, 0.f, 0.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
78
interface/src/ChatEntry.cpp
Normal file
78
interface/src/ChatEntry.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
//
|
||||
// ChatEntry.cpp
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 4/24/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "ChatEntry.h"
|
||||
#include "Util.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
const int MAX_CONTENT_LENGTH = 140;
|
||||
|
||||
void ChatEntry::clear () {
|
||||
contents.clear();
|
||||
cursorPos = 0;
|
||||
}
|
||||
|
||||
bool ChatEntry::key(unsigned char k) {
|
||||
switch (k) {
|
||||
case '\r':
|
||||
return false;
|
||||
|
||||
case '\b':
|
||||
if (cursorPos != 0) {
|
||||
contents.erase(cursorPos - 1, 1);
|
||||
cursorPos--;
|
||||
}
|
||||
return true;
|
||||
|
||||
case 127: // delete
|
||||
if (cursorPos < contents.size()) {
|
||||
contents.erase(cursorPos, 1);
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
if (contents.size() != MAX_CONTENT_LENGTH) {
|
||||
contents.insert(cursorPos, 1, k);
|
||||
cursorPos++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ChatEntry::specialKey(unsigned char k) {
|
||||
switch (k) {
|
||||
case GLUT_KEY_LEFT:
|
||||
if (cursorPos != 0) {
|
||||
cursorPos--;
|
||||
}
|
||||
break;
|
||||
|
||||
case GLUT_KEY_RIGHT:
|
||||
if (cursorPos != contents.size()) {
|
||||
cursorPos++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ChatEntry::render(int screenWidth, int screenHeight) {
|
||||
drawtext(20, screenHeight - 150, 0.10, 0, 1.0, 0, contents.c_str(), 1, 1, 1);
|
||||
|
||||
float width = 0;
|
||||
for (string::iterator it = contents.begin(), end = it + cursorPos; it != end; it++) {
|
||||
width += glutStrokeWidth(GLUT_STROKE_ROMAN, *it)*0.10;
|
||||
}
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2f(20 + width, screenHeight - 165);
|
||||
glVertex2f(20 + width, screenHeight - 150);
|
||||
glEnd();
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
}
|
33
interface/src/ChatEntry.h
Normal file
33
interface/src/ChatEntry.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// ChatEntry.h
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 4/24/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__ChatEntry__
|
||||
#define __interface__ChatEntry__
|
||||
|
||||
#include <string>
|
||||
|
||||
class ChatEntry {
|
||||
public:
|
||||
|
||||
const std::string& getContents () const { return contents; }
|
||||
|
||||
void clear ();
|
||||
|
||||
bool key(unsigned char k);
|
||||
void specialKey(unsigned char k);
|
||||
|
||||
void render(int screenWidth, int screenHeight);
|
||||
|
||||
private:
|
||||
|
||||
std::string contents;
|
||||
|
||||
int cursorPos;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__ChatEntry__) */
|
|
@ -64,6 +64,7 @@
|
|||
#include "MenuColumn.h"
|
||||
#include "Menu.h"
|
||||
#include "Camera.h"
|
||||
#include "ChatEntry.h"
|
||||
#include "Avatar.h"
|
||||
#include "Particle.h"
|
||||
#include "Texture.h"
|
||||
|
@ -180,6 +181,9 @@ int mousePressed = 0; // true if mouse has been pressed (clear when finished)
|
|||
Menu menu; // main menu
|
||||
int menuOn = 1; // Whether to show onscreen menu
|
||||
|
||||
ChatEntry chatEntry; // chat entry field
|
||||
bool chatEntryOn = false; // Whether to show the chat entry
|
||||
|
||||
struct HandController
|
||||
{
|
||||
bool enabled;
|
||||
|
@ -1004,6 +1008,11 @@ void display(void)
|
|||
menu.render(WIDTH,HEIGHT);
|
||||
}
|
||||
|
||||
// Show chat entry field
|
||||
if (::chatEntryOn) {
|
||||
chatEntry.render(WIDTH, HEIGHT);
|
||||
}
|
||||
|
||||
// Stats at upper right of screen about who domain server is telling us about
|
||||
glPointSize(1.0f);
|
||||
char agents[100];
|
||||
|
@ -1349,6 +1358,11 @@ void specialkeyUp(int k, int x, int y) {
|
|||
|
||||
void specialkey(int k, int x, int y)
|
||||
{
|
||||
if (::chatEntryOn) {
|
||||
chatEntry.specialKey(k);
|
||||
return;
|
||||
}
|
||||
|
||||
if (k == GLUT_KEY_UP || k == GLUT_KEY_DOWN || k == GLUT_KEY_LEFT || k == GLUT_KEY_RIGHT) {
|
||||
if (k == GLUT_KEY_UP) {
|
||||
if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) myAvatar.setDriveKeys(UP, 1);
|
||||
|
@ -1374,6 +1388,11 @@ void specialkey(int k, int x, int y)
|
|||
|
||||
|
||||
void keyUp(unsigned char k, int x, int y) {
|
||||
if (::chatEntryOn) {
|
||||
myAvatar.setKeyState(AvatarData::NoKeyDown);
|
||||
return;
|
||||
}
|
||||
|
||||
if (k == 'e') myAvatar.setDriveKeys(UP, 0);
|
||||
if (k == 'c') myAvatar.setDriveKeys(DOWN, 0);
|
||||
if (k == 'w') myAvatar.setDriveKeys(FWD, 0);
|
||||
|
@ -1385,6 +1404,19 @@ void keyUp(unsigned char k, int x, int y) {
|
|||
|
||||
void key(unsigned char k, int x, int y)
|
||||
{
|
||||
if (::chatEntryOn) {
|
||||
if (chatEntry.key(k)) {
|
||||
myAvatar.setKeyState(k == '\b' || k == 127 ? // backspace or delete
|
||||
AvatarData::DeleteKeyDown : AvatarData::InsertKeyDown);
|
||||
myAvatar.setChatMessage(string(chatEntry.getContents().size(), 'X'));
|
||||
|
||||
} else {
|
||||
myAvatar.setChatMessage(chatEntry.getContents());
|
||||
chatEntry.clear();
|
||||
::chatEntryOn = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Process keypresses
|
||||
if (k == 'q' || k == 'Q') ::terminate();
|
||||
|
@ -1451,6 +1483,12 @@ void key(unsigned char k, int x, int y)
|
|||
if (k == 'g') renderPitchRate += KEYBOARD_PITCH_RATE;
|
||||
if (k == 'a') myAvatar.setDriveKeys(ROT_LEFT, 1);
|
||||
if (k == 'd') myAvatar.setDriveKeys(ROT_RIGHT, 1);
|
||||
|
||||
if (k == '\r') {
|
||||
::chatEntryOn = true;
|
||||
myAvatar.setKeyState(AvatarData::NoKeyDown);
|
||||
myAvatar.setChatMessage(string());
|
||||
}
|
||||
}
|
||||
|
||||
// Receive packets from other agents/servers and decide what to do with them!
|
||||
|
@ -1659,7 +1697,12 @@ int main(int argc, const char * argv[])
|
|||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
AgentList::createInstance(AGENT_TYPE_AVATAR);
|
||||
unsigned int listenPort = AGENT_SOCKET_LISTEN_PORT;
|
||||
const char* portStr = getCmdOption(argc, argv, "--listenPort");
|
||||
if (portStr) {
|
||||
listenPort = atoi(portStr);
|
||||
}
|
||||
AgentList::createInstance(AGENT_TYPE_AVATAR, listenPort);
|
||||
|
||||
gettimeofday(&applicationStartupTime, NULL);
|
||||
const char* domainIP = getCmdOption(argc, argv, "--domain");
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "AvatarData.h"
|
||||
#include "avatars_Log.h"
|
||||
|
||||
using namespace std;
|
||||
using avatars_lib::printLog;
|
||||
|
||||
|
||||
|
@ -49,7 +50,8 @@ AvatarData::AvatarData() :
|
|||
_cameraFov(0.0f),
|
||||
_cameraAspectRatio(0.0f),
|
||||
_cameraNearClip(0.0f),
|
||||
_cameraFarClip(0.0f) {
|
||||
_cameraFarClip(0.0f),
|
||||
_keyState(NoKeyDown) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -112,7 +114,14 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
|
|||
memcpy(destinationBuffer, &_cameraFarClip, sizeof(_cameraFarClip));
|
||||
destinationBuffer += sizeof(_cameraFarClip);
|
||||
|
||||
// key state
|
||||
*destinationBuffer++ = _keyState;
|
||||
|
||||
// chat message
|
||||
*destinationBuffer++ = _chatMessage.size();
|
||||
memcpy(destinationBuffer, _chatMessage.data(), _chatMessage.size() * sizeof(char));
|
||||
destinationBuffer += _chatMessage.size() * sizeof(char);
|
||||
|
||||
return destinationBuffer - bufferStart;
|
||||
}
|
||||
|
||||
|
@ -168,6 +177,14 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
memcpy(&_cameraFarClip, sourceBuffer, sizeof(_cameraFarClip));
|
||||
sourceBuffer += sizeof(_cameraFarClip);
|
||||
|
||||
// key state
|
||||
_keyState = (KeyState)*sourceBuffer++;
|
||||
|
||||
// the rest is a chat message
|
||||
int chatMessageSize = *sourceBuffer++;
|
||||
_chatMessage = string((char*)sourceBuffer, chatMessageSize);
|
||||
sourceBuffer += chatMessageSize * sizeof(char);
|
||||
|
||||
return sourceBuffer - startPosition;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#ifndef __hifi__AvatarData__
|
||||
#define __hifi__AvatarData__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <AgentData.h>
|
||||
|
@ -74,6 +76,16 @@ public:
|
|||
void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; }
|
||||
void setCameraFarClip(float farClip) { _cameraFarClip = farClip; }
|
||||
|
||||
enum KeyState { NoKeyDown, InsertKeyDown, DeleteKeyDown };
|
||||
|
||||
// key state
|
||||
void setKeyState(KeyState s) { _keyState = s; }
|
||||
KeyState keyState() const { return _keyState; }
|
||||
|
||||
// chat message
|
||||
void setChatMessage(const std::string& msg) { _chatMessage = msg; }
|
||||
const std::string& chatMessage () const { return _chatMessage; }
|
||||
|
||||
protected:
|
||||
glm::vec3 _position;
|
||||
glm::vec3 _handPosition;
|
||||
|
@ -105,6 +117,12 @@ protected:
|
|||
float _cameraAspectRatio;
|
||||
float _cameraNearClip;
|
||||
float _cameraFarClip;
|
||||
|
||||
// key state (nothing, down, up, backspace)
|
||||
KeyState _keyState;
|
||||
|
||||
// chat message
|
||||
std::string _chatMessage;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__AvatarData__) */
|
||||
|
|
Loading…
Reference in a new issue