diff options
Diffstat (limited to 'source/gameengine/Expressions/Operator2Expr.cpp')
-rw-r--r-- | source/gameengine/Expressions/Operator2Expr.cpp | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/source/gameengine/Expressions/Operator2Expr.cpp b/source/gameengine/Expressions/Operator2Expr.cpp new file mode 100644 index 00000000000..33223b2ae3d --- /dev/null +++ b/source/gameengine/Expressions/Operator2Expr.cpp @@ -0,0 +1,275 @@ +// Operator2Expr.cpp: implementation of the COperator2Expr class. +/* + * Copyright (c) 1996-2000 Erwin Coumans <coockie@acm.org> + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Erwin Coumans makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ +// 31 dec 1998 - big update: try to use the cached data for updating, instead of +// rebuilding completely it from left and right node. Modified flags and bounding boxes +// have to do the trick +// when expression is cached, there will be a call to UpdateCalc() instead of Calc() + + + +#include "Operator2Expr.h" +#include "StringValue.h" +#include "VoidValue.h" +//#include "FactoryManager.h" +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +COperator2Expr::COperator2Expr(VALUE_OPERATOR op, CExpression *lhs, CExpression *rhs) +: +m_cached_calculate(NULL), +m_op(op), +m_lhs(lhs), +m_rhs(rhs) +/* +pre: +effect: constucts a COperator2Expr with op, lhs and rhs in it +*/ +{ + +} + +COperator2Expr::COperator2Expr(): +m_cached_calculate(NULL), +m_lhs(NULL), +m_rhs(NULL) + +/* +pre: +effect: constucts an empty COperator2Expr +*/ +{ + +} + +COperator2Expr::~COperator2Expr() +/* +pre: +effect: deletes the object +*/ +{ + if (m_lhs) + m_lhs->Release(); + if (m_rhs) + m_rhs->Release(); + if (m_cached_calculate) + m_cached_calculate->Release(); + +} +CValue* COperator2Expr::Calculate() +/* +pre: +ret: a new object containing the result of applying operator m_op to m_lhs +and m_rhs +*/ +{ + + bool leftmodified,rightmodified; + leftmodified = m_lhs->NeedsRecalculated(); + rightmodified = m_rhs->NeedsRecalculated(); + + // if no modifications on both left and right subtree, and result is already calculated + // then just return cached result... + if (!leftmodified && !rightmodified && (m_cached_calculate)) + { + // not modified, just return m_cached_calculate + } else { + // if not yet calculated, or modified... + + + if (m_cached_calculate) { + m_cached_calculate->Release(); + m_cached_calculate=NULL; + } + + CValue* ffleft = m_lhs->Calculate(); + CValue* ffright = m_rhs->Calculate(); + + ffleft->SetOwnerExpression(this);//->m_pOwnerExpression=this; + ffright->SetOwnerExpression(this);//->m_pOwnerExpression=this; + + m_cached_calculate = ffleft->Calc(m_op,ffright); + + //if (m_cached_calculate) + // m_cached_calculate->Action(CValue::SETOWNEREXPR,&CVoidValue(this,false,CValue::STACKVALUE)); + + ffleft->Release(); + ffright->Release(); + } + + return m_cached_calculate->AddRef(); + +} + +/* +bool COperator2Expr::IsInside(float x, float y, float z,bool bBorderInclude) +{ + bool inside; + inside = false; + + switch (m_op) + { + case VALUE_ADD_OPERATOR: { + // inside = first || second; // optimized with early out if first is inside + // todo: calculate smallest leaf first ! is much faster... + + bool second;//first ;//,second; + + //first = m_lhs->IsInside(x,y,z) ; + second = m_rhs->IsInside(x,y,z,bBorderInclude) ; + if (second) + return true; //early out + + // second = m_rhs->IsInside(x,y,z) ; + + return m_lhs->IsInside(x,y,z,bBorderInclude) ; + + break; + } + + case VALUE_SUB_OPERATOR: { + //inside = first && !second; // optimized with early out + // todo: same as with add_operator: calc smallest leaf first + + bool second;//first ;//,second; + //first = m_lhs->IsInside(x,y,z) ; + second = m_rhs->IsInside(x,y,z,bBorderInclude); + if (second) + return false; + + // second space get subtracted -> negate! + //second = m_rhs->IsInside(x,y,z); + + return (m_lhs->IsInside(x,y,z,bBorderInclude)); + + + break; + } + default:{ + assert(false); + // not yet implemented, only add or sub csg operations + } + } + + return inside; +} + + + +bool COperator2Expr::IsRightInside(float x, float y, float z,bool bBorderInclude) { + + return m_rhs->IsInside(x,y,z,bBorderInclude) ; + +} + +bool COperator2Expr::IsLeftInside(float x, float y, float z,bool bBorderInclude) { + return m_lhs->IsInside(x,y,z,bBorderInclude); +} +*/ +bool COperator2Expr::NeedsRecalculated() { + // added some lines, just for debugging purposes, it could be a one-liner :) + //bool modleft + //bool modright; + assertd(m_lhs); + assertd(m_rhs); + + //modright = m_rhs->NeedsRecalculated(); + if (m_rhs->NeedsRecalculated()) // early out + return true; + return m_lhs->NeedsRecalculated(); + //modleft = m_lhs->NeedsRecalculated(); + //return (modleft || modright); + +} + + + +CExpression* COperator2Expr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) { +// if both children are 'dead', return NULL +// if only one child is alive, return that child +// if both childresn are alive, return this + + +// bool leftalive = true,rightalive=true; + /* Does this mean the function will always bomb? */ + assertd(false); + assert(m_lhs); + assert(m_rhs); +/* + if (m_cached_calculate) + m_cached_calculate->Action(CValue::REFRESH_CACHE); + + CExpression* newlhs = m_lhs->CheckLink(brokenlinks); + CExpression* newrhs = m_rhs->CheckLink(brokenlinks); + + if (m_lhs != newlhs) + { + brokenlinks.push_back(new CBrokenLinkInfo(&m_lhs,m_lhs)); + } + + if (m_rhs != newrhs) + { + brokenlinks.push_back(new CBrokenLinkInfo(&m_rhs,m_rhs)); + } + + + + m_lhs = newlhs; + m_rhs = newrhs; + + if (m_lhs && m_rhs) { + return this; + } + + AddRef(); + if (m_lhs) + return Release(m_lhs->AddRef()); + + if (m_rhs) + return Release(m_rhs->AddRef()); +/ + + */ + return Release(); + + + +} + + +bool COperator2Expr::MergeExpression(CExpression *otherexpr) +{ + if (m_lhs) + { + if (m_lhs->GetExpressionID() == CExpression::CCONSTEXPRESSIONID) + { + // cross fingers ;) replace constexpr by new tree... + m_lhs->Release(); + m_lhs = otherexpr->AddRef(); + return true; + } + } + + assertd(false); + return false; +} + + +void COperator2Expr::BroadcastOperators(VALUE_OPERATOR op) +{ + if (m_lhs) + m_lhs->BroadcastOperators(m_op); + if (m_rhs) + m_rhs->BroadcastOperators(m_op); +} |