diff options
author | Hans Lambermont <hans@lambermont.dyndns.org> | 2002-10-12 15:37:38 +0400 |
---|---|---|
committer | Hans Lambermont <hans@lambermont.dyndns.org> | 2002-10-12 15:37:38 +0400 |
commit | 12315f4d0e0ae993805f141f64cb8c73c5297311 (patch) | |
tree | 59b45827cd8293cfb727758989c7a74b40183974 /source/gameengine/Expressions |
Initial revisionv2.25
Diffstat (limited to 'source/gameengine/Expressions')
40 files changed, 6408 insertions, 0 deletions
diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/BoolValue.cpp new file mode 100644 index 00000000000..544b760f4e9 --- /dev/null +++ b/source/gameengine/Expressions/BoolValue.cpp @@ -0,0 +1,213 @@ + +// BoolValue.cpp: implementation of the CBoolValue 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. + * + */ + + + +#include "BoolValue.h" +#include "StringValue.h" +#include "ErrorValue.h" +#include "VoidValue.h" +//#include "FactoryManager.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +CBoolValue::CBoolValue() +/* +pre: false +effect: constructs a new CBoolValue +*/ +{ + trace("Bool constructor error"); +} + + + +CBoolValue::CBoolValue(bool inBool) +: m_bool(inBool) +{ +} // Constructs a new CBoolValue containing <inBool> + + + +CBoolValue::CBoolValue(bool innie,STR_String name,AllocationTYPE alloctype) +{ + m_bool = innie; + SetName(name); + + if (alloctype == CValue::STACKVALUE) + CValue::DisableRefCount(); +} + + + +void CBoolValue::SetValue(CValue* newval) +{ + m_bool = (newval->GetNumber() != 0); + SetModified(true); +} + + + +CValue* CBoolValue::Calc(VALUE_OPERATOR op, CValue *val) +/* +pre: +ret: a new object containing the result of applying operator op to this +object and val +*/ +{ + switch (op) + { + case VALUE_POS_OPERATOR: + case VALUE_NEG_OPERATOR: + { + return new CErrorValue (op2str(op) + GetText()); + break; + } + case VALUE_NOT_OPERATOR: + { + return new CBoolValue (!m_bool); + break; + } + default: + { + return val->CalcFinal(VALUE_BOOL_TYPE, op, this); + break; + } + } +} + + + +CValue* CBoolValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) +/* +pre: the type of val is dtype +ret: a new object containing the result of applying operator op to val and +this object +*/ +{ + CValue *ret; + + switch(dtype) + { + case VALUE_EMPTY_TYPE: + case VALUE_BOOL_TYPE: + { + switch(op) + { + case VALUE_AND_OPERATOR: + { + ret = new CBoolValue (((CBoolValue *) val)->GetBool() && m_bool); + break; + } + case VALUE_OR_OPERATOR: + { + ret = new CBoolValue (((CBoolValue *) val)->GetBool() || m_bool); + break; + } + case VALUE_EQL_OPERATOR: + { + ret = new CBoolValue (((CBoolValue *) val)->GetBool() == m_bool); + break; + } + case VALUE_NEQ_OPERATOR: + { + ret = new CBoolValue (((CBoolValue *) val)->GetBool() != m_bool); + break; + } + case VALUE_NOT_OPERATOR: + { + return new CBoolValue (!m_bool); + break; + } + default: + { + ret = new CErrorValue(val->GetText() + op2str(op) + + "[operator not allowed on booleans]"); + break; + } + } + break; + } + case VALUE_STRING_TYPE: + { + switch(op) + { + case VALUE_ADD_OPERATOR: + { + ret = new CStringValue(val->GetText() + GetText(),""); + break; + } + default: + { + ret = new CErrorValue(val->GetText() + op2str(op) + "[Only + allowed on boolean and string]"); + break; + } + } + break; + } + default: + ret = new CErrorValue("[type mismatch]" + op2str(op) + GetText()); + } + + return ret; +} + + + +bool CBoolValue::GetBool() +/* +pre: +ret: the bool stored in the object +*/ +{ + return m_bool; +} + + + +float CBoolValue::GetNumber() +{ + return (float)m_bool; +} + + + +const STR_String& CBoolValue::GetText() +{ + static STR_String sTrueString = STR_String("TRUE"); + static STR_String sFalseString = STR_String("FALSE"); + + return m_bool ? sTrueString : sFalseString; +} + + + +CValue* CBoolValue::GetReplica() +{ + CBoolValue* replica = new CBoolValue(*this); + CValue::AddDataToReplica(replica); + + return replica; +} + + + +PyObject* CBoolValue::ConvertValueToPython() +{ + return PyInt_FromLong(m_bool != 0); +} diff --git a/source/gameengine/Expressions/BoolValue.h b/source/gameengine/Expressions/BoolValue.h new file mode 100644 index 00000000000..e78ff2ef4bf --- /dev/null +++ b/source/gameengine/Expressions/BoolValue.h @@ -0,0 +1,51 @@ +/* + * BoolValue.h: interface for the CBoolValue class. + * $Id$ + * 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. + * + */ +#if !defined _BOOLVALUE_H +#define _BOOLVALUE_H + +#include "Value.h" + +/** + * Smart Boolean Value class. + * Is used by parser when an expression tree is build containing booleans. + */ + +class CBoolValue : public CPropValue +{ + + //PLUGIN_DECLARE_SERIAL(CBoolValue,CValue) + +public: + CBoolValue(); + CBoolValue(bool inBool); + CBoolValue(bool innie, STR_String name, AllocationTYPE alloctype = CValue::HEAPVALUE); + + virtual const STR_String& GetText(); + virtual float GetNumber(); + bool GetBool(); + virtual void SetValue(CValue* newval); + + virtual CValue* Calc(VALUE_OPERATOR op, CValue *val); + virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); + + void Configure(CValue* menuvalue); + virtual CValue* GetReplica(); + virtual PyObject* ConvertValueToPython(); + +private: + bool m_bool; +}; + +#endif // !defined _BOOLVALUE_H diff --git a/source/gameengine/Expressions/ConstExpr.cpp b/source/gameengine/Expressions/ConstExpr.cpp new file mode 100644 index 00000000000..c8b4c311b7c --- /dev/null +++ b/source/gameengine/Expressions/ConstExpr.cpp @@ -0,0 +1,132 @@ +// ConstExpr.cpp: implementation of the CConstExpr 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. + * + */ + + + +#include "Value.h" // for precompiled header + +#include "ConstExpr.h" +#include "VectorValue.h" + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CConstExpr::CConstExpr() +{ +} + + + +CConstExpr::CConstExpr(CValue* constval) +/* +pre: +effect: constructs a CConstExpr cointing the value constval +*/ +{ + m_value = constval; +// m_bModified=true; +} + + + +CConstExpr::~CConstExpr() +/* +pre: +effect: deletes the object +*/ +{ + if (m_value) + m_value->Release(); +} + + + +unsigned char CConstExpr::GetExpressionID() +{ + return CCONSTEXPRESSIONID; +} + + + +CValue* CConstExpr::Calculate() +/* +pre: +ret: a new object containing the value of the stored CValue +*/ +{ + return m_value->AddRef(); +} + + + +void CConstExpr::ClearModified() +{ + if (m_value) + { + m_value->SetModified(false); + m_value->SetAffected(false); + } +} + + + +float CConstExpr::GetNumber() +{ + return -1; +} + + + +bool CConstExpr::NeedsRecalculated() +{ + return m_value->IsAffected(); // IsAffected is m_bModified OR m_bAffected !!! +} + + + +CExpression* CConstExpr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) +{ +// parent checks if child is still usefull. +// When for example it's value it's deleted flag set +// then release Value, and return NULL in case of constexpression +// else return this... + + assertd(m_value); + if (m_value->IsReleaseRequested()) + { + AddRef(); //numchanges++; + return Release(); + } + else + return this; +} + + + +void CConstExpr::BroadcastOperators(VALUE_OPERATOR op) +{ + assertd(m_value); + m_value->SetColorOperator(op); +} + + + +bool CConstExpr::MergeExpression(CExpression *otherexpr) +{ + assertd(false); + return false; +} diff --git a/source/gameengine/Expressions/ConstExpr.h b/source/gameengine/Expressions/ConstExpr.h new file mode 100644 index 00000000000..4c01c142d32 --- /dev/null +++ b/source/gameengine/Expressions/ConstExpr.h @@ -0,0 +1,46 @@ +/* + * ConstExpr.h: interface for the CConstExpr class. + * $Id$ + * 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. + * + */ + +#ifndef __CONSTEXPR_H__ +#define __CONSTEXPR_H__ + +#include "Expression.h" +#include "Value.h" // Added by ClassView + +class CConstExpr : public CExpression +{ + //PLUGIN_DECLARE_SERIAL_EXPRESSION (CConstExpr,CExpression) +public: + virtual bool MergeExpression(CExpression* otherexpr); + + void BroadcastOperators(VALUE_OPERATOR op); + + virtual unsigned char GetExpressionID(); + CExpression* CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks); + //bool IsInside(float x,float y,float z,bool bBorderInclude=true); + bool NeedsRecalculated(); + void ClearModified(); + virtual float GetNumber(); + virtual CValue* Calculate(); + CConstExpr(CValue* constval); + CConstExpr(); + virtual ~CConstExpr(); + + +private: + CValue* m_value; +}; + +#endif // !defined(AFX_CONSTEXPR_H__061ECFC3_BE87_11D1_A51C_00A02472FC58__INCLUDED_) diff --git a/source/gameengine/Expressions/EXP_C-Api.cpp b/source/gameengine/Expressions/EXP_C-Api.cpp new file mode 100644 index 00000000000..4d45fd556eb --- /dev/null +++ b/source/gameengine/Expressions/EXP_C-Api.cpp @@ -0,0 +1,124 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#include "EXP_C-Api.h" +#include "IntValue.h" +#include "BoolValue.h" +#include "StringValue.h" +#include "ErrorValue.h" +#include "InputParser.h" + + +EXP_ValueHandle EXP_CreateInt(int innie) +{ + return (EXP_ValueHandle) new CIntValue(innie); +} + + + +EXP_ValueHandle EXP_CreateBool(int innie) +{ + return (EXP_ValueHandle) new CBoolValue(innie!=0); +} + + + +EXP_ValueHandle EXP_CreateString(const char* str) +{ + + return (EXP_ValueHandle) new CStringValue(str,""); +} + + + +void EXP_SetName(EXP_ValueHandle inval,const char* newname) +{ + ((CValue*) inval)->SetName(newname); +} + + + +/* calculate expression from inputtext */ +EXP_ValueHandle EXP_ParseInput(const char* inputtext) +{ + CValue* resultval=NULL; + CParser parser; + CExpression* expr = parser.ProcessText(inputtext); + if (expr) + { + resultval = expr->Calculate(); + expr->Release(); + } + else + { + resultval = new CErrorValue("couldn't parsetext"); + } + + return (EXP_ValueHandle) resultval; +} + + + +void EXP_ReleaseValue(EXP_ValueHandle inval) +{ + ((CValue*) inval)->Release(); +} + + + +int EXP_IsValid(EXP_ValueHandle inval) +{ + return !((CValue*) inval)->IsError(); +} + + + +/* assign property 'propval' to 'destinationval' */ +void EXP_SetProperty(EXP_ValueHandle destinationval, + const char* propname, + EXP_ValueHandle propval) +{ + ((CValue*) destinationval)->SetProperty(propname,(CValue*)propval); +} + + + +const char* EXP_GetText(EXP_ValueHandle inval) +{ + return ((CValue*) inval)->GetText(); +} + + + +EXP_ValueHandle EXP_GetProperty(EXP_ValueHandle inval,const char* propname) +{ + return (EXP_ValueHandle) ((CValue*)inval)->GetProperty(propname); +} diff --git a/source/gameengine/Expressions/EXP_C-Api.h b/source/gameengine/Expressions/EXP_C-Api.h new file mode 100644 index 00000000000..e99152294f1 --- /dev/null +++ b/source/gameengine/Expressions/EXP_C-Api.h @@ -0,0 +1,68 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef __EXPRESSION_INCLUDE +#define __EXPRESSION_INCLUDE + + +#define EXP_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + +EXP_DECLARE_HANDLE(EXP_ValueHandle); +EXP_DECLARE_HANDLE(EXP_ExpressionHandle); + + +#ifdef __cplusplus +extern "C" { +#endif + +extern EXP_ValueHandle EXP_CreateInt(int innie); +extern EXP_ValueHandle EXP_CreateBool(int innie); +extern EXP_ValueHandle EXP_CreateString(const char* str); +extern void EXP_SetName(EXP_ValueHandle,const char* newname); + +/* calculate expression from inputtext */ +extern EXP_ValueHandle EXP_ParseInput(const char* inputtext); +extern void EXP_ReleaseValue(EXP_ValueHandle); +extern int EXP_IsValid(EXP_ValueHandle); + +/* assign property 'propval' to 'destinationval' */ +extern void EXP_SetProperty(EXP_ValueHandle propval,EXP_ValueHandle destinationval); + +/* returns NULL if property doesn't exist */ +extern EXP_ValueHandle EXP_GetProperty(EXP_ValueHandle inval,const char* propname); + +const char* EXP_GetText(EXP_ValueHandle); + +#ifdef __cplusplus +} +#endif + +#endif //__EXPRESSION_INCLUDE diff --git a/source/gameengine/Expressions/EmptyValue.cpp b/source/gameengine/Expressions/EmptyValue.cpp new file mode 100644 index 00000000000..25c0b6af5d7 --- /dev/null +++ b/source/gameengine/Expressions/EmptyValue.cpp @@ -0,0 +1,127 @@ + +// EmptyValue.cpp: implementation of the CEmptyValue 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. + * + */ + + + + +#include "EmptyValue.h" +#include "IntValue.h" +#include "FloatValue.h" +#include "StringValue.h" +#include "ErrorValue.h" +#include "ListValue.h" +#include "VoidValue.h" + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CEmptyValue::CEmptyValue() +/* +pre: +effect: constructs a new CEmptyValue +*/ +{ + SetModified(false); +} + + + +CEmptyValue::~CEmptyValue() +/* +pre: +effect: deletes the object +*/ +{ + +} + + + +CValue * CEmptyValue::Calc(VALUE_OPERATOR op, CValue * val) +/* +pre: +ret: a new object containing the result of applying operator op to this +object and val +*/ +{ + return val->CalcFinal(VALUE_EMPTY_TYPE, op, this); + +} + + + +CValue * CEmptyValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue * val) +/* +pre: the type of val is dtype +ret: a new object containing the result of applying operator op to val and +this object +*/ +{ + return val->AddRef(); +} + + + +float CEmptyValue::GetNumber() +{ + return 0; +} + + + +CListValue* CEmptyValue::GetPolySoup() +{ + CListValue* soup = new CListValue(); + //don't add any poly, while it's an empty value + return soup; +} + + + +bool CEmptyValue::IsInside(CValue* testpoint,bool bBorderInclude) +{ + // empty space is solid, so always inside + return true; +} + + + +double* CEmptyValue::GetVector3(bool bGetTransformedVec) +{ + assertd(false); // don't get vector from me + return ZeroVector(); +} + + + +static STR_String emptyString = STR_String(""); + + +const STR_String & CEmptyValue::GetText() +{ + return emptyString; +} + + + +CValue* CEmptyValue::GetReplica() +{ + CEmptyValue* replica = new CEmptyValue(*this); + CValue::AddDataToReplica(replica); + return replica; +} + diff --git a/source/gameengine/Expressions/EmptyValue.h b/source/gameengine/Expressions/EmptyValue.h new file mode 100644 index 00000000000..d400cd065f5 --- /dev/null +++ b/source/gameengine/Expressions/EmptyValue.h @@ -0,0 +1,39 @@ +/* + * EmptyValue.h: interface for the CEmptyValue class. + * $Id$ + * 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. + * + */ +#if !defined _EMPTYVALUE_H +#define _EMPTYVALUE_H + +#include "Value.h" + +class CListValue; + +class CEmptyValue : public CPropValue +{ + //PLUGIN_DECLARE_SERIAL (CEmptyValue,CValue) +public: + CEmptyValue(); + virtual ~CEmptyValue(); + + virtual const STR_String & GetText(); + virtual float GetNumber(); + CListValue* GetPolySoup(); + virtual double* GetVector3(bool bGetTransformedVec=false); + bool IsInside(CValue* testpoint,bool bBorderInclude=true); + CValue * Calc(VALUE_OPERATOR op, CValue *val); + CValue * CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); + virtual CValue* GetReplica(); +}; + +#endif // !defined _EMPTYVALUE_H diff --git a/source/gameengine/Expressions/ErrorValue.cpp b/source/gameengine/Expressions/ErrorValue.cpp new file mode 100644 index 00000000000..fd1ba7399b3 --- /dev/null +++ b/source/gameengine/Expressions/ErrorValue.cpp @@ -0,0 +1,125 @@ +// ErrorValue.cpp: implementation of the CErrorValue 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. + * + */ + + + + + + +#include "ErrorValue.h" + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CErrorValue::CErrorValue() +/* +pre: +effect: constructs a new CErrorValue containing errormessage "Error" +*/ +{ + m_strErrorText = "Error"; + SetError(true); +} + + + +CErrorValue::CErrorValue(STR_String errmsg) +/* +pre: +effect: constructs a new CErrorValue containing errormessage errmsg +*/ +{ + m_strErrorText = "[" + errmsg + "]"; + SetError(true); +} + + + +CErrorValue::~CErrorValue() +/* +pre: +effect: deletes the object +*/ +{ + +} + + + +CValue* CErrorValue::Calc(VALUE_OPERATOR op, CValue *val) +/* +pre: +ret: a new object containing the result of applying operator op to this + object and val +*/ +{ + CValue* errorval; + + switch (op) + { + case VALUE_POS_OPERATOR: + case VALUE_NEG_OPERATOR: + case VALUE_NOT_OPERATOR: + { + errorval = new CErrorValue (op2str(op) + GetText()); + break; + } + default: + { + errorval = val->CalcFinal(VALUE_ERROR_TYPE, op, this); + break; + } + } + + return errorval; +} + + + +CValue* CErrorValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) +/* +pre: the type of val is dtype +ret: a new object containing the result of applying operator op to val and + this object +*/ +{ + return new CErrorValue (val->GetText() + op2str(op) + GetText()); +} + + + +float CErrorValue::GetNumber() +{ + return -1; +} + + + +const STR_String & CErrorValue::GetText() +{ + return m_strErrorText; +} + + + +CValue* CErrorValue::GetReplica() +{ + // who would want a copy of an error ? + trace ("Error: ErrorValue::GetReplica() not implemented yet"); + assertd(false); + + return NULL; +}
\ No newline at end of file diff --git a/source/gameengine/Expressions/ErrorValue.h b/source/gameengine/Expressions/ErrorValue.h new file mode 100644 index 00000000000..8a4726e196d --- /dev/null +++ b/source/gameengine/Expressions/ErrorValue.h @@ -0,0 +1,38 @@ +/* + * ErrorValue.h: interface for the CErrorValue class. + * $Id$ + * 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. + * + */ + +#if !defined _ERRORVALUE_H +#define _ERRORVALUE_H + +#include "Value.h" + +class CErrorValue : public CPropValue +{ + +public: + virtual const STR_String & GetText(); + virtual float GetNumber(); + CErrorValue(); + CErrorValue(STR_String errmsg); + virtual ~CErrorValue(); + virtual CValue* Calc(VALUE_OPERATOR op, CValue* val); + virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); + virtual CValue* GetReplica(); + +private: + STR_String m_strErrorText; +}; + +#endif // !defined _ERRORVALUE_H diff --git a/source/gameengine/Expressions/Expression.cpp b/source/gameengine/Expressions/Expression.cpp new file mode 100644 index 00000000000..5e7950fbcf0 --- /dev/null +++ b/source/gameengine/Expressions/Expression.cpp @@ -0,0 +1,75 @@ +// Expression.cpp: implementation of the CExpression 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. + * + */ + + + +#include "Expression.h" +#include "ErrorValue.h" +//#include "FactoryManager.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CExpression::CExpression()// : m_cached_calculate(NULL) +{ + m_refcount = 1; +#ifdef _DEBUG + //gRefCountExpr++; +#endif +} + +CExpression::~CExpression() +{ + assert (m_refcount == 0); +} + + + +// destuctor for CBrokenLinkInfo +CBrokenLinkInfo::~CBrokenLinkInfo() +{ + if (m_pExpr && !m_bRestored) + m_pExpr->Release(); +} + + +void CBrokenLinkInfo::RestoreLink() +{ + + + assertd(m_pExpr); + + if (m_pExpr) + { + if (!m_bRestored){ + m_bRestored=true; + + } + if (*m_pmemExpr) + { + (*m_pmemExpr)->Release(); + } + *m_pmemExpr = m_pExpr; + +// m_pExpr=NULL; + } +} + +void CBrokenLinkInfo::BreakLink() +{ + m_bRestored=false; + m_pExpr->AddRef(); +} + diff --git a/source/gameengine/Expressions/Expression.h b/source/gameengine/Expressions/Expression.h new file mode 100644 index 00000000000..f48ac7eb160 --- /dev/null +++ b/source/gameengine/Expressions/Expression.h @@ -0,0 +1,133 @@ +/* + * Expression.h: interface for the CExpression class. + * $Id$ + * 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. + * + */ + +#if !defined _EXPRESSION_H +#define _EXPRESSION_H + +#include "Value.h" + +//extern int gRefCountExpr; // only for debugging purposes (detect mem.leaks) + + + + +#define PLUGIN_DECLARE_SERIAL_EXPRESSION(class_name,base_class_name) \ +public: \ + virtual base_class_name * Copy() { return new class_name; } \ + virtual bool EdSerialize(CompressorArchive& arch,class CFactoryManager* facmgr,bool bIsStoring); \ + virtual bool EdIdSerialize(CompressorArchive& arch,class CFactoryManager* facmgr,bool bIsStoring) \ +{ \ + if (bIsStoring) \ + { \ + unsigned char exprID = GetExpressionID(); \ + arch << exprID; \ + } \ + return true; \ +} \ + + + +class CExpression; + + +// for undo/redo system the deletion in the expressiontree can be restored by replacing broken links 'inplace' +class CBrokenLinkInfo +{ + public: + CBrokenLinkInfo(CExpression** pmemexpr,CExpression* expr) + :m_pmemExpr(pmemexpr), + m_pExpr(expr) + { + assertd(pmemexpr); + m_bRestored=false; + }; + + virtual ~CBrokenLinkInfo(); + void RestoreLink(); + void BreakLink(); + + + // members vars + private: + CExpression** m_pmemExpr; + CExpression* m_pExpr; + bool m_bRestored; + +}; + + + + + + + + +class CExpression +{ +public: + enum { + COPERATOR1EXPRESSIONID = 1, + COPERATOR2EXPRESSIONID = 2, + CCONSTEXPRESSIONID = 3, + CIFEXPRESSIONID = 4, + COPERATORVAREXPRESSIONID = 5, + CIDENTIFIEREXPRESSIONID = 6 + }; + + +protected: + virtual ~CExpression() = 0; //pure virtual +public: + virtual bool MergeExpression(CExpression* otherexpr) = 0; + CExpression(); + + + virtual CValue* Calculate() = 0; //pure virtual + virtual unsigned char GetExpressionID() = 0; + //virtual bool IsInside(float x,float y,float z,bool bBorderInclude=true) = 0; //pure virtual + virtual bool NeedsRecalculated() = 0; // another pure one + virtual CExpression * CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) =0; // another pure one + virtual void ClearModified() = 0; // another pure one + //virtual CExpression * Copy() =0; + virtual void BroadcastOperators(VALUE_OPERATOR op) =0; + + virtual CExpression * AddRef() { // please leave multiline, for debugger !!! + +#ifdef _DEBUG + //gRefCountExpr++; + assertd(m_refcount < 255); +#endif + m_refcount++; + return this; + }; + virtual CExpression* Release(CExpression* complicatedtrick=NULL) { +#ifdef _DEBUG + //gRefCountExpr--; +#endif + if (--m_refcount < 1) + { + delete this; + } //else + // return this; + return complicatedtrick; + }; + + +protected: + + int m_refcount; +}; + +#endif // !defined _EXPRESSION_H diff --git a/source/gameengine/Expressions/FloatValue.cpp b/source/gameengine/Expressions/FloatValue.cpp new file mode 100644 index 00000000000..78185bbe163 --- /dev/null +++ b/source/gameengine/Expressions/FloatValue.cpp @@ -0,0 +1,316 @@ +// FloatValue.cpp: implementation of the CFloatValue 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. + * + */ + + +#include "FloatValue.h" +#include "IntValue.h" +#include "StringValue.h" +#include "BoolValue.h" +#include "ErrorValue.h" +#include "VoidValue.h" + +///#include "..\..\menuvalue.h" +//#include "FactoryManager.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CFloatValue::CFloatValue() +/* +pre: false +effect: constructs a new CFloatValue +*/ +{ + m_pstrRep=NULL; +} + + + +CFloatValue::CFloatValue(float fl) +/* +pre: +effect: constructs a new CFloatValue containing value fl +*/ +{ + m_float = fl; + m_pstrRep=NULL; +} + + + +CFloatValue::CFloatValue(float fl,STR_String name,AllocationTYPE alloctype) +/* +pre: +effect: constructs a new CFloatValue containing value fl +*/ +{ + + m_float = fl; + SetName(name); + if (alloctype==CValue::STACKVALUE) + { + CValue::DisableRefCount(); + + } + m_pstrRep=NULL; +} + + + +CFloatValue::~CFloatValue() +/* +pre: +effect: deletes the object +*/ +{ + if (m_pstrRep) + delete m_pstrRep; +} + + + +CValue* CFloatValue::Calc(VALUE_OPERATOR op, CValue *val) +/* +pre: +ret: a new object containing the result of applying operator op to this + object and val +*/ +{ + //return val->CalcFloat(op, this); + switch (op) + { + case VALUE_POS_OPERATOR: + return new CFloatValue (m_float); + break; + case VALUE_NEG_OPERATOR: + return new CFloatValue (-m_float); + break; + case VALUE_NOT_OPERATOR: + return new CErrorValue (op2str(op) + "only allowed on booleans"); + break; + case VALUE_AND_OPERATOR: + case VALUE_OR_OPERATOR: + return new CErrorValue(val->GetText() + op2str(op) + "only allowed on booleans"); + break; + default: + return val->CalcFinal(VALUE_FLOAT_TYPE, op, this); + break; + } +} + + + +CValue* CFloatValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) +/* +pre: the type of val is dtype +ret: a new object containing the result of applying operator op to val and + this object +*/ +{ + CValue *ret; + + switch(dtype) + { + case VALUE_INT_TYPE: + { + switch (op) + { + case VALUE_ADD_OPERATOR: + ret = new CFloatValue(((CIntValue *) val)->GetInt() + m_float); + break; + case VALUE_SUB_OPERATOR: + ret = new CFloatValue(((CIntValue *) val)->GetInt() - m_float); + break; + case VALUE_MUL_OPERATOR: + ret = new CFloatValue(((CIntValue *) val)->GetInt() * m_float); + break; + case VALUE_DIV_OPERATOR: + if (m_float == 0) + ret = new CErrorValue("Division by zero"); + else + ret = new CFloatValue (((CIntValue *) val)->GetInt() / m_float); + break; + case VALUE_EQL_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() == m_float); + break; + case VALUE_NEQ_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() != m_float); + break; + case VALUE_GRE_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() > m_float); + break; + case VALUE_LES_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() < m_float); + break; + case VALUE_GEQ_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() >= m_float); + break; + case VALUE_LEQ_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() <= m_float); + break; + default: + ret = new CErrorValue("illegal operator. please send a bug report."); + break; + } + break; + } + case VALUE_EMPTY_TYPE: + case VALUE_FLOAT_TYPE: + { + switch (op) + { + case VALUE_ADD_OPERATOR: + ret = new CFloatValue(((CFloatValue *) val)->GetFloat() + m_float); + break; + case VALUE_SUB_OPERATOR: + ret = new CFloatValue(((CFloatValue *) val)->GetFloat() - m_float); + break; + case VALUE_MUL_OPERATOR: + ret = new CFloatValue(((CFloatValue *) val)->GetFloat() * m_float); + break; + case VALUE_DIV_OPERATOR: + if (m_float == 0) + ret = new CErrorValue("Division by zero"); + else + ret = new CFloatValue (((CFloatValue *) val)->GetFloat() / m_float); + break; + case VALUE_EQL_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() == m_float); + break; + case VALUE_NEQ_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() != m_float); + break; + case VALUE_GRE_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() > m_float); + break; + case VALUE_LES_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() < m_float); + break; + case VALUE_GEQ_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() >= m_float); + break; + case VALUE_LEQ_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() <= m_float); + break; + case VALUE_NEG_OPERATOR: + ret = new CFloatValue (-m_float); + break; + case VALUE_POS_OPERATOR: + ret = new CFloatValue (m_float); + break; + + default: + ret = new CErrorValue("illegal operator. please send a bug report."); + break; + } + break; + } + case VALUE_STRING_TYPE: + { + switch(op) + { + case VALUE_ADD_OPERATOR: + ret = new CStringValue(val->GetText() + GetText(),""); + break; + case VALUE_EQL_OPERATOR: + case VALUE_NEQ_OPERATOR: + case VALUE_GRE_OPERATOR: + case VALUE_LES_OPERATOR: + case VALUE_GEQ_OPERATOR: + case VALUE_LEQ_OPERATOR: + ret = new CErrorValue("[Cannot compare string with float]" + op2str(op) + GetText()); + break; + default: + ret = new CErrorValue("[operator not allowed on strings]" + op2str(op) + GetText()); + break; + } + break; + } + case VALUE_BOOL_TYPE: + ret = new CErrorValue("[operator not valid on boolean and float]" + op2str(op) + GetText()); + break; + case VALUE_ERROR_TYPE: + ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); + break; + default: + ret = new CErrorValue("illegal type. contact your dealer (if any)"); + break; + } + return ret; +} + + + +void CFloatValue::SetFloat(float fl) +{ + m_float = fl; + SetModified(true); +} + + + +float CFloatValue::GetFloat() +/* +pre: +ret: the float stored in the object +*/ +{ + return m_float; +} + + + +float CFloatValue::GetNumber() +{ + return m_float; +} + + + +void CFloatValue::SetValue(CValue* newval) +{ + m_float = newval->GetNumber(); + SetModified(true); +} + + + +const STR_String & CFloatValue::GetText() +{ + if (!m_pstrRep) + m_pstrRep = new STR_String(); + + m_pstrRep->Format("%f",m_float); + return *m_pstrRep; +} + + + +CValue* CFloatValue::GetReplica() +{ + CFloatValue* replica = new CFloatValue(*this); + replica->m_pstrRep = NULL; + CValue::AddDataToReplica(replica); + + return replica; +} + + + +PyObject* CFloatValue::ConvertValueToPython() +{ + return PyFloat_FromDouble(m_float); +} + diff --git a/source/gameengine/Expressions/FloatValue.h b/source/gameengine/Expressions/FloatValue.h new file mode 100644 index 00000000000..4dce35ebfa0 --- /dev/null +++ b/source/gameengine/Expressions/FloatValue.h @@ -0,0 +1,48 @@ +/* + * FloatValue.h: interface for the CFloatValue class. + * $Id$ + * 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. + * + */ +#if !defined _FLOATVALUE_H +#define _FLOATVALUE_H + +#include "Value.h" + + +class CFloatValue : public CPropValue +{ + //PLUGIN_DECLARE_SERIAL (CFloatValue,CValue) +public: + CFloatValue(); + CFloatValue(float fl); + CFloatValue(float fl,STR_String name,AllocationTYPE alloctype=CValue::HEAPVALUE); + + virtual const STR_String & GetText(); + + void Configure(CValue* menuvalue); + virtual float GetNumber(); + virtual void SetValue(CValue* newval); + float GetFloat(); + void SetFloat(float fl); + virtual ~CFloatValue(); + virtual CValue* GetReplica(); + virtual CValue* Calc(VALUE_OPERATOR op, CValue *val); + virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); + virtual PyObject* ConvertValueToPython(); + +protected: + float m_float; + STR_String* m_pstrRep; + +}; + +#endif // !defined _FLOATVALUE_H diff --git a/source/gameengine/Expressions/IdentifierExpr.cpp b/source/gameengine/Expressions/IdentifierExpr.cpp new file mode 100644 index 00000000000..ff517aa7636 --- /dev/null +++ b/source/gameengine/Expressions/IdentifierExpr.cpp @@ -0,0 +1,103 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "IdentifierExpr.h" + + +CIdentifierExpr::CIdentifierExpr(const STR_String& identifier,CValue* id_context) +:m_identifier(identifier) +{ + if (id_context) + m_idContext = id_context->AddRef(); + else + m_idContext=NULL; +} + + +CIdentifierExpr::~CIdentifierExpr() +{ + if (m_idContext) + m_idContext->Release(); +} + + + +CValue* CIdentifierExpr::Calculate() +{ + CValue* result = NULL; + if (m_idContext) + result = m_idContext->FindIdentifier(m_identifier); + + return result; +} + + + +bool CIdentifierExpr::MergeExpression(CExpression* otherexpr) +{ + return false; +} + + + +unsigned char CIdentifierExpr::GetExpressionID() +{ + return CIDENTIFIEREXPRESSIONID; +} + + + +bool CIdentifierExpr::NeedsRecalculated() +{ + return true; +} + + + +CExpression* CIdentifierExpr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) +{ + assertd(false); // not implemented yet + return NULL; +} + + + +void CIdentifierExpr::ClearModified() +{ + assertd(false); // not implemented yet +} + + + +void CIdentifierExpr::BroadcastOperators(VALUE_OPERATOR op) +{ + assertd(false); // not implemented yet +}
\ No newline at end of file diff --git a/source/gameengine/Expressions/IdentifierExpr.h b/source/gameengine/Expressions/IdentifierExpr.h new file mode 100644 index 00000000000..dbffe7c02bc --- /dev/null +++ b/source/gameengine/Expressions/IdentifierExpr.h @@ -0,0 +1,55 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef __IDENTIFIER_EXPR +#define __IDENTIFIER_EXPR + +#include "Expression.h" + +class CIdentifierExpr : public CExpression +{ + CValue* m_idContext; + STR_String m_identifier; +public: + CIdentifierExpr(const STR_String& identifier,CValue* id_context); + virtual ~CIdentifierExpr(); + + virtual CValue* Calculate(); + virtual bool MergeExpression(CExpression* otherexpr); + virtual unsigned char GetExpressionID(); + virtual bool NeedsRecalculated(); + virtual CExpression* CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks); + virtual void ClearModified(); + virtual void BroadcastOperators(VALUE_OPERATOR op); +}; + +#endif //__IDENTIFIER_EXPR + diff --git a/source/gameengine/Expressions/IfExpr.cpp b/source/gameengine/Expressions/IfExpr.cpp new file mode 100644 index 00000000000..bcb365b87cc --- /dev/null +++ b/source/gameengine/Expressions/IfExpr.cpp @@ -0,0 +1,141 @@ +// IfExpr.cpp: implementation of the CIfExpr 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. + * + */ + +#include "IfExpr.h" +#include "EmptyValue.h" +#include "ErrorValue.h" + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +CIfExpr::CIfExpr() +{ +} + + + +CIfExpr::CIfExpr(CExpression *guard, CExpression *e1, CExpression *e2) +/* +pre: +effect: constructs an CifExpr-object corresponding to IF(guard, e1, e2) +*/ +{ + m_guard = guard; + m_e1 = e1; + m_e2 = e2; +} + + + +CIfExpr::~CIfExpr() +/* +pre: +effect: dereferences the object +*/ +{ + if (m_guard) + m_guard->Release(); + + if (m_e1) + m_e1->Release(); + + if (m_e2) + m_e2->Release(); +} + + + +CValue* CIfExpr::Calculate() +/* +pre: +ret: a new object containing the value of m_e1 if m_guard is a boolean TRUE + a new object containing the value of m_e2 if m_guard is a boolean FALSE + an new errorvalue if m_guard is not a boolean +*/ +{ + CValue *guardval; + guardval = m_guard->Calculate(); + STR_String text = guardval->GetText(); + guardval->Release(); + + if (text == STR_String("TRUE")) + { + return m_e1->Calculate(); + } + else if (text == STR_String("FALSE")) + { + return m_e2->Calculate(); + } + else + { + return new CErrorValue("Guard should be of boolean type"); + } +} + + + +bool CIfExpr::MergeExpression(CExpression *otherexpr) +{ + assertd(false); + return false; +} + + + +bool CIfExpr::IsInside(float x,float y,float z,bool bBorderInclude) +{ + assertd(false); + return false; +} + + + +bool CIfExpr::NeedsRecalculated() +{ + return (m_guard->NeedsRecalculated() || + m_e1->NeedsRecalculated() || + m_e2->NeedsRecalculated()); +} + + + +CExpression* CIfExpr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) +{ + assertd(false); + return NULL; +} + + + +void CIfExpr::ClearModified() +{ + assertd(false); +} + + + +void CIfExpr::BroadcastOperators(VALUE_OPERATOR op) +{ + assertd(false); +} + + + +unsigned char CIfExpr::GetExpressionID() +{ + return CIFEXPRESSIONID; +}
\ No newline at end of file diff --git a/source/gameengine/Expressions/IfExpr.h b/source/gameengine/Expressions/IfExpr.h new file mode 100644 index 00000000000..192edfe8fee --- /dev/null +++ b/source/gameengine/Expressions/IfExpr.h @@ -0,0 +1,49 @@ +/* + * IfExpr.h: interface for the CIfExpr class. + * $Id$ + * 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. + * + */ +#if !defined(AFX_IFEXPR_H__1F691841_C5C7_11D1_A863_0000B4542BD8__INCLUDED_) +#define AFX_IFEXPR_H__1F691841_C5C7_11D1_A863_0000B4542BD8__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +#include "Expression.h" + +class CIfExpr : public CExpression +{ + //PLUGIN_DECLARE_SERIAL_EXPRESSION (CIfExpr,CExpression) + +private: + CExpression *m_guard, *m_e1, *m_e2; + +public: + virtual bool MergeExpression(CExpression* otherexpr); + CIfExpr(CExpression *guard, CExpression *e1, CExpression *e2); + CIfExpr(); + + virtual unsigned char GetExpressionID(); + virtual ~CIfExpr(); + virtual CValue* Calculate(); + + virtual bool IsInside(float x,float y,float z,bool bBorderInclude=true); + virtual bool NeedsRecalculated(); + + + virtual CExpression* CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks); + virtual void ClearModified(); + virtual void BroadcastOperators(VALUE_OPERATOR op); +}; + +#endif // !defined(AFX_IFEXPR_H__1F691841_C5C7_11D1_A863_0000B4542BD8__INCLUDED_) diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp new file mode 100644 index 00000000000..efb5e277737 --- /dev/null +++ b/source/gameengine/Expressions/InputParser.cpp @@ -0,0 +1,648 @@ +// Parser.cpp: implementation of the CParser 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. + * + */ + +#include <stdlib.h> + +#include "Value.h" +#include "InputParser.h" +#include "ErrorValue.h" +#include "IntValue.h" +#include "StringValue.h" +#include "FloatValue.h" +#include "BoolValue.h" +#include "EmptyValue.h" +#include "ConstExpr.h" +#include "Operator2Expr.h" +#include "Operator1Expr.h" +#include "IdentifierExpr.h" + +// this is disable at the moment, I expected a memleak from it, but the error-cleanup was the reason +// well, looks we don't need it anyway, until maybe the Curved Surfaces are integrated into CSG +// cool things like (IF(LOD==1,CCurvedValue,IF(LOD==2,CCurvedValue2)) etc... +#include "IfExpr.h" + + +#define NUM_PRIORITY 6 +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CParser::CParser() : m_identifierContext(NULL) +{ +} + + + +CParser::~CParser() +{ + if (m_identifierContext) + m_identifierContext->Release(); +} + + + +void CParser::ScanError(STR_String str) +{ + // sets the global variable errmsg to an errormessage with + // contents str, appending if it already exists + // AfxMessageBox("Parse Error:"+str,MB_ICONERROR); + if (errmsg) + errmsg = new COperator2Expr(VALUE_ADD_OPERATOR, errmsg, Error(str)); + else + errmsg = Error(str); + + sym = errorsym; +} + + + +CExpression* CParser::Error(STR_String str) +{ + // makes and returns a new CConstExpr filled with an CErrorValue + // with string str + // AfxMessageBox("Error:"+str,MB_ICONERROR); + return new CConstExpr(new CErrorValue(str)); +} + + + +void CParser::NextCh() +{ + // sets the global variable ch to the next character, if it exists + // and increases the global variable chcount + chcount++; + + if (chcount < text.Length()) + ch = text[chcount]; + else + ch = 0x00; +} + + + +void CParser::TermChar(char c) +{ + // generates an error if the next char isn't the specified char c, + // otherwise, skip the char + if(ch == c) + { + NextCh(); + } + else + { + STR_String str; + str.Format("Warning: %c expected\ncontinuing without it", c); + trace(str); + } +} + + + +void CParser::DigRep() +{ + // changes the current character to the first character that + // isn't a decimal + while ((ch >= '0') && (ch <= '9')) + NextCh(); +} + + + +void CParser::CharRep() +{ + // changes the current character to the first character that + // isn't an alphanumeric character + while (((ch >= '0') && (ch <= '9')) + || ((ch >= 'a') && (ch <= 'z')) + || ((ch >= 'A') && (ch <= 'Z')) + || (ch == '.') || (ch == '_')) + NextCh(); +} + + + +void CParser::GrabString(int start) +{ + // puts part of the input string into the global variable + // const_as_string, from position start, to position chchount + const_as_string = text.Mid(start, chcount-start); +} + + + +void CParser::NextSym() +{ + // sets the global variable sym to the next symbol, and + // if it is an operator + // sets the global variable opkind to the kind of operator + // if it is a constant + // sets the global variable constkind to the kind of operator + // if it is a reference to a cell + // sets the global variable cellcoord to the kind of operator + + errmsg = NULL; + while(ch == ' ' || ch == 0x9) + NextCh(); + + switch(ch) + { + case '(': + sym = lbracksym; NextCh(); + break; + case ')': + sym = rbracksym; NextCh(); + break; + case ',': + sym = commasym; NextCh(); + break; + case '+' : + sym = opsym; opkind = OPplus; NextCh(); + break; + case '-' : + sym = opsym; opkind = OPminus; NextCh(); + break; + case '*' : + sym = opsym; opkind = OPtimes; NextCh(); + break; + case '/' : + sym = opsym; opkind = OPdivide; NextCh(); + break; + case '&' : + sym = opsym; opkind = OPand; NextCh(); TermChar('&'); + break; + case '|' : + sym = opsym; opkind = OPor; NextCh(); TermChar('|'); + break; + case '=' : + sym = opsym; opkind = OPequal; NextCh(); TermChar('='); + break; + case '!' : + sym = opsym; + NextCh(); + if (ch == '=') + { + opkind = OPunequal; + NextCh(); + } + else + { + opkind = OPnot; + } + break; + case '>': + sym = opsym; + NextCh(); + if (ch == '=') + { + opkind = OPgreaterequal; + NextCh(); + } + else + { + opkind = OPgreater; + } + break; + case '<': + sym = opsym; + NextCh(); + if (ch == '=') { + opkind = OPlessequal; + NextCh(); + } else { + opkind = OPless; + } + break; + case '\"' : { + int start; + sym = constsym; + constkind = stringtype; + NextCh(); + start = chcount; + while ((ch != '\"') && (ch != 0x0)) + NextCh(); + GrabString(start); + TermChar('\"'); // check for eol before '\"' + break; + } + case 0x0: sym = eolsym; break; + default: + { + int start; + start = chcount; + DigRep(); + if ((start != chcount) || (ch == '.')) { // number + sym = constsym; + if (ch == '.') { + constkind = floattype; + NextCh(); + DigRep(); + } + else constkind = inttype; + if ((ch == 'e') || (ch == 'E')) { + int mark; + constkind = floattype; + NextCh(); + if ((ch == '+') || (ch == '-')) NextCh(); + mark = chcount; + DigRep(); + if (mark == chcount) { + ScanError("Number expected after 'E'"); + return; + } + } + GrabString(start); + } else if (((ch >= 'a') && (ch <= 'z')) + || ((ch >= 'A') && (ch <= 'Z'))) + { // reserved word? + int start; + STR_String funstr; + start = chcount; + CharRep(); + GrabString(start); + funstr = const_as_string; + funstr.Upper(); + if (funstr == STR_String("SUM")) { + sym = sumsym; + } + else if (funstr == STR_String("NOT")) { + sym = opsym; + opkind = OPnot; + } + else if (funstr == STR_String("AND")) { + sym = opsym; opkind = OPand; + } + else if (funstr == STR_String("OR")) { + sym = opsym; opkind = OPor; + } + else if (funstr == STR_String("IF")) { + sym = ifsym; + } else if (funstr == STR_String("WHOMADE")) { + sym = whocodedsym; + } else if (funstr == STR_String("FALSE")) { + sym = constsym; constkind = booltype; boolvalue = false; + } else if (funstr == STR_String("TRUE")) { + sym = constsym; constkind = booltype; boolvalue = true; + } else { + sym = idsym; + //STR_String str; + //str.Format("'%s' makes no sense here", (const char*)funstr); + //ScanError(str); + } + } else { // unknown symbol + STR_String str; + str.Format("Unexpected character '%c'", ch); + NextCh(); + ScanError(str); + return; + } + } + } +} + +int CParser::MakeInt() { + // returns the integer representation of the value in the global + // variable const_as_string + // pre: const_as_string contains only numercal chars + return atoi(const_as_string); +} + +STR_String CParser::Symbol2Str(int s) { + // returns a string representation of of symbol s, + // for use in Term when generating an error + switch(s) { + case errorsym: return "error"; + case lbracksym: return "("; + case rbracksym: return ")"; + case commasym: return ","; + case opsym: return "operator"; + case constsym: return "constant"; + case sumsym: return "SUM"; + case ifsym: return "IF"; + case whocodedsym: return "WHOMADE"; + case eolsym: return "end of line"; + case idsym: return "identifier"; + default: return "unknown"; // should not happen + } +} + +void CParser::Term(int s) { + // generates an error if the next symbol isn't the specified symbol s + // otherwise, skip the symbol + if(s == sym) NextSym(); + else { + STR_String msg; + msg.Format("Warning: " + Symbol2Str(s) + " expected\ncontinuing without it"); + +// AfxMessageBox(msg,MB_ICONERROR); + + trace(msg); + } +} + +int CParser::Priority(int optorkind) { + // returns the priority of an operator + // higher number means higher priority + switch(optorkind) { + case OPor: return 1; + case OPand: return 2; + case OPgreater: + case OPless: + case OPgreaterequal: + case OPlessequal: + case OPequal: + case OPunequal: return 3; + case OPplus: + case OPminus: return 4; + case OPtimes: + case OPdivide: return 5; + } + assert(false); + return 0; // should not happen +} + +CExpression *CParser::Ex(int i) { + // parses an expression in the imput, starting at priority i, and + // returns an CExpression, containing the parsed input + CExpression *e1 = NULL, *e2 = NULL; + int opkind2; + + if (i < NUM_PRIORITY) { + e1 = Ex(i + 1); + while ((sym == opsym) && (Priority(opkind) == i)) { + opkind2 = opkind; + NextSym(); + e2 = Ex(i + 1); + switch(opkind2) { + case OPplus: e1 = new COperator2Expr(VALUE_ADD_OPERATOR,e1, e2); break; + case OPminus: e1 = new COperator2Expr(VALUE_SUB_OPERATOR,e1, e2); break; + case OPtimes: e1 = new COperator2Expr(VALUE_MUL_OPERATOR,e1, e2); break; + case OPdivide: e1 = new COperator2Expr(VALUE_DIV_OPERATOR,e1, e2); break; + case OPand: e1 = new COperator2Expr(VALUE_AND_OPERATOR,e1, e2); break; + case OPor: e1 = new COperator2Expr(VALUE_OR_OPERATOR,e1, e2); break; + case OPequal: e1 = new COperator2Expr(VALUE_EQL_OPERATOR,e1, e2); break; + case OPunequal: e1 = new COperator2Expr(VALUE_NEQ_OPERATOR,e1, e2); break; + case OPgreater: e1 = new COperator2Expr(VALUE_GRE_OPERATOR,e1, e2); break; + case OPless: e1 = new COperator2Expr(VALUE_LES_OPERATOR,e1, e2); break; + case OPgreaterequal: e1 = new COperator2Expr(VALUE_GEQ_OPERATOR,e1, e2); break; + case OPlessequal: e1 = new COperator2Expr(VALUE_LEQ_OPERATOR,e1, e2); break; + default: assert(false); break; // should not happen + } + } + } else if (i == NUM_PRIORITY) { + if ((sym == opsym) + && ( (opkind == OPminus) || (opkind == OPnot) || (opkind == OPplus) ) + ) + { + NextSym(); + switch(opkind) { + /* +1 is also a valid number! */ + case OPplus: e1 = new COperator1Expr(VALUE_POS_OPERATOR, Ex(NUM_PRIORITY)); break; + case OPminus: e1 = new COperator1Expr(VALUE_NEG_OPERATOR, Ex(NUM_PRIORITY)); break; + case OPnot: e1 = new COperator1Expr(VALUE_NOT_OPERATOR, Ex(NUM_PRIORITY)); break; + default: { + // should not happen + e1 = Error("operator +, - or ! expected"); + } + } + } + else { + switch(sym) { + case constsym: { + switch(constkind) { + case booltype: + e1 = new CConstExpr(new CBoolValue(boolvalue)); + break; + case inttype: + { + int temp; + temp = atoi(const_as_string); + e1 = new CConstExpr(new CIntValue(temp)); + break; + } + case floattype: + { + double temp; + temp = atof(const_as_string); + e1 = new CConstExpr(new CFloatValue(temp)); + break; + } + case stringtype: + e1 = new CConstExpr(new CStringValue(const_as_string,"")); + break; + default : + assert(false); + break; + } + NextSym(); + break; + } + case lbracksym: + NextSym(); + e1 = Ex(1); + Term(rbracksym); + break; + case ifsym: + { + CExpression *e3; + NextSym(); + Term(lbracksym); + e1 = Ex(1); + Term(commasym); + e2 = Ex(1); + if (sym == commasym) { + NextSym(); + e3 = Ex(1); + } else { + e3 = new CConstExpr(new CEmptyValue()); + } + Term(rbracksym); + e1 = new CIfExpr(e1, e2, e3); + break; + } + case idsym: + { + e1 = new CIdentifierExpr(const_as_string,m_identifierContext); + NextSym(); + + break; + } + case errorsym: + { + assert(!e1); + STR_String errtext="[no info]"; + if (errmsg) + { + CValue* errmsgval = errmsg->Calculate(); + errtext=errmsgval->GetText(); + errmsgval->Release(); + + //e1 = Error(errmsg->Calculate()->GetText());//new CConstExpr(errmsg->Calculate()); + + if ( !(errmsg->Release()) ) + { + errmsg=NULL; + } else { + // does this happen ? + assert ("does this happen"); + } + } + e1 = Error(errtext); + + break; + } + default: + NextSym(); + //return Error("Expression expected"); + assert(!e1); + e1 = Error("Expression expected"); + } + } + } + return e1; +} + +CExpression *CParser::Expr() { + // parses an expression in the imput, and + // returns an CExpression, containing the parsed input + return Ex(1); +} + +CExpression* CParser::ProcessText +(STR_String intext) { + + // and parses the string in intext and returns it. + + + CExpression* expr; + text = intext; + + + chcount = 0; + if (text.Length() == 0) { + return NULL; + } + + ch = text[0]; + /*if (ch != '=') { + expr = new CConstExpr(new CStringValue(text)); + *dependant = deplist; + return expr; + } else + */ + // NextCh(); + NextSym(); + expr = Expr(); + if (sym != eolsym) { + CExpression* oldexpr = expr; + expr = new COperator2Expr(VALUE_ADD_OPERATOR, + oldexpr, Error(STR_String("Extra characters after expression")));//new CConstExpr(new CErrorValue("Extra characters after expression"))); + } + if (errmsg) + errmsg->Release(); + + return expr; +} + + + +float CParser::GetFloat(STR_String txt) +{ + // returns parsed text into a float + // empty string returns -1 + +// AfxMessageBox("parsed string="+txt); + CValue* val=NULL; + float result=-1; +// String tmpstr; + + CExpression* expr = ProcessText(txt); + if (expr) { + val = expr->Calculate(); + result=val->GetNumber(); + + + + val->Release(); + expr->Release(); + } +// tmpstr.Format("parseresult=%g",result); +// AfxMessageBox(tmpstr); + return result; +} + +CValue* CParser::GetValue(STR_String txt, bool bFallbackToText) +{ + // returns parsed text into a value, + // empty string returns NULL value ! + // if bFallbackToText then unparsed stuff is put into text + + CValue* result=NULL; + CExpression* expr = ProcessText(txt); + if (expr) { + result = expr->Calculate(); + expr->Release(); + } + if (result) + { + // if the parsed stuff lead to an errorvalue, don't return errors, just NULL + if (result->IsError()) { + result->Release(); + result=NULL; + if (bFallbackToText) { + if (txt.Length()>0) + { + result = new CStringValue(txt,""); + } + } + } + } + return result; +} + +void CParser::SetContext(CValue* context) +{ + if (m_identifierContext) + { + m_identifierContext->Release(); + } + m_identifierContext = context; +} + + + + +PyObject* CParserPyMake(PyObject* ignored,PyObject* args) +{ + char* txt; + Py_Try(PyArg_ParseTuple(args,"s",&txt)); + CParser parser; + CExpression* expr = parser.ProcessText(txt); + CValue* val = expr->Calculate(); + expr->Release(); + return val; +} + +static PyMethodDef CParserMethods[] = +{ + { "calc", CParserPyMake , Py_NEWARGS}, + { NULL,NULL} // Sentinel +}; + +extern "C" { + void initExpressionModule(void) + { + Py_InitModule("Expression",CParserMethods); + } +} + diff --git a/source/gameengine/Expressions/InputParser.h b/source/gameengine/Expressions/InputParser.h new file mode 100644 index 00000000000..43832f9c350 --- /dev/null +++ b/source/gameengine/Expressions/InputParser.h @@ -0,0 +1,105 @@ +/* + * Parser.h: interface for the CParser class. + * Eindhoven University of Technology 1997 + * OOPS team (Serge vd Boom, Erwin Coumans, Tom Geelen, Wynke Stuylemeier) + * $Id$ + * 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. + * + */ +#ifndef __INPUTPARSER_H__ +#define __INPUTPARSER_H__ + +class CParser; +#include "Expression.h" + + +class CParser +{ +public: + CParser(); + virtual ~CParser(); + + float GetFloat(STR_String txt); + CValue* GetValue(STR_String txt, bool bFallbackToText=false); + CExpression* ProcessText(STR_String intext); + void SetContext(CValue* context); + +private: + enum symbols { + errorsym, + lbracksym, + rbracksym, + cellsym, + commasym, + opsym, + constsym, + sumsym, + ifsym, + whocodedsym, + eolsym, + idsym + }; // all kinds of symbols + + enum optype { + OPplus, + OPminus, + OPtimes, + OPdivide, + OPand, + OPor, + OPequal, + OPunequal, + OPgreater, + OPless, + OPgreaterequal, + OPlessequal, + OPnot + }; // all kinds of operators + + enum consttype { + booltype, + inttype, + floattype, + stringtype + }; // all kinds of constants + + int sym, // current symbol + opkind, // kind of operator, if symbol is an operator + constkind; // kind of operator, if symbol is a constant + + char ch; // current character + int chcount; // index to character in input string + CExpression *errmsg; // contains a errormessage, if scanner error + + STR_String text, // contains a copy of the original text + const_as_string; // string representation of the symbol, if symbol is a constant + bool boolvalue; // value of the boolean, if symbol is a constant of type boolean + CValue* m_identifierContext;// context in which identifiers are looked up + + + void ScanError(STR_String str); + CExpression* Error(STR_String str); + void NextCh(); + void TermChar(char c); + void DigRep(); + void CharRep(); + void GrabString(int start); + void NextSym(); + int MakeInt(); + STR_String Symbol2Str(int s); + void Term(int s); + int Priority(int optor); + CExpression *Ex(int i); + CExpression *Expr(); + +}; + +#endif diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp new file mode 100644 index 00000000000..591fe76cd48 --- /dev/null +++ b/source/gameengine/Expressions/IntValue.cpp @@ -0,0 +1,325 @@ +// IntValue.cpp: implementation of the CIntValue 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. +* +*/ + + +#include "IntValue.h" +#include "ErrorValue.h" +#include "FloatValue.h" +#include "BoolValue.h" +#include "StringValue.h" +#include "VoidValue.h" +//#include "FactoryManager.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CIntValue::CIntValue() +/* +pre: false +effect: constructs a new CIntValue +*/ +{ + +#ifdef _DEBUG_ + m_textval = "Int illegal constructor"; +#endif + m_pstrRep=NULL; +} + + + +CIntValue::CIntValue(int innie) +/* +pre: +effect: constructs a new CIntValue containing int innie +*/ +{ + m_int = innie; + m_pstrRep=NULL; +} + + + +CIntValue::CIntValue(int innie,STR_String name,AllocationTYPE alloctype) +{ + m_int = innie; + SetName(name); + + if (alloctype==CValue::STACKVALUE) + { + CValue::DisableRefCount(); + } + m_pstrRep=NULL; + +} + + + +CIntValue::~CIntValue() +/* +pre: +effect: deletes the object +*/ +{ + if (m_pstrRep) + delete m_pstrRep; +} + + + +CValue* CIntValue::Calc(VALUE_OPERATOR op, CValue *val) +/* +pre: +ret: a new object containing the result of applying operator op to this +object and val +*/ +{ + //return val->CalcInt(op, this); + switch (op) { + case VALUE_POS_OPERATOR: + return new CIntValue (m_int); + break; + case VALUE_NEG_OPERATOR: + return new CIntValue (-m_int); + break; + case VALUE_NOT_OPERATOR: + return new CErrorValue (op2str(op) + "only allowed on booleans"); + break; + case VALUE_AND_OPERATOR: + case VALUE_OR_OPERATOR: + return new CErrorValue(val->GetText() + op2str(op) + "only allowed on booleans"); + break; + default: + return val->CalcFinal(VALUE_INT_TYPE, op, this); + break; + } +} + + + +CValue* CIntValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) +/* +pre: the type of val is dtype +ret: a new object containing the result of applying operator op to val and +this object +*/ +{ + CValue *ret; + + switch(dtype) { + case VALUE_EMPTY_TYPE: + case VALUE_INT_TYPE: + { + switch (op) { + case VALUE_ADD_OPERATOR: + ret = new CIntValue (((CIntValue *) val)->GetInt() + m_int); + break; + case VALUE_SUB_OPERATOR: + ret = new CIntValue (((CIntValue *) val)->GetInt() - m_int); + break; + case VALUE_MUL_OPERATOR: + ret = new CIntValue (((CIntValue *) val)->GetInt() * m_int); + break; + case VALUE_DIV_OPERATOR: + if (m_int == 0) + { + if (val->GetNumber() == 0) + { + ret = new CErrorValue("Not a Number"); + } else + { + ret = new CErrorValue("Division by zero"); + } + } + else + ret = new CIntValue (((CIntValue *) val)->GetInt() / m_int); + break; + case VALUE_EQL_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() == m_int); + break; + case VALUE_NEQ_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() != m_int); + break; + case VALUE_GRE_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() > m_int); + break; + case VALUE_LES_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() < m_int); + break; + case VALUE_GEQ_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() >= m_int); + break; + case VALUE_LEQ_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() <= m_int); + break; + case VALUE_NEG_OPERATOR: + ret = new CIntValue (-m_int); + break; + case VALUE_POS_OPERATOR: + ret = new CIntValue (m_int); + break; + default: + ret = new CErrorValue("illegal operator. please send a bug report."); + break; + } + break; + } + case VALUE_FLOAT_TYPE: + { + switch (op) { + case VALUE_ADD_OPERATOR: + ret = new CFloatValue (((CFloatValue *) val)->GetFloat() + m_int); + break; + case VALUE_SUB_OPERATOR: + ret = new CFloatValue (((CFloatValue *) val)->GetFloat() - m_int); + break; + case VALUE_MUL_OPERATOR: + ret = new CFloatValue (((CFloatValue *) val)->GetFloat() * m_int); + break; + case VALUE_DIV_OPERATOR: + if (m_int == 0) + ret = new CErrorValue("Division by zero"); + else + ret = new CFloatValue (((CFloatValue *) val)->GetFloat() / m_int); + break; + case VALUE_EQL_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() == m_int); + break; + case VALUE_NEQ_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() != m_int); + break; + case VALUE_GRE_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() > m_int); + break; + case VALUE_LES_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() < m_int); + break; + case VALUE_GEQ_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() >= m_int); + break; + case VALUE_LEQ_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() <= m_int); + break; + default: + ret = new CErrorValue("illegal operator. please send a bug report."); + break; + } + break; + } + case VALUE_STRING_TYPE: + { + switch(op) { + case VALUE_ADD_OPERATOR: + ret = new CStringValue(val->GetText() + GetText(),""); + break; + case VALUE_EQL_OPERATOR: + case VALUE_NEQ_OPERATOR: + case VALUE_GRE_OPERATOR: + case VALUE_LES_OPERATOR: + case VALUE_GEQ_OPERATOR: + case VALUE_LEQ_OPERATOR: + ret = new CErrorValue("[Cannot compare string with integer]" + op2str(op) + GetText()); + break; + default: + ret = new CErrorValue("[operator not allowed on strings]" + op2str(op) + GetText()); + break; + } + break; + } + case VALUE_BOOL_TYPE: + ret = new CErrorValue("[operator not valid on boolean and integer]" + op2str(op) + GetText()); + break; + /* + case VALUE_EMPTY_TYPE: + { + switch(op) { + + case VALUE_ADD_OPERATOR: + ret = new CIntValue (m_int); + break; + case VALUE_SUB_OPERATOR: + ret = new CIntValue (-m_int); + break; + default: + { + ret = new CErrorValue(op2str(op) + GetText()); + } + } + break; + } + */ + case VALUE_ERROR_TYPE: + ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); + break; + default: + ret = new CErrorValue("illegal type. contact your dealer (if any)"); + break; + } + return ret; +} + + + +int CIntValue::GetInt() +/* +pre: +ret: the int stored in the object +*/ +{ + return m_int; +} + + + +float CIntValue::GetNumber() +{ + return (float) m_int; +} + + + +const STR_String & CIntValue::GetText() +{ + if (!m_pstrRep) + m_pstrRep=new STR_String(); + m_pstrRep->Format("%d",m_int); + + return *m_pstrRep; +} + + + +CValue* CIntValue::GetReplica() { + CIntValue* replica = new CIntValue(*this); + CValue::AddDataToReplica(replica); + replica->m_pstrRep = NULL; + + return replica; +} + + + +void CIntValue::SetValue(CValue* newval) +{ + m_int = (int)newval->GetNumber(); + SetModified(true); +} + + + +PyObject* CIntValue::ConvertValueToPython() +{ + return PyInt_FromLong(m_int); +}
\ No newline at end of file diff --git a/source/gameengine/Expressions/IntValue.h b/source/gameengine/Expressions/IntValue.h new file mode 100644 index 00000000000..8174c863895 --- /dev/null +++ b/source/gameengine/Expressions/IntValue.h @@ -0,0 +1,60 @@ +/* + * IntValue.h: interface for the CIntValue class. + * $Id$ + * 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. + * + */ +#if !defined _INTVALUE_H +#define _INTVALUE_H + + +#include "Value.h" + + +class CIntValue : public CPropValue +{ + //PLUGIN_DECLARE_SERIAL (CIntValue,CValue) + +public: + virtual const STR_String& GetText(); + virtual float GetNumber(); + + int GetInt(); + CIntValue(); + CIntValue(int innie); + CIntValue(int innie, + STR_String name, + AllocationTYPE alloctype=CValue::HEAPVALUE); + + virtual CValue* Calc(VALUE_OPERATOR op, + CValue *val); + + virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, + VALUE_OPERATOR op, + CValue *val); + + virtual void SetValue(CValue* newval); + + void Configure(CValue* menuvalue); + void AddConfigurationData(CValue* menuvalue); + virtual CValue* GetReplica(); + virtual PyObject* ConvertValueToPython(); + +protected: + virtual ~CIntValue(); + +private: + int m_int; + STR_String* m_pstrRep; + +}; + +#endif // !defined _INTVALUE_H diff --git a/source/gameengine/Expressions/KX_HashedPtr.cpp b/source/gameengine/Expressions/KX_HashedPtr.cpp new file mode 100644 index 00000000000..7d573ebc37d --- /dev/null +++ b/source/gameengine/Expressions/KX_HashedPtr.cpp @@ -0,0 +1,58 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#include "KX_HashedPtr.h" + +unsigned int KX_Hash(unsigned int inDWord) +{ + unsigned int key = inDWord; + key += ~(key << 16); + key ^= (key >> 5); + key += (key << 3); + key ^= (key >> 13); + key += ~(key << 9); + key ^= (key >> 17); + return key; +}; + + + +CHashedPtr::CHashedPtr(void* val) : m_valptr(val) +{ +} + + + +unsigned int CHashedPtr::hash() const +{ + return KX_Hash((unsigned int) m_valptr); +} diff --git a/source/gameengine/Expressions/KX_HashedPtr.h b/source/gameengine/Expressions/KX_HashedPtr.h new file mode 100644 index 00000000000..eccd23991bc --- /dev/null +++ b/source/gameengine/Expressions/KX_HashedPtr.h @@ -0,0 +1,53 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef __KX_HASHEDPTR +#define __KX_HASHEDPTR + +unsigned int KX_Hash(unsigned int inDWord); + + +class CHashedPtr +{ + void* m_valptr; + +public: + CHashedPtr(void* val); + + unsigned int hash() const; + + inline friend bool operator ==( const CHashedPtr & rhs,const CHashedPtr & lhs) + { + return rhs.m_valptr == lhs.m_valptr; + } +}; + +#endif //__KX_HASHEDPTR diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp new file mode 100644 index 00000000000..25723350f36 --- /dev/null +++ b/source/gameengine/Expressions/ListValue.cpp @@ -0,0 +1,536 @@ +// ListValue.cpp: implementation of the CListValue 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. + * + */ + + +#include "ListValue.h" +#include "StringValue.h" +#include "VoidValue.h" +#include <algorithm> + +int listvalue_bufferlen(PyObject* list) +{ + return ( ((CListValue*)list)->GetCount()); +} + + + +PyObject* listvalue_buffer_item(PyObject* list,int index) +{ + if (index >= 0 && index < ((CListValue*) list)->GetCount()) + { + PyObject* pyobj = ((CListValue*) list)->GetValue(index)->ConvertValueToPython(); + if (pyobj) + return pyobj; + else + return ((CListValue*) list)->GetValue(index)->AddRef(); + + } + Py_Error(PyExc_IndexError, "Python ListIndex out of range"); + return NULL; +} + + + +/* just slice it into a python list... */ +PyObject* listvalue_buffer_slice(PyObject* list,int ilow, int ihigh) +{ + int i, j; + PyListObject *newlist; + + if (ilow < 0) ilow = 0; + + int n = ((CListValue*) list)->GetCount(); + + if (ihigh >= n) + ihigh = n; + if (ihigh < ilow) + ihigh = ilow; + + newlist = (PyListObject *) PyList_New(ihigh - ilow); + if (!newlist) + return NULL; + + for (i = ilow, j = 0; i < ihigh; i++, j++) + { + PyObject* pyobj = ((CListValue*) list)->GetValue(i)->ConvertValueToPython(); + if (!pyobj) + pyobj = ((CListValue*) list)->GetValue(i)->AddRef(); + newlist->ob_item[j] = pyobj; + } + return (PyObject *) newlist; +} + + + +static PyObject * +listvalue_buffer_concat(PyObject * self, PyObject * other) +{ + // for now, we support CListValue concatenated with items + // and CListValue concatenated to Python Lists + // and CListValue concatenated with another CListValue + + CListValue* listval = (CListValue*) self; + listval->AddRef(); + if (other->ob_type == &PyList_Type) + { + bool error = false; + + int i; + int numitems = PyList_Size(other); + for (i=0;i<numitems;i++) + { + PyObject* listitem = PyList_GetItem(other,i); + CValue* listitemval = listval->ConvertPythonToValue(listitem); + if (listitemval) + { + listval->Add(listitemval); + } else + { + error = true; + } + } + + if (error) + Py_Error(PyExc_SystemError, "Python Error: couldn't add one or more items to a list"); + + + } else + { + if (other->ob_type == &CListValue::Type) + { + // add items from otherlist to this list + CListValue* otherval = (CListValue*) other; + + + for (int i=0;i<otherval->GetCount();i++) + { + otherval->Add(listval->GetValue(i)->AddRef()); + } + } + else + { + CValue* objval = listval->ConvertPythonToValue(other); + if (objval) + { + listval->Add(objval); + } else + { + Py_Error(PyExc_SystemError, "Python Error: couldn't add item to a list"); + // bad luck + } + } + } + + return self; +} + + + +static PySequenceMethods listvalue_as_sequence = { + (inquiry)listvalue_bufferlen,//(inquiry)buffer_length, /*sq_length*/ + (binaryfunc)listvalue_buffer_concat, /*sq_concat*/ + 0,//(intargfunc)buffer_repeat, /*sq_repeat*/ + (intargfunc)listvalue_buffer_item, /*sq_item*/ + (intintargfunc)listvalue_buffer_slice, /*sq_slice*/ + 0,//(intobjargproc)buffer_ass_item, /*sq_ass_item*/ + 0,//(intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/ +}; + + + +/* Is this one used ? */ +static PyMappingMethods instance_as_mapping = { + (inquiry)listvalue_bufferlen, /*mp_length*/ + 0,//(binaryfunc)instance_subscript, /*mp_subscript*/ + 0,//(objobjargproc)instance_ass_subscript, /*mp_ass_subscript*/ +}; + + + +PyTypeObject CListValue::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "CListValue", /*tp_name*/ + sizeof(CListValue), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + PyDestructor, /*tp_dealloc*/ + 0, /*tp_print*/ + __getattr, /*tp_getattr*/ + __setattr, /*tp_setattr*/ + 0, /*tp_compare*/ + __repr, /*tp_repr*/ + 0, /*tp_as_number*/ + &listvalue_as_sequence, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call */ +}; + + + +PyParentObject CListValue::Parents[] = { + &CListValue::Type, + &CValue::Type, + NULL +}; + + + + +PyMethodDef CListValue::Methods[] = { + {"append", (PyCFunction)CListValue::sPyappend,METH_VARARGS}, + {"reverse", (PyCFunction)CListValue::sPyreverse,METH_VARARGS}, + {"index", (PyCFunction)CListValue::sPyindex,METH_VARARGS}, + {"count", (PyCFunction)CListValue::sPycount,METH_VARARGS}, + + {NULL,NULL} //Sentinel +}; + + + +PyObject* CListValue::_getattr(char* attr) { + _getattr_up(CValue); +} + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CListValue::CListValue(PyTypeObject *T ) +: CPropValue(T) +{ + m_bReleaseContents=true; +} + + + +CListValue::~CListValue() +{ + + if (m_bReleaseContents) { + for (int i=0;i<m_pValueArray.size();i++) { + m_pValueArray[i]->Release(); + } + } +} + + +static STR_String gstrListRep=STR_String("List"); + +const STR_String & CListValue::GetText() +{ + gstrListRep = "["; + STR_String commastr = ""; + + for (int i=0;i<GetCount();i++) + { + gstrListRep += commastr; + gstrListRep += GetValue(i)->GetText(); + commastr = ","; + } + gstrListRep += "]"; + + return gstrListRep; +} + + + +CValue* CListValue::GetReplica() { + CListValue* replica = new CListValue(*this); + + CValue::AddDataToReplica(replica); + + replica->m_bReleaseContents=true; // for copy, complete array is copied for now... + // copy all values + int numelements = m_pValueArray.size(); + int i=0; + replica->m_pValueArray.resize(numelements); + for (i=0;i<m_pValueArray.size();i++) + replica->m_pValueArray[i] = m_pValueArray[i]->GetReplica(); + + + return replica; +}; + + + +void CListValue::SetValue(int i, CValue *val) +{ + assertd(i < m_pValueArray.size()); + m_pValueArray[i]=val; +} + + + +void CListValue::Resize(int num) +{ + m_pValueArray.resize(num); +} + + + +void CListValue::Remove(int i) +{ + assertd(i<m_pValueArray.size()); + m_pValueArray.erase(m_pValueArray.begin()+i); +} + + + +void CListValue::ReleaseAndRemoveAll() +{ + for (int i=0;i<m_pValueArray.size();i++) + m_pValueArray[i]->Release(); + m_pValueArray.clear();//.Clear(); +} + + + +CValue* CListValue::FindValue(const STR_String & name) +{ + CValue* resultval = NULL; + int i=0; + + while (!resultval && i < GetCount()) + { + CValue* myval = GetValue(i); + + if (myval->GetName() == name) + resultval = GetValue(i)->AddRef(); // add referencecount + else + i++; + + } + return resultval; +} + + + +bool CListValue::SearchValue(CValue *val) +{ + for (int i=0;i<GetCount();i++) + if (val == GetValue(i)) + return true; + return false; +} + + + +void CListValue::SetReleaseOnDestruct(bool bReleaseContents) +{ + m_bReleaseContents = bReleaseContents; +} + + + +bool CListValue::RemoveValue(CValue *val) +{ + bool result=false; + + for (int i=GetCount()-1;i>=0;i--) + if (val == GetValue(i)) + { + Remove(i); + result=true; + } + return result; +} + + + +void CListValue::MergeList(CListValue *otherlist) +{ + + int numelements = this->GetCount(); + int numotherelements = otherlist->GetCount(); + + + Resize(numelements+numotherelements); + + for (int i=0;i<numotherelements;i++) + { + SetValue(i+numelements,otherlist->GetValue(i)->AddRef()); + } + +} + + + +PyObject* CListValue::Pyappend(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + + PyObject* pyobj = NULL; + if (PyArg_ParseTuple(args,"O",&pyobj)) + { + return listvalue_buffer_concat(self,pyobj); + } + else + { + return NULL; + } + + +} + + + +PyObject* CListValue::Pyreverse(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + std::reverse(m_pValueArray.begin(),m_pValueArray.end()); + + Py_Return; + +} + + + +bool CListValue::CheckEqual(CValue* first,CValue* second) +{ + bool result = false; + + CValue* eqval = ((CValue*)first)->Calc(VALUE_EQL_OPERATOR,(CValue*)second); + STR_String txt = eqval->GetText(); + eqval->Release(); + if (txt=="TRUE") + { + result = true; + } + return result; + +} + + + +PyObject* CListValue::Pyindex(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + PyObject* result = NULL; + + PyObject* pyobj = NULL; + if (PyArg_ParseTuple(args,"O",&pyobj)) + { + + CValue* checkobj = ConvertPythonToValue(pyobj); + int numelem = GetCount(); + for (int i=0;i<numelem;i++) + { + CValue* elem = GetValue(i); + if (CheckEqual(checkobj,elem)) + { + result = PyInt_FromLong(i); + break; + } + } + checkobj->Release(); + } + + return result; + +} + + + +PyObject* CListValue::Pycount(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + + int numfound = 0; + + PyObject* pyobj = NULL; + if (PyArg_ParseTuple(args,"O",&pyobj)) + { + CValue* checkobj = ConvertPythonToValue(pyobj); + int numelem = GetCount(); + for (int i=0;i<numelem;i++) + { + CValue* elem = GetValue(i); + if (CheckEqual(checkobj,elem)) + { + numfound ++; + } + } + checkobj->Release(); + } + + return PyInt_FromLong(numfound); +} + + + +/* --------------------------------------------------------------------- + * Some stuff taken from the header + * --------------------------------------------------------------------- */ +CValue* CListValue::Calc(VALUE_OPERATOR op,CValue *val) +{ + assert(false); // todo: implement me! + return NULL; +} + + + +CValue* CListValue::CalcFinal(VALUE_DATA_TYPE dtype, + VALUE_OPERATOR op, + CValue* val) +{ + assert(false); // todo: implement me! + return NULL; +} + + + +void CListValue::Add(CValue* value) +{ + m_pValueArray.push_back(value); +} + + + +float CListValue::GetNumber() +{ + return -1; +} + + + +void CListValue::SetModified(bool bModified) +{ + CValue::SetModified(bModified); + int numels = GetCount(); + + for (int i=0;i<numels;i++) + GetValue(i)->SetModified(bModified); +} + + + +bool CListValue::IsModified() +{ + bool bmod = CValue::IsModified(); //normal own flag + int numels = GetCount(); + + for (int i=0;i<numels;i++) + bmod = bmod || GetValue(i)->IsModified(); + + return bmod; +}
\ No newline at end of file diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h new file mode 100644 index 00000000000..fce4e9da8c2 --- /dev/null +++ b/source/gameengine/Expressions/ListValue.h @@ -0,0 +1,77 @@ +/* + * ListValue.h: interface for the CListValue class. + * $Id$ + * 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. + * + */ + +#if !defined _LISTVALUE_H +#define _LISTVALUE_H + + +#include "Value.h" + +class CListValue : public CPropValue +{ + Py_Header; + //PLUGIN_DECLARE_SERIAL (CListValue,CValue) + +public: + CListValue(PyTypeObject *T = &Type); + virtual ~CListValue(); + + void AddConfigurationData(CValue* menuvalue); + void Configure(CValue* menuvalue); + void Add(CValue* value); + + /** @attention not implemented yet :( */ + virtual CValue* Calc(VALUE_OPERATOR op,CValue *val); + virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, + VALUE_OPERATOR op, + CValue* val); + virtual float GetNumber(); + virtual CValue* GetReplica(); + +public: + void MergeList(CListValue* otherlist); + bool RemoveValue(CValue* val); + void SetReleaseOnDestruct(bool bReleaseContents); + bool SearchValue(CValue* val); + + CValue* FindValue(const STR_String & name); + + void ReleaseAndRemoveAll(); + virtual void SetModified(bool bModified); + virtual inline bool IsModified(); + void Remove(int i); + void Resize(int num); + void SetValue(int i,CValue* val); + CValue* GetValue(int i){ assertd(i < m_pValueArray.size()); return m_pValueArray[i];} + int GetCount() { return m_pValueArray.size();}; + virtual const STR_String & GetText(); + + bool CheckEqual(CValue* first,CValue* second); + + virtual PyObject* _getattr(char *attr); + + KX_PYMETHOD(CListValue,append); + KX_PYMETHOD(CListValue,reverse); + KX_PYMETHOD(CListValue,index); + KX_PYMETHOD(CListValue,count); + + +private: + + std::vector<CValue*> m_pValueArray; + bool m_bReleaseContents; +}; + +#endif // !defined _LISTVALUE_H diff --git a/source/gameengine/Expressions/Makefile b/source/gameengine/Expressions/Makefile new file mode 100644 index 00000000000..9199698d3e9 --- /dev/null +++ b/source/gameengine/Expressions/Makefile @@ -0,0 +1,45 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# + +LIBNAME = expression +DIR = $(OCGDIR)/gameengine/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(LEVEL_1_CPP_WARNINGS) + +CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I../../kernel/gen_system +CPPFLAGS += -I../Ketsji + diff --git a/source/gameengine/Expressions/Operator1Expr.cpp b/source/gameengine/Expressions/Operator1Expr.cpp new file mode 100644 index 00000000000..91a3a02aabe --- /dev/null +++ b/source/gameengine/Expressions/Operator1Expr.cpp @@ -0,0 +1,148 @@ +// Operator1Expr.cpp: implementation of the COperator1Expr 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. + * + */ + +#include "Operator1Expr.h" +//#include "FactoryManager.h" +#include "EmptyValue.h" +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +COperator1Expr::COperator1Expr() +/* +pre: +effect: constucts an empty COperator1Expr +*/ +{ + m_lhs = NULL; +} + +COperator1Expr::COperator1Expr(VALUE_OPERATOR op, CExpression * lhs) +/* +pre: +effect: constucts a COperator1Expr with op and lhs in it +*/ +{ + m_lhs = lhs; + m_op = op; +} + +COperator1Expr::~COperator1Expr() +/* +pre: +effect: deletes the object +*/ +{ + if (m_lhs) m_lhs->Release(); +} + +CValue * COperator1Expr::Calculate() +/* +pre: +ret: a new object containing the result of applying the operator m_op to the + value of m_lhs +*/ +{ + CValue *ret; + CValue *temp = m_lhs->Calculate(); + CValue* empty = new CEmptyValue(); + ret = empty->Calc(m_op, temp); + empty->Release(); + temp->Release(); + + return ret; +} + +/* +bool COperator1Expr::IsInside(float x, float y, float z,bool bBorderInclude) +{ + + bool result = true; + switch (m_op) + { + + case VALUE_ADD_OPERATOR: + { + + if (m_lhs) + { + result = result || m_lhs->IsInside(x,y,z,bBorderInclude); + } + break; + } + case VALUE_SUB_OPERATOR: + { + result = true; + if (m_lhs) + { + result = result && (!m_lhs->IsInside(x,y,z,bBorderInclude)); + } + break; + } + } + return result; +} + +*/ +bool COperator1Expr::NeedsRecalculated() { + + return m_lhs->NeedsRecalculated(); + +} + +CExpression* COperator1Expr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) { + + CExpression* newlhs = m_lhs->CheckLink(brokenlinks); + + if (newlhs) + { + if (newlhs==m_lhs) { + // not changed + } else { + // changed + //numchanges++; + newlhs->AddRef(); + + //m_lhs->Release(); + brokenlinks.push_back(new CBrokenLinkInfo(&m_lhs,m_lhs)); + + m_lhs = newlhs; + } + return this; + } else { + //numchanges++; + AddRef(); + + return Release(); + } + +} + +void COperator1Expr::BroadcastOperators(VALUE_OPERATOR op) +{ + if (m_lhs) + m_lhs->BroadcastOperators(m_op); +} + + + + +bool COperator1Expr::MergeExpression(CExpression *otherexpr) +{ + if (m_lhs) + return m_lhs->MergeExpression(otherexpr); + + assertd(false); // should not get here, expression is not compatible for merge + return false; +} diff --git a/source/gameengine/Expressions/Operator1Expr.h b/source/gameengine/Expressions/Operator1Expr.h new file mode 100644 index 00000000000..9362c568dc9 --- /dev/null +++ b/source/gameengine/Expressions/Operator1Expr.h @@ -0,0 +1,53 @@ +/* + * Operator1Expr.h: interface for the COperator1Expr class. + * $Id$ + * 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. + * + */ + +#if !defined(AFX_OPERATOR1EXPR_H__A1653901_BF41_11D1_A51C_00A02472FC58__INCLUDED_) +#define AFX_OPERATOR1EXPR_H__A1653901_BF41_11D1_A51C_00A02472FC58__INCLUDED_ + + + +#include "Expression.h" + +class COperator1Expr : public CExpression +{ + //PLUGIN_DECLARE_SERIAL_EXPRESSION (COperator1Expr,CExpression) + + + +public: + virtual bool MergeExpression(CExpression* otherexpr); + void virtual BroadcastOperators(VALUE_OPERATOR op); + + virtual unsigned char GetExpressionID() { return COPERATOR1EXPRESSIONID;}; + CExpression* CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks); + //virtual bool IsInside(float x,float y,float z,bool bBorderInclude = true); + virtual bool NeedsRecalculated(); + void ClearModified() { + if (m_lhs) + m_lhs->ClearModified(); + } + virtual CValue* Calculate(); + COperator1Expr(VALUE_OPERATOR op, CExpression *lhs); + COperator1Expr(); + virtual ~COperator1Expr(); + + + +private: + VALUE_OPERATOR m_op; + CExpression * m_lhs; +}; + +#endif // !defined(AFX_OPERATOR1EXPR_H__A1653901_BF41_11D1_A51C_00A02472FC58__INCLUDED_) 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); +} diff --git a/source/gameengine/Expressions/Operator2Expr.h b/source/gameengine/Expressions/Operator2Expr.h new file mode 100644 index 00000000000..7e1dc3ed250 --- /dev/null +++ b/source/gameengine/Expressions/Operator2Expr.h @@ -0,0 +1,59 @@ +/* + * Operator2Expr.h: interface for the COperator2Expr class. + * $Id$ + * 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. + * + */ + +#if !defined _OPERATOR2EXPR_H +#define _OPERATOR2EXPR_H + + +#include "Expression.h" +#include "Value.h" // Added by ClassView + + +class COperator2Expr : public CExpression +{ + //PLUGIN_DECLARE_SERIAL_EXPRESSION (COperator2Expr,CExpression) + +public: + virtual bool MergeExpression(CExpression* otherexpr); + virtual unsigned char GetExpressionID() { return COPERATOR2EXPRESSIONID;}; + virtual void BroadcastOperators(VALUE_OPERATOR op); + CExpression* CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks); + //virtual bool IsInside(float x,float y,float z,bool bBorderInclude=true); + //virtual bool IsLeftInside(float x,float y,float z,bool bBorderInclude); + //virtual bool IsRightInside(float x,float y,float z,bool bBorderInclude); + bool NeedsRecalculated(); + void ClearModified() { + if (m_lhs) + m_lhs->ClearModified(); + if (m_rhs) + m_rhs->ClearModified(); + } + virtual CValue* Calculate(); + COperator2Expr(VALUE_OPERATOR op, CExpression *lhs, CExpression *rhs); + COperator2Expr(); + virtual ~COperator2Expr(); + + +protected: + CExpression * m_rhs; + CExpression * m_lhs; + CValue* m_cached_calculate; // cached result + +private: + VALUE_OPERATOR m_op; + +}; + +#endif // !defined _OPERATOR2EXPR_H diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp new file mode 100644 index 00000000000..7b93b1d4daa --- /dev/null +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -0,0 +1,157 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NO_EXP_PYTHON_EMBEDDING + +/*------------------------------ + * PyObjectPlus cpp + * + * C++ library routines for Crawl 3.2 + * + * Derived from work by + * David Redish + * graduate student + * Computer Science Department + * Carnegie Mellon University (CMU) + * Center for the Neural Basis of Cognition (CNBC) + * http://www.python.org/doc/PyCPP.html + * +------------------------------*/ +#include <assert.h> +#include "stdlib.h" +#include "PyObjectPlus.h" +#include "STR_String.h" +/*------------------------------ + * PyObjectPlus Type -- Every class, even the abstract one should have a Type +------------------------------*/ + +PyTypeObject PyObjectPlus::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "PyObjectPlus", /*tp_name*/ + sizeof(PyObjectPlus), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + PyDestructor, /*tp_dealloc*/ + 0, /*tp_print*/ + __getattr, /*tp_getattr*/ + __setattr, /*tp_setattr*/ + 0, /*tp_compare*/ + __repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call */ +}; + +PyObjectPlus::PyObjectPlus(PyTypeObject *T) // constructor +{ + assert(T != NULL); + this->ob_type = T; + _Py_NewReference(this); +}; + +/*------------------------------ + * PyObjectPlus Methods -- Every class, even the abstract one should have a Methods +------------------------------*/ +PyMethodDef PyObjectPlus::Methods[] = { + {"isA", (PyCFunction) sPy_isA, Py_NEWARGS}, + {NULL, NULL} /* Sentinel */ +}; + +/*------------------------------ + * PyObjectPlus Parents -- Every class, even the abstract one should have parents +------------------------------*/ +PyParentObject PyObjectPlus::Parents[] = {&PyObjectPlus::Type, NULL}; + +/*------------------------------ + * PyObjectPlus attributes -- attributes +------------------------------*/ +PyObject *PyObjectPlus::_getattr(char *attr) +{ + //if (streq(attr, "type")) + // return Py_BuildValue("s", (*(GetParents()))->tp_name); + + return Py_FindMethod(Methods, this, attr); +} + +int PyObjectPlus::_setattr(char *attr, PyObject *value) +{ + //return PyObject::_setattr(attr,value); + //cerr << "Unknown attribute" << endl; + return 1; +} + +/*------------------------------ + * PyObjectPlus repr -- representations +------------------------------*/ +PyObject *PyObjectPlus::_repr(void) +{ + Py_Error(PyExc_SystemError, "Representation not overridden by object."); +} + +/*------------------------------ + * PyObjectPlus isA -- the isA functions +------------------------------*/ +bool PyObjectPlus::isA(PyTypeObject *T) // if called with a Type, use "typename" +{ + return isA(T->tp_name); +} + + +bool PyObjectPlus::isA(const char *mytypename) // check typename of each parent +{ + int i; + PyParentObject P; + PyParentObject *Ps = GetParents(); + + for (P = Ps[i=0]; P != NULL; P = Ps[i++]) + { + if (STR_String(P->tp_name) == STR_String(mytypename) ) + return true; + } + + return false; +} + +PyObject *PyObjectPlus::Py_isA(PyObject *args) // Python wrapper for isA +{ + char *mytypename; + Py_Try(PyArg_ParseTuple(args, "s", &mytypename)); + if(isA(mytypename)) + {Py_INCREF(Py_True); return Py_True;} + else + {Py_INCREF(Py_False); return Py_False;}; +} + +#endif //NO_EXP_PYTHON_EMBEDDING + diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h new file mode 100644 index 00000000000..e88ea2b255a --- /dev/null +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -0,0 +1,135 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef NO_EXP_PYTHON_EMBEDDING + +#ifndef _adr_py_lib_h_ // only process once, +#define _adr_py_lib_h_ // even if multiply included + +#ifndef __cplusplus // c++ only +#error Must be compiled with C++ +#endif + +#include "KX_Python.h" + +/*------------------------------ + * Python defines +------------------------------*/ + + // some basic python macros +#define Py_NEWARGS 1 +#define Py_Return Py_INCREF(Py_None); return Py_None; + +#define Py_Error(E, M) {PyErr_SetString(E, M); return NULL;} +#define Py_Try(F) {if (!(F)) return NULL;} +#define Py_Assert(A,E,M) {if (!(A)) {PyErr_SetString(E, M); return NULL;}} + +inline void Py_Fatal(char *M) { + //cout << M << endl; + exit(-1); +}; + + // This must be the first line of each + // PyC++ class +#define Py_Header \ + public: \ + static PyTypeObject Type; \ + static PyMethodDef Methods[]; \ + static PyParentObject Parents[]; \ + virtual PyTypeObject *GetType(void) {return &Type;}; \ + virtual PyParentObject *GetParents(void) {return Parents;} + + // This defines the _getattr_up macro + // which allows attribute and method calls + // to be properly passed up the hierarchy. +#define _getattr_up(Parent) \ + PyObject *rvalue = Py_FindMethod(Methods, this, attr); \ + if (rvalue == NULL) \ + { \ + PyErr_Clear(); \ + return Parent::_getattr(attr); \ + } \ + else \ + return rvalue + + +/*------------------------------ + * PyObjectPlus +------------------------------*/ +typedef PyTypeObject * PyParentObject; // Define the PyParent Object + +class PyObjectPlus : public PyObject { // The PyObjectPlus abstract class + + Py_Header; // Always start with Py_Header + + public: + PyObjectPlus(PyTypeObject *T); + + virtual ~PyObjectPlus() {}; // destructor + static void PyDestructor(PyObject *P) // python wrapper + { + delete ((PyObjectPlus *) P); + }; + + //void INCREF(void) { +// Py_INCREF(this); +// }; // incref method + //void DECREF(void) { +// Py_DECREF(this); +// }; // decref method + + virtual PyObject *_getattr(char *attr); // _getattr method + static PyObject *__getattr(PyObject * PyObj, char *attr) // This should be the entry in Type. + { return ((PyObjectPlus*) PyObj)->_getattr(attr); }; + + virtual int _setattr(char *attr, PyObject *value); // _setattr method + static int __setattr(PyObject *PyObj, // This should be the entry in Type. + char *attr, + PyObject *value) + { return ((PyObjectPlus*) PyObj)->_setattr(attr, value); }; + + virtual PyObject *_repr(void); // _repr method + static PyObject *__repr(PyObject *PyObj) // This should be the entry in Type. + { return ((PyObjectPlus*) PyObj)->_repr(); }; + + + // isA methods + bool isA(PyTypeObject *T); + bool isA(const char *mytypename); + PyObject *Py_isA(PyObject *args); + static PyObject *sPy_isA(PyObject *self, PyObject *args, PyObject *kwd) + {return ((PyObjectPlus*)self)->Py_isA(args);}; +}; + +#endif // _adr_py_lib_h_ + +#endif //NO_EXP_PYTHON_EMBEDDING + diff --git a/source/gameengine/Expressions/StringValue.cpp b/source/gameengine/Expressions/StringValue.cpp new file mode 100644 index 00000000000..7bdb841e1e4 --- /dev/null +++ b/source/gameengine/Expressions/StringValue.cpp @@ -0,0 +1,139 @@ +// StringValue.cpp: implementation of the CStringValue 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. + * + */ + + +#include "StringValue.h" +#include "BoolValue.h" +#include "ErrorValue.h" +#include "VoidValue.h" +//#include "FactoryManager.h" + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CStringValue::CStringValue() +/* +pre: false +effect: constructs a new CStringValue +*/ +{ + m_strString = "[Illegal String constructor call]"; +} + +CStringValue::CStringValue(STR_String txt,STR_String name,AllocationTYPE alloctype) +/* +pre: +effect: constructs a new CStringValue containing text txt +*/ +{ + m_strString = txt; + SetName(name); + + if (alloctype==CValue::STACKVALUE) + { + CValue::DisableRefCount(); + + } + + +} + + +CValue* CStringValue::Calc(VALUE_OPERATOR op, CValue *val) +/* +pre: +ret: a new object containing the result of applying operator op to this +object and val +*/ +{ + //return val->CalrcString(op, this); + return val->CalcFinal(VALUE_STRING_TYPE, op, this); +} + +CValue* CStringValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) +/* +pre: the type of val is dtype +ret: a new object containing the result of applying operator op to val and +this object +*/ +{ + CValue *ret; + + if (op == VALUE_ADD_OPERATOR) { + if (dtype == VALUE_ERROR_TYPE) + ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); + else + ret = new CStringValue(val->GetText() + GetText(),""); + } else { + + if (dtype == VALUE_STRING_TYPE || dtype == VALUE_EMPTY_TYPE) { + switch(op) { + case VALUE_EQL_OPERATOR: + ret = new CBoolValue(val->GetText() == GetText()); + break; + case VALUE_NEQ_OPERATOR: + ret = new CBoolValue(val->GetText() != GetText()); + break; + case VALUE_GRE_OPERATOR: + ret = new CBoolValue(val->GetText() > GetText()); + break; + case VALUE_LES_OPERATOR: + ret = new CBoolValue(val->GetText() < GetText()); + break; + case VALUE_GEQ_OPERATOR: + ret = new CBoolValue(val->GetText() >= GetText()); + break; + case VALUE_LEQ_OPERATOR: + ret = new CBoolValue(val->GetText() <= GetText()); + break; + default: + ret = new CErrorValue(val->GetText() + op2str(op) + "[operator not allowed on strings]"); + break; + } + } else { + ret = new CErrorValue(val->GetText() + op2str(op) + "[operator not allowed on strings]"); + } + } + return ret; +} + + + +float CStringValue::GetNumber() +{ + return -1; +} + + + +const STR_String & CStringValue::GetText() +{ + return m_strString; +} + +bool CStringValue::IsEqual(const STR_String & other) +{ + return (m_strString == other); +} + +CValue* CStringValue::GetReplica() +{ + CStringValue* replica = new CStringValue(*this); + CValue::AddDataToReplica(replica); + return replica; +}; + + diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/StringValue.h new file mode 100644 index 00000000000..6f90536a98b --- /dev/null +++ b/source/gameengine/Expressions/StringValue.h @@ -0,0 +1,51 @@ +/* + * StringValue.h: interface for the CStringValue class. + * $Id$ + * 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. + * + */ + +#ifndef __STRINGVALUE_H__ +#define __STRINGVALUE_H__ + +#include "Value.h" + +class CStringValue : public CPropValue +{ + + + //PLUGIN_DECLARE_SERIAL(CStringValue,CValue) +public: + /// Construction / destruction + CStringValue(); + CStringValue (STR_String txt, STR_String name , AllocationTYPE alloctype = CValue::HEAPVALUE); + + virtual ~CStringValue() { + }; + /// CValue implementation + virtual bool IsEqual(const STR_String & other); + virtual const STR_String & GetText(); + virtual float GetNumber(); + + virtual CValue* Calc(VALUE_OPERATOR op, CValue *val); + virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); + virtual void SetValue(CValue* newval) { m_strString = newval->GetText(); SetModified(true); }; + virtual CValue* GetReplica(); + virtual PyObject* ConvertValueToPython() { + return PyString_FromString(m_strString.Ptr()); + } + +private: + // data member + STR_String m_strString; +}; + +#endif diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp new file mode 100644 index 00000000000..e2a7189fb02 --- /dev/null +++ b/source/gameengine/Expressions/Value.cpp @@ -0,0 +1,767 @@ +// Value.cpp: implementation of the CValue class. +// developed at Eindhoven University of Technology, 1997 +// by the OOPS team +////////////////////////////////////////////////////////////////////// +/* + * 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. + * + */ + + +#include "Value.h" +#include "FloatValue.h" +#include "IntValue.h" +#include "VectorValue.h" +#include "VoidValue.h" +#include "StringValue.h" +#include "ErrorValue.h" +#include "ListValue.h" + +//#include "FactoryManager.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +double CValue::m_sZeroVec[3] = {0.0,0.0,0.0}; + +#ifndef NO_EXP_PYTHON_EMBEDDING + +PyObject* cvalue_add(PyObject*v, PyObject*w) +{ + return ((CValue*)v)->Calc(VALUE_ADD_OPERATOR,(CValue*)w); +} +PyObject* cvalue_sub(PyObject*v, PyObject*w) +{ + return ((CValue*)v)->Calc(VALUE_SUB_OPERATOR,(CValue*)w); +} +PyObject* cvalue_mul(PyObject*v, PyObject*w) +{ + return ((CValue*)v)->Calc(VALUE_MUL_OPERATOR,(CValue*)w); +} +PyObject* cvalue_div(PyObject*v, PyObject*w) +{ + return ((CValue*)v)->Calc(VALUE_DIV_OPERATOR,(CValue*)w); +} +PyObject* cvalue_neg(PyObject*v) +{ + return ((CValue*)v)->Calc(VALUE_NEG_OPERATOR,(CValue*)v); +} +PyObject* cvalue_pos(PyObject*v) +{ + return ((CValue*)v)->Calc(VALUE_POS_OPERATOR,(CValue*)v); +} + + +int MyPyCompare (PyObject* v,PyObject* w) +{ + CValue* eqval = ((CValue*)v)->Calc(VALUE_EQL_OPERATOR,(CValue*)w); + STR_String txt = eqval->GetText(); + eqval->Release(); + if (txt=="TRUE") + return 0; + CValue* lessval = ((CValue*)v)->Calc(VALUE_LES_OPERATOR,(CValue*)w); + txt = lessval->GetText(); + lessval->Release(); + if (txt=="TRUE") + return -1; + + return 1; +} + + +int cvalue_coerce(PyObject** pv,PyObject** pw) +{ + if (PyInt_Check(*pw)) { + double db = (double)PyInt_AsLong(*pw); + *pw = new CIntValue(db); + Py_INCREF(*pv); + return 0; + } + else if (PyLong_Check(*pw)) { + double db = PyLong_AsDouble(*pw); + *pw = new CFloatValue(db); + Py_INCREF(*pv); + return 0; + } + else if (PyFloat_Check(*pw)) { + double db = PyFloat_AsDouble(*pw); + *pw = new CFloatValue(db); + Py_INCREF(*pv); + return 0; + } else if (PyString_Check(*pw)) { + const STR_String str = PyString_AsString(*pw); + *pw = new CStringValue(str,""); + Py_INCREF(*pv); + return 0; + } + return 1; /* Can't do it */ + +} +static PyNumberMethods cvalue_as_number = { + (binaryfunc)cvalue_add, /*nb_add*/ + (binaryfunc)cvalue_sub, /*nb_subtract*/ + (binaryfunc)cvalue_mul, /*nb_multiply*/ + (binaryfunc)cvalue_div, /*nb_divide*/ + 0,//(binaryfunc)cvalue_remainder, /*nb_remainder*/ + 0,//(binaryfunc)cvalue_divmod, /*nb_divmod*/ + 0,//0,//0,//0,//(ternaryfunc)cvalue_pow, /*nb_power*/ + (unaryfunc)cvalue_neg, /*nb_negative*/ + 0,//(unaryfunc)cvalue_pos, /*nb_positive*/ + 0,//(unaryfunc)cvalue_abs, /*nb_absolute*/ + 0,//(inquiry)cvalue_nonzero, /*nb_nonzero*/ + 0, /*nb_invert*/ + 0, /*nb_lshift*/ + 0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ + (coercion)cvalue_coerce, /*nb_coerce*/ + 0,//(unaryfunc)cvalue_int, /*nb_int*/ + 0,//(unaryfunc)cvalue_long, /*nb_long*/ + 0,//(unaryfunc)cvalue_float, /*nb_float*/ + 0, /*nb_oct*/ + 0, /*nb_hex*/ +}; + + +PyTypeObject CValue::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "CValue", + sizeof(CValue), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + &MyPyCompare, + __repr, + &cvalue_as_number, + 0, + 0, + 0, + 0 +}; + +PyParentObject CValue::Parents[] = { + &CValue::Type, + NULL +}; + +PyMethodDef CValue::Methods[] = { +// { "printHello", (PyCFunction) CValue::sPyPrintHello, Py_NEWARGS}, + { "getName", (PyCFunction) CValue::sPyGetName, Py_NEWARGS}, + {NULL,NULL} //Sentinel +}; + +PyObject* CValue::PyGetName(PyObject* self,PyObject* args,PyObject* kwds) +{ + PyObject* pyname = PyString_FromString(this->GetName()); + return pyname; +} + + + +CValue::CValue(PyTypeObject *T) + : PyObjectPlus(T), +#else +CValue::CValue() +: +#endif //NO_EXP_PYTHON_EMBEDDING + +m_refcount(1), +m_pNamedPropertyArray(NULL) +/* +pre: false +effect: constucts a CValue +*/ +{ + //debug(gRefCountValue++) // debugging +} + + + +CValue::~CValue() +/* +pre: +effect: deletes the object +*/ +{ + ClearProperties(); + + assertd (m_refcount==0); +} + + + + +#define VALUE_SUB(val1, val2) (val1)->Calc(VALUE_SUB_OPERATOR, val2) +#define VALUE_MUL(val1, val2) (val1)->Calc(VALUE_MUL_OPERATOR, val2) +#define VALUE_DIV(val1, val2) (val1)->Calc(VALUE_DIV_OPERATOR, val2) +#define VALUE_NEG(val1) (val1)->Calc(VALUE_NEG_OPERATOR, val1) +#define VALUE_POS(val1) (val1)->Calc(VALUE_POS_OPERATOR, val1) + + +STR_String CValue::op2str (VALUE_OPERATOR op) +{ + //pre: + //ret: the stringrepresentation of operator op + + STR_String opmsg; + switch (op) { + case VALUE_ADD_OPERATOR: + opmsg = " + "; + break; + case VALUE_SUB_OPERATOR: + opmsg = " - "; + break; + case VALUE_MUL_OPERATOR: + opmsg = " * "; + break; + case VALUE_DIV_OPERATOR: + opmsg = " / "; + break; + case VALUE_NEG_OPERATOR: + opmsg = " -"; + break; + case VALUE_POS_OPERATOR: + opmsg = " +"; + break; + case VALUE_AND_OPERATOR: + opmsg = " & "; + break; + case VALUE_OR_OPERATOR: + opmsg = " | "; + break; + case VALUE_EQL_OPERATOR: + opmsg = " = "; + break; + case VALUE_NEQ_OPERATOR: + opmsg = " != "; + break; + case VALUE_NOT_OPERATOR: + opmsg = " !"; + break; + default: + opmsg="Error in Errorhandling routine."; + // AfxMessageBox("Invalid operator"); + break; + } + return opmsg; +} + + + + + +//--------------------------------------------------------------------------------------------------------------------- +// Property Management +//--------------------------------------------------------------------------------------------------------------------- + + + +// +// Set property <ioProperty>, overwrites and releases a previous property with the same name if needed +// +void CValue::SetProperty(const STR_String & name,CValue* ioProperty) +{ + // Check if somebody is setting an empty property + if (ioProperty==NULL) + { + trace("Warning:trying to set empty property!"); + return; + } + + // Make sure we have a property array + if (m_pNamedPropertyArray == NULL) + m_pNamedPropertyArray = new std::map<const STR_String,CValue *>; + + // Try to replace property (if so -> exit as soon as we replaced it) + CValue* oldval = (*m_pNamedPropertyArray)[name]; + if (oldval) + { + oldval->Release(); + } + + // Add property at end of array + (*m_pNamedPropertyArray)[name] = ioProperty;//->Add(ioProperty); +} + + + +// +// Get pointer to a property with name <inName>, returns NULL if there is no property named <inName> +// +CValue* CValue::GetProperty(const STR_String & inName) +{ + // Check properties, as soon as we found it -> Return a pointer to the property + CValue* result = NULL; + if (m_pNamedPropertyArray) + { + std::map<const STR_String,CValue*>::iterator it = (*m_pNamedPropertyArray).find(inName); + if (!( it==m_pNamedPropertyArray->end())) + { + result = (*it).second; + } + + } + //for (int i=0; i<m_pValuePropertyArray->size(); i++) + // if ((*m_pValuePropertyArray)[i]->GetName() == inName) + // return (*m_pValuePropertyArray)[i]; + + // Did not find property with name <inName>, return NULL property pointer + return result; +} + + + +// +// Get text description of property with name <inName>, returns an empty string if there is no property named <inName> +// +STR_String CValue::GetPropertyText(const STR_String & inName,const STR_String& deftext) +{ + CValue *property = GetProperty(inName); + if (property) + return property->GetText(); + else + return deftext;//String::sEmpty; +} + +float CValue::GetPropertyNumber(const STR_String& inName,float defnumber) +{ + CValue *property = GetProperty(inName); + if (property) + return property->GetNumber(); + else + return defnumber; +} + + + +// +// Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed +// +bool CValue::RemoveProperty(const STR_String & inName) +{ + // Check if there are properties at all which can be removed + if (m_pNamedPropertyArray == NULL) + return false; + + // Scan all properties, as soon as we find one with <inName> -> Remove it +// CValue* val = (*m_pNamedPropertyArray)[inName]; + if (m_pNamedPropertyArray->erase(inName)) return true; + + return false; +} + + + +// +// Clear all properties +// +void CValue::ClearProperties() +{ + // Check if we have any properties + if (m_pNamedPropertyArray == NULL) + return; + + // Remove all properties + for ( std::map<const STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin(); + !(it == m_pNamedPropertyArray->end());it++) + { + CValue* tmpval = (*it).second; + STR_String name = (*it).first; + tmpval->Release(); + } + + // Delete property array + delete m_pNamedPropertyArray; + m_pNamedPropertyArray=NULL; +} + + + +// +// Set all properties' modified flag to <inModified> +// +void CValue::SetPropertiesModified(bool inModified) +{ + int numprops = GetPropertyCount(); + for (int i=0; i<numprops; i++) + GetProperty(i)->SetModified(inModified); +} + + + +// +// Check if any of the properties in this value have been modified +// +bool CValue::IsAnyPropertyModified() +{ + int numprops = GetPropertyCount(); + for (int i=0;i<numprops;i++) + if (GetProperty(i)->IsModified()) + return true; + + return false; +} + + + +// +// Get property number <inIndex> +// + +CValue* CValue::GetProperty(int inIndex) +{ + + int count=0; + CValue* result = NULL; + + if (m_pNamedPropertyArray) + { + for ( std::map<const STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin(); + !(it == m_pNamedPropertyArray->end());it++) + { + if (count++==inIndex) + { + result = (*it).second; + break; + } + } + + } + return result; +} + + + +// +// Get the amount of properties assiocated with this value +// +int CValue::GetPropertyCount() +{ + if (m_pNamedPropertyArray) + return m_pNamedPropertyArray->size(); + else + return 0; +} + + + + + +void CValue::CloneProperties(CValue *replica) +{ + + if (m_pNamedPropertyArray) + { + replica->m_pNamedPropertyArray=NULL; + for ( std::map<const STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin(); + !(it == m_pNamedPropertyArray->end());it++) + { + + replica->SetProperty((*it).first,(*it).second->GetReplica()); + } + } + + +} + + + + + + +double* CValue::GetVector3(bool bGetTransformedVec) +{ + assertd(false); // don;t get vector from me + return m_sZeroVec;//::sZero; +} + + + + + + +/*--------------------------------------------------------------------------------------------------------------------- + Reference Counting +---------------------------------------------------------------------------------------------------------------------*/ + + + +// +// Add a reference to this value +// +CValue *CValue::AddRef() +{ + // Increase global reference count, used to see at the end of the program + // if all CValue-derived classes have been dereferenced to 0 + //debug(gRefCountValue++); + m_refcount++; + return this; +} + + + +// +// Release a reference to this value (when reference count reaches 0, the value is removed from the heap) +// +int CValue::Release() +{ + // Decrease global reference count, used to see at the end of the program + // if all CValue-derived classes have been dereferenced to 0 + //debug(gRefCountValue--); + + // Decrease local reference count, if it reaches 0 the object should be freed + if (--m_refcount > 0) + { + // Reference count normal, return new reference count + return m_refcount; + } + else + { + // Reference count reached 0, delete ourselves and return 0 +// assert(m_refcount==0, "Reference count reached sub-zero, object released too much"); + delete this; + return 0; + } + +} + + + +// +// Disable reference counting for this value +// +void CValue::DisableRefCount() +{ + assertd(m_refcount == 1); + m_refcount--; + + //debug(gRefCountValue--); + m_ValFlags.RefCountDisabled=true; +} + + + +void CValue::AddDataToReplica(CValue *replica) +{ + replica->m_refcount = 1; +#ifdef _DEBUG + //gRefCountValue++; +#endif + replica->m_ValFlags.RefCountDisabled = false; + + replica->ReplicaSetName(GetName()); + + //copy all props + CloneProperties(replica); +} + + + +CValue* CValue::FindIdentifier(const STR_String& identifiername) +{ + + CValue* result = NULL; + + int pos = 0; + // if a dot exists, explode the name into pieces to get the subcontext + if ((pos=identifiername.Find('.'))>=0) + { + const STR_String rightstring = identifiername.Right(identifiername.Length() -1 - pos); + const STR_String leftstring = identifiername.Left(pos); + CValue* tempresult = GetProperty(leftstring); + if (tempresult) + { + result=tempresult->FindIdentifier(rightstring); + } + } else + { + result = GetProperty(identifiername); + } + if (result) + return result->AddRef(); + // warning here !!! + result = new CErrorValue(identifiername+" not found"); + return result; +} + + +#ifndef NO_EXP_PYTHON_EMBEDDING + + +static PyMethodDef CValueMethods[] = +{ + //{ "new", CValue::PyMake , Py_NEWARGS}, + { NULL,NULL} // Sentinel +}; + + +PyObject* CValue::_getattr(char* attr) +{ + CValue* resultattr = FindIdentifier(attr); + STR_String text; + if (resultattr) + { + if (resultattr->IsError()) + { + resultattr->Release(); + } else + { + // to avoid some compare problems, return a real pythonthing + PyObject* pyconvert = resultattr->ConvertValueToPython(); + if (pyconvert) + { + resultattr->Release(); + return pyconvert; + } else + { + // also check if it's already in pythoninterpreter! + return resultattr; + } + + } + } + _getattr_up(PyObjectPlus); +} + +CValue* CValue::ConvertPythonToValue(PyObject* pyobj) +{ + + CValue* vallie = NULL; + + PyTypeObject* type = pyobj->ob_type; + + if (type == &PyList_Type) + { + CListValue* listval = new CListValue(); + bool error = false; + + int i; + int numitems = PyList_Size(pyobj); + for (i=0;i<numitems;i++) + { + PyObject* listitem = PyList_GetItem(pyobj,i); + CValue* listitemval = ConvertPythonToValue(listitem); + if (listitemval) + { + listval->Add(listitemval); + } else + { + error = true; + } + } + if (!error) + { + // jippie! could be converted + vallie = listval; + } else + { + // list could not be converted... bad luck + listval->Release(); + } + + } else + if (type == &PyFloat_Type) + { + float fl; + PyArg_Parse(pyobj,"f",&fl); + vallie = new CFloatValue(fl); + } else + if (type==&PyInt_Type) + { + int innie; + PyArg_Parse(pyobj,"i",&innie); + vallie = new CIntValue(innie); + } else + + if (type==&PyString_Type) + { + vallie = new CStringValue(PyString_AsString(pyobj),""); + } else + if (type==&CValue::Type || type==&CListValue::Type) + { + vallie = ((CValue*) pyobj)->AddRef(); + } + return vallie; + +} +int CValue::_setattr(char* attr,PyObject* pyobj) +{ + + if (!pyobj) { // member deletion + RemoveProperty(attr); + return 0; + } + + CValue* vallie = ConvertPythonToValue(pyobj); + if (vallie) + { + CValue* oldprop = GetProperty(attr); + + if (oldprop) + { + oldprop->SetValue(vallie); + } else + { + SetProperty(attr,vallie->AddRef()); + } + vallie->Release(); + } + + //PyObjectPlus::_setattr(attr,value); + return 0; +}; +/* +PyObject* CValue::PyMake(PyObject* ignored,PyObject* args) +{ + + //Py_Try(PyArg_ParseTuple(args,"s",&name)); + Py_INCREF(Py_None); + return Py_None;//new CValue(); +} +*/ + +extern "C" { + void initCValue(void) + { + Py_InitModule("CValue",CValueMethods); + } +} + + + +#endif //NO_EXP_PYTHON_EMBEDDING + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +/* These implementations were moved out of the header */ + +void CValue::SetOwnerExpression(class CExpression* expr) +{ + /* intentionally empty */ +} + +void CValue::SetColorOperator(VALUE_OPERATOR op) +{ + /* intentionally empty */ +} +void CValue::SetValue(CValue* newval) +{ + // no one should get here + assertd(newval->GetNumber() == 10121969); +} +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h new file mode 100644 index 00000000000..8131cc152bc --- /dev/null +++ b/source/gameengine/Expressions/Value.h @@ -0,0 +1,467 @@ +/* + * Value.h: interface for the CValue class. + * $Id$ + * 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. + * + */ + +#ifdef WIN32 +#pragma warning (disable:4786) +#endif //WIN32 + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +//// +//// Baseclass CValue +//// Together with CExpression, CValue and it's derived classes can be used to +//// parse expressions into a parsetree with error detecting/correcting capabilities +//// also expandible by a CFactory pluginsystem +//// +//// Features: +//// Reference Counting (AddRef() / Release()) +//// Calculations (Calc() / CalcFinal()) +//// Configuration (Configure()) +//// Serialization (EdSerialize() / EdIdSerialize() / EdPtrSerialize() and macro PLUGIN_DECLARE_SERIAL +//// Property system (SetProperty() / GetProperty() / FindIdentifier()) +//// Replication (GetReplica()) +//// Flags (IsSelected() / IsModified() / SetSelected()...) +//// +//// Some small editor-specific things added +//// A helperclass CompressorArchive handles the serialization +//// +//////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +#ifndef __VALUE_H__ +#define __VALUE_H__ + +#include <map> // array functionality for the propertylist +#include "STR_String.h" // STR_String class + + + + +#ifndef GEN_NO_ASSERT +#undef assert +#define assert(exp) ((void)NULL) +#endif + + +#ifndef GEN_NO_TRACE +#undef trace +#define trace(exp) ((void)NULL) +#endif + +#ifndef GEN_NO_DEBUG +#undef debug +#define debug(exp) ((void)NULL) +#endif + + + + +#ifndef GEN_NO_ASSERTD +#undef assertd +#define assertd(exp) ((void)NULL) +#endif + + +#ifndef USE_PRAGMA_ONCE +#ifdef WIN32 + #pragma once + +#endif //WIN32 +#endif + +#define EDITOR_LEVEL_VERSION 0x06 + +enum VALUE_OPERATOR { + + VALUE_ADD_OPERATOR, // + + VALUE_SUB_OPERATOR, // - + VALUE_MUL_OPERATOR, // * + VALUE_DIV_OPERATOR, // / + VALUE_NEG_OPERATOR, // - + VALUE_POS_OPERATOR, // + + VALUE_AND_OPERATOR, // && + VALUE_OR_OPERATOR, // || + VALUE_EQL_OPERATOR, // == + VALUE_NEQ_OPERATOR, // != + VALUE_GRE_OPERATOR, // > + VALUE_LES_OPERATOR, // < + VALUE_GEQ_OPERATOR, // >= + VALUE_LEQ_OPERATOR, // <= + VALUE_NOT_OPERATOR, // ! + VALUE_NO_OPERATOR // no operation at all +}; + +enum VALUE_DATA_TYPE { + VALUE_NO_TYPE, // abstract baseclass + VALUE_INT_TYPE, + VALUE_FLOAT_TYPE, + VALUE_STRING_TYPE, + VALUE_BOOL_TYPE, + VALUE_ERROR_TYPE, + VALUE_EMPTY_TYPE, + VALUE_SOLID_TYPE, + VALUE_COMBISOLID_TYPE, + VALUE_VECTOR_TYPE, + VALUE_MENU_TYPE, + VALUE_ACTOR_TYPE, + VALUE_MAX_TYPE //only here to provide number of types +}; + + + +#ifdef _DEBUG +//extern int gRefCountValue; // debugonly variable to check if all CValue Refences are Dereferenced at programexit +#endif + +struct HashableInt +{ + HashableInt(int id) : mData(id) { } + + unsigned long Hash() const { return 0;} ////}gHash(&mData, sizeof(int));} + + bool operator==(HashableInt rhs) { return mData == rhs.mData; } + + int mData; +}; + + +// +// Bitfield that stores the flags for each CValue derived class +// +struct ValueFlags { + ValueFlags() : + Modified(true), + Selected(false), + Affected(false), + ReleaseRequested(false), + Error(false), + RefCountDisabled(false), + HasProperties(false), + HasName(false), + Visible(true), + CustomFlag1(false), + CustomFlag2(false) + { + } + + unsigned short Modified : 1; + unsigned short Selected : 1; + unsigned short Affected : 1; + unsigned short ReleaseRequested : 1; + unsigned short Error : 1; + unsigned short RefCountDisabled : 1; + unsigned short HasProperties : 1; + unsigned short HasName : 1; + unsigned short Visible : 1; + unsigned short CustomFlag1 : 1; + unsigned short CustomFlag2 : 1; + + +}; + +/** + * Base Class for all Actions performed on CValue's. Can be extended for undo/redo system in future. +*/ +class CAction +{ +public: + CAction() { + }; + virtual ~CAction(){ + }; + virtual void Execute() const =0; +}; + +// +// CValue +// +// Base class for all editor functionality, flexible object type that allows +// calculations and uses reference counting for memory management. +// +// + +/** + * These macros are helpfull when embedding Python routines. The second + * macro is one that also requires a documentation string + */ +#define KX_PYMETHOD(class_name, method_name) \ + PyObject* Py##method_name(PyObject* self, PyObject* args, PyObject* kwds); \ + static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \ + return ((class_name*) self)->Py##method_name(self, args, kwds); \ + }; \ + +#define KX_PYMETHOD_DOC(class_name, method_name) \ + PyObject* Py##method_name(PyObject* self, PyObject* args, PyObject* kwds); \ + static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \ + return ((class_name*) self)->Py##method_name(self, args, kwds); \ + }; \ + static char method_name##_doc[]; \ + +/* The line above should remain empty */ + +#ifndef NO_EXP_PYTHON_EMBEDDING +#include "PyObjectPlus.h" +#include "object.h" +class CValue : public PyObjectPlus +#else +class CValue +#endif //NO_EXP_PYTHON_EMBEDDING + + +{ +#ifndef NO_EXP_PYTHON_EMBEDDING +Py_Header; +#endif //NO_EXP_PYTHON_EMBEDDING +public: + enum AllocationTYPE { + STACKVALUE = 0, + HEAPVALUE = 1 + }; + + enum DrawTYPE { + STARTFRAME = 0, + ENDFRAME = 1, + INTERFRAME = 2 + }; + + + // Construction / Destruction +#ifndef NO_EXP_PYTHON_EMBEDDING + + CValue(PyTypeObject *T = &Type); + //static PyObject* PyMake(PyObject*,PyObject*); + virtual PyObject *_repr(void) + { + return Py_BuildValue("s",(const char*)GetText()); + } + + + + PyObject* _getattr(char* attr); + + void SpecialRelease() + { + int i=0; + if (ob_refcnt == 0) + { + _Py_NewReference(this); + + } else + { + i++; + } + Release(); + } + static void PyDestructor(PyObject *P) // python wrapper + { + ((CValue*)P)->SpecialRelease(); + }; + + virtual PyObject* ConvertValueToPython() { + return NULL; + } + + virtual CValue* ConvertPythonToValue(PyObject* pyobj); + + + int _setattr(char* attr,PyObject* value); + + KX_PYMETHOD(CValue,GetName); + +#else + CValue(); +#endif //NO_EXP_PYTHON_EMBEDDING + + + + // Expression Calculation + virtual CValue* Calc(VALUE_OPERATOR op, CValue *val) = 0; + virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) = 0; + virtual void SetOwnerExpression(class CExpression* expr); + + + + void Execute(const CAction& a) + { + a.Execute(); + }; + + /// Reference Counting + int GetRefCount() { return m_refcount; } + virtual CValue* AddRef(); // Add a reference to this value + virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap) + + /// Property Management + virtual void SetProperty(const STR_String& name,CValue* ioProperty); // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed + virtual CValue* GetProperty(const STR_String & inName); // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName> + STR_String GetPropertyText(const STR_String & inName,const STR_String& deftext=""); // Get text description of property with name <inName>, returns an empty string if there is no property named <inName> + float GetPropertyNumber(const STR_String& inName,float defnumber); + virtual bool RemoveProperty(const STR_String & inName); // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed + virtual void ClearProperties(); // Clear all properties + + virtual void SetPropertiesModified(bool inModified); // Set all properties' modified flag to <inModified> + virtual bool IsAnyPropertyModified(); // Check if any of the properties in this value have been modified + + virtual CValue* GetProperty(int inIndex); // Get property number <inIndex> + virtual int GetPropertyCount(); // Get the amount of properties assiocated with this value + + virtual void CloneProperties(CValue* replica); + virtual CValue* FindIdentifier(const STR_String& identifiername); + /** Set the wireframe color of this value depending on the CSG + * operator type <op> + * @attention: not implemented */ + virtual void SetColorOperator(VALUE_OPERATOR op); + + virtual const STR_String & GetText() = 0; + virtual float GetNumber() = 0; + double* ZeroVector() { return m_sZeroVec; }; + virtual double* GetVector3(bool bGetTransformedVec = false); + + virtual STR_String GetName() = 0; // Retrieve the name of the value + virtual void SetName(STR_String name) = 0; // Set the name of the value + virtual void ReplicaSetName(STR_String name) = 0; + /** Sets the value to this cvalue. + * @attention this particular function should never be called. Why not abstract? */ + virtual void SetValue(CValue* newval); + virtual CValue* GetReplica() =0; + //virtual CValue* Copy() = 0; + + + STR_String op2str(VALUE_OPERATOR op); + + // setting / getting flags + inline void SetSelected(bool bSelected) { m_ValFlags.Selected = bSelected; } + virtual void SetModified(bool bModified) { m_ValFlags.Modified = bModified; } + virtual void SetAffected(bool bAffected=true) { m_ValFlags.Affected = bAffected; } + inline void SetReleaseRequested(bool bReleaseRequested) { m_ValFlags.ReleaseRequested=bReleaseRequested; } + inline void SetError(bool err) { m_ValFlags.Error=err; } + inline void SetVisible (bool vis) { m_ValFlags.Visible=vis; } + + virtual bool IsModified() { return m_ValFlags.Modified; } + inline bool IsError() { return m_ValFlags.Error; } + virtual bool IsAffected() { return m_ValFlags.Affected || m_ValFlags.Modified; } + virtual bool IsSelected() { return m_ValFlags.Selected; } + inline bool IsReleaseRequested() { return m_ValFlags.ReleaseRequested; } + virtual bool IsVisible() { return m_ValFlags.Visible;} + virtual void SetCustomFlag1(bool bCustomFlag) { m_ValFlags.CustomFlag1 = bCustomFlag;}; + virtual bool IsCustomFlag1() { return m_ValFlags.CustomFlag1;}; + + virtual void SetCustomFlag2(bool bCustomFlag) { m_ValFlags.CustomFlag2 = bCustomFlag;}; + virtual bool IsCustomFlag2() { return m_ValFlags.CustomFlag2;}; + +protected: + virtual void DisableRefCount(); // Disable reference counting for this value + virtual void AddDataToReplica(CValue* replica); + virtual ~CValue(); +private: + // Member variables + std::map<const STR_String,CValue*>* m_pNamedPropertyArray; // Properties for user/game etc + ValueFlags m_ValFlags; // Frequently used flags in a bitfield (low memoryusage) + int m_refcount; // Reference Counter + static double m_sZeroVec[3]; + +}; + + + +// +// Declare a CValue or CExpression or CWhatever to be serialized by the editor. +// +// This macro introduces the EdSerialize() function (which must be implemented by +// the client) and the EdIdSerialize() function (which is implemented by this macro). +// +// The generated Copy() function returns a pointer to <root_base_class_name> type +// of object. So, for *any* CValue-derived object this should be set to CValue, +// for *any* CExpression-derived object this should be set to CExpression. +// +#define PLUGIN_DECLARE_SERIAL(class_name, root_base_class_name) \ +public: \ + virtual root_base_class_name * Copy() { return new class_name; } \ + virtual bool EdSerialize(CompressorArchive& arch,class CFactoryManager* facmgr,bool bIsStoring); \ + virtual bool EdIdSerialize(CompressorArchive& arch,class CFactoryManager* facmgr,bool bIsStoring) \ +{ \ + if (bIsStoring) \ + arch.StoreString(#class_name); \ + \ + return false; \ +} \ + + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +// CPropValue is a CValue derived class, that implements the identification (String name) +// SetName() / GetName(), +// normal classes should derive from CPropValue, real lightweight classes straight from CValue + + +class CPropValue : public CValue +{ +public: + +#ifndef NO_EXP_PYTHON_EMBEDDING + CPropValue(PyTypeObject* T=&Type) : + CValue(T), +#else + CPropValue() : +#endif //NO_EXP_PYTHON_EMBEDDING + m_pstrNewName(NULL) + + { + } + + virtual ~CPropValue() + { + if (m_pstrNewName) + { + delete m_pstrNewName; + m_pstrNewName = NULL; + } + } + + virtual void SetName(STR_String name) { + if (m_pstrNewName) + { + delete m_pstrNewName; + m_pstrNewName = NULL; + } + if (name.Length()) + m_pstrNewName = new STR_String(name); + } + virtual void ReplicaSetName(STR_String name) { + m_pstrNewName=NULL; + if (name.Length()) + m_pstrNewName = new STR_String(name); + } + + virtual STR_String GetName() { + //STR_String namefromprop = GetPropertyText("Name"); + //if (namefromprop.Length() > 0) + // return namefromprop; + + if (m_pstrNewName) + { + return *m_pstrNewName; + } + return STR_String(""); + }; // name of Value + +protected: + STR_String* m_pstrNewName; // Identification +}; + + + +#endif // !defined _VALUEBASECLASS_H diff --git a/source/gameengine/Expressions/VectorValue.cpp b/source/gameengine/Expressions/VectorValue.cpp new file mode 100644 index 00000000000..6aa7926bfa7 --- /dev/null +++ b/source/gameengine/Expressions/VectorValue.cpp @@ -0,0 +1,213 @@ +// VectorValue.cpp: implementation of the CVectorValue 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. + * + */ + +#ifdef WIN32 +#pragma warning (disable:4786) +#endif + +#include "Value.h" +#include "VectorValue.h" +#include "ErrorValue.h" +//#include "MatrixValue.h" +#include "VoidValue.h" +#include "StringValue.h" +//#include "FactoryManager.h" + + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CVectorValue::CVectorValue(float x,float y,float z, AllocationTYPE alloctype) +{ + SetCustomFlag1(false);//FancyOutput=false; + + if (alloctype == STACKVALUE) + { + CValue::DisableRefCount(); + }; + + m_vec[KX_X] = m_transformedvec[KX_X] = x; + m_vec[KX_Y] = m_transformedvec[KX_Y] = y; + m_vec[KX_Z] = m_transformedvec[KX_Z] = z; + +} +CVectorValue::CVectorValue(double vec[],STR_String name,AllocationTYPE alloctype) { + + SetCustomFlag1(false);//FancyOutput=false; + + m_vec[KX_X] = m_transformedvec[KX_X] = vec[KX_X]; + m_vec[KX_Y] = m_transformedvec[KX_Y] = vec[KX_Y]; + m_vec[KX_Z] = m_transformedvec[KX_Z] = vec[KX_Z]; + + if (alloctype == STACKVALUE) + { + CValue::DisableRefCount(); + + } + + SetName(name); +} + +CVectorValue::CVectorValue(double vec[],AllocationTYPE alloctype) { + + SetCustomFlag1(false);//FancyOutput=false; + + m_vec[KX_X] = m_transformedvec[KX_X] = vec[KX_X]; + m_vec[KX_Y] = m_transformedvec[KX_Y] = vec[KX_Y]; + m_vec[KX_Z] = m_transformedvec[KX_Z] = vec[KX_Z]; + + if (alloctype == STACKVALUE) + { + CValue::DisableRefCount(); + + } + + +} +CVectorValue::~CVectorValue() +{ + +} + +CValue* CVectorValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) +/* +pre: the type of val is dtype +ret: a new object containing the result of applying operator op to val and +this object +*/ +{ + CValue *ret = NULL; + + switch(op) + { + case VALUE_ADD_OPERATOR: + { + switch (dtype) + { + case VALUE_EMPTY_TYPE: + case VALUE_VECTOR_TYPE: + { + ret = new CVectorValue( + val->GetVector3()[KX_X] + GetVector3()[KX_X], + val->GetVector3()[KX_Y] + GetVector3()[KX_Y], + val->GetVector3()[KX_Z] + GetVector3()[KX_Z], + CValue::HEAPVALUE); + ret->SetName(GetName()); + break; + } + + default: + ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); + } + break; + } + case VALUE_MUL_OPERATOR: + { + switch (dtype) + { + + case VALUE_EMPTY_TYPE: + case VALUE_VECTOR_TYPE: + { + //MT_Vector3 supports 'scaling' by another vector, instead of using general transform, Gino? + //ret = new CVectorValue(val->GetVector3().Scaled(GetVector3()),GetName()); + break; + } + case VALUE_FLOAT_TYPE: + { + ret = new CVectorValue( + val->GetVector3()[KX_X] * GetVector3()[KX_X], + val->GetVector3()[KX_Y] * GetVector3()[KX_Y], + val->GetVector3()[KX_Z] * GetVector3()[KX_Z], + CValue::HEAPVALUE); + ret->SetName(GetName()); + break; + } + + default: + ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); + } + break; + + } + + default: + ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); + } + + + return ret; +} + +float CVectorValue::GetNumber() +{ + return m_vec[KX_X]; +} + + +double* CVectorValue::GetVector3(bool bGetTransformedVec) +{ + if (bGetTransformedVec) + return m_transformedvec; + // else + return m_vec; +} + + + + + +void CVectorValue::SetVector(double newvec[]) +{ + m_vec[KX_X] = m_transformedvec[KX_X] = newvec[KX_X]; + m_vec[KX_Y] = m_transformedvec[KX_Y] = newvec[KX_Y]; + m_vec[KX_Z] = m_transformedvec[KX_Z] = newvec[KX_Z]; + + SetModified(true); +} + + +void CVectorValue::SetValue(CValue *newval) +{ + + double* newvec = ((CVectorValue*)newval)->GetVector3(); + m_vec[KX_X] = m_transformedvec[KX_X] = newvec[KX_X]; + m_vec[KX_Y] = m_transformedvec[KX_Y] = newvec[KX_Y]; + m_vec[KX_Z] = m_transformedvec[KX_Z] = newvec[KX_Z]; + + SetModified(true); +} + +static const STR_String gstrVectorStr=STR_String(); +const STR_String & CVectorValue::GetText() +{ + assertd(false); + return gstrVectorStr; +} + +CValue* CVectorValue::GetReplica() { + CVectorValue* replica = new CVectorValue(*this); + CValue::AddDataToReplica(replica); + return replica; +}; + +/*void CVectorValue::Transform(rcMatrix4x4 mat) +{ + m_transformedvec = mat*m_vec; +} +*/ + + diff --git a/source/gameengine/Expressions/VectorValue.h b/source/gameengine/Expressions/VectorValue.h new file mode 100644 index 00000000000..8ed671721a3 --- /dev/null +++ b/source/gameengine/Expressions/VectorValue.h @@ -0,0 +1,86 @@ +/* + * VectorValue.h: interface for the CVectorValue class. + * $Id$ + * 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. + * + */ +#if !defined _VECTORVALUE_H +#define _VECTORVALUE_H + + +#include "Value.h" + +#define KX_X 0 +#define KX_Y 1 +#define KX_Z 2 + + +class CVectorValue : public CPropValue +{ + //PLUGIN_DECLARE_SERIAL(CVectorValue,CValue) + +public: + //void Transform(rcMatrix4x4 mat); + virtual void SetValue(CValue* newval); + void SetVector(double newvec[]); + void Configure(CValue* menuvalue); + virtual double* GetVector3(bool bGetTransformedVec=false); + virtual float GetNumber(); + + CValue* Calc(VALUE_OPERATOR op, CValue *val) { + return val->CalcFinal(VALUE_VECTOR_TYPE, op, this); + } + + CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); + + + CVectorValue(double vec[],STR_String name,AllocationTYPE alloctype=CValue::HEAPVALUE); + CVectorValue() {}; + + CVectorValue(double vec[],AllocationTYPE alloctype=CValue::HEAPVALUE); + CVectorValue(float x,float y,float z, AllocationTYPE alloctype = CValue::HEAPVALUE); + virtual ~CVectorValue(); + //virtual bool ExportT3D(File *txtfile,bool bNoName=false); + void AddConfigurationData(CValue* menuvalue); + + + + virtual CValue* GetReplica(); + virtual const STR_String & GetText(); + +/* + void SnapPoint(float num,int snap) + { + if (num > 0) num += ((float)snap / 2); + else num -= ((float)snap / 2); + num = (long)(((long)(num / snap)) * snap); + }; + + void SnapPosition(const double snapvec[]) + { + + if (snapvec[KX_X] >= 1) + SnapPoint(m_vec[KX_X],snapvec[KX_X]); + if (snapvec[KX_Y] >= 1) + SnapPoint(m_vec[KX_Y],snapvec[KX_Y]); + if (snapvec[KX_Z] >= 1) + SnapPoint(m_vec[KX_Z],snapvec[KX_Z]); + + } +*/ + +protected: + double m_vec[3]; + double m_transformedvec[3]; +}; + +#endif // !defined _VECTORVALUE_H + diff --git a/source/gameengine/Expressions/VoidValue.h b/source/gameengine/Expressions/VoidValue.h new file mode 100644 index 00000000000..5cf40268b97 --- /dev/null +++ b/source/gameengine/Expressions/VoidValue.h @@ -0,0 +1,68 @@ +/** + * VoidValue.h: interface for the CVoidValue class. + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef __VOIDVALUE_H__ +#define __VOIDVALUE_H__ + +#include "Value.h" + + +// +// Void value, used to transport *any* type of data +// +class CVoidValue : public CPropValue +{ + //PLUGIN_DECLARE_SERIAL (CVoidValue,CValue) + +public: + /// Construction/destruction + CVoidValue() : m_pAnything(NULL), m_bDeleteOnDestruct(false) { } + CVoidValue(void * voidptr, bool bDeleteOnDestruct, AllocationTYPE alloctype) : m_pAnything(voidptr), m_bDeleteOnDestruct(bDeleteOnDestruct) { if (alloctype == STACKVALUE) CValue::DisableRefCount(); } + virtual ~CVoidValue(); // Destruct void value, delete memory if we're owning it + + /// Value -> String or number + virtual const STR_String & GetText(); // Get string description of void value (unimplemented) + virtual float GetNumber() { return -1; } + + /// Value calculation + virtual CValue* Calc(VALUE_OPERATOR op, CValue *val); + virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue* val); + + /// Value replication + virtual CValue* GetReplica(); + + /// Data members + bool m_bDeleteOnDestruct; + void* m_pAnything; +}; + +#endif // !defined _VOIDVALUE_H |