Cursos e Bibliotecas Ver Mais

Galeria 3D1 Ver Mais

robson cardoso   Londrina/PR - AC
Grasiano   Campo bom - RS - RS
isac vitor   curitiba - PR
Ismael de jesus   Florianópolis - SC

Portfólios Ver Mais

VIPERCEL   SÃO JOSÉ DO RIO PRETO SP - SP
maaxxwel   campina grande paraiba - PB
d3daniel   são paulo - AC
gustavorios2   Brasil - RJ

ConstruSim - Soft para Maquete Interativa

Por: Andre Vieira  

Em: 21/12/2017 08:28

Sim, Andre, você já me disse que é um consultor-arquiteto-projetista-mestre de obras dos parentes da Elis, kkkkk. Muito resquisitado, sinal de que oferece excelentes serviços. Eu realmente não sou capacitado para falar além do que disse, mas posso, com propriedade, perceber que é um excelente produto para ser explorado e mais desenvolvido, pois é praticamente certo que há um ótimo segmento ou nicho de mercado para ele, Andre.

Eu só não entendi se você vai implementar no projeto ou vai desenvolver um outro para casas pré-fabircadas. Explique-me isso melhor, pois aí teria outro sentido, mas, também, só vendo. Você é muito criativo e possui recursos (konw-how) como desenvolvedor de ideias. Não esmoreça ou se desencante. Como te disse, vejo milhares de documentários sobre produtos e faço reflexões profundas a respeito da evolução de certos produtos, desde a sua gêneses. Como eu já tive a oportunidade de te dizer, todos eles, SEM EXCEÇÃO, são HISTÓRIAS DE FRACASOS, mas por trás destas histórias havia seres humanos destemidos, determinados a não aceitar o fracaso e sempre abertos às correções, melhorias e aperfeiçoamentos de duas ideias e produtos. Logo, isso implica em AUTO-APERFEIÇOAMENTO, também.
Abração fraterno,

Marcelo Baglione
Oi Marcelo, tudo bem?

Agradeço mesmo por todas as suas observações porque você é a pessoa perfeita para testar esse programa, justamente por não atuar na área de arquitetura, pois o objetivo era que pessoas sem o conhecimento da área conseguissem projetar uma casinha sem dificuldade.

Agora, sobre a modificação para casas pré-fabricadas, o lance é como eu construi o programa, as paredes, portas, janelas e tudo mais funcionam como módulos dentro do programa, então, a qualquer momento eu posso trocar todos eles facilmente.

Por isso penso em modelar aquelas paredes de casas pré-fabricadas, ainda não sei se farei de madeira ou de placas de concreto, dai troco as janelas por Sasazakis de metal como são usadas nestas obras e o programa passará a inserir estes módulos criando casas no padrão das pré-fabricadas, sem eu ter que programar mais nada.

Assim, poderei apresentar para uma empresa que produz estas casas para ver se eles têm algum interesse.

Abração e tudo de bom.

André Vieira
Oi Gustavo, tudo bem?

Vou explicar esta última parte em duas mensagens, nesta primeira mostrarei uma forma bem simples de você testar a troca do ID do objeto usando teclas, na segunda vou mostrar como fazer a definição através de botões na interface.

Segue o passo a passo:

1 - Abra o Blueprint do Array de objetos, selecione a variável que define o número do Array, no meu exemplo chamada Numero_Array, e marque a opção Expose on Spawm, como mostra a primeira imagem em anexo.
Assim, ela vai aparecer como um item no Node Spawn Actor From Class que usamos no Blueprint do Player Controller.
Compile, salve e feche o Blueprint.


2 - Abra o Blueprint do Player Controller e crie uma variável para guardar o ID atual, no caso ela precisa ser do tipo Integer, no meu exemplo usei o nome ID_Atual, como mostra a segunda imagem em anexo.
Arraste essa variável para o gráfico com a opção Get e conecte-a no item Numero Array do Node Spawn Actor, como mostra a imagem.
Deste jeito a variável vai passar o valor do ID para o Blueprint do Array de objetos.

Tem várias formas de definir o valor desta variável, por exemplo, usando teclas, clicando em algum objeto na cena ou clicando em ícones na interface.
A forma mais simples para testar é usando teclas.


