Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b485cdb
Fix inspector row height and hide layer ID column
enkei64 Jul 8, 2025
bdb1a30
Use new sliders
enkei64 Jul 8, 2025
13ff60e
GUI update
enkei64 Jul 8, 2025
7e3fd7c
Seperate position and bound boxes
enkei64 Jul 8, 2025
065f9b6
Seperate commit and bound boxes
enkei64 Jul 8, 2025
4d96d98
Revert "Seperate commit and bound boxes"
enkei64 Jul 8, 2025
39906b3
geometryFlipped fix
enkei64 Jul 8, 2025
252460b
Load images in assets folder
enkei64 Jul 8, 2025
3c9d2d2
reset app
enkei64 Jul 8, 2025
5a91806
better restart
enkei64 Jul 8, 2025
cd35899
anchor point fix!!!!
enkei64 Jul 9, 2025
b5e5742
Add layer theme fix, language not updating immediately
enkei64 Jul 9, 2025
84e2641
scale updates properly
enkei64 Jul 9, 2025
d60d4ab
Handles easier to drag
enkei64 Jul 10, 2025
8d3a5f4
text layer fix
enkei64 Jul 10, 2025
95d46cc
Correct indentation .caml files
enkei64 Jul 10, 2025
573accf
Discord RPC
enkei64 Jul 10, 2025
46abb81
Appearance and UI tab merged
enkei64 Jul 10, 2025
d962421
Position and bound handles fix (finally)
enkei64 Jul 10, 2025
3785f0a
Remove open file button, new message when nothing is selected in the …
enkei64 Jul 10, 2025
f37747a
Keyboard shortcuts update
enkei64 Jul 11, 2025
5351d79
fix bug found by glixed
retronbv Jul 16, 2025
17e7b40
New icon files
enkei64 Aug 5, 2025
063125d
README improvement
enkei64 Aug 12, 2025
0e20fd0
README fix
enkei64 Aug 12, 2025
6d3a11a
README new image
enkei64 Aug 12, 2025
33415d0
Merge branch 'main' into v0.0.4-B1A
enkei64 Aug 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 47 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,64 @@
<h3>A collection of scripts to edit .ca files, all connected through a GUI powered by hope, dreams, and a bit of code.</h3>

<h4>Website: https://openposter.pages.dev/</h4>
<h4>Discord Server (500+ members): https://discord.gg/t3abQJjHm6</h4>
</div>

<!-- back to normal markdown we go -->
## Building
## Getting Started

Install requirements:
````pip3 install -r requirements.txt````
### Prerequisites

To build the OpenPoster app:
```python3 app.py```
Before you begin, ensure you have the following:

