Compare commits

..

2 Commits

Author SHA1 Message Date
evan.liu
5cb2875ba6 修复了编译问题,去掉了x86这样的编译选项 2026-09-21 06:22:39 +08:00
evan.liu
c7130cbb07 更换 DOME 风格图标,About 增加基于 OBS 二次开发说明
- 图标重新绘制为 DOME 风格:蓝色半球穹顶 + 白色三叶片光圈 + CAIIC 三色环绕圆弧
  (obs.png、obs-studio.ico、updater 用旧版 ico 同步更换,附生成脚本 tools/dome-icon-gen.js)
- About 保留原有 logo/名称/版本号,新增 "Based on OBS Studio (GPLv2) /
  Secondary development by CAIIC" 说明及官网链接
- deploy 同步重新编译的 obs64.exe(版本仍为 1.0.0)
2026-09-19 08:45:06 +08:00
13 changed files with 225 additions and 85 deletions

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -23,25 +23,6 @@ if(OBS_PARENT_ARCHITECTURE STREQUAL CMAKE_VS_PLATFORM_NAME)
RESULT_VARIABLE _process_result
COMMAND_ERROR_IS_FATAL ANY
)
execute_process(
COMMAND
"${CMAKE_COMMAND}" -S ${CMAKE_CURRENT_SOURCE_DIR} -B ${CMAKE_SOURCE_DIR}/build_x86 -A
"Win32,version=${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}" -G "${CMAKE_GENERATOR}"
-DCMAKE_SYSTEM_VERSION:STRING='${CMAKE_SYSTEM_VERSION}' -DVIRTUALCAM_GUID:STRING=${VIRTUALCAM_GUID}
-DCMAKE_MESSAGE_LOG_LEVEL:STRING=${CMAKE_MESSAGE_LOG_LEVEL} -DOBS_PARENT_ARCHITECTURE:STRING=ARM64
RESULT_VARIABLE _process_result
COMMAND_ERROR_IS_FATAL ANY
)
elseif(OBS_PARENT_ARCHITECTURE STREQUAL x64)
execute_process(
COMMAND
"${CMAKE_COMMAND}" -S ${CMAKE_CURRENT_SOURCE_DIR} -B ${CMAKE_SOURCE_DIR}/build_x86 -A
"Win32,version=${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}" -G "${CMAKE_GENERATOR}"
-DCMAKE_SYSTEM_VERSION:STRING='${CMAKE_SYSTEM_VERSION}' -DVIRTUALCAM_GUID:STRING=${VIRTUALCAM_GUID}
-DCMAKE_MESSAGE_LOG_LEVEL:STRING=${CMAKE_MESSAGE_LOG_LEVEL} -DOBS_PARENT_ARCHITECTURE:STRING=x64
RESULT_VARIABLE _process_result
COMMAND_ERROR_IS_FATAL ANY
)
endif()
else()
# target_disable_feature: Stub macro for child architecture builds

View File