3 - Portanto, clique com o botão direito no gráfico para abrir a lista de Nodes e digite o número 1 para filtar, assim vai aparecer o Node 1 com o ícone do teclado no grupo Keyboard da lista.
Escolha este Node e também o número 2 e número 3, como mostra a terceira imagem em anexo.

Em seguida, arraste a variável ID_Atual para o gráfico com a opção Set e conecte no Pin de execução Pressed de cada Node das teclas de números, como mostra a imagem.
Depois é muito importante colocar o valor correto do ID em cada uma para definir um objeto diferente em cada tecla, então, coloquei 0 no número 1, 1 no número 2 e 2 no número 3 para pegar os 3 primeiros objetos do Array, você pode criar quantas teclas quiser.


4 - Compile, salve e feche o Blueprint, clique no Play para rodar a aplicação e teste se funciona, enquanto não teclar nenhum número vai criar o primeiro objeto do Array, depois que teclar algum número vai criar o objeto definido neste número.

Na próxima mensagem vou mostrar como fazer através de ícones na interface e como restringir a criação dos objetos para apenas quando clicar no ícone, assim, não ficará criando os objetos a esmo em qualquer clique.

Abração e tudo de bom.

André Vieira
Oi Gustavo, tudo bem?

Nesta mensagem vou explicar como fazer a definição do ID do objeto através de ícones na Interface e também restringir a criação dos objetos para acontecer somente quando clicar num ícone.

Segue o passo a passo:

1 - Crie um Blueprint do tipo Widget clicando com o botão direito numa área vazia do Content Browser e acessando o User Interface > Widget Blueprint, como mostra a primeira imagem em anexo.


2 - Esse Blueprint cria os itens da interface e tem bastante detalhes para estudar, mas basicamente você vai arrastando os itens do painel Palette para montar a interface na área central, chamada de Canvas, no painel Hierarchy os itens no Canvas são listados em hierarquia, pois é a hierarquia que faz um aparecer em cima do outro ou ser anexado ao outro, já no painel Details ficam as configurações de cada item, o primeiro é o alinhamento mostrado na segunda imagem em anexo.

A coisa mais importante do mundo é definir a escala da tela corretamente de acordo com o seu monitor para ver as coisas no tamanho certo, então, clique no Screen Size no parte superior direita do Canvas e escolha a opção que fará aparecer DPI Scale 1.0 no canto inferior direito, como mostra a imagem.

Para criar uma interface bem simples eu arrastei o item Horizontal Box para o Canvas e cliquei no alinhamento central superior, como mostra a imagem.
O Horizontal Box serve para receber outros itens e organizá-los horizontalmente, no meu exemplo troquei o nome dele para barra_icones.

O mais comum é criar os ícones automaticamente de forma procedural, mas aqui vamos criar manualmente, então, arrastei o item Button para cima do Horizontal Box (barra_icones), tanto faz se for no Canvas ou no Hierarchy, o importante é que ele fique dentro do Horizontal Box, fiz isso mais duas vezes para criar os 3 botões como mostra a imagem.

Depois arrastei o item Text para cima de cada Button para ele ficar dentro do Button, como mostra a imagem.


3 - Você pode configurar a posição do Horizontal Box (barra_icones) na tela usando os primeiros parâmetros disponíveis no painel Detail do lado direito da tela.
Selecionando o botão você também poderá ajustar o alinhamento e tamanho dele no painel Detail, como mostra a terceira imagem em anexo.

Clicando no Style abrirá as opções, incluindo o tamanho no Image Size como aparece na image, você ainda pode adicionar imagens e margens, note que o botão tem várias opções e precisa ajustar todas, pois uma é para quando passa o mouse em cima, outra é para quando clica, então, se não ajustar todas os ícones vão mudar de tamanho conforme passar o mouse sobre eles.

Selecionando o texto também poderá ajustar o tamanho, fonte, cor e tudo mais.

É bom colocar nome nos botões para poder identificá-los facilmente no gráfico.


4 - Agora, clique no botão grande escrito Graph na parte superior direita da tela para entrar no gráfico do Blueprint.
Clique com o botão direito no gráfico para abrir a lista de Nodes e digite Player para filtrar, pegue o Node Get Player Controller como mostra a quarta imagem em anexo.

