1
2#include <math.h>
3#include <stdio.h>
4#include <stdlib.h>
5
6#include <Message.h>
7#include <MessageQueue.h>
8#include <MessageRunner.h>
9#include <Messenger.h>
10#include <Rect.h>
11#include <String.h>
12
13#include "WindowLayer.h"
14
15#include "ClientLooper.h"
16
17#define SLOW_DRAWING 0
18
19#define SPEED 2.0
20
21// random_number_between
22static float
23random_number_between(float v1, float v2)
24{
25	if (v1 < v2)
26		return v1 + fmod(rand() / 1000.0, (v2 - v1));
27	else if (v2 < v1)
28		return v2 + fmod(rand() / 1000.0, (v1 - v2));
29	return v1;
30}
31
32// init_polygon
33static void
34init_polygon(const BRect& b, point* polygon)
35{
36	polygon[0].x = b.left;
37	polygon[0].y = b.top;
38	polygon[0].direction_x = random_number_between(-SPEED, SPEED);
39	polygon[0].direction_y = random_number_between(-SPEED, SPEED);
40	polygon[1].x = b.right;
41	polygon[1].y = b.top;
42	polygon[1].direction_x = random_number_between(-SPEED, SPEED);
43	polygon[1].direction_y = random_number_between(-SPEED, SPEED);
44	polygon[2].x = b.right;
45	polygon[2].y = b.bottom;
46	polygon[2].direction_x = random_number_between(-SPEED, SPEED);
47	polygon[2].direction_y = random_number_between(-SPEED, SPEED);
48	polygon[3].x = b.left;
49	polygon[3].y = b.bottom;
50	polygon[3].direction_x = random_number_between(-SPEED, SPEED);
51	polygon[3].direction_y = random_number_between(-SPEED, SPEED);
52}
53
54// morph
55static inline void
56morph(double* value, double* direction, double min, double max)
57{
58	*value += *direction;
59	if (*value < min) {
60		*value = min;
61		*direction = -*direction;
62	} else if (*value > max) {
63		*value = max;
64		*direction = -*direction;
65	}
66}
67
68// morph_polygon
69static inline void
70morph_polygon(const BRect& b, point* polygon)
71{
72	morph(&polygon[0].x, &polygon[0].direction_x, b.left, b.right);
73	morph(&polygon[1].x, &polygon[1].direction_x, b.left, b.right);
74	morph(&polygon[2].x, &polygon[2].direction_x, b.left, b.right);
75	morph(&polygon[3].x, &polygon[3].direction_x, b.left, b.right);
76	morph(&polygon[0].y, &polygon[0].direction_y, b.top, b.bottom);
77	morph(&polygon[1].y, &polygon[1].direction_y, b.top, b.bottom);
78	morph(&polygon[2].y, &polygon[2].direction_y, b.top, b.bottom);
79	morph(&polygon[3].y, &polygon[3].direction_y, b.top, b.bottom);
80}
81
82
83
84// constructor
85ClientLooper::ClientLooper(const char* name, WindowLayer* serverWindow)
86	: BLooper("", B_DISPLAY_PRIORITY),
87	  fServerWindow(serverWindow),
88	  fViewCount(0)
89{
90	BString clientName(name);
91	clientName << " client";
92	SetName(clientName.String());
93
94	BMessenger messenger(this);
95	fTicker = new BMessageRunner(messenger, new BMessage(MSG_TICK), 40000);
96
97	init_polygon(BRect(0, 0, 100, 100), fPolygon);
98}
99
100// destructor
101ClientLooper::~ClientLooper()
102{
103	delete fTicker;
104}
105
106// MessageReceived
107void
108ClientLooper::MessageReceived(BMessage* message)
109{
110	switch (message->what) {
111		case MSG_UPDATE:
112
113			fServerWindow->PostMessage(MSG_BEGIN_UPDATE);
114
115			for (int32 i = 0; i < fViewCount; i++) {
116				// the client is slow
117//				snooze(40000L);
118				// send the command to redraw a view
119				if (i == 5) {
120					_DrawAnimatedLayer(i);
121				} else {
122					BMessage command(MSG_DRAWING_COMMAND);
123					command.AddInt32("token", i);
124					fServerWindow->PostMessage(&command);
125				}
126			}
127
128			fServerWindow->PostMessage(MSG_END_UPDATE);
129
130			break;
131		case MSG_VIEWS_ADDED: {
132			int32 count;
133			if (message->FindInt32("count", &count) >= B_OK) {
134				fViewCount += count;
135			}
136			break;
137		}
138		case MSG_VIEWS_REMOVED: {
139			int32 count;
140			if (message->FindInt32("count", &count) >= B_OK)
141				fViewCount -= count;
142			break;
143		}
144
145		case MSG_WINDOW_HIDDEN:
146			// there is no way we're going to accept this
147			// discrimination for longer than 2 seconds!
148			snooze(2000000);
149			fServerWindow->PostMessage(MSG_SHOW);
150			break;
151
152		case MSG_TICK: {
153			BMessage invalidate(MSG_INVALIDATE_VIEW);
154			invalidate.AddInt32("token", 5);
155			fServerWindow->PostMessage(&invalidate);
156
157			morph_polygon(BRect(0, 0, 100, 100), fPolygon);
158			break;
159		}
160
161		default:
162			BLooper::MessageReceived(message);
163			break;
164	}
165}
166
167// _DrawAnimatedLayer
168void
169ClientLooper::_DrawAnimatedLayer(int32 token)
170{
171	BMessage message(MSG_DRAW_POLYGON);
172	message.AddInt32("token", token);
173
174	message.AddPoint("point", BPoint(fPolygon[0].x, fPolygon[0].y));
175	message.AddPoint("point", BPoint(fPolygon[1].x, fPolygon[1].y));
176	message.AddPoint("point", BPoint(fPolygon[2].x, fPolygon[2].y));
177	message.AddPoint("point", BPoint(fPolygon[3].x, fPolygon[3].y));
178
179	fServerWindow->PostMessage(&message);
180}
181
182