Skip to content

Commit eb1b684

Browse files
committed
Adds Python Commandlet.
1 parent 5470bbe commit eb1b684

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed

Source/UnrealEnginePython/Private/UnrealEnginePython.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@ void FUnrealEnginePythonModule::RunString(char *str) {
117117

118118
void FUnrealEnginePythonModule::RunFile(char *filename) {
119119
FScopePythonGIL gil;
120-
char *full_path = TCHAR_TO_UTF8(*FPaths::Combine(*FPaths::GameContentDir(), UTF8_TO_TCHAR("Scripts"), *FString("/"), UTF8_TO_TCHAR(filename)));
120+
char *full_path = filename;
121+
if (!FPaths::FileExists(filename))
122+
{
123+
full_path = TCHAR_TO_UTF8(*FPaths::Combine(*FPaths::GameContentDir(), UTF8_TO_TCHAR("Scripts"), *FString("/"), UTF8_TO_TCHAR(filename)));
124+
}
121125
FILE *fd = nullptr;
122126

123127
#if PLATFORM_WINDOWS
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#include "UnrealEnginePythonPrivatePCH.h"
2+
#include "PyCommandlet.h"
3+
4+
#include "Regex.h"
5+
6+
UPyCommandlet::UPyCommandlet(const FObjectInitializer& ObjectInitializer)
7+
: Super(ObjectInitializer)
8+
{
9+
LogToConsole = 1;
10+
}
11+
12+
int32 UPyCommandlet::Main(const FString& CommandLine)
13+
{
14+
TArray<FString> Tokens, Switches;
15+
TMap<FString, FString> Params;
16+
ParseCommandLine(*CommandLine, Tokens, Switches, Params);
17+
18+
FString Filepath = Tokens[0];
19+
if (!FPaths::FileExists(*Filepath))
20+
{
21+
UE_LOG(LogPython, Error, TEXT("Python file could not be found: %s"), *Filepath);
22+
return -1;
23+
}
24+
25+
FString RegexString = FString::Printf(TEXT("(?<=%s).*"), *(Filepath.Replace(TEXT("\\"), TEXT("\\\\"))));
26+
const FRegexPattern myPattern(RegexString);
27+
FRegexMatcher myMatcher(myPattern, *CommandLine);
28+
myMatcher.FindNext();
29+
FString PyCommandLine = myMatcher.GetCaptureGroup(0).Trim().TrimTrailing();
30+
31+
TArray<FString> PyArgv = {FString()};
32+
bool escaped = false;
33+
for (int i = 0; i < PyCommandLine.Len(); i++)
34+
{
35+
if(PyCommandLine[i] == ' ')
36+
{
37+
PyArgv.Add(FString());
38+
continue;
39+
}
40+
else if(PyCommandLine[i] == '\"' && !escaped)
41+
{
42+
i++;
43+
while(i < PyCommandLine.Len() && !(PyCommandLine[i] == '"'))
44+
{
45+
PyArgv[PyArgv.Num() - 1].AppendChar(PyCommandLine[i]);
46+
i++;
47+
if (i == PyCommandLine.Len())
48+
{
49+
PyArgv[PyArgv.Num() - 1].InsertAt(0, "\"");
50+
}
51+
}
52+
}
53+
else
54+
{
55+
if (PyCommandLine[i] == '\\')
56+
escaped = true;
57+
else
58+
escaped = false;
59+
PyArgv[PyArgv.Num() - 1].AppendChar(PyCommandLine[i]);
60+
}
61+
}
62+
PyArgv.Insert(Filepath, 0);
63+
64+
#if PY_MAJOR_VERSION >= 3
65+
wchar_t **argv = (**wchar_t)malloc(PyArgv.Num() * sizeof(void*));
66+
#else
67+
char **argv = (char **)malloc(PyArgv.Num() * sizeof(void*));
68+
#endif
69+
70+
for (int i=0; i<PyArgv.Num(); i++)
71+
{
72+
#if PY_MAJOR_VERSION >= 3
73+
argv[i] = (wchar_t*)malloc(PyArgv[i].Len()+1);
74+
wcscpy_s(argv[i], PyArgv[i].Len()+1, *PyArgv[i].ReplaceEscapedCharWithChar());
75+
#else
76+
argv[i] = (char*)malloc(PyArgv[i].Len() + 1);
77+
strcpy_s(argv[i], PyArgv[i].Len()+1, TCHAR_TO_UTF8(*PyArgv[i].ReplaceEscapedCharWithChar()));
78+
#endif
79+
}
80+
81+
PySys_SetArgv(PyArgv.Num(), argv);
82+
83+
FUnrealEnginePythonModule &PythonModule = FModuleManager::GetModuleChecked<FUnrealEnginePythonModule>("UnrealEnginePython");
84+
PythonModule.RunFile(TCHAR_TO_UTF8(*Filepath));
85+
return 0;
86+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
#include "UnrealEd.h"
4+
#include "Core.h"
5+
#include "Commandlets/Commandlet.h"
6+
#include "PyCommandlet.generated.h"
7+
8+
UCLASS()
9+
class UPyCommandlet : public UCommandlet
10+
{
11+
GENERATED_UCLASS_BODY()
12+
virtual int32 Main(const FString& Params) override;
13+
};

0 commit comments

Comments
 (0)