Em seguida, arraste o Pin do Return Value dele para abrir a lista de Nodes neste contexto e digite o nome do Blueprint do seu Player Controller, escolha o Node Cast To Nome do Seu Player Controller, no meu exemplo o Player Controller se chama Teste_Player_Ctrl.
Conecte o Pin de execução do Event Construct que já estava no gráfico com o Cast To, como mostra a imagem.

Depois crie uma variável para guardar o Player Controller, ela precisa ser do mesmo tipo do seu Player Controller, como mostra a imagem.
Conecte essa variável no Cast To como mostra a imagem.

Fizemos isso para ter uma referência do Player Controller que contém o código para criar os objetos conforme o ID, pois vamos precisar acessar as variáveis dele.


5 - Agora, selecione a variável de um dos botões no painel da lateral esquerda, como mostra a quinta imagem em anexo, assim, aparecerá as configurações dela no painel Detail e entre elas está o menu Events, que contém as ações que o botão aceita.
Clicando no botão verde na frente do item On Clicked, vai aparecer no gráfico o Node On Clicked com o nome do botão entre parêntesis e o texto View em cima do botão verde ativado, como mostra a imagem.

Desta forma, quando o botão for clicado na interface vai rodar o código que estiver conectado neste Event On Clicked.


6 - Portanto, precisa fazer a mesma coisa para os outros botões criando o On Clicked selecionando cada botão e acessando o menu Events no painel Detail.

Em seguida, arraste para o gráfico a variável onde guardou o Player Controller com a opção Get, depois arraste o Pin dela para abrir a lista de Nodes e digite o nome da variável que criou para definir o ID do objeto no Blueprint do Player Controller.
A variável vai aparecer na lista em duas opções, com o Get para pegar informações e com o Set para inserir informações, então, precisamos usar a opção Set para alterar o valor da variável no Blueprint do Player Controller a partir deste Blueprint da interface.

Conecte o Pin de execução do Node On Clicked no Pin de execução da variável com o ID do objeto, como mostra a sexta imagem em anexo, e coloque o ID correto de cada objeto no valor da variável, lembrando que o Array inicia sempre com zero, então, usei zero no botão 1, 1 no botão 2 e 2 no botão 3, como aparece na imagem.
Compile, salve e feche o Blueprint.


7 - Abra o Blueprint do Player Controller, não vamos mais usar a definição do ID pelas teclas que fizemos anteriormente, então, pode deletar os Nodes com os números das teclas e as variáveis com o ID do objeto que estão conectadas neles.

Depois, clique com o botão direito no gráfico para abrir a lista de Nodes e digite Create para filtrar, selecione o Node Create Widget na lista.
Conecte o Pin de execução do lado esquerdo do Create Widget no Pin de execução do Node Show Mouse Cursor, que está conectado no Event Begin Play, como mostra a sétima imagem em anexo.

O Node Create Widget tem o item Class com uma listinha, clicando nela poderá escolher o Widget Blueprint que criamos com os ícones, digite o nome dele para encontrar rapidamente.
Agora é só arrastar o Pin do Return Value do Create Widget e escolher o nome Add To Viewport, como aparece na imagem.

Pronto, se você compilar, salvar e rodar a aplicação, os ícones estarão funcionando, porém, se clicar no piso vai criar o primeiro objeto do Array mesmo que não tenha clicado em nenhum ícone porque o código que fizemos no Event Left Mouse Button apenas verifica se houve o click e se acertou algum objeto, então, se clicar no ícone 2 para criar o segundo objeto do Array, o sistema vai mudar para o segundo objeto, mas vai criá-lo toda vez que clicar no piso e não é isso que queremos.

Para evitar este comportamento precisamos criar uma restrição que só deixe o Left Mouse Button funcionar quando tiver clicado num dos ícones, então, crie uma variável do tipo Boolean com o nome que quiser para definir quando o Left Mouse Button deve ser ativado, eu usei o nome Ativou, como aparece na sétima imagem em anexo.

Arraste a variável para o gráfico com a opção Get, depois arraste o Pin dela e escolha o Node Branch para saber quando ela é verdadeira ou falsa, como mostra a imagem.
Conecte o Pin de execução Pressed do Node Left Mouse Button no Pin de execução do lado esquerdo do Branch, depois conecte o Pin True do Branch no Pin de execução do lado esquerdo do outro Branch que temos no código, aquele que está ligado ao Hit Break Result, como mostra a imagem.

