/* * GRacer * * Copyright (C) 1999 Takashi Matsuda * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include #define GL_GLEXT_LEGACY #include #include #include #include #include #include "tcldefs.h" #include #include #include #include "glbind.h" #include "glhash.h" #include "gluthash.h" #define ENUM_CHECK(cmd,label) if ((cmd) == GL_NONE) {goto label;} Tcl_Interp *main_interp; static Tcl_HashTable gl_enum_hash; static Tcl_HashTable gl_func_hash; static Tcl_HashTable glut_enum_hash; static Tcl_HashTable glut_func_hash; static Tcl_HashTable cache_hash; static Tcl_HashTable scene_hash; static Tcl_HashTable glut_timer_hash; static TclGlutCallback display_cb; static TclGlutCallback reshape_cb; static TclGlutCallback keyboard_cb; static TclGlutCallback keyboard_up_cb; static TclGlutCallback special_cb; static TclGlutCallback special_up_cb; static TclGlutCallback mouse_cb; static TclGlutCallback motion_cb; static TclGlutCallback passive_motion_cb; static TclGlutCallback entry_cb; static TclGlutCallback visibility_cb; static TclGlutCallback menu_state_cb; static TclGlutCallback tablet_motion_cb; static TclGlutCallback tablet_button_cb; static TclGlutCallback menu_status_cb; static TclGlutCallback window_status_cb; static TclGlutCallback idle_cb; Tcl_Obj *obj_x; Tcl_Obj *obj_y; Tcl_Obj *obj_width; Tcl_Obj *obj_height; Tcl_Obj *obj_state; Tcl_Obj *obj_status; Tcl_Obj *obj_key; Tcl_Obj *obj_button; Tcl_Obj *obj_value; typedef int (*GrSubCmdFunc)(Tcl_Interp *, int objc, Tcl_Obj *CONST objv[]); typedef struct { char *name; GrSubCmdFunc func; int value; } GrFunctionList; FILE* gr_open_file (char *url, char *mode) { char *str; int res; if (!url || !mode) return NULL; res = Tcl_VarEval (main_interp, "cache::get ", url, NULL); if (res == TCL_ERROR) { fputs (Tcl_GetVar (main_interp, "errorInfo", TCL_GLOBAL_ONLY), stderr); return NULL; } str = Tcl_GetStringResult (main_interp); return fopen (str, mode); } char* gr_get_fullurl (char *url, char *baseurl) { int res; res = Tcl_VarEval (main_interp, "cache::fullurl ", url, " ", baseurl, NULL); if (res == TCL_ERROR) { fputs (Tcl_GetVar (main_interp, "errorInfo", TCL_GLOBAL_ONLY), stderr); return NULL; } return Tcl_GetStringResult (main_interp); } void tcl_PutCache (char *key, ClientData data) { Tcl_HashEntry *entry; int _new; entry = Tcl_CreateHashEntry (&cache_hash, key, &_new); /* i dont mind entry is newly created or not */ Tcl_SetHashValue (entry, data); } ClientData tcl_GetCache (char *key) { Tcl_HashEntry *entry; if (!key) return NULL; entry = Tcl_FindHashEntry (&cache_hash, key); if (&entry) return NULL; return Tcl_GetHashValue (entry); } static int GlCmd (ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_HashEntry *entry; GrFunctionList *funclist; int i; char *str; int res; if (objc == 1) { OBJ_RESULT (objv[0], ": missing sub-command."); return TCL_ERROR; } for (i=1; ifunc)(interp, objc-i, objv+i)) <= 0) { return TCL_ERROR; } i += res; } return TCL_OK; } static int GlutCmd (ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_HashEntry *entry; GrFunctionList *funclist; int i; char *str; int res; if (objc == 1) { OBJ_RESULT (objv[0], " missing sub-command."); return TCL_ERROR; } for (i=1; ifunc)(interp, objc-i, objv+i)) <= 0) { return TCL_ERROR; } i += res; } return TCL_OK; } static int tcl_SetGlutCallback (Tcl_Interp *interp, TclGlutCallback *cb, Tcl_Obj *CONST script, int value) { int length; if (Tcl_ListObjLength (interp, script, &length) == TCL_ERROR) return TCL_ERROR; if (length > 0) { if (cb->obj) { Tcl_DecrRefCount (cb->obj); } cb->interp = interp; cb->obj = script; Tcl_IncrRefCount (cb->obj); cb->value = value; } else { if (cb->obj) { Tcl_DecrRefCount (cb->obj); } cb->interp = NULL; cb->obj = NULL; } return TCL_OK; } static int tcl_InstallGlutCallback (Tcl_Interp *interp, Tcl_HashTable *hash, Tcl_Obj *CONST script, int key, int value) { int _new; Tcl_HashEntry *entry; TclGlutCallback *cb; int length; if (Tcl_ListObjLength (interp, script, &length) == TCL_ERROR) return TCL_ERROR; if (length == 0) { entry = Tcl_FindHashEntry (hash, (ClientData) key); if (entry) { cb = (TclGlutCallback *) Tcl_GetHashValue (entry); if (cb && cb->obj) { Tcl_DecrRefCount (cb->obj); cb->interp = NULL; cb->obj = NULL; } } } else { entry = Tcl_CreateHashEntry (hash, (ClientData) key, &_new); if (!_new) { cb = (TclGlutCallback *) Tcl_GetHashValue (entry); if (cb && cb->obj) { Tcl_DecrRefCount (cb->obj); } } else { cb = gr_new (TclGlutCallback, 1); } cb->interp = interp; cb->obj = script; //cb->obj = Tcl_DuplicateObj (script); Tcl_IncrRefCount (cb->obj); cb->value = value; Tcl_SetHashValue (entry, (ClientData) cb); } return TCL_OK; } static TclGlutCallback * tcl_GetGlutCallback (Tcl_HashTable *hash, int key) { Tcl_HashEntry *entry; entry = Tcl_FindHashEntry (hash, (ClientData) key); if (!entry) return NULL; return (TclGlutCallback *) Tcl_GetHashValue (entry); } static int tcl_InvokeCallback (TclGlutCallback *cb) { int res; Tcl_Interp *interp = cb->interp; Tcl_Obj *obj = cb->obj; Tcl_IncrRefCount (obj); if ((res = Tcl_EvalObj (interp, obj)) == TCL_ERROR) fputs (Tcl_GetVar (interp, "errorInfo", TCL_GLOBAL_ONLY), stderr); Tcl_DecrRefCount (obj); return res; } void tcl_DisplayFunc (void) { if (!display_cb.interp) return; tcl_InvokeCallback (&display_cb); } void tcl_ReshapeFunc (int width, int height) { Tcl_Interp *interp; if (!reshape_cb.interp) return; interp = reshape_cb.interp; Tcl_ObjSetVar2 (interp, obj_width, NULL, Tcl_NewIntObj(width), 0); Tcl_ObjSetVar2 (interp, obj_height, NULL, Tcl_NewIntObj(height), 0); tcl_InvokeCallback (&reshape_cb); } void tcl_KeyboardFunc (unsigned char key, int x, int y) { Tcl_Interp *interp; if (!keyboard_cb.interp) return; interp = keyboard_cb.interp; Tcl_ObjSetVar2 (interp, obj_key, NULL, Tcl_NewIntObj(key), 0); Tcl_ObjSetVar2 (interp, obj_x, NULL, Tcl_NewIntObj(x), 0); Tcl_ObjSetVar2 (interp, obj_y, NULL, Tcl_NewIntObj(y), 0); Tcl_ObjSetVar2 (interp, obj_value, NULL, Tcl_NewIntObj(keyboard_cb.value), 0); tcl_InvokeCallback (&keyboard_cb); } void tcl_KeyboardUpFunc (unsigned char key, int x, int y) { Tcl_Interp *interp; if (!keyboard_up_cb.interp) return; interp = keyboard_up_cb.interp; Tcl_ObjSetVar2 (interp, obj_key, NULL, Tcl_NewIntObj(key), 0); Tcl_ObjSetVar2 (interp, obj_x, NULL, Tcl_NewIntObj(x), 0); Tcl_ObjSetVar2 (interp, obj_y, NULL, Tcl_NewIntObj(y), 0); Tcl_ObjSetVar2 (interp, obj_value, NULL, Tcl_NewIntObj(keyboard_up_cb.value), 0); tcl_InvokeCallback (&keyboard_up_cb); } void tcl_SpecialFunc (int key, int x, int y) { Tcl_Interp *interp; if (!special_cb.interp) return; interp = special_cb.interp; Tcl_ObjSetVar2 (interp, obj_key, NULL, Tcl_NewIntObj(key), 0); Tcl_ObjSetVar2 (interp, obj_x, NULL, Tcl_NewIntObj(x), 0); Tcl_ObjSetVar2 (interp, obj_y, NULL, Tcl_NewIntObj(y), 0); Tcl_ObjSetVar2 (interp, obj_value, NULL, Tcl_NewIntObj(special_cb.value), 0); tcl_InvokeCallback (&special_cb); } void tcl_SpecialUpFunc (int key, int x, int y) { Tcl_Interp *interp; if (!special_up_cb.interp) return; interp = special_up_cb.interp; Tcl_ObjSetVar2 (interp, obj_key, NULL, Tcl_NewIntObj(key), 0); Tcl_ObjSetVar2 (interp, obj_x, NULL, Tcl_NewIntObj(x), 0); Tcl_ObjSetVar2 (interp, obj_y, NULL, Tcl_NewIntObj(y), 0); Tcl_ObjSetVar2 (interp, obj_value, NULL, Tcl_NewIntObj(special_up_cb.value), 0); tcl_InvokeCallback (&special_up_cb); } void tcl_MouseFunc (int button, int state, int x, int y) { Tcl_Interp *interp; if (!mouse_cb.interp) return; interp = mouse_cb.interp; Tcl_ObjSetVar2 (interp, obj_button, NULL, Tcl_NewIntObj(button), 0); Tcl_ObjSetVar2 (interp, obj_state, NULL, Tcl_NewIntObj(state), 0); Tcl_ObjSetVar2 (interp, obj_x, NULL, Tcl_NewIntObj(x), 0); Tcl_ObjSetVar2 (interp, obj_y, NULL, Tcl_NewIntObj(y), 0); Tcl_ObjSetVar2 (interp, obj_value, NULL, Tcl_NewIntObj(mouse_cb.value), 0); tcl_InvokeCallback (&mouse_cb); } void tcl_MotionFunc (int x, int y) { Tcl_Interp *interp; if (!motion_cb.interp) return; interp = motion_cb.interp; Tcl_ObjSetVar2 (interp, obj_x, NULL, Tcl_NewIntObj(x), 0); Tcl_ObjSetVar2 (interp, obj_y, NULL, Tcl_NewIntObj(y), 0); Tcl_ObjSetVar2 (interp, obj_value, NULL, Tcl_NewIntObj(motion_cb.value), 0); tcl_InvokeCallback (&motion_cb); } void tcl_PassiveMotionFunc (int x, int y) { Tcl_Interp *interp; if (!passive_motion_cb.interp) return; interp = passive_motion_cb.interp; Tcl_ObjSetVar2 (interp, obj_x, NULL, Tcl_NewIntObj(x), 0); Tcl_ObjSetVar2 (interp, obj_y, NULL, Tcl_NewIntObj(y), 0); Tcl_ObjSetVar2 (interp, obj_value, NULL, Tcl_NewIntObj(passive_motion_cb.value), 0); tcl_InvokeCallback (&passive_motion_cb); } void tcl_EntryFunc (int state) { Tcl_Interp *interp; if (!entry_cb.interp) return; interp = entry_cb.interp; Tcl_ObjSetVar2 (interp, obj_state, NULL, Tcl_NewIntObj(state), 0); Tcl_ObjSetVar2 (interp, obj_value, NULL, Tcl_NewIntObj(entry_cb.value), 0); tcl_InvokeCallback (&entry_cb); } void tcl_VisibilityFunc (int state) { Tcl_Interp *interp; if (!visibility_cb.interp) return; interp = visibility_cb.interp; Tcl_ObjSetVar2 (interp, obj_state, NULL, Tcl_NewIntObj(state), 0); Tcl_ObjSetVar2 (interp, obj_value, NULL, Tcl_NewIntObj(visibility_cb.value), 0); tcl_InvokeCallback (&visibility_cb); } void tcl_TimerFunc (int value) { TclGlutCallback *cb; Tcl_Interp *interp; Tcl_Obj *script; cb = tcl_GetGlutCallback (&glut_timer_hash, value); if (!cb || !cb->obj) return; interp = cb->interp; script = cb->obj; cb->obj = NULL; Tcl_ObjSetVar2 (interp, obj_value, NULL, Tcl_NewIntObj(value), 0); if (Tcl_EvalObj (interp, script) == TCL_ERROR) fputs (Tcl_GetVar (interp, "errorInfo", TCL_GLOBAL_ONLY), stderr); Tcl_DecrRefCount (script); } void tcl_IdleFunc (void) { Tcl_Interp *interp; if (!idle_cb.interp) return; interp = idle_cb.interp; if (Tcl_EvalObj (interp, idle_cb.obj) == TCL_ERROR) fputs (Tcl_GetVar (interp, "errorInfo", TCL_GLOBAL_ONLY), stderr); } void tcl_MenuStateFunc (int state) { Tcl_ObjSetVar2 (menu_state_cb.interp, obj_state, NULL, Tcl_NewIntObj(state), 0); Tcl_ObjSetVar2 (menu_state_cb.interp, obj_value, NULL, Tcl_NewIntObj(menu_state_cb.value), 0); if (Tcl_EvalObj (menu_state_cb.interp, menu_state_cb.obj) == TCL_ERROR) fputs (Tcl_GetVar (menu_state_cb.interp, "errorInfo", TCL_GLOBAL_ONLY), stderr); } void tcl_TabletMotionFunc (int x, int y) { Tcl_ObjSetVar2 (tablet_motion_cb.interp, obj_x, NULL, Tcl_NewIntObj(x), 0); Tcl_ObjSetVar2 (tablet_motion_cb.interp, obj_y, NULL, Tcl_NewIntObj(y), 0); Tcl_ObjSetVar2 (tablet_motion_cb.interp, obj_value, NULL, Tcl_NewIntObj(tablet_motion_cb.value), 0); if (Tcl_EvalObj (tablet_motion_cb.interp, tablet_motion_cb.obj) == TCL_ERROR) fputs (Tcl_GetVar (tablet_motion_cb.interp, "errorInfo", TCL_GLOBAL_ONLY), stderr); } void tcl_TabletButtonFunc (int button, int state, int x, int y) { Tcl_ObjSetVar2 (tablet_button_cb.interp, obj_button, NULL, Tcl_NewIntObj(button), 0); Tcl_ObjSetVar2 (tablet_button_cb.interp, obj_state, NULL, Tcl_NewIntObj(state), 0); Tcl_ObjSetVar2 (tablet_button_cb.interp, obj_x, NULL, Tcl_NewIntObj(x), 0); Tcl_ObjSetVar2 (tablet_button_cb.interp, obj_y, NULL, Tcl_NewIntObj(y), 0); Tcl_ObjSetVar2 (tablet_button_cb.interp, obj_value, NULL, Tcl_NewIntObj(tablet_button_cb.value), 0); if (Tcl_EvalObj (tablet_button_cb.interp, tablet_button_cb.obj) == TCL_ERROR) fputs (Tcl_GetVar (tablet_button_cb.interp, "errorInfo", TCL_GLOBAL_ONLY), stderr); } void tcl_MenuStatusFunc (int status, int x, int y) { Tcl_ObjSetVar2 (menu_status_cb.interp, obj_status, NULL, Tcl_NewIntObj(status), 0); Tcl_ObjSetVar2 (menu_status_cb.interp, obj_x, NULL, Tcl_NewIntObj(x), 0); Tcl_ObjSetVar2 (menu_status_cb.interp, obj_y, NULL, Tcl_NewIntObj(y), 0); Tcl_ObjSetVar2 (menu_status_cb.interp, obj_value, NULL, Tcl_NewIntObj(menu_status_cb.value), 0); if (Tcl_EvalObj (menu_status_cb.interp, menu_status_cb.obj) == TCL_ERROR) fputs (Tcl_GetVar (menu_status_cb.interp, "errorInfo", TCL_GLOBAL_ONLY), stderr); } void tcl_WindowStatusFunc (int state) { Tcl_ObjSetVar2 (window_status_cb.interp, obj_state, NULL, Tcl_NewIntObj(state), 0); Tcl_ObjSetVar2 (window_status_cb.interp, obj_value, NULL, Tcl_NewIntObj(window_status_cb.value), 0); if (Tcl_EvalObj (window_status_cb.interp, window_status_cb.obj) == TCL_ERROR) fputs (Tcl_GetVar (window_status_cb.interp, "errorInfo", TCL_GLOBAL_ONLY), stderr); } static GrObjectDrawOption gr_get_draw_option (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char *str; int i; GrObjectDrawOption option = 0, newopt = 0; int invert; for (i=0; itexture_name) { if (Tcl_VarEval (interp, "cache::fullurl ", obj->texture_name, " ", baseurl, NULL) == TCL_ERROR) { fputs (Tcl_GetVar (interp, "errorInfo", TCL_GLOBAL_ONLY), stderr); goto PASS; } str = Tcl_GetStringResult (interp); if (Tcl_VarEval (interp, "cache::get ", str, NULL) == TCL_ERROR) { fputs (Tcl_GetVar (interp, "errorInfo", TCL_GLOBAL_ONLY), stderr); goto PASS; } filename = Tcl_GetStringResult (interp); if (!(obj->texture = tcl_GetCache (filename))) { obj->texture = gr_texture_new_from_file (filename); if (!obj->texture) { fputs ("can not load texture\n", stderr); goto PASS; } tcl_PutCache (filename, obj->texture); } gr_INCREF (obj->texture); } PASS: if (recursive) { for (i=0; inum_kids; i++) { tcl_GrObjectLoadTexture (interp, baseurl, obj->kids[i], 1); } } } void tcl_GrSceneLoadTexture (Tcl_Interp *interp, char *baseurl, GrScene *scene) { int i; for (i=0; inum_objs; i++) { tcl_GrObjectLoadTexture (interp, baseurl, scene->objs[i], 1); } } GrScene *tcl_GetGrScene (Tcl_Interp *interp, char *name, char *baseurl) { GrScene *scene; char *fullurl; char *str; int res; FILE *file; if (!name) return NULL; if (baseurl) { Tcl_VarEval (interp, "cache::fullurl ", name, " ", baseurl, NULL); fullurl = strdup (Tcl_GetStringResult (interp)); } else { fullurl = strdup (name); } res = Tcl_VarEval (interp, "cache::get ", fullurl, NULL); if (res == TCL_ERROR) { free (fullurl); return NULL; } str = Tcl_GetStringResult (interp); scene = tcl_GetCache (str); if (!scene) { file = fopen (str, "r"); if (!file) { Tcl_AppendResult (interp, ": couldn't open file.", NULL); free (fullurl); return NULL; } scene = gr_scene_new_from_file (file); fclose (file); if (!scene) { Tcl_AppendResult (interp, ": failed to read scene file.", NULL); free (fullurl); return NULL; } tcl_PutCache (str, scene); tcl_GrSceneLoadTexture (interp, fullurl, scene); } free (fullurl); gr_INCREF (scene); return scene; } static int grSceneCmd (ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_HashEntry *entry; static int count = 0; GrScene *scene; char *filename; char *url; int _new; char buf[256]; FILE *file; GrObjectDrawOption option; GrObject *object; char *str; int key; double sx, sy, sz; if (objc < 2) { goto ERROR; } str = Tcl_GetStringFromObj (objv[1], NULL); if (!strcmp (str, "create")) { if (objc < 3) goto ERROR; url = Tcl_GetStringFromObj (objv[2], NULL); filename = Tcl_GetStringResult (interp); if (Tcl_VarEval (interp, "cache::get ", url, NULL) == TCL_ERROR) { return TCL_ERROR; } filename = Tcl_GetStringResult (interp); scene = tcl_GetCache (filename); if (!scene) { file = fopen (filename, "r"); if (!file) { OBJ_RESULT(objv[0], ": couldn't open file."); return TCL_ERROR; } scene = gr_scene_new_from_file (file); fclose (file); if (!scene) { OBJ_RESULT(objv[0], ": couldn't create scene data."); return TCL_ERROR; } tcl_GrSceneLoadTexture (interp, url, scene); } gr_INCREF (scene); sprintf (buf, "%d", count); entry = Tcl_CreateHashEntry (&scene_hash, (ClientData)count++, &_new); Tcl_SetHashValue (entry, (ClientData *) scene); Tcl_SetResult (interp, buf, TCL_VOLATILE); return TCL_OK; } else if (!strcmp (str, "destroy")) { if (objc < 3) goto ERROR; Tcl_GetIntFromObj (interp, objv[2], &key); entry = Tcl_FindHashEntry (&scene_hash, (ClientData)key); if (!entry) { OBJ_RESULT(objv[0], ": scene does not defined."); return TCL_ERROR; } scene = (GrScene *) Tcl_GetHashValue (entry); gr_DECREF (scene); Tcl_DeleteHashEntry (entry); } else if (!strcmp (str, "setup")) { if (objc < 3) goto ERROR; Tcl_GetIntFromObj (interp, objv[2], &key); entry = Tcl_FindHashEntry (&scene_hash, (ClientData)key); if (!entry) { OBJ_RESULT(objv[0], ": scene does not defined."); return TCL_ERROR; } scene = (GrScene *) Tcl_GetHashValue (entry); option = gr_get_draw_option (interp, objc - 3, objv + 3); if (option == 0) { option = GR_OBJECT_ALL; } gr_scene_setup_gl (scene, option); } else if (!strcmp (str, "release")) { if (objc < 3) goto ERROR; Tcl_GetIntFromObj (interp, objv[2], &key); entry = Tcl_FindHashEntry (&scene_hash, (ClientData)key); if (!entry) { OBJ_RESULT(objv[0], ": scene does not defined."); return TCL_ERROR; } scene = (GrScene *) Tcl_GetHashValue (entry); gr_scene_release_gl (scene); } else if (!strcmp (str, "draw")) { if (objc < 3) goto ERROR; Tcl_GetIntFromObj (interp, objv[2], &key); entry = Tcl_FindHashEntry (&scene_hash, (ClientData)key); if (!entry) { OBJ_RESULT(objv[0], ": scene does not defined."); return TCL_ERROR; } scene = (GrScene *) Tcl_GetHashValue (entry); str = Tcl_GetStringFromObj (objv[3], NULL); object = NULL; if (!strcmp(str, "-obj")) { str = Tcl_GetStringFromObj (objv[4], NULL); object = gr_scene_find_object (scene, str, NULL); option = gr_get_draw_option (interp, objc - 5, objv + 5); } else { option = gr_get_draw_option (interp, objc - 3, objv + 3); } if (option == 0) { option = GR_OBJECT_ALL; } glPushMatrix (); gr_scene_draw (scene, object, option, 1); glPopMatrix (); } else if (!strcmp (str, "scale")) { if (objc < 6) goto ERROR; Tcl_GetIntFromObj (interp, objv[2], &key); entry = Tcl_FindHashEntry (&scene_hash, (ClientData)key); if (!entry) { OBJ_RESULT(objv[0], ": scene does not defined."); return TCL_ERROR; } scene = (GrScene *) Tcl_GetHashValue (entry); Tcl_GetDoubleFromObj (interp, objv[3], &sx); Tcl_GetDoubleFromObj (interp, objv[4], &sy); Tcl_GetDoubleFromObj (interp, objv[5], &sz); gr_scene_scale (scene, sx, sy, sz); } else { goto ERROR; } return TCL_OK; ERROR: OBJ_RESULT (objv[0], ": wrong args. should be create , destroy , setup , " "release , draw , or scale .\n"); return TCL_ERROR; } #include extern Display *__glutDisplay; extern Window __glutRoot; extern struct GLUTwindow *__glutCurrentWindow; #if 0 static Tcl_Obj* ObjFromList (Tcl_Interp *interp, Tcl_Obj *list, int index) { Tcl_Obj *item = NULL; Tcl_ListObjIndex (interp, list, index, &item); return item; } static int IntFromList (Tcl_Interp *interp, Tcl_Obj *list, int index) { Tcl_Obj *item; int val = 0; if (Tcl_ListObjIndex (interp, list, index, &item) == TCL_ERROR) return 0.0; Tcl_GetIntFromObj (interp, item, &val); return val; } #endif static double DoubleFromList (Tcl_Interp *interp, Tcl_Obj *list, int index) { Tcl_Obj *item; double val = 0.0; if (Tcl_ListObjIndex (interp, list, index, &item) == TCL_ERROR) return 0.0; Tcl_GetDoubleFromObj (interp, item, &val); return val; } #if 0 static char * StringFromList (Tcl_Interp *interp, Tcl_Obj *list, int index) { Tcl_Obj *item; if (Tcl_ListObjIndex (interp, list, index, &item) == TCL_ERROR) return NULL; return Tcl_GetStringFromObj (item, NULL); } static int CheckNumArg (Tcl_Interp *interp, Tcl_Obj *arg, int num, char *message) { int argc; if (Tcl_ListObjLength (interp, arg, &argc) == TCL_ERROR) return TCL_ERROR; if (argc != num) { Tcl_AppendResult (interp, " ", StringFromList (interp, arg, 0), ": wrong # args. ", message, NULL); return TCL_ERROR; } return TCL_OK; } #endif GLenum GetGLEnum (Tcl_Obj *CONST obj) { char *str; Tcl_HashEntry *entry; str = Tcl_GetStringFromObj (obj, NULL); if (!str) return GL_NONE; entry = Tcl_FindHashEntry (&gl_enum_hash, str); if (!entry) return GL_NONE; return (GLenum) Tcl_GetHashValue (entry); } void * GetGlutEnum (Tcl_Obj *CONST obj) { char *str; Tcl_HashEntry *entry; str = Tcl_GetStringFromObj (obj, NULL); if (!str) return GL_NONE; entry = Tcl_FindHashEntry (&glut_enum_hash, str); if (!entry) return GL_NONE; return (void *) Tcl_GetHashValue (entry); } static int gl_subcmd_vertex (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { double v[4]; if (objc < 3) goto ERROR; TCL_CHECK(Tcl_GetDoubleFromObj (interp, objv[1], &v[0]), ERROR); TCL_CHECK(Tcl_GetDoubleFromObj (interp, objv[2], &v[1]), ERROR); if (objc < 4 || Tcl_GetDoubleFromObj (interp, objv[3], &v[2]) == TCL_ERROR) { glVertex2dv (v); return 3; } if (objc < 5 || Tcl_GetDoubleFromObj (interp, objv[4], &v[3]) == TCL_ERROR) { glVertex3dv (v); return 4; } else { glVertex4dv (v); return 5; } ERROR: OBJ_RESULT (objv[0], ": wrong # args. should be x y [z [w]]"); return 0; } static int gl_subcmd_normal (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { double v[3]; if (objc < 4) goto ERROR; TCL_CHECK(Tcl_GetDoubleFromObj (interp, objv[1], &v[0]), ERROR); TCL_CHECK(Tcl_GetDoubleFromObj (interp, objv[2], &v[1]), ERROR); TCL_CHECK(Tcl_GetDoubleFromObj (interp, objv[3], &v[2]), ERROR); glNormal3dv (v); return 4; ERROR: OBJ_RESULT (objv[0], ": wrong # args. should be nx ny nz."); return 0; } static int gl_subcmd_color (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { double c[4]; if (objc < 4) goto ERROR; TCL_CHECK(Tcl_GetDoubleFromObj (interp, objv[1], &c[0]), ERROR); TCL_CHECK(Tcl_GetDoubleFromObj (interp, objv[2], &c[1]), ERROR); TCL_CHECK(Tcl_GetDoubleFromObj (interp, objv[3], &c[2]), ERROR); if (objc < 5 || Tcl_GetDoubleFromObj (interp, objv[4], &c[3]) == TCL_ERROR) { glColor3dv (c); return 4; } else { glColor4dv (c); return 5; } ERROR: OBJ_RESULT (objv[0], ": wrong # args. r g b [a]"); return 0; } static int gl_subcmd_enable (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { GLenum attr; int i; char *str; for (i=1; i < objc; i++) { str = Tcl_GetStringFromObj (objv[i], NULL); if (str && str[0] == '-') { return i; } attr = GetGLEnum (objv[i]); if (attr == GL_NONE) { Tcl_SetObjResult (interp, objv[0]); Tcl_AppendResult (interp, ": unknown attribute \"", str, "\".", NULL); return 0; } GL_CHECK(glEnable (attr)); } return i; } static int gl_subcmd_deletelists (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int list; int range; if (objc < 3) { OBJ_RESULT (objv[0], ": wrong # args. should be "); return 0; } TCL_CHECK (Tcl_GetIntFromObj (interp, objv[1], &list), ERROR); TCL_CHECK (Tcl_GetIntFromObj (interp, objv[2], &range), ERROR); GL_CHECK(glDeleteLists (list, range)); return 3; ERROR: OBJ_RESULT (objv[0], ": wrong args. should be integer value."); return 0; } static int gl_subcmd_deletetextures (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int i; int val; for (i=1; i 2 && Tcl_GetIntFromObj (interp, objv[2], &num) == TCL_ERROR) { Tcl_SetObjResult (interp, objv[0]); Tcl_AppendResult (interp, ": wrong args. num must be integer.", NULL); return 0; } GL_CHECK(name = glGenLists (num)); val = Tcl_NewIntObj (name); Tcl_ObjSetVar2 (interp, objv[1], NULL, val, 0); return (objc > 2)? 3:2; } static int gl_subcmd_newlist (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { GLuint name; GLenum mode; if (objc < 3) goto ERROR; TCL_CHECK (Tcl_GetIntFromObj (interp, objv[1], &name), ERROR); TCL_CHECK((mode = GetGLEnum (objv[2])), ERROR); GL_CHECK(glNewList (name, mode)); return 3; ERROR: Tcl_SetObjResult (interp, objv[0]); Tcl_AppendResult (interp, ": wrong args. should be id mode.", NULL); return 0; } static int gl_subcmd_endlist (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { GL_CHECK(glEndList ()); return 1; } static int gl_subcmd_calllist (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { GLuint name; int i; if (objc < 2) { Tcl_SetObjResult (interp, objv[0]); Tcl_AppendResult (interp, ": wrong # args. id [id ...].", NULL); return 0; } for (i=1; i= 3 && Tcl_GetIntFromObj (interp, objv[2], &num) != TCL_ERROR) { nargs = 2; } names = gr_new (GLuint, num); GL_CHECK(glGenTextures (num, names)); if (num == 1) { val = Tcl_NewIntObj (names[0]); Tcl_ObjSetVar2 (interp, objv[1], NULL, val, 0); } else { val = Tcl_NewListObj (0, NULL); for (i=0; i .", NULL); return 0; } static int glut_subcmd_window_size (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int w, h; if (objc < 3) goto ERROR; TCL_CHECK(Tcl_GetIntFromObj (interp, objv[1], &w), ERROR); TCL_CHECK(Tcl_GetIntFromObj (interp, objv[2], &h), ERROR); glutInitWindowSize (w, h); return 3; ERROR: Tcl_AppendResult (interp, ": wrong # args. should be .", NULL); return 0; } static int glut_subcmd_create_window (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_create_subwindow (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_destroy_window (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_post_redisplay (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { glutPostRedisplay (); return 1; } static int glut_subcmd_swap_buffers (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { glutSwapBuffers (); return 1; } static int glut_subcmd_set_window (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_set_window_title (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_set_icon_title (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_position_window (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_reshape_window (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int width; int height; TCL_CHECK(Tcl_GetIntFromObj (interp, objv[1], &width), ERROR); TCL_CHECK(Tcl_GetIntFromObj (interp, objv[2], &height), ERROR); glutReshapeWindow (width, height); return 3; ERROR: OBJ_RESULT(objv[0], ": wrong # args. should be width height"); return 0; } static int glut_subcmd_pop_window (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_push_window (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_iconify_window (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_show_window (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_hide_window (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_get_window (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_full_screen (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_set_cursor (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_warp_pointer (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_create_menu (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_destroy_menu (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_get_menu (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_set_menu (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_add_menu_entry (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_add_sub_menu (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_change_to_menu_entry (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_change_to_sub_menu (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_remove_menu_item (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_attach_menu (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_detach_menu (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_get (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_device_get (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_get_modifiers (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_bitmap_character (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int i, len; void *font = GetGlutEnum (objv[1]); char *string = Tcl_GetStringFromObj (objv[2], &len); for (i=0; i < len; i++) { glutBitmapCharacter (font, string[i]); } return 3; } static int glut_subcmd_bitmap_width (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_stroke_character (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int i; void *font = GetGlutEnum (objv[1]); char *string = Tcl_GetStringFromObj (objv[2], NULL); for (i=0; string[i] != '\0'; i++) { glutStrokeCharacter (font, string[i]); } return 3; } static int glut_subcmd_stroke_width (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_bitmap_length (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_stroke_length (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_wire_sphere (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_solid_sphere (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_wire_cone (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_solid_cone (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_wire_cube (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_solid_cube (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_wire_torus (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_solid_torus (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_wire_dodecahedron (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_solid_dodecahedron (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_wire_teapot (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_solid_teapot (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_wire_octahedron (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_solid_octahedron (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_wire_tetrahedron (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_solid_tetrahedron (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_wire_icosahedron (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_solid_icosahedron (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_video_resize_get (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_setup_video_resizing (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_stop_video_resizing (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_video_resize (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_video_pan (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_report_errors (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { return 1; } static int glut_subcmd_ignore_keyrepeat (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int value; if (objc < 2 || Tcl_GetBooleanFromObj (interp, objv[1], &value) == TCL_ERROR) { Tcl_AppendResult (interp, ": -ignorekeyrepeat .", NULL); return 0; } glutIgnoreKeyRepeat (value); return 2; } static GrFunctionList glutfunclist[] = { {"displayfunc", glut_subcmd_display_func}, {"reshapefunc", glut_subcmd_reshape_func}, {"keyboardfunc", glut_subcmd_keyboard_func}, {"keyboardupfunc", glut_subcmd_keyboard_up_func}, {"mousefunc", glut_subcmd_mouse_func}, {"motionfunc", glut_subcmd_motion_func}, {"passivemotionfunc", glut_subcmd_passive_motion_func}, {"entryfunc", glut_subcmd_entry_func}, {"visibilityfunc", glut_subcmd_visibility_func}, {"idlefunc", glut_subcmd_idle_func}, {"timerfunc", glut_subcmd_timer_func}, {"menustatefunc", glut_subcmd_menu_state_func}, {"specialfunc", glut_subcmd_special_func}, {"specialupfunc", glut_subcmd_special_up_func}, {"tabletmotionfunc", glut_subcmd_tablet_motion_func}, {"tabletbuttonfunc", glut_subcmd_tablet_button_func}, {"menustatusfunc", glut_subcmd_menu_status_func}, {"windowstatusfunc", glut_subcmd_window_status_func}, {"initwindowposition", glut_subcmd_window_position}, {"initwindowsize", glut_subcmd_window_size}, {"createwindow", glut_subcmd_create_window}, {"createsubwindow", glut_subcmd_create_subwindow}, {"destroywindow", glut_subcmd_destroy_window}, {"postredisplay", glut_subcmd_post_redisplay}, {"swapbuffers", glut_subcmd_swap_buffers}, {"getwindow", glut_subcmd_get_window}, {"setwindow", glut_subcmd_set_window}, {"setwindow_title", glut_subcmd_set_window_title}, {"seticontitle", glut_subcmd_set_icon_title}, {"positionwindow", glut_subcmd_position_window}, {"reshapewindow", glut_subcmd_reshape_window}, {"popwindow", glut_subcmd_pop_window}, {"pushwindow", glut_subcmd_push_window}, {"iconifywindow", glut_subcmd_iconify_window}, {"showwindow", glut_subcmd_show_window}, {"hidewindow", glut_subcmd_hide_window}, {"fullscreen", glut_subcmd_full_screen}, {"setcursor", glut_subcmd_set_cursor}, {"warppointer", glut_subcmd_warp_pointer}, {"createmenu", glut_subcmd_create_menu}, {"destroymenu", glut_subcmd_destroy_menu}, {"getmenu", glut_subcmd_get_menu}, {"setmenu", glut_subcmd_set_menu}, {"addmenuentry", glut_subcmd_add_menu_entry}, {"addsubmenu", glut_subcmd_add_sub_menu}, {"changetomenuentry", glut_subcmd_change_to_menu_entry}, {"changetosubmenu", glut_subcmd_change_to_sub_menu}, {"removemenuitem", glut_subcmd_remove_menu_item}, {"attachmenu", glut_subcmd_attach_menu}, {"detachmenu", glut_subcmd_detach_menu}, {"get", glut_subcmd_get}, {"deviceget", glut_subcmd_device_get}, {"getmodifiers", glut_subcmd_get_modifiers}, {"bitmapcharacter", glut_subcmd_bitmap_character}, {"bitmapwidth", glut_subcmd_bitmap_width}, {"strokecharacter", glut_subcmd_stroke_character}, {"strokewidth", glut_subcmd_stroke_width}, {"bitmaplength", glut_subcmd_bitmap_length}, {"strokelength", glut_subcmd_stroke_length}, {"wiresphere", glut_subcmd_wire_sphere}, {"solidsphere", glut_subcmd_solid_sphere}, {"wirecone", glut_subcmd_wire_cone}, {"solidcone", glut_subcmd_solid_cone}, {"wirecube", glut_subcmd_wire_cube}, {"solidcube", glut_subcmd_solid_cube}, {"wiretorus", glut_subcmd_wire_torus}, {"solidtorus", glut_subcmd_solid_torus}, {"wiredodecahedron", glut_subcmd_wire_dodecahedron}, {"soliddodecahedron", glut_subcmd_solid_dodecahedron}, {"wireteapot", glut_subcmd_wire_teapot}, {"solidteapot", glut_subcmd_solid_teapot}, {"wireoctahedron", glut_subcmd_wire_octahedron}, {"solidoctahedron", glut_subcmd_solid_octahedron}, {"wiretetrahedron", glut_subcmd_wire_tetrahedron}, {"solidtetrahedron", glut_subcmd_solid_tetrahedron}, {"wireicosahedron", glut_subcmd_wire_icosahedron}, {"solidicosahedron", glut_subcmd_solid_icosahedron}, {"videoresizeget", glut_subcmd_video_resize_get}, {"setupvideoresizing", glut_subcmd_setup_video_resizing}, {"stopvideoresizing", glut_subcmd_stop_video_resizing}, {"videoresize", glut_subcmd_video_resize}, {"videopan", glut_subcmd_video_pan}, {"reporterrors", glut_subcmd_report_errors}, {"ignorekeyrepeat", glut_subcmd_ignore_keyrepeat}, {NULL, NULL}, }; static int real_init (Tcl_Interp *interp) { static int do_init = 1; int i; int _new; Tcl_HashEntry *entry; if (do_init) { do_init = 0; Tcl_InitHashTable (&gl_enum_hash, TCL_STRING_KEYS); Tcl_InitHashTable (&gl_func_hash, TCL_STRING_KEYS); Tcl_InitHashTable (&glut_enum_hash, TCL_STRING_KEYS); Tcl_InitHashTable (&glut_func_hash, TCL_STRING_KEYS); Tcl_InitHashTable (&scene_hash, TCL_ONE_WORD_KEYS); Tcl_InitHashTable (&glut_timer_hash, TCL_ONE_WORD_KEYS); Tcl_InitHashTable (&cache_hash, TCL_STRING_KEYS); obj_x = Tcl_NewStringObj ("X", 1); obj_y = Tcl_NewStringObj ("Y", 1); obj_width = Tcl_NewStringObj ("WIDTH", 5); obj_height = Tcl_NewStringObj ("HEIGHT", 6); obj_state = Tcl_NewStringObj ("STATE", 5); obj_status = Tcl_NewStringObj ("STATUS", 6); obj_key = Tcl_NewStringObj ("KEY", 3); obj_button = Tcl_NewStringObj ("BUTTON", 6); obj_value = Tcl_NewStringObj ("VALUE", 5); for (i=0; glwordlist[i].name != NULL; i++) { entry = Tcl_CreateHashEntry (&gl_enum_hash, glwordlist[i].name, &_new); Tcl_SetHashValue (entry, (ClientData) glwordlist[i].val); } for (i=0; glfunclist[i].name != NULL; i++) { entry = Tcl_CreateHashEntry (&gl_func_hash, glfunclist[i].name, &_new); Tcl_SetHashValue (entry, (ClientData) &glfunclist[i]); } for (i=0; glutwordlist[i].name != NULL; i++) { entry = Tcl_CreateHashEntry (&glut_enum_hash, glutwordlist[i].name, &_new); Tcl_SetHashValue (entry, (ClientData) glutwordlist[i].val); } for (i=0; glutfunclist[i].name != NULL; i++) { entry = Tcl_CreateHashEntry (&glut_func_hash, glutfunclist[i].name, &_new); Tcl_SetHashValue (entry, (ClientData) &glutfunclist[i]); } } Tcl_CreateObjCommand (interp, "gl", GlCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "glut", GlutCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "gr::scene", grSceneCmd, NULL, NULL); return TCL_OK; } int Glbind_Init (Tcl_Interp *interp) { main_interp = interp; return real_init (interp); } int Glbind_SafeInit (Tcl_Interp *interp) { return real_init (interp); }