Initial revision
This commit is contained in:
275
source/gameengine/Expressions/Operator2Expr.cpp
Normal file
275
source/gameengine/Expressions/Operator2Expr.cpp
Normal file
@@ -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);
|
||||
}
|
Reference in New Issue
Block a user