Desta forma o Left Mouse Button só vai funcionar quando a variável Ativou for verdadeira.


8 - Mas para funcionar direito temos que definir quando a variável é verdadeira e principalmente desativá-la depois de usada, caso contrário o Left Mouse Button continuará criando o objeto em todos os cliques depois que a variável se tornar verdadeira.

Portanto, para ela parar de funcionar depois que criar um objeto, é só arrastá-la para o gráfico com a opção Set e colocá-la no final de tudo, depois do Node Spawn Actor From Class, como mostra a oitava imagem em anexo.
O mais importante é deixar desativada a caixinha de seleção dela, para marcá-la como falsa quando terminar de executar o código de criação do objeto.
Compile, salve e feche o Blueprint.


9 - Agora abra o Widget Blueprint que criamos com os ícones, acesse o gráfico dele e arraste a variável que guardou o Player Controller com a opção Get, colocando-a na frente do código de um dos botões, depois arraste o Pin dela e digite o nome da variável que criou para ativar o Left Mouse Button, ela vai aparecer na lista com as duas opções, escolha a Set.

Conecte o Pin de execução da variável do ID do objeto no Pin de execução da variável que ativa o Left Mouse Button, depois faça o mesmo para os outros botões, como mostra a nona imagem em anexo.
O mais importante é marcar a caixinha de seleção da variável que ativa o Left Mouse Button para o código dele funcionar quando clicar no ícone.
Compile, salve e feche o Blueprint.


10 - Rode a aplicação, agora tudo deve estar funcionando a contento, você pode clicar onde quiser que nenhum objeto será criado, mas quando clicar num dos ícone e depois clicar no piso, o objeto definido no ícone será criado, porém, se clicar em seguida no piso não vai mais criar o objeto, para isso terá que selecionar o ícone novamente.

No meu teste eu tinha apenas alguns objetos de uma casinha, sendo o piso o primeiro do Array, o segundo o teto e o terceiro as vigas, então, veja na última imagem em anexo que os 3 foram criados de acordo com cada ícone.


Se tiver qualquer problema na execução desta última ou em qualquer outra questão do seu projeto, é só falar.

Abração e tudo de bom.

André Vieira

André ta insano aqui, consegui fazer tudo certinho e ja consigo ver a base do projeto ja formada está muito legal Muito obrigado até agora.

1º Eu só tenho uma duvida que tentei fazer aqui sozinho mas não consegui. O Actor que controlamos para nos movimentar na cena ele tem a colisão com os outros mashes da cena eu queria que esse actor que controlamos não tenha essa colisão, como a camera no meu será posicionada em 90º essa colisão não pode acontecer para que o usuário possa se locomover pelo cenario livremente.

2º Depois me manda seu nome completo para eu poder te citar no meu trabalho. Vou citar o ConstruSim tambem

Oi Gustavo, tudo bem?

Fico realmente muito feliz de saber que o seu projeto está dando certo e principalmente que está ficando legal.
Vou gostar muito de ver quando estiver pronto.

Sobre a sua dúvida, o Character tem uma capsula de componente que serve como colisor do corpo com os elementos da cena.
Se não quiser que aconteça essa colisão, você pode entrar no Blueprint do Character, selecionar o CapsuleComponent na raiz da lista de componentes e mudar o Collision Presets para NoCollision, como mostra a imagem em anexo.

Porém, fazendo isso o usuário vai conseguir atravessar os objetos, então, você não vai conseguir limitar o mundo 3D para ele e se a pessoa chegar no final da cena, vai cair fora do mapa.

Me explica melhor porque o usuário não pode colidir ou qual o problema que está acontecendo, pois certamente tem outra solução.

Uma opção é desabilitar a colisão, mas criar uma rotina para limitar o deslocamento do usuário na cena.
Por exemplo, se movimento em X for maior do que tanto, X é igual ao valor máximo do deslocamento

Sobre o meu nome, é André Buttignoli Vieira e agradeço pela citação.

Abração e tudo de bom.

André Vieira

Por meu projeto se tratar de um criador de mapas o movimento deve ser livre pelo mapa que o jogador está criando então ele não pode colidir com os objetos da cena.
Assista o começo deste video pra voce ter uma ideia de como a movimentação deve se comportar e o porque de tudo.

