diff --git a/.github/workflows/native-compile-platforms.yml b/.github/workflows/native-compile-platforms.yml index eaf7a4c84bc..d9ac157c3d2 100644 --- a/.github/workflows/native-compile-platforms.yml +++ b/.github/workflows/native-compile-platforms.yml @@ -327,7 +327,7 @@ jobs: NATIVE_ROOT=$GITHUB_WORKSPACE/native echo "Compiling Openharmony ... " - cd $GITHUB_WORKSPACE/templates/openharmony + cd $GITHUB_WORKSPACE/templates/harmonyos-next echo "message(STATUS \"hook before \${CC_TARGET_NAME}\")" >> Pre-Sample.cmake echo "message(STATUS \"hook after \${CC_TARGET_NAME}\")" >> Post-Sample.cmake @@ -350,7 +350,7 @@ jobs: mkdir -p build-oh/assets - ASSET_DIR=$GITHUB_WORKSPACE/templates/openharmony/build-oh + ASSET_DIR=$GITHUB_WORKSPACE/templates/harmonyos-next/build-oh echo "=============== HACK ./entry/build-profile.json5 ===============" sed -i "s@[^-]DRES_DIR[^=]@$ASSET_DIR@g" ./entry/build-profile.json5 diff --git a/.github/workflows/package-size-check.js b/.github/workflows/package-size-check.js index ea58509b211..8f30f2e8099 100644 --- a/.github/workflows/package-size-check.js +++ b/.github/workflows/package-size-check.js @@ -11,7 +11,9 @@ const features = []; files.forEach(file => { const filePath = ps.join(exportsDir, file); const feature = ps.parse(ps.basename(filePath)).name; - features.push(feature); + if (feature !== 'vendor') { + features.push(feature); + } }); console.log(`features: [ ${features.join(', ')} ]`); diff --git a/@types/jsb.d.ts b/@types/jsb.d.ts index d53fb8658a2..418b3ec8394 100644 --- a/@types/jsb.d.ts +++ b/@types/jsb.d.ts @@ -357,6 +357,485 @@ declare namespace jsb { readonly thermalStatusNormalized: number; onThermalStatusChanged?: (previousStatus: number, newStatus: number, statusMin: number, statusMax: number) => void; } | undefined; + + /** + * @en Params containing the response code and the debug message from In-app Billing API response. + * @zh 包含应用内结算 API 响应代码和调试信息的参数 + */ + export interface BillingResult { + /** + * @en Debug message returned in In-app Billing API calls. + * @zh 应用内结算 API 调用中返回的调试消息。 + */ + readonly debugMessage: string; + /** + * @en Code returned in In-app Billing API calls. + * @zh 应用内结算 API 调用中返回的响应代码。 + */ + readonly responseCode: string; + readonly toStr: string; + } + + /** + * @en Represents the offer details to buy an one-time purchase product. + * @zh 代表一次性购买产品的报价详情。 + */ + export interface OneTimePurchaseOfferDetails { + /** + * @en The price for the payment in micro-units, where 1,000,000 micro-units equal one unit of the currency. + * @zh 以微单位返回支付价格,其中 1,000,000 个微单位等于 1 个货币单位。 + */ + readonly priceAmountMicros: number; + /** + * @en Formatted price for the payment, including its currency sign. + * @zh 支付的格式化价格,包括其货币单位。 + */ + readonly formattedPrice: string; + /** + * @en ISO 4217 currency code for price. + * @zh 价格的 ISO 4217 货币代码。 + */ + readonly priceCurrencyCode: string; + } + + /** + * @en Represents additional details of an installment subscription plan. + * @zh 表示分期付款订阅计划的附加详细信息。 + */ + export interface InstallmentPlanDetails { + /** + * @en Committed payments count after a user signs up for this subscription plan. + * @zh 用户注册此订阅计划后承诺的付款数量。 + */ + readonly installmentPlanCommitmentPaymentsCount: number; + /** + * @en Subsequent committed payments count after this subscription plan renews. + * @zh 此订阅计划续订后的后续承诺付款数量。 + */ + readonly subsequentInstallmentPlanCommitmentPaymentsCount: number; + } + + /** + * @en Represents a pricing phase, describing how a user pays at a point in time. + * @zh 表示定价阶段,描述用户在某个时间点如何付款。 + */ + export interface PricingPhase { + /** + * @en Number of cycles for which the billing period is applied. + * @zh 计费周期适用的周期数。 + */ + readonly billingCycleCount: number; + /** + * @en The price for the payment cycle in micro-units, where 1,000,000 micro-units equal one unit of the currency. + * @zh 微单位付款周期的价格,其中 1,000,000 个微单位等于 1 个货币单位。 + */ + readonly priceAmountMicros: number; + /** + * @en RecurrenceMode for the pricing phase. + * @zh 定价阶段的RecurrenceMode。 + */ + readonly recurrenceMode: number; + /** + * @en Billing period for which the given price applies, specified in ISO 8601 format. + * @zh 给定价格适用的计费期,以 ISO 8601 格式指定。 + */ + readonly billingPeriod: string; + /** + * @en Formatted price for the payment cycle, including its currency sign. + * @zh 付款周期的格式化价格,包括其货币符号。 + */ + readonly formattedPrice: string; + /** + * @en Returns ISO 4217 currency code for price. + * @zh 返回价格的 ISO 4217 货币代码。 + */ + readonly priceCurrencyCode: string; + } + + /** + * @en Represents the available purchase plans to buy a subscription product. + * @zh 代表一次性购买产品的报价详情。 + */ + export interface SubscriptionOfferDetails { + /** + * @en The base plan id associated with the subscription product. + * @zh 与订阅产品相关的基本计划 ID。 + */ + readonly basePlanId: string; + /** + * @en The offer id associated with the subscription product. + * @zh 与订阅产品相关的优惠 ID。 + */ + readonly offerId: string; + /** + * @en The offer tags associated with this Subscription Offer. + * @zh 与此订阅优惠相关的优惠标签。 + */ + readonly offerTags: string[]; + /** + * @en The offer token required to pass in launchBillingFlow to purchase the subscription product with these pricing phases. + * @zh 在 launchBillingFlow 中传递以使用这些定价阶段购买订阅产品所需的优惠令牌。 + */ + readonly offerToken: string; + /** + * @en The pricing phases for the subscription product. + * @zh 订阅产品的定价区间。 + */ + readonly pricingPhaseList: PricingPhase[]; + /** + * @en The additional details of an installment plan. + * @zh 分期付款计划的附加详细信息。 + */ + readonly installmentPlanDetails: InstallmentPlanDetails; + } + /** + * @en Represents the details of a one time or subscription product. + * @zh 代表一次性或订阅产品的详细信息。 + */ + export interface ProductDetails { + /** + * @en Hash code + * @zh hash值 + */ + readonly hashCode: number; + /** + * @en The description of the product. + * @zh 产品的描述。 + */ + readonly description: string; + /** + * @en The name of the product being sold. + * @zh 所售产品的名称。 + */ + readonly name: string; + /** + * @en The product's Id. + * @zh 产品的 ID。 + */ + readonly productId: string; + /** + * @en The ProductType of the product. + * @zh ProductType产品的。 + */ + readonly productType: string; + /** + * @en The title of the product being sold. + * @zh 所售产品的标题。 + */ + readonly title: string; + /** + * @en To string + * @zh 转换成字符串 + */ + readonly toStr: string; + /** + * @en The offer details of an one-time purchase product. + * @zh 代表一次性购买产品的报价详情。 + */ + readonly oneTimePurchaseOfferDetails: OneTimePurchaseOfferDetails; + /** + * @en A list containing all available offers to purchase a subscription product. + * @zh 返回包含购买订阅产品的所有可用优惠的列表。 + */ + readonly subscriptionOfferDetails: SubscriptionOfferDetails[]; + } + + /** + * @en Account identifiers that were specified when the purchase was made. + * @zh 购买时指定的帐户标识符。 + */ + export interface AccountIdentifiers { + /** + * @en The obfuscated account id specified in setObfuscatedAccountId. + * @zh 在setObfuscatedAccountId中设置的混淆账户id + */ + readonly obfuscatedAccountId: string; + /** + * @en The obfuscated profile id specified in setObfuscatedProfileId. + * @zh 在setObfuscatedProfileId中设置的混淆profile id + */ + readonly obfuscatedProfileId: string; + } + + /** + * @en Represents a pending change/update to the existing purchase. + * @zh 表示对现有购买的待定更改/更新。 + */ + export interface PendingPurchaseUpdate { + /** + * @en A token that uniquely identifies this pending transaction. + * @zh 唯一标识此待处理交易的令牌。 + */ + readonly purchaseToken: string; + /** + * @en The product ids. + * @zh 产品 ID。 + */ + readonly products: string[]; + } + + /** + * @en Represents an in-app billing purchase. + * @zh 代表应用内billing购买。 + */ + export interface Purchase { + /** + * @en One of PurchaseState indicating the state of the purchase. + * @zh PurchaseState表示购买状态的其中一个值。 + */ + readonly purchaseState: number; + /** + * @en The time the product was purchased, in milliseconds since the epoch (Jan 1, 1970). + * @zh 产品购买的时间,以纪元(1970 年 1 月 1 日)以来的毫秒数表示。 + */ + readonly purchaseTime: number; + /** + * @en Indicates whether the purchase has been acknowledged. + * @zh 表示是否已确认购买。 + */ + readonly isAcknowledged: number; + /** + * @en Indicates whether the subscription renews automatically. + * @zh 指示订阅是否自动续订。 + */ + readonly isAutoRenewing: number; + /** + * @en Hash code + * @zh hash值 + */ + readonly hashCode: number; + + /** + * @en The quantity of the purchased product. + * @zh 购买产品的数量。 + */ + readonly quantity: number; + /** + * @en The payload specified when the purchase was acknowledged or consumed. + * @zh 确认或消费购买时指定的有效负载。 + */ + readonly developerPayload: string; + /** + * @en Returns a unique order identifier for the transaction. + * @zh 交易的唯一订单标识符。 + */ + readonly orderId: string; + /** + * @en Returns a String in JSON format that contains details about the purchase order. + * @zh 包含有关采购订单详细信息的 JSON 格式的字符串。 + */ + readonly originalJson: string; + /** + * @en The application package from which the purchase originated. + * @zh 购买来源的应用程序包。 + */ + readonly packageName: string; + /** + * @en A token that uniquely identifies a purchase for a given item and user pair. + * @zh 唯一标识给定商品和用户对的购买的令牌。 + */ + readonly purchaseToken: string; + /** + * @en String containing the signature of the purchase data that was signed with the private key of the developer. + * @zh 包含使用开发者私钥签名的购买数据签名的字符串。 + */ + readonly signature: string; + /** + * @en To string + * @zh 转换成字符串 + */ + readonly toStr: string; + + /** + * @en Returns account identifiers that were provided when the purchase was made. + * @zh 返回购买时提供的帐户标识符。 + */ + readonly accountIdentifiers: AccountIdentifiers; + /** + * @en The PendingPurchaseUpdate for an uncommitted transaction. + * @zh 返回PendingPurchaseUpdate未提交的事务。 + */ + readonly pendingPurchaseUpdate: PendingPurchaseUpdate; + /** + * @en the product Ids. + * @zh 产品 ID。 + */ + readonly products: string[]; + } + + export interface BillingConfig { + /** + * @en The customer's country code. + * @zh 客户的国家代码。 + */ + readonly countryCode: string; + } + + /** + * @en The details used to report transactions made via alternative billing without user choice to use Google Play Billing. + * @zh 用于报告用户未选择使用 Google Play Billing方式而通过替代Billing方式进行的交易的详细信息。 + */ + export interface AlternativeBillingOnlyReportingDetails { + /** + * @en An external transaction token that can be used to report a transaction made via alternative billing + * without user choice to use Google Play billing. + * @zh 返回一个外部交易令牌,该令牌可用于报告通过替代付款方式进行的交易,而无需用户选择使用 Google Play 付款方式。 + */ + readonly externalTransactionToken: string; + } + + /** + * @en The details used to report transactions made via external offer. + * @zh 用于报告通过外部报价进行的交易的详细信息。 + */ + export interface ExternalOfferReportingDetails { + /** + * @en An external transaction token that can be used to report a transaction made via external offer. + * @zh 可用于报告通过外部报价进行的交易的外部交易令牌。 + */ + readonly externalTransactionToken: string; + } + + /** + * @en Results related to in-app messaging. + * @zh 与应用程序内消息相关的结果。 + */ + export interface InAppMessageResult { + /** + * @en Response code for the in-app messaging API call. + * @zh 应用内消息传递 API 调用的响应代码。 + */ + readonly responseCode: number; + /** + * @en Token that identifies the purchase to be acknowledged, if any. + * @zh 返回标识需要确认的购买的令牌。 + */ + readonly purchaseToken: string; + } + + /** + * @en Main interface for communication between the Google Play library and user application code. + * @zh 产品 ID。 + */ + const googleBilling: { + /** + * @en Starts up BillingClient setup process asynchronously. + * @zh 异步启动 BillingClient 设置过程。 + */ + startConnection(): void; + + /** + * @en Closes the connection and releases all held resources such as service connections. + * @zh 关闭连接并释放所有持有的资源,例如服务连接。 + */ + endConnection(): void; + + /** + * @en Get the current billing client connection state. + * @zh 获取当前计费客户端连接状态。 + */ + getConnectionState(): number; + + /** + * @en Checks if the client is currently connected to the service, so that requests to other methods will succeed. + Returns true if the client is currently connected to the service, false otherwise. + * @zh 检查客户端当前是否连接到服务,以便对其他方法的请求能够成功。 + 如果客户端当前已连接到服务,则返回 true,否则返回 false。 + */ + isReady(): boolean; + + /** + * @en Performs a network query the details of products available for sale in your app. + * @zh 执行网络查询您的应用中可供销售的产品的详细信息。 + */ + queryProductDetailsParams(productId: string[], productType: string): void; + /** + * @en Initiates the billing flow for an in-app purchase or subscription. + * @zh 启动应用内购买或订阅的计费流程。 + */ + launchBillingFlow(productDetails: ProductDetails[], selectedOfferToken: string | null): void; + /** + * @en Consumes a given in-app product. + * @zh 消费指定的应用内产品。 + */ + consumePurchases(purchases: Purchase[]): void; + /** + * @en Returns purchases details for currently owned items bought within your app. + * @zh 返回您应用内当前拥有的购买商品的购买详情。 + */ + queryPurchasesAsync(productType: string): void; + /** + * @en Acknowledges in-app purchases.. + * @zh 确认应用内购买。 + */ + acknowledgePurchase(purchases: Purchase[]): void; + /** + * @en Gets the billing config, which stores configuration used to perform billing operations. + * @zh 获取计费配置,其中存储用于执行计费操作的配置。 + */ + getBillingConfigAsync(): void; + + /** + * @en Creates alternative billing only purchase details that can be used to report a transaction made via alternative billing without user choice to use Google Play billing. + * @zh 创建仅限替代结算的购买详情,可用于报告通过替代结算进行的交易,而无需用户选择使用 Google Play Billing。 + */ + createAlternativeBillingOnlyReportingDetailsAsync(): void; + /** + * @en Checks the availability of offering alternative billing without user choice to use Google Play Billing. + * @zh 检查是否可以提供替代结算方式,而无需用户选择使用 Google Play Billing方式。 + */ + isAlternativeBillingOnlyAvailableAsync(): void; + + /** + * @en Creates purchase details that can be used to report a transaction made via external offer. + * @zh 创建可用于报告通过外部报价进行的交易的购买详情。 + */ + createExternalOfferReportingDetailsAsync(): void; + /** + * @en Checks the availability of providing external offer. + * @zh 检查提供外部报价的可用性。 + */ + isExternalOfferAvailableAsync(): void; + + /** + * @en Checks if the specified feature or capability is supported by the Play Store. + * @zh 检查 Play Store 是否支持指定的功能。 + */ + isFeatureSupported(feature: string): BillingResult; + + /** + * @en Shows the alternative billing only information dialog on top of the calling app. + * @zh 在调用应用程序顶部显示仅显示备用计费信息对话框。 + */ + showAlternativeBillingOnlyInformationDialog(): BillingResult; + + /** + * @en Shows the external offer information dialog on top of the calling app. + * @zh 在调用应用程序顶部显示外部优惠信息对话框。 + */ + showExternalOfferInformationDialog(): BillingResult; + + /** + * @en Overlays billing related messages on top of the calling app. + * @zh 在调用应用程序上叠加与计费相关的消息。 + */ + showInAppMessages(): BillingResult; + } | undefined; + export let onBillingSetupFinished: (result: BillingResult) => void | undefined; + export let onBillingServiceDisconnected: () => void | undefined; + export let onProductDetailsResponse: (result: BillingResult, productDetailsList: ProductDetails[]) => void | undefined; + export let onPurchasesUpdated: (result: BillingResult, purchaseList: Purchase[]) => void | undefined; + export let onConsumeResponse: (result: BillingResult, purchaseToken: string) => void | undefined; + export let onAcknowledgePurchaseResponse: (result: BillingResult) => void | undefined; + export let onQueryPurchasesResponse: (result: BillingResult, purchaseList: Purchase[]) => void | undefined; + export let onBillingConfigResponse: (result: BillingResult, config: BillingConfig) => void | undefined; + export let onAlternativeBillingOnlyTokenResponse: (result: BillingResult, details: AlternativeBillingOnlyReportingDetails) => void | undefined; + export let onExternalOfferReportingDetailsResponse: (result: BillingResult, details: ExternalOfferReportingDetails) => void | undefined; + export let onAlternativeBillingOnlyAvailabilityResponse: (result: BillingResult) => void | undefined; + export let onExternalOfferAvailabilityResponse: (result: BillingResult) => void | undefined; + export let onAlternativeBillingOnlyInformationDialogResponse: (result: BillingResult) => void | undefined; + export let onExternalOfferInformationDialogResponse: (result: BillingResult) => void | undefined; + export let onInAppMessageResponse: (result: InAppMessageResult) => void | undefined; } declare namespace ns { diff --git a/@types/webGPU.d.ts b/@types/webGPU.d.ts index 8b2bebe872b..4d8b09d919d 100644 --- a/@types/webGPU.d.ts +++ b/@types/webGPU.d.ts @@ -68,15 +68,8 @@ type GPUColor = | GPUColorDict; type GPUColorWriteFlags = number; -type GPUDepthBias = - number; -type GPUExtent3D = - - | Iterable - | GPUExtent3DDict; -type GPUFlagsConstant = - number; -type GPUImageCopyExternalImageSource = +declare interface VideoFrame {} +type GPUCopyExternalImageSource = | ImageBitmap | ImageData @@ -85,6 +78,14 @@ type GPUImageCopyExternalImageSource = | VideoFrame | HTMLCanvasElement | OffscreenCanvas; +type GPUDepthBias = + number; +type GPUExtent3D = + + | Iterable + | GPUExtent3DDict; +type GPUFlagsConstant = + number; type GPUIndex32 = number; type GPUIntegerCoordinate = @@ -142,7 +143,11 @@ type GPUBlendFactor = | 'one-minus-dst-alpha' | 'src-alpha-saturated' | 'constant' - | 'one-minus-constant'; + | 'one-minus-constant' + | 'src1' + | 'one-minus-src1' + | 'src1-alpha' + | 'one-minus-src1-alpha'; type GPUBlendOperation = | 'add' @@ -164,6 +169,10 @@ type GPUCanvasAlphaMode = | 'opaque' | 'premultiplied'; +type GPUCanvasToneMappingMode = + + | 'standard' + | 'extended'; type GPUCompareFunction = | 'never' @@ -198,14 +207,19 @@ type GPUFeatureName = | 'depth-clip-control' | 'depth32float-stencil8' | 'texture-compression-bc' + | 'texture-compression-bc-sliced-3d' | 'texture-compression-etc2' | 'texture-compression-astc' + | 'texture-compression-astc-sliced-3d' | 'timestamp-query' | 'indirect-first-instance' | 'shader-f16' | 'rg11b10ufloat-renderable' | 'bgra8unorm-storage' - | 'float32-filterable'; + | 'float32-filterable' + | 'float32-blendable' + | 'clip-distances' + | 'dual-source-blending'; type GPUFilterMode = | 'nearest' @@ -393,22 +407,31 @@ type GPUTextureViewDimension = | '3d'; type GPUVertexFormat = + | 'uint8' | 'uint8x2' | 'uint8x4' + | 'sint8' | 'sint8x2' | 'sint8x4' + | 'unorm8' | 'unorm8x2' | 'unorm8x4' + | 'snorm8' | 'snorm8x2' | 'snorm8x4' + | 'uint16' | 'uint16x2' | 'uint16x4' + | 'sint16' | 'sint16x2' | 'sint16x4' + | 'unorm16' | 'unorm16x2' | 'unorm16x4' + | 'snorm16' | 'snorm16x2' | 'snorm16x4' + | 'float16' | 'float16x2' | 'float16x4' | 'float32' @@ -423,7 +446,8 @@ type GPUVertexFormat = | 'sint32x2' | 'sint32x3' | 'sint32x4' - | 'unorm10-10-10-2'; + | 'unorm10-10-10-2' + | 'unorm8x4-bgra'; type GPUVertexStepMode = | 'vertex' @@ -458,6 +482,9 @@ interface GPUBindGroupEntry { interface GPUBindGroupLayoutDescriptor extends GPUObjectDescriptorBase { + /** + * A list of entries describing the shader resource bindings for a bind group. + */ entries: Iterable; } @@ -574,7 +601,7 @@ interface GPUBufferBindingLayout { */ minBindingSize?: GPUSize64; } -type PredefinedGPUColorSpace = 'display-p3' | 'srgb'; + interface GPUBufferDescriptor extends GPUObjectDescriptorBase { /** @@ -625,7 +652,12 @@ interface GPUCanvasConfiguration { * The color space that values written into textures returned by * {@link GPUCanvasContext#getCurrentTexture} should be displayed with. */ - colorSpace?: PredefinedGPUColorSpace; + colorSpace?: PredefinedColorSpace; + /** + * The tone mapping determines how the content of textures returned by + * {@link GPUCanvasContext#getCurrentTexture} are to be displayed. + */ + toneMapping?: GPUCanvasToneMapping; /** * Determines the effect that alpha values will have on the content of textures returned by * {@link GPUCanvasContext#getCurrentTexture} when read, displayed, or used as an image source. @@ -633,6 +665,25 @@ interface GPUCanvasConfiguration { alphaMode?: GPUCanvasAlphaMode; } +interface GPUCanvasConfigurationOut + extends Required< + Omit< + GPUCanvasConfiguration, + 'toneMapping' + > + > { + /** {@inheritDoc GPUCanvasConfiguration.viewFormats} */ + viewFormats: GPUTextureFormat[]; + /** + * {@inheritDoc GPUCanvasConfiguration.toneMapping} + */ + toneMapping?: GPUCanvasToneMapping; +} + +interface GPUCanvasToneMapping { + mode?: GPUCanvasToneMappingMode; +} + interface GPUColorDict { /** * The red channel value. @@ -709,6 +760,53 @@ interface GPUComputePipelineDescriptor compute: GPUProgrammableStage; } +interface GPUCopyExternalImageDestInfo + extends GPUTexelCopyTextureInfo { + /** + * Describes the color space and encoding used to encode data into the destination texture. + * This [[#color-space-conversions|may result]] in values outside of the range [0, 1] + * being written to the target texture, if its format can represent them. + * Otherwise, the results are clamped to the target texture format's range. + * Note: + * If {@link GPUCopyExternalImageDestInfo#colorSpace} matches the source image, + * conversion may not be necessary. See [[#color-space-conversion-elision]]. + */ + colorSpace?: PredefinedColorSpace; + /** + * Describes whether the data written into the texture should have its RGB channels + * premultiplied by the alpha channel, or not. + * If this option is set to `true` and the {@link GPUCopyExternalImageSourceInfo#source} is also + * premultiplied, the source RGB values must be preserved even if they exceed their + * corresponding alpha values. + * Note: + * If {@link GPUCopyExternalImageDestInfo#premultipliedAlpha} matches the source image, + * conversion may not be necessary. See [[#color-space-conversion-elision]]. + */ + premultipliedAlpha?: boolean; +} + +interface GPUCopyExternalImageSourceInfo { + /** + * The source of the texel copy. The copy source data is captured at the moment that + * {@link GPUQueue#copyExternalImageToTexture} is issued. Source size is determined as described + * by the external source dimensions table. + */ + source: GPUCopyExternalImageSource; + /** + * Defines the origin of the copy - the minimum (top-left) corner of the source sub-region to copy from. + * Together with `copySize`, defines the full copy sub-region. + */ + origin?: GPUOrigin2D; + /** + * Describes whether the source image is vertically flipped, or not. + * If this option is set to `true`, the copy is flipped vertically: the bottom row of the source + * region is copied into the first row of the destination region, and so on. + * The {@link GPUCopyExternalImageSourceInfo#origin} option is still relative to the top-left corner + * of the source image, increasing downward. + */ + flipY?: boolean; +} + interface GPUDepthStencilState { /** * The {@link GPUTextureViewDescriptor#format} of {@link GPURenderPassDescriptor#depthStencilAttachment} @@ -744,15 +842,15 @@ interface GPUDepthStencilState { */ stencilWriteMask?: GPUStencilValue; /** - * Constant depth bias added to each fragment. See [$biased fragment depth$] for details. + * Constant depth bias added to each triangle fragment. See [$biased fragment depth$] for details. */ depthBias?: GPUDepthBias; /** - * Depth bias that scales with the fragment’s slope. See [$biased fragment depth$] for details. + * Depth bias that scales with the triangle fragment’s slope. See [$biased fragment depth$] for details. */ depthBiasSlopeScale?: number; /** - * The maximum depth bias of a fragment. See [$biased fragment depth$] for details. + * The maximum depth bias of a triangle fragment. See [$biased fragment depth$] for details. */ depthBiasClamp?: number; } @@ -769,9 +867,9 @@ interface GPUDeviceDescriptor /** * Specifies the limits that are required by the device request. * The request will fail if the adapter cannot provide these limits. - * Each key must be the name of a member of supported limits. - * Exactly the specified limits, and no limit/better or worse, - * will be allowed in validation of API calls on the resulting device. + * Each key with a non-`undefined` value must be the name of a member of supported limits. + * API calls on the resulting device perform validation according to the exact limits of the + * device (not the adapter; see [[#limits]]). * + + + + + + + + + + + + + + diff --git a/templates/google-play/template/app/build.gradle b/templates/google-play/template/app/build.gradle new file mode 100644 index 00000000000..184a68947f0 --- /dev/null +++ b/templates/google-play/template/app/build.gradle @@ -0,0 +1,113 @@ +import org.apache.tools.ant.taskdefs.condition.Os + +apply plugin: 'com.android.application' + +RES_PATH = RES_PATH.replace("\\", "/") +COCOS_ENGINE_PATH = COCOS_ENGINE_PATH.replace("\\", "/") + +buildDir = "${RES_PATH}/proj/build/${project.name ==~ /^[_a-zA-Z0-9-]+$/ ? project.name : 'CocosGame'}" +android { + compileSdkVersion PROP_COMPILE_SDK_VERSION.toInteger() + buildToolsVersion PROP_BUILD_TOOLS_VERSION + ndkPath PROP_NDK_PATH + namespace APPLICATION_ID + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + defaultConfig { + applicationId APPLICATION_ID + minSdkVersion PROP_MIN_SDK_VERSION + targetSdkVersion PROP_TARGET_SDK_VERSION + versionCode 1 + versionName "1.0" + + externalNativeBuild { + cmake { + targets "cocos" + arguments "-DRES_DIR=${RES_PATH}", "-DANDROID_STL=c++_static", "-DANDROID_TOOLCHAIN=clang", "-DANDROID_ARM_NEON=TRUE" + } + ndk { abiFilters PROP_APP_ABI.split(':') } + } + } + + sourceSets.main { + java.srcDirs "../src", "src" + res.srcDirs "../res", 'res', "${RES_PATH}/proj/res" + jniLibs.srcDirs "../libs", 'libs' + manifest.srcFile "AndroidManifest.xml" + assets.srcDir "${RES_PATH}/data" + jniLibs { + // Vulkan validation layer + // srcDir "${android.ndkDirectory}/sources/third_party/vulkan/src/build-android/jniLibs" + } + } + + externalNativeBuild { + cmake { + version "3.22.1" + path "../CMakeLists.txt" + buildStagingDirectory "${RES_PATH}/proj/build" + } + } + + signingConfigs { + + release { + if (project.hasProperty("RELEASE_STORE_FILE") && !RELEASE_STORE_FILE.isEmpty()) { + storeFile file(RELEASE_STORE_FILE) + storePassword RELEASE_STORE_PASSWORD + keyAlias RELEASE_KEY_ALIAS + keyPassword RELEASE_KEY_PASSWORD + } + } + } + + buildTypes { + release { + debuggable false + jniDebuggable false + renderscriptDebuggable false + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + if (project.hasProperty("RELEASE_STORE_FILE")) { + signingConfig signingConfigs.release + } + + externalNativeBuild { + cmake { + // switch HIDE_SYMBOLS to OFF to skip compilation flag `-fvisibility=hidden` + arguments "-DHIDE_SYMBOLS=ON" + } + } + + if (!Boolean.parseBoolean(PROP_IS_DEBUG)) { + getIsDefault().set(true) + } + + } + + debug { + debuggable true + jniDebuggable true + renderscriptDebuggable true + // resValue "string", "app_name", "${PROP_APP_NAME}-dbg" + // applicationIdSuffix ".debug" + } + } +} + +dependencies { + implementation fileTree(dir: '../libs', include: ['*.jar','*.aar']) + implementation fileTree(dir: 'libs', include: ['*.jar','*.aar']) + implementation fileTree(dir: "${COCOS_ENGINE_PATH}/cocos/platform/android/java/libs", include: ['*.jar']) + implementation project(':libservice') + implementation project(':libcocos') + if (Boolean.parseBoolean(PROP_ENABLE_INPUTSDK)) { + implementation 'com.google.android.libraries.play.games:inputmapping:1.1.0-beta' + implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.10" + } +} diff --git a/templates/google-play/template/app/proguard-rules.pro b/templates/google-play/template/app/proguard-rules.pro new file mode 100644 index 00000000000..fc884b76762 --- /dev/null +++ b/templates/google-play/template/app/proguard-rules.pro @@ -0,0 +1,54 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in E:\developSoftware\Android\SDK/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Proguard Cocos2d-x-lite for release +-keep public class com.cocos.** { *; } +-dontwarn com.cocos.** + +# Proguard Apache HTTP for release +-keep class org.apache.http.** { *; } +-dontwarn org.apache.http.** + +# Proguard okhttp for release +-keep class okhttp3.** { *; } +-dontwarn okhttp3.** + +-keep class okio.** { *; } +-dontwarn okio.** + +# Proguard Android Webivew for release. you can comment if you are not using a webview +-keep public class android.net.http.SslError +-keep public class android.webkit.WebViewClient + +-keep public class com.google.** { *; } + +-dontwarn android.webkit.WebView +-dontwarn android.net.http.SslError +-dontwarn android.webkit.WebViewClient + +# This is generated automatically by the Android Gradle plugin. +-dontwarn android.hardware.BatteryState +-dontwarn android.hardware.lights.Light +-dontwarn android.hardware.lights.LightState$Builder +-dontwarn android.hardware.lights.LightState +-dontwarn android.hardware.lights.LightsManager$LightsSession +-dontwarn android.hardware.lights.LightsManager +-dontwarn android.hardware.lights.LightsRequest$Builder +-dontwarn android.hardware.lights.LightsRequest +-dontwarn android.net.ssl.SSLSockets +-dontwarn android.os.VibratorManager \ No newline at end of file diff --git a/templates/google-play/template/app/src/com/cocos/game/AppActivity.java b/templates/google-play/template/app/src/com/cocos/game/AppActivity.java new file mode 100644 index 00000000000..5aaece88515 --- /dev/null +++ b/templates/google-play/template/app/src/com/cocos/game/AppActivity.java @@ -0,0 +1,125 @@ +/**************************************************************************** +Copyright (c) 2015-2016 Chukong Technologies Inc. +Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +package com.cocos.game; + +import android.os.Bundle; +import android.content.Intent; +import android.content.res.Configuration; + +import com.cocos.service.SDKWrapper; +import com.cocos.lib.CocosActivity; + +public class AppActivity extends CocosActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // DO OTHER INITIALIZATION BELOW + SDKWrapper.shared().init(this); + + } + + @Override + protected void onResume() { + super.onResume(); + SDKWrapper.shared().onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + SDKWrapper.shared().onPause(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + // Workaround in https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508 + if (!isTaskRoot()) { + return; + } + SDKWrapper.shared().onDestroy(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + SDKWrapper.shared().onActivityResult(requestCode, resultCode, data); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + SDKWrapper.shared().onNewIntent(intent); + } + + @Override + protected void onRestart() { + super.onRestart(); + SDKWrapper.shared().onRestart(); + } + + @Override + protected void onStop() { + super.onStop(); + SDKWrapper.shared().onStop(); + } + + @Override + public void onBackPressed() { + SDKWrapper.shared().onBackPressed(); + super.onBackPressed(); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + SDKWrapper.shared().onConfigurationChanged(newConfig); + super.onConfigurationChanged(newConfig); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + SDKWrapper.shared().onRestoreInstanceState(savedInstanceState); + super.onRestoreInstanceState(savedInstanceState); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + SDKWrapper.shared().onSaveInstanceState(outState); + super.onSaveInstanceState(outState); + } + + @Override + protected void onStart() { + SDKWrapper.shared().onStart(); + super.onStart(); + } + + @Override + public void onLowMemory() { + SDKWrapper.shared().onLowMemory(); + super.onLowMemory(); + } +} diff --git a/templates/google-play/template/build-cfg.json b/templates/google-play/template/build-cfg.json new file mode 100644 index 00000000000..fb658e29853 --- /dev/null +++ b/templates/google-play/template/build-cfg.json @@ -0,0 +1,8 @@ +{ + "ndk_module_path" :[ + "${COCOS_ROOT}", + "${COCOS_ROOT}/cocos", + "${COCOS_ROOT}/external" + ], + "copy_resources": [] +} diff --git a/templates/google-play/template/build.gradle b/templates/google-play/template/build.gradle new file mode 100644 index 00000000000..84203e08ee1 --- /dev/null +++ b/templates/google-play/template/build.gradle @@ -0,0 +1,28 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + + repositories { + google() + mavenCentral() + // jcenter() // keeped as anchor, will be removed soon + } + dependencies { + classpath 'com.android.tools.build:gradle:8.0.2' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + mavenCentral() + // jcenter() // keeped as anchor, will be removed soon + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/templates/google-play/template/instantapp/AndroidManifest.xml b/templates/google-play/template/instantapp/AndroidManifest.xml new file mode 100644 index 00000000000..0216ac9da8f --- /dev/null +++ b/templates/google-play/template/instantapp/AndroidManifest.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/google-play/template/instantapp/build.gradle b/templates/google-play/template/instantapp/build.gradle new file mode 100644 index 00000000000..4336667f2c4 --- /dev/null +++ b/templates/google-play/template/instantapp/build.gradle @@ -0,0 +1,100 @@ +import org.apache.tools.ant.taskdefs.condition.Os + +apply plugin: 'com.android.application' + +RES_PATH = RES_PATH.replace("\\", "/") +COCOS_ENGINE_PATH = COCOS_ENGINE_PATH.replace("\\", "/") +buildDir = "${RES_PATH}/proj/build/instantapp" + +android { + compileSdkVersion PROP_COMPILE_SDK_VERSION.toInteger() + buildToolsVersion PROP_BUILD_TOOLS_VERSION + ndkPath PROP_NDK_PATH + namespace APPLICATION_ID + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + defaultConfig { + minSdkVersion PROP_MIN_SDK_VERSION + targetSdkVersion PROP_TARGET_SDK_VERSION + versionCode 1 + versionName "1.0" + + externalNativeBuild { + cmake { + targets "cocos" + arguments "-DRES_DIR=${RES_PATH}", "-DCOCOS_X_PATH=${COCOS_ENGINE_PATH}","-DANDROID_STL=c++_static", "-DANDROID_TOOLCHAIN=clang", "-DANDROID_ARM_NEON=TRUE", "-DANDROID_LD=gold" + cppFlags "-frtti -fexceptions -fsigned-char -DANDROID_INSTANT=1" + } + ndk { abiFilters PROP_APP_ABI.split(':') } + } + } + + sourceSets.main { + java.srcDirs "../src", "src" + res.srcDirs "../res", 'res', "${RES_PATH}/proj/res" + jniLibs.srcDirs "../libs", 'libs' + manifest.srcFile "AndroidManifest.xml" + assets.srcDir "${RES_PATH}/data" + } + + externalNativeBuild { + cmake { + version "3.22.1" + path "../CMakeLists.txt" + buildStagingDirectory "${RES_PATH}/proj/build" + } + } + + signingConfigs { + + release { + if (project.hasProperty("RELEASE_STORE_FILE") && !RELEASE_STORE_FILE.isEmpty()) { + storeFile file(RELEASE_STORE_FILE) + storePassword RELEASE_STORE_PASSWORD + keyAlias RELEASE_KEY_ALIAS + keyPassword RELEASE_KEY_PASSWORD + } + } + } + + buildTypes { + release { + debuggable false + jniDebuggable false + renderscriptDebuggable false + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + if (project.hasProperty("RELEASE_STORE_FILE")) { + signingConfig signingConfigs.release + } + + externalNativeBuild { + cmake { + // switch HIDE_SYMBOLS to OFF to skip compilation flag `-fvisibility=hidden` + arguments "-DHIDE_SYMBOLS=ON" + } + } + } + + debug { + debuggable true + jniDebuggable true + renderscriptDebuggable true + // resValue "string", "app_name", "${PROP_APP_NAME}-dbg" + // applicationIdSuffix ".debug" + } + } +} + +dependencies { + implementation fileTree(dir: '../libs', include: ['*.jar','*.aar']) + implementation fileTree(dir: 'libs', include: ['*.jar','*.aar']) + implementation fileTree(dir: "${COCOS_ENGINE_PATH}/cocos/platform/android/java/libs", include: ['*.jar']) + implementation project(':libservice') + implementation project(':libcocos') +} diff --git a/templates/google-play/template/instantapp/proguard-rules.pro b/templates/google-play/template/instantapp/proguard-rules.pro new file mode 100644 index 00000000000..fc884b76762 --- /dev/null +++ b/templates/google-play/template/instantapp/proguard-rules.pro @@ -0,0 +1,54 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in E:\developSoftware\Android\SDK/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Proguard Cocos2d-x-lite for release +-keep public class com.cocos.** { *; } +-dontwarn com.cocos.** + +# Proguard Apache HTTP for release +-keep class org.apache.http.** { *; } +-dontwarn org.apache.http.** + +# Proguard okhttp for release +-keep class okhttp3.** { *; } +-dontwarn okhttp3.** + +-keep class okio.** { *; } +-dontwarn okio.** + +# Proguard Android Webivew for release. you can comment if you are not using a webview +-keep public class android.net.http.SslError +-keep public class android.webkit.WebViewClient + +-keep public class com.google.** { *; } + +-dontwarn android.webkit.WebView +-dontwarn android.net.http.SslError +-dontwarn android.webkit.WebViewClient + +# This is generated automatically by the Android Gradle plugin. +-dontwarn android.hardware.BatteryState +-dontwarn android.hardware.lights.Light +-dontwarn android.hardware.lights.LightState$Builder +-dontwarn android.hardware.lights.LightState +-dontwarn android.hardware.lights.LightsManager$LightsSession +-dontwarn android.hardware.lights.LightsManager +-dontwarn android.hardware.lights.LightsRequest$Builder +-dontwarn android.hardware.lights.LightsRequest +-dontwarn android.net.ssl.SSLSockets +-dontwarn android.os.VibratorManager \ No newline at end of file diff --git a/templates/google-play/template/instantapp/src/com/cocos/game/InstantActivity.java b/templates/google-play/template/instantapp/src/com/cocos/game/InstantActivity.java new file mode 100644 index 00000000000..318e8398d31 --- /dev/null +++ b/templates/google-play/template/instantapp/src/com/cocos/game/InstantActivity.java @@ -0,0 +1,125 @@ +/**************************************************************************** +Copyright (c) 2015-2016 Chukong Technologies Inc. +Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +package com.cocos.game; + +import android.os.Bundle; +import android.content.Intent; +import android.content.res.Configuration; + +import com.cocos.service.SDKWrapper; +import com.cocos.lib.CocosActivity; + +public class InstantActivity extends CocosActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // DO OTHER INITIALIZATION BELOW + SDKWrapper.shared().init(this); + + } + + @Override + protected void onResume() { + super.onResume(); + SDKWrapper.shared().onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + SDKWrapper.shared().onPause(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + // Workaround in https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508 + if (!isTaskRoot()) { + return; + } + SDKWrapper.shared().onDestroy(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + SDKWrapper.shared().onActivityResult(requestCode, resultCode, data); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + SDKWrapper.shared().onNewIntent(intent); + } + + @Override + protected void onRestart() { + super.onRestart(); + SDKWrapper.shared().onRestart(); + } + + @Override + protected void onStop() { + super.onStop(); + SDKWrapper.shared().onStop(); + } + + @Override + public void onBackPressed() { + SDKWrapper.shared().onBackPressed(); + super.onBackPressed(); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + SDKWrapper.shared().onConfigurationChanged(newConfig); + super.onConfigurationChanged(newConfig); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + SDKWrapper.shared().onRestoreInstanceState(savedInstanceState); + super.onRestoreInstanceState(savedInstanceState); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + SDKWrapper.shared().onSaveInstanceState(outState); + super.onSaveInstanceState(outState); + } + + @Override + protected void onStart() { + SDKWrapper.shared().onStart(); + super.onStart(); + } + + @Override + public void onLowMemory() { + SDKWrapper.shared().onLowMemory(); + super.onLowMemory(); + } +} diff --git a/templates/google-play/template/res/mipmap-hdpi/ic_launcher.png b/templates/google-play/template/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000000..888c0d56abe Binary files /dev/null and b/templates/google-play/template/res/mipmap-hdpi/ic_launcher.png differ diff --git a/templates/google-play/template/res/mipmap-mdpi/ic_launcher.png b/templates/google-play/template/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000000..d5e3c770af8 Binary files /dev/null and b/templates/google-play/template/res/mipmap-mdpi/ic_launcher.png differ diff --git a/templates/openharmony/AppScope/resources/base/media/app_icon.png b/templates/google-play/template/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from templates/openharmony/AppScope/resources/base/media/app_icon.png rename to templates/google-play/template/res/mipmap-xhdpi/ic_launcher.png diff --git a/templates/google-play/template/res/mipmap-xxhdpi/ic_launcher.png b/templates/google-play/template/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000000..2f1e5a6b377 Binary files /dev/null and b/templates/google-play/template/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/templates/google-play/template/res/mipmap-xxxhdpi/ic_launcher.png b/templates/google-play/template/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000000..a9ebc7956e9 Binary files /dev/null and b/templates/google-play/template/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/templates/google-play/template/res/values/strings.xml b/templates/google-play/template/res/values/strings.xml new file mode 100644 index 00000000000..8542005550c --- /dev/null +++ b/templates/google-play/template/res/values/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/templates/openharmony/.gitignore b/templates/harmonyos-next/.gitignore similarity index 100% rename from templates/openharmony/.gitignore rename to templates/harmonyos-next/.gitignore diff --git a/templates/openharmony/AppScope/app.json5 b/templates/harmonyos-next/AppScope/app.json5 similarity index 100% rename from templates/openharmony/AppScope/app.json5 rename to templates/harmonyos-next/AppScope/app.json5 diff --git a/templates/openharmony/AppScope/resources/base/element/string.json b/templates/harmonyos-next/AppScope/resources/base/element/string.json similarity index 100% rename from templates/openharmony/AppScope/resources/base/element/string.json rename to templates/harmonyos-next/AppScope/resources/base/element/string.json diff --git a/templates/openharmony/entry/src/main/resources/base/media/icon.png b/templates/harmonyos-next/AppScope/resources/base/media/app_icon.png similarity index 100% rename from templates/openharmony/entry/src/main/resources/base/media/icon.png rename to templates/harmonyos-next/AppScope/resources/base/media/app_icon.png diff --git a/templates/openharmony/CMakeLists.txt b/templates/harmonyos-next/CMakeLists.txt similarity index 100% rename from templates/openharmony/CMakeLists.txt rename to templates/harmonyos-next/CMakeLists.txt diff --git a/templates/openharmony/build-profile.json5 b/templates/harmonyos-next/build-profile.json5 similarity index 100% rename from templates/openharmony/build-profile.json5 rename to templates/harmonyos-next/build-profile.json5 diff --git a/templates/openharmony/entry/.gitignore b/templates/harmonyos-next/entry/.gitignore similarity index 100% rename from templates/openharmony/entry/.gitignore rename to templates/harmonyos-next/entry/.gitignore diff --git a/templates/openharmony/entry/build-profile.json5 b/templates/harmonyos-next/entry/build-profile.json5 similarity index 100% rename from templates/openharmony/entry/build-profile.json5 rename to templates/harmonyos-next/entry/build-profile.json5 diff --git a/templates/openharmony/entry/hvigorfile.ts b/templates/harmonyos-next/entry/hvigorfile.ts similarity index 100% rename from templates/openharmony/entry/hvigorfile.ts rename to templates/harmonyos-next/entry/hvigorfile.ts diff --git a/templates/openharmony/entry/oh-package.json5 b/templates/harmonyos-next/entry/oh-package.json5 similarity index 100% rename from templates/openharmony/entry/oh-package.json5 rename to templates/harmonyos-next/entry/oh-package.json5 diff --git a/templates/openharmony/entry/src/main/cpp/types/libcocos/index.d.ts b/templates/harmonyos-next/entry/src/main/cpp/types/libcocos/index.d.ts similarity index 100% rename from templates/openharmony/entry/src/main/cpp/types/libcocos/index.d.ts rename to templates/harmonyos-next/entry/src/main/cpp/types/libcocos/index.d.ts diff --git a/templates/openharmony/entry/src/main/cpp/types/libcocos/oh-package.json5 b/templates/harmonyos-next/entry/src/main/cpp/types/libcocos/oh-package.json5 similarity index 100% rename from templates/openharmony/entry/src/main/cpp/types/libcocos/oh-package.json5 rename to templates/harmonyos-next/entry/src/main/cpp/types/libcocos/oh-package.json5 diff --git a/templates/openharmony/entry/src/main/ets/cocos/WorkerManager.ets b/templates/harmonyos-next/entry/src/main/ets/cocos/WorkerManager.ets similarity index 100% rename from templates/openharmony/entry/src/main/ets/cocos/WorkerManager.ets rename to templates/harmonyos-next/entry/src/main/ets/cocos/WorkerManager.ets diff --git a/templates/openharmony/entry/src/main/ets/cocos/game.ts b/templates/harmonyos-next/entry/src/main/ets/cocos/game.ts similarity index 100% rename from templates/openharmony/entry/src/main/ets/cocos/game.ts rename to templates/harmonyos-next/entry/src/main/ets/cocos/game.ts diff --git a/templates/openharmony/entry/src/main/ets/cocos/jsb-adapter/sys-ability-polyfill.js b/templates/harmonyos-next/entry/src/main/ets/cocos/jsb-adapter/sys-ability-polyfill.js similarity index 100% rename from templates/openharmony/entry/src/main/ets/cocos/jsb-adapter/sys-ability-polyfill.js rename to templates/harmonyos-next/entry/src/main/ets/cocos/jsb-adapter/sys-ability-polyfill.js diff --git a/templates/openharmony/entry/src/main/ets/cocos/oh-adapter/sys-ability-polyfill.js b/templates/harmonyos-next/entry/src/main/ets/cocos/oh-adapter/sys-ability-polyfill.js similarity index 100% rename from templates/openharmony/entry/src/main/ets/cocos/oh-adapter/sys-ability-polyfill.js rename to templates/harmonyos-next/entry/src/main/ets/cocos/oh-adapter/sys-ability-polyfill.js diff --git a/templates/openharmony/entry/src/main/ets/common/Constants.ts b/templates/harmonyos-next/entry/src/main/ets/common/Constants.ts similarity index 100% rename from templates/openharmony/entry/src/main/ets/common/Constants.ts rename to templates/harmonyos-next/entry/src/main/ets/common/Constants.ts diff --git a/templates/openharmony/entry/src/main/ets/common/PortProxy.ts b/templates/harmonyos-next/entry/src/main/ets/common/PortProxy.ts similarity index 100% rename from templates/openharmony/entry/src/main/ets/common/PortProxy.ts rename to templates/harmonyos-next/entry/src/main/ets/common/PortProxy.ts diff --git a/templates/openharmony/entry/src/main/ets/components/CocosVideoPlayer.ets b/templates/harmonyos-next/entry/src/main/ets/components/CocosVideoPlayer.ets similarity index 100% rename from templates/openharmony/entry/src/main/ets/components/CocosVideoPlayer.ets rename to templates/harmonyos-next/entry/src/main/ets/components/CocosVideoPlayer.ets diff --git a/templates/openharmony/entry/src/main/ets/components/CocosWebView.ets b/templates/harmonyos-next/entry/src/main/ets/components/CocosWebView.ets similarity index 100% rename from templates/openharmony/entry/src/main/ets/components/CocosWebView.ets rename to templates/harmonyos-next/entry/src/main/ets/components/CocosWebView.ets diff --git a/templates/openharmony/entry/src/main/ets/components/EditBoxDialog.ets b/templates/harmonyos-next/entry/src/main/ets/components/EditBoxDialog.ets similarity index 100% rename from templates/openharmony/entry/src/main/ets/components/EditBoxDialog.ets rename to templates/harmonyos-next/entry/src/main/ets/components/EditBoxDialog.ets diff --git a/templates/openharmony/entry/src/main/ets/entryability/EntryAbility.ts b/templates/harmonyos-next/entry/src/main/ets/entryability/EntryAbility.ts similarity index 100% rename from templates/openharmony/entry/src/main/ets/entryability/EntryAbility.ts rename to templates/harmonyos-next/entry/src/main/ets/entryability/EntryAbility.ts diff --git a/templates/openharmony/entry/src/main/ets/pages/index.ets b/templates/harmonyos-next/entry/src/main/ets/pages/index.ets similarity index 100% rename from templates/openharmony/entry/src/main/ets/pages/index.ets rename to templates/harmonyos-next/entry/src/main/ets/pages/index.ets diff --git a/templates/openharmony/entry/src/main/ets/workers/cocos_worker.ts b/templates/harmonyos-next/entry/src/main/ets/workers/cocos_worker.ts similarity index 100% rename from templates/openharmony/entry/src/main/ets/workers/cocos_worker.ts rename to templates/harmonyos-next/entry/src/main/ets/workers/cocos_worker.ts diff --git a/templates/openharmony/entry/src/main/module.json5 b/templates/harmonyos-next/entry/src/main/module.json5 similarity index 100% rename from templates/openharmony/entry/src/main/module.json5 rename to templates/harmonyos-next/entry/src/main/module.json5 diff --git a/templates/openharmony/entry/src/main/resources/base/element/color.json b/templates/harmonyos-next/entry/src/main/resources/base/element/color.json similarity index 100% rename from templates/openharmony/entry/src/main/resources/base/element/color.json rename to templates/harmonyos-next/entry/src/main/resources/base/element/color.json diff --git a/templates/openharmony/entry/src/main/resources/base/element/string.json b/templates/harmonyos-next/entry/src/main/resources/base/element/string.json similarity index 100% rename from templates/openharmony/entry/src/main/resources/base/element/string.json rename to templates/harmonyos-next/entry/src/main/resources/base/element/string.json diff --git a/templates/harmonyos-next/entry/src/main/resources/base/media/icon.png b/templates/harmonyos-next/entry/src/main/resources/base/media/icon.png new file mode 100644 index 00000000000..2b6f32ae038 Binary files /dev/null and b/templates/harmonyos-next/entry/src/main/resources/base/media/icon.png differ diff --git a/templates/openharmony/entry/src/main/resources/base/profile/main_pages.json b/templates/harmonyos-next/entry/src/main/resources/base/profile/main_pages.json similarity index 100% rename from templates/openharmony/entry/src/main/resources/base/profile/main_pages.json rename to templates/harmonyos-next/entry/src/main/resources/base/profile/main_pages.json diff --git a/templates/openharmony/entry/src/main/resources/rawfile/.keep b/templates/harmonyos-next/entry/src/main/resources/rawfile/.keep similarity index 100% rename from templates/openharmony/entry/src/main/resources/rawfile/.keep rename to templates/harmonyos-next/entry/src/main/resources/rawfile/.keep diff --git a/templates/openharmony/hvigor/hvigor-config.json5 b/templates/harmonyos-next/hvigor/hvigor-config.json5 similarity index 100% rename from templates/openharmony/hvigor/hvigor-config.json5 rename to templates/harmonyos-next/hvigor/hvigor-config.json5 diff --git a/templates/openharmony/hvigorfile.ts b/templates/harmonyos-next/hvigorfile.ts similarity index 100% rename from templates/openharmony/hvigorfile.ts rename to templates/harmonyos-next/hvigorfile.ts diff --git a/templates/openharmony/oh-package.json5 b/templates/harmonyos-next/oh-package.json5 similarity index 100% rename from templates/openharmony/oh-package.json5 rename to templates/harmonyos-next/oh-package.json5 diff --git a/templates/taobao-mini-game/game.ejs b/templates/taobao-mini-game/game.ejs index 0c5f811417f..3ae735585bd 100644 --- a/templates/taobao-mini-game/game.ejs +++ b/templates/taobao-mini-game/game.ejs @@ -1,4 +1,7 @@ -globalThis.window = globalThis; + +if (!globalThis.window) { + globalThis.window = globalThis; +} globalThis.self = $global; globalThis.__taobaoRequire = (urlNoSchema) => { @@ -71,7 +74,6 @@ function loadCC() { function onApplicationCreated(application) { return System.import('cc').then((cc) => { - globalThis.cc = cc; require('./engine-adapter'); return application.init(cc); }).then(() => { return application.start(); }); diff --git a/tests/tween/tween.test.ts b/tests/tween/tween.test.ts index 323b5a06953..8459964d3a1 100644 --- a/tests/tween/tween.test.ts +++ b/tests/tween/tween.test.ts @@ -6,8 +6,7 @@ import { game, director } from "../../cocos/game"; import { UITransform } from "../../cocos/2d/framework/ui-transform"; import { Canvas } from "../../cocos/2d/framework/canvas"; import { Batcher2D } from "../../cocos/2d/renderer/batcher-2d"; -import { Label, UIOpacity } from "../../cocos/2d"; -import { Sprite } from "../../cocos/2d"; +import { UIOpacity, Sprite } from "../../cocos/2d"; function isSizeEqualTo(a: Size, b: Size) { return approx(a.width, b.width) && approx(a.height, b.height); @@ -239,6 +238,136 @@ test('Test different target in sequence', function() { director.unregisterSystem(sys); }); +test('Test different target in sequence nesting parallel', function() { + const sys = new TweenSystem(); + (TweenSystem.instance as any) = sys; + director.registerSystem(TweenSystem.ID, sys, System.Priority.MEDIUM); + + const scene = new Scene('test'); + director.runSceneImmediate(scene); + + const node = new Node('TestNode'); + const uiOpacity = node.addComponent(UIOpacity) as UIOpacity; + node.parent = scene; + + tween(node) + .sequence( + tween(node) + .to(1, {scale: v3(2, 2, 2)}), + tween(node) + .parallel( + tween(uiOpacity) + .to(1, { opacity: 0 }), + tween(node) + .to(1, { scale: v3(1, 1, 1) }) + ) + ) + .start(); + + runFrames(1); // Kick off + + runFrames(30); + expect(node.scale.equals(new Vec3(1.5, 1.5, 1.5))).toBeTruthy(); + expect(uiOpacity.opacity).toBeCloseTo(255); + runFrames(30); + expect(node.scale.equals(new Vec3(2, 2, 2))).toBeTruthy(); + runFrames(30); + expect(node.scale.equals(new Vec3(1.5, 1.5, 1.5))).toBeTruthy(); + expect(uiOpacity.opacity).toBeCloseTo(255/2); + runFrames(30); + expect(node.scale.equals(new Vec3(1, 1, 1))).toBeTruthy(); + expect(uiOpacity.opacity).toBeCloseTo(0); + + // test end + director.unregisterSystem(sys); +}); + +test('Test different target in parallel nesting sequence', function() { + const sys = new TweenSystem(); + (TweenSystem.instance as any) = sys; + director.registerSystem(TweenSystem.ID, sys, System.Priority.MEDIUM); + + const scene = new Scene('test'); + director.runSceneImmediate(scene); + + const node = new Node('TestNode'); + const uiOpacity = node.addComponent(UIOpacity) as UIOpacity; + node.parent = scene; + + tween(node) + .parallel( + tween(node).sequence( + tween(node) + .to(1, { scale: v3(2, 2, 2) }), + tween(node) + .to(1, { position: v3(100, 100, 0) }) + ), + tween(uiOpacity) + .to(2, { opacity: 0 }), + ) + .start(); + + runFrames(1); // Kick off + + runFrames(30); + expect(node.scale.equals(new Vec3(1.5, 1.5, 1.5))).toBeTruthy(); + expect(node.position.equals(new Vec3(0, 0, 0))).toBeTruthy(); + runFrames(30); + expect(node.scale.equals(new Vec3(2, 2, 2))).toBeTruthy(); + expect(node.position.equals(new Vec3(0, 0, 0))).toBeTruthy(); + + expect(uiOpacity.opacity).toBeCloseTo(255/2); + + runFrames(60); + expect(node.scale.equals(new Vec3(2, 2, 2))).toBeTruthy(); + expect(node.position.equals(new Vec3(100, 100, 0))).toBeTruthy(); + expect(uiOpacity.opacity).toBeCloseTo(0); + + // test end + director.unregisterSystem(sys); +}); + +test('Test different target in sequence nesting parallel and re-target', function() { + const sys = new TweenSystem(); + (TweenSystem.instance as any) = sys; + director.registerSystem(TweenSystem.ID, sys, System.Priority.MEDIUM); + + const scene = new Scene('test'); + director.runSceneImmediate(scene); + + const node1 = new Node('TestNode1'); + node1.parent = scene; + + const node2 = new Node('TestNode2'); + node2.parent = scene; + + const node3 = new Node('TestNode3'); + node3.parent = scene; + + tween(node1) + .sequence( + tween(node1) + .to(1, { position: v3(100, 100, 0) }).target(node3), + ) + .target(node2) + .to(1, { position: v3(200, 200, 200) }) + .start(); + + runFrames(1); // Kick off + runFrames(60); + expect(node1.position.equals(new Vec3(0, 0, 0))).toBeTruthy(); + expect(node2.position.equals(new Vec3(0, 0, 0))).toBeTruthy(); + expect(node3.position.equals(new Vec3(100, 100, 0))).toBeTruthy(); + + runFrames(60); + expect(node1.position.equals(new Vec3(0, 0, 0))).toBeTruthy(); + expect(node2.position.equals(new Vec3(200, 200, 200))).toBeTruthy(); + expect(node3.position.equals(new Vec3(100, 100, 0))).toBeTruthy(); + + // test end + director.unregisterSystem(sys); +}); + test('Test different target in then', function() { // @ts-expect-error director.root!._batcher = new Batcher2D(director.root!); @@ -4811,4 +4940,4 @@ test('parallel with two call tween', function () { expect(cb2).toBeCalledTimes(1); director.unregisterSystem(sys); -}); \ No newline at end of file +}); diff --git a/tsconfig.json b/tsconfig.json index 273a16fd24f..369cb10f46b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -55,6 +55,7 @@ "exports/**/*.ts", "editor/exports/**/*.ts", "typedoc-index.ts", - "pal/**/*.ts" + "pal/**/*.ts", + "vendor/**/*.ts" ] } diff --git a/typedoc-index.ts b/typedoc-index.ts index f5f38d1b343..c25b3950dbe 100644 --- a/typedoc-index.ts +++ b/typedoc-index.ts @@ -29,3 +29,4 @@ export * from './exports/video'; export * from './exports/webview'; export * from './exports/sorting'; export * from './exports/xr'; +export * from './exports/vendor-google'; diff --git a/vendor/google/billing/billing.ts b/vendor/google/billing/billing.ts new file mode 100644 index 00000000000..c31f64ad209 --- /dev/null +++ b/vendor/google/billing/billing.ts @@ -0,0 +1,829 @@ +/**************************************************************************** + Copyright (c) 2024 Xiamen Yaji Software Co., Ltd. + + http://www.cocos.com + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*****************************************************************************/ +import { JSB } from 'internal:constants'; +import { EventTarget } from '../../../cocos/core/event'; + +interface BillingEventMap { + [google.BillingEventType.BILLING_SETUP_FINISHED]: (result: google.BillingResult) => void, + [google.BillingEventType.BILLING_SERVICE_DISCONNECTED]: () => void, + [google.BillingEventType.PRODUCT_DETAILS_RESPONSE]: + (result: google.BillingResult, productDetailsList: google.ProductDetails[]) => void, + [google.BillingEventType.PURCHASES_UPDATED]: (result: google.BillingResult, purchases: google.Purchase[]) => void, + [google.BillingEventType.CONSUME_RESPONSE]: (result: google.BillingResult, purchaseToken: string) => void, + [google.BillingEventType.ACKNOWLEDGE_PURCHASES_RESPONSE]: (result: google.BillingResult) => void + [google.BillingEventType.QUERY_PURCHASES_RESPONSE]: (result: google.BillingResult, purchases: google.Purchase[]) => void, + [google.BillingEventType.BILLING_CONFIG_RESPONSE]: (result: google.BillingResult, config: google.BillingConfig) => void + [google.BillingEventType.ALTERNATIVE_BILLING_ONLY_TOKEN_RESPONSE]: + (result: google.BillingResult, alternativeBillingOnlyReportingDetails: google.AlternativeBillingOnlyReportingDetails) => void + [google.BillingEventType.EXTERNAL_OFFER_REPORTING_DETAILS_RESPONSE]: + (result: google.BillingResult, externalOfferReportingDetails: google.ExternalOfferReportingDetails) => void + [google.BillingEventType.ALTERNATIVE_BILLING_ONLY_AVAILABILITY_RESPONSE]: (result: google.BillingResult) => void + [google.BillingEventType.EXTERNAL_OFFER_AVAILABILITY_RESPONSE]: (result: google.BillingResult) => void + [google.BillingEventType.ALTERNATIVE_BILLING_ONLY_INFORMATION_DIALOG_RESPONSE]: (result: google.BillingResult) => void + [google.BillingEventType.EXTERNAL_OFFER_INFORMATION_DIALOG_RESPONSE]: (result: google.BillingResult) => void + [google.BillingEventType.IN_APP_MESSAGE_RESPONSE]: (result: google.InAppMessageResult) => void +} + +class Billing { + private _eventTarget: EventTarget = new EventTarget(); + constructor () { + if (!JSB || !jsb.googleBilling) { + return; + } + jsb.onBillingSetupFinished = (result: google.BillingResult): void => { + this._eventTarget.emit(google.BillingEventType.BILLING_SETUP_FINISHED, result); + }; + + jsb.onBillingServiceDisconnected = (): void => { + this._eventTarget.emit(google.BillingEventType.BILLING_SERVICE_DISCONNECTED); + }; + + jsb.onProductDetailsResponse = ( + result: google.BillingResult, + productDetailsList: google.ProductDetails[], + ): void => { + this._eventTarget.emit(google.BillingEventType.PRODUCT_DETAILS_RESPONSE, result, productDetailsList); + }; + + jsb.onPurchasesUpdated = ( + result: google.BillingResult, + purchaseList: google.Purchase[], + ): void => { + this._eventTarget.emit(google.BillingEventType.PURCHASES_UPDATED, result, purchaseList); + }; + + jsb.onConsumeResponse = ( + result: google.BillingResult, + purchaseToken: string, + ): void => { + this._eventTarget.emit(google.BillingEventType.CONSUME_RESPONSE, result, purchaseToken); + }; + + jsb.onAcknowledgePurchaseResponse = (result: google.BillingResult): void => { + this._eventTarget.emit(google.BillingEventType.ACKNOWLEDGE_PURCHASES_RESPONSE, result); + }; + + jsb.onQueryPurchasesResponse = ( + result: google.BillingResult, + purchaseList: google.Purchase[], + ): void => { + this._eventTarget.emit(google.BillingEventType.QUERY_PURCHASES_RESPONSE, result, purchaseList); + }; + + jsb.onBillingConfigResponse = (result: google.BillingResult, config: google.BillingConfig): void => { + this._eventTarget.emit(google.BillingEventType.BILLING_CONFIG_RESPONSE, result, config); + }; + + jsb.onAlternativeBillingOnlyTokenResponse = ( + result: google.BillingResult, + details: google.AlternativeBillingOnlyReportingDetails, + ): void => { + this._eventTarget.emit(google.BillingEventType.ALTERNATIVE_BILLING_ONLY_TOKEN_RESPONSE, result, details); + }; + + jsb.onExternalOfferReportingDetailsResponse = (result: google.BillingResult, details: google.ExternalOfferReportingDetails): void => { + this._eventTarget.emit(google.BillingEventType.EXTERNAL_OFFER_REPORTING_DETAILS_RESPONSE, result, details); + }; + + jsb.onAlternativeBillingOnlyAvailabilityResponse = (result: google.BillingResult): void => { + this._eventTarget.emit(google.BillingEventType.ALTERNATIVE_BILLING_ONLY_AVAILABILITY_RESPONSE, result); + }; + + jsb.onExternalOfferAvailabilityResponse = (result: google.BillingResult): void => { + this._eventTarget.emit(google.BillingEventType.EXTERNAL_OFFER_AVAILABILITY_RESPONSE, result); + }; + + jsb.onAlternativeBillingOnlyInformationDialogResponse = (result: google.BillingResult): void => { + this._eventTarget.emit(google.BillingEventType.ALTERNATIVE_BILLING_ONLY_INFORMATION_DIALOG_RESPONSE, result); + }; + + jsb.onExternalOfferInformationDialogResponse = (result: google.BillingResult): void => { + this._eventTarget.emit(google.BillingEventType.EXTERNAL_OFFER_INFORMATION_DIALOG_RESPONSE, result); + }; + + jsb.onInAppMessageResponse = (result: google.InAppMessageResult): void => { + this._eventTarget.emit(google.BillingEventType.IN_APP_MESSAGE_RESPONSE, result); + }; + } + + /** + * @en Starts up BillingClient setup process asynchronously. + * @zh 异步启动 BillingClient 设置过程。 + */ + public startConnection (): void { + jsb.googleBilling?.startConnection(); + } + + /** + * @en Closes the connection and releases all held resources such as service connections. + * @zh 关闭连接并释放所有持有的资源,例如服务连接。 + */ + public endConnection (): void { + jsb.googleBilling?.endConnection(); + } + + /** + * @en Get the current billing client connection state. + * @zh 获取当前billing客户端连接状态。 + */ + public getConnectionState (): number { + if (jsb.googleBilling) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return jsb.googleBilling.getConnectionState(); + } + return google.ConnectionState.DISCONNECTED; + } + + /** + * @en Checks if the client is currently connected to the service, so that requests to other methods will succeed. + Returns true if the client is currently connected to the service, false otherwise. + * @zh 检查客户端当前是否连接到服务,以便对其他方法的请求能够成功。 + 如果客户端当前已连接到服务,则返回 true,否则返回 false。 + */ + public isReady (): boolean { + if (jsb.googleBilling) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return jsb.googleBilling.isReady(); + } + return false; + } + + /** + * @en Performs a network query the details of products available for sale in your app. + * @zh 执行网络查询您的应用中可供销售的产品的详细信息。 + * @param productId @zh 产品ID。 @en product id. + * @param productType @zh 产品类型。 @en product type. + * + */ + public queryProductDetailsParams (productId: string[], productType: google.ProductType): void { + jsb.googleBilling?.queryProductDetailsParams(productId, productType); + } + + /** + * @en Initiates the billing flow for an in-app purchase or subscription. + * @zh 启动应用内购买或订阅的计费流程。 + * @param productDetails @zh 产品详情。 @en product details. + * @param selectedOfferToken @zh 选择提供的token。 @en selected offer token. + */ + public launchBillingFlow (productDetails: google.ProductDetails[], selectedOfferToken: string | null): void { + jsb.googleBilling?.launchBillingFlow(productDetails, selectedOfferToken); + } + + /** + * @en Consumes a given in-app product. + * @zh 消费指定的应用内产品。 + * @param purchase @zh 已经购买的产品。 @en Purchased Products. + */ + public consumePurchases (purchase: google.Purchase[]): void { + jsb.googleBilling?.consumePurchases(purchase); + } + + /** + * @en Acknowledges in-app purchases. + * @zh 确认应用内购买。 + * @param purchase @zh 已经购买的产品。 @en Purchased Products. + */ + public acknowledgePurchase (purchase: google.Purchase[]): void { + jsb.googleBilling?.acknowledgePurchase(purchase); + } + + /** + * @en Returns purchases details for currently owned items bought within your app. + * @zh 返回您应用内当前拥有的购买商品的购买详情。 + * @param productType @zh 产品类型 @en Product type. + */ + public queryPurchasesAsync (productType: google.ProductType): void { + jsb.googleBilling?.queryPurchasesAsync(productType); + } + + /** + * @en Gets the billing config, which stores configuration used to perform billing operations. + * @zh 获取计费配置,其中存储用于执行计费操作的配置。 + */ + public getBillingConfigAsync (): void { + jsb.googleBilling?.getBillingConfigAsync(); + } + + /** + * @en Creates alternative billing only purchase details that can be used to report a transaction made + * via alternative billing without user choice to use Google Play billing. + * @zh 创建仅限替代结算的购买详情,可用于报告通过替代结算进行的交易,而无需用户选择使用 Google Play 结算。 + */ + public createAlternativeBillingOnlyReportingDetailsAsync (): void { + jsb.googleBilling?.createAlternativeBillingOnlyReportingDetailsAsync(); + } + + /** + * @en Checks the availability of offering alternative billing without user choice to use Google Play billing. + * @zh 检查是否可以提供替代结算方式,而无需用户选择使用 Google Play 结算方式。 + */ + public isAlternativeBillingOnlyAvailableAsync (): void { + jsb.googleBilling?.isAlternativeBillingOnlyAvailableAsync(); + } + + /** + * @en Creates purchase details that can be used to report a transaction made via external offer. + * @zh 创建可用于报告通过外部报价进行的交易的购买详情。 + */ + public createExternalOfferReportingDetailsAsync (): void { + jsb.googleBilling?.createExternalOfferReportingDetailsAsync(); + } + + /** + * @en Checks the availability of providing external offer. + * @zh 检查提供外部报价的可用性。 + */ + public isExternalOfferAvailableAsync (): void { + jsb.googleBilling?.isExternalOfferAvailableAsync(); + } + + /** + * @en Checks if the specified feature or capability is supported by the Play Store. + * @zh 检查 Play Store 是否支持指定的功能。 + * @param feature @zh 功能特性 @en feature. + */ + public isFeatureSupported (feature: string): google.BillingResult | null { + if (jsb.googleBilling) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return jsb.googleBilling.isFeatureSupported(feature); + } + return null; + } + + /** + * @en Shows the alternative billing only information dialog on top of the calling app. + * @zh 在调用应用程序顶部显示仅显示备用计费信息对话框。 + */ + public showAlternativeBillingOnlyInformationDialog (): google.BillingResult | null { + if (jsb.googleBilling) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return jsb.googleBilling.showAlternativeBillingOnlyInformationDialog(); + } + return null; + } + + /** + * @en Shows the external offer information dialog on top of the calling app. + * @zh 在调用应用程序顶部显示外部优惠信息对话框。 + */ + public showExternalOfferInformationDialog (): google.BillingResult | null { + if (jsb.googleBilling) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return jsb.googleBilling.showExternalOfferInformationDialog(); + } + return null; + } + + /** + * @en Overlays billing related messages on top of the calling app. + * @zh 在调用应用程序上叠加与计费相关的消息。 + */ + public showInAppMessages (): google.BillingResult | null { + if (jsb.googleBilling) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return jsb.googleBilling.showInAppMessages(); + } + return null; + } + + public on (type: K, callback: BillingEventMap[K], target?: unknown): BillingEventMap[K] { + this._eventTarget.on(type, callback, target); + return callback; + } + public once (type: K, callback: BillingEventMap[K], target?: unknown): BillingEventMap[K] { + this._eventTarget.once(type, callback, target); + return callback; + } + public off (eventType: K, callback?: BillingEventMap[K], target?: any): void { + this._eventTarget.off(eventType, callback, target); + } +} + +const gpBilling = new Billing(); + +export namespace google { + /** + * @en Google Play Billing event type + * @zh Google Play Billing事件类型 + */ + export enum BillingEventType { + /** + * @en + * Called to notify that setup is complete. + * + * @zh + * 当安装已经完成时触发。 + */ + BILLING_SETUP_FINISHED = 'billing_setup_finished', + /** + * @en + * Called to notify that the connection to the billing service was lost. + * + * @zh + * 当Billing服务连接断开时触发。 + */ + BILLING_SERVICE_DISCONNECTED = 'billing_service_disconnected', + /** + * @en + * Listen to this event to get notifications of purchase updates. + * + * @zh + * 监听这个事件可以获取购买更新。 + */ + PURCHASES_UPDATED = 'purchases_updated', + /** + * @en + * Called to notify that query product details operation has finished. + * + * @zh + * 查询产品详细信息操作完成时触发。 + */ + PRODUCT_DETAILS_RESPONSE = 'product_details_response', + /** + * @en + * Called to notify that the query purchases operation has finished. + * + * @zh + * 查询购买操作完成时触发。 + */ + QUERY_PURCHASES_RESPONSE = 'query_purchases_response', + /** + * @en + * Called to notify that a consume operation has finished. + * + * @zh + * 消费操作完成时触发。 + */ + CONSUME_RESPONSE = 'consume_response', + /** + * @en + * Called to notify that an acknowledge purchase operation has finished. + * + * @zh + * 确认购买操作完成时触发。 + */ + ACKNOWLEDGE_PURCHASES_RESPONSE = 'acknowledge_purchases_response', + /** + * @en + * Called to notify when the get billing config flow has finished. + * + * @zh + * 获取Billing配置流程完成时触发。 + */ + BILLING_CONFIG_RESPONSE = 'billing_config_response', + /** + * @en + * Called to receive the results from createAlternativeBillingOnlyReportingDetailsAsync when it is finished. + * + * @zh + * 当调用createAlternativeBillingOnlyReportingDetailsAsync接口完成时触发,可以接收调用结果。 + */ + ALTERNATIVE_BILLING_ONLY_TOKEN_RESPONSE = 'alternative_billing_only_token_response', + /** + * @en + * Called to receive the results from createExternalOfferReportingDetailsAsync when it is finished. + * + * @zh + * 当调用createExternalOfferReportingDetailsAsync接口完成时触发,可以接收调用结果。 + */ + EXTERNAL_OFFER_REPORTING_DETAILS_RESPONSE = 'external_offer_reporting_details_response', + /** + * @en + * Called to receive the results from BillingClient#isAlternativeBillingOnlyAvailableAsync when it is finished. + * + * @zh + * 当调用BillingClient#isAlternativeBillingOnlyAvailableAsync接口完成时触发,可以接收调用结果。 + */ + ALTERNATIVE_BILLING_ONLY_AVAILABILITY_RESPONSE = 'alternative_billing_only_availability_response', + /** + * @en + * Called to receive the results from BillingClient#isExternalOfferAvailableAsync when it is finished. + * + * @zh + * 当调用BillingClient#isExternalOfferAvailableAsync接口完成时触发,可以接收调用结果。 + */ + EXTERNAL_OFFER_AVAILABILITY_RESPONSE = 'external_offer_availability_response', + /** + * @en + * Called to notify that the alternative billing only dialog flow is finished. + * + * @zh + * 当仅替代Billing对话流程已完成时触发。 + */ + ALTERNATIVE_BILLING_ONLY_INFORMATION_DIALOG_RESPONSE = 'alternative_billing_only_information_dialog_response', + /** + * @en + * Called to notify that the external offer information dialog flow is finished. + * + * @zh + * 当外部报价信息对话流程已完成时触发。 + */ + EXTERNAL_OFFER_INFORMATION_DIALOG_RESPONSE = 'external_offer_information_dialog_response', + /** + * @en + * Called to notify when the in-app messaging flow has finished. + * + * @zh + * 当应用内消息流程完成时触发。 + */ + IN_APP_MESSAGE_RESPONSE = 'in_app_message_response', + + } + + /** + * @en + * Supported Product types. + * + * @zh + * 支持的产品类型。 + */ + export enum ProductType { + /** + * @en + * A Product type for Android apps in-app products. + * + * @zh + * Android 应用内产品的产品类型。 + */ + INAPP = 'inapp', + /** + * @en + * A Product type for Android apps subscriptions. + * + * @zh + * Android 应用程序订阅的产品类型。 + */ + SUBS = 'subs' + } + + /** + * @en + * Possible response codes. + * + * @zh + * 可能的响应代码。 + */ + export enum BillingResponseCode { + /** + * @en + * This field is deprecated. + * See SERVICE_UNAVAILABLE which will be used instead of this code. + * + * @zh + * 这个字段已经废弃。 + * 看看SERVICE_UNAVAILABLE将使用哪一个来代替此代码。 + */ + SERVICE_TIMEOUT = -3, + /** + * @en + * The requested feature is not supported by the Play Store on the current device. + * + * @zh + * 当前设备上的 Play Store 不支持所请求的功能。 + */ + FEATURE_NOT_SUPPORTED = -2, + /** + * @en + * The app is not connected to the Play Store service via the Google Play Billing Library. + * + * @zh + * 该应用未通过 Google Play Billing库连接到 Play Store 服务。 + */ + SERVICE_DISCONNECTED = -1, + /** + * @en + * Success. + * + * @zh + * 成功。 + */ + OK = 0, + /** + * @en + * Transaction was canceled by the user. + * + * @zh + * 交易已被用户取消。 + */ + USER_CANCELED = 1, + /** + * @en + * The service is currently unavailable. + * + * @zh + * 当前设备上的 Play Store 不支持所请求的功能。 + */ + SERVICE_UNAVAILABLE = 2, + /** + * @en + * A user billing error occurred during processing. + * + * @zh + * 处理过程中出现用户billing错误。 + */ + BILLING_UNAVAILABLE = 3, + /** + * @en + * The requested product is not available for purchase. + * + * @zh + * 所请求的产品无法购买。 + */ + ITEM_UNAVAILABLE = 4, + /** + * @en + * Error resulting from incorrect usage of the API. + * + * @zh + * 由于错误使用 API 而导致的错误。 + */ + DEVELOPER_ERROR = 5, + /** + * @en + * Fatal error during the API action. + * + * @zh + * API 操作期间发生致命错误。 + */ + ERROR = 6, + /** + * @en + * The purchase failed because the item is already owned. + * + * @zh + * 购买失败,因为该物品已被拥有。 + */ + ITEM_ALREADY_OWNED = 7, + /** + * @en + * Requested action on the item failed since it is not owned by the user. + * + * @zh + * 由于该项目不属于用户,因此对该项目请求的操作失败。 + */ + ITEM_NOT_OWNED = 8, + /** + * @en + * A network error occurred during the operation. + * + * @zh + * 操作期间发生网络错误。 + */ + NETWORK_ERROR = 12, + } + + /** + * @en + * Recurrence mode of the pricing phase. + * + * @zh + * 定价阶段的复现模式。 + */ + export enum RecurrenceMode { + /** + * @en + * The billing plan payment recurs for infinite billing periods unless cancelled. + * + * @zh + * 除非取消,否则billing计划付款将无限期地重复。 + */ + INFINITE_RECURRING = 1, + /** + * @en + * The billing plan payment recurs for a fixed number of billing period set in billingCycleCount. + * + * @zh + * Billing计划付款将在 billingCycleCount 中设置的固定计费周期内重复发生。 + */ + FINITE_RECURRING = 2, + /** + * @en + * The billing plan payment is a one time charge that does not repeat. + * + * @zh + * Billing计划付款是一次性费用,不会重复。 + */ + NON_RECURRING = 3, + } + + /** + * @en + * Connection state of billing client. + * + * @zh + * Billing client的连接状态 + */ + export enum ConnectionState { + /** + * @en + * This client was not yet connected to billing service or was already closed. + * + * @zh + * 此客户端尚未连接到Billing服务或已关闭。 + */ + DISCONNECTED = 0, + /** + * @en + * This client is currently in process of connecting to billing service. + * + * @zh + * 此客户端目前正在连接到Billing服务。 + */ + CONNECTING = 1, + /** + * @en + * This client is currently connected to billing service. + * + * @zh + * 此客户端当前已连接到Billing服务。 + */ + CONNECTED = 2, + /** + * @en + * This client was already closed and shouldn't be used again. + * + * @zh + * 该客户端已关闭,不应再次使用。 + */ + CLOSED = 3, + } + + /** + * @en + * Features/capabilities supported by isFeatureSupported. + * + * @zh + * 支持的特性/能力isFeatureSupported。 + */ + export enum FeatureType { + /** + * @en + * Alternative billing only. + * + * @zh + * 仅限替代Billing。 + */ + ALTERNATIVE_BILLING_ONLY = 'jjj', + /** + * @en + * Get billing config. + * + * @zh + * 获取计费配置。 + */ + BILLING_CONFIG = 'ggg', + /** + * @en + * Play billing library support for external offer. + * + * @zh + * Play billing库支持外部报价。 + */ + EXTERNAL_OFFER = 'kkk', + /** + * @en + * Show in-app messages. + * + * @zh + * 显示应用内消息。 + */ + IN_APP_MESSAGING = 'bbb', + /** + * @en + * Launch a price change confirmation flow. + * + * @zh + * 启动价格变动确认流程。 + */ + PRICE_CHANGE_CONFIRMATION = 'priceChangeConfirmation', + /** + * @en + * Play billing library support for querying and purchasing. + * + * @zh + * Play Billing库支持查询、购买。 + */ + PRODUCT_DETAILS = 'fff', + /** + * @en + * Purchase/query for subscriptions. + * + * @zh + * 购买/查询订阅。 + */ + SUBSCRIPTIONS = 'subscriptions', + /** + * @en + * Subscriptions update/replace. + * + * @zh + * 订阅更新/替换。 + */ + UBSCRIPTIONS_UPDATE = 'subscriptionsUpdate', + } + + /** + * @en + * Possible purchase states. + * + * @zh + * 可能的购买状态。 + */ + export enum PurchaseState { + /** + * @en + * Purchase is pending and not yet completed to be processed by your app. + * + * @zh + * 购买处于待处理状态且尚未完成,无法由您的应用程序处理。 + */ + PENDING = 2, + /** + * @en + * Purchase is completed.. + * + * @zh + * 购买完成。 + */ + PURCHASED = 1, + /** + * @en + * Purchase with unknown state. + * + * @zh + * 未知状态 + */ + UNSPECIFIED_STATE = 0, + } + + /** + * @en + * Possible response codes. + * + * @zh + * InAppMessage可能的影响代码。 + */ + export enum InAppMessageResponseCode { + /** + * @en + * The flow has finished and there is no action needed from developers. + * + * @zh + * 流程已完成,开发人员无需采取任何行动。 + */ + NO_ACTION_NEEDED = 0, + /** + * @en + * The subscription status changed. + * + * @zh + * 订阅状态已改变。 + */ + SUBSCRIPTION_STATUS_UPDATED = 1, + } + + export type BillingResult = jsb.BillingResult; + export type OneTimePurchaseOfferDetails = jsb.OneTimePurchaseOfferDetails; + export type InstallmentPlanDetails = jsb.InstallmentPlanDetails; + export type PricingPhase = jsb.PricingPhase; + export type SubscriptionOfferDetails = jsb.SubscriptionOfferDetails; + export type ProductDetails = jsb.ProductDetails; + export type AccountIdentifiers = jsb.AccountIdentifiers; + export type PendingPurchaseUpdate = jsb.PendingPurchaseUpdate; + export type Purchase = jsb.Purchase; + export type BillingConfig = jsb.BillingConfig; + export type AlternativeBillingOnlyReportingDetails = jsb.AlternativeBillingOnlyReportingDetails; + export type ExternalOfferReportingDetails = jsb.ExternalOfferReportingDetails; + export type InAppMessageResult = jsb.InAppMessageResult; + + /** + * @en + * Interface for Google Play blling module. + * + * @zh + * Google Play blling模块的接口。 + * + */ + export const billing = gpBilling; +} diff --git a/vendor/google/index.ts b/vendor/google/index.ts new file mode 100644 index 00000000000..51359d6f468 --- /dev/null +++ b/vendor/google/index.ts @@ -0,0 +1,25 @@ +/* + Copyright (c) 2024 Xiamen Yaji Software Co., Ltd. + + https://www.cocos.com/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +export * from './billing/billing';