@ -26,8 +26,6 @@ function(set_target_properties_obs target)
elseif(target STREQUAL inject-helper OR target STREQUAL get-graphics-offsets)
set(OBS_EXECUTABLE_DESTINATION "${OBS_DATA_DESTINATION}/obs-plugins/win-capture")
_target_install_obs(${target} DESTINATION ${OBS_EXECUTABLE_DESTINATION} x86)
if(CMAKE_VS_PLATFORM_NAME STREQUAL ARM64)
_target_install_obs(${target} DESTINATION ${OBS_EXECUTABLE_DESTINATION} x64)
endif()
@ -70,16 +68,12 @@ function(set_target_properties_obs target)
target_add_resource(graphics-hook "${CMAKE_CURRENT_SOURCE_DIR}/obs-vulkan64.json" "${target_destination}")
target_add_resource(graphics-hook "${CMAKE_CURRENT_SOURCE_DIR}/obs-vulkan32.json" "${target_destination}")
_target_install_obs(${target} DESTINATION ${target_destination} x86)
if(CMAKE_VS_PLATFORM_NAME STREQUAL ARM64)
_target_install_obs(${target} DESTINATION ${target_destination} x64)
endif()
elseif(target STREQUAL obs-virtualcam-module)
set(target_destination "${OBS_DATA_DESTINATION}/obs-plugins/win-dshow")
_target_install_obs(${target} DESTINATION ${target_destination} x86)
if(CMAKE_VS_PLATFORM_NAME STREQUAL ARM64)
_target_install_obs(${target} DESTINATION ${target_destination} x64)
endif()
@ -182,33 +176,12 @@ endfunction()
# _target_install_obs: Helper function to install build artifacts to rundir and install location
function(_target_install_obs target)
set(options "x86" "x64")
set(options "x64")
set(oneValueArgs "DESTINATION" "LIBRARY_DESTINATION" "HEADER_DESTINATION")
set(multiValueArgs "")
cmake_parse_arguments(PARSE_ARGV 0 _TIO "${options}" "${oneValueArgs}" "${multiValueArgs}")
if(_TIO_x86)
get_target_property(target_type ${target} TYPE)
if(target_type STREQUAL EXECUTABLE)
set(suffix exe)
else()
set(suffix dll)
endif()
cmake_path(RELATIVE_PATH CMAKE_CURRENT_SOURCE_DIR BASE_DIRECTORY "${OBS_SOURCE_DIR}" OUTPUT_VARIABLE project_path)
set(32bit_project_path "${OBS_SOURCE_DIR}/build_x86/${project_path}")
set(target_file "${32bit_project_path}/$<CONFIG>/${target}32.${suffix}")
set(target_pdb_file "${32bit_project_path}/$<CONFIG>/${target}32.pdb")
set(comment "Copy ${target} (x86) to destination")
install(
FILES "${32bit_project_path}/$<CONFIG>/${target}32.${suffix}"
DESTINATION "${_TIO_DESTINATION}"
COMPONENT Runtime
OPTIONAL
)
elseif(_TIO_x64)
if(_TIO_x64)
get_target_property(target_type ${target} TYPE)
if(target_type STREQUAL EXECUTABLE)
set(suffix exe)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>520</width>
<height>300</height>
<height>340</height>
</rect>
</property>
<property name="windowTitle">
@ -73,6 +73,22 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="basedOn">
<property name="text">
<string notr="true">Based on &lt;a href="https://obsproject.com"&gt;OBS Studio&lt;/a&gt; (GPLv2)&lt;br/&gt;Secondary development by CAIIC</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextBrowserInteraction</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -29,15 +29,6 @@ if(OBS_PARENT_ARCHITECTURE STREQUAL CMAKE_VS_PLATFORM_NAME)
)
endif()
if(CMAKE_VS_PLATFORM_NAME MATCHES "(ARM64|x64)")
add_custom_command(
TARGET get-graphics-offsets
POST_BUILD
COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_SOURCE_DIR}/build_x86 --config $<CONFIG> -t get-graphics-offsets
COMMENT "Build x86 get-graphics-offsets"
)
endif()
add_dependencies(win-capture get-graphics-offsets)
endif()

View File

@ -64,15 +64,6 @@ if(OBS_PARENT_ARCHITECTURE STREQUAL CMAKE_VS_PLATFORM_NAME)
)
endif()
if(CMAKE_VS_PLATFORM_NAME MATCHES "(ARM64|x64)")
add_custom_command(
TARGET graphics-hook
POST_BUILD
COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_SOURCE_DIR}/build_x86 --config $<CONFIG> -t graphics-hook
COMMENT "Build x86 graphics-hook"
)
endif()
add_dependencies(win-capture graphics-hook)
endif()

View File

@ -24,15 +24,6 @@ if(OBS_PARENT_ARCHITECTURE STREQUAL CMAKE_VS_PLATFORM_NAME)
)
endif()
if(CMAKE_VS_PLATFORM_NAME MATCHES "(ARM64|x64)")
add_custom_command(
TARGET inject-helper
POST_BUILD
COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_SOURCE_DIR}/build_x86 --config $<CONFIG> -t inject-helper
COMMENT "Build x86 inject-helper"
)
endif()
add_dependencies(win-capture inject-helper)
endif()

View File

@ -114,15 +114,6 @@ if(OBS_PARENT_ARCHITECTURE STREQUAL CMAKE_VS_PLATFORM_NAME)
)
endif()
if(CMAKE_VS_PLATFORM_NAME MATCHES "(ARM64|x64)")
add_custom_command(
TARGET obs-virtualcam-module
POST_BUILD
COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_SOURCE_DIR}/build_x86 --config $<CONFIG> -t obs-virtualcam-module
COMMENT "Build x86 obs-virtualcam-module"
)
endif()
add_dependencies(win-dshow obs-virtualcam-module)
endif()

206
tools/dome-icon-gen.js Normal file
View File

