source: cpp/frams/vm/classes/3dobject.cpp @ 109

Last change on this file since 109 was 109, checked in by sz, 10 years ago

source reorganization (see README)
new feature added: part/joint shapes (see frams/_demos/part_shapes.cpp)

  • Property svn:eol-style set to native
File size: 16.0 KB
Line 
1#include <frams/util/3d.h>
2#include "3dobject.h"
3#include <frams/param/param.h>
4#include "collectionobj.h"
5
6ParamEntry* Pt3D_Ext::getStaticParamtab()
7{
8#define FIELDSTRUCT Pt3D_Ext
9static ParamEntry paramtab[]=
10{
11{"XYZ",1,18,"XYZ","3D vector"},
12
13{"x",0,PARAM_NOSTATIC,"x","f",FIELD(p.x),},
14{"y",0,PARAM_NOSTATIC,"y","f",FIELD(p.y),},
15{"z",0,PARAM_NOSTATIC,"z","f",FIELD(p.z),},
16{"new",0,0,"create new XYZ object","p oXYZ(f x,f y,f z)",PROCEDURE(p_new),"3D vectors objects can be also created using the (x,y,z) notation, i.e. var v=(1,2,3) is the same as var v=XYZ.new(1,2,3);",},
17{"newFromVector",0,0,"create new XYZ object","p oXYZ(oVector)",PROCEDURE(p_newFromVector),"used for deserialization"},
18{"clone",0,PARAM_NOSTATIC,"create new XYZ object copying the coordinates","p oXYZ()",PROCEDURE(p_clone),"Note: copying object references does not create new objects. Use clone() if a new object is needed.\n\nExample:\nvar o1=(1,2,3), o2=o1, o3=o1.clone();\no1.y=9999;\n//o2 is now (1,9999,3) but o3 is still (1,2,3)",},
19{"set",0,PARAM_NOSTATIC,"set (copy) coordinates from another XYZ object","p(oXYZ)",PROCEDURE(p_set),},
20{"set3",0,PARAM_NOSTATIC,"set individual 3 coordinates","p(f x,f y,f z)",PROCEDURE(p_set3),},
21{"add",0,PARAM_NOSTATIC,"add","p(oXYZ)",PROCEDURE(p_addvec),"Note: it does not return a new object, just modifies the existing one"},
22{"sub",0,PARAM_NOSTATIC,"subtract","p(oXYZ)",PROCEDURE(p_subvec),"Note: it does not return a new object, just modifies the existing one"},
23{"scale",0,PARAM_NOSTATIC,"multiply by scalar","p(f)",PROCEDURE(p_scale),},
24{"length",0,PARAM_READONLY+PARAM_NOSTATIC,"length","f",GETONLY(length),},
25{"normalize",0,PARAM_NOSTATIC,"normalize","p()",PROCEDURE(p_normalize),"scales the vector length to 1.0"},
26{"toString",0,PARAM_READONLY+PARAM_NOSTATIC,"textual form","s",GETONLY(toString),},
27{"toVector",0,PARAM_READONLY+PARAM_NOSTATIC,"vector of [x,y,z]","oVector",GETONLY(toVector),},
28{"rotate",0,PARAM_NOSTATIC,"rotate using Orient object","p(oOrient)",PROCEDURE(p_rotate),},
29{"revRotate",0,PARAM_NOSTATIC,"reverse rotate using Orient object","p(oOrient)",PROCEDURE(p_revrotate),},
30{"get",0,PARAM_NOSTATIC,"get one of coordinates","p f(d index)",PROCEDURE(p_get),"this function makes the XYZ objects \"indexable\" (so you can use [] for accessing subsequent fields, like in Vector)",},
31{0,0,0,},
32};
33#undef FIELDSTRUCT
34return paramtab;
35}
36
37void Pt3D_Ext::p_new(ExtValue *args,ExtValue *ret)
38{
39*ret=makeDynamicObject(new Pt3D_Ext(args[2].getDouble(),args[1].getDouble(),args[0].getDouble()));
40}
41
42static double doubleFromVec(VectorObject *vec,int i)
43{
44if (i>=vec->data.size()) return 0;
45ExtValue *v=(ExtValue*)vec->data.get(i);
46if (v)
47        return v->getDouble();
48return 0;
49}
50
51static Pt3D pt3DFromVec(VectorObject* v,int offset=0)
52{
53return Pt3D(doubleFromVec(v,offset),doubleFromVec(v,offset+1),doubleFromVec(v,offset+2));
54}
55
56void Pt3D_Ext::p_newFromVector(ExtValue *args,ExtValue *ret)
57{
58VectorObject *vec=VectorObject::fromObject(args->getObject());
59if (vec)
60        *ret=makeDynamicObject(new Pt3D_Ext(pt3DFromVec(vec)));
61else
62        ret->setEmpty();
63}
64
65void Pt3D_Ext::p_clone(ExtValue *args,ExtValue *ret)
66{
67*ret=makeDynamicObject(new Pt3D_Ext(p.x,p.y,p.z));
68}
69
70void Pt3D_Ext::p_set3(ExtValue *args,ExtValue *ret)
71{
72p.x=args[2].getDouble();
73p.y=args[1].getDouble();
74p.z=args[0].getDouble();
75ret->setEmpty();
76}
77
78void Pt3D_Ext::p_set(ExtValue *args,ExtValue *ret)
79{
80Pt3D_Ext *other=fromObject(args[0]);
81if (other)
82        p=other->p;
83ret->setEmpty();
84}
85
86void Pt3D_Ext::get_length(ExtValue *ret)
87{
88ret->setDouble(p.length());
89}
90
91void Pt3D_Ext::get_toString(ExtValue *ret)
92{
93SString s="(";
94ExtValue v;
95v.setDouble(p.x); s+=v.getString();
96s+=",";
97v.setDouble(p.y); s+=v.getString();
98s+=",";
99v.setDouble(p.z); s+=v.getString();
100s+=")";
101ret->setString(s);
102}
103
104static void add3Coords(VectorObject* vec,const Pt3D& p)
105{
106vec->data+=new ExtValue(p.x);
107vec->data+=new ExtValue(p.y);
108vec->data+=new ExtValue(p.z);
109}
110
111void Pt3D_Ext::get_toVector(ExtValue *ret)
112{
113VectorObject *vec=new VectorObject;
114add3Coords(vec,p);
115ret->setObject(ExtObject(&VectorObject::par,vec));
116}
117
118void Pt3D_Ext::p_addvec(ExtValue *args,ExtValue *ret)
119{
120Pt3D_Ext *other=fromObject(args[0]);
121if (other)
122        p+=other->p;
123ret->setEmpty();
124}
125
126void Pt3D_Ext::p_subvec(ExtValue *args,ExtValue *ret)
127{
128Pt3D_Ext *other=fromObject(args[0]);
129if (other)
130        p-=other->p;
131ret->setEmpty();
132}
133
134void Pt3D_Ext::p_scale(ExtValue *args,ExtValue *ret)
135{
136double d=args[0].getDouble();
137p.x*=d; p.y*=d; p.z*=d;
138ret->setEmpty();
139}
140
141void Pt3D_Ext::p_normalize(ExtValue *args,ExtValue *ret)
142{
143p.normalize();
144ret->setEmpty();
145}
146
147void Pt3D_Ext::p_rotate(ExtValue *args,ExtValue *ret)
148{
149Orient_Ext *o=Orient_Ext::fromObject(args[0]);
150if (o)
151        {
152        Pt3D tmp=p;
153        o->o.transform(p,tmp);
154        }
155ret->setEmpty();
156}
157
158void Pt3D_Ext::p_revrotate(ExtValue *args,ExtValue *ret)
159{
160Orient_Ext *o=Orient_Ext::fromObject(args[0]);
161if (o)
162        {
163        Pt3D tmp=p;
164        o->o.revTransform(p,tmp);
165        }
166ret->setEmpty();
167}
168
169void Pt3D_Ext::p_get(ExtValue *args,ExtValue *ret)
170{
171int index=args->getInt();
172if ((index<0)||(index>2))
173        ret->setEmpty();
174else
175        ret->setDouble((&p.x)[index]);
176}
177
178Param& Pt3D_Ext::getStaticParam()
179{
180#ifdef __CODEGUARD__
181static Pt3D_Ext static_pt3dobj;
182static Param static_pt3dparam(getStaticParamtab(),&static_pt3dobj);
183#else
184static Param static_pt3dparam(getStaticParamtab());
185#endif
186return static_pt3dparam;
187}
188
189Pt3D_Ext* Pt3D_Ext::fromObject(const ExtValue& v)
190{
191if (v.type!=TObj) return 0;
192const ExtObject& o=v.getObject();
193return (Pt3D_Ext*)o.getTarget(getStaticParam().getName());
194}
195
196ParamInterface* Pt3D_Ext::getInterface() {return &getStaticParam();}
197
198ExtObject Pt3D_Ext::makeStaticObject(Pt3D* p)
199{return ExtObject(&getStaticParam(),((char*)p)+(((char*)&p->x)-((char*)&((Pt3D_Ext*)p)->p.x)));}
200
201ExtObject Pt3D_Ext::makeDynamicObject(Pt3D_Ext* p)
202{return ExtObject(&getStaticParam(),p);}
203
204//////////////////////////////////////
205
206ParamEntry* Orient_Ext::getStaticParamtab()
207{
208#define FIELDSTRUCT Orient_Ext
209static ParamEntry paramtab[]=
210{
211{"Orient",1,27,"Orient","3D orientation, stored as 3x3 matrix."},
212
213{"xx",1,PARAM_NOSTATIC,"orientation.x.x","f",FIELD(o.x.x),},
214{"xy",1,PARAM_NOSTATIC,"orientation.x.y","f",FIELD(o.x.y),},
215{"xz",1,PARAM_NOSTATIC,"orientation.x.z","f",FIELD(o.x.z),},
216{"yx",1,PARAM_NOSTATIC,"orientation.y.x","f",FIELD(o.y.x),},
217{"yy",1,PARAM_NOSTATIC,"orientation.y.y","f",FIELD(o.y.y),},
218{"yz",1,PARAM_NOSTATIC,"orientation.y.z","f",FIELD(o.y.z),},
219{"zx",1,PARAM_NOSTATIC,"orientation.z.x","f",FIELD(o.z.x),},
220{"zy",1,PARAM_NOSTATIC,"orientation.z.y","f",FIELD(o.z.y),},
221{"zz",1,PARAM_NOSTATIC,"orientation.z.z","f",FIELD(o.z.z),},
222
223{"x",0,PARAM_NOSTATIC,"x vector","oXYZ",GETONLY(x),},
224{"y",0,PARAM_NOSTATIC,"y vector","oXYZ",GETONLY(y),},
225{"z",0,PARAM_NOSTATIC,"z vector","oXYZ",GETONLY(z),},
226
227{"new",0,0,"create new Orient object","p oOrient()",PROCEDURE(p_new),},
228{"newFromVector",0,0,"create new Orient object","p oOrient(oVector)",PROCEDURE(p_newFromVector),},
229{"toVector",0,PARAM_READONLY+PARAM_NOSTATIC,"vector representation","oVector",GETONLY(toVector),"for serialization"},
230{"clone",0,PARAM_NOSTATIC,"create new Orient object","p oOrient()",PROCEDURE(p_clone),},
231{"set",0,PARAM_NOSTATIC,"copy from another Orient object","p(oOrient)",PROCEDURE(p_set),},
232{"reset",0,PARAM_NOSTATIC,"set identity matrix","p()",PROCEDURE(p_reset),},
233{"rotate3",0,PARAM_NOSTATIC,"rotate around 3 axes","p(f x,f y,f z)",PROCEDURE(p_rotate3),},
234{"rotate",0,PARAM_NOSTATIC,"rotate using Orient object","p(oOrient)",PROCEDURE(p_rotate),},
235{"revRotate",0,PARAM_NOSTATIC,"reverse rotate using Orient object","p(oOrient)",PROCEDURE(p_revrotate),},
236{"lookAt",0,PARAM_NOSTATIC,"calculate rotation from 2 vectors","p(oXYZ direction,oXYZ up)",PROCEDURE(p_lookat),},
237{"normalize",0,PARAM_NOSTATIC,"normalize","p()",PROCEDURE(p_normalize),},
238{"between2",0,PARAM_NOSTATIC,"interpolate orientation","p(oOrient,oOrient,f amount)",PROCEDURE(p_between2),"The calling Orient receives the orientation interpolated from 2 input orientations.\nExample:\n"
239        "var o1=Orient.new(), o2=Orient.new(), o3=Orient.new();\n"
240        "o2.rotate3(0,Math.pi/2,0);\n"
241        "o3.between2(o1,o2,0); // o3 equals o2\n"
242        "o3.between2(o1,o2,1); // o3 equals o1\n"
243        "o3.between2(o1,o2,0.5); // o3 is halfway between o1 and o2\n"},
244{"betweenOV",0,PARAM_NOSTATIC,"interpolate orientation","p(oOrient,oXYZ,f amount)",PROCEDURE(p_betweenOV),"Like between2(), but the second Orient is composed of the supplied XYZ vector (X component) and Y Z vectors from the calling object.\n"
245        "Example:\n"
246        "var o=Orient.new();\n"
247        "o.betweenOV(o,(0,1,0),1); //no change, o remains 100 010 001\n"
248        "o.betweenOV(o,(0,1,0),0.9); //o is slightly rotated towards (0,1,0)\n"
249        "o.betweenOV(o,(0,1,0),0); //o is completely transformed, o.x=(0,1,0)\n"
250        },
251{"localToWorld",0,PARAM_NOSTATIC,"transform coordinates","p XYZ(oXYZ point,oXYZ center)",PROCEDURE(p_localToWorld),},
252{"worldToLocal",0,PARAM_NOSTATIC,"transform coordinates","p XYZ(oXYZ point,oXYZ center)",PROCEDURE(p_worldToLocal),},
253{0,0,0,},
254};
255#undef FIELDSTRUCT
256return paramtab;
257}
258
259void Orient_Ext::p_new(ExtValue *args,ExtValue *ret)
260{
261*ret=makeDynamicObject(new Orient_Ext());
262}
263
264void Orient_Ext::p_newFromVector(ExtValue *args,ExtValue *ret)
265{
266VectorObject *vec=VectorObject::fromObject(args->getObject());
267if (vec)
268        *ret=makeDynamicObject(new Orient_Ext(Orient(pt3DFromVec(vec,0),pt3DFromVec(vec,3),pt3DFromVec(vec,6))));
269else
270        ret->setEmpty();
271}
272
273void Orient_Ext::get_toVector(ExtValue *ret)
274{
275VectorObject *vec=new VectorObject;
276add3Coords(vec,o.x);
277add3Coords(vec,o.y);
278add3Coords(vec,o.z);
279ret->setObject(ExtObject(&VectorObject::par,vec));
280}
281
282void Orient_Ext::p_clone(ExtValue *args,ExtValue *ret)
283{
284*ret=makeDynamicObject(new Orient_Ext(o));
285}
286
287void Orient_Ext::p_set(ExtValue *args,ExtValue *ret)
288{
289Orient_Ext *other=fromObject(args[0]);
290if (other)
291        o=other->o;
292ret->setEmpty();
293}
294
295void Orient_Ext::p_reset(ExtValue *args,ExtValue *ret)
296{
297o=Orient_1;
298ret->setEmpty();
299}
300
301void Orient_Ext::get_x(PARAMGETARGS)
302{
303*ret=Pt3D_Ext::makeStaticObject(&o.x);
304}
305
306void Orient_Ext::get_y(PARAMGETARGS)
307{
308*ret=Pt3D_Ext::makeStaticObject(&o.y);
309}
310
311void Orient_Ext::get_z(PARAMGETARGS)
312{
313*ret=Pt3D_Ext::makeStaticObject(&o.z);
314}
315
316void Orient_Ext::p_lookat(ExtValue *args,ExtValue *ret)
317{
318Pt3D_Ext *dir=Pt3D_Ext::fromObject(args[1]),*up=Pt3D_Ext::fromObject(args[0]);
319if (dir&&up)
320        o.lookAt(dir->p,up->p);
321ret->setEmpty();
322}
323
324void Orient_Ext::p_rotate3(ExtValue *args,ExtValue *ret)
325{
326Pt3D p(args[2].getDouble(),args[1].getDouble(),args[0].getDouble());
327o.rotate(p);
328ret->setEmpty();
329}
330
331void Orient_Ext::p_rotate(ExtValue *args,ExtValue *ret)
332{
333Orient_Ext *obj=Orient_Ext::fromObject(args[0]);
334if (!obj)
335        {
336        Orient tmp=o;
337        obj->o.transform(o,tmp);
338        }
339ret->setEmpty();
340}
341
342void Orient_Ext::p_revrotate(ExtValue *args,ExtValue *ret)
343{
344Orient_Ext *obj=Orient_Ext::fromObject(args[0]);
345if (obj)
346        {
347        Orient tmp=o;
348        obj->o.revTransform(o,tmp);
349        }
350ret->setEmpty();
351}
352
353void Orient_Ext::p_normalize(ExtValue *args,ExtValue *ret)
354{
355o.normalize();
356ret->setEmpty();
357}
358
359void Orient_Ext::p_between2(ExtValue *args,ExtValue *ret)
360{
361Orient_Ext *o1=Orient_Ext::fromObject(args[2]);
362Orient_Ext *o2=Orient_Ext::fromObject(args[1]);
363if (o1&&o2)
364        {
365        double q1=args[0].getDouble(),q2=1.0-q1;
366        o.x.x=q1*o1->o.x.x+q2*o2->o.x.x;
367        o.x.y=q1*o1->o.x.y+q2*o2->o.x.y;
368        o.x.z=q1*o1->o.x.z+q2*o2->o.x.z;
369        o.y.x=q1*o1->o.y.x+q2*o2->o.y.x;
370        o.y.y=q1*o1->o.y.y+q2*o2->o.y.y;
371        o.y.z=q1*o1->o.y.z+q2*o2->o.y.z;
372        o.z.x=q1*o1->o.z.x+q2*o2->o.z.x;
373        o.z.y=q1*o1->o.z.y+q2*o2->o.z.y;
374        o.z.z=q1*o1->o.z.z+q2*o2->o.z.z;
375        o.normalize();
376        }
377ret->setEmpty();
378}
379
380void Orient_Ext::p_betweenOV(ExtValue *args,ExtValue *ret)
381{
382Orient_Ext *o1=Orient_Ext::fromObject(args[2]);
383Pt3D_Ext *p2=Pt3D_Ext::fromObject(args[1]);
384if (o1&&p2)
385        {
386        double q1=args[0].getDouble(),q2=1.0-q1;
387        o.x.x=q1*o1->o.x.x+q2*p2->p.x;
388        o.x.y=q1*o1->o.x.y+q2*p2->p.y;
389        o.x.z=q1*o1->o.x.z+q2*p2->p.z;
390        o.normalize();
391        }
392ret->setEmpty();
393}
394
395void Orient_Ext::p_localToWorld(ExtValue *args,ExtValue *ret)
396{
397Pt3D_Ext *center,*point;
398point=Pt3D_Ext::fromObject(args[1]);
399center=Pt3D_Ext::fromObject(args[0]);
400if (center && point)
401        {
402        Pt3D d;
403        Pt3D src=point->p;
404        o.transform(d,src);
405        d+=center->p;
406        *ret=Pt3D_Ext::makeDynamicObject(new Pt3D_Ext(d));
407        }
408else
409        ret->setEmpty();
410}
411
412void Orient_Ext::p_worldToLocal(ExtValue *args,ExtValue *ret)
413{
414Pt3D_Ext *center,*point;
415point=Pt3D_Ext::fromObject(args[1]);
416center=Pt3D_Ext::fromObject(args[0]);
417if (center && point)
418        {
419        Pt3D d;
420        Pt3D src=point->p;
421        d-=center->p;
422        o.revTransform(d,src);
423        *ret=Pt3D_Ext::makeDynamicObject(new Pt3D_Ext(d));
424        }
425else
426        ret->setEmpty();
427}
428
429Param& Orient_Ext::getStaticParam()
430{
431#ifdef __CODEGUARD__
432static Orient_Ext static_orientobj;
433static Param static_orientparam(getStaticParamtab(),&static_orientobj);
434#else
435static Param static_orientparam(getStaticParamtab());
436#endif
437return static_orientparam;
438}
439
440Orient_Ext* Orient_Ext::fromObject(const ExtValue& v)
441{
442if (v.type!=TObj) return 0;
443const ExtObject& o=v.getObject();
444return (Orient_Ext*)o.getTarget(getStaticParam().getName());
445}
446
447ParamInterface* Orient_Ext::getInterface() {return &getStaticParam();}
448
449ExtObject Orient_Ext::makeStaticObject(Orient* o)
450{return ExtObject(&getStaticParam(),((char*)o)+(((char*)&o->x)-((char*)&((Orient_Ext*)o)->o.x)));}
451
452ExtObject Orient_Ext::makeDynamicObject(Orient_Ext* p)
453{return ExtObject(&getStaticParam(),p);}
454
455ParamEntry* ReferenceObj::getStaticParamtab()
456{
457#define FIELDSTRUCT ReferenceObj
458static ParamEntry paramtab[]=
459{
460{"Ref",1,5,"Ref","Reference objects. Useful for returning things from functions.\n\nExample:\nvar x=111;\nsquare(&x);// '&' creates the Reference object\nSimulator.print(x);//x is now 12321\n\nfunction square(r)\n{r.value=r.value*r.value;}\n//square receives the Reference objects and changes its 'value' field"},
461
462{"value",0,PARAM_NOSTATIC,"value","x",GETSET(value),},
463{"newS",0,0,"create new reference","p",PROCEDURE(p_newS),"(for internal use only) use &variablename to create Ref objects.",},
464{"newO",0,0,"create new reference","p",PROCEDURE(p_newO),"(for internal use only) use &variablename to create Ref objects.",},
465{"copyFrom",0,0,"copy the reference","p(oRef)",PROCEDURE(p_copyFrom),"make the reference point to the same target,"},
466{"toString",0,PARAM_READONLY+PARAM_NOSTATIC,"textual form","s",GETONLY(toString),},
467{0,0,0,},
468};
469#undef FIELDSTRUCT
470return paramtab;
471}
472
473Param& ReferenceObj::getStaticParam()
474{
475#ifdef __CODEGUARD__
476static ReferenceObj static_referenceobj;
477static Param static_refobjectparam(getStaticParamtab(),&static_referenceobj);
478#else
479static Param static_refobjectparam(getStaticParamtab());
480#endif
481return static_refobjectparam;
482}
483
484void ReferenceObj::p_newS(ExtValue *args,ExtValue *ret)
485{
486*ret=makeDynamicObject(new ReferenceObj((ExtValue*)args->getInt()));
487}
488
489void ReferenceObj::p_newO(ExtValue *args,ExtValue *ret)
490{
491if (args[0].type==TInt)
492        *ret=makeDynamicObject(new ReferenceObj(args[1].getObject(),args[0].getInt()));
493else
494        *ret=makeDynamicObject(new ReferenceObj(args[1].getObject(),args[0].getString()));
495}
496
497void ReferenceObj::p_copyFrom(ExtValue *args,ExtValue *ret)
498{
499ReferenceObj* other=fromObject(args[0]);
500if (other)
501        {
502        value=other->value;
503        obj=other->obj;
504        prop=other->prop;
505        }
506}
507
508void ReferenceObj::get_toString(ExtValue *ret)
509{
510SString s="(";
511static SListTempl<ReferenceObj*> trace;
512if (trace.find(this)>=0)
513        s+="...";
514else
515        {
516        trace+=this;
517        if (value)
518                s+=value->getString();
519        else
520                {
521                ExtValue v;
522                Param tmp_param;
523                ParamInterface *pi=obj.getParamInterface(tmp_param);
524                pi->get(prop,v);
525                s+=v.getString();
526                }
527        trace-=this;
528        }
529s+=")";
530ret->setString(s);
531}
532
533void ReferenceObj::get_value(ExtValue *ret)
534{
535if (value)
536        *ret=*value;
537else
538        {
539        Param tmp_param;
540        ParamInterface *pi=obj.getParamInterface(tmp_param);
541        pi->get(prop,*ret);
542        }
543}
544
545int ReferenceObj::set_value(const ExtValue *val)
546{
547if (value)
548        *value=*val;
549else
550        {
551        Param tmp_param;
552        ParamInterface *pi=obj.getParamInterface(tmp_param);
553        pi->set(prop,*val);
554        }
555return PSET_CHANGED;
556}
557
558ReferenceObj::ReferenceObj(const ExtObject &o,const SString &p)
559        :value(0),obj(o)
560{
561Param tmp_param;
562ParamInterface *pi=obj.getParamInterface(tmp_param);
563prop=pi->findId(p);
564}
565
566ExtObject ReferenceObj::makeDynamicObject(ReferenceObj* r)
567{return ExtObject(&getStaticParam(),r);}
568
569ReferenceObj* ReferenceObj::fromObject(const ExtValue& v)
570{
571if (v.type!=TObj) return 0;
572const ExtObject& o=v.getObject();
573return (ReferenceObj*)o.getTarget(getStaticParam().getName());
574}
Note: See TracBrowser for help on using the repository browser.