Subversion Repositories spk

Rev

Rev 1 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1 Rev 114
Line 2... Line 2...
2
#include "../common/strutils.h"
2
#include "../common/strutils.h"
3
//---------------------------------------------------------------------------------
3
//---------------------------------------------------------------------------------
4
bool bod_cut_parser::compile(token_stream& is, bob_dom_obinaryfilestream& os)
4
bool bod_cut_parser::compile(token_stream& is, obinaryfilestream& os)
5
{
5
{
6
	os << bob_dom_cut::hdr_begin;
6
	os << bob_dom_cut::HDR_BEGIN;
7
	
7
 
8
	bob_dom_cut *cut=loadCUT(is, &os, true);
8
	bob_dom_cut *cut=loadCUT(is, &os, true);
9
	
9
 
10
	//if(cut)
10
	//if(cut)
11
		//cut->toFile(os);
11
		//cut->toFile(os);
12
	
12
 
13
	delete cut;
13
	delete cut;
14
	
14
 
15
	os << bob_dom_cut::hdr_end;
15
	os << bob_dom_cut::HDR_END;
16
	
16
 
17
	return cut!=NULL;
17
	return cut!=NULL;
18
}
18
}
19
//---------------------------------------------------------------------------------
19
//---------------------------------------------------------------------------------
20
bob_dom_cut * bod_cut_parser::loadCUT(token_stream& is)
20
bob_dom_cut * bod_cut_parser::loadCUT(token_stream& is)
21
{
21
{
22
	bob_dom_obinaryfilestream *dummy=0;
22
	obinaryfilestream *dummy=0;
23
	
23
 
24
	return loadCUT(is, dummy, false);
24
	return loadCUT(is, dummy, false);
25
}
25
}
26
//---------------------------------------------------------------------------------
26
//---------------------------------------------------------------------------------
27
// this is bit weird function as it serves for 2 purposes: it can return loaded cut object
27
// this is bit weird function as it serves for 2 purposes: it can return loaded cut object
28
// or it can directly output parts of cut as it's being loaded
28
// or it can directly output parts of cut as it's being loaded
29
bob_dom_cut * bod_cut_parser::loadCUT(token_stream& is, bob_dom_obinaryfilestream *os, bool bDirectOutput)
29
bob_dom_cut * bod_cut_parser::loadCUT(token_stream& is, obinaryfilestream *os, bool bDirectOutput)
30
{
30
{
31
	bod_text_parser::token *t;
31
	bod_text_parser::token *t;
32
	bob_dom_path *actPath=0;
32
	bob_path *actPath=0;
33
	bob_dom_stat *actStat=0;
33
	bob_stat *actStat=0;
34
	bob_dom_cut *cut=new bob_dom_cut(m_settings);
34
	bob_dom_cut *cut=new bob_dom_cut(m_settings);
35
	
35
 
36
	// used for direct output
36
	// used for direct output
37
	int pathCountOffset;
37
	int pathCountOffset;
38
	int pathCount=0;
38
	int pathCount=0;
39
	
39
 
40
	bool bErrors=false;
40
	bool bErrors=false;
41
	bool bRes=false;
41
	bool bRes=false;
42
	
42
 
43
	while(is.good() && is.tok()->type==token::t_hdrinfo){
43
	while(is.good() && is.tok()->type==token::t_hdrinfo){
44
		if(cut->info.text()!=0)
44
		if(cut->info.text()!=0)
45
			error(is.tok(), S_Warning, "Header info already defined, last value will be used");
45
			error(is.tok(), S_Warning, "Header info already defined, last value will be used");
46
		cut->info.text(is.tok()->text);
46
		cut->info.text(is.tok()->text);
47
		++is;
47
		++is;
48
	}
48
	}
49
 
49
 
50
	do{
50
	do{
51
		// VERSION
51
		// VERSION
52
		t=is.tok();
52
		t=is.tok();
53
		if(t==NULL || t->type!=token::t_text || strcmp(t->text, "VER")!=0)
53
		if(t==NULL || t->type!=token::t_text || strcmp(t->text, "VER")!=0)
54
			{ error(t ? t : is.previous(), S_Error, "Expected version specification"); break; }
54
			{ error(t ? t : is.previous(), S_Error, "Expected version specification"); break; }
55
		
55
 
56
		t=(++is).tok();
56
		t=(++is).tok();
57
		if(t==NULL || t->type!=token::t_colon)
57
		if(t==NULL || t->type!=token::t_colon)
58
			{ error(t ? t : is.previous(), S_Error, "Expected ':' after '%s'", is.previous()->text); break; }
58
			{ error(t ? t : is.previous(), S_Error, "Expected ':' after '%s'", is.previous()->text); break; }
59
		
59
 
60
		if(!checkImmediatePlacement(is.previous(), is.tok())) 
60
		if(!checkImmediatePlacement(is.previous(), is.tok()))
61
			break;
61
			break;
62
		
62
 
63
		if((t=loadValue(++is))==NULL)
63
		if((t=loadValue(++is))==NULL)
64
			break;
64
			break;
65
		if(!isinteger(t->text))
65
		if(!isinteger(t->text))
66
			{ error(t ? t : is.previous(), S_Error, "Expected version number after ':'"); break; }
66
			{ error(t ? t : is.previous(), S_Error, "Expected version number after ':'"); break; }
67
			
67
 
68
		cut->version=atoi(t->text);
68
		cut->version=atoi(t->text);
69
		
69
 
70
		if(cut->version > bob_dom_cut::supported_version)
70
		if(cut->version > bob_dom_cut::supported_version)
71
			error(is.tok(), S_Warning, "File version is %d, supported version is %d", cut->version, bob_dom_cut::supported_version);
71
			error(is.tok(), S_Warning, "File version is %d, supported version is %d", cut->version, bob_dom_cut::supported_version);
72
		
72
 
73
		if(bDirectOutput){
73
		if(bDirectOutput){
74
			cut->info.toFile(*os);
74
			cut->info.toFile(*os);
75
			*os << cut->version; 
75
			*os << cut->version;
76
			/*	
76
			/*
77
				we must output the path count right now, 
77
				we must output the path count right now,
78
				but we will rewrite it once we finish
78
				but we will rewrite it once we finish
79
			*/
79
			*/
80
			pathCountOffset=(int)os->tell();
80
			pathCountOffset=(int)os->tell();
81
			*os << pathCount; 
81
			*os << pathCount;
82
		}
82
		}
83
		
83
 
84
		while(is.good()){
84
		while(is.good()){
85
			t=is.tok();
85
			t=is.tok();
86
			
86
 
87
			if(t->type==token::t_openBracket){
87
			if(t->type==token::t_openCrBracket){
88
				if(actPath==NULL){
88
				if(actPath==NULL){
89
					error(t, S_Error, "Block unexpected here.");
89
					error(t, S_Error, "Block unexpected here.");
90
					break;
90
					break;
91
				}
91
				}
92
				else{
92
				else{
93
					bErrors|=!loadFrame(actPath, ++is); 
93
					bErrors|=!loadFrame(actPath, ++is);
94
				}
94
				}
95
			}
95
			}
96
			
96
 
97
			else{
97
			else{
98
				if(actPath && bDirectOutput){
98
				if(actPath && bDirectOutput){
99
					pathCount++;
99
					pathCount++;
100
					actPath->toFile(*os, cut->version);
100
					actPath->toFile(*os, cut->version);
101
					cut->removeChild(--cut->end());
101
					cut->removeChild(--cut->end());
102
				}
102
				}
103
				if((actPath=loadPath(cut, is))==NULL)
103
				if((actPath=loadPath(cut, is))==NULL)
104
					break;
104
					break;
105
				
105
 
106
				if(!is.good()){
106
				if(!is.good()){
107
					error(is.previous(), S_Error, "Missing Frame declaration after Body declaration");
107
					error(is.previous(), S_Error, "Missing Frame declaration after Body declaration");
108
					break;
108
					break;
109
				}
109
				}
110
			}
110
			}
111
			bRes=!bErrors;
111
			bRes=!bErrors;
112
		}
112
		}
113
	}
113
	}
114
	while(false);
114
	while(false);
115
	
115
 
116
	if(actPath && bDirectOutput){
116
	if(actPath && bDirectOutput){
117
		pathCount++;
117
		pathCount++;
118
		actPath->toFile(*os, cut->version);
118
		actPath->toFile(*os, cut->version);
119
		cut->removeChild(--cut->end());
119
		cut->removeChild(--cut->end());
120
	}
120
	}
121
	
121
 
122
	if(bRes==false){
122
	if(bRes==false){
123
		delete cut;
123
		delete cut;
124
		return NULL;
124
		return NULL;
125
	}
125
	}
126
	else{
126
	else{
127
		if(bDirectOutput){	
127
		if(bDirectOutput){
128
			size_t endPos=os->tell();
128
			size_t endPos=os->tell();
129
			os->seek(pathCountOffset, bob_filestream::seek_begin);
129
			os->seek(pathCountOffset, mystream::stream_base::seek_begin);
130
			*os << pathCount;
130
			*os << pathCount;
131
			os->seek((int)endPos, bob_filestream::seek_begin);
131
			os->seek((int)endPos, mystream::stream_base::seek_begin);
132
		}
132
		}
133
		return cut;
133
		return cut;
134
	}
134
	}
135
}
135
}
136
//---------------------------------------------------------------------------------
136
//---------------------------------------------------------------------------------
137
bob_dom_path * bod_cut_parser::loadPath(bob_dom_cut *cut, token_stream& is)
137
bob_path * bod_cut_parser::loadPath(bob_dom_cut *cut, token_stream& is)
138
{
138
{
139
	bob_dom_path *path=cut->createChild();
139
	bob_path *path=cut->createChild();
140
 
140
 
141
	bool bRes=false;
141
	bool bRes=false;
142
	
142
 
143
	bod_text_parser::token *t;
143
	bod_text_parser::token *t;
144
	
144
 
145
	do{
145
	do{
146
		t=is.tok();
146
		t=is.tok();
147
		
147
 
148
		// index
148
		// index
149
		if(t==NULL || t->type!=token::t_text || strcmp(t->text, "P")!=0)
149
		if(t==NULL || t->type!=token::t_text || strcmp(t->text, "P")!=0)
150
			{ error(t ? t : is.previous(), S_Error, "Expected body declaration starting with Path ID (P)."); break; }
150
			{ error(t ? t : is.previous(), S_Error, "Expected body declaration starting with Path ID (P)."); break; }
151
		if((t=loadValue(++is))==NULL)
151
		if((t=loadValue(++is))==NULL)
152
			break;
152
			break;
153
		if(!isinteger(t->text))
153
		if(!isinteger(t->text))
154
			{ error(t, S_Error, "Body declaration: Expected number after '%s'", is.previous()->text); break; }
154
			{ error(t, S_Error, "Body declaration: Expected number after '%s'", is.previous()->text); break; }
155
		else
155
		else
156
			path->partIdx=atoi(t->text);
156
			path->partIdx=atoi(t->text);
157
		
157
 
158
		// body id
158
		// body id
159
		t=is.tok();
159
		t=is.tok();
160
		if(t==NULL || t->type!=token::t_text || strcmp(t->text, "B")!=0)
160
		if(t==NULL || t->type!=token::t_text || strcmp(t->text, "B")!=0)
161
			{ error(t ? t : is.previous(), S_Error, "Body declaration: Expected Body ID (B)."); break; }
161
			{ error(t ? t : is.previous(), S_Error, "Body declaration: Expected Body ID (B)."); break; }
162
		if((t=loadValue(++is))==NULL)
162
		if((t=loadValue(++is))==NULL)
Line 164... Line 164...
164
		if(cut->version < 6 && !isinteger(t->text)) {
164
		if(cut->version < 6 && !isinteger(t->text)) {
165
			error(t, S_Error, "Body declaration: body ID is string but cut version is %d. Change version to 6.", cut->version);
165
			error(t, S_Error, "Body declaration: body ID is string but cut version is %d. Change version to 6.", cut->version);
166
			break;
166
			break;
167
		}
167
		}
168
		path->bodyId(t->text);
168
		path->bodyId(t->text);
169
		
169
 
170
		bRes=true;
170
		bRes=true;
171
		
171
 
172
		bool bCockpit=false, bParentIdx=false, bName=false, bNotes=false;
172
		bool bCockpit=false, bParentIdx=false, bName=false, bNotes=false;
173
		
173
 
174
		// cockpit, name, flag, body flag, inner bob, notes
174
		// cockpit, name, flag, body flag, inner bob, notes
175
		while(is.good()){
175
		while(is.good()){
176
			t=is.tok();
176
			t=is.tok();
177
			if(t->type==token::t_openBracket)
177
			if(t->type==token::t_openCrBracket)
178
				break;
178
				break;
179
				
179
 
180
			if(t->type!=token::t_text || strlen(t->text) > 1){
180
			if(t->type!=token::t_text || strlen(t->text) > 1){
181
				error(t, S_Error, "Unexpected here: '%s'", t->getText());
181
				error(t, S_Error, "Unexpected here: '%s'", t->getText());
182
				bRes=false;
182
				bRes=false;
183
				break;
183
				break;
184
			}
184
			}
185
			
185
 
186
			char ch=t->text[0];
186
			char ch=t->text[0];
187
			
187
 
188
			// cockpit index
188
			// cockpit index
189
			if(ch=='C'){
189
			if(ch=='C'){
190
				if((t=loadValue(++is))==NULL)
190
				if((t=loadValue(++is))==NULL)
191
					{ bRes=false; break; }
191
					{ bRes=false; break; }
192
				if(!isinteger(t->text))
192
				if(!isinteger(t->text))
193
					{ error(t, S_Error, "Body declaration: Expected number after '%s'", is.previous()->text); bRes=false; break; }
193
					{ error(t, S_Error, "Body declaration: Expected number after '%s'", is.previous()->text); bRes=false; break; }
194
				
194
 
195
				if(bCockpit)
195
				if(bCockpit)
196
					error(t, S_Warning, "Cockpit index already defined, last value will be used");
196
					error(t, S_Warning, "Cockpit index already defined, last value will be used");
197
				
197
 
198
				bCockpit=true;
198
				bCockpit=true;
199
				path->cockpitIdx=atoi(t->text);
199
				path->cockpitIdx=atoi(t->text);
200
			}
200
			}
201
			// parent index
201
			// parent index
202
			else if(ch=='F'){
202
			else if(ch=='F'){
203
				if((t=loadValue(++is))==NULL)
203
				if((t=loadValue(++is))==NULL)
204
					{ bRes=false; break; }
204
					{ bRes=false; break; }
205
				if(!isinteger(t->text))
205
				if(!isinteger(t->text))
206
					{ error(t, S_Error, "Body declaration: Expected number after '%s'", is.previous()->text); bRes=false; break; }
206
					{ error(t, S_Error, "Body declaration: Expected number after '%s'", is.previous()->text); bRes=false; break; }
207
				
207
 
208
				if(bParentIdx)
208
				if(bParentIdx)
209
					error(t, S_Warning, "Parent index already defined, last value will be used");
209
					error(t, S_Warning, "Parent index already defined, last value will be used");
210
					
210
 
211
				bParentIdx=true;
211
				bParentIdx=true;
212
				path->parentIdx=atoi(t->text);
212
				path->parentIdx=atoi(t->text);
213
			}
213
			}
214
			// name
214
			// name
215
			else if(ch=='N'){
215
			else if(ch=='N'){
216
				const char *name=loadString(++is);
216
				const char *name=loadString(++is);
217
				if(name==0) break;
217
				if(name==0) break;
218
				
218
 
219
				if(bName)
219
				if(bName)
220
					error(t, S_Warning, "Name already defined, last value will be used");
220
					error(t, S_Warning, "Name already defined, last value will be used");
221
				
221
 
222
				bName=true;
222
				bName=true;
223
				path->name.m_text=(char*)name;
223
				path->name.m_text=(char*)name;
224
			}
224
			}
225
			// embedded bob
225
			// embedded bob
226
			else if(ch=='L'){
226
			else if(ch=='L'){
227
				t=(++is).tok();
227
				t=(++is).tok();
228
				if(t==NULL || t->type!=token::t_openBracket)
228
				if(t==NULL || t->type!=token::t_openCrBracket)
229
					{ error(t ? t : is.previous(), S_Error, "Expected beginning of block after '%s'", is.previous()->getText()); bRes=false; break; }
229
					{ error(t ? t : is.previous(), S_Error, "Expected beginning of block after '%s'", is.previous()->getText()); bRes=false; break; }
230
				else{
230
				else{
231
					++is;
231
					++is;
232
					path->bob=loadBOB(is, true);
232
					path->bob=loadBOB(is, true);
233
					if(path->bob==NULL) {
233
					if(path->bob==NULL) {
Line 235... Line 235...
235
					}
235
					}
236
				}
236
				}
237
			}
237
			}
238
			// notes
238
			// notes
239
			else if(ch=='T'){
239
			else if(ch=='T'){
240
				if(loadNote(path, is)==false) 
240
				if(loadNote(path, is)==false)
241
					{ bRes=false; break; }
241
					{ bRes=false; break; }
242
				
242
 
243
				if(bNotes)
243
				if(bNotes)
244
					error(t, S_Warning, "Notes already defined, last definition will be used");
244
					error(t, S_Warning, "Notes already defined, last definition will be used");
245
				
245
 
246
				bNotes=true;
246
				bNotes=true;
247
			}
247
			}
248
			// constants
248
			// constants
249
			else if(ch=='K'){
249
			else if(ch=='K'){
250
				int count;
250
				int count;
251
				bob_dom_constants::constant c;
251
				bob_constants::constant c;
252
				
252
 
253
				if(!loadIntValue(++is, &count)){
253
				if(!loadIntValue(++is, &count)){
254
					bRes=false; break;
254
					bRes=false; break;
255
				}
255
				}
256
				for(int i=0; i < count; i++){
256
				for(int i=0; i < count; i++){
257
					loadIntValue(is, &(c.a));
257
					loadIntValue(is, &(c.a));
258
					if(!loadDoubleValue(is, &(c.b))){
258
					if(!loadDoubleValue(is, &(c.b))){
259
						bRes=false; break;
259
						bRes=false; break;
260
					}
260
					}
261
					path->constants.values.push_back(c);
261
					path->constants.values.push_back(c);
262
				}
262
				}
263
				if(bRes==false) break;	
263
				if(bRes==false) break;
264
			}
264
			}
265
			// last try if it's a body flag (Camera, Light, Direct, v). It must not be followed by semicolon
265
			// last try if it's a body flag (Camera, Light, Direct, v). It must not be followed by semicolon
266
			else{
266
			else{
267
				t=(++is).tok();
267
				t=(++is).tok();
268
				if(t){
268
				if(t){
Line 273... Line 273...
273
				}
273
				}
274
				if(!(ch >='a' && ch<='z' || ch>='A' && ch<='Z'))
274
				if(!(ch >='a' && ch<='z' || ch>='A' && ch<='Z'))
275
					{ error(is.previous(), S_Error, "Invalid Body flag specification '%c': flag must be alphabetic character", ch); bRes=false; break; }
275
					{ error(is.previous(), S_Error, "Invalid Body flag specification '%c': flag must be alphabetic character", ch); bRes=false; break; }
276
				if(ch!='c' && ch!='l' && ch!='d' && ch!='v' && ch!='b' && ch!='j' && ch!='u')
276
				if(ch!='c' && ch!='l' && ch!='d' && ch!='v' && ch!='b' && ch!='j' && ch!='u')
277
					{ error(is.previous(), S_Warning, "Body flag '%c' out of safe limits, known values are 'c', 'l', 's', 'v', 'p', 'j', 'u'", ch); }
277
					{ error(is.previous(), S_Warning, "Body flag '%c' out of safe limits, known values are 'c', 'l', 's', 'v', 'p', 'j', 'u'", ch); }
278
				
278
 
279
				//path->bodyFlag=ch - 'b';
279
				//path->bodyFlag=ch - 'b';
280
				/*
280
				/*
281
					TODO: translate the char into body flag and
281
					TODO: translate the char into body flag and
282
					OR the flags together
282
					OR the flags together
283
				
283
 
284
				*/
284
				*/
285
				/*
285
				/*
286
					if(bodyFlags & BodyFlags::fBody)
286
					if(bodyFlags & BodyFlags::fBody)
287
					os << "b ";
287
					os << "b ";
288
					if(bodyFlags & BodyFlags::fScene)
288
					if(bodyFlags & BodyFlags::fScene)
289
						os << "j ";
289
						os << "j ";
290
					int i=bodyFlags & 0x3F;
290
					int i=bodyFlags & 0x3F;
291
					if(i) 
291
					if(i)
292
						os << (char) ('b' + i) << ' ';
292
						os << (char) ('b' + i) << ' ';
293
				*/
293
				*/
294
				switch(ch){
294
				switch(ch){
295
					// both probably mean 'scene'
295
					// both probably mean 'scene'
296
					case 'j': // no break
296
					case 'j': // no break
297
					case 'u':
297
					case 'u':
298
						path->bodyFlags|=bob_dom_path::fScene;
298
						path->bodyFlags|=bob_path::fScene;
299
						break;
299
						break;
300
					case 'b':
300
					case 'b':
301
						path->bodyFlags|=bob_dom_path::fBody;
301
						path->bodyFlags|=bob_path::fBody;
302
						break;
302
						break;
303
					default:
303
					default:
304
						path->bodyFlags|=ch - 'b';
304
						path->bodyFlags|=ch - 'b';
305
				}
305
				}
306
			}
306
			}
307
		}
307
		}
308
	}
308
	}
309
	while(false);
309
	while(false);
310
	
310
 
311
	if(bRes && t && t->type!=token::t_openBracket)
311
	if(bRes && t && t->type!=token::t_openCrBracket)
312
		{ error(is.previous(), S_Error, "Unexpected end of document found when looking for beginning of Frame block"); bRes=false; }
312
		{ error(is.previous(), S_Error, "Unexpected end of document found when looking for beginning of Frame block"); bRes=false; }
313
	
313
 
314
	if(bRes==false){
314
	if(bRes==false){
315
		cut->removeChild(cut->end() - 1);
315
		cut->removeChild(cut->end() - 1);
316
		path=NULL;
316
		path=NULL;
317
	}
317
	}
318
	
318
 
319
	return path;
319
	return path;
320
}
320
}
321
//---------------------------------------------------------------------------------
321
//---------------------------------------------------------------------------------
322
bool bod_cut_parser::loadNote(bob_dom_path *path, token_stream& is)
322
bool bod_cut_parser::loadNote(bob_path *path, token_stream& is)
323
{
323
{
324
	bob_note *n;
324
	bob_note *n;
325
	bod_text_parser::token *t;
325
	bod_text_parser::token *t;
326
	bool bEnd=false;
326
	bool bEnd=false;
327
	
327
 
328
	path->notes().removeChildren();
328
	path->notes().removeChildren();
329
	
329
 
330
	++is;
330
	++is;
331
	do{
331
	do{
332
		n=path->notes().createChild();
332
		n=path->notes().createChild();
333
		// left
333
		// left
334
		if((t=loadValue(is))==NULL)
334
		if((t=loadValue(is))==NULL)
335
			break;
335
			break;
336
		if(!isinteger(t->text))
336
		if(!isinteger(t->text))
337
			{ error(t, S_Error, "Expected number"); break; }
337
			{ error(t, S_Error, "Expected number"); break; }
338
		n->value=atoi(t->text);
338
		n->value=atoi(t->text);
339
		
339
 
340
		if(n->value==-1) {	
340
		if(n->value==-1) {
341
			path->notes().removeChild(path->notes().end() - 1);
341
			path->notes().removeChild(path->notes().end() - 1);
342
			bEnd=true;
342
			bEnd=true;
343
			break; // end of notes
343
			break; // end of notes
344
		}
344
		}
345
		
345
 
346
		// right 
346
		// right
347
		n->text=loadString(is);
347
		n->text=loadString(is);
348
		if(n->text==NULL){
348
		if(n->text==NULL){
349
			path->notes().removeChild(path->notes().end() - 1);
349
			path->notes().removeChild(path->notes().end() - 1);
350
			break;
350
			break;
351
		}
351
		}
352
	}
352
	}
353
	while(is.good());
353
	while(is.good());
354
	
354
 
355
	if(bEnd==false && is.eof())
355
	if(bEnd==false && is.eof())
356
		error(is.previous(), S_Error, "Unexpected end of document found while looking for end of Notes (-1)");
356
		error(is.previous(), S_Error, "Unexpected end of document found while looking for end of Notes (-1)");
357
	
357
 
358
	return t!=NULL;
358
	return t!=NULL;
359
}
359
}
360
//---------------------------------------------------------------------------------
360
//---------------------------------------------------------------------------------
361
#ifdef X2BC_USE_INI_FORMATS
-
 
