1 /** \file gameengine/Expressions/Operator2Expr.cpp
4 // Operator2Expr.cpp: implementation of the COperator2Expr class.
6 * Copyright (c) 1996-2000 Erwin Coumans <coockie@acm.org>
8 * Permission to use, copy, modify, distribute and sell this software
9 * and its documentation for any purpose is hereby granted without fee,
10 * provided that the above copyright notice appear in all copies and
11 * that both that copyright notice and this permission notice appear
12 * in supporting documentation. Erwin Coumans makes no
13 * representations about the suitability of this software for any
14 * purpose. It is provided "as is" without express or implied warranty.
17 // 31 dec 1998 - big update: try to use the cached data for updating, instead of
18 // rebuilding completely it from left and right node. Modified flags and bounding boxes
19 // have to do the trick
20 // when expression is cached, there will be a call to UpdateCalc() instead of Calc()
22 #include "Operator2Expr.h"
23 #include "StringValue.h"
24 #include "VoidValue.h"
26 //////////////////////////////////////////////////////////////////////
27 // Construction/Destruction
28 //////////////////////////////////////////////////////////////////////
30 COperator2Expr::COperator2Expr(VALUE_OPERATOR op, CExpression *lhs, CExpression *rhs)
34 m_cached_calculate(NULL),
38 effect: constucts a COperator2Expr with op, lhs and rhs in it
44 COperator2Expr::COperator2Expr():
47 m_cached_calculate(NULL)
51 effect: constucts an empty COperator2Expr
57 COperator2Expr::~COperator2Expr()
60 effect: deletes the object
67 if (m_cached_calculate)
68 m_cached_calculate->Release();
71 CValue* COperator2Expr::Calculate()
74 ret: a new object containing the result of applying operator m_op to m_lhs
79 bool leftmodified,rightmodified;
80 leftmodified = m_lhs->NeedsRecalculated();
81 rightmodified = m_rhs->NeedsRecalculated();
83 // if no modifications on both left and right subtree, and result is already calculated
84 // then just return cached result...
85 if (!leftmodified && !rightmodified && (m_cached_calculate))
87 // not modified, just return m_cached_calculate
89 // if not yet calculated, or modified...
92 if (m_cached_calculate) {
93 m_cached_calculate->Release();
94 m_cached_calculate=NULL;
97 CValue* ffleft = m_lhs->Calculate();
98 CValue* ffright = m_rhs->Calculate();
100 ffleft->SetOwnerExpression(this);//->m_pOwnerExpression=this;
101 ffright->SetOwnerExpression(this);//->m_pOwnerExpression=this;
103 m_cached_calculate = ffleft->Calc(m_op,ffright);
105 //if (m_cached_calculate)
106 // m_cached_calculate->Action(CValue::SETOWNEREXPR,&CVoidValue(this,false,CValue::STACKVALUE));
112 return m_cached_calculate->AddRef();
117 bool COperator2Expr::IsInside(float x, float y, float z,bool bBorderInclude)
124 case VALUE_ADD_OPERATOR: {
125 // inside = first || second; // optimized with early out if first is inside
126 // todo: calculate smallest leaf first ! is much faster...
128 bool second;//first ;//,second;
130 //first = m_lhs->IsInside(x,y,z) ;
131 second = m_rhs->IsInside(x,y,z,bBorderInclude) ;
133 return true; //early out
135 // second = m_rhs->IsInside(x,y,z) ;
137 return m_lhs->IsInside(x,y,z,bBorderInclude) ;
142 case VALUE_SUB_OPERATOR: {
143 //inside = first && !second; // optimized with early out
144 // todo: same as with add_operator: calc smallest leaf first
146 bool second;//first ;//,second;
147 //first = m_lhs->IsInside(x,y,z) ;
148 second = m_rhs->IsInside(x,y,z,bBorderInclude);
152 // second space get subtracted -> negate!
153 //second = m_rhs->IsInside(x,y,z);
155 return (m_lhs->IsInside(x,y,z,bBorderInclude));
162 // not yet implemented, only add or sub csg operations
171 bool COperator2Expr::IsRightInside(float x, float y, float z,bool bBorderInclude) {
173 return m_rhs->IsInside(x,y,z,bBorderInclude) ;
177 bool COperator2Expr::IsLeftInside(float x, float y, float z,bool bBorderInclude) {
178 return m_lhs->IsInside(x,y,z,bBorderInclude);
181 bool COperator2Expr::NeedsRecalculated() {
182 // added some lines, just for debugging purposes, it could be a one-liner :)
188 //modright = m_rhs->NeedsRecalculated();
189 if (m_rhs->NeedsRecalculated()) // early out
191 return m_lhs->NeedsRecalculated();
192 //modleft = m_lhs->NeedsRecalculated();
193 //return (modleft || modright);
199 CExpression* COperator2Expr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) {
200 // if both children are 'dead', return NULL
201 // if only one child is alive, return that child
202 // if both childresn are alive, return this
205 // bool leftalive = true,rightalive=true;
206 /* Does this mean the function will always bomb? */
211 if (m_cached_calculate)
212 m_cached_calculate->Action(CValue::REFRESH_CACHE);
214 CExpression* newlhs = m_lhs->CheckLink(brokenlinks);
215 CExpression* newrhs = m_rhs->CheckLink(brokenlinks);
219 brokenlinks.push_back(new CBrokenLinkInfo(&m_lhs,m_lhs));
224 brokenlinks.push_back(new CBrokenLinkInfo(&m_rhs,m_rhs));
232 if (m_lhs && m_rhs) {
238 return Release(m_lhs->AddRef());
241 return Release(m_rhs->AddRef());
252 bool COperator2Expr::MergeExpression(CExpression *otherexpr)
256 if (m_lhs->GetExpressionID() == CExpression::CCONSTEXPRESSIONID)
258 // cross fingers ;) replace constexpr by new tree...
260 m_lhs = otherexpr->AddRef();
270 void COperator2Expr::BroadcastOperators(VALUE_OPERATOR op)
273 m_lhs->BroadcastOperators(m_op);
275 m_rhs->BroadcastOperators(m_op);