cherry-pick #1: initial Kindred branding + assembly joint fix
Cherry-picked 316d4f4b52 with conflict resolution:
- CMakeLists.txt: merged Kindred version vars with upstream 1.2.0-dev base
- src/Main/*.cpp: applied Kindred branding (banner, copyright, license)
- Resolved add/add conflicts for files already copied in Phase 1
- Includes assembly joint flip overconstrain fix
@@ -48,18 +48,38 @@ if(FREECAD_USE_CCACHE)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(FreeCAD)
|
project(KindredCreate)
|
||||||
|
|
||||||
set(PACKAGE_VERSION_MAJOR "1")
|
# Kindred Create version
|
||||||
set(PACKAGE_VERSION_MINOR "2")
|
set(KINDRED_CREATE_VERSION_MAJOR "0")
|
||||||
set(PACKAGE_VERSION_PATCH "0") # number of patch release (e.g. "4" for the 0.18.4 release)
|
set(KINDRED_CREATE_VERSION_MINOR "1")
|
||||||
|
set(KINDRED_CREATE_VERSION_PATCH "0")
|
||||||
|
set(KINDRED_CREATE_VERSION "${KINDRED_CREATE_VERSION_MAJOR}.${KINDRED_CREATE_VERSION_MINOR}.${KINDRED_CREATE_VERSION_PATCH}")
|
||||||
|
|
||||||
|
# Underlying FreeCAD version
|
||||||
|
set(FREECAD_VERSION_MAJOR "1")
|
||||||
|
set(FREECAD_VERSION_MINOR "2")
|
||||||
|
set(FREECAD_VERSION_PATCH "0")
|
||||||
|
set(FREECAD_VERSION "${FREECAD_VERSION_MAJOR}.${FREECAD_VERSION_MINOR}.${FREECAD_VERSION_PATCH}")
|
||||||
|
|
||||||
|
# Package version (used for build system compatibility)
|
||||||
|
set(PACKAGE_VERSION_MAJOR ${KINDRED_CREATE_VERSION_MAJOR})
|
||||||
|
set(PACKAGE_VERSION_MINOR ${KINDRED_CREATE_VERSION_MINOR})
|
||||||
|
set(PACKAGE_VERSION_PATCH ${KINDRED_CREATE_VERSION_PATCH})
|
||||||
set(PACKAGE_VERSION_SUFFIX "dev") # either "dev" for development snapshot or "" (empty string)
|
set(PACKAGE_VERSION_SUFFIX "dev") # either "dev" for development snapshot or "" (empty string)
|
||||||
set(PACKAGE_BUILD_VERSION "0") # used when the same FreeCAD version will be re-released (for example using an updated LibPack)
|
set(PACKAGE_BUILD_VERSION "0") # used when the same version will be re-released
|
||||||
string(TIMESTAMP PACKAGE_COPYRIGHT_YEAR "%Y")
|
string(TIMESTAMP PACKAGE_COPYRIGHT_YEAR "%Y")
|
||||||
|
|
||||||
set(PACKAGE_VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_PATCH}")
|
set(PACKAGE_VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_PATCH}")
|
||||||
set(PACKAGE_STRING "${PROJECT_NAME} ${PACKAGE_VERSION}")
|
set(PACKAGE_STRING "${PROJECT_NAME} ${PACKAGE_VERSION}")
|
||||||
|
|
||||||
|
# Pass Kindred Create version to compiler
|
||||||
|
add_definitions(-DKINDRED_CREATE_VERSION="${KINDRED_CREATE_VERSION}")
|
||||||
|
add_definitions(-DKINDRED_CREATE_VERSION_MAJOR=${KINDRED_CREATE_VERSION_MAJOR})
|
||||||
|
add_definitions(-DKINDRED_CREATE_VERSION_MINOR=${KINDRED_CREATE_VERSION_MINOR})
|
||||||
|
add_definitions(-DKINDRED_CREATE_VERSION_PATCH=${KINDRED_CREATE_VERSION_PATCH})
|
||||||
|
add_definitions(-DFREECAD_VERSION="${FREECAD_VERSION}")
|
||||||
|
|
||||||
# include local modules
|
# include local modules
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
include(AddFileDependencies)
|
include(AddFileDependencies)
|
||||||
|
|||||||
106
kindred-logo.svg
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="1028"
|
||||||
|
height="1028"
|
||||||
|
viewBox="0 0 271.99167 271.99167"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:version="1.4.2 (2aeb623e1d, 2025-05-12)"
|
||||||
|
sodipodi:docname="kindred-logo.svg"
|
||||||
|
inkscape:export-filename="../3290ed6b/kindred-logo-blue-baack.png"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:zoom="1.036062"
|
||||||
|
inkscape:cx="397.6596"
|
||||||
|
inkscape:cy="478.25323"
|
||||||
|
inkscape:window-width="2494"
|
||||||
|
inkscape:window-height="1371"
|
||||||
|
inkscape:window-x="1146"
|
||||||
|
inkscape:window-y="1112"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:export-bgcolor="#79c0c500">
|
||||||
|
<inkscape:grid
|
||||||
|
type="axonomgrid"
|
||||||
|
id="grid6"
|
||||||
|
units="mm"
|
||||||
|
originx="0"
|
||||||
|
originy="0"
|
||||||
|
spacingx="0.99999998"
|
||||||
|
spacingy="1"
|
||||||
|
empcolor="#0099e5"
|
||||||
|
empopacity="0.30196078"
|
||||||
|
color="#0099e5"
|
||||||
|
opacity="0.14901961"
|
||||||
|
empspacing="5"
|
||||||
|
dotted="false"
|
||||||
|
gridanglex="30"
|
||||||
|
gridanglez="30"
|
||||||
|
enabled="true"
|
||||||
|
visible="true" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 123.49166 : 1"
|
||||||
|
inkscape:vp_y="0 : 999.99998 : 0"
|
||||||
|
inkscape:vp_z="210.00001 : 123.49166 : 1"
|
||||||
|
inkscape:persp3d-origin="105 : 73.991665 : 1"
|
||||||
|
id="perspective1" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#7c4a82;fill-opacity:1;stroke:#12101c;stroke-width:5;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path6-81-5"
|
||||||
|
inkscape:flatsided="true"
|
||||||
|
sodipodi:sides="6"
|
||||||
|
sodipodi:cx="61.574867"
|
||||||
|
sodipodi:cy="103.99491"
|
||||||
|
sodipodi:r1="25.000006"
|
||||||
|
sodipodi:r2="22.404818"
|
||||||
|
sodipodi:arg1="-1.5707963"
|
||||||
|
sodipodi:arg2="-1.0471974"
|
||||||
|
inkscape:rounded="0.77946499"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
d="m 61.574868,78.994905 c 19.486629,10e-7 11.907325,-4.375912 21.65064,12.500004 9.743314,16.875911 9.743314,8.12409 -1e-6,25.000001 -9.743315,16.87592 -2.164011,12.50001 -21.65064,12.50001 -19.486629,0 -11.907326,4.37591 -21.65064,-12.50001 -9.743314,-16.875912 -9.743314,-8.12409 0,-25.000002 9.743315,-16.875916 2.164012,-12.500003 21.650641,-12.500003 z"
|
||||||
|
transform="matrix(1.9704344,0,0,1.8525167,-28.510585,-40.025402)" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#ff9701;fill-opacity:1;stroke:#12101c;stroke-width:5;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path6-81-5-6"
|
||||||
|
inkscape:flatsided="true"
|
||||||
|
sodipodi:sides="6"
|
||||||
|
sodipodi:cx="61.574867"
|
||||||
|
sodipodi:cy="103.99491"
|
||||||
|
sodipodi:r1="25.000006"
|
||||||
|
sodipodi:r2="22.404818"
|
||||||
|
sodipodi:arg1="-1.5707963"
|
||||||
|
sodipodi:arg2="-1.0471974"
|
||||||
|
inkscape:rounded="0.77946499"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
d="m 61.574868,78.994905 c 19.486629,10e-7 11.907325,-4.375912 21.65064,12.500004 9.743314,16.875921 9.743314,8.12409 -1e-6,25.000001 -9.743315,16.87592 -2.164011,12.50001 -21.65064,12.50001 -19.48663,0 -11.907326,4.37591 -21.65064,-12.50001 -9.743314,-16.875913 -9.743315,-8.12409 10e-7,-25.000002 9.743315,-16.875916 2.164011,-12.500003 21.65064,-12.500003 z"
|
||||||
|
transform="matrix(1.9704344,0,0,1.8525167,56.811738,-86.338327)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.0 KiB |
98
resources/branding/generate-icons.sh
Executable file
@@ -0,0 +1,98 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# generate-icons.sh - Generate application icons for Kindred Create
|
||||||
|
#
|
||||||
|
# This script generates icon files for all platforms from the source SVG.
|
||||||
|
# Prerequisites:
|
||||||
|
# - Inkscape (SVG to PNG conversion)
|
||||||
|
# - ImageMagick (ICO generation for Windows)
|
||||||
|
# - png2icns or iconutil (ICNS generation for macOS)
|
||||||
|
#
|
||||||
|
# Usage: ./generate-icons.sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
SVG_SOURCE="$SCRIPT_DIR/kindred-logo.svg"
|
||||||
|
OUTPUT_DIR="$SCRIPT_DIR/../icons"
|
||||||
|
|
||||||
|
# Check for source file
|
||||||
|
if [ ! -f "$SVG_SOURCE" ]; then
|
||||||
|
echo "Error: Source SVG not found at $SVG_SOURCE"
|
||||||
|
echo "Please place kindred-logo.svg in the branding directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for Inkscape
|
||||||
|
if ! command -v inkscape &> /dev/null; then
|
||||||
|
echo "Error: Inkscape is required but not installed."
|
||||||
|
echo "Install with: sudo apt install inkscape (Debian/Ubuntu)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Generating icons from $SVG_SOURCE..."
|
||||||
|
|
||||||
|
# Generate PNGs for Linux/hicolor icon theme
|
||||||
|
for size in 16 24 32 48 64 128 256 512; do
|
||||||
|
dir="$OUTPUT_DIR/hicolor/${size}x${size}/apps"
|
||||||
|
mkdir -p "$dir"
|
||||||
|
echo " Generating ${size}x${size} PNG..."
|
||||||
|
inkscape -w $size -h $size "$SVG_SOURCE" -o "$dir/kindred-create.png" 2>/dev/null
|
||||||
|
done
|
||||||
|
|
||||||
|
# Copy SVG for scalable
|
||||||
|
mkdir -p "$OUTPUT_DIR/hicolor/scalable/apps"
|
||||||
|
cp "$SVG_SOURCE" "$OUTPUT_DIR/hicolor/scalable/apps/kindred-create.svg"
|
||||||
|
echo " Copied scalable SVG"
|
||||||
|
|
||||||
|
# Generate Windows ICO (requires ImageMagick)
|
||||||
|
if command -v convert &> /dev/null; then
|
||||||
|
echo " Generating Windows ICO..."
|
||||||
|
convert \
|
||||||
|
"$OUTPUT_DIR/hicolor/16x16/apps/kindred-create.png" \
|
||||||
|
"$OUTPUT_DIR/hicolor/24x24/apps/kindred-create.png" \
|
||||||
|
"$OUTPUT_DIR/hicolor/32x32/apps/kindred-create.png" \
|
||||||
|
"$OUTPUT_DIR/hicolor/48x48/apps/kindred-create.png" \
|
||||||
|
"$OUTPUT_DIR/hicolor/64x64/apps/kindred-create.png" \
|
||||||
|
"$OUTPUT_DIR/hicolor/128x128/apps/kindred-create.png" \
|
||||||
|
"$OUTPUT_DIR/hicolor/256x256/apps/kindred-create.png" \
|
||||||
|
"$OUTPUT_DIR/kindred-create.ico"
|
||||||
|
echo " Created kindred-create.ico"
|
||||||
|
else
|
||||||
|
echo " Warning: ImageMagick not found, skipping ICO generation."
|
||||||
|
echo " Install with: sudo apt install imagemagick"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate macOS ICNS (requires png2icns or iconutil)
|
||||||
|
if command -v png2icns &> /dev/null; then
|
||||||
|
echo " Generating macOS ICNS..."
|
||||||
|
png2icns "$OUTPUT_DIR/kindred-create.icns" \
|
||||||
|
"$OUTPUT_DIR/hicolor/16x16/apps/kindred-create.png" \
|
||||||
|
"$OUTPUT_DIR/hicolor/32x32/apps/kindred-create.png" \
|
||||||
|
"$OUTPUT_DIR/hicolor/128x128/apps/kindred-create.png" \
|
||||||
|
"$OUTPUT_DIR/hicolor/256x256/apps/kindred-create.png" \
|
||||||
|
"$OUTPUT_DIR/hicolor/512x512/apps/kindred-create.png"
|
||||||
|
echo " Created kindred-create.icns"
|
||||||
|
elif command -v iconutil &> /dev/null; then
|
||||||
|
echo " Generating macOS ICNS using iconutil..."
|
||||||
|
ICONSET_DIR="$OUTPUT_DIR/kindred-create.iconset"
|
||||||
|
mkdir -p "$ICONSET_DIR"
|
||||||
|
cp "$OUTPUT_DIR/hicolor/16x16/apps/kindred-create.png" "$ICONSET_DIR/icon_16x16.png"
|
||||||
|
cp "$OUTPUT_DIR/hicolor/32x32/apps/kindred-create.png" "$ICONSET_DIR/icon_16x16@2x.png"
|
||||||
|
cp "$OUTPUT_DIR/hicolor/32x32/apps/kindred-create.png" "$ICONSET_DIR/icon_32x32.png"
|
||||||
|
cp "$OUTPUT_DIR/hicolor/64x64/apps/kindred-create.png" "$ICONSET_DIR/icon_32x32@2x.png"
|
||||||
|
cp "$OUTPUT_DIR/hicolor/128x128/apps/kindred-create.png" "$ICONSET_DIR/icon_128x128.png"
|
||||||
|
cp "$OUTPUT_DIR/hicolor/256x256/apps/kindred-create.png" "$ICONSET_DIR/icon_128x128@2x.png"
|
||||||
|
cp "$OUTPUT_DIR/hicolor/256x256/apps/kindred-create.png" "$ICONSET_DIR/icon_256x256.png"
|
||||||
|
cp "$OUTPUT_DIR/hicolor/512x512/apps/kindred-create.png" "$ICONSET_DIR/icon_256x256@2x.png"
|
||||||
|
cp "$OUTPUT_DIR/hicolor/512x512/apps/kindred-create.png" "$ICONSET_DIR/icon_512x512.png"
|
||||||
|
iconutil -c icns "$ICONSET_DIR" -o "$OUTPUT_DIR/kindred-create.icns"
|
||||||
|
rm -rf "$ICONSET_DIR"
|
||||||
|
echo " Created kindred-create.icns"
|
||||||
|
else
|
||||||
|
echo " Warning: Neither png2icns nor iconutil found, skipping ICNS generation."
|
||||||
|
echo " Install png2icns with: sudo apt install icnsutils"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Icon generation complete!"
|
||||||
|
echo "Output directory: $OUTPUT_DIR"
|
||||||
214
resources/branding/generate-splash.py
Executable file
@@ -0,0 +1,214 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generate Kindred Create splash screen and about images.
|
||||||
|
|
||||||
|
This script creates branded splash screens with:
|
||||||
|
- Rounded dark rectangle background (Catppuccin Mocha base #1e1e2e)
|
||||||
|
- Kindred logo centered
|
||||||
|
- "Kindred Create" title text
|
||||||
|
- Version string
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
pip install Pillow cairosvg
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python generate-splash.py [--version VERSION] [--freecad-version FREECAD_VERSION]
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
try:
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
except ImportError:
|
||||||
|
print("Error: Pillow is required. Install with: pip install Pillow")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
import cairosvg
|
||||||
|
except ImportError:
|
||||||
|
print("Warning: cairosvg not found. Will try alternative SVG conversion.")
|
||||||
|
cairosvg = None
|
||||||
|
|
||||||
|
# Catppuccin Mocha colors
|
||||||
|
COLORS = {
|
||||||
|
'base': '#1e1e2e',
|
||||||
|
'surface0': '#313244',
|
||||||
|
'text': '#cdd6f4',
|
||||||
|
'subtext0': '#a6adc8',
|
||||||
|
'blue': '#89b4fa',
|
||||||
|
'lavender': '#b4befe',
|
||||||
|
}
|
||||||
|
|
||||||
|
def hex_to_rgb(hex_color):
|
||||||
|
"""Convert hex color to RGB tuple."""
|
||||||
|
hex_color = hex_color.lstrip('#')
|
||||||
|
return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
|
||||||
|
|
||||||
|
def create_rounded_rectangle(draw, bbox, radius, fill):
|
||||||
|
"""Draw a rounded rectangle."""
|
||||||
|
x1, y1, x2, y2 = bbox
|
||||||
|
draw.rounded_rectangle(bbox, radius=radius, fill=fill)
|
||||||
|
|
||||||
|
def load_svg_as_image(svg_path, width, height):
|
||||||
|
"""Load an SVG file and convert to PIL Image at specified size."""
|
||||||
|
if cairosvg:
|
||||||
|
import io
|
||||||
|
png_data = cairosvg.svg2png(url=str(svg_path), output_width=width, output_height=height)
|
||||||
|
return Image.open(io.BytesIO(png_data)).convert('RGBA')
|
||||||
|
else:
|
||||||
|
# Fallback: try using inkscape command line
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp:
|
||||||
|
tmp_path = tmp.name
|
||||||
|
try:
|
||||||
|
subprocess.run([
|
||||||
|
'inkscape', '-w', str(width), '-h', str(height),
|
||||||
|
str(svg_path), '-o', tmp_path
|
||||||
|
], check=True, capture_output=True)
|
||||||
|
img = Image.open(tmp_path).convert('RGBA')
|
||||||
|
return img
|
||||||
|
finally:
|
||||||
|
if os.path.exists(tmp_path):
|
||||||
|
os.unlink(tmp_path)
|
||||||
|
|
||||||
|
def get_font(size, bold=False):
|
||||||
|
"""Get a font, falling back to default if not available."""
|
||||||
|
font_names = [
|
||||||
|
'/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf' if bold else '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf',
|
||||||
|
'/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf' if bold else '/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf',
|
||||||
|
'/usr/share/fonts/TTF/DejaVuSans-Bold.ttf' if bold else '/usr/share/fonts/TTF/DejaVuSans.ttf',
|
||||||
|
]
|
||||||
|
for font_name in font_names:
|
||||||
|
if os.path.exists(font_name):
|
||||||
|
return ImageFont.truetype(font_name, size)
|
||||||
|
# Fallback to default
|
||||||
|
return ImageFont.load_default()
|
||||||
|
|
||||||
|
def create_splash(output_path, logo_path, width, height, version, freecad_version, scale=1):
|
||||||
|
"""Create a splash screen image."""
|
||||||
|
# Scale dimensions
|
||||||
|
w = int(width * scale)
|
||||||
|
h = int(height * scale)
|
||||||
|
radius = int(16 * scale)
|
||||||
|
padding = int(30 * scale)
|
||||||
|
|
||||||
|
# Create image with transparent background
|
||||||
|
img = Image.new('RGBA', (w, h), (0, 0, 0, 0))
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
|
# Draw rounded rectangle background
|
||||||
|
bg_color = hex_to_rgb(COLORS['base'])
|
||||||
|
create_rounded_rectangle(draw, (padding, padding, w - padding, h - padding), radius, bg_color)
|
||||||
|
|
||||||
|
# Load and place logo
|
||||||
|
logo_max_width = int(300 * scale)
|
||||||
|
logo_max_height = int(150 * scale)
|
||||||
|
|
||||||
|
try:
|
||||||
|
logo = load_svg_as_image(logo_path, logo_max_width, logo_max_height)
|
||||||
|
# Center logo horizontally, place in upper portion
|
||||||
|
logo_x = (w - logo.width) // 2
|
||||||
|
logo_y = int(80 * scale)
|
||||||
|
img.paste(logo, (logo_x, logo_y), logo)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning: Could not load logo: {e}")
|
||||||
|
logo_y = int(80 * scale)
|
||||||
|
|
||||||
|
# Draw "Kindred Create" title
|
||||||
|
title_font = get_font(int(24 * scale), bold=True)
|
||||||
|
title = "Kindred Create"
|
||||||
|
title_bbox = draw.textbbox((0, 0), title, font=title_font)
|
||||||
|
title_width = title_bbox[2] - title_bbox[0]
|
||||||
|
title_x = (w - title_width) // 2
|
||||||
|
title_y = int(250 * scale)
|
||||||
|
draw.text((title_x, title_y), title, fill=hex_to_rgb(COLORS['text']), font=title_font)
|
||||||
|
|
||||||
|
# Draw version string
|
||||||
|
version_font = get_font(int(12 * scale))
|
||||||
|
version_str = f"v{version} (FreeCAD {freecad_version})"
|
||||||
|
version_bbox = draw.textbbox((0, 0), version_str, font=version_font)
|
||||||
|
version_width = version_bbox[2] - version_bbox[0]
|
||||||
|
version_x = (w - version_width) // 2
|
||||||
|
version_y = title_y + int(35 * scale)
|
||||||
|
draw.text((version_x, version_y), version_str, fill=hex_to_rgb(COLORS['subtext0']), font=version_font)
|
||||||
|
|
||||||
|
# Save
|
||||||
|
img.save(output_path, 'PNG')
|
||||||
|
print(f"Created: {output_path}")
|
||||||
|
|
||||||
|
def create_about(output_path, logo_path, width, height, scale=1):
|
||||||
|
"""Create an about dialog image."""
|
||||||
|
# Scale dimensions
|
||||||
|
w = int(width * scale)
|
||||||
|
h = int(height * scale)
|
||||||
|
|
||||||
|
# Create image
|
||||||
|
img = Image.new('RGBA', (w, h), hex_to_rgb(COLORS['base']) + (255,))
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
|
# Load and place logo
|
||||||
|
logo_max_width = int(200 * scale)
|
||||||
|
logo_max_height = int(100 * scale)
|
||||||
|
|
||||||
|
try:
|
||||||
|
logo = load_svg_as_image(logo_path, logo_max_width, logo_max_height)
|
||||||
|
logo_x = (w - logo.width) // 2
|
||||||
|
logo_y = int(30 * scale)
|
||||||
|
img.paste(logo, (logo_x, logo_y), logo)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning: Could not load logo: {e}")
|
||||||
|
|
||||||
|
# Save
|
||||||
|
img.save(output_path, 'PNG')
|
||||||
|
print(f"Created: {output_path}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='Generate Kindred Create splash screens')
|
||||||
|
parser.add_argument('--version', default='0.1.0', help='Kindred Create version')
|
||||||
|
parser.add_argument('--freecad-version', default='1.0.0', help='FreeCAD version')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
script_dir = Path(__file__).parent
|
||||||
|
logo_path = script_dir / 'kindred-logo.svg'
|
||||||
|
icons_dir = script_dir.parent.parent / 'src' / 'Gui' / 'Icons'
|
||||||
|
|
||||||
|
if not logo_path.exists():
|
||||||
|
print(f"Error: Logo not found at {logo_path}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Create splash screens (600x400 as per spec)
|
||||||
|
create_splash(
|
||||||
|
icons_dir / 'kindredcreatesplash.png',
|
||||||
|
logo_path,
|
||||||
|
600, 400,
|
||||||
|
args.version,
|
||||||
|
args.freecad_version,
|
||||||
|
scale=1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create 2x version for HiDPI
|
||||||
|
create_splash(
|
||||||
|
icons_dir / 'kindredcreatesplash_2x.png',
|
||||||
|
logo_path,
|
||||||
|
600, 400,
|
||||||
|
args.version,
|
||||||
|
args.freecad_version,
|
||||||
|
scale=2
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create about image
|
||||||
|
create_about(
|
||||||
|
icons_dir / 'kindredcreateabout.png',
|
||||||
|
logo_path,
|
||||||
|
400, 200,
|
||||||
|
scale=1
|
||||||
|
)
|
||||||
|
|
||||||
|
print("\nSplash screen generation complete!")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
106
resources/branding/kindred-logo.svg
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="1028"
|
||||||
|
height="1028"
|
||||||
|
viewBox="0 0 271.99167 271.99167"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:version="1.4.2 (2aeb623e1d, 2025-05-12)"
|
||||||
|
sodipodi:docname="kindred-logo.svg"
|
||||||
|
inkscape:export-filename="../3290ed6b/kindred-logo-blue-baack.png"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:zoom="1.036062"
|
||||||
|
inkscape:cx="397.6596"
|
||||||
|
inkscape:cy="478.25323"
|
||||||
|
inkscape:window-width="2494"
|
||||||
|
inkscape:window-height="1371"
|
||||||
|
inkscape:window-x="1146"
|
||||||
|
inkscape:window-y="1112"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:export-bgcolor="#79c0c500">
|
||||||
|
<inkscape:grid
|
||||||
|
type="axonomgrid"
|
||||||
|
id="grid6"
|
||||||
|
units="mm"
|
||||||
|
originx="0"
|
||||||
|
originy="0"
|
||||||
|
spacingx="0.99999998"
|
||||||
|
spacingy="1"
|
||||||
|
empcolor="#0099e5"
|
||||||
|
empopacity="0.30196078"
|
||||||
|
color="#0099e5"
|
||||||
|
opacity="0.14901961"
|
||||||
|
empspacing="5"
|
||||||
|
dotted="false"
|
||||||
|
gridanglex="30"
|
||||||
|
gridanglez="30"
|
||||||
|
enabled="true"
|
||||||
|
visible="true" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 123.49166 : 1"
|
||||||
|
inkscape:vp_y="0 : 999.99998 : 0"
|
||||||
|
inkscape:vp_z="210.00001 : 123.49166 : 1"
|
||||||
|
inkscape:persp3d-origin="105 : 73.991665 : 1"
|
||||||
|
id="perspective1" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#7c4a82;fill-opacity:1;stroke:#12101c;stroke-width:5;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path6-81-5"
|
||||||
|
inkscape:flatsided="true"
|
||||||
|
sodipodi:sides="6"
|
||||||
|
sodipodi:cx="61.574867"
|
||||||
|
sodipodi:cy="103.99491"
|
||||||
|
sodipodi:r1="25.000006"
|
||||||
|
sodipodi:r2="22.404818"
|
||||||
|
sodipodi:arg1="-1.5707963"
|
||||||
|
sodipodi:arg2="-1.0471974"
|
||||||
|
inkscape:rounded="0.77946499"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
d="m 61.574868,78.994905 c 19.486629,10e-7 11.907325,-4.375912 21.65064,12.500004 9.743314,16.875911 9.743314,8.12409 -1e-6,25.000001 -9.743315,16.87592 -2.164011,12.50001 -21.65064,12.50001 -19.486629,0 -11.907326,4.37591 -21.65064,-12.50001 -9.743314,-16.875912 -9.743314,-8.12409 0,-25.000002 9.743315,-16.875916 2.164012,-12.500003 21.650641,-12.500003 z"
|
||||||
|
transform="matrix(1.9704344,0,0,1.8525167,-28.510585,-40.025402)" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#ff9701;fill-opacity:1;stroke:#12101c;stroke-width:5;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path6-81-5-6"
|
||||||
|
inkscape:flatsided="true"
|
||||||
|
sodipodi:sides="6"
|
||||||
|
sodipodi:cx="61.574867"
|
||||||
|
sodipodi:cy="103.99491"
|
||||||
|
sodipodi:r1="25.000006"
|
||||||
|
sodipodi:r2="22.404818"
|
||||||
|
sodipodi:arg1="-1.5707963"
|
||||||
|
sodipodi:arg2="-1.0471974"
|
||||||
|
inkscape:rounded="0.77946499"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
d="m 61.574868,78.994905 c 19.486629,10e-7 11.907325,-4.375912 21.65064,12.500004 9.743314,16.875921 9.743314,8.12409 -1e-6,25.000001 -9.743315,16.87592 -2.164011,12.50001 -21.65064,12.50001 -19.48663,0 -11.907326,4.37591 -21.65064,-12.50001 -9.743314,-16.875913 -9.743315,-8.12409 10e-7,-25.000002 9.743315,-16.875916 2.164011,-12.500003 21.65064,-12.500003 z"
|
||||||
|
transform="matrix(1.9704344,0,0,1.8525167,56.811738,-86.338327)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.0 KiB |
BIN
resources/icons/hicolor/128x128/apps/kindred-create.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
resources/icons/hicolor/16x16/apps/kindred-create.png
Normal file
|
After Width: | Height: | Size: 491 B |
BIN
resources/icons/hicolor/24x24/apps/kindred-create.png
Normal file
|
After Width: | Height: | Size: 721 B |
BIN
resources/icons/hicolor/256x256/apps/kindred-create.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
resources/icons/hicolor/32x32/apps/kindred-create.png
Normal file
|
After Width: | Height: | Size: 982 B |
BIN
resources/icons/hicolor/48x48/apps/kindred-create.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
resources/icons/hicolor/512x512/apps/kindred-create.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
resources/icons/hicolor/64x64/apps/kindred-create.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
106
resources/icons/hicolor/scalable/apps/kindred-create.svg
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="1028"
|
||||||
|
height="1028"
|
||||||
|
viewBox="0 0 271.99167 271.99167"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:version="1.4.2 (2aeb623e1d, 2025-05-12)"
|
||||||
|
sodipodi:docname="kindred-logo.svg"
|
||||||
|
inkscape:export-filename="../3290ed6b/kindred-logo-blue-baack.png"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:zoom="1.036062"
|
||||||
|
inkscape:cx="397.6596"
|
||||||
|
inkscape:cy="478.25323"
|
||||||
|
inkscape:window-width="2494"
|
||||||
|
inkscape:window-height="1371"
|
||||||
|
inkscape:window-x="1146"
|
||||||
|
inkscape:window-y="1112"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:export-bgcolor="#79c0c500">
|
||||||
|
<inkscape:grid
|
||||||
|
type="axonomgrid"
|
||||||
|
id="grid6"
|
||||||
|
units="mm"
|
||||||
|
originx="0"
|
||||||
|
originy="0"
|
||||||
|
spacingx="0.99999998"
|
||||||
|
spacingy="1"
|
||||||
|
empcolor="#0099e5"
|
||||||
|
empopacity="0.30196078"
|
||||||
|
color="#0099e5"
|
||||||
|
opacity="0.14901961"
|
||||||
|
empspacing="5"
|
||||||
|
dotted="false"
|
||||||
|
gridanglex="30"
|
||||||
|
gridanglez="30"
|
||||||
|
enabled="true"
|
||||||
|
visible="true" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 123.49166 : 1"
|
||||||
|
inkscape:vp_y="0 : 999.99998 : 0"
|
||||||
|
inkscape:vp_z="210.00001 : 123.49166 : 1"
|
||||||
|
inkscape:persp3d-origin="105 : 73.991665 : 1"
|
||||||
|
id="perspective1" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#7c4a82;fill-opacity:1;stroke:#12101c;stroke-width:5;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path6-81-5"
|
||||||
|
inkscape:flatsided="true"
|
||||||
|
sodipodi:sides="6"
|
||||||
|
sodipodi:cx="61.574867"
|
||||||
|
sodipodi:cy="103.99491"
|
||||||
|
sodipodi:r1="25.000006"
|
||||||
|
sodipodi:r2="22.404818"
|
||||||
|
sodipodi:arg1="-1.5707963"
|
||||||
|
sodipodi:arg2="-1.0471974"
|
||||||
|
inkscape:rounded="0.77946499"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
d="m 61.574868,78.994905 c 19.486629,10e-7 11.907325,-4.375912 21.65064,12.500004 9.743314,16.875911 9.743314,8.12409 -1e-6,25.000001 -9.743315,16.87592 -2.164011,12.50001 -21.65064,12.50001 -19.486629,0 -11.907326,4.37591 -21.65064,-12.50001 -9.743314,-16.875912 -9.743314,-8.12409 0,-25.000002 9.743315,-16.875916 2.164012,-12.500003 21.650641,-12.500003 z"
|
||||||
|
transform="matrix(1.9704344,0,0,1.8525167,-28.510585,-40.025402)" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#ff9701;fill-opacity:1;stroke:#12101c;stroke-width:5;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path6-81-5-6"
|
||||||
|
inkscape:flatsided="true"
|
||||||
|
sodipodi:sides="6"
|
||||||
|
sodipodi:cx="61.574867"
|
||||||
|
sodipodi:cy="103.99491"
|
||||||
|
sodipodi:r1="25.000006"
|
||||||
|
sodipodi:r2="22.404818"
|
||||||
|
sodipodi:arg1="-1.5707963"
|
||||||
|
sodipodi:arg2="-1.0471974"
|
||||||
|
inkscape:rounded="0.77946499"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
d="m 61.574868,78.994905 c 19.486629,10e-7 11.907325,-4.375912 21.65064,12.500004 9.743314,16.875921 9.743314,8.12409 -1e-6,25.000001 -9.743315,16.87592 -2.164011,12.50001 -21.65064,12.50001 -19.48663,0 -11.907326,4.37591 -21.65064,-12.50001 -9.743314,-16.875913 -9.743315,-8.12409 10e-7,-25.000002 9.743315,-16.875916 2.164011,-12.500003 21.65064,-12.500003 z"
|
||||||
|
transform="matrix(1.9704344,0,0,1.8525167,56.811738,-86.338327)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.0 KiB |
BIN
resources/icons/kindred-create.icns
Normal file
BIN
resources/icons/kindred-create.ico
Normal file
|
After Width: | Height: | Size: 107 KiB |
109
resources/preferences/KindredCreate/KindredCreate.cfg
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<FCParameters>
|
||||||
|
<FCParamGroup Name="Root">
|
||||||
|
<FCParamGroup Name="BaseApp">
|
||||||
|
<FCParamGroup Name="Preferences">
|
||||||
|
<FCParamGroup Name="Editor">
|
||||||
|
<FCUInt Name="Text" Value="3453416703"/>
|
||||||
|
<FCUInt Name="Bookmark" Value="3032415999"/>
|
||||||
|
<FCUInt Name="Breakpoint" Value="4086016255"/>
|
||||||
|
<FCUInt Name="Keyword" Value="3416717311"/>
|
||||||
|
<FCUInt Name="Comment" Value="2139095295"/>
|
||||||
|
<FCUInt Name="Block comment" Value="2139095295"/>
|
||||||
|
<FCUInt Name="Number" Value="4206069759"/>
|
||||||
|
<FCUInt Name="String" Value="2799935999"/>
|
||||||
|
<FCUInt Name="Character" Value="4073902335"/>
|
||||||
|
<FCUInt Name="Class name" Value="2310339327"/>
|
||||||
|
<FCUInt Name="Define name" Value="2310339327"/>
|
||||||
|
<FCUInt Name="Operator" Value="2312199935"/>
|
||||||
|
<FCUInt Name="Python output" Value="2796290303"/>
|
||||||
|
<FCUInt Name="Python error" Value="4086016255"/>
|
||||||
|
<FCUInt Name="Current line highlight" Value="1162304255"/>
|
||||||
|
</FCParamGroup>
|
||||||
|
<FCParamGroup Name="OutputWindow">
|
||||||
|
<FCUInt Name="colorText" Value="3453416703"/>
|
||||||
|
<FCUInt Name="colorLogging" Value="2497893887"/>
|
||||||
|
<FCUInt Name="colorWarning" Value="4192382975"/>
|
||||||
|
<FCUInt Name="colorError" Value="4086016255"/>
|
||||||
|
</FCParamGroup>
|
||||||
|
<FCParamGroup Name="View">
|
||||||
|
<FCUInt Name="BackgroundColor" Value="505294591"/>
|
||||||
|
<FCUInt Name="BackgroundColor2" Value="286333951"/>
|
||||||
|
<FCUInt Name="BackgroundColor3" Value="404235775"/>
|
||||||
|
<FCUInt Name="BackgroundColor4" Value="825378047"/>
|
||||||
|
<FCBool Name="Simple" Value="0"/>
|
||||||
|
<FCBool Name="Gradient" Value="1"/>
|
||||||
|
<FCBool Name="UseBackgroundColorMid" Value="0"/>
|
||||||
|
<FCUInt Name="HighlightColor" Value="3416717311"/>
|
||||||
|
<FCUInt Name="SelectionColor" Value="3032415999"/>
|
||||||
|
<FCUInt Name="PreselectColor" Value="2497893887"/>
|
||||||
|
<FCUInt Name="DefaultShapeColor" Value="1482387711"/>
|
||||||
|
<FCBool Name="RandomColor" Value="0"/>
|
||||||
|
<FCUInt Name="DefaultShapeLineColor" Value="2470768383"/>
|
||||||
|
<FCUInt Name="DefaultShapeVertexColor" Value="2470768383"/>
|
||||||
|
<FCUInt Name="BoundingBoxColor" Value="1819509759"/>
|
||||||
|
<FCUInt Name="AnnotationTextColor" Value="3453416703"/>
|
||||||
|
<FCUInt Name="SketchEdgeColor" Value="3453416703"/>
|
||||||
|
<FCUInt Name="SketchVertexColor" Value="3453416703"/>
|
||||||
|
<FCUInt Name="EditedEdgeColor" Value="3416717311"/>
|
||||||
|
<FCUInt Name="EditedVertexColor" Value="4123402495"/>
|
||||||
|
<FCUInt Name="ConstructionColor" Value="4206069759"/>
|
||||||
|
<FCUInt Name="ExternalColor" Value="4192382975"/>
|
||||||
|
<FCUInt Name="FullyConstrainedColor" Value="2799935999"/>
|
||||||
|
<FCUInt Name="InternalAlignedGeoColor" Value="1959907071"/>
|
||||||
|
<FCUInt Name="FullyConstraintElementColor" Value="2799935999"/>
|
||||||
|
<FCUInt Name="FullyConstraintConstructionElementColor" Value="2497893887"/>
|
||||||
|
<FCUInt Name="FullyConstraintInternalAlignmentColor" Value="2312199935"/>
|
||||||
|
<FCUInt Name="FullyConstraintConstructionPointColor" Value="2799935999"/>
|
||||||
|
<FCUInt Name="ConstrainedIcoColor" Value="2310339327"/>
|
||||||
|
<FCUInt Name="NonDrivingConstrDimColor" Value="2139095295"/>
|
||||||
|
<FCUInt Name="ConstrainedDimColor" Value="3416717311"/>
|
||||||
|
<FCUInt Name="ExprBasedConstrDimColor" Value="4206069759"/>
|
||||||
|
<FCUInt Name="DeactivatedConstrDimColor" Value="1819509759"/>
|
||||||
|
<FCUInt Name="CursorTextColor" Value="3453416703"/>
|
||||||
|
<FCUInt Name="CursorCrosshairColor" Value="3416717311"/>
|
||||||
|
<FCUInt Name="CreateLineColor" Value="2799935999"/>
|
||||||
|
<FCUInt Name="ShadowLightColor" Value="2470768128"/>
|
||||||
|
<FCUInt Name="ShadowGroundColor" Value="286333952"/>
|
||||||
|
<FCUInt Name="HiddenLineColor" Value="825378047"/>
|
||||||
|
<FCUInt Name="HiddenLineFaceColor" Value="505294591"/>
|
||||||
|
<FCUInt Name="HiddenLineBackground" Value="505294591"/>
|
||||||
|
<FCBool Name="EnableBacklight" Value="1"/>
|
||||||
|
<FCUInt Name="BacklightColor" Value="1162304255"/>
|
||||||
|
<FCFloat Name="BacklightIntensity" Value="0.30"/>
|
||||||
|
</FCParamGroup>
|
||||||
|
<FCParamGroup Name="TreeView">
|
||||||
|
<FCUInt Name="TreeEditColor" Value="3416717311"/>
|
||||||
|
<FCUInt Name="TreeActiveColor" Value="2799935999"/>
|
||||||
|
</FCParamGroup>
|
||||||
|
<FCParamGroup Name="MainWindow">
|
||||||
|
<FCText Name="StyleSheet">KindredCreate.qss</FCText>
|
||||||
|
</FCParamGroup>
|
||||||
|
<FCParamGroup Name="Mod">
|
||||||
|
<FCParamGroup Name="Start">
|
||||||
|
<FCUInt Name="BackgroundColor1" Value="404235775"/>
|
||||||
|
<FCUInt Name="BackgroundTextColor" Value="3453416703"/>
|
||||||
|
<FCUInt Name="PageColor" Value="505294591"/>
|
||||||
|
<FCUInt Name="PageTextColor" Value="3453416703"/>
|
||||||
|
<FCUInt Name="BoxColor" Value="825378047"/>
|
||||||
|
<FCUInt Name="LinkColor" Value="2310339327"/>
|
||||||
|
<FCUInt Name="BackgroundColor2" Value="286333951"/>
|
||||||
|
</FCParamGroup>
|
||||||
|
<FCParamGroup Name="Part">
|
||||||
|
<FCUInt Name="VertexColor" Value="3032415999"/>
|
||||||
|
<FCUInt Name="EdgeColor" Value="2310339327"/>
|
||||||
|
</FCParamGroup>
|
||||||
|
<FCParamGroup Name="PartDesign">
|
||||||
|
<FCUInt Name="DefaultDatumColor" Value="3416717311"/>
|
||||||
|
</FCParamGroup>
|
||||||
|
<FCParamGroup Name="Draft">
|
||||||
|
<FCUInt Name="snapcolor" Value="2799935999"/>
|
||||||
|
</FCParamGroup>
|
||||||
|
<FCParamGroup Name="Sketcher">
|
||||||
|
<FCUInt Name="GridLineColor" Value="1162304255"/>
|
||||||
|
</FCParamGroup>
|
||||||
|
</FCParamGroup>
|
||||||
|
</FCParamGroup>
|
||||||
|
</FCParamGroup>
|
||||||
|
</FCParamGroup>
|
||||||
|
</FCParameters>
|
||||||
1229
resources/preferences/KindredCreate/KindredCreate.qss
Normal file
18
resources/preferences/package.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<package format="1" xmlns="https://wiki.freecad.org/Package_Metadata">
|
||||||
|
|
||||||
|
<name>Kindred Create Preference Packs</name>
|
||||||
|
<description>Default preference packs for Kindred Create, featuring the Catppuccin Mocha color theme.</description>
|
||||||
|
<version>0.1.0</version>
|
||||||
|
<maintainer email="support@kindredsystems.net">Kindred Systems LLC</maintainer>
|
||||||
|
<license>LGPL-2.1-or-later</license>
|
||||||
|
<url type="website">https://kindredsystems.net</url>
|
||||||
|
|
||||||
|
<content>
|
||||||
|
<preferencepack>
|
||||||
|
<name>KindredCreate</name>
|
||||||
|
<description>The default Kindred Create theme based on Catppuccin Mocha - a soothing dark color palette.</description>
|
||||||
|
</preferencepack>
|
||||||
|
</content>
|
||||||
|
|
||||||
|
</package>
|
||||||
@@ -328,9 +328,14 @@ void AboutDialog::showCredits()
|
|||||||
|
|
||||||
//: Header for the Credits tab of the About screen
|
//: Header for the Credits tab of the About screen
|
||||||
QString creditsHTML
|
QString creditsHTML
|
||||||
= QStringLiteral("<html><body><h1>%1</h1><p>%2</p><h2>%3</h2><ul>")
|
= QStringLiteral("<html><body><h1>%1</h1>"
|
||||||
|
"<h2>Kindred Systems LLC</h2>"
|
||||||
|
"<p>Kindred Create is developed by Kindred Systems LLC, Kansas City, Missouri.<br/>"
|
||||||
|
"Website: <a href=\"https://kindredsystems.net\">https://kindredsystems.net</a></p>"
|
||||||
|
"<h2>FreeCAD Project</h2>"
|
||||||
|
"<p>%2</p><h2>%3</h2><ul>")
|
||||||
.arg(tr("Credits", "Header for the Credits tab of the About screen"))
|
.arg(tr("Credits", "Header for the Credits tab of the About screen"))
|
||||||
.arg(tr("FreeCAD would not be possible without the contributions of:"))
|
.arg(tr("Kindred Create is based on FreeCAD and would not be possible without the contributions of:"))
|
||||||
.arg(tr("Individuals", "Header for the list of individual people in the Credits list."));
|
.arg(tr("Individuals", "Header for the list of individual people in the Credits list."));
|
||||||
|
|
||||||
QTextStream stream(&creditsFile);
|
QTextStream stream(&creditsFile);
|
||||||
|
|||||||
@@ -122,6 +122,10 @@
|
|||||||
<file>freecadsplash8.png</file>
|
<file>freecadsplash8.png</file>
|
||||||
<file>freecadsplash9_2x.png</file>
|
<file>freecadsplash9_2x.png</file>
|
||||||
<file>freecadsplash9.png</file>
|
<file>freecadsplash9.png</file>
|
||||||
|
<file>kindred-create.svg</file>
|
||||||
|
<file>kindredcreateabout.png</file>
|
||||||
|
<file>kindredcreatesplash.png</file>
|
||||||
|
<file>kindredcreatesplash_2x.png</file>
|
||||||
<file>Geoassembly.svg</file>
|
<file>Geoassembly.svg</file>
|
||||||
<file>Geofeaturegroup.svg</file>
|
<file>Geofeaturegroup.svg</file>
|
||||||
<file>Group.svg</file>
|
<file>Group.svg</file>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ SET(PreferencePacks_Files
|
|||||||
)
|
)
|
||||||
|
|
||||||
SET(PreferencePacks_Directories
|
SET(PreferencePacks_Directories
|
||||||
|
"KindredCreate"
|
||||||
"FreeCAD Classic"
|
"FreeCAD Classic"
|
||||||
"Dark behave"
|
"Dark behave"
|
||||||
"FreeCAD Light"
|
"FreeCAD Light"
|
||||||
|
|||||||
1229
src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss
Normal file
@@ -1,12 +1,23 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
<package format="1">
|
<package format="1">
|
||||||
<name>Built-In Preference Packs</name>
|
<name>Built-In Preference Packs</name>
|
||||||
<description>Preference Packs included with the FreeCAD distribution</description>
|
<description>Preference Packs included with the Kindred Create distribution</description>
|
||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
<maintainer email="email@FreeCAD.org">MisterMaker</maintainer>
|
<maintainer email="support@kindredsystems.net">Kindred Systems LLC</maintainer>
|
||||||
<license file="../../LICENSE">LGPL2</license>
|
<license file="../../LICENSE">LGPL2</license>
|
||||||
<url type="repository">https://github.com/FreeCAD/FreeCAD</url>
|
<url type="repository">https://github.com/kindredsystems/create</url>
|
||||||
<content>
|
<content>
|
||||||
|
<preferencepack>
|
||||||
|
<name>KindredCreate</name>
|
||||||
|
<type>Theme</type>
|
||||||
|
<description>The default Kindred Create theme based on Catppuccin Mocha - a soothing dark color palette with carefully chosen colors for optimal readability.</description>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<tag>built-in</tag>
|
||||||
|
<tag>default</tag>
|
||||||
|
<tag>dark</tag>
|
||||||
|
<tag>catppuccin</tag>
|
||||||
|
<tag>mocha</tag>
|
||||||
|
</preferencepack>
|
||||||
<preferencepack>
|
<preferencepack>
|
||||||
<name>FreeCAD Classic</name>
|
<name>FreeCAD Classic</name>
|
||||||
<type>Theme</type>
|
<type>Theme</type>
|
||||||
@@ -17,8 +28,8 @@
|
|||||||
<tag>no stylesheet</tag>
|
<tag>no stylesheet</tag>
|
||||||
<tag>classic theme</tag>
|
<tag>classic theme</tag>
|
||||||
</preferencepack>
|
</preferencepack>
|
||||||
<preferencepack>
|
<preferencepack>
|
||||||
<name>FreeCAD Light</name>
|
<name>FreeCAD Light</name>
|
||||||
<type>Theme</type>
|
<type>Theme</type>
|
||||||
<description>Applies a basic light theme.</description>
|
<description>Applies a basic light theme.</description>
|
||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
@@ -26,8 +37,8 @@
|
|||||||
<tag>background</tag>
|
<tag>background</tag>
|
||||||
<tag>light</tag>
|
<tag>light</tag>
|
||||||
</preferencepack>
|
</preferencepack>
|
||||||
<preferencepack>
|
<preferencepack>
|
||||||
<name>FreeCAD Dark</name>
|
<name>FreeCAD Dark</name>
|
||||||
<type>Theme</type>
|
<type>Theme</type>
|
||||||
<description>Applies a basic dark theme.</description>
|
<description>Applies a basic dark theme.</description>
|
||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
|
|||||||
@@ -360,8 +360,8 @@ QPixmap SplashScreen::splashImage()
|
|||||||
fontExe.setPointSizeF(20.0);
|
fontExe.setPointSizeF(20.0);
|
||||||
QFontMetrics metricExe(fontExe);
|
QFontMetrics metricExe(fontExe);
|
||||||
int l = QtTools::horizontalAdvance(metricExe, title);
|
int l = QtTools::horizontalAdvance(metricExe, title);
|
||||||
if (title == QLatin1String("FreeCAD")) {
|
if (title == QLatin1String("Kindred Create")) {
|
||||||
l = 0.0; // "FreeCAD" text is already part of the splashscreen, version goes below it
|
// For Kindred Create splash, we draw the title as part of the dynamic rendering
|
||||||
}
|
}
|
||||||
int w = splash_image.width();
|
int w = splash_image.width();
|
||||||
int h = splash_image.height();
|
int h = splash_image.height();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
SET(Stylesheets_Files
|
SET(Stylesheets_Files
|
||||||
|
"KindredCreate.qss"
|
||||||
"FreeCAD.qss"
|
"FreeCAD.qss"
|
||||||
"defaults.qss"
|
"defaults.qss"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -338,11 +338,11 @@ PyMOD_INIT_FUNC(FreeCADGui)
|
|||||||
try {
|
try {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
Base::Interpreter().loadModule("FreeCAD");
|
Base::Interpreter().loadModule("FreeCAD");
|
||||||
App::Application::Config()["AppIcon"] = "freecad";
|
App::Application::Config()["AppIcon"] = "kindred-create";
|
||||||
App::Application::Config()["SplashScreen"] = "freecadsplash";
|
App::Application::Config()["SplashScreen"] = "kindredcreatesplash";
|
||||||
App::Application::Config()["CopyrightInfo"] = fmt::format("\xc2\xa9 Juergen Riegel, Werner Mayer, Yorik van Havre and others 2001-{}\n", FCCopyrightYear);
|
App::Application::Config()["CopyrightInfo"] = "\xc2\xa9 2025 Kindred Systems LLC\n";
|
||||||
App::Application::Config()["LicenseInfo"] = "FreeCAD is free and open-source software licensed under the terms of LGPL2+ license.\n";
|
App::Application::Config()["LicenseInfo"] = "Kindred Create is licensed under LGPL-3.0-or-later.\nBased on FreeCAD, licensed under LGPL-2.0-or-later.\n";
|
||||||
App::Application::Config()["CreditsInfo"] = "FreeCAD would not be possible without the FreeCAD community.\n";
|
App::Application::Config()["CreditsInfo"] = "Kindred Create is based on FreeCAD and would not be possible without the FreeCAD community.\n";
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
// it's possible that the GUI is already initialized when the Gui version of the executable
|
// it's possible that the GUI is already initialized when the Gui version of the executable
|
||||||
|
|||||||
@@ -46,11 +46,10 @@
|
|||||||
using App::Application;
|
using App::Application;
|
||||||
using Base::Console;
|
using Base::Console;
|
||||||
|
|
||||||
const auto sBanner = fmt::format(
|
const char sBanner[]
|
||||||
"(C) 2001-{} FreeCAD contributors\n"
|
= "(C) 2025 Kindred Systems LLC\n"
|
||||||
"FreeCAD is free and open-source software licensed under the terms of LGPL2+ license.\n\n",
|
"Kindred Create is licensed under LGPL-3.0-or-later.\n"
|
||||||
FCCopyrightYear
|
"Based on FreeCAD (C) 2001-2025 FreeCAD contributors, licensed under LGPL-2.0-or-later.\n\n";
|
||||||
);
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
@@ -67,12 +66,13 @@ int main(int argc, char** argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Name and Version of the Application
|
// Name and Version of the Application
|
||||||
App::Application::Config()["ExeName"] = "FreeCAD";
|
App::Application::Config()["ExeName"] = "Kindred Create";
|
||||||
App::Application::Config()["ExeVendor"] = "FreeCAD";
|
App::Application::Config()["ExeVendor"] = "Kindred Systems LLC";
|
||||||
App::Application::Config()["AppDataSkipVendor"] = "true";
|
App::Application::Config()["AppDataSkipVendor"] = "true";
|
||||||
|
|
||||||
// set the banner (for logging and console)
|
// set the banner (for logging and console)
|
||||||
App::Application::Config()["CopyrightInfo"] = sBanner;
|
App::Application::Config()["CopyrightInfo"] = sBanner;
|
||||||
|
App::Application::Config()["MaintainerUrl"] = "https://kindredsystems.net";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Init phase ===========================================================
|
// Init phase ===========================================================
|
||||||
@@ -147,7 +147,7 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Destruction phase ===========================================================
|
// Destruction phase ===========================================================
|
||||||
Console().log("FreeCAD terminating...\n");
|
Console().log("Kindred Create terminating...\n");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// close open documents
|
// close open documents
|
||||||
@@ -159,7 +159,7 @@ int main(int argc, char** argv)
|
|||||||
// cleans up
|
// cleans up
|
||||||
Application::destruct();
|
Application::destruct();
|
||||||
|
|
||||||
Console().log("FreeCAD completely terminated\n");
|
Console().log("Kindred Create completely terminated\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,11 +54,10 @@
|
|||||||
|
|
||||||
void PrintInitHelp();
|
void PrintInitHelp();
|
||||||
|
|
||||||
const auto sBanner = fmt::format(
|
const char sBanner[]
|
||||||
"(C) 2001-{} FreeCAD contributors\n"
|
= "(C) 2025 Kindred Systems LLC\n"
|
||||||
"FreeCAD is free and open-source software licensed under the terms of LGPL2+ license.\n\n",
|
"Kindred Create is licensed under LGPL-3.0-or-later.\n"
|
||||||
FCCopyrightYear
|
"Based on FreeCAD (C) 2001-2025 FreeCAD contributors, licensed under LGPL-2.0-or-later.\n\n";
|
||||||
);
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
void InitMiniDumpWriter(const std::string&);
|
void InitMiniDumpWriter(const std::string&);
|
||||||
@@ -188,26 +187,25 @@ int main(int argc, char** argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Name and Version of the Application
|
// Name and Version of the Application
|
||||||
App::Application::Config()["ExeName"] = "FreeCAD";
|
App::Application::Config()["ExeName"] = "Kindred Create";
|
||||||
App::Application::Config()["ExeVendor"] = "FreeCAD";
|
App::Application::Config()["ExeVendor"] = "Kindred Systems LLC";
|
||||||
App::Application::Config()["AppDataSkipVendor"] = "true";
|
App::Application::Config()["AppDataSkipVendor"] = "true";
|
||||||
App::Application::Config()["MaintainerUrl"] = "https://freecad.org";
|
App::Application::Config()["MaintainerUrl"] = "https://kindredsystems.net";
|
||||||
|
|
||||||
// set the banner (for logging and console)
|
// set the banner (for logging and console)
|
||||||
App::Application::Config()["CopyrightInfo"] = sBanner;
|
App::Application::Config()["CopyrightInfo"] = sBanner;
|
||||||
App::Application::Config()["AppIcon"] = "freecad";
|
App::Application::Config()["AppIcon"] = "kindred-create";
|
||||||
App::Application::Config()["SplashScreen"] = "freecadsplash";
|
App::Application::Config()["SplashScreen"] = "kindredcreatesplash";
|
||||||
App::Application::Config()["AboutImage"] = App::Application::isDevelopmentVersion()
|
App::Application::Config()["AboutImage"] = "kindredcreateabout";
|
||||||
? "freecadaboutdev"
|
App::Application::Config()["StyleSheet"] = "KindredCreate.qss";
|
||||||
: "freecadabout";
|
|
||||||
App::Application::Config()["StartWorkbench"] = "PartDesignWorkbench";
|
App::Application::Config()["StartWorkbench"] = "PartDesignWorkbench";
|
||||||
// App::Application::Config()["HiddenDockWindow"] = "Property editor";
|
// App::Application::Config()["HiddenDockWindow"] = "Property editor";
|
||||||
App::Application::Config()["SplashAlignment"] = "Bottom|Left";
|
App::Application::Config()["SplashAlignment"] = "Bottom|Left";
|
||||||
App::Application::Config()["SplashTextColor"] = "#418FDE";
|
App::Application::Config()["SplashTextColor"] = "#cdd6f4"; // Catppuccin Mocha text
|
||||||
App::Application::Config()["SplashWarningColor"] = "#CA333B";
|
App::Application::Config()["SplashWarningColor"] = "#f38ba8"; // Catppuccin Mocha red
|
||||||
App::Application::Config()["SplashInfoColor"] = "#000000";
|
App::Application::Config()["SplashInfoColor"] = "#a6adc8"; // Catppuccin Mocha subtext0
|
||||||
App::Application::Config()["SplashInfoPosition"] = "6,75";
|
App::Application::Config()["SplashInfoPosition"] = "6,75";
|
||||||
App::Application::Config()["DesktopFileName"] = "org.freecad.FreeCAD";
|
App::Application::Config()["DesktopFileName"] = "net.kindredsystems.KindredCreate";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Init phase ===========================================================
|
// Init phase ===========================================================
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID /*lpReser
|
|||||||
PyMOD_INIT_FUNC(FreeCAD)
|
PyMOD_INIT_FUNC(FreeCAD)
|
||||||
{
|
{
|
||||||
// Init phase ===========================================================
|
// Init phase ===========================================================
|
||||||
App::Application::Config()["ExeName"] = "FreeCAD";
|
App::Application::Config()["ExeName"] = "Kindred Create";
|
||||||
App::Application::Config()["ExeVendor"] = "FreeCAD";
|
App::Application::Config()["ExeVendor"] = "Kindred Systems LLC";
|
||||||
App::Application::Config()["AppDataSkipVendor"] = "true";
|
App::Application::Config()["AppDataSkipVendor"] = "true";
|
||||||
|
|
||||||
QByteArray path;
|
QByteArray path;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
// remains consistent on all systems.
|
// remains consistent on all systems.
|
||||||
IDI_ICON1 ICON DISCARDABLE "icon.ico"
|
IDI_ICON1 ICON DISCARDABLE "icon.ico"
|
||||||
|
|
||||||
// File info for the FreeCAD.exe
|
// File info for the kindred-create.exe
|
||||||
//
|
//
|
||||||
1 VERSIONINFO
|
1 VERSIONINFO
|
||||||
FILEVERSION ${PACKAGE_VERSION_MAJOR},${PACKAGE_VERSION_MINOR},${PACKAGE_VERSION_PATCH},${PACKAGE_BUILD_VERSION}
|
FILEVERSION ${PACKAGE_VERSION_MAJOR},${PACKAGE_VERSION_MINOR},${PACKAGE_VERSION_PATCH},${PACKAGE_BUILD_VERSION}
|
||||||
@@ -20,12 +20,12 @@ BEGIN
|
|||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "040904b0" // 409 stands for US English
|
BLOCK "040904b0" // 409 stands for US English
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "${PROJECT_NAME} Team"
|
VALUE "CompanyName", "Kindred Systems LLC"
|
||||||
VALUE "FileDescription", "${PROJECT_NAME} main executable"
|
VALUE "FileDescription", "Kindred Create - Parametric 3D CAD modeler"
|
||||||
VALUE "InternalName", "FreeCAD.exe"
|
VALUE "InternalName", "kindred-create.exe"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2022"
|
VALUE "LegalCopyright", "Copyright (C) 2025 Kindred Systems LLC"
|
||||||
VALUE "OriginalFilename", "FreeCAD.exe"
|
VALUE "OriginalFilename", "kindred-create.exe"
|
||||||
VALUE "ProductName", "${PROJECT_NAME}"
|
VALUE "ProductName", "Kindred Create"
|
||||||
VALUE "ProductVersion", "${PACKAGE_VERSION}${PACKAGE_VERSION_SUFFIX}"
|
VALUE "ProductVersion", "${PACKAGE_VERSION}${PACKAGE_VERSION_SUFFIX}"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
// remains consistent on all systems.
|
// remains consistent on all systems.
|
||||||
IDI_ICON1 ICON DISCARDABLE "icon.ico"
|
IDI_ICON1 ICON DISCARDABLE "icon.ico"
|
||||||
|
|
||||||
// File info for the FreeCADCmd.exe
|
// File info for the kindred-create-cmd.exe
|
||||||
//
|
//
|
||||||
1 VERSIONINFO
|
1 VERSIONINFO
|
||||||
FILEVERSION ${PACKAGE_VERSION_MAJOR},${PACKAGE_VERSION_MINOR},${PACKAGE_VERSION_PATCH},${PACKAGE_BUILD_VERSION}
|
FILEVERSION ${PACKAGE_VERSION_MAJOR},${PACKAGE_VERSION_MINOR},${PACKAGE_VERSION_PATCH},${PACKAGE_BUILD_VERSION}
|
||||||
@@ -20,12 +20,12 @@ BEGIN
|
|||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "040904b0" // 409 stands for US English
|
BLOCK "040904b0" // 409 stands for US English
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "${PROJECT_NAME} Team"
|
VALUE "CompanyName", "Kindred Systems LLC"
|
||||||
VALUE "FileDescription", "${PROJECT_NAME} command line executable"
|
VALUE "FileDescription", "Kindred Create command line executable"
|
||||||
VALUE "InternalName", "FreeCADCmd.exe"
|
VALUE "InternalName", "kindred-create-cmd.exe"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2022"
|
VALUE "LegalCopyright", "Copyright (C) 2025 Kindred Systems LLC"
|
||||||
VALUE "OriginalFilename", "FreeCADCmd.exe"
|
VALUE "OriginalFilename", "kindred-create-cmd.exe"
|
||||||
VALUE "ProductName", "${PROJECT_NAME}"
|
VALUE "ProductName", "Kindred Create"
|
||||||
VALUE "ProductVersion", "${PACKAGE_VERSION}${PACKAGE_VERSION_SUFFIX}"
|
VALUE "ProductVersion", "${PACKAGE_VERSION}${PACKAGE_VERSION_SUFFIX}"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
|||||||
@@ -165,9 +165,8 @@ int AssemblyObject::solve(bool enableRedo, bool updateJCS)
|
|||||||
|
|
||||||
jointParts(joints);
|
jointParts(joints);
|
||||||
|
|
||||||
if (enableRedo) {
|
// Always save placements to enable orientation flip detection
|
||||||
savePlacementsForUndo();
|
savePlacementsForUndo();
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mbdAssembly->runPreDrag();
|
mbdAssembly->runPreDrag();
|
||||||
@@ -186,8 +185,22 @@ int AssemblyObject::solve(bool enableRedo, bool updateJCS)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate that the solve didn't cause any parts to flip orientation
|
||||||
|
if (!validateNewPlacements()) {
|
||||||
|
// Restore previous placements - the solve found an invalid configuration
|
||||||
|
undoSolve();
|
||||||
|
lastSolverStatus = -2;
|
||||||
|
updateSolveStatus();
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
setNewPlacements();
|
setNewPlacements();
|
||||||
|
|
||||||
|
// Clear undo history if the caller didn't want redo capability
|
||||||
|
if (!enableRedo) {
|
||||||
|
clearUndo();
|
||||||
|
}
|
||||||
|
|
||||||
redrawJointPlacements(joints);
|
redrawJointPlacements(joints);
|
||||||
|
|
||||||
updateSolveStatus();
|
updateSolveStatus();
|
||||||
@@ -480,8 +493,56 @@ bool AssemblyObject::validateNewPlacements()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: We could do further tests
|
// Check if any part has flipped orientation (rotation > 90 degrees from original)
|
||||||
// For example check if the joints connectors are correctly aligned.
|
// This prevents joints from "breaking" when the solver finds an alternate configuration
|
||||||
|
for (const auto& savedPair : previousPositions) {
|
||||||
|
App::DocumentObject* obj = savedPair.first;
|
||||||
|
if (!obj) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = objectPartMap.find(obj);
|
||||||
|
if (it == objectPartMap.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<MbD::ASMTPart> mbdPart = it->second.part;
|
||||||
|
if (!mbdPart) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Base::Placement newPlacement = getMbdPlacement(mbdPart);
|
||||||
|
if (!it->second.offsetPlc.isIdentity()) {
|
||||||
|
newPlacement = newPlacement * it->second.offsetPlc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Base::Placement& oldPlc = savedPair.second;
|
||||||
|
|
||||||
|
// Calculate the rotation difference between old and new orientations
|
||||||
|
Base::Rotation oldRot = oldPlc.getRotation();
|
||||||
|
Base::Rotation newRot = newPlacement.getRotation();
|
||||||
|
|
||||||
|
// Get the relative rotation: how much did the part rotate?
|
||||||
|
Base::Rotation relativeRot = newRot * oldRot.inverse();
|
||||||
|
|
||||||
|
// Get the angle of this rotation
|
||||||
|
Base::Vector3d axis;
|
||||||
|
double angle;
|
||||||
|
relativeRot.getRawValue(axis, angle);
|
||||||
|
|
||||||
|
// If the part rotated more than 90 degrees, consider it a flip
|
||||||
|
// Use 91 degrees to allow for small numerical errors
|
||||||
|
constexpr double maxAngle = 91.0 * M_PI / 180.0;
|
||||||
|
if (std::abs(angle) > maxAngle) {
|
||||||
|
Base::Console().warning(
|
||||||
|
"Assembly : Ignoring bad solve, part (%s) flipped orientation (%.1f degrees).\n",
|
||||||
|
obj->getFullLabel(),
|
||||||
|
std::abs(angle) * 180.0 / M_PI
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||