https://www.youtube.com/watch?v=tgZzx0K4cPY

- Eu preciso aumentar a velocidade de movimento tambem.
- No meu trabalho a camera será posicionada 90º em relação ao solo. Vou colocar uma imagem em anexo do meu trabalho.

eu desabilitei esse mesmo item uma vez mas ele atravessa ao chão, coisa que não deveria acontecer hehehehehehe, apenas atravessar os objetos colocados.

PS: consegui fazer o que eu queria

Oi Gustavo, tudo bem?

Agora eu entendi o que você deseja fazer e fico feliz de saber que conseguiu, mas como você fez?

Pois tem um subterfúgio bem bobo que vai reproduzir perfeitamente o sistema que mostrou no vídeo em anexo.

Imagine criar uma caixa invisível um pouco acima do mapa onde o personagem vai andar, assim, a movimentação ficará parecida com a do vídeo de exemplo.
Neste caso é só usar colisores sem Mesh para fazer a caixa e desabilitar a colisão deles com o clique do mouse para continuar criando os objetos no solo do mapa.

Gostaria de aproveitar para te falar um pouco dos Components, pois são muito importantes para você configurar as coisas conforme a necessidade do seu projeto.

Os Blueprints possuem diversos componentes para fazer coisas especiais e cada tipo de Blueprint tem seus componentes exclusivos, então, quando cria um Blueprint do tipo Character ele já vem com certos componentes especiais para controlar a movimentação do personagem.

Portanto, se tentar usar o Node Add Movement Input num outro tipo de Blueprint, não vai encontrar, pois ele não existirá naquele Blueprint, a não ser que você adicione o Component Character Movement, porque é esse componente que possui os recursos que geram o Node Add Movement Input no gráfico, entende?

Sendo assim, para criar um usuário puramente flutuante da forma mais econômica possível não poderia iniciar com o Blueprint do tipo Character, era melhor iniciar com o Blueprint do tipo Pawn e adicionar nele o Component Floating Pawn Movement.

Desta forma, em vez de ter os recursos do Character Movement, teria apenas os do Floating Pawn Movement.

O Floating Pawn Movement possui as mesmas implementações do Character Movement, mas sem incluir a gravidade, por isso é mais econômico.

Porém, como o Character Movement é um Floating Pawn Movement com gravidade, você pode transformar ele no Floating Pawn Movement desligando as propriedades de gravidade.

O Character Movement tem vários recursos nos menus dele no painel Detail, você poderia desabilitar a gravidade como falei, colocando zero no Gravit Scale, mas ele já tem um Preset para o Character voar, então, é só escolher a opção Flying no Default Land Movement Mode, como mostra a primeira imagem em anexo.

Assim, o personagem vai flutuar pela cena na altura do solo, para ele subir e descer terá que adicionar um Get Up Vector > Add Movement Input no gráfico, igual fizemos em X e Y, mas terá que manter a colisão para ele não atravessar o chão e nem os objetos da cena, porque se ele atravessar os objetos do mapa também vai ficar feio, vai ver tudo preto por dentro.

A configuração é praticamente a mesma que fizemos antes, como mostram a segunda e terceira imagens em anexo.

1 - Primeiro precisa ir lá no Project Settings > Input e adicionar um novo par de teclas para subir e descer, eu coloquei as teclas E e Q, pois ficam do lado do WASD, e chamei de SobeDesce.

2 - Depois adicionei o Node do Event SobeDesce no gráfico, puxei o Get Up Vector do Make Rotator e conectei num novo Add Input Movement.


O problema da velocidade do movimento encorre na mesma questão, pois todos os recursos para a movimentação estão no Component Character Movement, selecionando ele no quadro Component os parâmetros aparecem no quadro Details, o Max Walk Speed controla a velocidade, como mostra a primeira imagem em anexo.

Dá uma brincada com os parâmetros do Character Movement para ver o que eles fazem, assim, poderá configurar conforme a sua necessidade.

Mas se quiser, também pode controlar a velocidade através do gráfico no Blueprint, por exemplo, se quiser variar a velocidade conforme a situação.

Neste caso é só colocar um Node de multiplicação na conexão entre o Axis Value do Event e o Scale Value do Add Movement Input, como mostra a última imagem em anexo.

