PyObject *py_ue_actor_set_level_sequence(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *py_sequence; if (!PyArg_ParseTuple(args, "O:actor_set_level_sequence", &py_sequence)) { return NULL; } ALevelSequenceActor *actor = ue_py_check_type<ALevelSequenceActor>(self); if (!actor) { return PyErr_Format(PyExc_Exception, "uobject is not a LevelSequenceActor"); } ULevelSequence *sequence = ue_py_check_type<ULevelSequence>(py_sequence); if (!sequence) { return PyErr_Format(PyExc_Exception, "argument is not a LevelSequence"); } actor->SetSequence(sequence); Py_RETURN_NONE; }
PyObject *py_ue_actor_destroy_component(ue_PyUObject * self, PyObject * args) { ue_py_check(self); AActor *actor = ue_get_actor(self); if (!actor) return PyErr_Format(PyExc_Exception, "cannot retrieve Actor from uobject"); PyObject *py_component; if (!PyArg_ParseTuple(args, "O:actor_destroy_component", &py_component)) { return NULL; } UActorComponent *component = ue_py_check_type<UActorComponent>(py_component); if (!component) return PyErr_Format(PyExc_Exception, "argument is not a UActorComponent"); #if ENGINE_MINOR_VERSION >= 17 component->DestroyComponent(); #else actor->K2_DestroyComponent(component); #endif Py_INCREF(Py_None); return Py_None; }
PyObject *py_ue_actor_create_default_subobject(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *obj; char *name; if (!PyArg_ParseTuple(args, "Os:actor_create_default_subobject", &obj, &name)) { return NULL; } AActor *actor = ue_py_check_type<AActor>(self); if (!actor) return PyErr_Format(PyExc_Exception, "uobject is not an AActor"); UClass *u_class = ue_py_check_type<UClass>(obj); if (!u_class) return PyErr_Format(PyExc_Exception, "argument is not a UClass"); if (!FUObjectThreadContext::Get().TopInitializer()) return PyErr_Format(PyExc_Exception, "CreateDefaultSubobject() can be called only in a constructor"); UObject *ret_obj = actor->CreateDefaultSubobject(FName(UTF8_TO_TCHAR(name)), UObject::StaticClass(), u_class, false, false, true); if (!ret_obj) return PyErr_Format(PyExc_Exception, "unable to create component"); Py_RETURN_UOBJECT(ret_obj); }
PyObject *py_ue_get_actor_component(ue_PyUObject * self, PyObject * args) { ue_py_check(self); AActor *actor = ue_get_actor(self); if (!actor) return PyErr_Format(PyExc_Exception, "cannot retrieve Actor from uobject"); char *name; if (!PyArg_ParseTuple(args, "s:get_actor_component", &name)) { return NULL; } for (UActorComponent *component : actor->GetComponents()) { if (component->GetName().Equals(UTF8_TO_TCHAR(name))) { Py_RETURN_UOBJECT(component); } } Py_RETURN_NONE; }
PyObject *py_ue_find_actor_by_label(ue_PyUObject * self, PyObject * args) { ue_py_check(self); char *name; if (!PyArg_ParseTuple(args, "s:find_actor_by_label", &name)) { return NULL; } UWorld *world = ue_get_uworld(self); if (!world) return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject"); UObject *u_object = nullptr; for (TActorIterator<AActor> Itr(world); Itr; ++Itr) { AActor *u_obj = *Itr; if (u_obj->GetActorLabel().Equals(UTF8_TO_TCHAR(name))) { u_object = u_obj; break; } } if (u_object) { Py_RETURN_UOBJECT(u_object); } Py_RETURN_NONE; }
PyObject *py_ue_add_instance_component(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *py_component; if (!PyArg_ParseTuple(args, "O:add_instance_component", &py_component)) { return nullptr; } AActor *actor = ue_py_check_type<AActor>(self); if (!actor) { return PyErr_Format(PyExc_Exception, "uobject is not an AActor"); } UActorComponent *component = ue_py_check_type<UActorComponent>(py_component); if (!component) { return PyErr_Format(PyExc_Exception, "argument is not a UActorComponent"); } actor->AddInstanceComponent(component); Py_RETURN_NONE; }
PyObject *py_ue_controller_posses(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *obj; if (!PyArg_ParseTuple(args, "O:posses", &obj)) { return NULL; } if (!self->ue_object->IsA<AController>()) { return PyErr_Format(PyExc_Exception, "uobject is not an APawn"); } if (!ue_is_pyuobject(obj)) { return PyErr_Format(PyExc_Exception, "argument is not a UObject"); } ue_PyUObject *py_obj = (ue_PyUObject *)obj; if (!py_obj->ue_object->IsA<APawn>()) { return PyErr_Format(PyExc_Exception, "argument is not a APAwn"); } APawn *pawn = (APawn *)py_obj->ue_object; AController *controller = (AController *)self->ue_object; controller->Possess(pawn); Py_INCREF(Py_None); return Py_None; }
PyObject *py_ue_set_player_hud(ue_PyUObject *self, PyObject * args) { ue_py_check(self); PyObject *py_hud; int controller_id = 0; if (!PyArg_ParseTuple(args, "O|i:set_player_hud", &py_hud, &controller_id)) { return NULL; } UWorld *world = ue_get_uworld(self); if (!world) return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject"); AHUD *hud = ue_py_check_type<AHUD>(py_hud); if (!hud) return PyErr_Format(PyExc_Exception, "argument is not a AHUD"); APlayerController *controller = UGameplayStatics::GetPlayerController(world, controller_id); if (!controller) return PyErr_Format(PyExc_Exception, "unable to retrieve controller %d", controller_id); controller->MyHUD = hud; Py_RETURN_NONE; }
PyObject *py_ue_create_player(ue_PyUObject *self, PyObject * args) { ue_py_check(self); int controller_id; PyObject *spawn_pawn; if (!PyArg_ParseTuple(args, "i|O:create_player", &controller_id, &spawn_pawn)) { return NULL; } bool b_spawn_pawn = true; if (spawn_pawn && !PyObject_IsTrue(spawn_pawn)) { b_spawn_pawn = false; } UWorld *world = ue_get_uworld(self); if (!world) return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject"); APlayerController *controller = UGameplayStatics::CreatePlayer(world, controller_id, b_spawn_pawn); if (!controller) return PyErr_Format(PyExc_Exception, "unable to create a new player from controller %d", controller_id); return PyLong_FromLong(controller->PlayerState->PlayerId); }
PyObject *py_ue_find_actor_by_label(ue_PyUObject * self, PyObject * args) { ue_py_check(self); char *name; if (!PyArg_ParseTuple(args, "s:find_actor_by_label", &name)) { return NULL; } UWorld *world = ue_get_uworld(self); if (!world) return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject"); UObject *u_object = nullptr; for (TActorIterator<AActor> Itr(world); Itr; ++Itr) { AActor *u_obj = *Itr; if (u_obj->GetActorLabel().Equals(UTF8_TO_TCHAR(name))) { u_object = u_obj; break; } } if (u_object) { ue_PyUObject *ret = ue_get_python_wrapper(u_object); if (!ret) return PyErr_Format(PyExc_Exception, "PyUObject is in invalid state"); Py_INCREF(ret); return (PyObject *)ret; } Py_INCREF(Py_None); return Py_None; }
PyObject *py_ue_is_input_key_down(ue_PyUObject *self, PyObject * args) { ue_py_check(self); char *key; int controller_id = 0; if (!PyArg_ParseTuple(args, "s|i:is_input_key_down", &key, &controller_id)) { return NULL; } UWorld *world = ue_get_uworld(self); if (!world) return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject"); APlayerController *controller = UGameplayStatics::GetPlayerController(world, controller_id); if (!controller) return PyErr_Format(PyExc_Exception, "unable to retrieve controller %d", controller_id); if (controller->IsInputKeyDown(key)) { Py_INCREF(Py_True); return Py_True; } Py_INCREF(Py_False); return Py_False; }
PyObject *py_ue_draw_debug_line(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *py_obj_start; PyObject *py_obj_end; PyObject *py_color; float duration = 0; float thickness = 0; UWorld *world = ue_get_uworld(self); if (!world) return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject"); if (!PyArg_ParseTuple(args, "OOO|ff:draw_debug_line", &py_obj_start, &py_obj_end, &py_color, &duration, &thickness)) { return NULL; } ue_PyFVector *start = py_ue_is_fvector(py_obj_start); ue_PyFVector *end = py_ue_is_fvector(py_obj_end); if (!start || !end) return PyErr_Format(PyExc_Exception, "start and end location must be vectors"); ue_PyFLinearColor *py_linear_color = py_ue_is_flinearcolor(py_color); if (!py_linear_color) return PyErr_Format(PyExc_Exception, "argument is not a FLinearColor"); UKismetSystemLibrary::DrawDebugLine(world, start->vec, end->vec, py_linear_color->color, duration, thickness); Py_RETURN_NONE; }
PyObject *py_ue_input_axis(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *py_fkey; float delta; float delta_time; int num_samples = 1; PyObject *py_gamepad = nullptr; int controller_id = 0; if (!PyArg_ParseTuple(args, "Off|iO:input_axis", &py_fkey, &delta, &delta_time, &num_samples, &py_gamepad)) { return nullptr;; } APlayerController *controller = ue_py_check_type<APlayerController>(self); if (!controller) return PyErr_Format(PyExc_Exception, "object is not a APlayerController"); FKey *key = ue_py_check_struct<FKey>(py_fkey); if (!key) return PyErr_Format(PyExc_Exception, "argument is not a FKey"); if (controller->InputAxis(*key, delta, delta_time, num_samples, py_gamepad && PyObject_IsTrue(py_gamepad))) { Py_RETURN_TRUE; } Py_RETURN_FALSE; }
PyObject *py_ue_enable_mouse_over_events(ue_PyUObject * self, PyObject * args) { ue_py_check(self); bool enabled = true; PyObject *is_true = NULL; int controller_id = 0; if (!PyArg_ParseTuple(args, "|Oi:enable_mouse_over_events", &is_true, &controller_id)) { return NULL; } if (is_true && !PyObject_IsTrue(is_true)) enabled = false; UWorld *world = ue_get_uworld(self); if (!world) return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject"); APlayerController *controller = UGameplayStatics::GetPlayerController(world, controller_id); if (controller) controller->bEnableMouseOverEvents = enabled; Py_INCREF(Py_None); return Py_None; }
PyObject *py_ue_get_world_location_at_distance_along_spline(ue_PyUObject * self, PyObject * args) { ue_py_check(self); float distance = 0; if (!PyArg_ParseTuple(args, "f:get_world_location_at_distance_along_spline", &distance)) { return NULL; } USplineComponent *spline = nullptr; if (self->ue_object->IsA<USplineComponent>()) { spline = (USplineComponent *)self->ue_object; } else { return PyErr_Format(PyExc_Exception, "uobject is not a USplineComponent"); } if (!spline) { return PyErr_Format(PyExc_Exception, "unable to get spline object"); } FVector location = spline->GetWorldLocationAtDistanceAlongSpline(distance); return py_ue_new_fvector(location); }
PyObject *py_ue_get_input_axis(ue_PyUObject *self, PyObject * args) { ue_py_check(self); char *axis_name; if (!PyArg_ParseTuple(args, "s:get_input_axis", &axis_name)) { return NULL; } UInputComponent *input = nullptr; if (self->ue_object->IsA<AActor>()) { input = ((AActor *)self->ue_object)->InputComponent; } else if (self->ue_object->IsA<UActorComponent>()) { input = ((UActorComponent *)self->ue_object)->GetOwner()->InputComponent; } else { return PyErr_Format(PyExc_Exception, "uobject is not an actor or a component"); } if (!input) { return PyErr_Format(PyExc_Exception, "no input manager for this uobject"); } return Py_BuildValue("f", input->GetAxisValue(FName(UTF8_TO_TCHAR(axis_name)))); }
PyObject *py_ue_actor_has_tag(ue_PyUObject * self, PyObject * args) { ue_py_check(self); char *tag; if (!PyArg_ParseTuple(args, "s:actor_has_tag", &tag)) { return NULL; } if (!self->ue_object->IsA<AActor>()) { return PyErr_Format(PyExc_Exception, "uobject is not an AActor"); } AActor *actor = (AActor *)self->ue_object; if (actor->ActorHasTag(FName(UTF8_TO_TCHAR(tag)))) { Py_INCREF(Py_True); return Py_True; } Py_INCREF(Py_False); return Py_False; }
PyObject *py_ue_set_blend_parameter(ue_PyUObject * self, PyObject * args) { ue_py_check(self); int index; PyObject *py_blend; if (!PyArg_ParseTuple(args, "iO:get_blend_parameter", &index, &py_blend)) return nullptr; UBlendSpaceBase *blend = ue_py_check_type<UBlendSpaceBase>(self); if (!blend) return PyErr_Format(PyExc_Exception, "UObject is not a UBlendSpaceBase."); if (index < 0 || index > 2) return PyErr_Format(PyExc_Exception, "invalid Blend Parameter index"); FBlendParameter *parameter = ue_py_check_struct<FBlendParameter>(py_blend); if (!parameter) return PyErr_Format(PyExc_Exception, "argument is not a FBlendParameter"); const FBlendParameter & orig_parameter = blend->GetBlendParameter(index); FMemory::Memcpy((uint8 *)&orig_parameter, parameter, FBlendParameter::StaticStruct()->GetStructureSize()); Py_RETURN_NONE; }
PyObject *py_ue_set_skeletal_mesh(ue_PyUObject *self, PyObject * args) { ue_py_check(self); PyObject *py_skeletal_mesh; PyObject *py_reinit_pose = nullptr; if (!PyArg_ParseTuple(args, "O|O:set_skeletal_mesh", &py_skeletal_mesh, &py_reinit_pose)) return nullptr; USkinnedMeshComponent *component = ue_py_check_type<USkinnedMeshComponent>(self); if (!component) return PyErr_Format(PyExc_Exception, "uobject is not a USkeletalMeshComponent"); USkeletalMesh *mesh = ue_py_check_type<USkeletalMesh>(py_skeletal_mesh); if (!mesh) return PyErr_Format(PyExc_Exception, "argument is not a USkeletalMesh"); bool reinit_pose = true; if (py_reinit_pose && !PyObject_IsTrue(py_reinit_pose)) reinit_pose = false; component->SetSkeletalMesh(mesh, reinit_pose); Py_RETURN_NONE; }
PyObject *py_ue_skeletal_mesh_set_skeleton(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *py_skeleton; if (!PyArg_ParseTuple(args, "O:skeletal_mesh_set_skeleton", &py_skeleton)) return nullptr; USkeletalMesh *mesh = ue_py_check_type<USkeletalMesh>(self); if (!mesh) return PyErr_Format(PyExc_Exception, "UObject is not a USkeletalMesh."); USkeleton *skeleton = ue_py_check_type<USkeleton>(py_skeleton); if (!skeleton) return PyErr_Format(PyExc_Exception, "argument is not a USkeleton."); mesh->ReleaseResources(); mesh->ReleaseResourcesFence.Wait(); mesh->Skeleton = skeleton; mesh->RefSkeleton = skeleton->GetReferenceSkeleton(); mesh->RefBasesInvMatrix.Empty(); mesh->CalculateInvRefMatrices(); #if WITH_EDITOR mesh->PostEditChange(); #endif mesh->InitResources(); mesh->MarkPackageDirty(); Py_RETURN_NONE; }
PyObject *py_ue_skeletal_mesh_register_morph_target(ue_PyUObject *self, PyObject * args) { ue_py_check(self); PyObject *py_morph; if (!PyArg_ParseTuple(args, "O:skeletal_mesh_register_morph_target", &py_morph)) { return nullptr; } USkeletalMesh *mesh = ue_py_check_type<USkeletalMesh>(self); if (!mesh) return PyErr_Format(PyExc_Exception, "uobject is not a SkeletalMesh"); UMorphTarget *morph = ue_py_check_type<UMorphTarget>(py_morph); if (!morph) return PyErr_Format(PyExc_Exception, "argument is not a MorphTarget"); #if ENGINE_MINOR_VERSION > 16 if (!morph->HasValidData()) return PyErr_Format(PyExc_Exception, "the MorphTarget has no valid data"); #endif mesh->PreEditChange(nullptr); mesh->RegisterMorphTarget(morph); mesh->PostEditChange(); mesh->MarkPackageDirty(); Py_RETURN_NONE; }
PyObject *py_ue_morph_target_get_deltas(ue_PyUObject *self, PyObject * args) { ue_py_check(self); int lod_index = 0; if (!PyArg_ParseTuple(args, "|i:morph_target_get_deltas", &lod_index)) { return nullptr; } UMorphTarget *morph = ue_py_check_type<UMorphTarget>(self); if (!morph) return PyErr_Format(PyExc_Exception, "uobject is not a MorphTarget"); if (lod_index < 0 || lod_index > morph->MorphLODModels.Num()) return PyErr_Format(PyExc_Exception, "invalid LOD index"); PyObject *py_list = PyList_New(0); for (FMorphTargetDelta delta : morph->MorphLODModels[lod_index].Vertices) { PyList_Append(py_list, py_ue_new_fmorph_target_delta(delta)); } return py_list; }
PyObject *py_ue_get_player_pawn(ue_PyUObject *self, PyObject * args) { ue_py_check(self); int controller_id = 0; if (!PyArg_ParseTuple(args, "|i:get_player_pawn", &controller_id)) { return NULL; } UWorld *world = ue_get_uworld(self); if (!world) return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject"); APlayerController *controller = UGameplayStatics::GetPlayerController(world, controller_id); if (!controller) return PyErr_Format(PyExc_Exception, "unable to retrieve controller %d", controller_id); // the controller could not have a pawn if (!controller->GetPawn()) Py_RETURN_NONE; Py_RETURN_UOBJECT(controller->GetPawn()); }
PyObject *py_ue_get_actor_component(ue_PyUObject * self, PyObject * args) { ue_py_check(self); AActor *actor = ue_get_actor(self); if (!actor) return PyErr_Format(PyExc_Exception, "cannot retrieve Actor from uobject"); char *name; if (!PyArg_ParseTuple(args, "s:get_actor_component", &name)) { return NULL; } for (UActorComponent *component : actor->GetComponents()) { if (component->GetName().Equals(UTF8_TO_TCHAR(name))) { ue_PyUObject *py_obj = ue_get_python_wrapper(component); if (!py_obj) return PyErr_Format(PyExc_Exception, "PyUObject is in invalid state"); Py_INCREF(py_obj); return (PyObject *)py_obj; } } Py_INCREF(Py_None); return Py_None; }
PyObject *py_ue_input_key(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *py_fkey; int event_type; float amount = 0.0; PyObject *py_gamepad = nullptr; int controller_id = 0; if (!PyArg_ParseTuple(args, "Oi|fO:input_key", &py_fkey, &event_type, &amount, &py_gamepad)) { return nullptr;; } APlayerController *controller = ue_py_check_type<APlayerController>(self); if (!controller) return PyErr_Format(PyExc_Exception, "object is not a APlayerController"); FKey *key = ue_py_check_struct<FKey>(py_fkey); if (!key) return PyErr_Format(PyExc_Exception, "argument is not a FKey"); if (controller->InputKey(*key, (EInputEvent)event_type, amount, py_gamepad && PyObject_IsTrue(py_gamepad))) { Py_RETURN_TRUE; } Py_RETURN_FALSE; }
PyObject *py_ue_morph_target_populate_deltas(ue_PyUObject *self, PyObject * args) { ue_py_check(self); PyObject *py_deltas; int lod_index = 0; if (!PyArg_ParseTuple(args, "O|i:morph_target_populate_deltas", &py_deltas, &lod_index)) { return nullptr; } UMorphTarget *morph = ue_py_check_type<UMorphTarget>(self); if (!morph) return PyErr_Format(PyExc_Exception, "uobject is not a MorphTarget"); if (lod_index < 0) return PyErr_Format(PyExc_Exception, "invalid LOD index"); PyObject *py_iter = PyObject_GetIter(py_deltas); if (!py_iter) return PyErr_Format(PyExc_Exception, "argument is not an iterable of FMorphTargetDelta"); TArray<FMorphTargetDelta> deltas; while (PyObject *py_item = PyIter_Next(py_iter)) { ue_PyFMorphTargetDelta *py_delta = py_ue_is_fmorph_target_delta(py_item); if (!py_delta) { Py_DECREF(py_iter); return PyErr_Format(PyExc_Exception, "argument is not an iterable of FMorphTargetDelta"); } deltas.Add(py_delta->morph_target_delta); } Py_DECREF(py_iter); #if ENGINE_MINOR_VERSION < 19 morph->PopulateDeltas(deltas, lod_index); #else FSkeletalMeshModel *model = morph->BaseSkelMesh->GetImportedModel(); morph->PopulateDeltas(deltas, lod_index, model->LODModels[lod_index].Sections); #endif #if ENGINE_MINOR_VERSION > 16 if (morph->HasValidData()) { Py_RETURN_TRUE; } Py_RETURN_FALSE; #else Py_RETURN_TRUE; #endif }
PyObject *py_ue_bind_released_key(ue_PyUObject *self, PyObject * args) { ue_py_check(self); char *key_name; PyObject *py_callable; if (!PyArg_ParseTuple(args, "sO:bind_released_key", &key_name, &py_callable)) { return NULL; } return py_ue_bind_key(self, Py_BuildValue("siO", key_name, EInputEvent::IE_Released, py_callable)); }
PyObject *py_ue_skeleton_bones_get_num(ue_PyUObject *self, PyObject * args) { ue_py_check(self); USkeleton *skeleton = ue_py_check_type<USkeleton>(self); if (!skeleton) return PyErr_Format(PyExc_Exception, "uobject is not a USkeleton"); return PyLong_FromLong(skeleton->GetReferenceSkeleton().GetNum()); }
PyObject *py_ue_actor_has_component_of_type(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *obj; if (!PyArg_ParseTuple(args, "O:actor_has_component_of_type", &obj)) { return NULL; } if (!ue_is_pyuobject(obj)) { return PyErr_Format(PyExc_Exception, "argument is not a UObject"); } ue_PyUObject *py_obj = (ue_PyUObject *)obj; if (!self->ue_object->IsA<AActor>()) { return PyErr_Format(PyExc_Exception, "uobject is not an AActor"); } AActor *actor = (AActor *)self->ue_object; if (actor->GetComponentByClass((UClass *)py_obj->ue_object)) { Py_INCREF(Py_True); return Py_True; } Py_INCREF(Py_False); return Py_False; }
PyObject *py_ue_actor_spawn(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *py_obj_location = nullptr; PyObject *py_obj_rotation = nullptr; UWorld *world = ue_get_uworld(self); if (!world) return PyErr_Format(PyExc_Exception, "unable to retrieve UWorld from uobject"); PyObject *obj; if (!PyArg_ParseTuple(args, "O|OO:actor_spawn", &obj, &py_obj_location, &py_obj_rotation)) { return NULL; } if (!ue_is_pyuobject(obj)) { return PyErr_Format(PyExc_Exception, "argument is not a UObject"); } ue_PyUObject *py_obj = (ue_PyUObject *)obj; if (!py_obj->ue_object->IsA<UClass>()) { return PyErr_Format(PyExc_Exception, "argument is not a UClass derived from AActor"); } UClass *u_class = (UClass *)py_obj->ue_object; if (!u_class->IsChildOf<AActor>()) { return PyErr_Format(PyExc_Exception, "argument is not a UClass derived from AActor"); } FVector location = FVector(0, 0, 0); FRotator rotation = FRotator(0, 0, 0); if (py_obj_location) { ue_PyFVector *py_location = py_ue_is_fvector(py_obj_location); if (!py_location) return PyErr_Format(PyExc_Exception, "location must be an FVector"); location = py_location->vec; } if (py_obj_rotation) { ue_PyFRotator *py_rotation = py_ue_is_frotator(py_obj_rotation); if (!py_rotation) return PyErr_Format(PyExc_Exception, "location must be an FRotator"); rotation = py_rotation->rot; } AActor *actor = world->SpawnActor((UClass *)py_obj->ue_object, &location, &rotation); PyObject *ret = (PyObject *)ue_get_python_wrapper(actor); if (!ret) return PyErr_Format(PyExc_Exception, "uobject is in invalid state"); Py_INCREF(ret); return ret; }