520 lines
14 KiB
C++
Executable File
520 lines
14 KiB
C++
Executable File
/* Numbers.h - the Thunk family of classes - variable accessors for MAXScript
|
|
*
|
|
* Copyright (c) John Wainwright, 1996
|
|
*
|
|
*
|
|
*/
|
|
|
|
#ifndef _H_THUNKS
|
|
#define _H_THUNKS
|
|
|
|
#include "Name.h"
|
|
#include "Arrays.h"
|
|
#include "Rollouts.h"
|
|
#include "MouseTool.h"
|
|
|
|
#include "UIExtend.h"
|
|
|
|
/* ----------------------- Thunk ---------------------- */
|
|
visible_class (Thunk)
|
|
|
|
class Thunk : public Value
|
|
{
|
|
public:
|
|
Value* name;
|
|
BOOL clear_container; // outer-level prop in a prop sequence, clear current_container when done
|
|
|
|
classof_methods (Thunk, Value);
|
|
# define is_thunk(o) ((o)->_is_thunk())
|
|
# define is_indirect_thunk(o) ((o)->_is_indirect_thunk())
|
|
BOOL _is_thunk() { return TRUE; }
|
|
ScripterExport void gc_trace();
|
|
Thunk() : clear_container(FALSE), name(NULL) { }
|
|
|
|
Thunk* to_thunk() {return this; }
|
|
virtual Thunk* make_free_thunk(int level) { return NULL; }
|
|
void assign(Value* val) { assign_vf(&val, 1); }
|
|
|
|
ScripterExport Value* get_property(Value** arg_list, int count);
|
|
ScripterExport Value* set_property(Value** arg_list, int count);
|
|
};
|
|
|
|
/* -------------------- GlobalThunk ------------------- */
|
|
|
|
class GlobalThunk : public Thunk
|
|
{
|
|
public:
|
|
Value* cell;
|
|
|
|
ScripterExport GlobalThunk(Value* init_name) { init(init_name); }
|
|
ScripterExport GlobalThunk(Value* init_name, Value* init_val);
|
|
ScripterExport void init(Value* init_name);
|
|
# define is_globalthunk(p) ((p)->tag == INTERNAL_GLOBAL_THUNK_TAG)
|
|
|
|
ScripterExport Value* eval();
|
|
|
|
ScripterExport void gc_trace();
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
|
|
};
|
|
|
|
class ConstGlobalThunk : public GlobalThunk
|
|
{
|
|
public:
|
|
ConstGlobalThunk(Value* iname) : GlobalThunk(iname) { tag = INTERNAL_CONST_GLOBAL_THUNK_TAG; }
|
|
ConstGlobalThunk(Value* iname, Value* ival) : GlobalThunk(iname, ival) { tag = INTERNAL_CONST_GLOBAL_THUNK_TAG; }
|
|
# define is_constglobalthunk(p) ((p)->tag == INTERNAL_CONST_GLOBAL_THUNK_TAG)
|
|
|
|
Value* eval() { return cell->is_const() ? cell->copy_vf(NULL, 0) : cell; }
|
|
void collect() { delete this; }
|
|
|
|
Value* assign_vf(Value**arg_list, int count) { throw AssignToConstError (this); return &undefined; }
|
|
};
|
|
|
|
/* -------------------- SystemGlobalThunk ------------------- */
|
|
|
|
/* system globals are abstractions over some system state accessing functions, such as
|
|
* animation_range, current_renderer,e tc. */
|
|
|
|
class SystemGlobalThunk : public Thunk
|
|
{
|
|
Value* (*get_fn)();
|
|
Value* (*set_fn)(Value*);
|
|
public:
|
|
ScripterExport SystemGlobalThunk(Value* init_name, Value* (*iget)(), Value* (*iset)(Value*));
|
|
// LAM 4/1/00 - added following to prevent AF in name clash debugging output in HashTable::put_new()
|
|
# define is_systemglobalthunk(p) ((p)->tag == INTERNAL_SYS_GLOBAL_THUNK_TAG)
|
|
|
|
ScripterExport Value* eval();
|
|
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s) { s->printf(_T("SystemGlobal:%s"), name->to_string()); }
|
|
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
/* -------------------- LocalThunk ------------------- */
|
|
|
|
class LocalThunk : public Thunk
|
|
{
|
|
public:
|
|
int frame_level; // frame nest level at declaration
|
|
int index; // local var's index in local frame
|
|
|
|
LocalThunk(Value* init_name, int init_index, int iframe_lvl);
|
|
# define is_localthunk(p) ((p)->tag == INTERNAL_LOCAL_THUNK_TAG)
|
|
|
|
Thunk* make_free_thunk(int level);
|
|
|
|
Value* eval();
|
|
void collect() { delete this; }
|
|
void sprin1(CharStream* s);
|
|
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
class IndirectLocalThunk : public LocalThunk
|
|
{
|
|
public:
|
|
IndirectLocalThunk(Value* init_name, int init_index, int iframe_lvl) :
|
|
LocalThunk(init_name, init_index, iframe_lvl) { }
|
|
|
|
BOOL _is_indirect_thunk() { return TRUE; }
|
|
Thunk* make_free_thunk(int level);
|
|
|
|
Value* eval();
|
|
void collect() { delete this; }
|
|
void sprin1(CharStream* s) { s->printf(_T("&")); LocalThunk::sprin1(s); }
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
// ContextThunk created from an IndirectLocal/FreeThunk on entry to a MAXScript function apply
|
|
// to contain the callers frame context for evals and assigns
|
|
class ContextThunk : public Thunk
|
|
{
|
|
public:
|
|
Thunk* thunk; // the wrapped thunk
|
|
Value** frame; // callers frame
|
|
|
|
ENABLE_STACK_ALLOCATE(ContextLocalThunk);
|
|
|
|
ContextThunk(Thunk* thunk, Value** frame) :
|
|
thunk(thunk), frame(frame) { }
|
|
|
|
void collect() { delete this; }
|
|
void sprin1(CharStream* s) { s->printf(_T("&")); thunk->sprin1(s); }
|
|
|
|
Value* eval();
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
/* -------------------- FreeThunk ------------------- */
|
|
|
|
class FreeThunk : public Thunk
|
|
{
|
|
public:
|
|
int level; // how many levels to reach back
|
|
int index; // index there
|
|
FreeThunk(Value* init_name, int level, int index);
|
|
# define is_freethunk(p) ((p)->tag == INTERNAL_FREE_THUNK_TAG)
|
|
|
|
Thunk* make_free_thunk(int level);
|
|
|
|
void collect() { delete this; }
|
|
void sprin1(CharStream* s);
|
|
|
|
Value* eval();
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
class IndirectFreeThunk : public FreeThunk
|
|
{
|
|
public:
|
|
IndirectFreeThunk(Value* init_name, int level, int index) :
|
|
FreeThunk(init_name, level, index) { }
|
|
|
|
BOOL _is_indirect_thunk() { return TRUE; }
|
|
Thunk* make_free_thunk(int level);
|
|
|
|
void collect() { delete this; }
|
|
void sprin1(CharStream* s) { s->printf(_T("&")); FreeThunk::sprin1(s); }
|
|
|
|
Value* eval();
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
/* -------------------- ClosureFreeThunk ------------------- */
|
|
|
|
class ClosureFreeThunk : public Thunk
|
|
{
|
|
public:
|
|
ScripterExport Value* eval();
|
|
|
|
void gc_trace();
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
ClosureFreeThunk();
|
|
~ClosureFreeThunk();
|
|
};
|
|
|
|
/* -------------------- PropertyThunk ------------------- */
|
|
|
|
class PropertyThunk : public Thunk
|
|
{
|
|
public:
|
|
Value* target_code; // code to eval to get target
|
|
Value* property_name; // property name
|
|
getter_vf getter; // getter virtual fn for built-in properties
|
|
setter_vf setter; // setter " " " "
|
|
|
|
PropertyThunk(Value* target, Value* prop_name);
|
|
PropertyThunk(Value* target, Value* prop_name, getter_vf get_fn, setter_vf set_fn);
|
|
|
|
void gc_trace();
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
# define is_propertythunk(p) ((p)->tag == INTERNAL_PROP_THUNK_TAG)
|
|
|
|
ScripterExport Value* eval();
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
Value* op_assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
// a PropThunk subclass that is used when a Prop access occurs in a function call
|
|
// this is basically a hack to support OLE client method calls, since OLE IDISPATCH
|
|
// cannot distinguish methods from props
|
|
class FnCallPropertyThunk : public PropertyThunk
|
|
{
|
|
public:
|
|
FnCallPropertyThunk(Value* target, Value* prop_name, getter_vf get_fn, setter_vf set_fn)
|
|
: PropertyThunk (target, prop_name, get_fn, set_fn) {}
|
|
void collect() { delete this; }
|
|
ScripterExport Value* eval();
|
|
};
|
|
|
|
#ifdef USE_PROPERTY_PATH_THUNKS
|
|
/* PropertyPathThunk encodes a multi-level property access, such as $foo.twist.gizmo.pos.x
|
|
* in a single thunk so that MAXWrapper objects (and others that want) can look-ahead doing the whole path at once and
|
|
* not need backreferencing leaf-values for some of the funnier pseudo property accesses
|
|
* allowed in MAXScript */
|
|
|
|
class PropertyPathThunk : public Thunk
|
|
{
|
|
Value* target_code; // code to eval to get target
|
|
Array* property_path; // list of property names
|
|
|
|
public:
|
|
PropertyPathThunk(Value* target, Array* prop_path);
|
|
|
|
void gc_trace();
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
Value* append_property(Value* prop_name);
|
|
|
|
ScripterExport Value* eval();
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
#endif
|
|
|
|
/* -------------------- IndexThunk ------------------- */
|
|
|
|
class IndexThunk : public Thunk
|
|
{
|
|
Value* target_code; // code to eval to get target
|
|
Value* index_code; // code to eval to get index
|
|
|
|
public:
|
|
IndexThunk(Value* index);
|
|
|
|
# define is_indexthunk(o) ((o)->tag == INTERNAL_INDEX_THUNK_TAG)
|
|
void gc_trace();
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
Value* set_target(Value* targ) { target_code = targ; return this; }
|
|
ScripterExport Value* eval();
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
/* -------------------- RolloutControlThunk ------------------- */
|
|
|
|
class RolloutControlThunk : public Thunk
|
|
{
|
|
public:
|
|
int index;
|
|
Rollout* rollout;
|
|
|
|
RolloutControlThunk(Value* name, int control_index, Rollout* rollout);
|
|
BOOL _is_rolloutthunk() { return 1; }
|
|
# define is_rolloutthunk(o) ((o)->_is_rolloutthunk())
|
|
|
|
Value* eval() { return rollout->controls[index]; }
|
|
|
|
void ScripterExport gc_trace();
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
/* -------------------- RolloutLocalThunk ------------------- */
|
|
|
|
class RolloutLocalThunk : public Thunk
|
|
{
|
|
public:
|
|
int index;
|
|
Rollout* rollout;
|
|
|
|
RolloutLocalThunk(Value* name, int control_index, Rollout* rollout);
|
|
BOOL _is_rolloutthunk() { return 1; }
|
|
|
|
ScripterExport Value* eval();
|
|
|
|
void gc_trace();
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
class ConstRolloutLocalThunk : public RolloutLocalThunk
|
|
{
|
|
public:
|
|
ConstRolloutLocalThunk(Value* name, int control_index, Rollout* rollout)
|
|
: RolloutLocalThunk(name, control_index, rollout) { }
|
|
|
|
void collect() { delete this; }
|
|
|
|
Value* assign_vf(Value**arg_list, int count) { throw AssignToConstError (this); return &undefined; }
|
|
};
|
|
|
|
/* -------------------- ToolLocalThunk ------------------- */
|
|
|
|
class ToolLocalThunk : public Thunk
|
|
{
|
|
public:
|
|
int index;
|
|
MouseTool* tool;
|
|
|
|
ToolLocalThunk(Value* name, int iindex, MouseTool* tool);
|
|
|
|
ScripterExport Value* eval();
|
|
|
|
void gc_trace();
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
/* -------------------- CodeBlockLocalThunk ------------------- */
|
|
|
|
class CodeBlock;
|
|
|
|
class CodeBlockLocalThunk : public Thunk
|
|
{
|
|
public:
|
|
int index;
|
|
CodeBlock* block;
|
|
|
|
CodeBlockLocalThunk(Value* name, int iindex, CodeBlock* block);
|
|
|
|
ScripterExport Value* eval();
|
|
|
|
void gc_trace();
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
/* -------------------- RCMenuItemThunk ------------------- */
|
|
|
|
class RCMenuItemThunk : public Thunk
|
|
{
|
|
public:
|
|
int index;
|
|
RCMenu* rcmenu;
|
|
|
|
RCMenuItemThunk(Value* name, int item_index, RCMenu* menu);
|
|
BOOL _is_rolloutthunk() { return 1; }
|
|
# define is_rcmenuthunk(o) ((o)->_is_rcmenuthunk())
|
|
|
|
Value* eval() { return rcmenu->items[index]; }
|
|
|
|
void ScripterExport gc_trace();
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
/* -------------------- RCMenuLocalThunk ------------------- */
|
|
|
|
class RCMenuLocalThunk : public Thunk
|
|
{
|
|
public:
|
|
int index;
|
|
RCMenu* rcmenu;
|
|
|
|
RCMenuLocalThunk(Value* name, int iindex, RCMenu* menu);
|
|
BOOL _is_rcmenuthunk() { return 1; }
|
|
|
|
ScripterExport Value* eval();
|
|
|
|
void gc_trace();
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
/* -------------------- PluginLocalThunk ------------------- */
|
|
|
|
class PluginLocalThunk : public Thunk
|
|
{
|
|
public:
|
|
int index; // access via current_plugin thread local
|
|
BOOL re_init; // indicate whether this local needs re-initialization on a redefinition (say for local rollouts, fns, etc.)
|
|
|
|
PluginLocalThunk(Value* name, int iindex, BOOL re_init = FALSE);
|
|
# define is_pluginlocalthunk(p) ((p)->tag == INTERNAL_PLUGIN_LOCAL_THUNK_TAG)
|
|
|
|
ScripterExport Value* eval();
|
|
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
class ConstPluginLocalThunk : public PluginLocalThunk
|
|
{
|
|
public:
|
|
ConstPluginLocalThunk(Value* name, int iindex, BOOL re_init = FALSE) : PluginLocalThunk(name, iindex, re_init) { }
|
|
void collect() { delete this; }
|
|
Value* assign_vf(Value**arg_list, int count) { throw AssignToConstError (this); return &undefined; }
|
|
};
|
|
|
|
/* -------------------- PluginParamThunk ------------------- */
|
|
|
|
class PluginParamThunk : public Thunk
|
|
{
|
|
public:
|
|
PluginParamThunk(Value* name);
|
|
|
|
ScripterExport Value* eval();
|
|
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
|
|
Value* get_container_property(Value* prop, Value* cur_prop);
|
|
Value* set_container_property(Value* prop, Value* val, Value* cur_prop);
|
|
};
|
|
|
|
#define push_plugin(_pi) \
|
|
MSPlugin* _save_cp = thread_local(current_plugin); \
|
|
thread_local(current_plugin) = _pi;
|
|
|
|
#define pop_plugin() \
|
|
thread_local(current_plugin) = _save_cp;
|
|
|
|
/* -------------------- StructMemberThunk ------------------- */
|
|
|
|
class StructMemberThunk : public Thunk
|
|
{
|
|
public:
|
|
int index; // access via current_plugin thread local
|
|
|
|
StructMemberThunk(Value* name, int iindex);
|
|
|
|
ScripterExport Value* eval();
|
|
|
|
void collect() { delete this; }
|
|
ScripterExport void sprin1(CharStream* s);
|
|
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
/* -------------------- ThunkReference ------------------- */
|
|
// indirect thunk (eg, &foo)
|
|
|
|
class ThunkReference : public Thunk
|
|
{
|
|
public:
|
|
Thunk* target; // the target thunk
|
|
|
|
ScripterExport ThunkReference(Thunk* target);
|
|
# define is_thunkref(p) ((p)->tag == INTERNAL_THUNK_REF_TAG)
|
|
|
|
void gc_trace();
|
|
void collect() { delete this; }
|
|
void sprin1(CharStream* s);
|
|
|
|
Value* eval();
|
|
};
|
|
|
|
class DerefThunk : public Thunk // generated by a '*' prefix operator
|
|
{
|
|
public:
|
|
Value* target; // the target to deref
|
|
|
|
ScripterExport DerefThunk(Value* target);
|
|
|
|
void gc_trace();
|
|
void collect() { delete this; }
|
|
void sprin1(CharStream* s) { s->printf(_T("*")); target->sprin1(s); }
|
|
|
|
Value* eval();
|
|
Value* assign_vf(Value**arg_list, int count);
|
|
};
|
|
|
|
#endif
|