Dai você pode conectar uma variável no valor que multiplica e alterar quando quiser, até por meio de teclas ou outro Blueprint como explique nas mensagens anteriores, ainda poderá ter velocidades diferentes para o deslocamento vertical e horizontal.

Porém, essa movimentação com flutuação não sofre colisão com o solo, então, depois de um impulso o personagem segue em frente até você aplicar uma força contrária ou colidir com alguma coisa e não fica parecido com a movimentação que mostrou no vídeo de exemplo, dai a idéia da caixa invisível é mais prática e funciona perfeitamente.

Abração e tudo de bom.

André Vieira

no caso do Pawn eu cdeixei o colisor dele como Spectador, o que me proporcionou exatamente o que eu preciso, em elevações(do cenário) muito ingremes ele não atravessa e para na base do monte. Apliquei o zoom in/out com a teclas E e Q.

A velocidade eu alterei mas é como você falou ele fica andando até eu colocar uma força contrária, tentei mudar alguns parametros para não deixar isso acontecer, mas não consegui. mas de resto estou investindo mais o meu tempo na modelagem dos objetos (casas, castelo, tavernas, estatuas e por ai vai...). Estou utilizando o blender e estou gostando de modelar hein, estou investindo.

Oi Gustavo, tudo bem?

Desculpe a demora para responder, estive enrolado aqui.

Sobre a movimentação do jogador, tem algumas formas de aplicar forças contrárias quando solta a tecla de movimentação através de Blueprint, mas não vale a pena neste caso.

É mais prático fazer a caixa com colisores que te falei porque também facilitará em diversas outras questões, assim, é só diminuir a altura do Capsule Collider do jogador e ele será como uma esfera que rola dentro da caixa invisível acima do cenário, junto com o controle do Zoom que você fez ficará perfeito!

Para fazer a caixa é só criar um Actor Blueprint e adicionar 5 Box Colliders no Add Component, dai você aplica o Scale neles para transformar em piso e 4 paredes, posiciona na Viewport do Blueprint como mostra a imagem em anexo e pronto.

Dai é só colocar no Level e mover o Player Start para dentro da caixa.

Sobre modelagem, é uma terapia, tem vezes que sinto falta de modelar alguma coisa e sento para bricar um pouco, mas quando tem muita coisa para modelar profissionalmente chega uma hora que enjoa. rsrsrsrs

Lembre-se que para obter uma melhor qualidade gráfica é bom gerar mapas de Ambient Occlusion (AO) e Bent Normal Map, assim, terá um sombreado mais refinado nos objetos, principalmente se for iluminar o ambiente com HDRI.

Você sabe que precisa economizar nos polígonos né?

Então, quando tiver alguma coisa que precisa ser bem detalhada, você pode modelar normalmente em High Poly e no final faz a retopologia para gerar um objeto em Low Poly com baixa resolução, dai gera um Tangent Normal Map projetando a malha High Poly sobre a malha Low Poly para embutir os detalhes da malha High Poly no Normal Map.

Desta forma você consegue um ótimo resultado no objeto em Real-Time gastanto poucos polígonos.

Nestes casos também é bom gerar o mapa de AO e o Bent Normal Map com base na malha em High Poly.

Qualquer dúvida que tiver nesta parte de modelagem e texturização é só falar, mas eu não sei fazer no Blender, só no 3ds max e no Substance Designer.

Abração e tudo de bom.

André Vieira

Faça o login para poder comentar

Usuários conectados

Total de mensagens publicadas pelos membros da comunidade: 707615.

Total de membros registrados: 135229

Últimos membros registrados: rauldossantossousa, adudis_, mauriciovrc, rodneitjr, anacarolfinardic, saulo favero, sanerreddie, Humberto1082.

Usuário(s) on-line na última hora: 1065, sendo 17 membro(s) e 1048 visitante(s).

Membro(s) on-line na última hora: Adalberto Batista, Vladis, rauldossantossousa, Eduardo Ramos, Abilio, Victor Mendonça, Adalberto Rocha, Reinaldo Silva, Le_Andro, Leonardo Muller, Ronaldo Junior, Lucas Reis, Henrique Ribeiro, Thiago Couto, JMDesign, magster, Antigo.

Legenda: Administrador, Especial, Moderador, Parceiro .

3D1 © Três D1 © 1999-2024. Todos direitos reservados.