maxscript.h

Go to the documentation of this file.
00001 /*      MAXScript.h - main include for MAXScript sources
00002  *
00003  *      Copyright (c) John Wainwright, 1996
00004  *      
00005  *
00006  */
00007 
00008 #pragma once
00009 
00010 #ifndef WIN32_LEAN_AND_MEAN
00011 #define WIN32_LEAN_AND_MEAN     // trims win32 includes
00012 #endif
00013 
00014 #include <stdlib.h> 
00015 #include <stdio.h>
00016 #include <windows.h>
00017 #include <float.h>
00018 #include <math.h>
00019 
00020 // forward declarations
00021 class Value;
00022 class CharStream;
00023 class Rollout;
00024 class MAXScriptException;
00025 class MSPlugin;
00026 class Struct;
00027 class MSZipPackage;
00028 class String;
00029 class StringStream;
00030 class IMXSDebugger;
00031 class Object;
00032 class Interface;
00033 class FPValue;
00034 class Control;
00035 class INode;
00036 class Bitmap;
00037 class BitmapInfo;
00038 class HashTable;
00039 class RandGenerator;
00040 class Listener;
00041 
00042 // Includes to make this file compile
00043 #include "ScripterExport.h"
00044 #include "kernel\exceptions.h"
00045 #include "kernel\interupts.h"
00046 #include "..\WindowsDefines.h"
00047 #include "..\strbasic.h"
00048 #include "..\ref.h"
00049 #include "..\DefaultActions.h" // for DEFAULTACTIONS_LOGMSG
00050 
00051 // Includes that are useful for the maxscript library
00052 #include "..\dllutilities.h"
00053 #include "..\iFnPub.h"
00054 #include "..\IParamm2.h"
00055 #include "kernel\value.h"
00056 #include "util\sceneio.h"
00057 #include "foundation\arrays.h"
00058 #include "foundation\hashtable.h"
00059 #include "foundation\name.h"
00060 #include "foundation\streams.h"
00061 #include "foundation\strings.h"
00062 #include "foundation\functions.h"
00063 #include "compiler\thunks.h"
00064 
00065 #define NOT_SUPPORTED_BY_PRODUCT(fn)    \
00066     throw RuntimeError (_M("Feature not available: "), _M(#fn)); 
00067 
00068 #define END             NULL                    // null varargs arg list terminator
00069 
00070 #define MAXSCRIPT_UTILITY_CLASS_ID  Class_ID(0x4d64858, 0x16d1751d)
00071 #define MAX_SCRIPT_DIR              _M("scripts")
00072 #define SCRIPT_AUTOLOAD_DIR         _M("Startup\\")
00073 
00074 // check whether we are UNICODE or Code page 0 (==> no mbcs code)
00075 #ifdef _UNICODE
00076 #   define  no_mb_chars     TRUE
00077 #   define  bytelen(s)      (sizeof(mwchar_t) * wcslen(s))
00078 #else
00079 #   define  no_mb_chars     (MB_CUR_MAX == 1)
00080 #   define  bytelen(s)      strlen(s)
00081 #endif
00082 
00083 // the output from these functions are used for %g float printing, so must return double
00084 inline double EPS(float v)  { return _isnan(v) ? (v) : fabs(v) < FLT_EPSILON ? 0.0 : (v); }  // small number round down for %g float printing
00085 inline double EPS(double v) { return _isnan(v) ? (v) : fabs(v) < DBL_EPSILON ? 0.0 : (v); }  // small number round down for %g double printing
00086 inline double EPS(int v)    { return (double)v; }
00087 inline double EPS(INT64 v)  { return (double)v; }
00088 inline double EPS(DWORD v)  { return (double)v; }
00089 inline double EPS(short v)  { return (double)v; }
00090 
00091 /* MAXScript-specific window messages */
00092 
00093 #define MXS_ADD_ROLLOUT_PAGE        (WM_USER + 0x100)
00094 #define MXS_DELETE_ROLLOUT_PAGE     (WM_USER + 0x101)
00095 #define MXS_REDRAW_VIEWS            (WM_USER + 0x102)
00096 #define MXS_EDIT_SCRIPT             (WM_USER + 0x103)
00097 #define MXS_NEW_SCRIPT              (WM_USER + 0x104)
00098 #define MXS_DISPLAY_BITMAP          (WM_USER + 0x105)
00099 #define MXS_ERROR_MESSAGE_BOX       (WM_USER + 0x106)
00100 #define MXS_PRINT_STRING            (WM_USER + 0x107)
00101 #define MXS_LISTENER_EVAL           (WM_USER + 0x108)
00102 #define MXS_MESSAGE_BOX             (WM_USER + 0x109)
00103 #define MXS_INITIALIZE_MAXSCRIPT    (WM_USER + 0x10A)
00104 #define MXS_KEYBOARD_INPUT          (WM_USER + 0x10B)
00105 #define MXS_SHOW_SOURCE             (WM_USER + 0x10C)
00106 #define MXS_TAKE_FOCUS              (WM_USER + 0x10D)
00107 #define MXS_STOP_CREATING           (WM_USER + 0x10E)
00108 #define MXS_CLOSE_DOWN              (WM_USER + 0x10F)
00109 #define MXS_STOP_EDITING            (WM_USER + 0x110)
00110 #define MXS_LOAD_STARTUP_SCRIPTS    (WM_USER + 0x111)
00111 #define MXS_EXECUTE_MACRO           (WM_USER + 0x112)
00112 #define MXS_RESTART_EDITING         (WM_USER + 0x113)
00113 #define MXS_NOTIFY_REF_DEPENDENTS   (WM_USER + 0x114)
00114 #define MSPLUGINCLASS_STOPEDITING   (WM_USER + 0x115)
00115 #define MSPLUGINCLASS_RESTARTEDITING    (WM_USER + 0x116)
00116 
00117 struct message_box_data     // LPARAM for MXS_MESSAGE_BOX contains a pointer to this structure
00118 {
00119     MCHAR* title;
00120     MCHAR* message;
00121     BOOL beep;
00122     int flags;
00123     BOOL result;
00124 };
00125 
00126 class mxs_notify_ref_data           // LPARAM for MXS_NOTIFY_REF_DEPENDENTS contains a pointer to this class
00127 {
00128 public:
00129     RefTargetHandle hSender;
00130     Interval changeInt;
00131     PartID partID;
00132     RefMessage message;
00133     SClass_ID sclass;
00134     BOOL propagate;
00135     RefTargetHandle hTarg;
00136     RefResult result;
00137     
00138     mxs_notify_ref_data(RefTargetHandle hSender, PartID partID = PART_ALL, RefMessage message = REFMSG_CHANGE) : 
00139         changeInt(FOREVER), partID(partID), message(message), sclass(NOTIFY_ALL), propagate(TRUE),
00140         hTarg(NULL), hSender(hSender), result(REF_SUCCEED)
00141         {
00142             DbgAssert(hSender);
00143         }
00144 };
00145 
00146 #include "kernel\MAXScript_TLS.h"
00147 
00148 /* error handlers */
00149 
00150 void out_of_memory();
00151 void bad_delete();
00152 
00153 /* arg count check & keyword arg accessors (assume conventional names for arg_list & count in using function) */
00154 
00155 ScripterExport Value* _get_key_arg(Value** arg_list, int count, Value* key_name);
00156 ScripterExport Value* _get_key_arg_or_default(Value** arg_list, int count, Value* key_name, Value* def);
00157 
00158 #define key_arg(key)                    _get_key_arg(arg_list, count, n_##key)
00159 #define key_arg_or_default(key, def)    _get_key_arg_or_default(arg_list, count, n_##key##, def)
00160 #define int_key_arg(key, var, def)      ((var = _get_key_arg(arg_list, count, n_##key)) == &unsupplied ? def : var->to_int())
00161 #define intptr_key_arg(key, var, def)   ((var = _get_key_arg(arg_list, count, n_##key)) == &unsupplied ? def : var->to_intptr())
00162 #define float_key_arg(key, var, def)    ((var = _get_key_arg(arg_list, count, n_##key)) == &unsupplied ? def : var->to_float())
00163 #define bool_key_arg(key, var, def)     ((var = _get_key_arg(arg_list, count, n_##key)) == &unsupplied ? def : var->to_bool())
00164 #define interval_key_arg(key, var, def)     ((var = _get_key_arg(arg_list, count, n_##key)) == &unsupplied ? def : var->to_interval())
00165 #define timevalue_key_arg(key, var, def)    ((var = _get_key_arg(arg_list, count, n_##key)) == &unsupplied ? def : var->to_timevalue())
00166 #define node_key_arg(key, var, def)         ((var = _get_key_arg(arg_list, count, n_##key)) == &unsupplied ? def : var->to_node())
00167 #define string_key_arg(key, var, def)       ((var = _get_key_arg(arg_list, count, n_##key)) == &unsupplied ? def : var->to_string())
00168 
00169 #define check_arg_count(fn, w, g)           if ((w) != (g)) throw ArgCountError (_M(#fn), w, g)
00170 #define check_gen_arg_count(fn, w, g)       if ((w) != (g + 1)) throw ArgCountError (_M(#fn), w, g + 1)
00171 #define check_arg_count_with_keys(fn, w, g) if (!(g == w || (g > w && arg_list[w] == &keyarg_marker))) throw ArgCountError (_M(#fn), w, count_with_keys())
00172 #define check_gen_arg_count_with_keys(fn, w, g) if (!(g == w || (g > w && arg_list[w-1] == &keyarg_marker))) throw ArgCountError (_M(#fn), w, count_with_keys() + 1)
00173 #define count_with_keys()                   _count_with_keys(arg_list, count)
00174 
00175 /* for functions that return a boolean */
00176 
00177 #define bool_result(val)                    ((val) ? &true_value : &false_value)
00178 
00179 /* for testing a value to ensure that it is within range */
00180 
00181 // following only valid for integer and float range checking
00182 #define MXS_range_check(_val, _lowerLimit, _upperLimit, _desc)      \
00183     if (_val < _lowerLimit || _val > _upperLimit) {                 \
00184         MCHAR buf[256];                                             \
00185         MCHAR buf2[128];                                            \
00186         _tcscpy(buf,_desc);                                         \
00187         _tcscat(buf,_M(" < "));                                     \
00188         _sntprintf(buf2, 128, _M("%g"), EPS(_lowerLimit));          \
00189         _tcscat(buf,buf2);                                          \
00190         _tcscat(buf,_M(" or > "));                                  \
00191         _sntprintf(buf2, 128, _M("%g"), EPS(_upperLimit));          \
00192         _tcscat(buf,buf2);                                          \
00193         _tcscat(buf,_M(": "));                                      \
00194         _sntprintf(buf2, 128, _M("%g"), EPS(_val));                 \
00195         _tcscat(buf,buf2);                                          \
00196         throw RuntimeError (buf);                                   \
00197     }
00198 
00199 
00200 /* value local macros - for managing C local variable references to Value*'s for the collector - see Collectable.cpp */
00201 
00202 #include "macros\value_locals.h"
00203 
00204 /* general utilities */
00205 
00206 ScripterExport MCHAR* save_string(const MCHAR* str);
00207 MCHAR  wputch(HWND w, MCHAR* buf, MCHAR* bufp, const MCHAR c);                  /* edit window output... */
00208 MCHAR* wputs(HWND w, MCHAR* buf, MCHAR* bufp, const MCHAR *str);        
00209 int    wprintf(HWND w, MCHAR* buf, MCHAR* bufp, const MCHAR *format, ...);
00210 void   wflush(HWND w, MCHAR* buf, MCHAR* bufp);     
00211 #define mputs   thread_local(current_stdout)->puts  /* current MAXScript stdout output... */
00212 #define mputch  thread_local(current_stdout)->putch /* current MAXScript stdout output... */
00213 #define mprintf thread_local(current_stdout)->printf
00214 #define mflush  thread_local(current_stdout)->flush
00215 
00216 ScripterExport Object* Get_Object_Or_XRef_BaseObject(Object* obj);
00217 
00218 // Converts string to valid property or class name, replacing invalid characters with an underscore.
00219 // For example, 'Vol. Select' would be converted to 'Vol__Select'
00220 // Type corresponds to PROPNAME, CLASSNAME, or DROPSPACES where:
00221 //  PROPNAME - spaces in string are converted to underscore
00222 //  CLASSNAME - spaces and punctuation in string are converted to underscore
00223 //  DROPSPACES - removes underscore characters in string
00224 // if bStripTrailing is true, after conversion any underscore characters at end of string are removed
00225 // Return value is how many characters were converted to an underscore
00226 // This method is MBCS-aware
00227 static const int PROPNAME = 1;
00228 static const int CLASSNAME = 2;
00229 static const int DROPSPACES = 3;
00230 
00231 ScripterExport int namify(MCHAR* n, int type, bool bStripTrailing = true);
00232 
00233  
00234 ScripterExport void  install_utility_page(Rollout* rollout);
00235 
00236 #include "kernel\MaxscriptTypedefs.h"
00237 
00238 /* MAXScript signal flags */
00239 
00240 #define INTERRUPT_EVAL      0x0001
00241 #define EXIT_LISTENER       0x0002
00242 
00243 ScripterExport int      mxs_rand(); // resolution is 0 - 2^31-1
00244 ScripterExport INT64    mxs_rand64(); // resolution is 0 - 2^63-1
00245 ScripterExport void     mxs_seed(int);
00246 ScripterExport int      random_range(int from, int to);
00247 ScripterExport INT64    random_range(INT64 from, INT64 to);
00248 ScripterExport float    random_range(float from, float to);
00249 ScripterExport double   random_range(double from, double to);
00250 ScripterExport void     dlx_detaching(HINSTANCE hinstance);
00251 ScripterExport void     define_system_global(MCHAR* name, Value* (*getter)(), Value* (*setter)(Value*));
00252 // LAM 4/1/00 - added following to be able to overwrite existing global value in hash table.
00253 ScripterExport void     define_system_global_replace(MCHAR* name, Value* (*getter)(), Value* (*setter)(Value*));
00254 ScripterExport void     define_struct_global(MCHAR* name, MCHAR* struct_name, Value* (*getter)(), Value* (*setter)(Value*));
00255 extern ScripterExport HashTable* english_to_local;
00256 extern ScripterExport HashTable* local_to_english;
00257 extern ScripterExport BOOL      non_english_numerics;
00258 ScripterExport void     printable_name(MSTR& name);
00259 ScripterExport void     show_source_pos();
00260 ScripterExport void     show_listener();
00261 
00262 ScripterExport void     init_MAXScript();
00263 typedef void (*utility_installer)(Rollout* ro);
00264 ScripterExport void     set_utility_installer(utility_installer ui);
00265 ScripterExport void     reset_utility_installer();
00266 ScripterExport void     error_message_box(MAXScriptException& e, const MCHAR* caption);
00267 typedef Value* (*autocad_point_reader)(MCHAR* str);
00268 ScripterExport void     set_autocad_point_reader(autocad_point_reader apr);
00269 
00270 extern ScripterExport Interface* MAXScript_interface;
00271 extern ScripterExport Interface7* MAXScript_interface7;
00272 extern ScripterExport Interface8* MAXScript_interface8;
00273 extern ScripterExport Interface9* MAXScript_interface9;
00274 extern ScripterExport Interface11* MAXScript_interface11;
00275 extern ScripterExport Interface13* MAXScript_interface13;
00276 
00277 extern ScripterExport BOOL      escape_enabled; // RK: 05/20/02, 5.0 or later only
00278 extern ScripterExport BOOL      MAXScript_detaching;
00279 extern ScripterExport BOOL      MAXScript_running;
00280 extern ScripterExport HWND      main_thread_window;
00281 extern ScripterExport BOOL      progress_bar_up;
00282 
00283 
00284 // obsolete variables for error handling, use methods below instead
00286 MAX_DEPRECATED extern BOOL      trace_back_active;
00288 MAX_DEPRECATED extern BOOL      disable_trace_back;
00290 MAX_DEPRECATED extern int       trace_back_levels;
00291 
00292 // accessors for thread values for error handling
00293 ScripterExport BOOL get_error_trace_back_active();
00294 ScripterExport void set_error_trace_back_active( BOOL isTraceBackActive );
00295 ScripterExport BOOL get_error_trace_back_disabled();
00296 ScripterExport void set_error_trace_back_disabled(BOOL isTraceBackDisabled);
00297 ScripterExport int  get_error_trace_back_level();
00298 ScripterExport void set_error_trace_back_level(int level);
00299 ScripterExport void increment_error_trace_back_level();
00300 
00301 // LAM - 4/28/03
00303 
00317 ScripterExport BOOL     ExecuteMAXScriptScript(MCHAR* s, BOOL quietErrors = FALSE, FPValue* fpv = NULL);
00318 
00319 // LAM - 8/19/05
00320 // Returns Value* resulting from evaluating source. If res is non-NULL, will contain TRUE on return if script was executed 
00321 // successfully, FALSE if not. Evaluation is within a try/catch, so this function will not throw.
00322 ScripterExport Value*   ExecuteScript(CharStream* source, bool *res);
00323 
00324 // LAM - 6/24/03
00325 // Method for processing input value or array for default action value. Current recognized values are:
00326 // #logMsg, #logToFile, #abort, and integer values. Actions are converted to DWORD where bit 0 is log to Default Action 
00327 // system log, bit 1 is log to log file, and bit 2 is abort/cancel (if applicable).
00328 ScripterExport DWORD        ProcessDefaultActionVal (Value* inpActionVal, DWORD defaultAction = DEFAULTACTIONS_LOGMSG);
00329 
00330 // LAM - 3/25/05 - the MXS debugger interface. A Singleton.
00331 extern ScripterExport IMXSDebugger* theMXSDebugger;
00332 
00333 #define type_check(val, cl, where) if (val->tag != class_tag(cl)) throw TypeError (where, val, &cl##_class);
00334 
00335 // macros for setting numeric printing to English locale and back again - all numeric output in MAXScript is English
00336 #define set_english_numerics()                      \
00337     MCHAR* locale;                                  \
00338     MCHAR slocale[256];                             \
00339     if (non_english_numerics != NULL)               \
00340     {                                               \
00341         locale = setlocale(LC_NUMERIC, NULL);       \
00342         _tcsncpy(slocale, locale, sizeof(slocale)/sizeof(slocale[0]));  \
00343         setlocale(LC_NUMERIC, "C");                 \
00344     }
00345 
00346 #define reset_numerics()                            \
00347     if (non_english_numerics != NULL)               \
00348         setlocale(LC_NUMERIC, slocale); 
00349 
00350 #define SOURCE_STREAM_ENCRYPTED_FLAG 1 /* flag set in thread local source_flags when source is encrypted  */
00351 
00352 extern ScripterExport HashTable* globals;
00353 extern ScripterExport HashTable* persistents;
00354 extern ScripterExport Listener*  the_listener;
00355 extern ScripterExport HWND       the_listener_window;
00356 ScripterExport void       listener_message(UINT iMsg, WPARAM wParam, LPARAM lParam, BOOL block_flag);
00357 
00358 
00359 extern ScripterExport RandGenerator* ClassIDRandGenerator;
00360 
00361 inline int _count_with_keys(Value** arg_list, int count)
00362 {
00363     // compute # args before any key-args
00364     for (int i = 0; i < count; i++)
00365         if (arg_list[i] == (Value*)&keyarg_marker)
00366             return i;
00367     return count;
00368 }
00369 
00370 ScripterExport BOOL GetPrintAllElements(); // get whether to print all elements of arrays, meshselection, BigMatrix, etc.
00371 ScripterExport BOOL SetPrintAllElements(BOOL); // set whether to print all elements of arrays, meshselection, BigMatrix, etc. Returns old value
00372 
00373 ScripterExport bool CanChangeGroupFlags(INode* node); // Since grouping break the node hierarchy used to represent ALOs, we don't allow it
00374 
00375 // get MXS path to object. This is the path shown in macro recorder. If resolved, returns TRUE and places path in name
00376 ScripterExport BOOL Find_MXS_Name_For_Obj(Animatable* obj, MSTR &name, BOOL explicitName = TRUE); 
00377 
00378 // methods to convert LF strings to CR/LF strings and back
00379 ScripterExport void Replace_LF_with_CRLF(MSTR &string);
00380 ScripterExport void Replace_CRLF_with_LF(MSTR &string);
00381 
00382 ScripterExport void checkFileOpenModeValidity(MCHAR* mode); // checks validity of mode for fopen commands, and throws error if not valid
00383 
00384 ScripterExport BOOL max_name_match(MCHAR* max_name, MCHAR* pattern, bool caseSensitive = false);// returns true if name matches pattern. Will test original and translated name.
00385 
00386 // create and return a Bitmap* based on the BitmapInfo. Basically just a wrapped version of
00387 // TheManager->Create(bitmapInfo) that throws a runtime error if creation is unsuccessful.
00388 ScripterExport Bitmap* CreateBitmapFromBitmapInfo(BitmapInfo& bitmapInfo);
00389 
00390 // get the storable bitmapinfo type for the specified bitmapinfo type
00391 ScripterExport int GetStorableBitmapInfoTypeForBitmapInfoType(int type);
00392 
00393 // MAXScript preferences.  An instance of this class lives in CORE and is accessible to both CORE and MAXScript
00394 class MAXScriptPrefs
00395 {
00396 public:
00397     int     loadStartupScripts;
00398     int     loadSaveSceneScripts;
00399     int     loadSavePersistentGlobals;
00400     MSTR    font;
00401     int     fontSize;
00402     int     autoOpenListener;
00403     float   initialHeapSize;
00404     int     enableMacroRecorder;
00405     int     showCommandPanelSwitch;
00406     int     showToolSelections;
00407     int     showMenuSelections;
00408     int     absoluteSceneNames;
00409     int     absoluteSubObjects;
00410     int     absoluteTransforms;
00411     int     useFastNodeNameLookup;
00412     int     showGCStatus;
00413     int     showEditorPath;
00414     int     useMultiThreadedUsedMacroscriptCompile;
00415     int     logUsedMacroscriptCompiles;
00416     int     preValidateResourceValues;
00417 
00418     MAXScriptPrefs() { Reset(); }
00419     virtual ~MAXScriptPrefs() { }
00420     void    Reset()
00421     {
00422         // MAXScript preference defaults
00423         loadStartupScripts =        TRUE;
00424         loadSaveSceneScripts =      TRUE;
00425         loadSavePersistentGlobals = TRUE;
00426         font =                      _M("Courier New");
00427         fontSize =                  9;
00428         initialHeapSize =           15.0;
00429         autoOpenListener =          FALSE;
00430         enableMacroRecorder =       FALSE;
00431         showCommandPanelSwitch =    FALSE;
00432         showToolSelections =        FALSE;
00433         showMenuSelections =        FALSE;
00434         absoluteSceneNames =        FALSE;
00435         absoluteSubObjects =        FALSE;
00436         absoluteTransforms =        FALSE;
00437         useFastNodeNameLookup =     TRUE;
00438         showGCStatus =              FALSE;
00439         showEditorPath =            TRUE;
00440         useMultiThreadedUsedMacroscriptCompile =    TRUE;
00441         logUsedMacroscriptCompiles =                FALSE;
00442         preValidateResourceValues =                 FALSE;
00443     }
00444 
00445     virtual void LoadMAXScriptPreferences();
00446     virtual void SaveMAXScriptPreferences();
00447 };
00448 
00449 // temporarily adds license for various activeX controls
00450 // ctor registers the license if needed, dtor removes them
00451 class ActiveXLicensor
00452 {
00453     DWORD licenseAdded; // acts as bitfield. Each bit signifies whether a specifc license was added.
00454 public:
00455     ScripterExport ActiveXLicensor();
00456     ScripterExport ~ActiveXLicensor();
00457 };
00458 
00459 // Exception safe helper class for controlling temporary changing of quiet mode. ctor sets quiet mode to 
00460 // specified state, Restore resets to initial state, and dtor resets to initial state if Restore has not been run.
00461 class TempQuietMode
00462 {
00463 public:
00464     ScripterExport TempQuietMode (BOOL newState = TRUE);
00465     ScripterExport ~TempQuietMode();
00466     ScripterExport void Restore();
00467 private:
00468     BOOL oldState;
00469     bool needsRestore;
00470 };
00471 
00472 // Exception safe helper class for controlling temporary changing of BitmapManager silent mode. ctor sets silent mode to 
00473 // specified state, Restore resets to initial state, and dtor resets to initial state if Restore has not been run.
00474 class TempBitmapManagerSilentMode
00475 {
00476 public:
00477     ScripterExport TempBitmapManagerSilentMode (BOOL newState = TRUE);
00478     ScripterExport ~TempBitmapManagerSilentMode();
00479     ScripterExport void Restore();
00480 private:
00481     BOOL oldState;
00482     bool needsRestore;
00483 };
00484