some changes
This commit is contained in:
parent
0f00c634ef
commit
97c59aa96c
@ -57,6 +57,16 @@ void Error_Handler(void);
|
||||
/* USER CODE END EFP */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define DISPLAY_DC_Pin GPIO_PIN_2
|
||||
#define DISPLAY_DC_GPIO_Port GPIOA
|
||||
#define DISPLAY_RES_Pin GPIO_PIN_3
|
||||
#define DISPLAY_RES_GPIO_Port GPIOA
|
||||
#define DISPLAY_CS_Pin GPIO_PIN_4
|
||||
#define DISPLAY_CS_GPIO_Port GPIOA
|
||||
#define TOUCH_IRQ_Pin GPIO_PIN_5
|
||||
#define TOUCH_IRQ_GPIO_Port GPIOB
|
||||
#define TOUCH_CS_Pin GPIO_PIN_6
|
||||
#define TOUCH_CS_GPIO_Port GPIOB
|
||||
|
||||
/* USER CODE BEGIN Private defines */
|
||||
|
||||
|
||||
@ -18,11 +18,11 @@
|
||||
#define ILI9341_SPI_PORT hspi1
|
||||
extern SPI_HandleTypeDef ILI9341_SPI_PORT;
|
||||
|
||||
#define ILI9341_RES_Pin GPIO_PIN_3
|
||||
#define ILI9341_RES_Pin GPIO_PIN_3 //output
|
||||
#define ILI9341_RES_GPIO_Port GPIOA
|
||||
#define ILI9341_CS_Pin GPIO_PIN_4
|
||||
#define ILI9341_CS_Pin GPIO_PIN_4 //output
|
||||
#define ILI9341_CS_GPIO_Port GPIOA
|
||||
#define ILI9341_DC_Pin GPIO_PIN_2
|
||||
#define ILI9341_DC_Pin GPIO_PIN_2 //output
|
||||
#define ILI9341_DC_GPIO_Port GPIOA
|
||||
// default orientation
|
||||
/*
|
||||
|
||||
@ -11,9 +11,9 @@
|
||||
#define ILI9341_TOUCH_SPI_PORT hspi2
|
||||
extern SPI_HandleTypeDef ILI9341_TOUCH_SPI_PORT;
|
||||
|
||||
#define ILI9341_TOUCH_IRQ_Pin GPIO_PIN_5 // Arduino D5
|
||||
#define ILI9341_TOUCH_IRQ_Pin GPIO_PIN_5
|
||||
#define ILI9341_TOUCH_IRQ_GPIO_Port GPIOB
|
||||
#define ILI9341_TOUCH_CS_Pin GPIO_PIN_6 // Arduino D2
|
||||
#define ILI9341_TOUCH_CS_Pin GPIO_PIN_6
|
||||
#define ILI9341_TOUCH_CS_GPIO_Port GPIOB
|
||||
|
||||
// change depending on screen orientation
|
||||
|
||||
154
Core/Src/main.c
154
Core/Src/main.c
@ -57,6 +57,10 @@ const osThreadAttr_t draw_attributes = { .name = "draw", .stack_size = 128 * 4,
|
||||
osThreadId_t reactiongameHandle;
|
||||
const osThreadAttr_t reactiongame_attributes = { .name = "reactiongame",
|
||||
.stack_size = 128 * 4, .priority = (osPriority_t) osPriorityLow, };
|
||||
/* Definitions for gamepicker */
|
||||
osThreadId_t gamepickerHandle;
|
||||
const osThreadAttr_t gamepicker_attributes = { .name = "gamepicker",
|
||||
.stack_size = 128 * 4, .priority = (osPriority_t) osPriorityLow, };
|
||||
/* Definitions for presses */
|
||||
osMessageQueueId_t pressesHandle;
|
||||
const osMessageQueueAttr_t presses_attributes = { .name = "presses" };
|
||||
@ -73,8 +77,9 @@ static void MX_GPIO_Init(void);
|
||||
static void MX_SPI1_Init(void);
|
||||
static void MX_SPI2_Init(void);
|
||||
void StartTouchHist(void *argument);
|
||||
void startdraw(void *argument);
|
||||
void snakegame(void *argument);
|
||||
void startreactiongame(void *argument);
|
||||
void gamepicker_entry(void *argument);
|
||||
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
@ -82,6 +87,7 @@ void startreactiongame(void *argument);
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
#define touchbuffersize 50
|
||||
struct {
|
||||
int x[touchbuffersize];
|
||||
@ -166,6 +172,10 @@ void GameInit() {
|
||||
snake.fruitCordY = rand() % snake.gamesizeheight;
|
||||
snake.playerScore = 0;
|
||||
snake.TailLen = 0;
|
||||
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
|
||||
ILI9341_FillScreen(ILI9341_WHITE);
|
||||
osMutexRelease(displayHandle);
|
||||
}
|
||||
}
|
||||
// Function for updating the game state
|
||||
void UpdateGame() {
|
||||
@ -220,7 +230,7 @@ void UpdateGame() {
|
||||
break;
|
||||
}
|
||||
|
||||
// Checks for snake's collision with the wall (|)
|
||||
// Checks for snake's collision with the wall
|
||||
if (snake.x >= snake.gamesizewidth || snake.x < 0
|
||||
|| snake.y >= snake.gamesizeheight || snake.y < 0)
|
||||
snake.isGameOver = true;
|
||||
@ -241,7 +251,7 @@ void UpdateGame() {
|
||||
if (snake.isGameOver) {
|
||||
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
|
||||
|
||||
if (Flash_Read_HighScore() < snake.playerScore) {
|
||||
if (Flash_Read_HighScore() > snake.playerScore) {
|
||||
char str[50];
|
||||
sprintf(str, "Highscore Remains: %lu", Flash_Read_HighScore());
|
||||
ILI9341_WriteString(320 / 2 - 70, 240 / 2, str, Font_11x18,
|
||||
@ -259,6 +269,7 @@ void UpdateGame() {
|
||||
}
|
||||
}
|
||||
// Function to handle user UserInput
|
||||
int prevpressed;
|
||||
void UserInput() {
|
||||
// Checks if a key is pressed or not
|
||||
|
||||
@ -285,12 +296,26 @@ void UserInput() {
|
||||
}
|
||||
|
||||
// Send the direction to the queue
|
||||
|
||||
if (!prevpressed && ILI9341_TouchPressed()) {
|
||||
osStatus_t status = osMessageQueuePut(pressesHandle, &dir, 0, 0);
|
||||
if (status != osOK) {
|
||||
// Optional: Handle error
|
||||
}
|
||||
}
|
||||
prevpressed = 1;
|
||||
} else {
|
||||
prevpressed = 0;
|
||||
//give illegal coords
|
||||
//if it is already we can skip it
|
||||
if (touchcoord.x[0] != ILI9341_WIDTH) { //is the last buffer coord illegal?
|
||||
for (int i = 0; i < touchbuffersize - 1; i++) {
|
||||
touchcoord.x[i] = touchcoord.x[i + 1];
|
||||
touchcoord.y[i] = touchcoord.y[i + 1];
|
||||
}
|
||||
touchcoord.x[touchbuffersize - 1] = ILI9341_WIDTH;
|
||||
touchcoord.y[touchbuffersize - 1] = ILI9341_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Function for creating the game board & rendering
|
||||
@ -306,8 +331,9 @@ void GameRender() {
|
||||
if (x == snake.x && y == snake.y) {
|
||||
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
|
||||
|
||||
ILI9341_FillRectangle((x * ILI9341_WIDTH) / ILI9341_WIDTH,
|
||||
(y * ILI9341_WIDTH) / ILI9341_WIDTH,
|
||||
ILI9341_FillRectangle(
|
||||
(x * ILI9341_WIDTH) / snake.gamesizewidth,
|
||||
(y * ILI9341_HEIGHT) / snake.gamesizeheight,
|
||||
ILI9341_WIDTH / snake.gamesizewidth,
|
||||
ILI9341_HEIGHT / snake.gamesizeheight,
|
||||
ILI9341_BLACK);
|
||||
@ -317,10 +343,11 @@ void GameRender() {
|
||||
|
||||
//cout << "O";
|
||||
// Creating the sanke's food with '#'
|
||||
else if (x == snake.fruitCordY && y == snake.fruitCordX) {
|
||||
else if (x == snake.fruitCordX && y == snake.fruitCordY) {
|
||||
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
|
||||
ILI9341_FillRectangle((x * ILI9341_WIDTH) / ILI9341_WIDTH,
|
||||
(y * ILI9341_WIDTH) / ILI9341_WIDTH,
|
||||
ILI9341_FillRectangle(
|
||||
(x * ILI9341_WIDTH) / snake.gamesizewidth,
|
||||
(y * ILI9341_HEIGHT) / snake.gamesizeheight,
|
||||
ILI9341_WIDTH / snake.gamesizewidth,
|
||||
ILI9341_HEIGHT / snake.gamesizeheight, ILI9341_RED);
|
||||
osMutexRelease(displayHandle);
|
||||
@ -331,8 +358,9 @@ void GameRender() {
|
||||
// Creating snake's head with 'O'
|
||||
else if (snake.TailX[0] == x && snake.TailY[0] == y) {
|
||||
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
|
||||
ILI9341_FillRectangle((x * ILI9341_WIDTH) / ILI9341_WIDTH,
|
||||
(y * ILI9341_WIDTH) / ILI9341_WIDTH,
|
||||
ILI9341_FillRectangle(
|
||||
(x * ILI9341_WIDTH) / snake.gamesizewidth,
|
||||
(y * ILI9341_HEIGHT) / snake.gamesizeheight,
|
||||
ILI9341_WIDTH / snake.gamesizewidth,
|
||||
ILI9341_HEIGHT / snake.gamesizeheight,
|
||||
ILI9341_GREEN);
|
||||
@ -342,8 +370,9 @@ void GameRender() {
|
||||
} else if (snake.TailPendingDeletionX == x
|
||||
&& snake.TailPendingDeletionY == y) {
|
||||
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
|
||||
ILI9341_FillRectangle((x * ILI9341_WIDTH) / ILI9341_WIDTH,
|
||||
(y * ILI9341_WIDTH) / ILI9341_WIDTH,
|
||||
ILI9341_FillRectangle(
|
||||
(x * ILI9341_WIDTH) / snake.gamesizewidth,
|
||||
(y * ILI9341_HEIGHT) / snake.gamesizeheight,
|
||||
ILI9341_WIDTH / snake.gamesizewidth,
|
||||
ILI9341_HEIGHT / snake.gamesizeheight,
|
||||
ILI9341_WHITE);
|
||||
@ -374,7 +403,7 @@ int main(void) {
|
||||
HAL_Init();
|
||||
|
||||
/* USER CODE BEGIN Init */
|
||||
|
||||
ILI9341_Init();
|
||||
/* USER CODE END Init */
|
||||
|
||||
/* Configure the system clock */
|
||||
@ -423,6 +452,17 @@ int main(void) {
|
||||
touchhistoryHandle = osThreadNew(StartTouchHist, NULL,
|
||||
&touchhistory_attributes);
|
||||
|
||||
/* creation of draw */
|
||||
drawHandle = osThreadNew(snakegame, NULL, &draw_attributes);
|
||||
|
||||
/* creation of reactiongame */
|
||||
reactiongameHandle = osThreadNew(startreactiongame, NULL,
|
||||
&reactiongame_attributes);
|
||||
|
||||
/* creation of gamepicker */
|
||||
gamepickerHandle = osThreadNew(gamepicker_entry, NULL,
|
||||
&gamepicker_attributes);
|
||||
|
||||
/* USER CODE BEGIN RTOS_THREADS */
|
||||
/* add threads, ... */
|
||||
titlescreen();
|
||||
@ -431,7 +471,7 @@ int main(void) {
|
||||
osStatus_t status = osMessageQueueGet(pressesHandle, &dir, NULL,
|
||||
osWaitForever); // blocking
|
||||
if (dir == 'L')
|
||||
drawHandle = osThreadNew(startdraw, NULL, &draw_attributes);
|
||||
drawHandle = osThreadNew(snakegame, NULL, &draw_attributes);
|
||||
if (dir == 'R')
|
||||
reactiongameHandle = osThreadNew(startreactiongame, NULL,
|
||||
&reactiongame_attributes);
|
||||
@ -448,9 +488,7 @@ int main(void) {
|
||||
|
||||
/* Infinite loop */
|
||||
/* USER CODE BEGIN WHILE */
|
||||
uint16_t a, b;
|
||||
ILI9341_TouchGetCoordinates(&a, &b);
|
||||
GameInit();
|
||||
|
||||
while (1) {
|
||||
|
||||
/* USER CODE END WHILE */
|
||||
@ -576,6 +614,7 @@ static void MX_SPI2_Init(void) {
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_GPIO_Init(void) {
|
||||
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
|
||||
/* USER CODE BEGIN MX_GPIO_Init_1 */
|
||||
|
||||
/* USER CODE END MX_GPIO_Init_1 */
|
||||
@ -584,6 +623,33 @@ static void MX_GPIO_Init(void) {
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOA, DISPLAY_DC_Pin | DISPLAY_RES_Pin | DISPLAY_CS_Pin,
|
||||
GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pins : DISPLAY_DC_Pin DISPLAY_RES_Pin DISPLAY_CS_Pin */
|
||||
GPIO_InitStruct.Pin = DISPLAY_DC_Pin | DISPLAY_RES_Pin | DISPLAY_CS_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pin : TOUCH_IRQ_Pin */
|
||||
GPIO_InitStruct.Pin = TOUCH_IRQ_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(TOUCH_IRQ_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pin : TOUCH_CS_Pin */
|
||||
GPIO_InitStruct.Pin = TOUCH_CS_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(TOUCH_CS_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN MX_GPIO_Init_2 */
|
||||
|
||||
/* USER CODE END MX_GPIO_Init_2 */
|
||||
@ -613,27 +679,29 @@ void StartTouchHist(void *argument) {
|
||||
osMutexRelease(displayHandle);
|
||||
}
|
||||
|
||||
osDelay(10);
|
||||
osDelay(1);
|
||||
}
|
||||
/* USER CODE END 5 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Header_startdraw */
|
||||
/* USER CODE BEGIN Header_snakegame */
|
||||
/**
|
||||
* @brief Function implementing the draw thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_startdraw */
|
||||
void startdraw(void *argument) {
|
||||
/* USER CODE BEGIN startdraw */
|
||||
/* USER CODE END Header_snakegame */
|
||||
void snakegame(void *argument) {
|
||||
/* USER CODE BEGIN snakegame */
|
||||
/* Infinite loop */
|
||||
GameInit();
|
||||
for (;;) {
|
||||
osDelay(100);
|
||||
osDelay(200);
|
||||
UpdateGame();
|
||||
GameRender();
|
||||
}
|
||||
/* USER CODE END startdraw */
|
||||
|
||||
/* USER CODE END snakegame */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Header_startreactiongame */
|
||||
@ -692,7 +760,6 @@ void startreactiongame(void *argument) {
|
||||
osMutexRelease(displayHandle);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
osDelay(1000);
|
||||
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
|
||||
@ -708,6 +775,41 @@ void startreactiongame(void *argument) {
|
||||
/* USER CODE END startreactiongame */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Header_gamepicker_entry */
|
||||
/**
|
||||
* @brief Function implementing the gamepicker thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_gamepicker_entry */
|
||||
void gamepicker_entry(void *argument) {
|
||||
/* USER CODE BEGIN gamepicker_entry */
|
||||
/* Infinite loop */
|
||||
for (;;) {
|
||||
osDelay(1);
|
||||
titlescreen(); // Render title screen
|
||||
|
||||
char dir;
|
||||
// Wait for input (blocking)
|
||||
osStatus_t status = osMessageQueueGet(pressesHandle, &dir, NULL,
|
||||
osWaitForever);
|
||||
|
||||
if (status == osOK) {
|
||||
if (dir == 'L') {
|
||||
drawHandle = osThreadNew(snakegame, NULL, &draw_attributes);
|
||||
osThreadExit(); // Game Manager exits or waits for signal to restart
|
||||
} else if (dir == 'R') {
|
||||
reactiongameHandle = osThreadNew(startreactiongame, NULL,
|
||||
&reactiongame_attributes);
|
||||
osThreadExit();
|
||||
} else {
|
||||
// not implemeted
|
||||
}
|
||||
}
|
||||
}
|
||||
/* USER CODE END gamepicker_entry */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Period elapsed callback in non blocking mode
|
||||
* @note This function is called when TIM2 interrupt took place, inside
|
||||
|
||||
@ -6,7 +6,7 @@ FREERTOS.FootprintOK=true
|
||||
FREERTOS.IPParameters=Tasks01,FootprintOK,configUSE_NEWLIB_REENTRANT,Queues01,Mutexes01
|
||||
FREERTOS.Mutexes01=display,Dynamic,NULL,Available
|
||||
FREERTOS.Queues01=presses,16,char,0,Dynamic,NULL,NULL
|
||||
FREERTOS.Tasks01=touchhistory,24,128,StartTouchHist,Default,NULL,Dynamic,NULL,NULL;draw,8,128,startdraw,Default,NULL,Dynamic,NULL,NULL;reactiongame,8,128,startreactiongame,Default,NULL,Dynamic,NULL,NULL
|
||||
FREERTOS.Tasks01=touchhistory,24,128,StartTouchHist,Default,NULL,Dynamic,NULL,NULL;draw,8,128,snakegame,Default,NULL,Dynamic,NULL,NULL;reactiongame,8,128,startreactiongame,Default,NULL,Dynamic,NULL,NULL;gamepicker,8,128,gamepicker_entry,Default,NULL,Dynamic,NULL,NULL
|
||||
FREERTOS.configUSE_NEWLIB_REENTRANT=1
|
||||
File.Version=6
|
||||
GPIO.groupedBy=Group By Peripherals
|
||||
@ -22,20 +22,25 @@ Mcu.IP5=SYS
|
||||
Mcu.IPNb=6
|
||||
Mcu.Name=STM32F401C(B-C)Ux
|
||||
Mcu.Package=UFQFPN48
|
||||
Mcu.Pin0=PA5
|
||||
Mcu.Pin1=PA6
|
||||
Mcu.Pin10=PB4
|
||||
Mcu.Pin11=VP_FREERTOS_VS_CMSIS_V2
|
||||
Mcu.Pin12=VP_SYS_VS_tim2
|
||||
Mcu.Pin2=PA7
|
||||
Mcu.Pin3=PB10
|
||||
Mcu.Pin4=PB14
|
||||
Mcu.Pin5=PB15
|
||||
Mcu.Pin6=PA13
|
||||
Mcu.Pin7=PA14
|
||||
Mcu.Pin8=PA15
|
||||
Mcu.Pin9=PB3
|
||||
Mcu.PinsNb=13
|
||||
Mcu.Pin0=PA2
|
||||
Mcu.Pin1=PA3
|
||||
Mcu.Pin10=PA14
|
||||
Mcu.Pin11=PA15
|
||||
Mcu.Pin12=PB3
|
||||
Mcu.Pin13=PB4
|
||||
Mcu.Pin14=PB5
|
||||
Mcu.Pin15=PB6
|
||||
Mcu.Pin16=VP_FREERTOS_VS_CMSIS_V2
|
||||
Mcu.Pin17=VP_SYS_VS_tim2
|
||||
Mcu.Pin2=PA4
|
||||
Mcu.Pin3=PA5
|
||||
Mcu.Pin4=PA6
|
||||
Mcu.Pin5=PA7
|
||||
Mcu.Pin6=PB10
|
||||
Mcu.Pin7=PB14
|
||||
Mcu.Pin8=PB15
|
||||
Mcu.Pin9=PA13
|
||||
Mcu.PinsNb=18
|
||||
Mcu.ThirdPartyNb=0
|
||||
Mcu.UserConstants=
|
||||
Mcu.UserName=STM32F401CCUx
|
||||
@ -67,6 +72,18 @@ PA14.Signal=SYS_JTCK-SWCLK
|
||||
PA15.Locked=true
|
||||
PA15.Mode=JTAG_5_pins
|
||||
PA15.Signal=SYS_JTDI
|
||||
PA2.GPIOParameters=GPIO_Label
|
||||
PA2.GPIO_Label=DISPLAY_DC
|
||||
PA2.Locked=true
|
||||
PA2.Signal=GPIO_Output
|
||||
PA3.GPIOParameters=GPIO_Label
|
||||
PA3.GPIO_Label=DISPLAY_RES
|
||||
PA3.Locked=true
|
||||
PA3.Signal=GPIO_Output
|
||||
PA4.GPIOParameters=GPIO_Label
|
||||
PA4.GPIO_Label=DISPLAY_CS
|
||||
PA4.Locked=true
|
||||
PA4.Signal=GPIO_Output
|
||||
PA5.Mode=Full_Duplex_Master
|
||||
PA5.Signal=SPI1_SCK
|
||||
PA6.Mode=Full_Duplex_Master
|
||||
@ -85,6 +102,14 @@ PB3.Signal=SYS_JTDO-SWO
|
||||
PB4.Locked=true
|
||||
PB4.Mode=JTAG_5_pins
|
||||
PB4.Signal=SYS_JTRST
|
||||
PB5.GPIOParameters=GPIO_Label
|
||||
PB5.GPIO_Label=TOUCH_IRQ
|
||||
PB5.Locked=true
|
||||
PB5.Signal=GPIO_Input
|
||||
PB6.GPIOParameters=GPIO_Label
|
||||
PB6.GPIO_Label=TOUCH_CS
|
||||
PB6.Locked=true
|
||||
PB6.Signal=GPIO_Output
|
||||
PinOutPanel.RotationAngle=0
|
||||
ProjectManager.AskForMigrate=true
|
||||
ProjectManager.BackupPrevious=false
|
||||
|
||||
Loading…
Reference in New Issue
Block a user