2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 // $Header: r:/t2repos/thief2/src/object/relinver.cpp,v 1.10 1998/10/19 13:04:49 mahk Exp $
16 // Must be last header
19 cInverseRelation::cInverseRelation(IRelation
* rel
)
24 // build the descriptor
25 const sRelationDesc
* desc
= rel
->Describe();
27 strcpy(Desc
.name
,RELNAME_INVERSE_PREFIX
);
28 strncat(Desc
.name
,desc
->name
,sizeof(Desc
.name
)-strlen(Desc
.name
)-1);
32 cInverseRelation::~cInverseRelation()
34 SafeRelease(Relation
);
37 STDMETHODIMP_(const sRelationDesc
*) cInverseRelation::Describe() const
42 ////////////////////////////////////////
44 STDMETHODIMP_(RelationID
) cInverseRelation::GetID() const
46 return RELID_INVERT(Relation
->GetID());
49 ////////////////////////////////////////
51 STDMETHODIMP
cInverseRelation::SetID(RelationID id
)
53 Warning(("Someone is calling cInverseRelation::SetID()!\n"));
54 return Relation
->SetID(RELID_INVERT(id
));
58 ////////////////////////////////////////
60 STDMETHODIMP_(const sRelationDataDesc
*) cInverseRelation::DescribeData() const
62 return Relation
->DescribeData();
65 ////////////////////////////////////////
67 STDMETHODIMP_(IRelation
*) cInverseRelation::Inverse()
73 ////////////////////////////////////////
75 STDMETHODIMP_(LinkID
) cInverseRelation::Add(ObjID source
, ObjID dest
)
77 LinkID id
= Relation
->Add(dest
,source
);
78 return LINKID_INVERT(id
);
81 STDMETHODIMP_(LinkID
) cInverseRelation::AddFull(ObjID s
, ObjID d
, void* dat
)
83 LinkID id
= Relation
->AddFull(d
,s
,dat
);
84 return LINKID_INVERT(id
);
87 ////////////////////////////////////////
89 STDMETHODIMP
cInverseRelation::Remove(LinkID link
)
91 return Relation
->Remove(LINKID_INVERT(link
));
95 static void invert_slink(sLink
* link
)
97 ObjID tmp
= link
->source
;
98 link
->source
= link
->dest
;
100 link
->flavor
= RELID_INVERT(link
->flavor
);
103 STDMETHODIMP_(BOOL
) cInverseRelation::Get(LinkID id
, sLink
* link
) const
105 if (Relation
->Get(LINKID_INVERT(id
),link
))
113 STDMETHODIMP
cInverseRelation::SetData(LinkID id
, void* data
)
115 return Relation
->SetData(LINKID_INVERT(id
),data
);
118 void* cInverseRelation::GetData(LinkID id
)
120 return Relation
->GetData(LINKID_INVERT(id
));
123 ////////////////////////////////////////
125 // Nothing better to do here than hand off to the real relation
126 STDMETHODIMP
cInverseRelation::Notify(eRelationNotifyMsg msg
, RelationNotifyData data
)
128 return Relation
->Notify(msg
,data
);
131 ////////////////////////////////////////
135 RelationListenFunc func
;
136 RelationListenerData data
;
140 void LGAPI
cInverseRelation::Listener(sRelationListenMsg
* msg_
, RelationListenerData data
)
142 sRelationListenMsg msg
= *msg_
;
143 sListenerData
* listen
= (sListenerData
*)data
;
144 // invert the message
145 msg
.id
= LINKID_INVERT(msg
.id
);
146 invert_slink(&msg
.link
);
148 listen
->func(&msg
,listen
->data
);
151 // Just a list of listeners so that they get cleaned up at the end of time
152 // If we add unlisten, each elem is going to need a relation/handle id.
154 static cSimpleDList
<sListenerData
> gListeners
;
156 STDMETHODIMP
cInverseRelation::Listen(RelationListenMsgSet msgs
, RelationListenFunc func
, RelationListenerData data
)
158 sListenerData listener
= { func
, data
};
159 // add the listener to our list
160 gListeners
.Append(listener
);
162 // Get the actual copy that's in our list
163 sListenerData
* our_data
= &gListeners
.GetLast()->Value();
166 return Relation
->Listen(msgs
,Listener
,our_data
);
169 ////////////////////////////////////////
171 STDMETHODIMP_(LinkID
) cInverseRelation::GetSingleLink(ObjID source
, ObjID dest
)
173 return Relation
->GetSingleLink(dest
, source
);
176 ////////////////////////////////////////
178 STDMETHODIMP_(BOOL
) cInverseRelation::AnyLinks(ObjID source
, ObjID dest
)
180 return Relation
->AnyLinks(dest
, source
);
183 ////////////////////////////////////////////////////////////
187 // Take a query and invert it.
188 ////////////////////////////////////////////////////////////
191 class cInverseQuery
: public ILinkQuery
195 DECLARE_UNAGGREGATABLE();
197 cInverseQuery(ILinkQuery
* q
) :Query(q
) { Query
->AddRef();};
198 virtual ~cInverseQuery() { SafeRelease(Query
);};
201 STDMETHOD_(BOOL
,Done
)() const;
202 STDMETHOD(Link
)(sLink
* link
) const;
205 STDMETHOD_(LinkID
,ID
)() const
207 LinkID id
= Query
->ID();
208 return LINKID_INVERT(id
);
210 STDMETHOD_(void*,Data
)() const { return Query
->Data();};
212 STDMETHOD_(ILinkQuery
*,Inverse
)()
220 IMPLEMENT_UNAGGREGATABLE_SELF_DELETE(cInverseQuery
,ILinkQuery
);
223 STDMETHODIMP_(BOOL
) cInverseQuery::Done() const
225 return Query
->Done();
228 STDMETHODIMP
cInverseQuery::Link(sLink
* link
) const
230 HRESULT result
= Query
->Link(link
);
231 if (FAILED(result
)) return result
;
236 STDMETHODIMP
cInverseQuery::Next()
238 return Query
->Next();
241 ////////////////////////////////////////
243 STDMETHODIMP_(ILinkQuery
*) cInverseRelation::Query(ObjID s
, ObjID d
) const
245 ILinkQuery
* q
= Relation
->Query(d
,s
);
246 ILinkQuery
* retval
= q
->Inverse();
251 ////////////////////////////////////////
253 ILinkQuery
* CreateInverseLinkQuery(ILinkQuery
* q
)
255 return new cInverseQuery(q
);