blender/source/gameengine/Expressions/Operator2Expr.cpp
Campbell Barton 761ac89877 style cleanup
2013-01-15 23:45:41 +00:00

277 lines
6.1 KiB
C++

/** \file gameengine/Expressions/Operator2Expr.cpp
* \ingroup expressions
*/
// 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"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
COperator2Expr::COperator2Expr(VALUE_OPERATOR op, CExpression *lhs, CExpression *rhs)
:
m_rhs(rhs),
m_lhs(lhs),
m_cached_calculate(NULL),
m_op(op)
/*
pre:
effect: constucts a COperator2Expr with op, lhs and rhs in it
*/
{
}
COperator2Expr::COperator2Expr():
m_rhs(NULL),
m_lhs(NULL),
m_cached_calculate(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();
}
#if 0
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);
}
#endif
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);
}