- Computer running MacOS, Windows 10/11, or Linux
- [Python](https://www.python.org/downloads/release/python-3119/) (3.11 recommended)

### Setup

1. Fork the repository
2. Clone your fork locally
3. Install requirements:
```
# MacOS:
pip3 install -r requirements.txt

# Windows:
pip install -r requirements.txt
```
4. Run the OpenPoster app:
```
# MacOS:
python3 app.py

# Windows:
python app.py
```
### Compiling:
```
# MacOS:
python3 compile.py

# Windows:
python compile.py
```

## Features

### Inspector
You can just read or edit in the inspector.
**Inspector:**
You can read and edit in the inspector for the layers, such as the name, position, bounds, color, and more.

### Preview
You can see the selected state's layers.
**Canvas:**
You can see supported layers and a preview of what they would look like on your iPhone/iPad once applied. You can also edit the layers in the Canvas such as resizing and rotating layers if you prefer using the Canvas over the Inspector.

### Layers
You can see all the supported layers in the .ca file.
**Layers:**
You can see all the supported layers in the .ca file with the correct file structure. You can also create new basic, text, and image layers.

### Exporting
**Exporting:**
You can save as a new .ca file or a .tendies file, as well as exporting to Nugget directly.

## License
OpenPoster is under the MIT License. You can view it [here.](LICENSE)

## Image
<img width="1527" alt="image" src="https://github.com/user-attachments/assets/2d98df84-6808-4e1d-93d1-13282f42e63c" /><div align="center">
8 changes: 6 additions & 2 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
# when the imposter is sus
# from configparser import ConfigParser
from gui.config_manager import ConfigManager
from PySide6.QtCore import QTranslator
from PySide6.QtCore import QTranslator, QProcess
from PySide6.QtGui import QFileOpenEvent
from gui.welcome import WelcomeWindow
from gui.newfile import NewFileDialog
import os
import os, shutil

class OpenPosterApplication(QtWidgets.QApplication):
def __init__(self, *args, **kwargs):
Expand Down Expand Up @@ -79,6 +79,10 @@ def event(self, event):
if action[0] == "open":
action_type = "open"
break
if action[0] == "reset":
process = QProcess()
process.startDetached(sys.executable, sys.argv)
sys.exit(0)
if action[0] == "new":
newdlg = NewFileDialog()
newdlg.exec()
Expand Down
Binary file added assets/OpenPoster-macOS-Default-1024x1024@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 48 additions & 0 deletions assets/OpenPoster.icon/icon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"fill" : {
"solid" : "extended-gray:1.00000,1.00000"
},
"groups" : [
{
"layers" : [
{
"glass" : false,
"image-name" : "Layer_2-removebg-preview.png",
"name" : "Layer_2-removebg-preview",
"position" : {
"scale" : 2,
"translation-in-points" : [
0,
0
]
}
},
{
"image-name" : "Layer_1-removebg-preview.png",
"name" : "Layer_1-removebg-preview",
"position" : {
"scale" : 2,
"translation-in-points" : [
0,
0
]
}
}
],
"shadow" : {
"kind" : "neutral",
"opacity" : 0.5
},
"translucency" : {
"enabled" : true,
"value" : 0.5
}
}
],
"supported-platforms" : {
"circles" : [
"watchOS"
],
"squares" : "shared"
}
}
34 changes: 32 additions & 2 deletions gui/_assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ def __init__(self):
self.cafilepath = ""
self.cachedImages = {}
self.missing_assets = set()
self.config_dir = os.path.join(os.path.expanduser("~"), ".openposter")
self.assets_cache_dir = os.path.join(self.config_dir, "assets-cache")

if hasattr(sys, '_MEIPASS'):
self.app_base_path = sys._MEIPASS
Expand All @@ -18,12 +20,27 @@ def loadImage(self, src_path):
return None

if src_path in self.cachedImages:
print(f"Found image in memory cache: {src_path}")
return self.cachedImages[src_path]

filename = os.path.basename(src_path)
cache_path = os.path.join(self.assets_cache_dir, filename)
if os.path.exists(cache_path):
print(f"Found image directly in assets cache: {cache_path}")
try:
img = QImage(cache_path)
if not img.isNull():
pixmap = QPixmap.fromImage(img)
self.cachedImages[src_path] = pixmap
return pixmap
except Exception as e:
print(f"Error loading cached image {cache_path}: {e}")

asset_path = self.findAssetPath(src_path)

if not asset_path or not os.path.exists(asset_path):
print(f"Could not find asset: {src_path}")
print(f"Checked in assets cache: {cache_path}")

if not hasattr(self, 'missing_assets'):
self.missing_assets = set()
Expand All @@ -48,7 +65,20 @@ def loadImage(self, src_path):
def findAssetPath(self, src_path):
if not src_path:
return None


if src_path.startswith("assets/"):
filename = os.path.basename(src_path)
cache_path = os.path.join(self.assets_cache_dir, filename)
if os.path.exists(cache_path):
print(f"Found asset in cache directory: {cache_path}")
return cache_path

filename = os.path.basename(src_path)
cache_path = os.path.join(self.assets_cache_dir, filename)
if os.path.exists(cache_path):
print(f"Found asset in cache by basename: {cache_path}")
return cache_path

if src_path.startswith("themes/") or src_path.startswith("icons/") or src_path.startswith("assets/"):
app_level_path = os.path.join(self.app_base_path, src_path)
if os.path.exists(app_level_path):
Expand Down
5 changes: 5 additions & 0 deletions gui/_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ def parseColor(self, color_str) -> QColor:

if color_str.startswith("#"):
return QColor(color_str)
if " " in color_str and all(p.replace(".", "", 1).isdigit() for p in color_str.split()):
parts = color_str.split()
r = int(float(parts[0])); g = int(float(parts[1])); b = int(float(parts[2]))
a = float(parts[3]) if len(parts) == 4 else 1.0
return QColor(r, g, b, int(a * 255))
except:
pass

Expand Down
Loading
Loading