@ -0,0 +1,206 @@
// DOME-style icon generator for the CAIIC OBS fork.
// Renders a blue observatory/planetarium dome with a white three-blade
// aperture (nod to the OBS logo) wrapped by three CAIIC-colored arcs
// (orange top, green lower-left, yellow lower-right).
// Usage: node dome-icon-gen.js <out-dir>
const fs = require('fs');
const path = require('path');
const zlib = require('zlib');
const DEG = Math.PI / 180;
// ---------- CRC32 / PNG ----------
const crcTable = (() => {
const t = new Uint32Array(256);
for (let n = 0; n < 256; n++) {
let c = n;
for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
t[n] = c >>> 0;
}
return t;
})();
function crc32(buf) {
let c = 0xffffffff;
for (let i = 0; i < buf.length; i++) c = crcTable[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
return (c ^ 0xffffffff) >>> 0;
}
function chunk(type, data) {
const out = Buffer.alloc(8 + data.length + 4);
out.writeUInt32BE(data.length, 0);
out.write(type, 4, 'ascii');
data.copy(out, 8);
out.writeUInt32BE(crc32(out.subarray(4, 8 + data.length)), 8 + data.length);
return out;
}
function pngEncode(width, height, rgba) {
const stride = width * 4;
const raw = Buffer.alloc((stride + 1) * height);
for (let y = 0; y < height; y++) {
raw[y * (stride + 1)] = 0;
rgba.copy(raw, y * (stride + 1) + 1, y * stride, (y + 1) * stride);
}
const ihdr = Buffer.alloc(13);
ihdr.writeUInt32BE(width, 0);
ihdr.writeUInt32BE(height, 4);
ihdr[8] = 8; // bit depth
ihdr[9] = 6; // RGBA
return Buffer.concat([
Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
chunk('IHDR', ihdr),
chunk('IDAT', zlib.deflateSync(raw, { level: 9 })),
chunk('IEND', Buffer.alloc(0)),
]);
}
function icoEncode(images) {
// images: [{size, png}]
const header = Buffer.alloc(6);
header.writeUInt16LE(1, 2);
header.writeUInt16LE(images.length, 4);
let offset = 6 + images.length * 16;
const entries = [];
for (const img of images) {
const e = Buffer.alloc(16);
e[0] = img.size >= 256 ? 0 : img.size;
e[1] = img.size >= 256 ? 0 : img.size;
e[4] = 1; // planes
e.writeUInt16LE(32, 6);
e.writeUInt32LE(img.png.length, 8);
e.writeUInt32LE(offset, 12);
offset += img.png.length;
entries.push(e);
}
return Buffer.concat([header, ...entries, ...images.map((i) => i.png)]);
}
// ---------- geometry ----------
function clamp(x, a, b) { return Math.min(Math.max(x, a), b); }
function mix(a, b, t) { return a + (b - a) * t; }
function mix3(c1, c2, t) { return [mix(c1[0], c2[0], t), mix(c1[1], c2[1], t), mix(c1[2], c2[2], t)]; }
// signed distance to a circular arc stroke (rounded caps), angles in radians
function arcSDF(px, py, cx, cy, r, a0, a1, w) {
const dx = px - cx, dy = py - cy;
const d = Math.hypot(dx, dy);
let ang = Math.atan2(dy, dx);
// normalize ang into [a0, a0 + 2PI)
const TWO_PI = Math.PI * 2;
while (ang < a0) ang += TWO_PI;
while (ang >= a0 + TWO_PI) ang -= TWO_PI;
let dist;
if (ang <= a1) {
dist = Math.abs(d - r);
} else {
const e0x = cx + r * Math.cos(a0), e0y = cy + r * Math.sin(a0);
const e1x = cx + r * Math.cos(a1), e1y = cy + r * Math.sin(a1);
dist = Math.min(Math.hypot(px - e0x, py - e0y), Math.hypot(px - e1x, py - e1y));
}
return dist - w / 2;
}
// rounded rect sdf
function rrSDF(px, py, cx, cy, hw, hh, r) {
const qx = Math.abs(px - cx) - (hw - r);
const qy = Math.abs(py - cy) - (hh - r);
const ax = Math.max(qx, 0), ay = Math.max(qy, 0);
return Math.hypot(ax, ay) + Math.min(Math.max(qx, qy), 0) - r;
}
// ---------- design ----------
const DOME_C = [0.5, 0.56]; // dome circle center
const DOME_R = 0.295; // dome radius
const BLADE_C = [0.5, 0.475]; // aperture center
const BLADE_R = 0.155;
const BLADE_W = 0.048;
const ARC_C = [0.5, 0.53];
const ARC_R = 0.4;
const ARC_W = 0.036;
const NAVY = [10, 52, 128];
const BLUE_HI = [110, 196, 250];
const BLUE_LO = [9, 68, 152];
const WHITE = [248, 252, 255];
const ORANGE = [240, 128, 60];
const GREEN = [110, 190, 74];
const YELLOW = [240, 204, 60];
function domeColor(px, py) {
const t = Math.pow(clamp(Math.hypot(px - 0.34, py - 0.36) / 0.5, 0, 1), 0.8);
let c = mix3(BLUE_HI, BLUE_LO, t);
// darken slightly toward the base for depth
const base = clamp((py - 0.42) / 0.16, 0, 1) * 0.18;
return [c[0] * (1 - base), c[1] * (1 - base), c[2] * (1 - base)];
}
function bladeSDF(px, py) {
let best = 1e9;
const span = 100 * DEG;
for (let i = 0; i < 3; i++) {
const a0 = (-90 + i * 120) * DEG;
best = Math.min(best, arcSDF(px, py, BLADE_C[0], BLADE_C[1], BLADE_R, a0, a0 + span, BLADE_W));
}
return best;
}
function arcsSDF(px, py) {
return [
{ sdf: arcSDF(px, py, ARC_C[0], ARC_C[1], ARC_R, -160 * DEG, -20 * DEG, ARC_W), color: ORANGE },
{ sdf: arcSDF(px, py, ARC_C[0], ARC_C[1], ARC_R, 105 * DEG, 170 * DEG, ARC_W), color: GREEN },
{ sdf: arcSDF(px, py, ARC_C[0], ARC_C[1], ARC_R, 10 * DEG, 75 * DEG, ARC_W), color: YELLOW },
];
}
function render(size) {
const SS = 4;
const R = size * SS;
const out = Buffer.alloc(size * size * 4);
const px = 1 / R;
for (let y = 0; y < size; y++) {
for (let x = 0; x < size; x++) {
let r = 0, g = 0, b = 0, a = 0;
for (let sy = 0; sy < SS; sy++) {
for (let sx = 0; sx < SS; sx++) {
const nx = (x * SS + sx + 0.5) / R;
const ny = (y * SS + sy + 0.5) / R;
const aa = (sdf) => clamp(0.5 - sdf / px, 0, 1);
let cr = 0, cg = 0, cb = 0, ca = 0;
const over = (sdf, col, opacity) => {
const cov = aa(sdf) * opacity;
cr = cr * (1 - cov) + col[0] * cov;
cg = cg * (1 - cov) + col[1] * cov;
cb = cb * (1 - cov) + col[2] * cov;
ca = ca * (1 - cov) + cov;
};
// base bar
over(rrSDF(nx, ny, 0.5, DOME_C[1] + 0.022, DOME_R + 0.045, 0.028, 0.026), NAVY, 1);
// dome (upper half of circle)
const dd = Math.max(Math.hypot(nx - DOME_C[0], ny - DOME_C[1]) - DOME_R, ny - DOME_C[1]);
over(dd, domeColor(nx, ny), 1);
// aperture blades
over(bladeSDF(nx, ny), WHITE, 0.95);
// colored arcs
for (const arc of arcsSDF(nx, ny)) over(arc.sdf, arc.color, 1);
r += cr; g += cg; b += cb; a += ca;
}
}
const n = SS * SS;
const o = (y * size + x) * 4;
out[o] = Math.round(clamp(r / n, 0, 255));
out[o + 1] = Math.round(clamp(g / n, 0, 255));
out[o + 2] = Math.round(clamp(b / n, 0, 255));
out[o + 3] = Math.round(clamp(a / n, 0, 1) * 255);
}
}
return out;
}
// ---------- main ----------
const outDir = process.argv[2] || '.';
const sizes = [16, 24, 32, 48, 64, 128, 256];
const images = sizes.map((s) => ({ size: s, png: pngEncode(s, s, render(s)) }));
fs.writeFileSync(path.join(outDir, 'obs.png'), images[images.length - 1].png);
fs.writeFileSync(path.join(outDir, 'obs-studio.ico'), icoEncode(images));
console.log('wrote obs.png (256x256) and obs-studio.ico (' + sizes.join(',') + ') to ' + outDir);