前端支持绘图引擎多例新建,切换,当前实例

This commit is contained in:
JackLee 2026-04-02 22:55:36 +08:00
parent c0d534af0a
commit 58a39f0ac9
3 changed files with 118 additions and 76 deletions

View File

@ -147,8 +147,8 @@ void NativeMgr::OnSurfaceCreated(OH_NativeXComponent *component, void *window) {
auto renderThread = std::make_shared<NativeRenderThread>(); auto renderThread = std::make_shared<NativeRenderThread>();
HILOG_ERROR(NATIVE_TAG,"uint64_t bfSize:%{public}dX%{public}d",bfWidth,bfHeight); HILOG_ERROR(NATIVE_TAG,"uint64_t bfSize:%{public}dX%{public}d",bfWidth,bfHeight);
rdThreads[crtXCompId] = renderThread; rdThreads[crtXCompId] = renderThread;
renderThread->InitRender(crtXCompId,bfWidth, bfHeight,reinterpret_cast<OHNativeWindow*>(window)); //renderThread->InitRender(crtXCompId,bfWidth, bfHeight,reinterpret_cast<OHNativeWindow*>(window));
renderThread->start(); //renderThread->start();
} }
} }
void NativeMgr::OnSurfaceDestroyed(OH_NativeXComponent *component, void *window) { void NativeMgr::OnSurfaceDestroyed(OH_NativeXComponent *component, void *window) {

View File

@ -2,18 +2,35 @@ import { TitleButton } from '../LayoutInterface/Interface/ButtonInterface';
import { CloseSubWindow, CreateAndShowSubWindow, WinInfo} from './SWBase'; import { CloseSubWindow, CreateAndShowSubWindow, WinInfo} from './SWBase';
import NativeOpenCAX from 'libopencax.so'; import NativeOpenCAX from 'libopencax.so';
import { mwInfo } from '../AppStorageV2Class'; import { mwInfo } from '../AppStorageV2Class';
import {NodeContent} from '@kit.ArkUI'; import { AppStorageV2, NodeContent} from '@kit.ArkUI';
import { ModelViewTab } from '../ModelViewTab';
export interface XComp{ @ObservedV2
nId?:string; export class XCompInfo{
xId?:string; @Trace nId?:string;
name?:string; @Trace xId?:string;
icon?:string; @Trace name?:string;
node?:NodeContent; @Trace icon?:string;
@Trace node?:NodeContent;
constructor(_nId?:string,_xId?: string, _name?: string,_icon?:string,_node?:NodeContent) {
this.nId = _nId ?? undefined;
this.xId = _xId ?? undefined;
this.name=_name?? undefined;
this.icon=_icon?? undefined;
this.node=_node?? undefined;
}
} }
export let XComps:Array<XComp>=[]; @ObservedV2
export let currentXComp:XComp={}; export class XCompInfos{
@Trace infos?:Array<XCompInfo>;
constructor(_infos?:Array<XCompInfo>) {
this.infos = _infos ?? undefined;
}
}
export let xcInfos:XCompInfos = AppStorageV2.connect<XCompInfos>(XCompInfos, () => new XCompInfos)!;
export let ctInfo: XCompInfo = AppStorageV2.connect<XCompInfo>(XCompInfo, () => new XCompInfo)!;
function XNRandomId(): string { function XNRandomId(): string {
// 获取当前时间戳(毫秒) // 获取当前时间戳(毫秒)
@ -30,35 +47,43 @@ function XNRandomId(): string {
// 调整范围到 [10000000, 99999999] // 调整范围到 [10000000, 99999999]
return (combined + 10000000).toString(); return (combined + 10000000).toString();
} }
export function InitXCompNode(name:string){ //初始化全局XComp管理
export function InitXCompNode(){
//数组为0表示初始化,Native侧这初始化主上下文,否则Native侧初始化共享上下文 //数组为0表示初始化,Native侧这初始化主上下文,否则Native侧初始化共享上下文
let ncInfo:XComp={}; const xcIs:XCompInfos = AppStorageV2.connect<XCompInfos>(XCompInfos, () => new XCompInfos)!;
ncInfo.nId='n_'+XNRandomId(); xcIs.infos=new Array<XCompInfo>;
ncInfo.xId='x_'+XNRandomId(); }
ncInfo.name=name+ncInfo.xId; //创建XComp组件
ncInfo.node=new NodeContent(); export function CreateXCompNode(name:string){
if(XComps.length==0) const xcIs:XCompInfos = AppStorageV2.connect<XCompInfos>(XCompInfos, () => new XCompInfos)!;
let xInfo:XCompInfo=new XCompInfo;
xInfo.nId='n_'+XNRandomId();
xInfo.xId='x_'+XNRandomId();
xInfo.name=name+xInfo.xId;
xInfo.node=new NodeContent();
if((xcIs.infos as Array<XCompInfo>).length>0)
{ {
NativeOpenCAX.InitNativeNode(ncInfo.nId,ncInfo.xId,true,ncInfo.node); NativeOpenCAX.InitNativeNode(xInfo.nId,xInfo.xId,true,xInfo.node);
}else{ }else{
NativeOpenCAX.InitNativeNode(ncInfo.nId,ncInfo.xId,false,ncInfo.node); NativeOpenCAX.InitNativeNode(xInfo.nId,xInfo.xId,false,xInfo.node);
} }
XComps.push(ncInfo); (xcIs.infos as Array<XCompInfo>).push(xInfo);
console.log(`ArkUI Node ID: ${ncInfo.nId}`); console.log(`ArkUI Node ID: ${xInfo.nId}`);
console.log(`ArkUI XComp ID: ${ncInfo.xId}`); console.log(`ArkUI XComp ID: ${xInfo.xId}`);
} }
//获取当前XComp组件
export function CurrentXCompIndex(id:number):XComp{ export function CurrentXCompIndex(id:number):XCompInfo{
return currentXComp=XComps[id]; const xcIs:XCompInfos = AppStorageV2.connect<XCompInfos>(XCompInfos, () => new XCompInfos)!;
return ctInfo=(xcIs.infos as Array<XCompInfo>)[id];
} }
//执行命令
export function ExecuteCommand(event:TitleButton){ export function ExecuteCommand(event:TitleButton){
//事件处理 //事件处理
if(event?.eEvent=='Execute_LoadModel'){ if(event?.eEvent=='Execute_LoadModel'){
//NativeOpenCAX.loadModel(undefined,undefined); //NativeOpenCAX.loadModel(undefined,undefined);
} }
if(event?.eEvent=='Create_New'){ if(event?.eEvent=='Create_New'){
InitXCompNode("nullptr"); CreateXCompNode("");
} }
//窗体打开 //窗体打开

View File

@ -1,67 +1,84 @@
import { hilog } from '@kit.PerformanceAnalysisKit'; import { hilog } from '@kit.PerformanceAnalysisKit';
import { MainWindowInfo } from './AppStorageV2Class'; import { MainWindowInfo } from './AppStorageV2Class';
import { AppStorageV2 } from '@kit.ArkUI'; import { AppStorageV2 } from '@kit.ArkUI';
import {InitXCompNode,XComps, XComp,CurrentXCompIndex} from './EventSubWin/ExCom' import {InitXCompNode,XCompInfos,XCompInfo,CurrentXCompIndex} from './EventSubWin/ExCom'
@ComponentV2 @ComponentV2
export struct ModelViewTab { export struct ModelViewTab {
@Local mwInfo: MainWindowInfo = AppStorageV2.connect<MainWindowInfo>(MainWindowInfo, () => new MainWindowInfo())!; @Local mwInfo: MainWindowInfo = AppStorageV2.connect<MainWindowInfo>(MainWindowInfo, () => new MainWindowInfo())!;
@Local xcInfos: XCompInfos = AppStorageV2.connect<XCompInfos>(XCompInfos, () => new XCompInfos)!;
//顶部导航组件 //顶部导航组件
private barTabs: TabsController = new TabsController(); private barTabs: TabsController = new TabsController();
//当前的顶部导航选择页 //当前的顶部导航选择页
@Local barFocusIndex: number = 0; @Local barFocusIndex: number = 0;
aboutToAppear(): void { aboutToAppear(): void {
InitXCompNode('测试') InitXCompNode()
} }
build() { build() {
Flex({ direction: FlexDirection.Column }) { Flex({ direction: FlexDirection.Column }) {
Scroll() { if((this.xcInfos.infos as Array<XCompInfo>).length>0){
Row() { Scroll() {
ForEach(XComps, (item: XComp, index: number) => { Row() {
Row({ space: 0 }) { ForEach(this.xcInfos.infos, (item: XCompInfo, index: number) => {
Image($r('app.media.startIcon')) Row({ space: 0 }) {
.width(this.mwInfo.mWinWidth*0.012) Image($r('app.media.startIcon'))
.height(this.mwInfo.mWinWidth*0.012) .width(this.mwInfo.mWinWidth*0.012)
.objectFit(ImageFit.Contain) .height(this.mwInfo.mWinWidth*0.012)
Button(item.name) .objectFit(ImageFit.Contain)
.fontWeight(index === this.barFocusIndex ? FontWeight.Bold : FontWeight.Normal) Button(item.name)
.width('auto') .fontWeight(index === this.barFocusIndex ? FontWeight.Bold : FontWeight.Normal)
.height(this.mwInfo.mWinWidth*0.012) .width('auto')
.type(ButtonType.Normal) .height(this.mwInfo.mWinWidth*0.012)
Button('X') .type(ButtonType.Normal)
.fontSize(12) Button('X')
.width(this.mwInfo.mWinWidth*0.012) .fontSize(12)
.height(this.mwInfo.mWinWidth*0.012) .width(this.mwInfo.mWinWidth*0.012)
.type(ButtonType.Normal) .height(this.mwInfo.mWinWidth*0.012)
.align(Alignment.Center) .type(ButtonType.Normal)
}.onClick(() => { .align(Alignment.Center)
this.barTabs.changeIndex(index); }.onClick(() => {
this.barFocusIndex = index; this.barTabs.changeIndex(index);
CurrentXCompIndex(index); this.barFocusIndex = index;
CurrentXCompIndex(index);
})
}) })
}
}.align(Alignment.Start)
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
//分割线
Divider().vertical(false).strokeWidth(1).color(0x000000).lineCap(LineCapStyle.Round).width('100%').backgroundColor(Color.Gray)
Tabs({ barPosition: BarPosition.Start, index: 0, controller: this.barTabs }) {
ForEach(this.xcInfos.infos,(item:XCompInfo, index: number)=>{
TabContent() {
ContentSlot(item.node);
}.align(Alignment.Start)
.padding(1)
}) })
} }.scrollable(false)
}.align(Alignment.Start) .barHeight(0)
.scrollable(ScrollDirection.Horizontal) .height('auto')
.scrollBar(BarState.Off) .barMode(BarMode.Fixed)
.width('100%')
//分割线 .barPosition(BarPosition.Start)
Divider().vertical(false).strokeWidth(1).color(0x000000).lineCap(LineCapStyle.Round).width('100%').backgroundColor(Color.Gray) .backgroundBlurStyle(BlurStyle.COMPONENT_THIN)
Tabs({ barPosition: BarPosition.Start, index: 0, controller: this.barTabs }) { .fadingEdge(true)
ForEach(XComps,(item:XComp, index: number)=>{ .barMode(BarMode.Scrollable)
TabContent() { .backgroundColor($r('sys.color.comp_background_secondary'))
ContentSlot(item.node); .divider({ strokeWidth: '1px', color: $r('sys.color.comp_divider') })
}.align(Alignment.Start) }else{
.padding(1) Image($r('app.media.base_background'))
}) }
}.scrollable(false)
.barHeight(0) }//.borderWidth('1')
.height('auto') //.borderColor(Color.Grey)
.barMode(BarMode.Fixed) //.height('auto')
}.borderWidth('1') //.backgroundColor('#f3f3f0')
.borderColor(Color.Grey)
.height('auto') .padding($r('sys.float.padding_level1'))
.backgroundColor('#f3f3f0') .backgroundImageSize({ width: '100%', height: '100%' })
.borderRadius($r('sys.float.corner_radius_level8'))
} }
} }