1 /*
2  * Tux Racer
3  * Copyright (C) 1999-2001 Jasmin F. Patry
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  */
19 
20 
21 #include "tuxracer.h"
22 #include "hier.h"
23 #include "tcl_util.h"
24 
25 /*
26  * Callbacks
27  */
28 
tux_rotate(ClientData cd,Tcl_Interp * ip,int argc,char * argv[])29 int tux_rotate( ClientData cd, Tcl_Interp *ip, int argc, char *argv[] )
30 {
31     char *errmsg;
32 
33     char *nodename;
34     char axis;
35     double angle ;
36 
37     if (4 != argc) {
38         Tcl_AppendResult(ip, argv[0], ": wrong number of arguments\n",
39 			 "Usage: ", argv[0], " <node> [x|y|z] <angle>",
40 			 (char *)0 );
41         return TCL_ERROR;
42     }
43 
44     /* obtain the nodename */
45     nodename = argv[1];
46 
47     /* obtain the axis */
48     axis = argv[2][0];
49     if ('x' != axis && 'y' != axis && 'z' != axis) {
50         Tcl_AppendResult(ip, argv[0], ": invalid rotation axes",
51 			 (char *)0 );
52         return TCL_ERROR;
53     }
54 
55     /* obtain the angle */
56     if (TCL_OK != Tcl_GetDouble(ip, argv[3], &angle)) {
57         Tcl_AppendResult(ip, argv[0], ": invalid rotation angle",
58 			 (char *)0 );
59         return TCL_ERROR;
60     }
61 
62     errmsg = rotate_scene_node(nodename,axis,angle);
63 
64     /* report error, if any */
65     if (errmsg) {
66         Tcl_AppendResult(ip, argv[0], ": ", errmsg, (char *)0 );
67         return TCL_ERROR;
68     }
69 
70     return TCL_OK;
71 }
72 
tux_translate(ClientData cd,Tcl_Interp * ip,int argc,char * argv[])73 int tux_translate( ClientData cd, Tcl_Interp *ip, int argc, char *argv[] )
74 {
75     char *errmsg;
76 
77     char *nodename;
78     scalar_t vec[3];
79 
80     if (3 != argc) {
81         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n",
82 			 "Usage: ", argv[0], " <node> { <x> <y> <z> }",
83 			 (char *)0 );
84         return TCL_ERROR;
85     }
86 
87     /* obtain the nodename */
88     nodename = argv[1];
89 
90     /* obtain the translation vector */
91     if (TCL_OK != get_tcl_tuple(ip,argv[2],vec,3)) {
92         Tcl_AppendResult(ip, argv[0], ": invalid translation vector",
93 			 (char *)0 );
94         return TCL_ERROR;
95     }
96 
97     errmsg = translate_scene_node(nodename,make_vector_from_array(vec));
98 
99     /* report error, if any */
100     if (errmsg) {
101         Tcl_AppendResult(ip, argv[0], ": ", errmsg, (char *)0 );
102         return TCL_ERROR;
103     }
104 
105     return TCL_OK;
106 }
107 
tux_scale(ClientData cd,Tcl_Interp * ip,int argc,char * argv[])108 int tux_scale( ClientData cd, Tcl_Interp *ip, int argc, char *argv[] )
109 {
110     char *errmsg;
111 
112     char *nodename;
113     scalar_t origin[3];
114     scalar_t factors[3];
115 
116     if (4 != argc) {
117         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n",
118 			 "Usage: ", argv[0], " <node> { <origin> } "
119 			 "{ <translation vector> }",
120 			 (char *)0 );
121         return TCL_ERROR;
122     }
123 
124     /* obtain the nodename */
125     nodename = argv[1];
126 
127     /* obtain the origin point */
128     if (TCL_OK != get_tcl_tuple(ip,argv[2],origin,3)) {
129         Tcl_AppendResult(ip, argv[0], ": invalid origin point",
130 			 (char *)0 );
131         return TCL_ERROR;
132     }
133 
134     /* obtain the scale factors */
135     if (TCL_OK != get_tcl_tuple(ip,argv[3],factors,3)) {
136         Tcl_AppendResult(ip, argv[0], ": invalid scale factors",
137 			 (char *)0 );
138         return TCL_ERROR;
139     }
140 
141     errmsg = scale_scene_node(nodename,make_point_from_array(origin),factors);
142 
143     /* report error, if any */
144     if (errmsg) {
145         Tcl_AppendResult(ip, argv[0], ": ", errmsg, (char *)0 );
146         return TCL_ERROR;
147     }
148 
149     return TCL_OK;
150 }
151 
tux_transform(ClientData cd,Tcl_Interp * ip,int argc,char * argv[])152 int tux_transform( ClientData cd, Tcl_Interp *ip, int argc, char *argv[] )
153 {
154     char *errmsg;
155 
156     char *parent_name;
157     char *child_name;
158 
159     if (3 != argc) {
160         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n",
161 			 "Usage: ", argv[0], " <parent node> <child node>",
162 			 (char *)0 );
163         return TCL_ERROR;
164     }
165 
166     /* obtain parent's name */
167     parent_name = argv[1];
168 
169     /* obtain child's name */
170     child_name  = argv[2];
171 
172     errmsg = create_tranform_node(parent_name, child_name);
173 
174     /* report error, if any */
175     if (errmsg) {
176         Tcl_AppendResult(ip, argv[0], ": ", errmsg, (char *)0 );
177         return TCL_ERROR;
178     }
179     return TCL_OK;
180 }
181 
tux_sphere(ClientData cd,Tcl_Interp * ip,int argc,char * argv[])182 int tux_sphere( ClientData cd, Tcl_Interp *ip, int argc, char *argv[] )
183 {
184     char *errmsg;
185 
186     char *parent_name;
187     char *child_name;
188     double resolution;
189 
190     if (4 != argc) {
191 	Tcl_AppendResult( ip, argv[0], ": wrong number of arguments\n",
192 			 "Usage: ", argv[0], " <parent node> <child node> "
193 			  "<radius>",
194 			  (char*) 0 );
195         return TCL_ERROR;
196     }
197 
198     /* obtain parent's name */
199     parent_name = argv[1];
200 
201     /* obtain child's name */
202     child_name  = argv[2];
203 
204     if ( TCL_OK != Tcl_GetDouble( ip, argv[3], &resolution ) ) {
205 	Tcl_AppendResult( ip, argv[0], ": resolution is invalid",
206 			  (char*) 0 );
207 	return TCL_ERROR;
208     }
209 
210     errmsg = create_sphere_node(parent_name, child_name, resolution);
211 
212     /* report error, if any */
213     if (errmsg) {
214         Tcl_AppendResult(ip, argv[0], ": ", errmsg, (char *)0 );
215         return TCL_ERROR;
216     }
217     return TCL_OK;
218 }
219 
220 
tux_material(ClientData cd,Tcl_Interp * ip,int argc,char * argv[])221 int tux_material( ClientData cd, Tcl_Interp *ip, int argc, char *argv[] )
222 {
223     char *errmsg;
224 
225     char *mat_name;
226     scalar_t diffuse[3];
227     scalar_t specular[3];
228     double spec_exp;
229 
230     if (5 != argc) {
231         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n",
232 			 "Usage: ", argv[0], " <name> { <ambient colour> } "
233 			 "{ <specular colour> } <specular exponent",
234 			 (char *)0 );
235         return TCL_ERROR;
236     }
237 
238     /* obtain material name */
239     mat_name = argv[1];
240 
241     /* obtain diffuse colour */
242     if (TCL_OK != get_tcl_tuple(ip,argv[2],diffuse,3)) {
243         Tcl_AppendResult(ip, argv[0], ": invalid diffuse colour",
244 			 (char *)0 );
245         return TCL_ERROR;
246     }
247 
248     /* obtain specular colour */
249     if (TCL_OK != get_tcl_tuple(ip,argv[3],specular,3)) {
250         Tcl_AppendResult(ip, argv[0], ": invalid specular colour",
251 			 (char *)0 );
252         return TCL_ERROR;
253     }
254 
255     /* obtain specular exponent */
256     if (TCL_OK != Tcl_GetDouble(ip,argv[4],&spec_exp)) {
257         Tcl_AppendResult(ip, argv[0], ": invalid specular exponent",
258 			 (char *)0 );
259         return TCL_ERROR;
260     }
261 
262     errmsg = create_material(mat_name,make_colour_from_array(diffuse),
263                 make_colour_from_array(specular), spec_exp);
264 
265     /* report error, if any */
266     if (errmsg) {
267         Tcl_AppendResult(ip, argv[0], ": ", errmsg, (char *)0 );
268         return TCL_ERROR;
269     }
270     return TCL_OK;
271 }
272 
tux_surfaceproperty(ClientData cd,Tcl_Interp * ip,int argc,char * argv[])273 int tux_surfaceproperty( ClientData cd, Tcl_Interp *ip,
274 			 int argc, char *argv[] )
275 {
276     char *errmsg;
277 
278     char *node_name;
279     char *mat_name;
280 
281     if (3 != argc) {
282         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n",
283 			 "Usage: ", argv[0], " <node> <material name>",
284 			 (char *)0 );
285         return TCL_ERROR;
286     }
287 
288     /* obtain node name */
289     node_name = argv[1];
290 
291     /* obtain material name */
292     mat_name  = argv[2];
293 
294     errmsg = set_scene_node_material(node_name, mat_name);
295 
296     /* report error, if any */
297     if (errmsg) {
298         Tcl_AppendResult(ip, argv[0], ": ", errmsg, (char *)0 );
299         return TCL_ERROR;
300     }
301     return TCL_OK;
302 }
303 
tux_shadow(ClientData cd,Tcl_Interp * ip,int argc,char * argv[])304 int tux_shadow( ClientData cd, Tcl_Interp *ip, int argc, char *argv[] )
305 {
306     char *errmsg;
307 
308     char *node_name;
309     char *state;
310 
311     if (3 != argc) {
312         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n",
313 			 "Usage: ", argv[0], " <node> [on|off]",
314 			 (char *)0 );
315         return TCL_ERROR;
316     }
317 
318     node_name = argv[1];
319     state = argv[2];
320 
321     errmsg = set_scene_node_shadow_state(node_name, state);
322 
323     /* report error, if any */
324     if (errmsg) {
325         Tcl_AppendResult(ip, argv[0], ": ", errmsg, (char *)0 );
326         return TCL_ERROR;
327     }
328     return TCL_OK;
329 }
330 
tux_eye(ClientData cd,Tcl_Interp * ip,int argc,char * argv[])331 int tux_eye( ClientData cd, Tcl_Interp *ip, int argc, char *argv[] )
332 {
333     char *errmsg;
334 
335     char *node_name;
336     char *which_eye;
337 
338     if (3 != argc) {
339         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n",
340 			 "Usage: ", argv[0], " <node> [left|right]",
341 			 (char *)0 );
342         return TCL_ERROR;
343     }
344 
345     node_name = argv[1];
346     which_eye = argv[2];
347 
348     errmsg = set_scene_node_eye( node_name, which_eye );
349 
350     /* report error, if any */
351     if (errmsg) {
352         Tcl_AppendResult(ip, argv[0], ": ", errmsg, (char *)0 );
353         return TCL_ERROR;
354     }
355     return TCL_OK;
356 }
357 
registerHierCallbacks(Tcl_Interp * ip)358 int registerHierCallbacks (
359     Tcl_Interp *ip
360 ) {
361     Tcl_CreateCommand(ip, "tux_rotate",          tux_rotate,          0,0);
362     Tcl_CreateCommand(ip, "tux_translate",       tux_translate,       0,0);
363     Tcl_CreateCommand(ip, "tux_scale",           tux_scale,           0,0);
364     Tcl_CreateCommand(ip, "tux_sphere",          tux_sphere,          0,0);
365     Tcl_CreateCommand(ip, "tux_transform",       tux_transform,       0,0);
366     Tcl_CreateCommand(ip, "tux_material",        tux_material,        0,0);
367     Tcl_CreateCommand(ip, "tux_surfaceproperty", tux_surfaceproperty, 0,0);
368     Tcl_CreateCommand(ip, "tux_shadow",          tux_shadow,          0,0);
369     Tcl_CreateCommand(ip, "tux_eye",             tux_eye,             0,0);
370 
371     return TCL_OK;
372 }
373