From e3876abec69013da50becc097ecd8786a556d8f1 Mon Sep 17 00:00:00 2001 From: yyc <395976266@qq.com> Date: Mon, 6 May 2019 21:40:01 +0800 Subject: [PATCH] feat(asset-bundle): add "generate all ab" draft logic(pass compile) --- public/css/index.css | 113 ++++++ .../components/ui/_generateAllABModal.scss | 80 ++++ public/sass/index.scss | 4 +- .../asset_bundle/HeaderAssetBundle.re | 157 +++++++- .../HeaderAssetBundleGenerateAllAB.re | 355 ++++++++++++++++++ .../HeaderAssetBundleGenerateSingleRAB.re | 9 +- .../data/HeaderAssetBundleType.re | 12 +- .../publish/local/HeaderPublishLocalUtils.re | 2 +- src/core/config/data/LanguageHeaderData.re | 7 + .../asset/AssetBundleNodeAssetService.re | 2 + .../GenerateAssetBundleEngineService.re | 4 +- 11 files changed, 738 insertions(+), 7 deletions(-) create mode 100644 public/sass/components/ui/_generateAllABModal.scss create mode 100644 src/core/composable_component/header/atom_component/asset_bundle/HeaderAssetBundleGenerateAllAB.re diff --git a/public/css/index.css b/public/css/index.css index 514667e9d..f6f3cb6a1 100755 --- a/public/css/index.css +++ b/public/css/index.css @@ -304,6 +304,119 @@ html, body { right: 30px; padding-top: 5px; } +.wonder-generateAllAB-modal { + position: fixed; + z-index: 200; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + top: 20%; + display: flex; + justify-content: center; } + .wonder-generateAllAB-modal .input-component { + position: relative; + display: inline-block; + padding: 4px 7px; + width: 100%; + height: 22px; + cursor: text; + font-size: 12px; + line-height: 1.5; + color: #666; + background-color: #fff; + background-image: none; + border: 1px solid #d9d9d9; + border-radius: 6px; + -webkit-transition: border 0.2s cubic-bezier(0.645, 0.045, 0.355, 1), background 0.2s cubic-bezier(0.645, 0.045, 0.355, 1), box-shadow 0.2s cubic-bezier(0.645, 0.045, 0.355, 1); + transition: border 0.2s cubic-bezier(0.645, 0.045, 0.355, 1), background 0.2s cubic-bezier(0.645, 0.045, 0.355, 1), box-shadow 0.2s cubic-bezier(0.645, 0.045, 0.355, 1); } + .wonder-generateAllAB-modal .input-component::placeholder { + color: #ccc; } + .wonder-generateAllAB-modal .input-component:hover { + border-color: #57c5f7; } + .wonder-generateAllAB-modal .input-component:focus { + border-color: #57c5f7; + outline: 0; + box-shadow: 0 0 0 2px rgba(45, 183, 245, 0.2); } + .wonder-generateAllAB-modal .modal-item { + width: 470px; + height: 200px; + position: relative; + background: #c1c1c1; + border-radius: 5px; + z-index: 150; } + .wonder-generateAllAB-modal .modal-item .modal-item-header { + width: 100%; + height: 22px; + line-height: 22px; + font-size: 14px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + text-align: center; + font-size: 17px; + font-weight: bold; + padding: 5px 0px 2px 0px; + border-bottom: 1px solid #868686; + background: #555454; + position: relative; } + .wonder-generateAllAB-modal .modal-item .modal-item-header img { + position: absolute; + top: 8px; + cursor: hand; + right: 20px; + width: 15px; + height: 15px; } + .wonder-generateAllAB-modal .modal-item .modal-item-content { + color: #000; + height: 114px; + overflow-y: auto; + width: 90%; + margin-left: 5%; + padding-top: 10px; + box-sizing: border-box; + font-size: 16px; } + .wonder-generateAllAB-modal .modal-item .modal-item-content::-webkit-scrollbar { + width: 4px; + height: 6px; } + .wonder-generateAllAB-modal .modal-item .modal-item-content::-webkit-scrollbar-button { + display: none; } + .wonder-generateAllAB-modal .modal-item .modal-item-content::-webkit-scrollbar-track { + background: rgba(1, 1, 1, 0.6); + width: 2px; } + .wonder-generateAllAB-modal .modal-item .modal-item-content::-webkit-scrollbar-thumb { + background: #cfcccc; + border-radius: 4px; } + .wonder-generateAllAB-modal .modal-item .modal-item-content::-webkit-scrollbar-thumb:hover { + background: #fc7100; } + .wonder-generateAllAB-modal .modal-item .modal-item-content .content-field { + width: 100%; + height: 24px; + display: flex; } + .wonder-generateAllAB-modal .modal-item .modal-item-content .content-field .field-title { + width: 20%; + text-align: center; + height: 24px; + line-height: 24px; } + .wonder-generateAllAB-modal .modal-item .modal-item-content .content-field .field-content { + width: 80%; + margin-left: 4px; + text-align: center; + height: 24px; + line-height: 24px; } + .wonder-generateAllAB-modal .modal-item .modal-item-content .content-field .field-content a { + white-space: nowrap; } + .wonder-generateAllAB-modal .modal-item .modal-item-footer { + height: 50px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + position: relative; } + .wonder-generateAllAB-modal .modal-item .modal-item-footer .footer-submit { + width: 100px; + position: absolute; + top: 5px; + right: 30px; + padding-top: 5px; } + .wonder-app-component { width: 100%; height: 100%; diff --git a/public/sass/components/ui/_generateAllABModal.scss b/public/sass/components/ui/_generateAllABModal.scss new file mode 100644 index 000000000..a1e15214c --- /dev/null +++ b/public/sass/components/ui/_generateAllABModal.scss @@ -0,0 +1,80 @@ +.wonder-generateAllAB-modal { + position: fixed; + z-index: 200; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + top: 20%; + display: flex; + justify-content: center; + @import "./normalInput"; + + .modal-item { + width: 470px; + height: 200px; + position: relative; + background: #c1c1c1; + border-radius: 5px; + z-index: 150; + + .modal-item-header { + width: 100%; + height: 22px; + line-height: 22px; + font-size: 14px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + text-align: center; + font-size: 17px; + font-weight: bold; + padding: 5px 0px 2px 0px; + border-bottom: 1px solid #868686; + background: #555454; + position: relative; + + img { + position: absolute; + top: 8px; + cursor: hand; + right: 20px; + width: 15px; + height: 15px; + } + } + + .modal-item-content { + @import "../../utils/scrollBarUtils"; + color: #000; + height: 114px; + overflow-y: auto; + width: 90%; + margin-left: 5%; + padding-top: 10px; + box-sizing: border-box; + font-size: 16px; + + .content-field { + width: 100%; + height: 24px; + display: flex; + @import "../../utils/modalUtils"; + } + } + + .modal-item-footer { + height: 50px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + position: relative; + + .footer-submit { + width: 100px; + position: absolute; + top: 5px; + right: 30px; + padding-top: 5px; + } + } + } +} \ No newline at end of file diff --git a/public/sass/index.scss b/public/sass/index.scss index 4916ba7e3..65f9641df 100755 --- a/public/sass/index.scss +++ b/public/sass/index.scss @@ -5,10 +5,10 @@ @import "./components/ui/modal"; @import "./components/ui/singleInputModal"; +@import "./components/ui/generateAllABModal"; @import "components/app"; @import "vendors/colorPickExtend"; -@import "vendors/selectComponent"; - +@import "vendors/selectComponent"; \ No newline at end of file diff --git a/src/core/composable_component/header/atom_component/asset_bundle/HeaderAssetBundle.re b/src/core/composable_component/header/atom_component/asset_bundle/HeaderAssetBundle.re index f57eaca60..5ca56e69a 100644 --- a/src/core/composable_component/header/atom_component/asset_bundle/HeaderAssetBundle.re +++ b/src/core/composable_component/header/atom_component/asset_bundle/HeaderAssetBundle.re @@ -1,13 +1,16 @@ type state = { isShowGenerateSingleRABModal: bool, isShowGenerateSingleSABModal: bool, + isShowGenerateAllABModal: bool, }; type action = | ShowGenerateSingleRABModal | HideGenerateSingleRABModal | ShowGenerateSingleSABModal - | HideGenerateSingleSABModal; + | HideGenerateSingleSABModal + | ShowGenerateAllABModal + | HideGenerateAllABModal; module Method = { let buildAssetBundleComponentSelectNav = (send, languageType) => @@ -40,6 +43,20 @@ module Method = { } +
send(ShowGenerateAllABModal)}> + + { + DomHelper.textEl( + LanguageUtils.getHeaderLanguageDataByType( + "generate-all-ab", + languageType, + ), + ) + } + +
; let _unsafeGetSelectTreeNodeIdFromFolderTreeMap = @@ -383,6 +400,127 @@ module Method = { selectTree; }; + + let buildSelectTreeForGenerateAllAB = ((editorState, engineState)) => { + /* open HeaderAssetBundleType; */ + + let initNodeId = 0; + let rootNode = + FolderNodeSelectTreeService.buildNode( + ~nodeId=initNodeId, + ~name=RootTreeAssetService.getAssetTreeRootName(), + ~isSelect=false, + ~children=[||], + (), + ); + let selectTree = rootNode; + + let (_, _, selectTree) = + IterateTreeAssetService.foldWithParentFolderNodeWithoutRootNode( + ~acc=( + initNodeId, + _setToFolderTreeMap( + RootTreeAssetEditorService.getRootNode(editorState), + rootNode, + WonderCommonlib.ImmutableSparseMapService.createEmpty(), + ), + selectTree, + ), + ~tree=TreeAssetEditorService.unsafeGetTree(editorState), + /* TODO refactor: duplicate */ + ~folderNodeFunc= + ( + parentFolderNode, + (currentSelectTreeNodeId, folderTreeMap, selectTree), + nodeId, + nodeData, + children, + ) => { + let newNodeId = + IdSelectTreeService.generateNodeId(currentSelectTreeNodeId); + + let newSelectTreeFolderNode = + FolderNodeSelectTreeService.buildNode( + ~nodeId=newNodeId, + ~name=FolderNodeAssetService.getNodeName(nodeData), + ~isSelect=false, + ~children=[||], + (), + ); + + let selectTree = + selectTree + |> OperateTreeSelectTreeService.insertNode( + _unsafeGetSelectTreeNodeIdFromFolderTreeMap( + parentFolderNode, + folderTreeMap, + ), + newSelectTreeFolderNode, + ); + + ( + newNodeId, + folderTreeMap + |> _setToFolderTreeMap( + FolderNodeAssetService.buildNodeByNodeData( + ~nodeId, + ~nodeData, + ~children, + ), + newSelectTreeFolderNode, + ), + selectTree, + ); + }, + ~textureNodeFunc=(parentFolderNode, acc, nodeId, nodeData) => acc, + ~assetBundleNodeFunc= + ( + parentFolderNode, + (currentSelectTreeNodeId, folderTreeMap, selectTree), + nodeId, + nodeData, + ) => { + /* TODO feat: exclude wab? */ + let assetNode = + AssetBundleNodeAssetService.buildNodeByNodeData( + ~nodeId, + ~nodeData, + ); + + _handleFoldAssetNode( + parentFolderNode, + (currentSelectTreeNodeId, folderTreeMap, selectTree), + ( + assetNode, + "assetBundle", + ( + { + assetBundle: + AssetBundleNodeAssetService.getAssetBundle(assetNode), + path: + PathTreeAssetLogicService.getNodePath( + assetNode, + (editorState, engineState), + ), + type_: AssetBundleNodeAssetService.getType(assetNode), + }: HeaderAssetBundleType.assetBundleData + ) + |> HeaderAssetBundleType.convertAssetBundleDataToValue, + ), + engineState, + ); + }, + ~materialNodeFunc=(parentFolderNode, acc, nodeId, nodeData) => acc, + ~scriptEventFunctionNodeFunc= + (parentFolderNode, acc, nodeId, nodeData) => acc, + ~scriptAttributeNodeFunc= + (parentFolderNode, acc, nodeId, nodeData) => acc, + ~wdbNodeFunc=(parentFolderNode, acc, nodeId, nodeData) => acc, + (), + ); + + selectTree; + }; }; let component = ReasonReact.reducerComponent("HeaderAssetBundle"); @@ -438,6 +576,18 @@ let render = /> : ReasonReact.null } + { + state.isShowGenerateAllABModal ? + StateLogicService.getStateToGetData + } + closeFunc={() => send(HideGenerateAllABModal)} + submitFunc={() => send(HideGenerateAllABModal)} + /> : + ReasonReact.null + } ; }; @@ -451,6 +601,10 @@ let reducer = (action, state) => ReasonReact.Update({...state, isShowGenerateSingleSABModal: true}) | HideGenerateSingleSABModal => ReasonReact.Update({...state, isShowGenerateSingleSABModal: false}) + | ShowGenerateAllABModal => + ReasonReact.Update({...state, isShowGenerateAllABModal: true}) + | HideGenerateAllABModal => + ReasonReact.Update({...state, isShowGenerateAllABModal: false}) }; let make = @@ -466,6 +620,7 @@ let make = initialState: () => { isShowGenerateSingleRABModal: false, isShowGenerateSingleSABModal: false, + isShowGenerateAllABModal: false, }, reducer, render: self => diff --git a/src/core/composable_component/header/atom_component/asset_bundle/HeaderAssetBundleGenerateAllAB.re b/src/core/composable_component/header/atom_component/asset_bundle/HeaderAssetBundleGenerateAllAB.re new file mode 100644 index 000000000..1164b3ba4 --- /dev/null +++ b/src/core/composable_component/header/atom_component/asset_bundle/HeaderAssetBundleGenerateAllAB.re @@ -0,0 +1,355 @@ +open WonderBsMost; + +open WonderBsJszip; + +open Js.Promise; + +type state = { + selectTreeForGenerateAllAB: SelectTreeType.tree, + nameInputValue: string, + dependencyRelationInputValue: string, +}; + +type action = + | ChangeName(string) + | ChangeDependencyRelation(string) + | UpdateSelectTreeForGenerateAllAB(SelectTreeType.tree); + +module Method = { + /* TODO refactor: duplicate */ + let _setSelectForSelectTree = (tree, isSelect, node) => { + open SelectTreeType; + + let rec _toggle = (isSelect, node, tree) => + switch (node) { + | FolderNode(nodeId, nodeData, children) => + let tree = + FolderNodeSelectTreeUILocalService.setNodeData( + nodeId, + FolderNodeSelectTreeService.setIsSelect(isSelect, nodeData), + children, + tree, + ); + + children + |> WonderCommonlib.ArrayService.reduceOneParam( + (. tree, node) => _toggle(isSelect, node, tree), + tree, + ); + | ValueNode(nodeId, nodeData) => + ValueNodeSelectTreeUILocalService.setNodeData( + nodeId, + ValueNodeSelectTreeService.setIsSelect(isSelect, nodeData), + tree, + ) + }; + + switch (node) { + | FolderNode(_, nodeData, _) => _toggle(isSelect, node, tree) + | ValueNode(nodeId, nodeData) => + ValueNodeSelectTreeUILocalService.setNodeData( + nodeId, + ValueNodeSelectTreeService.setIsSelect(isSelect, nodeData), + tree, + ) + }; + }; + + let _toggleSelect = (tree, send, isSelect, node) => { + open SelectTreeType; + + let tree = _setSelectForSelectTree(tree, isSelect, node); + + send(UpdateSelectTreeForGenerateAllAB(tree)); + }; + + let _buildGenerateAllABUI = (send, selectTreeForGenerateAllAB) => + + switch (type_) { + | "assetBundle" => Some("./public/img/assetBundle.png") + | _ => None + } + } + />; + + let _getMaterialComponentFromMaterialData = + (materialData: HeaderAssetBundleType.materialData) => + materialData.materialComponent; + + let _addLightMaterialContainedTextureData = + (lightMaterials, textures, (editorState, engineState)) => + lightMaterials + |> WonderCommonlib.ArrayService.reduceOneParam( + (. textures, lightMaterialComponent) => + LightMaterialEngineService.hasLightMaterialDiffuseMap( + lightMaterialComponent, + engineState, + ) ? + switch ( + TextureNodeAssetEditorService.getDataByTextureComponent( + LightMaterialEngineService.unsafeGetLightMaterialDiffuseMap( + lightMaterialComponent, + engineState, + ), + editorState, + ) + ) { + | None => textures + | Some(textureNodeData) => + textures + |> ArrayService.push( + { + textureComponent: textureNodeData.textureComponent, + imageDataIndex: textureNodeData.imageDataIndex, + }: HeaderAssetBundleType.textureData, + ) + } : + textures, + textures, + ); + + let _convertDependencyRelationInputValueStrToMap = [%raw + dependencyRelationInputValueStr => {| + return eval('(' + dependencyRelationInputValueStr + ')'); + |} + ]; + + let _generateRABAndSABData = selectTreeForGenerateAllAB => + IterateTreeSelectTreeService.fold( + ~tree=selectTreeForGenerateAllAB, + ~acc=( + WonderCommonlib.ArrayService.createEmpty(), + WonderCommonlib.ArrayService.createEmpty(), + ), + ~valueNodeFunc= + ((sabDataArr, rabDataArr), nodeId, nodeData) => + ValueNodeSelectTreeService.getIsSelect(nodeData) ? + { + let value = ValueNodeSelectTreeService.getValue(nodeData); + + switch (ValueNodeSelectTreeService.getType(nodeData)) { + | "assetBundle" => + let {type_, path, assetBundle}: HeaderAssetBundleType.assetBundleData = + value |> HeaderAssetBundleType.convertValueToAssetBundleData; + + switch (type_) { + | NodeAssetType.SAB => ( + sabDataArr |> ArrayService.push((path, assetBundle)), + rabDataArr, + ) + | NodeAssetType.RAB => ( + sabDataArr, + rabDataArr |> ArrayService.push((path, assetBundle)), + ) + }; + | type_ => + WonderLog.Log.fatal( + WonderLog.Log.buildFatalMessage( + ~title="_generateRABAndSABData", + ~description={j|unknown type_: $type_|j}, + ~reason="", + ~solution={j||j}, + ~params={j||j}, + ), + ) + }; + } : + (sabDataArr, rabDataArr), + ~folderNodeFunc=(acc, nodeId, nodeData, children) => acc, + (), + ); + + let generateAndDownloadAllAB = + ( + selectTreeForGenerateAllAB, + zipBaseName, + dependencyRelationInputValueStr, + (editorState, engineState), + ) => + MostUtils.callFunc(() => + ( + _convertDependencyRelationInputValueStrToMap( + dependencyRelationInputValueStr, + ), + _generateRABAndSABData(selectTreeForGenerateAllAB), + ) + ) + |> Most.flatMap(((dependencyRelation, rabAndSABData)) => + GenerateAssetBundleEngineService.generateAllAB( + dependencyRelation, + rabAndSABData, + ) + ) + |> Most.flatMap(((wab, rabDataArr, sabDataArr)) => + ( + ArrayService.fastConcat(rabDataArr, sabDataArr) + |> ArrayService.push(("WonderWAB.wab", wab)) + |> WonderCommonlib.ArrayService.reduceOneParam( + (. zip, (relativePath, ab)) => + zip + ->( + Zip.write( + ~options=Options.makeWriteOptions(~binary=true, ()), + relativePath, + `trustme(ab |> TypeArrayType.newBlobFromArrayBuffer), + ) + ), + Zip.create(), + ) + ) + ->(Zip.generateAsyncBlob(Zip.makeAsyncBlobOptions())) + |> then_(content => + FileSaver.saveAs(content, {j|$zipBaseName.zip|j}) |> resolve + ) + |> Most.fromPromise + ); + + let buildDefaultDependencyRelationInputValue = () => {| + var dependencyRelation = {}; + + //todo need rewrite + dependencyRelation["A.sab"] = ["AssetBundle/B.rab", "AssetBundle/F/c.rab"]; + + return dependencyRelation; + |}; + + let _changeName = event => + ChangeName( + ReactDOMRe.domElementToObj(ReactEventRe.Form.target(event))##value, + ); + + let _changeDependencyRelation = event => + ChangeDependencyRelation( + ReactDOMRe.domElementToObj(ReactEventRe.Form.target(event))##value, + ); + + let _renderNameInput = ((state, send)) => +
+
{DomHelper.textEl("name")}
+
+ send(_changeName(_e))} + /> +
+
; + + let _renderDependencyRelationInput = ((state, send)) => +
+
+ {DomHelper.textEl("dependencyRelation")} +
+
+