/** Convert the content for a tuple to a vector of TValue that can be passed to the Delphi RTTI system. * \param O: This must be a tuple. Not checked. * \param Values: vector filled with the return values. * \param Parameters: This must be the expected types for the converted values. The number of elements * must be the same as the number of items in the tuple. */ void TupleToValues(PyObject *O, std::vector<TValue> &Values, const DynamicArray<TRttiParameter*> &Parameters) { Values.clear(); unsigned Size = PyTuple_Size(O); for(unsigned I = 0; I < Size; I++) Values.push_back(ToValue(PyTuple_GetItem(O, I), Parameters[I]->ParamType->Handle)); }
bool CallableData::ToValue(int32_t& v) const { int64_t tmp;if(!ToValue(tmp)) return false; v=tmp; return true; }
bool CallableData::ToValue(bool&) const { int64_t v(0); if(!ToValue(v)) return false; return v!=0; }
bool CallableData::ToValue(float& v) const { double tmp;if(!ToValue(tmp)) return false; v=tmp; return true; }
/** Convert a PyObject to a TValue as used when calling functions and setting properties in a generic way through Delphi RTTI. * \param O: PyObject to convert * \param TypeInfo: The expected return type * \return A TValue with a value of the type given by TypeInfo. * \throw EPyVclError on conversion errors. */ TValue ToValue(PyObject *O, TTypeInfo *TypeInfo) { TValue Result; switch(TypeInfo->Kind) { case tkClass: if(VclObject_Check(O)) Result = TValue::From(VclObject_AsObject(O)); else if(O == Py_None || PyLong_Check(O)) Result = TValue::From((TObject*)(O == Py_None ? NULL : PyLong_AsLong(O))); else throw EPyVclError("Cannot convert Python object of type '" + String(O->ob_type->tp_name) + "' to '" + AnsiString(TypeInfo->Name) + "'"); break; case tkEnumeration: if(PyUnicode_Check(O)) TValue::Make(GetEnumValue(TypeInfo, PyUnicode_AsUnicode(O)), TypeInfo, Result); if(PyLong_Check(O)) TValue::Make(PyLong_AsLong(O), TypeInfo, Result); break; case tkSet: TValue::Make(StringToSet(TypeInfo, PyUnicode_AsUnicode(O)), TypeInfo, Result); break; case tkInteger: Result = TValue::From(PyLong_AsUnsignedLongMask(O)); break; case tkUString: case tkString: case tkLString: case tkWString: Result = TValue::From(String(PyUnicode_AsUnicode(O))); break; case tkChar: case tkWChar: if(PyUnicode_GetSize(O) != 1) throw EPyVclError("Expected string with one character"); Result = TValue::From(PyUnicode_AsUnicode(O)[0]); break; case tkFloat: Result = TValue::From(PyFloat_AsDouble(O)); break; case tkRecord: { TRttiType *Type = Context.GetType(TypeInfo); std::vector<BYTE> Data(Type->TypeSize); DynamicArray<TRttiField*> Fields = Type->GetFields(); if(PyTuple_Size(O) != Fields.Length) throw EPyVclError("Expected tuple with " + IntToStr(Fields.Length) + " elements"); for(int I = 0; I < Fields.Length; I++) Fields[I]->SetValue(&Data[0], ToValue(PyTuple_GetItem(O, I), Fields[I]->FieldType->Handle)); TValue::Make(&Data[0], TypeInfo, Result); break; } case tkInt64: Result = TValue::From(PyLong_AsLongLong(O)); break; case tkPointer: if(AnsiString(TypeInfo->Name) == "PWideChar") TValue::Make(reinterpret_cast<int>(PyUnicode_AsUnicode(O)), TypeInfo, Result); else throw EPyVclError("Cannot convert Python object of type '" + String(O->ob_type->tp_name) + "' to '" + AnsiString(TypeInfo->Name) + "'"); break; case tkVariant: case tkArray: case tkInterface: case tkDynArray: case tkClassRef: case tkProcedure: case tkUnknown: case tkMethod: default: throw EPyVclError("Cannot convert Python object of type '" + String(O->ob_type->tp_name) + "' to '" + AnsiString(TypeInfo->Name) + "'"); } if(PyErr_Occurred()) throw EPyVclError("Cannot convert Python object of type '" + String(O->ob_type->tp_name) + "' to '" + AnsiString(TypeInfo->Name) + "'"); return Result; }
STARTDECL(gl_scaling) () { auto sc = float2(object2view[0].x(), object2view[1].y()); return ToValue(sc); }
STARTDECL(gl_color) (Value &col, Value &body) { if (body.type != V_NIL) g_vm->Push(ToValue(curcolor)); // FIXME: maybe more efficient as an int curcolor = ValueDecTo<float4>(col); return body; }
STARTDECL(gl_origin) () { auto pos = float2(object2view[3].x(), object2view[3].y()); return ToValue(pos); }
STARTDECL(gl_locallastpos) (Value &name, Value &on) // need a local version of this too? { auto p = localpos(GetKeyPos(name.sval->str(), on.ival)); name.DEC(); return ToValue(p); }
STARTDECL(gl_localmousepos) (Value &i) { return ToValue(localfingerpos(i.ival)); }
STARTDECL(gl_mousedelta) (Value &i) { return ToValue(GetFinger(i.ival, true)); }
STARTDECL(gl_mousepos) (Value &i) { return ToValue(GetFinger(i.ival, false)); }
STARTDECL(gl_windowsize) () { return ToValue(screensize); }