2017-04-17 06:17:10 -06:00

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