362
bool bod_cut_parser::loadFrame(bob_dom_path *path, token_stream& is)
361
bool bod_cut_parser::loadFrame(bob_path *path, token_stream& is)
363
{
362
{
364
	token *t;
363
	token *t;
365
	bool bRes=false;
364
	bool bRes=false;
366
	
-
 
367
	bob_dom_stat *stat=path->createChild();
-
 
368
	const Settings::StatFormat *f;
-
 
369
	
-
 
370
	// frame id
-
 
371
	t=is.tok();
-
 
372
	if(t==NULL)
-
 
373
		error(is.previous(), S_Error, "Expected frame ID"); 
-
 
374
	else if(loadValue(is)){
-
 
375
		if(!(isinteger(t->text) || ishexa(t->text)))
-
 
376
			error(t, S_Error, "Expected frame ID in decadic or hexadecimal format");
-
 
377
		else{
-
 
378
			if(t->text[0]=='0' && ((t->text[1] | 0x20) == 'x'))
-
 
379
				stat->frameId=hextoi(t->text);
-
 
380
			else
-
 
381
				stat->frameId=atoi(t->text);
-
 
382
				
-
 
383
			f=m_settings->findStatFormat(stat->frameId);
-
 
384
			if(f==NULL)
-
 
385
				error(is.previous(), S_Error, "Cannot find frame format 0x%X - cannot continue", stat->frameId);
-
 
386
			else
-
 
387
				bRes=true;
-
 
388
		}
-
 
389
	}
-
 
390
	
-
 
391
	if(bRes){
-
 
392
		for(Settings::StatFormat::const_iterator &it=f->tokens.begin(); it!=f->tokens.end(); ++it){
-
 
393
			for(int i=0; i < it->count; i++){
-
 
394
				if((t=loadValue(is))==NULL){
-
 
395
					error(is.previous(), S_Error, "Frame format 0x%X requires %d numbers", stat->frameId, f->cumulativeTokenCount);
-
 
396
					bRes=false;
-
 
397
					goto the_end; // yes it's a GOTO so kill me
-
 
398
				}
-
 
399
				if(!isfloat(t->text)){
-
 
400
					error(t, S_Error, "Expected number (integer or float)"); 
-
 
401
					bRes=false;
-
 
402
					goto the_end;
-
 
403
				}
-
 
404
				
-
 
405
				if(it->numFormat->outformat==Settings::NumberFormat::Integer && !isinteger(t->text))
-
 
406
					error(t, S_Warning, "Expected integer not float");
-
 
407
				
-
 
408
				unsigned int v;
-
 
409
				double d=(atof(t->text) / it->numFormat->multiplier);
-
 
410
				
-
 
411
				// this is same as v=(unsigned int) d;
-
 
412
				// but is uses normal rounding - not round toward zero, this is important 'cos otherwise there will 
-
 
413
				// be error + 1 in the resulting int (only if the resulting double has fraction part)
-
 
414
				__asm{
-
 
415
					fld qword ptr d
-
 
416
					fistp dword ptr v
-
 
417
				}
-
 
418
				
-
 
419
				stat->push_back(v);
-
 
420
			}
-
 
421
		}
-
 
422
		size_t pos=is.tell();
-
 
423
		while((t=is.tok()) && t->type!=token::t_closeBracket){
-
 
424
			++is;
-
 
425
		}
-
 
426
		if(t==NULL){
-
 
427
			error(is.previous(), S_Error, "Unexpected end of document found while looking for end of frame block '}'");
-
 
428
			bRes=false;
-
 
429
		}
-
 
430
		else if(is.tell()!=pos){
-
 
431
			error(is.previous(), S_Error, "Too many parameters in frame declaration, expected %d numbers", f->cumulativeTokenCount);
-
 
432
			bRes=false;
-
 
433
		}
-
 
434
		++is; // advance past the end bracket
-
 
435
	}
-
 
436
	
-
 
437
the_end:
-
 
438
	if(bRes==false)
-
 
439
		path->removeChild(path->end() - 1);
-
 
440
	return bRes;
-
 
441
}
-
 
442
//---------------------------------------------------------------------------------
-
 
443
#else // !defined(X2BC_USE_INI_FORMATS)
-
 
444
bool bod_cut_parser::loadFrame(bob_dom_path *path, token_stream& is)
-
 
445
{
-
 
446
	token *t;
-
 
447
	bool bRes=false;
-
 
448
	
365
 
449
	bob_dom_frame *frame=path->createChild();
366
	bob_frame *frame=path->createChild();
450
	int flags;
367
	int flags;
451
	
368
 
452
	// frame flags
369
	// frame flags
453
	t=is.tok();
370
	t=is.tok();
454
	if(t==NULL)
371
	if(t==NULL)
455
		error(is.previous(), S_Error, "Expected frame ID"); 
372
		error(is.previous(), S_Error, "Expected frame ID");
456
	else if(loadValue(is)){
373
	else if(loadValue(is)){
457
		if(!(isinteger(t->text) || ishexa(t->text)))
374
		if(!(isinteger(t->text) || ishexa(t->text)))
458
			error(t, S_Error, "Expected frame ID in decadic or hexadecimal format");
375
			error(t, S_Error, "Expected frame ID in decadic or hexadecimal format");
459
		else{
376
		else{
460
			if(t->text[0]=='0' && ((t->text[1] | 0x20) == 'x'))
377
			if(t->text[0]=='0' && ((t->text[1] | 0x20) == 'x'))
461
				flags=hextoi(t->text);
378
				flags=hextoi(t->text);
462
			else
379
			else
463
				flags=atoi(t->text);
380
				flags=atoi(t->text);
464
			
381
 
465
			if(flags & CUT_F_POSBEZINFO)
382
			if(flags & CUT_F_POSBEZINFO)
466
				error(NULL, S_Warning, "CUT_F_POSBEZINFO encoutered - don't know how to compile");
383
				error(NULL, S_Warning, "CUT_F_POSBEZINFO encoutered - don't know how to compile");
467
			if(flags & CUT_F_SAMESCALE)
384
			if(flags & CUT_F_SAMESCALE)
468
				error(NULL, S_Warning, "CUT_F_SAMESCALE encoutered");
385
				error(NULL, S_Warning, "CUT_F_SAMESCALE encoutered");
469
			
386
 
470
			if(flags & ~bob_dom_frame::flagMask)
387
			if(flags & ~bob_frame::flagMask)
471
				error(is.tok(), S_Warning, "Unsupported bits set in frame flags - normalizing flags, unsupported values will not be compiled");
388
				error(is.tok(), S_Warning, "Unsupported bits set in frame flags - normalizing flags, unsupported values will not be compiled");
472
			
389
 
473
			flags&=bob_dom_frame::flagMask;
390
			flags&=bob_frame::flagMask;
474
			frame->flags=flags;
391
			frame->flags=flags;
475
			
392
 
476
			bRes=true;
393
			bRes=true;
477
		}
394
		}
478
	}
395
	}
479
	
396
 
480
	while(bRes){
397
	while(bRes){
481
		static const char *pos_context = "frame: position: ";
398
		static const char *pos_context = "frame: position: ";
482
		static const char *rot_context ="frame: rotation: ";
399
		static const char *rot_context ="frame: rotation: ";
483
		static const char *tpos_context ="frame: target position: ";
400
		static const char *tpos_context ="frame: target position: ";
484
		static const char *troll_context ="frame: roll angle: ";
401
		static const char *troll_context ="frame: roll angle: ";
485
		static const char *fov_context ="frame: FOV: ";
402
		static const char *fov_context ="frame: FOV: ";
486
		static const char *color_context ="frame: RGB: ";
403
		static const char *color_context ="frame: RGB: ";
487
		static const char *len_context ="frame: length: ";
404
		static const char *len_context ="frame: length: ";
488
		static const char *idx_context ="frame: index: ";
405
		static const char *idx_context ="frame: index: ";
489
		
406
 
490
		if((flags & CUT_F_SAMEPOS)==0){
407
		if((flags & CUT_F_SAMEPOS)==0){
491
			loadIntValue(is, &(frame->position.x), pos_context);
408
			loadIntValue(is, &(frame->position.x), pos_context);
492
			loadIntValue(is, &(frame->position.y), pos_context);
409
			loadIntValue(is, &(frame->position.y), pos_context);
493
			if((bRes=loadIntValue(is, &(frame->position.z), pos_context))==false) break;
410
			if((bRes=loadIntValue(is, &(frame->position.z), pos_context))==false) break;
494
			
411
 
495
			if(flags & CUT_F_POSTCBINFO) {
412
			if(flags & CUT_F_POSTCBINFO) {
496
				frame->pos_tcb_info=new bob_dom_frame::tcb_info();
413
				frame->pos_tcb_info=new bob_frame::tcb_info();
497
				if((bRes=loadTCBInfo(is, frame->pos_tcb_info))==false) break;
414
				if((bRes=loadTCBInfo(is, frame->pos_tcb_info))==false) break;
498
			}
415
			}
499
		}
416
		}
500
		if((flags & CUT_F_SAMEROT)==0 && (flags & CUT_F_ROT)){
417
		if((flags & CUT_F_SAMEROT)==0 && (flags & CUT_F_ROT)){
501
			frame->rotation=new bob_dom_frame::angle_axis();
418
			frame->rotation=new bob_frame::AngleAxis();
502
			loadDoubleValue(is, &(frame->rotation->angle), rot_context);
419
			loadDoubleValue(is, &(frame->rotation->angle), rot_context);
503
			loadDoubleValue(is, &(frame->rotation->x), rot_context);
420
			loadDoubleValue(is, &(frame->rotation->x), rot_context);
504
			loadDoubleValue(is, &(frame->rotation->y), rot_context);
421
			loadDoubleValue(is, &(frame->rotation->y), rot_context);
505
			if((bRes=loadDoubleValue(is, &(frame->rotation->z), rot_context))==false) break;
422
			if((bRes=loadDoubleValue(is, &(frame->rotation->z), rot_context))==false) break;
506
			
423
 
507
			if(flags & CUT_F_ROTTCBINFO){
424
			if(flags & CUT_F_ROTTCBINFO){
508
				frame->rot_tcb_info=new bob_dom_frame::tcb_info();
425
				frame->rot_tcb_info=new bob_frame::tcb_info();
509
				if((bRes=loadTCBInfo(is, frame->rot_tcb_info))==false) break;
426
				if((bRes=loadTCBInfo(is, frame->rot_tcb_info))==false) break;
510
			}
427
			}
511
		}
428
		}
512
		if(flags & CUT_F_TARGETPOS){
429
		if(flags & CUT_F_TARGETPOS){
513
			if((flags & CUT_F_SAMETARGET)==0){
430
			if((flags & CUT_F_SAMETARGET)==0){
514
				frame->targetPos=new bob_dom_frame::point3d();
431
				frame->targetPos=new bob_frame::Position();
515
				loadIntValue(is, &(frame->targetPos->x), tpos_context);
432
				loadIntValue(is, &(frame->targetPos->x), tpos_context);
516
				loadIntValue(is, &(frame->targetPos->y), tpos_context);
433
				loadIntValue(is, &(frame->targetPos->y), tpos_context);
517
				if((bRes=loadIntValue(is, &(frame->targetPos->z), tpos_context))==false) break;
434
				if((bRes=loadIntValue(is, &(frame->targetPos->z), tpos_context))==false) break;
518
			}
435
			}
519
			if((flags & CUT_F_SAMEROT)==0){
436
			if((flags & CUT_F_SAMEROT)==0){
520
				if((bRes=loadDoubleValue(is, &(frame->rollAngle), troll_context))==false) break;
437
				if((bRes=loadDoubleValue(is, &(frame->rollAngle), troll_context))==false) break;
521
			}
438
			}
522
			if(flags & CUT_F_TPOSTCBINFO){
439
			if(flags & CUT_F_TPOSTCBINFO){
523
				frame->tpos_tcb_info=new bob_dom_frame::tcb_info();
440
				frame->tpos_tcb_info=new bob_frame::tcb_info();
524
				if((bRes=loadTCBInfo(is, frame->tpos_tcb_info))==false) break;
441
				if((bRes=loadTCBInfo(is, frame->tpos_tcb_info))==false) break;
525
			}
442
			}
526
		}
443
		}
527
		if((flags & CUT_F_SAMEFOV)==0 && flags & CUT_F_FOV){
444
		if((flags & CUT_F_SAMEFOV)==0 && flags & CUT_F_FOV){
528
			if((bRes=loadDoubleValue(is, &(frame->fov), fov_context))==false) break;
445
			if((bRes=loadDoubleValue(is, &(frame->fov), fov_context))==false) break;
529
		}
446
		}
530
		if((flags & CUT_F_SAMECOLOR)==0 && flags & CUT_F_COLOR){
447
		if((flags & CUT_F_SAMECOLOR)==0 && flags & CUT_F_COLOR){
531
			frame->color=new bob_dom_frame::rgb();
448
			frame->color=new bob_frame::rgb();
532
			loadDoubleValue(is, &(frame->color->r), color_context);
449
			loadDoubleValue(is, &(frame->color->r), color_context);
533
			loadDoubleValue(is, &(frame->color->r), color_context);
450
			loadDoubleValue(is, &(frame->color->r), color_context);
534
			if((bRes=loadDoubleValue(is, &(frame->color->r), color_context))==false) break;
451
			if((bRes=loadDoubleValue(is, &(frame->color->r), color_context))==false) break;
535
		}
452
		}
536
		if((bRes=loadIntValue(is, &(frame->length), len_context))==false) break;
453
		if((bRes=loadIntValue(is, &(frame->length), len_context))==false) break;
537
		if((bRes=loadIntValue(is, &(frame->index), idx_context))==false) break;
454
		if((bRes=loadIntValue(is, &(frame->index), idx_context))==false) break;
538
		
455
 
539
		break;
456
		break;
540
	}
457
	}
541
	if(bRes){
458
	if(bRes){
542
		int c=0;
459
		int c=0;
543
		while((t=is.tok()) && t->type!=token::t_closeBracket){
460
		while((t=is.tok()) && t->type!=token::t_closeCrBracket){
544
			c++;
461
			c++;
545
			if(loadValue(is)==false) break;
462
			if(loadValue(is)==false) break;
546
		}
463
		}
547
		if(t==NULL){
464
		if(t==NULL){
548
			error(is.previous(), S_Error, "Unexpected end of document found while looking for end of frame block '}'");
465
			error(is.previous(), S_Error, "Unexpected end of document found while looking for end of frame block '}'");
Line 551... Line 468...
551
			error(is.tok(), S_Warning, "Too many values in frame block: %d (expected %d), they will be discarded", frame->valueCount() + 2, frame->valueCount() + 2 + c);
468
			error(is.tok(), S_Warning, "Too many values in frame block: %d (expected %d), they will be discarded", frame->valueCount() + 2, frame->valueCount() + 2 + c);
552
		}
469
		}
553
		++is; // past the end bracket
470
		++is; // past the end bracket
554
	}
471
	}
555
	else{
472
	else{
556
		if(is.tok() && is.tok()->type==token::t_closeBracket)
473
		if(is.tok() && is.tok()->type==token::t_closeCrBracket)
557
			error(is.tok(), S_Error, "Premature end of frame block encountered. Expected %d values (+frame flags)", frame->valueCount() + 2);
474
			error(is.tok(), S_Error, "Premature end of frame block encountered. Expected %d values (+frame flags)", frame->valueCount() + 2);
558
	}
475
	}
559
	return bRes;
476
	return bRes;
560
}
477
}
561
#endif // !defined(X2BC_USE_INI_FORMATS)
-
 
562
//---------------------------------------------------------------------------------
478
//---------------------------------------------------------------------------------
563
bool bod_cut_parser::loadTCBInfo(token_stream& is, bob_dom_frame::tcb_info *info)
479
bool bod_cut_parser::loadTCBInfo(token_stream& is, bob_frame::tcb_info *info)
564
{
480
{
565
	if(!loadDoubleValue(is, &(info->tension), "TCB info (tension): ")) return false;
481
	if(!loadDoubleValue(is, &(info->tension), "TCB info (tension): ")) return false;
566
	if(!loadDoubleValue(is, &(info->continuity), "TCB info (continuity): ")) return false;
482
	if(!loadDoubleValue(is, &(info->continuity), "TCB info (continuity): ")) return false;
567
	if(!loadDoubleValue(is, &(info->bias), "TCB info (bias): ")) return false;
483
	if(!loadDoubleValue(is, &(info->bias), "TCB info (bias): ")) return false;
568
	if(!loadDoubleValue(is, &(info->easeFrom), "TCB info (ease from): ")) return false;
484
	if(!loadDoubleValue(is, &(info->easeFrom), "TCB info (ease from): ")) return false;